vb.net datagrid to datagridview winforms - vb.net

We work with vb.net - Visual Studio 2013 (WinForms)
We are changing datagrids to datagridviews in our code.
At the moment I'm trying to convert a column that was described in the datagrid as follows:
Dim grdcolstyle5 As New PTSoft.FrameWork.DataBrowserTextColumnColorDecimal
With grdcolstyle5
.HeaderText = "text"
.MappingName = "vrd_199"
.Width = 80
.FormatString = "###,###,##0.00"
.[Operator] = "<"
.ParameterCol = 2
.ForeBrush = New SolidBrush(Color.Red)
End With
What is does is compare the value of one column with another and color the text when it's smaller (in this case).
I know how to do it in a loop after the grid has been filled, but this slows things somewhat down.
Does anyone know how this can be done "on the fly", on the moment the row is filled?
In short I am looking for the equivalent for the datagridview...

You can use RowPrePaint event, where you have large number of rows to paint.
Private Sub dataGridView1_RowPrePaint(ByVal sender As Object, ByVal e As DataGridViewRowPrePaintEventArgs)
If Convert.ToInt32(dataGridView1.Rows(e.RowIndex).Cells(2).Text) < Convert.ToInt32(dataGridView1.Rows(e.RowIndex).Cells(5).Text) Then
dataGridView1.Rows(e.RowIndex).DefaultCellStyle.ForeColor = Color.Red
End If
End Sub
The above code is comparing Cells(2) against Cells(5). You can customize that as per your need.
Another option is using CellFormattingEvent
Private Sub dataGridView1_CellFormatting(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs)
For Each Myrow As DataGridViewRow In dataGridView1.Rows
If Convert.ToInt32(Myrow.Cells(2).Value) < Convert.ToInt32(Myrow.Cells(1).Value) Then
Myrow.DefaultCellStyle.ForeColor = Color.Red
End If
Next
End Sub

Related

DataGridView + TextBox How to colorate more and different values

