I have an continous form in my database application. In this form the data of a table with 3 columns is showed: product, numberofItemsOfToday, numberOfItemsOfYesterday.
Now I want the rows to be colored in red (ForeColor), if numberofItemsOfToday != numberOfItemsOfYesterday in the correspondent row.
I tried something like
Private Sub Form_Current()
addConditionalFormatingText txtnumberofItemsOfToday, numberOfItemsOfYesterday, txtProduct, txtnumberofItemsOfToday, txtnumberOfItemsOfYesterday
End Sub
Private Sub addConditionalFormatingText(field1 As Object, field2 As Object, t1 As TextBox, t2 As TextBox, t3 As TextBox)
Dim color As Long
color = IIf(CBool(Nz(field1.Value, "") <> Nz(field2.Value, "")), RGB(255, 0, 0), RGB(0, 0, 0))
t1.ForeColor = color
t2.ForeColor = color
t3.ForeColor = color
End Sub
But of course the problem is that if in one row the values are different, all rows are colored red. How can I only set the color of a special row in a continous form?
Related
I Have a DataGridView with 6 column.
Column1 = "Product ID" //ReadOnly False
COlumn2 = "Product Name" //ReadOnly True - Auto Fill After Product ID Entered
COlumn3 = "Product Info" //ReadOnly True - Auto Fill After Product ID Entered
Column4 = "Price" //ReadOnly False
Column5 = "Qty" //ReadOnly False
Column6 = "Sub Total" //ReadOnly True - Auto Fill From Price*Qty
How can I only use tab on Cell where the ReadOnly set to False ? I mean, if I aleady input product ID and press "Enter", the cursor / focus move to Column4 and so move to Column5 after I hit "Enter" again in Column4 and add new row after press "Enter" again in Column5.
Allready tried others code but only works for all cell not specific cell.
http://www.vbforums.com/showthread.php?735207-DAtaGridView-move-to-next-column-automatically
Did you try this site? Sorry i cannot post to your comment section because it requires 50 reputation.
I use this so far to make it move to another cell using Enter Keys. Using code from Arsalan Tamiz Blog.
Dim celWasEndEdit As DataGridViewCell
Private _EnterMoveNext As Boolean = True
<System.ComponentModel.DefaultValue(True)>
Public Property OnEnterKeyMoveNext() As Boolean
Get
Return _EnterMoveNext
End Get
Set(ByVal value As Boolean)
_EnterMoveNext = value
End Set
End Property
Private Sub DataGridView_SelectionChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.SelectionChanged
'if Enter Move Next should work andalso mouse button was NOT down
'we are checking mouse buttons because if select was changed
'by Mouse then we will NOT do our Enter Move Next
If _EnterMoveNext AndAlso MouseButtons = 0 Then
'if selection is changed after Cell Editing
If celWasEndEdit IsNot Nothing AndAlso DataGridView1.CurrentCell IsNot Nothing Then
'if we are currently in the next line of last edit cell
If DataGridView1.CurrentCell.RowIndex = celWasEndEdit.RowIndex + 1 AndAlso DataGridView1.CurrentCell.ColumnIndex = celWasEndEdit.ColumnIndex Then
Dim iColNew As Integer
Dim iRowNew As Integer
'if we at the last column
If celWasEndEdit.ColumnIndex >= DataGridView1.ColumnCount - 2 Then
iColNew = 0 'move to first column
iRowNew = DataGridView1.CurrentCell.RowIndex 'and move to next row
Else 'else it means we are NOT at the last column move to next column
iColNew = celWasEndEdit.ColumnIndex + 1
'but row should remain same
iRowNew = celWasEndEdit.RowIndex
End If
DataGridView1.CurrentCell = DataGridView1(iColNew, iRowNew) ' ok set the current column
End If
End If
celWasEndEdit = Nothing ' reset the cell end edit
End If
End Sub
And for the bypass. I use this (But i don't think its the perfect one, because if i press Left Arrow on Column 4 to move to Column 0, the focus can't move to it, maybe because i put Keys.Sender Right)
Private Sub DataGridView1_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellEnter
If DataGridView1.Columns(e.ColumnIndex).ReadOnly = True Then
SendKeys.Send("{Right}")
End If
End Sub
When I begin typing in Field 1 textbox, Field 2's backcolor should be set to [color]. If i were to backspace all text from Field 1, the back color should be set back to white (all before leaving the field, saving, etc.)
you may try this code in your UserForm code pane:
Option Explicit
Dim typing As Boolean
Private Sub Field1_Change()
With Me
If typing Then
If Len(.Field1.Text) = 0 Then
.Field2.BackColor = vbWhite
typing = False
End If
Else
.Field2.BackColor = vbYellow '<--| change vbYellow to your needed Field2 background color
typing = True
End If
End With
End Sub
The idea of user3598756 can be reduced to one line:
Private Sub Field1_Change()
Me!Field2.BackColor = IIf(Me!Field1.Text = "", vbWhite, vbGreen)
End Sub
In a VB.NET WinForms project I'm working on in VS2013 I am detecting when the user changes something in a cell on the CellValueChanged event. When a row in the DataGridView is found that is different from the DataSet I highlight the row in pink.
In my code though, I only know how to iterate through all of the rows, rather than just compare the row that fired the CellValueChanged event to the DataSet.
Here's my current code:
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the edited row
CompareDgvToDataSource(e.RowIndex, e.ColumnIndex)
End Sub
Private Sub CompareDgvToDataSource(ByVal rowIndex As Integer, ByVal columnIndex As Integer)
' Force ending Edit mode so the last edited value is committed
EmployeesBindingSource.EndEdit()
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanged Is Nothing Then
For Each dt As DataTable In dsChanged.Tables
For Each row As DataRow In dt.Rows
For i As Integer = 0 To dt.Columns.Count - 1
Dim currentColor As System.Drawing.Color = dgvEmployees.AlternatingRowsDefaultCellStyle.BackColor
If Not row(i, DataRowVersion.Current).Equals(row(i, DataRowVersion.Original)) Then
Console.WriteLine("Row index: " & dt.Rows.IndexOf(row))
' This works
dgvEmployees.Rows(rowIndex).DefaultCellStyle.BackColor = Color.LightPink
Else
' Need to change the BackColor back to what it should be based on its original alternating row color
End If
Next
Next
Next
End If
End Sub
As you can see, I'm passing the row and column index of the changed cell, so how can I take that and compare it to the specific row and/or cell in the unchanged DataSet?
UPDATE
Nocturnal reminded me that I need to allow for sorting of the DGV, so using row indexes won't work. He offered this as a solution (changed slightly to work with my objects):
If Not dsChanged Is Nothing Then
For Each dtrow As DataRow In dsChanged.Tables("employees").Rows
If DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID.ToString = dgvEmployees.Rows(rowIndex).Cells("employeeID").Value.ToString Then
For i As Integer = 0 To dsChanged.Tables("employees").Columns.Count - 1
If Not dtrow(i, DataRowVersion.Current).Equals(dtrow(i, DataRowVersion.Original)) Then
Console.WriteLine("Employees ID: " & DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID)
dgvEmployees.Rows(rowIndex).Cells(columnIndex).Style.BackColor = Color.LightPink
Else
' Need to change the BackColor back to what it should be based on its original alternating row color
End If
Next
End If
Next
End If
However, I'm getting an error on the If DirectCast... line saying "Column named "employeeID" cannot be found." I'm not sure if the error is on the DataSet or on the DGV, but there is an employeeID column in the database and DataSet. There is an employeeID as a bound column for the DataGridView, but it is set to Visible = False. That's the only thing I can think of that could possibly cause that error, but if it's a bound column, I would think it could be compared against as in this case.
FINAL WORKING VERSION
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the edited row
CompareDgvToDataSource("employees", e.RowIndex, e.ColumnIndex)
End Sub
Private Sub CompareDgvToDataSource(ByVal dataSetName As String, ByVal rowIndex As Integer, ByVal columnIndex As Integer)
' Takes a dataset and the row and column indexes, checks if the row is different from the DataSet and colors the row appropriately
EmployeesBindingSource.EndEdit()
Dim dsChanges As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanges Is Nothing Then
For Each dtrow As DataRow In dsChanges.Tables("employees").Rows
If DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID.ToString = dgvEmployees.Rows(rowIndex).Cells("employeeID").Value.ToString Then
For i As Integer = 0 To dsChanges.Tables("employees").Columns.Count - 1
If dtrow.RowState.ToString = DataRowState.Added.ToString Then
' TODO: Color entire new row
ElseIf dsChanges.Tables(dataSetName).Rows(0).HasVersion(DataRowVersion.Original) Then
If Not dtrow(i, DataRowVersion.Current).Equals(dtrow(i, DataRowVersion.Original)) Then
Console.WriteLine("Employees ID: " & DirectCast(dtrow, EmployeesDataSet.employeesRow).employeeID)
dgvEmployees.Rows(rowIndex).Cells(columnIndex).Style.BackColor = Color.LightPink
Else
' TODO: Need to change the BackColor back to what it should be based on its original alternating row color
End If
End If
Next
End If
Next
End If
End Sub
My project has four DGVs in it, so this will eventually be expanded to allow for all four DGVs to be checked for changes.
have a look at this approach it is simlar but only iterating the specific Table
Private Sub dgvEmployees_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgvEmployees.CellValueChanged
' Pass the row and cell indexes to the method so we can change the color of the edited row
CompareDgvToDataSource(e.RowIndex, e.ColumnIndex, sender.DataSource.datamember.ToString)
End Sub
and comparing the ID of the given Table
Private Sub CompareDgvToDataSource(ByVal rowIndex As Integer, ByVal columnIndex As Integer, tablename As String)
EmployeesBindingSource.EndEdit()
Dim dsChanged As DataSet = EmployeesDataSet.GetChanges()
If Not dsChanged Is Nothing Then
For Each dtrow As DataRow In dsChanged.Tables(tablename).Rows
If DirectCast(dtrow, EmployeesDataSet.EmployeeRow).EmployeeID = dgvEmployees.Rows(rowIndex).Cells("EmployeeID").Value Then
Dim currentColor As System.Drawing.Color = dgvEmployees.AlternatingRowsDefaultCellStyle.BackColor
For i As Integer = 0 To dsChanged.Tables(tablename).Columns.Count - 1
If Not dtrow(i, DataRowVersion.Current).Equals(dtrow(i, DataRowVersion.Original)) Then
Console.WriteLine("Employees ID: " & DirectCast(dtrow, EmployeesDataSet.EmployeeRow).EmployeeID)
' This works
dgvEmployees.Rows(rowIndex).Cells(columnIndex).Style.BackColor = Color.LightPink
Else
' Need to change the BackColor back to what it should be based on its original alternating row color
End If
Next
End If
Next
End If
End Sub
and i am only changing the backcolor of the cell that was changed not the entire row....but depends how you would use that information anyways
EDIT:
with
Console.WriteLine(EmployeesDataSet.Employee(rowIndex)(columnIndex, DataRowVersion.Original).ToString())
Console.WriteLine(EmployeesDataSet.Employee(rowIndex)(columnIndex, DataRowVersion.Current).ToString())
you can see Current and Original Values
123456
I have a listbox and code to make sure it (and other elements) are selected. I added an ELSE to the code so that if the ListBox has a selected item, it changes the background color to white. This needs to happen if the previous attempted entry was a duplicate (which changed BG to red), but it was easier to just make that the default.
My comboBox and textBox do not do this. Any idea what I could do differently so that only the Initialize function clears it?
Thanks,
Here is the code snippet where it clears the listBox selected items. Comment above line that seems to be causing this.
EDIT: It deselects whenever I change the background color. It also deselects when I cause a duplicate, which doesn't change the background color. So the list box is deselecting on its own in many cases. If I can find the cause of one of them (two of which are listed here), then perhaps I can resolve the third one.
Function HighlightEmpty(ByVal nameSelect As Boolean, ByVal comboSelect As Boolean, ByVal listSelect As Boolean) As Boolean
' Highlight empty fields
If Not nameSelect Then
Enter_New_DTC_Form.SignalNameTxtBox.BackColor = RGB(255, 0, 0)
Else
Enter_New_DTC_Form.SignalNameTxtBox.BackColor = RGB(255, 255, 255)
End If
If Not comboSelect Then
Enter_New_DTC_Form.ComboBox1.BackColor = RGB(255, 0, 0)
Else
Enter_New_DTC_Form.ComboBox1.BackColor = RGB(255, 255, 255)
End If
If Not listSelect Then
Enter_New_DTC_Form.ListBox1.BackColor = RGB(255, 0, 0)
Else
**'This is where it breaks**
Enter_New_DTC_Form.ListBox1.BackColor = RGB(255, 255, 255)
End If
' Set focus to first empty field on form
If Not nameSelect Then
Enter_New_DTC_Form.SignalNameTxtBox.SetFocus
ElseIf Not comboSelect Then
Enter_New_DTC_Form.ComboBox1.SetFocus
ElseIf Not listSelect Then
Enter_New_DTC_Form.ListBox1.SetFocus
End If
' Return boolean to trigger message
HighlightEmpty = Not nameSelect Or Not comboSelect Or Not listSelect
End Function
I realize the original post is over 2 years old but it's still relevant as I experienced this EXACT issue using Excel 2013 and VBA 7.1. I'm just an amateur when it comes to coding, but I came up with the following code as a workaround.
This code would be used after the data has been validated and you're ready to move to the next step.
You end up finding the index of the selected list item, adding 1 to it, setting the selected list item to the next/previous item, then setting it back to the actual item. I don't know why this is necessary, but it works.
'Determine the currently selected list item and set j to the index of it
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) Then j = i
Next i
'Set j to 1 more than the index of the selected list item
j = j + 1
'If the selected list item isn't the last one, select the next item,
'then re-select the original item
If j < ListBox1.ListCount Then
ListBox1.BackColor = RGB(255, 255, 255) 'Set the background color to white
ListBox1.ForeColor = RGB(0, 0, 0) 'and the foreground color to black
ListBox1.ListIndex = (j) 'Select the NEXT item in the list
ListBox1.ListIndex = (j - 1) 'Re-select the ORIGINAL item
'If the selected list item is the last one, select the previous item,
'then re-select the original item
ElseIf j = ListBox1.ListCount Then
ListBox1.BackColor = RGB(255, 255, 255) 'Set the background color to white
ListBox1.ForeColor = RGB(0, 0, 0) 'Set the foreground color to black
ListBox1.ListIndex = (j - 2) 'Select the PREVIOUS item in the list
ListBox1.ListIndex = (j - 1) 'Re-select the ORIGINAL item
End If
Hope this helps. I spent a lot of time researching and could not find a solution to the root cause but implemented this code in my own spreadsheet.
A possible solution is to store the selections, change BackColor then reapply selections;
Public Sub UpdateBackgroundColor()
Dim sel() As Boolean: sel = GetSelectedIndexs()
list_box.BackColor = &H80000005
SetSelectedIndexs sel
End Sub
Private Function GetSelectedIndexs() As Boolean()
If list_box.ListCount > 0 Then
ReDim sel(0 To list_box.ListCount - 1) As Boolean
Dim i As Integer
For i = 0 To list_box.ListCount - 1
sel(i) = list_box.Selected(i)
Next
GetSelectedIndexs = sel
Else
ReDim GetSelectedIndexs(0)
End If
End Function
Private Function SetSelectedIndexs(sel() As Boolean)
Dim i As Integer
For i = LBound(sel) To UBound(sel)
list_box.Selected(i) = sel(i)
Next
End Function
I am using vb.net in my project. I have a datagridview bounded to a datatable m_table which has a column called Price_Change with decimal values. I want to display text in datagridview in green if price change>0 and red otherwise. I cannot simply use the following formatting because the bounded data table m_table is constructed in my code, not directly through data base.
DataGridView.Rows(0)Cells(0).Style.ForeColor=COLOR.BLACK
Code looks like
Dim rowText As DataRow = m_table.NewRow
rowText("Price Change")=10.00 'assign values to price change column
' there is no color formating for data table
I wonder if cellformatting event can be used for this purpose. Would it slow down the load of datagridview? Here is a [link]
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellformatting.aspx
Private Sub DGVTable_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DGVTable.CellFormatting
If Me.DGVTable.Columns(e.ColumnIndex).Name = columnPriceChange Then
If e.Value IsNot Nothing Then
Dim change As Decimal = CType(e.Value, Decimal)
If change >= 0 Then
e.CellStyle.ForeColor = Color.Green
Else
e.CellStyle.ForeColor = Color.Red
End If
End If
End If
End Sub