从 DatagridView 创建 Tiff 位图文件

Create a Tiff Bitmap file from a DatagridView

我想从 Datagridview 创建一个 Tiff 文件。我能够将 Datagridview 获取到 Tiff 文件,但我只想要行和列,别无其他。

这是否可以不使用第 3 方工具?

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    DataGridView1.Rows.Add(New String() {"Value1", "Value2", "Value3"})


    Dim height As Integer = DataGridView1.Height
    DataGridView1.Height = DataGridView1.RowCount * DataGridView1.RowTemplate.Height

    Dim bitmap As Bitmap = New Bitmap(Me.DataGridView1.Width - 1, Me.DataGridView1.Height - 1)
    DataGridView1.DrawToBitmap(bitmap, New Rectangle(0, 0, Me.DataGridView1.Width - 1, Me.DataGridView1.Height - 1))

    'Save the Bitmap to folder.
    bitmap.Save("C:Development\DataGridView.Tiff")

End Sub

我不想要突出显示的

有几点需要考虑:

  1. 当控件绘制到位图时,DataGridView 的行和列必须可见,
  2. 可能存在滚动条,
  3. Rows的高度可能不同,所以我们要对所有行的高度求和,
  4. 列也是如此,因为每个列都有自己的宽度,
  5. CellFormatting 可能已经到位,因此我们需要在绘制之前刷新 DataGridView:不可见的行可能尚未格式化,
  6. 位图尺寸有限制 (32,767)。

按如下方式调用此方法,指定是要包含行或列 Headers 还是排除两者,将 True/False 作为 ColumnHeadersRowHeaders 个参数。
dgv参数当然是要绘制的DataGridView控件实例:

' Prints the DataGridView including the Columns' Headers only
Dim dgvBitmap = DataGridViewToBitmap(DataGridView1, True, False)
Dim imagePath = Path.Combine(AppContext.BaseDirectory, $"{NameOf(DataGridView1)}.tiff")
dgvBitmap.Save(imagePath, ImageFormat.Tiff)

' Dispose of the Bitmap or set it as the PictureBox.Image, dispose of it later.  
dgvBitmap.Dispose()

Private Function DataGridViewToBitmap(dgv As DataGridView, ColumnHeaders As Boolean, RowHeaders As Boolean) As Bitmap
    dgv.ClearSelection()
    Dim originalSize = dgv.Size
    dgv.Height = dgv.Rows.OfType(Of DataGridViewRow).Sum(Function(r) r.Height) + dgv.ColumnHeadersHeight
    dgv.Width = dgv.Columns.OfType(Of DataGridViewColumn).Sum(Function(c) c.Width) + dgv.RowHeadersWidth
    dgv.Refresh()

    Dim dgvPosition = New Point(If(RowHeaders, 0, dgv.RowHeadersWidth), If(ColumnHeaders, 0, dgv.ColumnHeadersHeight))
    Dim dgvSize = New Size(dgv.Width, dgv.Height)
    If dgvSize.Height > 32760 OrElse dgvSize.Width > 32760 Then Return Nothing

    Dim rect As Rectangle = New Rectangle(Point.Empty, dgvSize)
    Using bmp As Bitmap = New Bitmap(dgvSize.Width, dgvSize.Height)
        dgv.DrawToBitmap(bmp, rect)
        If (dgv.Width > originalSize.Width) AndAlso dgv.ScrollBars.HasFlag(ScrollBars.Vertical) Then
            dgvSize.Width -= SystemInformation.VerticalScrollBarWidth
        End If
        If (dgv.Height > originalSize.Height) AndAlso dgv.ScrollBars.HasFlag(ScrollBars.Horizontal) Then
            dgvSize.Height -= SystemInformation.HorizontalScrollBarHeight
        End If
        dgvSize = New Size(dgvSize.Width - dgvPosition.X, dgvSize.Height - dgvPosition.Y)

        dgv.Size = originalSize
        Return bmp.Clone(New Rectangle(dgvPosition, dgvSize), PixelFormat.Format32bppArgb)
    End Using
End Function