DataGridViewのセル結合
DataGridViewでセルを結合するためには、自分でセルを結合したかのように描画する必要があるみたい。
見せかけのヘッダー列を固定したい場合は「行のセル固定」の記事を見てください。
そこで次の表を作成したいときのプログラムメモ。
- 表を見せるのみです。
- 行列の追加、編集、削除や、セル幅の変更は考慮していません。
- 行列のヘッダーは無効にしています。
- DataGridViewコントロールの名前は、「DataGridView1」です。
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Init() End Sub Private Sub Init() 'ちらつき防止 Dim type As System.Type = GetType(DataGridView) Dim propertyInfo As System.Reflection.PropertyInfo = type.GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.NonPublic) propertyInfo.SetValue(DataGridView1, True, Nothing) DataGridView1.AllowUserToAddRows = False DataGridView1.ReadOnly = True DataGridView1.AllowUserToDeleteRows = False DataGridView1.ColumnHeadersVisible = False DataGridView1.RowHeadersVisible = False Dim i As Integer Dim j As Integer Dim colAdd As DataGridViewColumn For i = 1 To 3 colAdd = New DataGridViewColumn colAdd.Name = String.Format("Column{0}", i) colAdd.Width = 60 colAdd.CellTemplate = New DataGridViewTextBoxCell DataGridView1.Columns.Add(colAdd) Next '結合したいセルには同じテキストを入れておく Dim cellText(,) As String = { {"店舗", "店舗", "売上"}, {"店舗名", "担当エリア", "売上"}, {"北支店", "駅北", "10000"}, {"北支店", "駅南", "9000"}, {"西支店", "商店街", "12000"}, {"東支店", "住宅区", "8000"}, {"南支店", "商業区", "11000"} } Dim rowAdd As DataGridViewRow For i = 0 To 6 rowAdd = New DataGridViewRow rowAdd.CreateCells(DataGridView1) For j = 0 To rowAdd.Cells.Count - 1 rowAdd.Cells(j).Value = cellText(i, j) Next DataGridView1.Rows.Add(rowAdd) Next End Sub Private Sub DataGridView1_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting '結合したいセルをここに書く MergeCell(e, New Point(0, 0), New Point(1, 0)) MergeCell(e, New Point(2, 0), New Point(2, 1)) MergeCell(e, New Point(0, 1), New Point(0, 1)) MergeCell(e, New Point(1, 1), New Point(1, 1)) End Sub 'Cell1には、セルの開始位置(X, Y) 'Cell2には、セルの終了位置(X, Y) Private Sub MergeCell(ByRef e As System.Windows.Forms.DataGridViewCellPaintingEventArgs, Cell1 As Point, Cell2 As Point) If (e.RowIndex >= Cell1.Y AndAlso e.RowIndex <= Cell2.Y) AndAlso (e.ColumnIndex >= Cell1.X AndAlso e.ColumnIndex <= Cell2.X) Then Dim rect As New Rectangle With {.X = 0, .Y = 0, .Width = 0, .Height = 0} Dim i As Integer '開始セルの位置 '結合セルが画面外にあるときの位置を考慮 For i = Cell1.Y + 1 To DataGridView1.FirstDisplayedScrollingRowIndex rect.Y -= DataGridView1(Cell1.X, i - 1).Size.Height Next For i = DataGridView1.FirstDisplayedScrollingRowIndex + 1 To Cell1.Y rect.Y += DataGridView1(Cell1.X, i - 1).Size.Height Next '結合セルが画面外にあるときの位置を考慮 For i = Cell1.X + 1 To DataGridView1.FirstDisplayedScrollingColumnIndex rect.X -= DataGridView1(i - 1, Cell1.Y).Size.Width Next For i = DataGridView1.FirstDisplayedScrollingColumnIndex + 1 To Cell1.X rect.X += DataGridView1(i - 1, Cell1.Y).Size.Width Next '終了セルの幅 For i = Cell1.Y To Cell2.Y rect.Height += DataGridView1(Cell2.X, i).Size.Height Next For i = Cell1.X To Cell2.X rect.Width += DataGridView1(i, Cell2.Y).Size.Width Next 'セル位置の補正 rect.X += 1 rect.Y += 1 'グラデーションをかけてヘッダーぽく見せる Dim gb As New System.Drawing.Drawing2D.LinearGradientBrush(rect, SystemColors.ControlLightLight, SystemColors.Control, System.Drawing.Drawing2D.LinearGradientMode.Vertical) gb.GammaCorrection = True '通常の塗りつぶし 'e.Graphics.FillRectangle(New SolidBrush(SystemColors.Control), rect) e.Graphics.FillRectangle(gb, rect) e.Graphics.DrawRectangle(New Pen(DataGridView1.GridColor), rect) gb.Dispose() '描画するセル位置の文字をヘッダーテキストとして表示 Dim headerText As String = DataGridView1(e.ColumnIndex, e.RowIndex).Value TextRenderer.DrawText(e.Graphics, headerText, e.CellStyle.Font, rect, e.CellStyle.ForeColor, TextFormatFlags.HorizontalCenter Or TextFormatFlags.VerticalCenter) e.Handled = True End If End Sub
2016/01/27 結合セルが半分だけ画面外の場合を考慮