Help with simplifying For Next loop for multiple Grids

Hello,


How do I modify the code to avoid writing the same code for multiple Grids (C1Screen1,C1Screen2,C1Screen3)?

For i = 0 To Me.C1Screen1.Rows.Count - 1
            For j = 1 To Me.C1Screen1.Columns.Count - 1
                 If Me.C1Screen1.Rows(i).Cells(j).Value = "" Then 
                    Me.C1Screen1.Rows(i).Cells(j).Style.BackColor = Color.Red
                 End If
            Next
        Next

Open in new window

vcharlesAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Rgonzo1971Commented:
Hi,

Why not write a subroutine with the object as parameter (C1Screen1,C1Screen2 or C1Screen3)

Regards
0
it_saigeDeveloperCommented:
I would think that an Extension method would fit the bill for you:
Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Sub MarkEmptyColumns(ByVal grid As DataGridView, Optional ByVal backColor As Color = Nothing)
		If backColor = Nothing Then backColor = Color.Red

		For Each [cell] In (From [row] As DataGridViewRow In grid.Rows
		    From [column] As DataGridViewCell In [row].Cells
		    Where String.IsNullOrEmpty([column].Value) Select [column])
			[cell].Style.BackColor = backColor
		Next
	End Sub
End Module

Open in new window

Proof of concept:
Form1.vb -
Public Class Form1
	ReadOnly customers As New List(Of Customer)

	Private Sub OnLoad(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
		For Each [customer] In (From item In Enumerable.Range(0, 5) Select New Customer() With {.ID = item, .Name = String.Format("Name{0}", item), .NickName = If(item Mod 2 = 0, "", "Odd")})
			customers.Add([customer])
		Next
		DataGridView1.DataSource = customers
		DataGridView1.MarkEmptyColumns()
	End Sub
End Class

Class Customer
	Public Property ID() As Integer
	Public Property Name() As String
	Public Property NickName() As String
End Class

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Sub MarkEmptyColumns(ByVal grid As DataGridView, Optional ByVal backColor As Color = Nothing)
		If backColor = Nothing Then backColor = Color.Red

		For Each [cell] In (From [row] As DataGridViewRow In grid.Rows
		    From [column] As DataGridViewCell In [row].Cells
		    Where String.IsNullOrEmpty([column].Value) Select [column])
			[cell].Style.BackColor = backColor
		Next
	End Sub
End Module

Open in new window

Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
		Me.DataGridView1 = New System.Windows.Forms.DataGridView()
		CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).BeginInit()
		Me.SuspendLayout()
		'
		'DataGridView1
		'
		Me.DataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
		Me.DataGridView1.Dock = System.Windows.Forms.DockStyle.Fill
		Me.DataGridView1.Location = New System.Drawing.Point(0, 0)
		Me.DataGridView1.Name = "DataGridView1"
		Me.DataGridView1.RowHeadersVisible = False
		Me.DataGridView1.Size = New System.Drawing.Size(413, 261)
		Me.DataGridView1.TabIndex = 0
		'
		'Form1
		'
		Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
		Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
		Me.ClientSize = New System.Drawing.Size(413, 261)
		Me.Controls.Add(Me.DataGridView1)
		Me.Name = "Form1"
		Me.Text = "Form1"
		CType(Me.DataGridView1, System.ComponentModel.ISupportInitialize).EndInit()
		Me.ResumeLayout(False)

	End Sub
	Friend WithEvents DataGridView1 As System.Windows.Forms.DataGridView

End Class

Open in new window

Produces the following output -Capture.JPG-saige-
0
vcharlesAuthor Commented:
Hi,

Is it possible to use this approach and replace Me.C1Screen1 with curXYZ ?

Dim xyz() As String = New String() {"c1screen1", "c1screen2", "c1screen3"}
Dim curXYZ = xyz(i)
For i = 0 To 2
For i = 0 To Me.C1Screen1.Rows.Count - 1
            For j = 1 To Me.C1Screen1.Columns.Count - 1
                 If Me.C1Screen1.Rows(i).Cells(j).Value = "" Then 
                    Me.C1Screen1.Rows(i).Cells(j).Style.BackColor = Color.Red
                 End If
            Next
        Next

Next

Open in new window


Thanks,

V.
0
it_saigeDeveloperCommented:
If you wanted to use this approach then you would want to utilize the form instance (lest you want to go down the road of reflection); e.g. -
Private Sub MarkEmptyColumns(ByVal form As Form, ByVal gridNames As IEnumerable(Of String))
	For Each gridName In gridNames
		Dim grid = form.Controls(gridName)
		If grid IsNot Nothing AndAlso TypeOf grid Is DataGridView Then
			For Each [row] As DataGridViewRow In DirectCast(grid, DataGridView).Rows
				For Each [cell] As DataGridViewCell In [row].Cells
					If String.IsNullOrEmpty([cell].Value) Then
						[cell].Style.BackColor = Color.Red
					End If
				Next
			Next
		End If
	Next
End Sub

Open in new window

Using the above code, you would call the method as such:
MarkEmptyColumns(Me, {"c1screen1", "c1screen2", "c1screen3"})

Open in new window

This method, however, is not an ideal method for referencing the controls on the form.  Since we are passing in strings to represent the controls, we are depending on our ability to recall the exact name (not taking case into account) of a control in order to retrieve it from the Controls collection.

A cleaner method would be to just reference the grids directly.  This way we don't have to pass the form instance and we don't have to worry about misspelling the name of the grid (intellisense to the rescue); e.g. -
Private Sub MarkEmptyColumns(ByVal grids As IEnumerable(Of DataGridView))
	For Each [grid] In grids
		If [grid] IsNot Nothing Then
			For Each [row] As DataGridViewRow In grid.Rows
				For Each [cell] As DataGridViewCell In [row].Cells
					If String.IsNullOrEmpty([cell].Value) Then
						[cell].Style.BackColor = Color.Red
					End If
				Next
			Next
		End If
	Next
End Sub

Open in new window

Using the above code, we would now call the method like this:
MarkEmptyColumns({c1screen1, c1screen2, c1screen3})

Open in new window

-saige-
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
vcharlesAuthor Commented:
Thank you, will try it and get back to you.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.