Sorting listview in vb.net - vb.net

I made a listview of players rank and sort it.(by players points)
I leave the first column empty so i can rank the player after Ill sort.
But when I add the players position it add it by the list before the sort
Sub sortLv1()
Lv1.Sorting = SortOrder.Descending
Lv1.ListViewItemSorter = New ListViewItemComparer2(2, Lv1.Sorting)
Lv1.Sort()
End Sub
Now after I sort it I want to add the position and mark the leader in blue
Sub paintLeader()
For i = 0 To Lv1.Items.Count - 1
Lv1.Items(i).Text = CStr(i + 1)
If i = 0 Then
Lv1.Items(0).ForeColor = Color.Blue
Else
Lv1.Items(i).ForeColor = Color.Purple
End If
Next
End Sub
And what I get it in the attached picture
It look like it sort the list after the ranking even I call the sort before

The problem was that I tried to sort it while it was in a visual=False state.

Related

Create x-axis for department and y-axis for total ticket based on datagridview vb.net

i am a beginner in vb. i have a datagridview which the data extract from excel file. My data look like this
. I want to create a column chart where x-axis is Department and y-axis is total of status ticket that is open and close.Below is my code which i have stuck and i know i get errors but this is the idea.
i want the result like this
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Chart1.Series("Open").Points.AddXY("Finance", value)
Me.Chart1.Series("Open").Points.AddXY("ITMS", value)
Me.Chart1.Series("Open").Points.AddXY("RV", value)
Me.Chart1.Series("Open").Points.AddXY("Security", value)
Me.Chart1.Series("Close").Points.AddXY("Finance", value)
Me.Chart1.Series("Close").Points.AddXY("ITMS", value)
Me.Chart1.Series("Close").Points.AddXY("RV", value)
Me.Chart1.Series("Close").Points.AddXY("Security", value)
For Count As Integer = 0 To DataGridView1.Rows.Count - 2
Chart1.Series("Open").Points.AddXY(DataGridView1.Item(1, Count).Value, DataGridView1.Item(1, Count).Value)
Chart1.Series("Close").Points.AddXY(DataGridView1.Item(1, Count).Value, DataGridView1.Item(1, Count).Value)
Next
End Sub
End Class
From what I can decipher from the pictures of the data and the chart… you want the number of “open-close” tickets from “Finance” for the first two data points in the chart. The other points are ITMS, RV and Security “departments.” The problem with the posted code is that the current loop is not “adding” the “open” tickets or “closed” tickets for each department. The code is simply “adding” another point to the chart instead of “adding 1” to the existing point.
Tracing the posted for loop using the picture of the grid data, this will add a total of nine (9) points in the chart, the “SAME” nine points are in both the Open/Close” series. However, since departments like “Finance” have three (3) points with the same value, this will display in the chart as three (3) separate “Finance” “departments” … it is here that you need to “add” 1 to the value of the existing “Finance-open/close” point and not simply add “another” “Finance-open/close” point.
The code will need to loop through the grids rows and accumulate the total number of rows that have “Finance” AND “Open”, “Finance” AND “Close”, “ITMS” AND “Open” … etc. This will give you the charts “y” values for each department-open/close. Given this, one possible solution is to write a method that takes two string parameters (department, status) and returns an integer that contains the numbers of rows that match “both” the department and status. These would become the data points for the chart. In this example, you would only be adding eight (8) data points, One for “Finance” “Open” another for “Finance” “Close” … etc... I hope that makes sense.
Below is a simple loop through the grids rows that accumulates the eight points. The method described above is not necessarily the best approach if the data set is large. The described method would loop through the grid a total of eight (8) times. Once for “Finance” and “Open”, another loop through the grid to get “Finance” “Close” … etc. The code below loops through the grid only “once”, however this approach requires the addition of the 8 variables. Pick your poison… hope this helps.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' 8 variables to hold the totals
Dim FinanceOpenCount = 0
Dim FinanceCloseCount = 0
Dim ITMSOpenCount = 0
Dim ITMSCloseCount = 0
Dim RVOpenCount = 0
Dim RVCloseCount = 0
Dim SecurityOpenCount = 0
Dim SecurityCloseCount = 0
' loop through each row and "ADD" 1 to the proper variables
For Each row As DataGridViewRow In DataGridView1.Rows
Select Case row.Cells("Department").Value
Case "Finance"
If (row.Cells("Status").Value = "Open") Then
FinanceOpenCount += 1
Else
FinanceCloseCount += 1
End If
Case "ITMS"
If (row.Cells("Status").Value = "Open") Then
ITMSOpenCount += 1
Else
ITMSCloseCount += 1
End If
Case "RV"
If (row.Cells("Status").Value = "Open") Then
RVOpenCount += 1
Else
RVCloseCount += 1
End If
Case "Security"
If (row.Cells("Status").Value = "Open") Then
SecurityOpenCount += 1
Else
SecurityCloseCount += 1
End If
End Select
Next
' add the points to the chart
Chart1.Series("Open").Points.Clear()
Chart1.Series("Close").Points.Clear()
Chart1.Series("Open").Points.AddXY("Finance", FinanceOpenCount)
Chart1.Series("Close").Points.AddXY("Finance", FinanceCloseCount)
Chart1.Series("Open").Points.AddXY("ITMS", ITMSOpenCount)
Chart1.Series("Close").Points.AddXY("ITMS", ITMSCloseCount)
Chart1.Series("Open").Points.AddXY("RV", RVOpenCount)
Chart1.Series("Close").Points.AddXY("RV", RVCloseCount)
Chart1.Series("Open").Points.AddXY("Security", SecurityOpenCount)
Chart1.Series("Close").Points.AddXY("Security", SecurityCloseCount)
End Sub
Multiple looping method described above.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Chart2.Series("Open").Points.Clear()
Chart2.Series("Close").Points.Clear()
Chart2.Series("Open").Points.AddXY("Finance", GetDeptStatusCount("Finance", "Open"))
Chart2.Series("Open").Points.AddXY("ITMS", GetDeptStatusCount("ITMS", "Open"))
Chart2.Series("Open").Points.AddXY("RV", GetDeptStatusCount("RV", "Open"))
Chart2.Series("Open").Points.AddXY("Security", GetDeptStatusCount("Security", "Open"))
Chart2.Series("Close").Points.AddXY("Finance", GetDeptStatusCount("Finance", "Close"))
Chart2.Series("Close").Points.AddXY("ITMS", GetDeptStatusCount("ITMS", "Close"))
Chart2.Series("Close").Points.AddXY("RV", GetDeptStatusCount("RV", "Close"))
Chart2.Series("Close").Points.AddXY("Security", GetDeptStatusCount("Security", "Close"))
End Sub
Private Function GetDeptStatusCount(department As String, status As String) As Int32
Dim count = 0
For Each row As DataGridViewRow In DataGridView1.Rows
If (row.Cells("Department").Value = department And row.Cells("Status").Value = status) Then
count += 1
End If
Next
Return count
End Function

