I want to paste data from the clipboard to selected cells in a DGV. I found the following link: https://www.codeproject.com/Articles/208281/Copy-Paste-in-Datagridview-Control but I have no clue about C# so I converted the code to VB.net using an online tool. The Copy and cut part is working, but I am not able to paste to the DGV. The code looks like this:
'paste data
Private Sub PasteToolStripMenuItem1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles PasteToolStripMenuItem1.Click
PasteClipboardToDGV()
End Sub
Private Sub PasteClipboardToDGV()
If DgvLeidingen.SelectedCells.Count = 0 Then
MessageBox.Show("Please select a cell", "Paste", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return
End If
Dim startCell As DataGridViewCell = GetStartCell(DgvLeidingen)
Dim cbValue As Dictionary(Of Integer, Dictionary(Of Integer, String)) = ClipBoardValues(Clipboard.GetText())
Dim iRowIndex As Integer = startCell.RowIndex
For Each rowKey As Integer In cbValue.Keys
Dim iColIndex As Integer = startCell.ColumnIndex
For Each cellKey As Integer In cbValue(rowKey).Keys
If iColIndex <= DgvLeidingen.Columns.Count - 1 AndAlso iRowIndex <= DgvLeidingen.Rows.Count - 1 Then
Dim cell As DataGridViewCell = DgvLeidingen(iColIndex, iRowIndex)
End If
iColIndex = iColIndex + 1
Next
iRowIndex = iRowIndex + 1
Next
End Sub
Private Function GetStartCell(ByVal DGV As DataGridView) As DataGridViewCell
If DGV.SelectedCells.Count = 0 Then Return Nothing
Dim rowIndex As Integer = DGV.Rows.Count - 1
Dim colIndex As Integer = DGV.ColumnCount -1
For Each dgvCell As DataGridViewCell In DGV.SelectedCells
If dgvCell.RowIndex < rowIndex Then rowIndex = dgvCell.RowIndex
If dgvCell.ColumnIndex < colIndex Then colIndex = dgvCell.ColumnIndex
Next
Return DGV(colIndex, rowIndex)
End Function
Private Function ClipBoardValues(ByVal clipboardValue As String) As Dictionary(Of Integer, Dictionary(Of Integer, String))
Dim copyValues As Dictionary(Of Integer, Dictionary(Of Integer, String)) = New Dictionary(Of Integer, Dictionary(Of Integer, String))()
Dim lines As String() = clipboardValue.Split(vbLf)
For i As Integer = 0 To lines.Length - 1
copyValues(i) = New Dictionary(Of Integer, String)()
Dim lineContent As String() = lines(i).Split(vbTab)
If lineContent.Length = 0 Then
copyValues(i)(0) = String.Empty
Else
For j As Integer = 0 To lineContent.Length - 1
copyValues(i)(j) = lineContent(j)
Next
End If
Next
Return copyValues
End Function
In vb code, it needs to put "If cell.Selected Then cell.Value = cbValue(rowKey)(cellKey)", after "Dim cell As DataGridViewCell = DgvLeidingen(iColIndex, iRowIndex)"
Related
So after some changes, I have used this code:
Dim XlApp = New Microsoft.Office.Interop.Excel.Application
Dim oBook As Object = XlApp.Workbooks.Open("C:\file.xlsx")
Dim oSheet As Object = oBook.Worksheets(1)
Private Sub form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim StartedRow As Integer
Dim TotalRows As Integer
TotalRows = XlApp.ActiveWorkbook.Sheets(1).Range("a1").CurrentRegion.Rows.Count
For StartedRow = 1 To TotalRows
Me.ListBox1.Items.Add(oSheet.Cells(StartedRow, 1).text)
Me.ListBox1.Items.Add(oSheet.Cells(StartedRow, 2).text)
Next
MessageBox.Show("Succesful")
This one works but only shows two rows which is not in proper order, I need to show the whole file.
Sorry, since I'm new to Stack Overflow I find it kinda confusing for now :)
You need to declare your variables as specific types so you can use the properties and methods of that type. In general, don't let variables flap about as Object unless absolutely necessary.
I used .UsedRange to get row count. It seemed a bit simpler.
I used an interpolated string, indicated by the $, to get the range. In versions of Visual Studio prior to 2015 you will have to use
String.Format("A{0}", RowNum)
Excel is hard to get rid of. Therefore, put the Excel stuff in a separate method and add the two GC calls when the method returns.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DoExcelThing()
GC.Collect()
GC.WaitForPendingFinalizers()
'Even doing this will still leave a Zoombie Excel in Task Manager when debugging. (Hopefully not release)
MessageBox.Show("Succesful")
End Sub
Private Sub DoExcelThing()
Dim XlApp As New Microsoft.Office.Interop.Excel.Application
Dim oBook As Workbook = XlApp.Workbooks.Open("C:\file.xlsx")
Dim oSheet As Worksheet = CType(oBook.Worksheets(1), Worksheet)
Dim TotalRows = oSheet.UsedRange.Rows.Count
For RowNum = 1 To TotalRows
ListBox1.Items.Add(oSheet.Range($"A{RowNum}").Value)
ListBox1.Items.Add(oSheet.Range($"B{RowNum}").Value)
Next
End Sub
#Wakashio1234
This Will loop through all the cells..
TotalRows = XlApp.ActiveWorkbook.Sheets(1).Range("a1").CurrentRegion.Rows.Count
Totalcolumns = XlApp.ActiveWorkbook.Sheets(1).Range("a1").CurrentRegion.columns.Count
For StartedRow = 1 To TotalRows
For Startedcolumn = 1 To Totalcolumns
Me.ListBox1.Items.Add(oSheet.Cells(StartedRow, Startedcolumn).text)
Next
Next
MessageBox.Show("Successful")
The following code shows how to take out the data in Excel and put it into 'List(Of String())', then bind listbox control to the List and draw aligned columns of data in listbox.
Dim XlApp = New Microsoft.Office.Interop.Excel.Application
Dim oBook As Excel.Workbook = XlApp.Workbooks.Open("your file path")
Dim oSheet As Excel.Worksheet = oBook.Worksheets(1)
Dim lst As List(Of String()) = New List(Of String())()
Private RowHeight, RowWidth As Single
Private ColWidths As Single() = Nothing
Private Const RowMargin As Single = 10
Private Const ColumnMargin As Single = 10
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ListBox1.DrawMode = DrawMode.OwnerDrawVariable
ListBox1.DataSource = GetList()
End Sub
Private Function GetList() As List(Of String())
Dim rows As Integer = oSheet.UsedRange.Rows.Count
'If you want to display only two columns, set the value of 'cols' to 2
Dim cols As Integer = oSheet.UsedRange.Columns.Count
For r As Integer = 1 To rows
Dim Value As String() = New String(cols - 1) {}
For c As Integer = 1 To cols
Value(c - 1) = oSheet.Cells(r, c).Text
Next
lst.Add(Value)
Next
oBook.Close()
XlApp.Quit()
Return lst
End Function
Private Sub ListBox1_MeasureItem(sender As Object, e As MeasureItemEventArgs) Handles ListBox1.MeasureItem
If ColWidths Is Nothing Then
GetRowColumnSizes(e.Graphics, ListBox1.Font, lst, RowHeight, ColWidths)
For i As Integer = 0 To ColWidths.Length - 1
ColWidths(i) += ColumnMargin
Next
RowHeight += RowMargin
RowWidth = ColWidths.Sum()
End If
e.ItemHeight = CInt(RowHeight)
e.ItemWidth = CInt(RowWidth)
End Sub
Private Sub ListBox1_DrawItem(sender As Object, e As DrawItemEventArgs) Handles ListBox1.DrawItem
Dim values As String() = CType(ListBox1.Items(e.Index), String())
e.DrawBackground()
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
DrawRow(e.Graphics, ListBox1.Font, SystemBrushes.HighlightText, Nothing, e.Bounds.X, e.Bounds.Y, RowHeight, ColWidths, values, False)
Else
DrawRow(e.Graphics, ListBox1.Font, Brushes.Black, Nothing, e.Bounds.X, e.Bounds.Y, RowHeight, ColWidths, values, False)
End If
End Sub
Private Sub GetRowColumnSizes(ByVal gr As Graphics, ByVal font As Font, ByVal values As List(Of String()), ByRef max_height As Single, ByRef col_widths As Single())
Dim num_cols As Integer = values(0).Length
col_widths = New Single(num_cols - 1) {}
max_height = 0
For Each row As String() In values
For col_num As Integer = 0 To num_cols - 1
Dim col_size As SizeF = gr.MeasureString(row(col_num), font)
If col_widths(col_num) < col_size.Width Then col_widths(col_num) = col_size.Width
If max_height < col_size.Height Then max_height = col_size.Height
Next
Next
End Sub
Private Sub DrawRow(ByVal gr As Graphics, ByVal font As Font, ByVal brush As Brush, ByVal box_pen As Pen, ByVal x0 As Single, ByVal y0 As Single, ByVal row_height As Single, ByVal col_widths As Single(), ByVal values As String(), ByVal draw_box As Boolean)
Dim rect As RectangleF = New RectangleF()
rect.Height = row_height
Using sf As StringFormat = New StringFormat()
Dim x As Single = x0
For col_num As Integer = 0 To values.Length - 1
sf.Alignment = StringAlignment.Near
sf.LineAlignment = StringAlignment.Center
rect.X = x
rect.Y = y0
rect.Width = col_widths(col_num)
gr.DrawString(values(col_num), font, brush, rect, sf)
If draw_box Then gr.DrawRectangle(box_pen, rect.X, rect.Y, rect.Width, rect.Height)
x += col_widths(col_num)
Next
End Using
End Sub
Result of my test:
For more details you can see: Make an owner-drawn ListBox that justifies columns in C#
Get all combinations which declares an established amount sum
I managed to convert the code written to C #, and I would need some help. I don't know how to let them display the appropriate values in my Textbox.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Call (Main) - How to call in a Textbox1.Text
End Sub
Code:
Class SurroundingClass
Private Sub Main()
Dim numbers As Integer() = {3, 9, 8, 4, 5, 7, 10}
Dim target As Integer = 15
sum_up(New List(Of Integer)(numbers.ToList()), target)
End Sub
Private Shared Sub sum_up_recursive(ByVal numbers As List(Of Integer), ByVal target As Integer, ByVal part As List(Of Integer))
Dim s As Integer = 0
For Each x As Integer In part
s += x
Next
If s = target Then
Console.WriteLine("sum(" & String.Join(",", part.[Select](Function(n) n.ToString()).ToArray()) & ")=" + target)
End If
If s >= target Then
Return
End If
For i As Integer = 0 To numbers.Count - 1
Dim remaining = New List(Of Integer)()
Dim n As Integer = numbers(i)
For j As Integer = i + 1 To numbers.Count - 1
remaining.Add(numbers(j))
Next
Dim part_rec = New List(Of Integer)(part)
part_rec.Add(n)
sum_up_recursive(remaining, target, part_rec)
Next
End Sub
Private Shared Sub sum_up(ByVal numbers As List(Of Integer), ByVal target As Integer)
sum_up_recursive(numbers, target, New List(Of Integer)())
End Sub
End Class
When you run the code you will see that it outputs the sets of results one set at a time in the line Console.WriteLine("sum(" & String.Join(",", part.[Select](Function(n) n.ToString()).ToArray()) & ")=" + target).
As you want to get the result sets in one go, you will need to accumulate them at that point instead of writing to the console, and the Sub will need to be a Function with another parameter for the accumulator.
Making those modifications:
Public Class Form1
' Derived from the code at https://stackoverflow.com/questions/4632322/finding-all-possible-combinations-of-numbers-to-reach-a-given-sum
Function SumUpRecursive(numbers As List(Of Integer), target As Integer, part As List(Of Integer), solutions As List(Of List(Of Integer))) As List(Of List(Of Integer))
Dim s = part.Sum()
If s = target Then
' MsgBox("sum(" & String.Join(",", part.[Select](Function(n) n.ToString()).ToArray()) & ")=" & target)
solutions.Add(part)
End If
If s >= target Then
Return Nothing
End If
For i As Integer = 0 To numbers.Count - 1
Dim remaining = New List(Of Integer)()
Dim n As Integer = numbers(i)
For j As Integer = i + 1 To numbers.Count - 1
remaining.Add(numbers(j))
Next
Dim part_rec = New List(Of Integer)(part)
part_rec.Add(n)
SumUpRecursive(remaining, target, part_rec, solutions)
Next
Return solutions
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim numbers As Integer() = {3, 9, 8, 4, 5, 7, 10}
Dim target As Integer = 15
Dim nums = SumUpRecursive((numbers.ToList()), target, New List(Of Integer), New List(Of List(Of Integer)))
If nums Is Nothing Then
MsgBox("Failure :(")
Else
MsgBox(String.Join(vbCrLf, nums.Select(Function(b) String.Join(", ", b))))
' TextBox1.Lines = nums.Select(Function(b) String.Join(", ", b)).ToArray()
End If
End Sub
End Class
I'm sure there's a neater way of writing it.
How can i select distinct values from datagridview1 and pass this values to datagridview2?
I had this image i upload, would you mind to take a look for more details to my question;
Scenario
I already tried this code but it seems not working;
Private Sub GetLabandOtherFees()
Dim DistinctValues() As String = (From row As DataGridViewRow In dgvSubjectsEnrolled.Rows.Cast(Of DataGridViewRow)() _
Where Not row.IsNewRow _
Select CStr(row.Cells(0).Value)).Distinct.ToArray
For Each row As DataGridViewRow In dgvsub.Rows
dgvsub.Rows(row.Index).Cells(0).Value = DistinctValues
Next
End Sub
Thanks for the help.
Try this one.
Private Sub GetLabandOtherFees()
Dim dic As New Dictionary(Of String, Integer)()
Dim cellValue As String = Nothing
For i As Integer = 0 To datagridview1.Rows.Count - 1
If Not datagridview1.Rows(i).IsNewRow Then
cellValue = datagridview1(0, i).Value.ToString()
If Not dic.ContainsKey(cellValue) Then
dic.Add(cellValue, 1)
Else
dic(cellValue) += 1
End If
End If
Next
Dim sb As New StringBuilder()
For Each keyvalue As KeyValuePair(Of String, Integer) In dic
sb.AppendLine(String.Format("{0}", keyvalue.Key, keyvalue.Value))
Next
For Each row As DataGridViewRow In datagridview2.Rows
row.Cells(0).Value = sb.ToString()
row.Cells(1).Value = dic.Count.ToString()
Next
End Sub
I have a form with several radio buttons that gets created during run-time. The number of radio buttons will change depending on number of records in the db.
I can get the value from click event but, cannot add another item to dictionary. The code below, shows only information from current click event and does not add another item for second, third, and so on...click events.
Public Sub RadClick(ByVal sender As Object, ByVal e As System.EventArgs)
Dim rb As RadioButton
Dim myDictionary As New Dictionary(Of Integer, String)
Dim x As Integer = 0
rb = DirectCast(sender, RadioButton)
If rb.Checked = True Then
x = x + 1
myDictionary.Add(x, rb.Name)
End If
For Each pair As KeyValuePair(Of Integer, String) In myDictionary
MsgBox(pair.Key & " - " & pair.Value)
Next
End Sub
Thanks for reply.
I ended up getting this to work based on your suggestion to use a list.
Public Sub ComboClick(ByVal sender As Object, ByVal e As System.EventArgs)
Dim counter As Integer = 0
Dim a_cb As ComboBox
a_cb = DirectCast(sender, ComboBox)
Dim x = a_cb.Name
Dim h As Integer = 0
'Dim pair As KeyValuePair(Of String, String)
btnAll.Enabled = False
ListID.Clear()
Try
Select Case a_cb.SelectedItem
Case Is = "P"
myDictionary.Add(x, a_cb.SelectedItem)
a_cb.Enabled = False
Case Is = "A"
myDictionary.Add(x, a_cb.SelectedItem)
a_cb.Enabled = False
Case Is = "L"
myDictionary.Add(x, a_cb.SelectedItem)
a_cb.Enabled = False
End Select
Catch ex As Exception
MsgBox(ex.Message)
End Try
For Each pair As KeyValuePair(Of String, String) In myDictionary
If pair.Value = "P" Then ListID.Add(pair.Value)
If pair.Value = "A" Then ListID.Add(pair.Value)
If pair.Value = "L" Then ListID.Add(pair.Value)
'MsgBox(pair.Key & " - " & pair.Value)
Next
If ListID.Count = ClRowCount Then
btnAttend.Enabled = True
Else
btnAttend.Enabled = False
End If
End Sub
I have a single Row in DataGridView which shows different results for the selected Oids..The problem is that the next result replaces the first one in the same row..Is there any way to get next result in next rows so that DataGridview can show previous results also..my datagrid is not bound to any data source.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim host As String
Dim community As String
host = DataGridView1.Rows(0).Cells(1).Value.ToString
community = DataGridView1.Rows(3).Cells(1).Value.ToString
Dim txt4B As New DataGridViewTextBoxCell()
txt4B.Value = "public"
Dim result As Dictionary(Of Oid, AsnType)
Dim requestOid() As String = Nothing
Dim snmp As New SimpleSnmp
snmp = New SimpleSnmp(DataGridView1.Rows(0).Cells(1).Value.ToString, DataGridView1.Rows(3).Cells(1).Value.ToString)
result = snmp.Get(SnmpVersion.Ver1, New String() {DataGridView1.Rows(1).Cells(1).Value.ToString()})
If Not snmp.Valid Then
MessageBox.Show("Invalid hostname/community")
End If
If result IsNot Nothing Then
For Each kvp In result
DataGridView2.Rows(0).Cells(0).Value = SnmpConstants.GetTypeName(kvp.Value.Type)
DataGridView2.Rows(0).Cells(1).Value = kvp.Key.ToString
DataGridView2.Rows(0).Cells(2).Value = kvp.Value.ToString()
Next kvp
Else
MessageBox.Show("No results received")
End If
DataGridView2.AutoResizeColumn(0)
DataGridView2.AutoResizeColumn(1)
DataGridView2.AutoResizeColumn(2)
End Sub
Replace...
DataGridView2.Rows(0).Cells(0).Value = SnmpConstants.GetTypeName(kvp.Value.Type)
DataGridView2.Rows(0).Cells(1).Value = kvp.Key.ToString
DataGridView2.Rows(0).Cells(2).Value = kvp.Value.ToString()
With something like this...
Dim NewRow As New DataGridViewRow
Dim Cell1 As DataGridViewCell
Cell1.Value = SnmpConstants.GetTypeName(kvp.Value.Type)
Dim Cell2 As DataGridViewCell
Cell2.Value = kvp.Key.ToString()
Dim Cell3 As DataGridViewCell
Cell3.Value = kvp.Value.ToString()
NewRow.Cells.Add(Cell1)
NewRow.Cells.Add(Cell2)
NewRow.Cells.Add(Cell3)
DataGridView2.Rows.Add(NewRow)
This will create a new row with those values instead of overwriting the existing values.