how can i merge cell of a gridview having same value at runtime in vb.net .-Collection of common programming errors
msdnHello,
i want to show the schedule in a grid.In that grid there is a column ‘Time’ with the cells like 8am,8:30:am……9pm. and other column have employee name so if an employee has task from 8 am to 10 am then i make those cells in red color with employee name. now whats happening is, from 8am to 10 am all the cells are showing that employee name but i want to merge them into one and make the employee name at center.
Please help me out.
Thanks & Regards,
Sonal
-
25 Answers
msdn1Hi,
i recreated the scenario in VB.NET language with DataTable as datasource. Please follow the code.It is working fine.
Imports System.Data Public Class Form1 Dim dt As New DataTable Public Sub New() ' This call is required by the designer. InitializeComponent() dt.Columns.Add(New DataColumn("Column1")) dt.Columns.Add(New DataColumn("Column2")) Dim row1 As DataRow = dt.NewRow() row1("Column1") = "A" row1("Column2") = "Green" dt.Rows.Add(row1) Dim row2 As DataRow = dt.NewRow() row2("Column1") = "A" row2("Column2") = "Pink" dt.Rows.Add(row2) Dim row3 As DataRow = dt.NewRow() row3("Column1") = "B" row3("Column2") = "Red" dt.Rows.Add(row3) Dim row4 As DataRow = dt.NewRow() row4("Column1") = "C" row4("Column2") = "Blue" dt.Rows.Add(row4) Dim row5 As DataRow = dt.NewRow() row5("Column1") = "D" row5("Column2") = "Green" dt.Rows.Add(row5) Dim row6 As DataRow = dt.NewRow() row6("Column1") = "D" row6("Column2") = "Blue" dt.Rows.Add(row6) Dim row7 As DataRow = dt.NewRow() row7("Column1") = "E" row7("Column2") = "Green" dt.Rows.Add(row7) DataGridView1.DataSource = dt End Sub Private Sub DataGridView1_CellPainting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex = 0 Then If (DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString()) Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If If e.RowIndex > 0 Then If e.RowIndex < DataGridView1.Rows.Count - 2 Then If (DataGridView1.Rows(e.RowIndex - 1).Cells(0).Value.ToString() = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString()) Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None End If End If If (DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString()) Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If End If End Sub End Class
Let me know if your issue persists. As you said you can remove duplicate text , so just let me know if you were able to do that!
msdn2Hi Sonal,
Thanks for your patience.
I thought it will be a better way to remove repeated entry in the DataSource itself and with some little modifications you can achieve your requirement.
So, before binding i modified the data table like this :
Dim prev As String = dt.Rows(0)(0).ToString() For i = 1 To dt.Rows.Count - 1 If dt.Rows(i)(0).ToString() = prev Then dt.Rows(i)(0) = "" Else prev = dt.Rows(i)(0).ToString() End If Next DataGridView1.DataSource = dt
After modification, i have done some changes in the CellPainting event, so please follow the code, you will achieve your requirement:
Private Sub DataGridView1_CellPainting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex > 0 Then If e.RowIndex < DataGridView1.Rows.Count - 2 Then If DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString() = "" Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If If DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = "" Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None End If End If End If End If If e.RowIndex = 0 Then If DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString() = "" Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If End Sub
Hope this helps. Let me know if you are still in problem.
One good question is equivalent to ten best answers.
msdn3Hello,
Not completely clear but is this what you want i.e. remove repeating data?
If so then add the following DataGridView to your project, use it as any DataGridView i.e. DataGridView1.DataSource = SomeDataTable.
''' ''' Original author ''' http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/a44622c0-74e1-463b-97b9-27b87513747e#faq8 ''' ''' ''' Original code was in C Sharp, I converted and tweaked some code ''' which did not compile under VB.NET ''' Public Class GroupByGrid Inherits DataGridView Protected Overrides Sub OnCellFormatting(ByVal args As DataGridViewCellFormattingEventArgs) MyBase.OnCellFormatting(args) ' First row always displays If args.RowIndex = 0 Then Return End If If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then args.Value = String.Empty args.FormattingApplied = True End If End Sub Private Function IsRepeatedCellValue(ByVal rowIndex As Integer, ByVal colIndex As Integer) As Boolean Dim currCell As DataGridViewCell = Rows(rowIndex).Cells(colIndex) Dim prevCell As DataGridViewCell = Rows(rowIndex - 1).Cells(colIndex) If (currCell.Value Is prevCell.Value) OrElse (currCell.Value IsNot Nothing AndAlso prevCell.Value IsNot Nothing AndAlso currCell.Value.ToString() = prevCell.Value.ToString()) Then Return True Else Return False End If End Function Protected Overrides Sub OnCellPainting(ByVal args As DataGridViewCellPaintingEventArgs) MyBase.OnCellPainting(args) args.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None ' Ignore column and row headers and first row If args.RowIndex < 1 OrElse args.ColumnIndex < 0 Then Return End If If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then args.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None Else args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top End If End Sub End Class
msdn4Hi Shyam,
It is a window form Desktop Project.
msdn5
msdn6Yes, I have gone through the below link, but i didnt find it helpful.
http://www.dotnetspider.com/resources/4644-Merge-columns-DataGridView-Excel-Spread.aspx
msdn7Hi, follow the code to get your resolution.
dataGridView1 is added in designer.
namespace WindowsFormsApplication1 { public partial class Form1 : Form { List li = new List(); public Form1() { InitializeComponent(); li.Add(new X() { Column1 = "A", Column2 ="Green" }); li.Add(new X() { Column1 = "A", Column2 = "Red" }); li.Add(new X() { Column1 = "B", Column2 = "Green" }); li.Add(new X() { Column1 = "C", Column2 = "Blue" }); li.Add(new X() { Column1 = "E", Column2 = "Pink" }); li.Add(new X() { Column1 = "E", Column2 = "Green" }); li.Add(new X() { Column1 = "F", Column2 = "Black" }); dataGridView1.DataSource = li; dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting); } void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex == 0) { if (dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString() == dataGridView1.Rows[e.RowIndex +1].Cells[0].Value.ToString()) { if (e.ColumnIndex == 0) { e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None; } } } if (e.RowIndex >0) { if (dataGridView1.Rows[e.RowIndex - 1].Cells[0].Value.ToString() == dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString()) { if (e.ColumnIndex == 0) { e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None; } } if (e.RowIndex < dataGridView1.Rows.Count - 1) { if (dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString() == dataGridView1.Rows[e.RowIndex + 1].Cells[0].Value.ToString()) { if (e.ColumnIndex == 0) { e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None; } } } } } } public class X { public string Column1 { get; set; } public string Column2 { get; set; } } }
Hope this may help.
One good question is equivalent to ten best answers.
msdn8Thanks Shyam.
But i have used same code before but it didnt work.datagridview cells border style remain same.
msdn9 Oh yea. I only thought to merge the borders. I left to take only one data per merged cell.Ok let me try.
Did the borders are merged from your side for repeated data?One good question is equivalent to ten best answers.
msdn10Nope, data i can handle but the issue is with the border only. its nt getting merge because i guess border style isnt getting change.
msdn11 Hi, have you copy-paste my whole code and taken DataGridView in design ?Here from my side everything works fine. All matching cells border are merged from my side.
msdn12I copied what i needed like i copied the whole code from datagridview CellPainting event and pasted it into Datagridview cellpainting event in my code.
msdn13I am binding Datagridview to a datatable. i am using the above code in the DataGridView_CellPainting event :
For i As Integer = 1 To dgvScheduler.Columns.Count – 1 If e.RowIndex = 0 Then If dgvScheduler.Rows(e.RowIndex).Cells(i).Value.ToString() = dgvScheduler.Rows(e.RowIndex + 1).Cells(i).Value.ToString() Then If e.ColumnIndex = 0 Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If If e.RowIndex > 0 Then If dgvScheduler.Rows(e.RowIndex – 1).Cells(i).Value.ToString() = dgvScheduler.Rows(e.RowIndex).Cells(i).Value.ToString() Then If e.ColumnIndex = 0 Then e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None End If End If If e.RowIndex < dgvScheduler.Rows.Count – 1 Then If dgvScheduler.Rows(e.RowIndex).Cells(i).Value.ToString() = dgvScheduler.Rows(e.RowIndex + 1).Cells(i).Value.ToString() Then If e.ColumnIndex = 0 Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If End If
Next
msdn14i created a separate application and used your code it worked absolutely fine. then why not in my code.
msdn15Hi,
i recreated the scenario in VB.NET language with DataTable as datasource. Please follow the code.It is working fine.
Imports System.Data Public Class Form1 Dim dt As New DataTable Public Sub New() ' This call is required by the designer. InitializeComponent() dt.Columns.Add(New DataColumn("Column1")) dt.Columns.Add(New DataColumn("Column2")) Dim row1 As DataRow = dt.NewRow() row1("Column1") = "A" row1("Column2") = "Green" dt.Rows.Add(row1) Dim row2 As DataRow = dt.NewRow() row2("Column1") = "A" row2("Column2") = "Pink" dt.Rows.Add(row2) Dim row3 As DataRow = dt.NewRow() row3("Column1") = "B" row3("Column2") = "Red" dt.Rows.Add(row3) Dim row4 As DataRow = dt.NewRow() row4("Column1") = "C" row4("Column2") = "Blue" dt.Rows.Add(row4) Dim row5 As DataRow = dt.NewRow() row5("Column1") = "D" row5("Column2") = "Green" dt.Rows.Add(row5) Dim row6 As DataRow = dt.NewRow() row6("Column1") = "D" row6("Column2") = "Blue" dt.Rows.Add(row6) Dim row7 As DataRow = dt.NewRow() row7("Column1") = "E" row7("Column2") = "Green" dt.Rows.Add(row7) DataGridView1.DataSource = dt End Sub Private Sub DataGridView1_CellPainting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex = 0 Then If (DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString()) Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If If e.RowIndex > 0 Then If e.RowIndex < DataGridView1.Rows.Count - 2 Then If (DataGridView1.Rows(e.RowIndex - 1).Cells(0).Value.ToString() = DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString()) Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None End If End If If (DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString()) Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If End If End Sub End Class
Let me know if your issue persists. As you said you can remove duplicate text , so just let me know if you were able to do that!
msdn16HI,
you need to modify second If condition. Get the code with appropiate If condition as per the Code.
Different languages different constructs!
msdn17Seems its working. Can u pls tell me how to merge data now?
msdn18Seems its working. Can u pls tell me how to merge data now?
Even if we remove the duplicate Text, i fear is it possible to Show the Text Vertically Center ?
Since unlike HTML table, here we did not have CellSpan or ColumnSpan ? So how your cells Text will be vertically center aligned ?
msdn19yeah true. but its no use if i don’t remove the duplicate Text. Can we show the text at TOP ?
msdn20yeah true. but its no use if i don’t remove the duplicate Text. Can we show the text at TOP ?
Yes, that we can try 🙂
msdn21ok, then lets try 🙂
msdn22Hi Sonal,
Thanks for your patience.
I thought it will be a better way to remove repeated entry in the DataSource itself and with some little modifications you can achieve your requirement.
So, before binding i modified the data table like this :
Dim prev As String = dt.Rows(0)(0).ToString() For i = 1 To dt.Rows.Count - 1 If dt.Rows(i)(0).ToString() = prev Then dt.Rows(i)(0) = "" Else prev = dt.Rows(i)(0).ToString() End If Next DataGridView1.DataSource = dt
After modification, i have done some changes in the CellPainting event, so please follow the code, you will achieve your requirement:
Private Sub DataGridView1_CellPainting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting If e.RowIndex > 0 Then If e.RowIndex < DataGridView1.Rows.Count - 2 Then If DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString() = "" Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If If DataGridView1.Rows(e.RowIndex).Cells(0).Value.ToString() = "" Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None End If End If End If End If If e.RowIndex = 0 Then If DataGridView1.Rows(e.RowIndex + 1).Cells(0).Value.ToString() = "" Then If (e.ColumnIndex = 0) Then e.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None End If End If End If End Sub
Hope this helps. Let me know if you are still in problem.
One good question is equivalent to ten best answers.
msdn23Hello,
Not completely clear but is this what you want i.e. remove repeating data?
If so then add the following DataGridView to your project, use it as any DataGridView i.e. DataGridView1.DataSource = SomeDataTable.
''' ''' Original author ''' http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/a44622c0-74e1-463b-97b9-27b87513747e#faq8 ''' ''' ''' Original code was in C Sharp, I converted and tweaked some code ''' which did not compile under VB.NET ''' Public Class GroupByGrid Inherits DataGridView Protected Overrides Sub OnCellFormatting(ByVal args As DataGridViewCellFormattingEventArgs) MyBase.OnCellFormatting(args) ' First row always displays If args.RowIndex = 0 Then Return End If If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then args.Value = String.Empty args.FormattingApplied = True End If End Sub Private Function IsRepeatedCellValue(ByVal rowIndex As Integer, ByVal colIndex As Integer) As Boolean Dim currCell As DataGridViewCell = Rows(rowIndex).Cells(colIndex) Dim prevCell As DataGridViewCell = Rows(rowIndex - 1).Cells(colIndex) If (currCell.Value Is prevCell.Value) OrElse (currCell.Value IsNot Nothing AndAlso prevCell.Value IsNot Nothing AndAlso currCell.Value.ToString() = prevCell.Value.ToString()) Then Return True Else Return False End If End Function Protected Overrides Sub OnCellPainting(ByVal args As DataGridViewCellPaintingEventArgs) MyBase.OnCellPainting(args) args.AdvancedBorderStyle.Bottom = DataGridViewAdvancedCellBorderStyle.None ' Ignore column and row headers and first row If args.RowIndex < 1 OrElse args.ColumnIndex < 0 Then Return End If If IsRepeatedCellValue(args.RowIndex, args.ColumnIndex) Then args.AdvancedBorderStyle.Top = DataGridViewAdvancedCellBorderStyle.None Else args.AdvancedBorderStyle.Top = AdvancedCellBorderStyle.Top End If End Sub End Class
msdn24Hi Shyam,
Thank you so much.
I really appreciated the way u helped me out and understood what i wanted.Finally i achieved exactly what i wanted 🙂
msdn25Hello Kevin,
Thanks alot.
your code is working perfectly and it helped me 🙂