First 30 % displayed columns in DataGridView

First of all: 30% doesn't matter. That's a question of design. We can also say the first 3 Displayed Columns.
In my DataGridView I am using BackgroundColors for Rows to pass the User some information.
To keep this information visible to the user while Rows are being selected the first 30% of the columns should get the same SelectionBack/ForeColor as the Back/ForeColor.
So far that has never been a problem using
.cells(0).Style.SelectionBackColor = .cells(0).Style.Backcolor
(and so on).
Now I added the function that allows the user to reorder the Columns which makes the following Statement become true:
ColumnIndex != DisplayedIndex.
That statement beeing true makes the SelectionBackColor-Changed cells be somewhere mixed in the row and not in the first columns anymore. It still does the job, but looks terrible.
Is there something like a "DisplayedColumns" collection in order of the .DisplayedIndex Value that i could use to call the first few DisplayedColumns? If not, how could I effectivly create one my own?
Edit:
The user can also hide specific columns, that do not matter for him. So we have to be aware of Column.DisplayedIndex and Column.Visble
Got it working with the following code:
Try
' calculate what is thirty percent
Dim colcount As Integer = oDic_TabToGridview(TabPage).DisplayedColumnCount(False)
Dim thirtyPercent As Integer = ((colcount / 100) * 30)
' Recolor the first 30 % of the Columns
Dim i As Integer = 0
Dim lastCol As DataGridViewColumn = oDic_TabToGridview(TabPage).Columns.GetFirstColumn(DataGridViewElementStates.Visible)
While i < thirtyPercent
.Cells(lastCol.Index).Style.SelectionBackColor = oCol(row.Item("Color_ID") - 1)
.Cells(lastCol.Index).Style.SelectionForeColor = Color.Black
lastCol = oDic_TabToGridview(TabPage).Columns.GetNextColumn(lastCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None)
i += 1
End While
Catch ex As Exception
MsgBox(ex.Message & vbNewLine & ex.StackTrace)
End Try
Let us first assume you are coloring your rows somehow resembling the following manner:
Me.dataGridView1.Rows(0).DefaultCellStyle.BackColor = Color.PowderBlue
Me.dataGridView1.Rows(1).DefaultCellStyle.BackColor = Color.Pink
' ...etc.
In the DataGridView.CellPainting event handler, you can determine if the painting cell falls within the first N columns by utilizing the DataGridViewColumnCollection.GetFirstColumn and DataGridViewColumnCollection.GetNextColumn methods.
If the cell belongs to one these columns, set the cell's SelectionBackColor to the cell's BackColor. Otherwise set it to the default highlighting color.
Dim column As DataGridViewColumn = Me.dataGridView1.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
e.CellStyle.SelectionBackColor = Color.FromName("Highlight")
' Example: Loop for the first N displayed columns, where here N = 2.
While column.DisplayIndex < 2
If column.Index = e.ColumnIndex Then
e.CellStyle.SelectionBackColor = e.CellStyle.BackColor
Exit While
End If
column = Me.dataGridView1.Columns.GetNextColumn(column, DataGridViewElementStates.Visible, DataGridViewElementStates.None)
End While
As a side note: You may want to consider changing the ForeColor on these cells for readability - depending on your row's BackColor choices. Likewise, if only a single cell is selected from one these first N columns, it can be difficult to notice.

