我使用标准的Microsoft.Office.Interop.Excel将1200 X 800矩阵(indexMatrix)导出到excel文件。该应用程序工作,只是它真的非常慢(即使对于100 x 100矩阵)。我还通过TextWriter导出文本文件,它几乎可以立即工作。有没有办法更快地导出到excel文件?
这是我的代码:
Excel.Application xlApp=new Excel.Application();
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
//xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
for (int i = 0; i < 800; i++) //h
for (int j = 0; j < 1200; j++)
xlWorkSheet.Cells[i+1,j+1] =indexMatrix[i][j];
xlWorkBook.SaveAs("C:\\a.xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
MessageBox.Show("Excel file created , you can find the file c:\\csharp-Excel.xls");
答案 0 :(得分:64)
您正在更新单个单元格。那将是非常缓慢的。如果您考虑一下,每次更新单元格时,RPC调用都将被编组到Excel进程。
如果您将二维数组值分配给单个语句中的相同维度的Excel范围(一个跨进程调用)而不是当前的1200 x 800,那么 会更快 = 960,000个跨进程调用。
类似的东西:
// Get dimensions of the 2-d array
int rowCount = indexMatrix.GetLength(0);
int columnCount = indexMatrix.GetLength(1);
// Get an Excel Range of the same dimensions
Excel.Range range = (Excel.Range) xlWorkSheet.Cells[1,1];
range = range.get_Resize(rowCount, columnCount);
// Assign the 2-d array to the Excel Range
range.set_Value(Excel.XlRangeValueDataType.xlRangeValueDefault, indexMatrix);
实际上,为了迂腐,上面的代码中有三个跨进程调用(.Cells,.get_Resize和.set_Value),并且在代码中每次迭代有两次调用(.Cells get和一个隐式的.set_Value )总计1200 x 800 x 2 = 1,920,000。
注意强>
首次撰写此帖子时,我正在使用的旧版Excel互操作库需要range.get_Resize
和range.set_Value
。现在,您可以使用@ The1nk评论中所述的range.Resize
和range.Value
。
答案 1 :(得分:15)
Excel互操作永远不会快。您基本上是远程控制Excel应用程序的实例。您可以通过创建CSV文件然后使用Excel互操作将其转换为.xls或.xlsx文件来获得更多成功
答案 2 :(得分:8)
我在阅读一个非常大的excel文件时遇到了类似的问题,使用interop需要花费2个多小时。
我尝试使用ClosedXml,这个过程不到10秒。 ClosedXml
// To loop
Sheet.Row(y).Cell(x).Value
另请注意,除非您安装了Excel,否则interop将无法在您的服务器上运行。 ClosedXml不需要安装excel。
答案 3 :(得分:5)
在写入任何数据之前关闭ScreenUpdating
,Application.ScreenUpdating = FALSE
然后在代码= TRUE
答案 4 :(得分:2)
使用Value2使其快速; 在填写数据之前显示excel
答案 5 :(得分:2)
ClosedXML 是一个奇迹,它更快更容易使用。
var workbook = new XLWorkbook();//create the new book
var worksheet = workbook.Worksheets.Add("Computer Install");// Add a sheet
worksheet.Cell(1,1).Value = "PC Name";// (Row, column) write to a cell
workbook.SaveAs(@"LIC documents.xlsx");// Save the book
使用nu Get软件包进行安装。 https://www.nuget.org/packages/ClosedXML
答案 6 :(得分:0)
有三种方法可以做到这一点,其中2种在其他人的答案中提到:
上述三种方法都非常快。我可以在大约6秒内写出大小为90000行和100列的数据。
P.S。然而,他们没有解决格式化边框,字体样式,颜色,单元格合并等数据的问题。
答案 7 :(得分:0)
对不起,我来晚了。我当时在做我的项目,我们不得不使用interop excel。而且我们的数据太大,使用interop excel花费了超过1分钟的时间。我们尝试了其他方法,即将datagridview的所有内容复制到剪贴板,使用interop excel打开excel工作表,然后将内容粘贴到excel。只需不到1秒的时间,即可完美导出我们的数据。
DataGridView转换为字符串:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = "";
foreach (DataGridViewRow row in dgProjeler.Rows)
{
for (int i = 0; i < row.Cells.Count; i++)
{
if (i == (row.Cells.Count - 1))
clipboard_string += row.Cells[i].Value + newline;
else
clipboard_string += row.Cells[i].Value + tab;
}
}
并将字符串复制到剪贴板
Clipboard.SetText(clipboard_string);
打开工作表,粘贴内容。
Excel.Application app = new Excel.Application();
app.Visible = true;
Excel.Workbook wb = app.Workbooks.Add(1);
Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];
// changing the name of active sheet
ws.Name = "Exported from gridview";
ws.Rows.HorizontalAlignment = HorizontalAlignment.Center;
app.ActiveWindow.Activate();
ws.Activate();
ws.Paste();
ws.Cells.EntireColumn.AutoFit();
它对我来说非常有效,我希望它能对仍然找不到解决方案的人有所帮助。