I have a problem, with DataGridView's CellFormatting. The cells are colored by the search result from a TextBox. When I search for 2 numbers together, they are no longer colored. What should I do?
I state that I am using CONCAT_WS to load the table in DataGridView. What can I do?
Private Sub DataGridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
Try
If e.ColumnIndex = 3 And e.Value IsNot Nothing Or e.ColumnIndex = 4 And e.Value IsNot Nothing Or e.ColumnIndex = 5 And e.Value IsNot Nothing Or e.ColumnIndex = 6 And e.Value IsNot Nothing Or e.ColumnIndex = 7 And e.Value IsNot Nothing Then
If String.IsNullOrEmpty(txtRefreshFiltra.Text) Then
txtRefreshFiltra.Text = ""
End If
Dim sum6 As String = Convert.ToInt32(e.Value)
If sum6 = txtRefreshFiltra.Text Then
e.CellStyle.BackColor = Color.Gold
e.CellStyle.ForeColor = Color.Black
End If
End If
Catch ex As Exception
MsgBox(ex.Message) 'show error msg'
End Try
End Sub
My connection
Public Sub FilterData(ValueToSearch As String)
Try
Dim SearchQyery As String = "SELECT * FROM LottoDeaBendata WHERE CONCAT_WS([Estratto1],[Estratto2],[Estratto3],[Estratto4],[Estratto5])LIKE'%" & ValueToSearch & "%'"
Dim command As New SqlCommand(SearchQyery, connection)
connection.Open()
Dim table As New DataTable()
Dim adapter As New SqlDataAdapter(command)
adapter.Fill(table)
DataGridView1.DataSource = table
connection.Close()
Catch ex As Exception
MsgBox(ex.Message) 'show error msg'
End Try
End Sub
Upload by button
Private Sub btnFiltraDati_Click(sender As Object, e As EventArgs) Handles btnFiltraDati.Click
FilterData(txtRefreshFiltra.Text)
End Sub
There are a few things you may want to consider to color the cells as you describe. First, using the grids CellFormatting event may not necessarily be the best choice. This event will fire once for each cell when the data is loaded into the grid and this is fine and colors the cells as we want when the data is loaded, however, it also may fire if the user simply moves the cursor over a cell or the user scrolls the grid.
In both the cases of the user moving the cursor over a cell or scrolling the grid, clearly demonstrates that the cells will get re-colored unnecessarily. In other words, if the text in the text box has not changed or a cells value has not changed, then, re-coloring the cell(s) is superfluous.
Given this, the only drawback to NOT using the grids CellFormatting event is that our code will have to color the cells AFTER the grid is loaded with data. This means we will need a method to loop through all the rows of the grid to check and color the cells. This method to color all the cells is also going to be needed if the text in the text box changes. So, making this method makes sense so we can call it when the data is loaded and also when the text box text changes.
So given all this, to simplify things, I suggest you create a method that takes a single DataGridViewCell. The method will get the comma separated values from the text box and compare the cells value to the values in the text box and if one matches, then we simply color the cell, otherwise do not color the cell.
This method is below. First, we check if the cell is not null and actually has some value. Then, we take the string in the text box and split it on commas. Then we start a loop through all the values in the split string from the text box and if a match is found, then we simply color the cell and exit the for each loop.
Private Sub ColorCell(cell As DataGridViewCell)
If (cell.Value IsNot Nothing) Then
Dim target = cell.Value.ToString()
If (Not String.IsNullOrEmpty(target)) Then
cell.Style.BackColor = Color.White
cell.Style.ForeColor = Color.Black
Dim split = txtRefreshFiltra.Text.Trim().Split(",")
For Each s As String In split
If (target = s.Trim()) Then
cell.Style.BackColor = Color.Gold
cell.Style.ForeColor = Color.Black
Exit For
End If
Next
End If
End If
End Sub
The method above should simplify looping through all the rows in the grid to color the proper cells. This method may look something like below and we would call this method once after the data is loaded into the grid and also when the text in the text box changes.
Private Sub ColorAllCells()
For Each row As DataGridViewRow In DataGridView1.Rows
ColorCell(row.Cells(3))
ColorCell(row.Cells(4))
ColorCell(row.Cells(5))
ColorCell(row.Cells(6))
ColorCell(row.Cells(7))
Next
End Sub
Lastly, the two event methods that we need to capture when the user changes a cells value in the grid in addition to when the user changes the text in the text box.
Private Sub txtRefreshFiltra_TextChanged(sender As Object, e As EventArgs) Handles txtRefreshFiltra.TextChanged
ColorAllCells()
End Sub
Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
If (e.RowIndex >= 0) Then
If (e.ColumnIndex = 3 Or e.ColumnIndex = 4 Or e.ColumnIndex = 5 Or e.ColumnIndex = 6 Or e.ColumnIndex = 7) Then
ColorCell(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex))
End If
End If
End Sub
Edit per OP comment…
There are definitely a couple of things we can do to speed up the current code above, like take out the call to ColorAllCells in the text boxes TextChanged event.
The TextChanged event will fire when the user types a single character. Example, if the user wants to color the cells that are “55”, then, when the user types the first “5” into the text box… then the TextChanged event will fire and the code will color all the cells with “5”. Then when the user types the second “5”, the cells will be un-colored/colored again.
So, one way we can prevent the unnecessary coloring as described above is to NOT call the ColorAllCells method in the text boxes TextChanged event and simply put the ColorAllCells method into a button click. In other words, the user types what they want into the text box… THEN clicks a button to color the cells.
In addition, if you look at the ColorCell method, you may note that each time the method is called, the code is splitting the same string over and over with … Dim split = txtRefreshFiltra.Text.Trim().Split(",") … this is potentially redundant in a sense that the text … txtRefreshFiltra.Text may not have changed.
Therefore, to remedy this and only split the txtRefreshFiltra.Text when needed, we will use a global variable called something like currentSplit that holds the current split of the text box. Then we would “update” the currentSplit variable only when needed… like in its TextChanged event.
This should somewhat speed things up. In my small tests, it took approximately 10 seconds to color the cells the FIRST time. Subsequent coloring of the cells when the text box value was changed took less than 1 second.
First make a global variable to hold the current text boxes split values…
Dim currentSplit As String()
Then change the other methods as shown below…
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = GetDT()
DataGridView1.DataSource = dt
currentSplit = txtRefreshFiltra.Text.Trim().Split(",")
End Sub
Private Sub ColorCell(cell As DataGridViewCell)
If (cell.Value IsNot Nothing) Then
Dim target = cell.Value.ToString()
If (Not String.IsNullOrEmpty(target)) Then
cell.Style.BackColor = Color.White
cell.Style.ForeColor = Color.Black
For Each s As String In currentSplit
If (target = s.Trim()) Then
cell.Style.BackColor = Color.Gold
cell.Style.ForeColor = Color.Black
Exit For
End If
Next
End If
End If
End Sub
Private Sub txtRefreshFiltra_TextChanged(sender As Object, e As EventArgs) Handles txtRefreshFiltra.TextChanged
currentSplit = txtRefreshFiltra.Text.Trim().Split(",")
End Sub
And finally, a button click event to color the cells. I added a stop watch to time how long it takes to color the cells.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim sw As Stopwatch = New Stopwatch()
Debug.WriteLine("Starting coloring of cells -------")
sw.Start()
ColorAllCells()
sw.Stop()
Debug.WriteLine("It took: " + sw.Elapsed.TotalSeconds.ToString() + " to color the cells of 100,000 rows with 10 columns")
End Sub