How to add multiple checkboxes in multiple columns (VBA)

I have a ListView with multiple columns. More precisely, the ListView contains 8 columns. 2 of them should be filled with checkboxes.
Currently only the first column contains checkboxes. It is defined as follows:
While Not rs.EOF
//first column with checkboxes
ListViewCustomer.ListItems.Add , , rs("Id")
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).tag = rs("Status")
//second column etc.
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).ListSubItems.Add , , rs("name")
....
//Here is the second column, which doesn't display the checkboxes
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).ListSubItems.Add , , IIf(IsNull(rs("date_from")), "", rs("date_from"))
ListViewCustomer.ListItems(ListViewCustomer.ListItems.Count).tag = rs("Status2")
Wend
Do anyone have an idea how to add the checkboxes in the last column?
EDIT:
Is it possible to realize this column with adding via .Controls?
A ListView is a more expanded version of the ListBox control.
See ListBox control on msdn as well.
They both display records of rows (the ListView has more advanced formatting options). This however means that a record is a row. Therefore you select a row when you select one of the items.
The function of the checkbox is to allow the user to mark the row(s) that is the records(s) he selects.
Thus there is only one checkbox per row, at the front of the row.
Consider this code (this is Excel 2003 VBA, but gives you the idea):
Private Sub UserForm_Initialize()
Dim MyArray(6, 8)
'Array containing column values for ListBox.
ListBox1.ColumnCount = 8
ListBox1.MultiSelect = fmMultiSelectExtended
'Load integer values MyArray
For i = 0 To 5
MyArray(i, 0) = i
For j = 1 To 7
MyArray(i, j) = Rnd
Next j
Next i
'Load ListBox1
ListBox1.List() = MyArray
End Sub
You could do a custom ListBox or ListView if you really want. You could create a frame and put Labels and CheckBoxes on it. This is the only way to do this in Excel2003 where I tested. The ListBox object has no Controls child.
But this is more like a datagrid and not really a ListBox or ListView which by definition are a listing of records (rows).
Update:
I saw your update and that you really want to place the CheckBox at the end of the row.
If you only want one checkbox at the last row, you could do this custom checkbox. Again this is written for the ListBox, so need to convert it to your ListView if you want to.
Still requires a custom handling, but I had some time, so I did this code. See if you like it:
Private Sub ListBox1_Change()
For i = 0 To ListBox1.ListCount - 1
ListBox1.List(i, 3) = ChrW(&H2610)
Next i
ListBox1.List(ListBox1.ListIndex, 3) = ChrW(&H2611)
End Sub
Private Sub UserForm_Initialize()
Dim MyArray(5, 3)
'Array containing column values for ListBox.
ListBox1.ColumnCount = 4
ListBox1.MultiSelect = 0
ListBox1.ListStyle = 0
'Load integer values MyArray
For i = 0 To 5
MyArray(i, 0) = i
For j = 1 To 2
MyArray(i, j) = Rnd
Next j
MyArray(i, 3) = ChrW(&H2610)
Next i
'Load ListBox1
ListBox1.List() = MyArray
End Sub

