使用 header 文本导出到 Excel
Export to Excel with header text
我的代码在导出到 Excel 时应该包含 header 文本。
For i As Integer = 0 To DataGridView2.Rows.Count - 2
For j As Integer = 0 To DataGridView2.Columns.Count - 1
' Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
If cellRowIndex = 1 Then
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView2.Columns(j).HeaderText
Else
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView2.Rows(i).Cells(j).Value
End If
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
但是,此代码将第一个数据行替换为 header 文本,而不是将其插入上面。如果我删除提取 header 文本的 If 语句,我会取出所有行,但不会得到 header 文本。
For i As Integer = 0 To DataGridView2.Rows.Count - 2
For j As Integer = 0 To DataGridView2.Columns.Count - 1
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView2.Rows(i).Cells(j).Value
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
关于如何解决这个问题有什么想法吗?
下面的代码使用 DataGridView 中的 header 创建了一个 Excel 文件。我在 Visual Studio 2010 测试过它。首先你必须添加 Microsoft Office 程序集的引用。
Microsoft.Office.Interop.Excel(版本 - 12.0.0.0)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim xlApp As Microsoft.Office.Interop.Excel.Application
Dim xlWorkBook As Microsoft.Office.Interop.Excel.Workbook
Dim xlWorkSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer
Dim j As Integer
xlApp = New Microsoft.Office.Interop.Excel.Application
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
For i = 0 To DataGridView1.RowCount - 2
For j = 0 To DataGridView1.ColumnCount - 1
For k As Integer = 1 To DataGridView1.Columns.Count
xlWorkSheet.Cells(1, k) = DataGridView1.Columns(k - 1).HeaderText
xlWorkSheet.Cells(i + 2, j + 1) = DataGridView1(j, i).Value.ToString()
Next
Next
Next
xlWorkSheet.SaveAs("C:\vbToexcel.xlsx")
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
MsgBox("File successfully created - C:\vbToexcel.xlsx") End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try End Sub
跟踪您的代码后,很明显您在两个 for
循环中遇到了索引问题。您提供的代码似乎缺少第一行数据。
正如您评论的那样:
this code replaces the first data row with the header text instead of inserting it above...
这是不正确的,它没有替换行,它只是跳过 DataGridView
中的第一行数据。下面是你的代码来解释。
For i As Integer = 0 To DataGridView1.Rows.Count - 2
For j As Integer = 0 To DataGridView1.Columns.Count - 1
If cellRowIndex = 1 Then
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView1.Columns(j).HeaderText
Else
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView1.Rows(i).Cells(j).Value
End If
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
基本上这循环遍历行然后列。问题出在 If
语句和索引 i
中。在此 If
语句中,您检查这是否是第一次获得 headers。如果这是第一次,请将 header 写入 excel 并继续。这将跳过第一行数据,因为循环变量 i
用作 DataGridView 行的索引,赋值:
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView1.Rows(i).Cells(j).Value
当第一次进入 j
循环时 i
是零 (0)。使用 cellRowIndex
进行检查以确定是否需要输出 header。在这种情况下,他们会……输出 header 然后退出此 if
并循环回到下一个 header。当所有 header 都输出时,您退出 j
循环并循环回到 i
循环。这会将 i
递增到 1 并进入 j
循环……因为当 header 输出时 i
已经为 0,我们将 skip/miss 行 0 in DataGridView
。我希望这是有道理的。
一个简单的解决方案是简单地从 i
at -1 开始:
For i As Integer = -1 To DataGridView1.Rows.Count - 2
这将解决您遇到的问题,但是代码并不容易理解。我建议使用 foreach
循环遍历 DataGridView
行并将列输出与行输出分开。这确实创建了两个循环,但第一个循环只会循环一次以添加 headers。下一个循环遍历所有行。这将使索引在将来更易于处理和阅读。
For Each column In DataGridView1.Columns
worksheet.Cells(1, column.Index + 1).Value = column.Name
Next
Dim rowIndex = 2
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
For colIndex As Integer = 0 To DataGridView1.Columns.Count - 1
worksheet.Cells(rowIndex, colIndex + 1).Value = row.Cells(colIndex).Value.ToString
Next
End If
rowIndex += 1
Next
希望这对您有所帮助。
我的代码在导出到 Excel 时应该包含 header 文本。
For i As Integer = 0 To DataGridView2.Rows.Count - 2
For j As Integer = 0 To DataGridView2.Columns.Count - 1
' Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
If cellRowIndex = 1 Then
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView2.Columns(j).HeaderText
Else
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView2.Rows(i).Cells(j).Value
End If
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
但是,此代码将第一个数据行替换为 header 文本,而不是将其插入上面。如果我删除提取 header 文本的 If 语句,我会取出所有行,但不会得到 header 文本。
For i As Integer = 0 To DataGridView2.Rows.Count - 2
For j As Integer = 0 To DataGridView2.Columns.Count - 1
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView2.Rows(i).Cells(j).Value
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
关于如何解决这个问题有什么想法吗?
下面的代码使用 DataGridView 中的 header 创建了一个 Excel 文件。我在 Visual Studio 2010 测试过它。首先你必须添加 Microsoft Office 程序集的引用。
Microsoft.Office.Interop.Excel(版本 - 12.0.0.0)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click Dim xlApp As Microsoft.Office.Interop.Excel.Application Dim xlWorkBook As Microsoft.Office.Interop.Excel.Workbook Dim xlWorkSheet As Microsoft.Office.Interop.Excel.Worksheet Dim misValue As Object = System.Reflection.Missing.Value Dim i As Integer Dim j As Integer xlApp = New Microsoft.Office.Interop.Excel.Application xlWorkBook = xlApp.Workbooks.Add(misValue) xlWorkSheet = xlWorkBook.Sheets("sheet1") For i = 0 To DataGridView1.RowCount - 2 For j = 0 To DataGridView1.ColumnCount - 1 For k As Integer = 1 To DataGridView1.Columns.Count xlWorkSheet.Cells(1, k) = DataGridView1.Columns(k - 1).HeaderText xlWorkSheet.Cells(i + 2, j + 1) = DataGridView1(j, i).Value.ToString() Next Next Next xlWorkSheet.SaveAs("C:\vbToexcel.xlsx") xlWorkBook.Close() xlApp.Quit() releaseObject(xlApp) releaseObject(xlWorkBook) releaseObject(xlWorkSheet) MsgBox("File successfully created - C:\vbToexcel.xlsx") End Sub Private Sub releaseObject(ByVal obj As Object) Try System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) obj = Nothing Catch ex As Exception obj = Nothing Finally GC.Collect() End Try End Sub
跟踪您的代码后,很明显您在两个 for
循环中遇到了索引问题。您提供的代码似乎缺少第一行数据。
正如您评论的那样:
this code replaces the first data row with the header text instead of inserting it above...
这是不正确的,它没有替换行,它只是跳过 DataGridView
中的第一行数据。下面是你的代码来解释。
For i As Integer = 0 To DataGridView1.Rows.Count - 2
For j As Integer = 0 To DataGridView1.Columns.Count - 1
If cellRowIndex = 1 Then
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView1.Columns(j).HeaderText
Else
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView1.Rows(i).Cells(j).Value
End If
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
基本上这循环遍历行然后列。问题出在 If
语句和索引 i
中。在此 If
语句中,您检查这是否是第一次获得 headers。如果这是第一次,请将 header 写入 excel 并继续。这将跳过第一行数据,因为循环变量 i
用作 DataGridView 行的索引,赋值:
worksheet.Cells(cellRowIndex, cellColumnIndex) = DataGridView1.Rows(i).Cells(j).Value
当第一次进入 j
循环时 i
是零 (0)。使用 cellRowIndex
进行检查以确定是否需要输出 header。在这种情况下,他们会……输出 header 然后退出此 if
并循环回到下一个 header。当所有 header 都输出时,您退出 j
循环并循环回到 i
循环。这会将 i
递增到 1 并进入 j
循环……因为当 header 输出时 i
已经为 0,我们将 skip/miss 行 0 in DataGridView
。我希望这是有道理的。
一个简单的解决方案是简单地从 i
at -1 开始:
For i As Integer = -1 To DataGridView1.Rows.Count - 2
这将解决您遇到的问题,但是代码并不容易理解。我建议使用 foreach
循环遍历 DataGridView
行并将列输出与行输出分开。这确实创建了两个循环,但第一个循环只会循环一次以添加 headers。下一个循环遍历所有行。这将使索引在将来更易于处理和阅读。
For Each column In DataGridView1.Columns
worksheet.Cells(1, column.Index + 1).Value = column.Name
Next
Dim rowIndex = 2
For Each row As DataGridViewRow In DataGridView1.Rows
If Not row.IsNewRow Then
For colIndex As Integer = 0 To DataGridView1.Columns.Count - 1
worksheet.Cells(rowIndex, colIndex + 1).Value = row.Cells(colIndex).Value.ToString
Next
End If
rowIndex += 1
Next
希望这对您有所帮助。