使用 Office Interop 将单元格写入 Excel 的最快方法?

Posted

技术标签:

【中文标题】使用 Office Interop 将单元格写入 Excel 的最快方法?【英文标题】:Fastest way to write cells to Excel with Office Interop? 【发布时间】:2010-06-22 18:38:03 【问题描述】:

我正在编写一个函数来使用 VB .NET 中的 Office 互操作将数据导出到 Excel。我目前正在使用 Excel 工作表的 Cells() 方法直接编写单元格:

worksheet.Cells(rowIndex, colIndex) = data(rowIndex)(colIndex)

处理大量数据需要很长时间。有没有更快的方法一次将大量数据写入 Excel?使用范围做某事会更快吗?

【问题讨论】:

这个几乎重复的答案有很多:***.com/questions/3840270/…。 【参考方案1】:

如果可以,您应该避免逐个单元格地读写。使用数组并一次读取或写入整个块要快得多。不久前我在reading from worksheets using C# 上写了一篇文章;基本上,相同的代码以相反的方式工作(见下文),并且运行速度更快,尤其是对于更大的数据块。

  var sheet = (Worksheet)Application.ActiveSheet;
  var range = sheet.get_Range("A1", "B2");
  var data = new string[3,3];
  data[0, 0] = "A1";
  data[0, 1] = "B1";
  data[1, 0] = "A2";
  data[1, 1] = "B2";
  range.Value2 = data;

【讨论】:

我无法在您的博客上发表评论,所以让我在这里写下。您可以在 C# 中使用 CreateInstance 方法创建一个从 1 开始的数组: var arr = (object[,] ) Array.CreateInstance(typeof(object), new int[] 2, 3 , new int[] 1, 1 )【参考方案2】:

如果您还没有设置,请确保在开始输出数据之前设置Application.ScreenUpdating = false。这将使事情进展得更快。完成输出数据后,将其设置回 True。每次更改单元格时都必须重新绘制屏幕需要很长时间,绕过它可以节省时间。

至于使用范围,您仍然需要将 1(一个)特定单元格作为值的目标,因此我认为这里没有任何好处。在实际输出数据方面,我不知道这样做比你正在做的更快。

【讨论】:

【参考方案3】:

只是为了补充汤米的答案。

您可能还想在开始编写之前将计算设置为手动。

应用程序.计算 = xl计算手册

完成写作后,将其设置回自动。 (如果原始模式有可能不是自动模式,则必须在将其设置为手动之前存储该值)

应用程序.计算 = xlCalculationAutomatic

您也可以使用 Range 对象的 CopyFromRecordset 方法。

http://msdn.microsoft.com/de-de/library/microsoft.office.interop.excel.range.copyfromrecordset(office.11).aspx

【讨论】:

【参考方案4】:

从 excel 范围写入和读取值的最快方法是 Range.get_ValueRange.set_Value

方法如下:

Range filledRange = Worksheet.get_Range("A1:Z678",Missing);
object[,] rngval = (object[,]) filledRange.get_Value (XlRangeValueDataType.xlRangeValueDefault);

Range Destination = Worksheet2.get_Range("A1:Z678",Missing);
destination.set_Value(Missing,rngval);

是的,不需要迭代。性能简直了!!

希望对你有帮助!!

【讨论】:

【参考方案5】:

老实说,最快的编写方法是使用逗号分隔符。使用 Join(",").ToString 方法编写一行字段比尝试遍历单元格更容易。然后将文件另存为“.csv”。使用互操作,以 csv 格式打开文件,它会在打开时自动为您更新单元格。

【讨论】:

如果速度是你所追求的,那么这就是你要走的路,但是特别是在字符串和特殊字符方面存在一些问题【参考方案6】:

如果有人像我一样使用@Mathias 给出的方法(这似乎是加载到Excel 中最快的方法)和@IMil 对数组的建议来寻找完整的解决方案。 给你:

'dt (DataTable) is the already populated DataTable
'myExcelWorksheet (Worksheet) is the worksheet we are populating
'rowNum (Integer) is the row we want to start from (usually 1)
Dim misValue As Object = System.Reflection.Missing.Value
Dim arr As Object = DataTableToArray(dt)
'Char 65 is the letter "A"
Dim RangeTopLeft As String = Convert.ToChar(65 + 0).ToString() + rowNum.ToString()
Dim RangeBottomRight As String = Convert.ToChar(65 + dt.Columns.Count - 1).ToString() + (rowNum + dt.Rows.Count - 1).ToString()
Dim Range As String = RangeTopLeft + ":" + RangeBottomRight
myExcelWorksheet.Range(Range, misValue).NumberFormat = "@" 'Include this line to format all cells as type "Text" (optional step)
'Assign to the worksheet
myExcelWorksheet.Range(Range, misValue).Value2 = arr

然后

Function DataTableToArray(dt As DataTable) As Object
    Dim arr As Object = Array.CreateInstance(GetType(Object), New Integer() dt.Rows.Count, dt.Columns.Count)
    For nRow As Integer = 0 To dt.Rows.Count - 1
        For nCol As Integer = 0 To dt.Columns.Count - 1
            arr(nRow, nCol) = dt.Rows(nRow).Item(nCol).ToString()
        Next
    Next
    Return arr
End Function

限制包括只允许 26 列,然后才需要更好的代码来提供范围值字母。

【讨论】:

以上是关于使用 Office Interop 将单元格写入 Excel 的最快方法?的主要内容,如果未能解决你的问题,请参考以下文章

C# 导入图片到Excel单元格

在构建服务器上使用 Microsoft.Office.Interop dll 进行单元测试失败

范围内的单元格样式对齐

按键精灵如何把复制的数据写入到excel指定单元格中

用 DocumentFormat.OpenXml 和Microsoft.Office.Interop.Word 写入或者读取word文件

C#winform怎么导出一维码到EXCEL单元格?