Add CheckBox To DataGridView Cell Programmatically

I’m trying to add a CheckBox programmatically to a DataGridVew cell if the cell next to it has a value of “1”. I’m trying to do this as the rows are added
I’m hoping someone can help me out with the correct code here. I understand one of the lines of code is incorrect but I’ve put it in to illustrate what I'm trying to do.
Thanks in advance.
Private Sub Controls_DGV_RowsAdded(sender As Object, e As Windows.Forms.DataGridViewRowsAddedEventArgs) Handles Controls_DGV.RowsAdded
If Controls_DGV.Rows(e.RowIndex).Cells(2).Value = "1" Then
Controls_DGV.Rows(e.RowIndex).Cells(1).AddCheckBox ' THIS LINE IS INCORRECT
End If
End Sub
This is the same as #miguel except for the checking the value, in this case Option Strict is On as it should be.
Public Class Form1
Private Sub dataGridView1_RowsAdded(sender As Object, e As DataGridViewRowsAddedEventArgs) _
Handles dataGridView1.RowsAdded
If CStr(dataGridView1.Rows(e.RowIndex).Cells(1).Value) <> "1" Then
dataGridView1.Rows(e.RowIndex).Cells(0).Value = False
dataGridView1.Rows(e.RowIndex).Cells(0) = New DataGridViewTextBoxCell()
dataGridView1.Rows(e.RowIndex).Cells(0).Value = ""
dataGridView1.Rows(e.RowIndex).Cells(0).ReadOnly = True
End If
End Sub
Private Sub AddRowsButton_Click(sender As Object, e As EventArgs) _
Handles AddRowsButton.Click
For index As Integer = 0 To 5
If CBool(index Mod 2) Then
dataGridView1.Rows.Add(False, "0")
Else
dataGridView1.Rows.Add(False, "1")
End If
Next
End Sub
End Class
The column number 1 that you want to display a checkbox should already be of type DataGridViewCheckBoxColumn and then if the value is not "1" you can transform the type of the cell for a DataGridViewTextBoxCell, so there is no checkbox and you can even put there some text if you want. Because you're using 3 columns, i'll try to do the same.
In your Form1_Load() you should have something like this if you are adding columns programmatically:
Dim ChkBox As New DataGridViewCheckBoxColumn
Controls_DGV.Columns.Add("TextBox1", "TextBox1")
Controls_DGV.Columns.Add(ChkBox)
Controls_DGV.Columns.Add("TextBox2", "TextBox2")
Then using your code it should be like this:
Private Sub Controls_DGV_RowsAdded(sender As Object, e As Windows.Forms.DataGridViewRowsAddedEventArgs) Handles Controls_DGV.RowsAdded
If Controls_DGV.Rows(e.RowIndex).Cells(2).Value <> "1" Then
' replace the checkbox cell by textbox cell
Controls_DGV.Rows(e.RowIndex).Cells(1) = New DataGridViewTextBoxCell()
Controls_DGV.Rows(e.RowIndex).Cells(1).Value = "(empty or some text)"
End If
End Sub

Implementing a Text change event from an Array

I am looking to change textbox fore and back colors of multiple textboxes based on a value if any one of the textboxes change it's value either by user input or reading from the DB.
I am not sure how to implement the code once an individual textbox has a change. The below code is as far as I got as I do not know how to implement it to work. Can someone assist?
Private Sub DiffCalcColor_TextChanged(sender As Object, e As EventArgs) Handles tbPMDiffCalc.TextChanged, tbLHDiffCalc.TextChanged, tbRFDiffCalc.TextChanged, tbFSDiffCalc.TextChanged, tbFSADiffCalc.TextChanged
Dim tb = DirectCast(sender, TextBox)
Dim text = tb.Text.Replace("$", "")
Dim number As Decimal
Decimal.TryParse(text, number)
Select Case number
Case < 0D : tb.ForeColor = Color.DarkRed
tb.BackColor = Color.White
Case > 0D : tb.ForeColor = Color.Green
tb.BackColor = Color.White
Case = 0D : tb.ForeColor = Color.DimGray
tb.BackColor = Color.Gainsboro
Case Else
Exit Select
End Select
End Sub
If you want to handle the same event for multiple controls with a single method then you simply include all those controls in the Handles clause, e.g.
Private Sub TextBoxes_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged,
TextBox2.TextChanged
Dim eventRaiser = DirectCast(sender, TextBox)
'Get the text that just changed.
Dim text = eventRaiser.Text
Dim number As Decimal
'Try to convert it to a number.
Decimal.TryParse(text, number)
'Use the number to decide how to format.
If number = Decimal.Zero Then
'...
Else
'...
End If
End Sub
You can do that manually or you can let the designer do it for you. To do the latter, start by selecting the multiple controls in the designer, then open the Properties window, click the Events button on the toolbar, then double-click the appropriate event. That will generate an event handler, much like double-clicking on a single control does, but it will add all the selected controls to the Handles clause. It also allows you to generate a handler for any event, rather than just the default event. To add a control to that Handles clause, you can select one or more controls, select the event and then select an existing event handler from the drop-down.

