如何将数据保存到一个 excel 文件中的 datagridview

How to save to datagridview data in one excel file

我正在使用 microsoft.excel.introp.dlldatagridview 数据保存到 excel 文件,我的问题是如何在一个文件中保存两个 datagridview 数据(sheet1sheet2

我正在使用此代码将第一个数据网格视图保存为 excel 文件:

    Private Sub copyAlltoClipboard()
        DataGridView1.SelectAll()
        Dim dataObj As DataObject = DataGridView1.GetClipboardContent()
        If dataObj IsNot Nothing Then Clipboard.SetDataObject(dataObj)
    End Sub

    Private Sub releaseObject(ByVal obj As Object)
        Try
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            obj = Nothing
        Catch ex As Exception
            obj = Nothing
            MessageBox.Show("Exception Occurred while releasing object " & ex.ToString())
        Finally
            GC.Collect()
        End Try
    End Sub

 Dim sfd As SaveFileDialog = New SaveFileDialog()
            sfd.Filter = "Microsoft Excel 97-2003 Workbook (*.xls)|*.xls"

            sfd.FileName = NomTextBox.Text & "_" & PrenomTextBox.Text

            If sfd.ShowDialog() = DialogResult.OK Then
                copyAlltoClipboard()
                Dim xlexcel As Excel.Application
                Dim xlWorkBook As Excel.Workbook
                Dim xlWorkSheet As Excel.Worksheet
                Dim misValue As Object = System.Reflection.Missing.Value
                xlexcel = New Excel.Application()
                xlexcel.Visible = False
                xlWorkBook = xlexcel.Workbooks.Add(misValue)
                xlWorkSheet = CType(xlWorkBook.Worksheets.Item(1), Excel.Worksheet)
                Dim CR As Excel.Range = CType(xlWorkSheet.Cells(1, 1), Excel.Range)
                CR.[Select]()
                xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)

 xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue)
                xlexcel.DisplayAlerts = True
                xlWorkBook.Close(True, misValue, misValue)
                xlexcel.Quit()
                releaseObject(xlWorkSheet)
                releaseObject(xlWorkBook)
                releaseObject(xlexcel)
                Clipboard.Clear()

这不是我的代码,我从别人那里拿来并修改过的。

首先,您应该知道不建议使用 Interop。还有其他 third-party 库在许多方面工作得更好并且有一些优势。也就是说,使用互操作需要目标计算机具有与代码使用的相同的 Excel 库。但是,我知道这可能是必需的或唯一的选择。如果是这种情况,那么下面的代码可能会有所帮助。

当前代码存在的一个问题是无法控制“工作表名称”应该是什么。恕我直言,最好给工作表一个“特定”名称,以便代码稍后可以用新数据覆盖文件。通过简单地添加新工作表,您最终可能会得到一堆具有相同数据的工作表。

因此,我创建了一个方法 GetWorksheet,它接受一个 WorkbookString name. 这个方法将 return 一个 Worksheet要么“匹配”给定的名称,要么如果在给定的工作簿中找不到工作表名称,那么它将 return 一个具有给定名称的新工作表。这个方法可能看起来像……

Private Function GetWorksheet(wb As Excel.Workbook, name As String) As Excel.Worksheet
  For Each ws In wb.Sheets
    If ws.Name = name Then
      Return ws
    End If
  Next
  Dim newWS = wb.Worksheets.Add()
  newWS.Name = name
  Return newWS
End Function

上面的代码遍历给定工作簿中的所有工作表。如果找到与给定名称匹配的工作表名称,则该工作表将被 returned。如果未找到工作表名称,则会 returned 一个具有给定名称的新工作表。这将允许您将工作表命名为比“Sheet1”、“Sheet2”等更直观的名称。我们可以使用此方法获取现有工作表或为要添加到工作簿的每个网格创建新工作表。

接下来,第二个名为 AddSheetToWorkbook 的辅助方法需要一个工作簿、一个 DataGridView 和一个工作表名称...可能会使事情变得更容易。在此方法中,代码将 select 给定网格中的所有单元格。使用上述方法从给定的 (OPEN) 工作簿中获取具有给定工作表名称的工作表。然后将复制的单元格粘贴到工作表中。它可能看起来像……

Private Sub AddSheetToWorkbook(xlWorkBook As Excel.Workbook, dgv As DataGridView, wkSheetName As String)
  dgv.SelectAll()
  Dim dataObj As DataObject = dgv.GetClipboardContent()
  If dataObj IsNot Nothing Then Clipboard.SetDataObject(dataObj)
  Dim xlWorkSheet = GetWorksheet(xlWorkBook, wkSheetName)
  Dim CR As Excel.Range = CType(xlWorkSheet.Cells(1, 1), Excel.Range)
  CR.[Select]()
  xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, True)
End Sub

我们可以使用此方法将每个 DataGridView 添加到工作簿中的不同工作表。

最后,将所有这些放在一起可能如下所示。我使用了一些不同的方法,使用 Try/Catch/Finally 来确保 Excel COM objects 被正确处理,但是,在我的测试中,当前代码也有效。

该代码使用与当前代码相同的方法。使用 SaveFileDialog. 获取工作簿的文件名 创建一个新的 Excel 应用程序,添加工作簿,然后将两个网格添加到工作簿。每个网格都将位于一个单独的工作表上,并带有提供的工作表名称。文件已保存,Finally COM objects 已关闭并释放。

不清楚在当前发布的代码中“在哪里”调用了这段代码。在此示例中,代码是 运行 通过按表单上的按钮。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  Dim sfd As SaveFileDialog = New SaveFileDialog With {
    .Filter = "Microsoft Excel 97-2003 Workbook (*.xls)|*.xls",
    .FileName = NomTextBox.Text & "_" & PrenomTextBox.Text
  }
  If sfd.ShowDialog() = DialogResult.OK Then
    Dim xlexcel As Excel.Application = Nothing
    Dim xlWorkBook As Excel.Workbook = Nothing
    Dim misValue As Object = Reflection.Missing.Value
    Try
      xlexcel = New Excel.Application()
      xlWorkBook = xlexcel.Workbooks.Add()
      AddSheetToWorkbook(xlWorkBook, DataGridView1, "Grid1")
      AddSheetToWorkbook(xlWorkBook, DataGridView2, "Grid2")
      xlWorkBook.SaveAs(sfd.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue)
    Catch ex As Exception
      MessageBox.Show("Error: " + ex.Message)
    Finally
      If (xlWorkBook IsNot Nothing) Then
        xlWorkBook.Close()
        Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook)
      End If
      If (xlexcel IsNot Nothing) Then
        xlexcel.Quit()
        Runtime.InteropServices.Marshal.ReleaseComObject(xlexcel)
      End If
      MessageBox.Show("Export Complete")
    End Try
  End If
End Sub

最后,我猜您不需要 Excel 文件中的 headers 列,因为 OS select all 和复制命令不会抓取网格列 header 文本。

我希望这是有道理的。