How to count Maximum rows in Visual Basic

I have the code for the next button. The data in the database show up normally.
The problem is when I click next button, the data will be repeated again as --> data1 > data2 > data3 > data1 > data2...
I've to been told that I should count the maximum rows but I didn't know how to do it; I've search for the coding as well, but nothing that I understand came out.
Please help me~~~ (I am not very good with English, sorry)
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnNext.Click
btnBack.Enabled = True
da.Fill(dt)
If position >= 0 Then
position = position + 1
Me.lblID.Text = dt.Rows(position).Item("RefNo")
Me.txtboxName.Text = dt.Rows(position).Item("Name")
Me.rtxtboxAddress.Text = dt.Rows(position).Item("Address")
Me.txtboxContactNo.Text = dt.Rows(position).Item("ContNo")
Me.txtboxFaxNo.Text = dt.Rows(position).Item("FaxNo")
Me.txtboxBrand.Text = dt.Rows(position).Item("Brand")
Me.txtboxModel.Text = dt.Rows(position).Item("Model")
Me.txtboxSN.Text = dt.Rows(position).Item("SN")
Me.rtxtboxProblems.Text = dt.Rows(position).Item("Problems")
Me.rtxtboxTechRemark.Text = dt.Rows(position).Item("TechRemark")
Me.rtxtboxServChange.Text = dt.Rows(position).Item("ServiceChange")
Me.rtxtboxPartChange.Text = dt.Rows(position).Item("PartsChange")
Me.txtboxTotal.Text = dt.Rows(position).Item("TotalPrice")
End If
End Sub
I don't know if this is also need to be told, but... there is two different class
1) database.vb - sql coding
2) forms.vb - coding for my visual basic form
Please help me!!
THANKS EVERYONE WHO HELO ME WITH THE ANSWERS!! I HAVE FOUND THE SOLUTION OF THE QUESTION AFTER RE-FIGURED THE CODING.
I didn't figure out the position value and the row value is same. My value of position = 0 and dt.Rows.Count = 4, since I have 4 data; so when the position = 0, the row = 1. I get confused about that; I thought both value is starting with 0.
A bit more code... this is bad code... don't rely on it for production since I'm sure there are plenty of corner cases it doesn't handle, but I wanted to give you a picture of how you could handle it and at least a glimpse of stuff you might need to worry about (e.g. 0 rows in the data table). Please work through this and try to understand the code... don't simply copy/paste.
Private Sub btnNext_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btnNext.Click
If position >= dt.Rows.Count Then
// No more rows to show after this one, so disable the next button
btnNext.Enabled = False
End If
// Put check for zero in btnBack.Click to make sure it doesn't go below 0
// I'm assuming position starts off at 0, and that you're showing the very
// first row by default
position += 1
// This is to handle a condition like having 0 rows in the data table,
// in which case don't want to do the next part...
If position > dt.Rows.Count Then Exit Sub
// Only necessary once really, but we'll do it each time anyway...
btnBack.Enabled = True
da.Fill(dt)
position += 1
// Update various textboxes and labels...
End Sub
dt.Rows.Count is the number of rows in the Rows collection. Anytime you want to check the whether you've reached the maximum number of rows compare the row count to dt.Rows.Count
da, dt, and position should be declared outside your sub above. The Fill statement should also be executed outside the sub.
In the sub:
If position >= 0 and position < dr.rows.count then
do stuff above
else
Beep ' out of range
end if

