I have looked around quite a bit, and nothing seems to answer my question in particular. I have DataGridView in which I add rows and columns dependent on a certain record count of geospatial data that is held in ArcGIS. The data is then passed through to the gridview for editing.
So I do not use any databinding methods, rather it is a very manual process. I store data into a two-dimensional arrays, which indexes are based off of those certain data record counts.
After the loops are complete, the data should be stored in each cell dependent on index. The very last row that was populated is populated perfectly, yet the other 72 (or so) rows are blank.
Here is the code as follows:
This populates column headers (works great):
For i_FieldNum = 0 To pFields_1.FieldCount - 1
str_FieldName = UCase(pFields_1.Field(i_FieldNum).Name)
str_FieldAliasName = pFields_1.Field(i_FieldNum).AliasName
ReDim Preserve m_array_str_FieldNames(i_FieldNum)
ReDim Preserve m_array_str_FieldAliasNames(i_FieldNum)
m_array_str_FieldNames(i_FieldNum) = str_FieldName
m_array_str_FieldAliasNames(i_FieldNum) = str_FieldAliasName
i_FieldCount = i_FieldCount + 1
i_ColNum = i_FieldCount - 1
'If this is the "SHAPE", "FID", or "OBJECTID" field, remember it:
If (str_FieldName = "SHAPE") Then
m_i_FieldNum_Shape = i_FieldCount - 1
ElseIf (str_FieldName = "FID") Then
m_i_FieldNum_FID = i_FieldCount - 1
ElseIf (str_FieldName = "OBJECTID") Then
m_i_FieldNum_OBJECTID = i_FieldCount - 1
End If
'Store the field name in the top row:
grid_Data.ColumnCount = i_FieldCount
grid_Data.Columns.Item(i_ColNum).HeaderText = str_FieldName
ReDim Preserve m_array_l_FieldColLengths(i_ColNum)
m_array_l_FieldColLengths(i_ColNum) = pFields_1.Field(i_FieldNum).Length
Next i_FieldNum
This populates the two-dimensional array:
Do Until pFeat_1 Is Nothing
'Until we run out of features ...
i_FeatCount = i_FeatCount + 1
For i_FieldNum = 0 To pFields_1.FieldCount - 1
'If the field is recorded as a shape
If (i_FieldNum = m_i_FieldNum_Shape) Then
array_Data(i_FeatCount - 1, i_FieldNum) = "<Shape>"
Else
'If the value of the field is null
If IsNothing(pFeat_1.Value(i_FieldNum)) Or pFeat_1.Value(i_FieldNum).ToString = "" Then
array_Data(i_FeatCount - 1, i_FieldNum) = "<Null>"
Else
array_Data(i_FeatCount - 1, i_FieldNum) = pFeat_1.Value(i_FieldNum).ToString
End If
End If
Next i_FieldNum
'End If
'Move to the next feature (if any).
pFeat_1 = pFeatCursor_1.NextFeature
Loop
This is suppose to display the data:
For i_RowNum = 0 To i_FeatCount - 1
'Add a new row to the grid:
grid_Data.RowCount = i_RowNum + 2
For i_ColNum = 0 To pFields_1.FieldCount - 1
grid_Data.Item(i_ColNum, i_RowNum + 1).Value = array_Data(i_RowNum, i_ColNum)
Next i_ColNum
Next i_RowNum
Everything runs and compiles perfectly, although as I stated before, only the last row's data is shown (which is populated properly).
If anyone can help figure out why only one row is populated, it would be more than appreciated.
Thank You,
Logan
Check your updated section -This is suppose to display the data: If you data is correctly set then as per my guess it making grid to show wrong data. Modify it as per your columns in your grid that you have added. Or you can create column names string array to put data in particular cells. as dgvr.Cells(columnsArray[index]).Value = array[,]
For i_RowNum = 0 To i_FeatCount - 1
'Add a new row to the grid:
DataGridViewRow dgvr = new System.Windows.Forms.DataGridViewRow();
dgvr.CreateCells(grid_Data)
For i_ColNum = 0 To pFields_1.FieldCount - 1
dgvr.Cells(i_ColNum).Value = array_Data(i_RowNum, i_ColNum)
Next i_ColNum
grid_Data.Rows.Add(dgvr)
Next i_RowNum
Ref: Adding a New Row to DataGridView and How to: Manipulate
Rows in the Windows Forms DataGridView Control
See here, each time you increment the row count its clearing out the data:
DataGridView1.RowCount += 1
DataGridView1.Item(0, 0).Value = "a value"
DataGridView1.RowCount += 1
DataGridView1.Item(0, 1).Value = "the previous value has been wiped"
To fix your code without any major changes, just use this method to add rows:
grid_Data.Rows.Add(paramArray)
or even easier put this line above the for loop and set the number of rows before you fill them in:
grid_Data.RowCount = i_FeatCount - 1
Related
I am updating some old software in VB, and fixed this, but I'd like to know how to make the second option work.
The problem is in the second For loop in the code below. I'm not sure how to get a column of a specific row.
I have not worked much with VB and not used it for 10 years or so, so bare the question.
Dim i As Integer = 0
Dim dsSettings As New DataSet
dsSettings.Locale = System.Globalization.CultureInfo.InvariantCulture
If System.IO.File.Exists("QuaData\Settings.xml") Then
dsSettings.ReadXml("QuaData\Settings.xml")
ReDim Preserve IdPrefixes(dsSettings.Tables(0).Rows.Count - 1)
For Each Row As DataRow In dsSettings.Tables(0).Rows
For Each Coll As DataColumn In dsSettings.Tables(0).Columns
IdPrefixes(i) = Row("IdPrefix").ToString()
Next
i = i + 1
Next
' Here I cannot see how I can get a column of a row -
' like Rows(1)
' I cannot select Rows(index)(column name)
For i = 0 To dsSettings.Tables(0).Rows.Count - 1
IdPrefixes(i) = dsSettings.Tables(0).Rows(i)("IdPrefix").ToString()
Next
End If
I have a DataGridView in which I have transferred rows from another Form.
In my DataGridView I have three columns: the first one is name, the second is value, the third is id.
I want to hide duplicate rows with the same name and id.
How can I do this? My code is not working.
For i As Integer = 1 To Form.DataGridView1.Rows.Count - 1
If Form.DataGridView1.Rows(i).Cells(0).Value.ToString = Form.DataGridView1.Rows(i - 1).Cells(0).Value.ToString AndAlso
Convert.ToInt32(Form.DataGridView1.Rows(i).Cells(2).Value) = Convert.ToInt32(Form.DataGridView1.Rows(i - 1).Cells(2).Value) Then
Form.DataGridView1.Rows(i).Visible = False
End If
Next
You have only compared current row with current index-1 row. So, your code is not working. You need a nested loop to eliminate duplicate rows:
For i As Integer = 1 To Form.DataGridView1.Rows.Count - 1
For j As Integer = i - 1 To 0 Step -1
If Form.DataGridView1.Rows(i).Cells(0).Value.ToString = Form.DataGridView1.Rows(j).Cells(0).Value.ToString AndAlso
Convert.ToInt32(Form.DataGridView1.Rows(i).Cells(2).Value) = Convert.ToInt32(Form.DataGridView1.Rows(j).Cells(2).Value) Then
Form.DataGridView1.Rows(i).Visible = False
End If
Next
Next
Here is output
I've created a form and added a listview (lsTest) through VS Designer (VS 2010) and then added columns to it. For each of the columns, I've added a column heading and a value for Text property. For instance, the first column is named col1 and the text I want to display for it is 'This is Col1':
Column definition
In the code, I have a simple SQL Select statement to pull data from a SQL Server table and load a dataset (dsTest). I then read through the dataset and load the columns from each dataset row into a new listview item. This data load works fine (I can see in debug that items are being added to the listview). I also put one of the SQL columns into the listview column's tag as it's the data's primary key (this is why the for loop stops at Count - 2, the key is the last column). This is the data load:
For iRow = 0 To dsTest.Tables(0).Rows.Count - 1
Dim lvItem As New ListViewItem
lvItem.Tag = dsTest.Tables(0).Rows(iRow)(dsTest.Tables(0).Columns.Count - 1).ToString()
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
lvItem.SubItems.Add(Trim(dsTest.Tables(0).Rows(iRow)(iCol).ToString()))
Next
lstTest.Items.Add(lvItem)
Next
The problem is that the columns do not show at all when the listview is displayed. After some research, I tried adding columnheadings using the SQL field names.
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
dsTest.Columns.Add(dsShares.Tables(0).Columns(iCol).ColumnName)
Next
The columns now display, but they're using the SQL field names as the headings (which I would expect as that is what I did in the code). But the thing is, I don't want to use the SQL field names for the headings; I want to use the defined column headings that I added in Design.
I then tried looping through lstTest.Items, and using the Text attribute to populate the columnheadings. If I do this BEFORE loading the data, the For..next loop executes 0 times. If I do this AFTER loading the data, the loop executes the correct number of times but the headings are empty.
Here are my attempts and the results:
Example 1 - Data load only
For iRow = 0 To dsTest.Tables(0).Rows.Count - 2
Dim lvItem As New ListViewItem
lvItem.Tag = dsTest.Tables(0).Rows(iRow)(dsTest.Tables(0).Columns.Count - 1).ToString()
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
lvItem.SubItems.Add(Trim(dsTest.Tables(0).Rows(iRow)(iCol).ToString()))
Next
lstTest.Items.Add(lvItem)
Next
Result: Data loads in lstTest.Items but nothing shows
Example 2 - Data load, headings from SQL columns
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
lstTest.Columns.Add(dsTest.Tables(0).Columns(iCol).ColumnName)
Next
For iRow = 0 To dsTest.Tables(0).Rows.Count - 2
Dim lvItem As New ListViewItem
lvItem.Tag = dsTest.Tables(0).Rows(iRow)(dsTest.Tables(0).Columns.Count - 1).ToString()
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
lvItem.SubItems.Add(Trim(dsTest.Tables(0).Rows(iRow)(iCol).ToString()))
Next
lstTest.Items.Add(lvItem)
Next
Result: Data shows with SQL column names as headings
Example 3 - Data load, headings from column.items before data load
For iCol = 0 To lstTest.Items.Count - 2
lstTest.Columns.Add(lstTest.Items(iCol).Text)
Next
For iRow = 0 To dsTest.Tables(0).Rows.Count - 2
Dim lvItem As New ListViewItem
lvItem.Tag = dsTest.Tables(0).Rows(iRow)(dsTest.Tables(0).Columns.Count - 1).ToString()
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
lvItem.SubItems.Add(Trim(dsTest.Tables(0).Rows(iRow)(iCol).ToString()))
Next
lstTest.Items.Add(lvItem)
Next
Result: First loop executes 0 times; data shows but no column headings
Example 4 - Data load, headings from column.items after data load
For iRow = 0 To dsTest.Tables(0).Rows.Count - 2
Dim lvItem As New ListViewItem
lvItem.Tag = dsTest.Tables(0).Rows(iRow)(dsTest.Tables(0).Columns.Count - 1).ToString()
For iCol = 0 To dsTest.Tables(0).Columns.Count - 2
lvItem.SubItems.Add(Trim(dsTest.Tables(0).Rows(iRow)(iCol).ToString()))
Next
lstTest.Items.Add(lvItem)
Next
For iCol = 0 To lstTest.Items.Count - 2
lstTest.Columns.Add(lstTest.Items(iCol).Text)
Next
Result: Second loop executes correct number of times; data shows but no column headings
I've searched and searched, but all the examples I could find load the column headings from within the code. I can't find any examples where the headings from Designer are used.
Is there something I am missing here? Or can't VB.net/VS do what I want?
Thanks in advance for your help
I am attempting to pass the selected values from a list box in Excel to legend in a chart. Specifically, I have data of certain companies in the following format
And I also have a list box, globalList, which contains the names of companies that can be selected. Selected companies' data will then be passed onto a chart using VBA.
However, the problems I encounter are in the following sections:
Initialising a variable to hold values selected in the globalList
listMax = globalList.ListCount - 1
`this creates the upper bound for the list box
For i = 0 To (globalList.ListCount - 1)
If globalList.Selected(i) = True Then
companiesSelected = companiesSelected + 1
End If
If i = listMax Then
Exit For
End If
Next i
`the above is used to retrieve the number of companies that have been selected by a user - whether =0 or > 0
Dim myLegend() As String
ReDim myLegend(0 To (globalList.ListCount - 1))
For i = 0 To (globalList.ListCount - 1)
If globalList.Selected(i) = True Then
myLegend(i) = globalList.List(i)
End If
If i = listMax Then
Exit For
End If
Next i
`this is the array object in which I intend to store company names selected in the list box.
The problem is that even though the above creates the myLegend string array, it also contains empty array items for the companies that may not have been selected by the user in the list box.
And even if I am able to remove these empty items from the array, the following problem occurs
Passing the held values from my variable to my chart
For i = 1 To companiesSelected
myChart.SeriesCollection(i).Name = myLegend(i)
Next i
Problem here is that myLegend array starts from 0, while SeriesCollection seems to start from 1. So I am unable to pass the string values for selected items to the legend of my chart's.
Could somebody please point out how to circumvent these problems?
Many thanks in advance!
Here is a code to extract the selected items into an one-based array of String (without empty items):
Dim i As Integer
Dim iCount As Integer
Dim myLegend() As String
iCount = 0
With globalList
ReDim myLegend(1 To .ListCount)
For i = 0 To .ListCount - 1
If .Selected(i) = True Then
iCount = iCount + 1
myLegend(iCount) = .List(i)
End If
Next i
End With
If iCount > 0 Then
ReDim Preserve myLegend(1 To iCount)
Else
ReDim myLegend(1 To 1)
myLegend(1) = "Nothing here!"
End If
I have a datagridview, called dgvSNEvents, that looks like the following:
This dgv is only a small sampling but what I need is to export this dgv without any of the rows that contain "No Data Found" where you see them above. Here's the code I use to export everything including the unwanted rows. The export is done through Office Automation and I can produce a file just fine.
For iX = 0 To dgvSNEvents.Rows.Count - 1
For iY = 0 To dgvSNEvents.Columns.Count - 1
If dgvSNEvents.Rows(iX).Cells("Event Outcome").Value = "F" Then
' this will paint the background in red because the column named "Event Outcome" has an "F" for a value
xlCells(iX + 2, iY + 1).interior.colorindex = 22
xlCells(iX + 2, iY + 1).value = dgvSNEvents(iY, iX).Value
Else
' there aren't any "F's" so just export the row
xlCells(iX + 2, iY + 1).value = dgvSNEvents(iY, iX).Value
End If
Next
Next
I don't know if this is enough to go on so I will edit this as needed.
Here is my output after applying OSKM's code:
all you need is an if statement to check the data and a seperate variable to determine the location on the exported spreadsheet such as:
Dim XlRow as Int32 = 0
For iX = 0 To dgvSNEvents.Rows.Count - 1
'add ifstatement to skip column loop if cell entry is 'No Data Found'
If dgvSNEvents.Rows(iX).Cells("Part Number").Value <> "No Data Found" Then
For iY = 0 To dgvSNEvents.Columns.Count - 1
If dgvSNEvents.Rows(iX).Cells("Event Outcome").Value = "F" Then
' this will paint the background in red because the column named "Event Outcome" has an "F" for a value
xlCells(XlRow + 2, iY + 1).interior.colorindex = 22
xlCells(XlRow + 2, iY + 1).value = dgvSNEvents(iY, iX).Value
Else
' there aren't any "F's" so just export the row
xlCells(XlRow + 2, iY + 1).value = dgvSNEvents(iY, iX).Value
End If
Next
XlRow += 1
End If
Next
I would do export from a data table instead. Filter the rows using Select(), and put them into another data table. Export this new data table into Excel. The code will become much more simple to maintain.
EDIT: Or even export from an array of DataRow(), because that's what Select() would return. You will have some performance gain, by not having to create a data table. If you decide to have your Select() criteria dynamic, you can do that, and then doing an empty Select() returns everything AS IS, so it looks like all corner cases are covered for you.