adding multiple textbox .net

What i want is when i input a number in texbox1.text like for example i enter 3 it should show 3 textbox but i always get an error. and also i have to save it in database but i dont know how. Help Please..
Private boxes(TextBox1.text) As TextBox
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim newbox As TextBox
For i As Integer = 1 To TextBox1.Text
newbox = New TextBox
newbox.Size = New Drawing.Size(575, 35)
newbox.Location = New Point(10, 10 + 35 * (i - 1))
newbox.Name = "TextBox" & i
newbox.Text = newbox.Name
'connect it to a handler, save a reference to the array and add it to the form controls
AddHandler newbox.TextChanged, AddressOf TextBox_TextChanged
boxes(i) = newbox
Me.Controls.Add(newbox)
Next
End Sub
OK. The error I get when I try to run your code is :-
An unhandled exception of type 'System.InvalidCastException' occurred in Microsoft.VisualBasic.dll
Additional information: Conversion from string "" to type 'Integer' is not valid.`
This is because you're trying to start a loop using a string as the termination index for the loop. Try using
For i As Integer = 1 To Val(TextBox1.Text)
your next problem will depend on how you've declared boxes. If you have declared it like this ..
Dim boxes() As TextBox
You'll end up with a Null reference exception because when you declared boxes, you didnt supply any elements. To remedy this you'll need to add this just before your loop ..
ReDim Preserve boxes(Val(TextBox1.Text))
If boxes is a list.. and to be honest .. thats a better choice than an array, instead of the above line you'll need to change
boxes(i) = newbox
to
boxes.Add(newbox)
You might also need to change other code associated with boxes, but the work will be worth it.
Your biggest problem is that you're trying to get a value from a TextBox that hasn't even appeared yet. You've put your code inside the form's load event. It really needs to be in a separate method. Oh and rather than use the TextBox.changed event you should use a button control to execute the method. Otherwise it's too easy for someone to change the number in the textbox. With your code, each time the textbox is changed (deleting a digit or adding another digit), more TextBoxes will be added and you could end up with lots of them.
So possible final code should look like ..
Public Class Form1
Dim boxes As New List(Of TextBox)
Private Sub Addbuttons(buttonCount As Integer)
Dim newbox As TextBox
For i As Integer = 1 To buttonCount
newbox = New TextBox
newbox.Size = New Drawing.Size(575, 35)
newbox.Location = New Drawing.Point(10, 10 + 35 * (i - 1))
newbox.Name = "TextBox" & i
newbox.Text = newbox.Name
'connect it to a handler, save a reference to the array and add it to the form controls
boxes.Add(newbox)
Me.Controls.Add(newbox)
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Addbuttons(Val(TextBox1.Text))
End Sub
End Class

GridView Size Problem?

Using VB.NET 2008
Am using Datagridview in my application, Datagridview should display according to the windows screen size, Before I used vb6
code.
Private Sub Form_Resize()
On Error Resume Next
If Me.WindowState = vbMinimized Then
Exit Sub
End If
listview1.Top = 1550
listview1.Left = 0
If ScaleHeight > 1550 Then
listview1.Height = ScaleHeight - 1550
End If
listview1.Width = ScaleWidth
End Sub
Am new to vb.net, How to set a datagridview size according to windows screen size, In Datagridview property itself any option is available or i have to make a code as like vb. If i have to make a code, how to give form_resize in vb.net.
Need vb.net code Help.
I'm not sure I understand your question, but I'll give it a try. This should be pretty simple. You set the DataGridView size using the Size property.
If you want it to fill the entire window you would say something like this:
Private Sub frmBar_Resize(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Resize
If (Me.WindowState = FormWindowState.Minimized) Then
Exit Sub
End If
dataGridView.Location = New Point(0, 0)
dataGridView.Size = Me.Size - New Size(4, 30)
End Sub
But you can make it whatever size you want. All you have to do is change what you are setting for the dataGridView.Size property.