How to Implement Rowspan in a GridView (for .NET 3.5)

I created a custom GridView (actually a RadGrid) which does roughly the following.
Initialize GridView formatting
Setup Columns (depending on type of data to be displayed)
Populate the rows
When Instantiating this GridView, and adding it to my page, I want the first column to contain a "rowspan" attribute on the first row of repeated, but similar data. The "rowspan" value should be equal to the number of similar rows following it. In this way I hope to make the final view cleaner.
The logic for this, I figure, should take place while populating the rows. Initially I add rows to a DataTable and then bind it to the GridView as the final step.
Here's the general logic I was attempting, but it didn't work for me. What am I doing wrong?
Dim dt As New DataTable() 'Has three default columns
For Each d In Documents 'MAIN ITEM (First Column Data)
Dim rowspan As Integer
rowspan = 0
For Each f In Files
If rowspan = 0 Then
Me.dt.Rows.Add(New Object() {d.Title, f.Language, f.FileSize})
'THIS DOESN'T WORK!
Me.dt.Columns(0).ExtendedProperties.Item("rowspan") = rowspan.ToString()
Else
Me.dt.Rows.Add(New Object() {Nothing, f.Language, f.FileSize})
End If
rowspan += 1
Next
Next
Also keep in mind that the this is dumped into a DataView which is sorted by the first column, so I would imagine it must actually be sorted first, then somehow count the rows for each "like" first column, then set the "rowspan" value for the first row of that column equal to the number of rows belonging to it.
Does this make sense? Here is an ideal example of what I would like to accomplish in the layout:
Try this.
Protected Sub DemoGrid_PreRender(sender As Object, e As System.EventArgs) Handles DemoGrid.PreRender
MergeRowsWithSameContent(sender)
End Sub
Public Sub MergeRowsWithSameContent(gvw As GridView)
For rowIndex As Integer = gvw.Rows.Count - 2 To 0 Step -1
Dim row As GridViewRow = gvw.Rows(rowIndex)
Dim previousRow As GridViewRow = gvw.Rows(rowIndex + 1)
For i As Integer = 0 To row.Cells.Count - 1
If row.Cells(i).Text = previousRow.Cells(i).Text Then
row.Cells(i).RowSpan = If(previousRow.Cells(i).RowSpan < 2, 2, previousRow.Cells(i).RowSpan + 1)
previousRow.Cells(i).Visible = False
End If
Next
Next
End Sub
P.S: Shameless port of this wonderful code I have been using for years.