C# 如何加快将数据表转储到Excel工作表的速度?
我有以下例程将数据表转储到Excel工作表中C# 如何加快将数据表转储到Excel工作表的速度?,c#,performance,excel,interop,.net-2.0,C#,Performance,Excel,Interop,.net 2.0,我有以下例程将数据表转储到Excel工作表中 private void RenderDataTableOnXlSheet(DataTable dt, Excel.Worksheet xlWk, string [] columnNames, string [] fieldNames) { // render the column names (e.g. headers) for
private void RenderDataTableOnXlSheet(DataTable dt, Excel.Worksheet xlWk,
string [] columnNames, string [] fieldNames)
{
// render the column names (e.g. headers)
for (int i = 0; i < columnNames.Length; i++)
xlWk.Cells[1, i + 1] = columnNames[i];
// render the data
for (int i = 0; i < fieldNames.Length; i++)
{
for (int j = 0; j < dt.Rows.Count; j++)
{
xlWk.Cells[j + 2, i + 1] = dt.Rows[j][fieldNames[i]].ToString();
}
}
}
private void RenderDataTableOnXlSheet(DataTable dt、Excel.Workbench xlWk、,
字符串[]列名称,字符串[]字段名称)
{
//呈现列名(例如标题)
for(int i=0;i
不管出于什么原因,在我相对现代的PC上转储25列400行的数据表大约需要10-15秒。测试人员的机器需要更长的时间
我能做些什么来加速这个代码吗?或者互操作本身就是很慢的
解决方案:根据Helen Toomik的建议,我已经修改了该方法,它现在可以用于几种常见的数据类型(int32、double、datetime、string)。请随意扩展它。处理我的数据集的速度从15秒下降到1秒以下
private void RenderDataTableOnXlSheet(DataTable dt, Excel.Worksheet xlWk, string [] columnNames, string [] fieldNames)
{
Excel.Range rngExcel = null;
Excel.Range headerRange = null;
try
{
// render the column names (e.g. headers)
for (int i = 0; i < columnNames.Length; i++)
xlWk.Cells[1, i + 1] = columnNames[i];
// for each column, create an array and set the array
// to the excel range for that column.
for (int i = 0; i < fieldNames.Length; i++)
{
string[,] clnDataString = new string[dt.Rows.Count, 1];
int[,] clnDataInt = new int[dt.Rows.Count, 1];
double[,] clnDataDouble = new double[dt.Rows.Count, 1];
string columnLetter = char.ConvertFromUtf32("A".ToCharArray()[0] + i);
rngExcel = xlWk.get_Range(columnLetter + "2", Missing.Value);
rngExcel = rngExcel.get_Resize(dt.Rows.Count, 1);
string dataTypeName = dt.Columns[fieldNames[i]].DataType.Name;
for (int j = 0; j < dt.Rows.Count; j++)
{
if (fieldNames[i].Length > 0)
{
switch (dataTypeName)
{
case "Int32":
clnDataInt[j, 0] = Convert.ToInt32(dt.Rows[j][fieldNames[i]]);
break;
case "Double":
clnDataDouble[j, 0] = Convert.ToDouble(dt.Rows[j][fieldNames[i]]);
break;
case "DateTime":
if (fieldNames[i].ToLower().Contains("time"))
clnDataString[j, 0] = Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToShortTimeString();
else if (fieldNames[i].ToLower().Contains("date"))
clnDataString[j, 0] = Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToShortDateString();
else
clnDataString[j, 0] = Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToString();
break;
default:
clnDataString[j, 0] = dt.Rows[j][fieldNames[i]].ToString();
break;
}
}
else
clnDataString[j, 0] = string.Empty;
}
// set values in the sheet wholesale.
if (dataTypeName == "Int32")
rngExcel.set_Value(Missing.Value, clnDataInt);
else if (dataTypeName == "Double")
rngExcel.set_Value(Missing.Value, clnDataDouble);
else
rngExcel.set_Value(Missing.Value, clnDataString);
}
// figure out the letter of the last column (supports 1 letter column names)
string lastColumn = char.ConvertFromUtf32("A".ToCharArray()[0] + columnNames.Length - 1);
// make the header range bold
headerRange = xlWk.get_Range("A1", lastColumn + "1");
headerRange.Font.Bold = true;
// autofit for better view
xlWk.Columns.AutoFit();
}
finally
{
ReleaseObject(headerRange);
ReleaseObject(rngExcel);
}
}
private void ReleaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch
{
obj = null;
}
finally
{
GC.Collect();
}
}
private void RenderDataTableOnXlSheet(DataTable dt、Excel.Workbench xlWk、string[]列名、string[]字段名)
{
Excel.Range rngExcel=null;
Excel.Range headerRange=null;
尝试
{
//呈现列名(例如标题)
for(int i=0;i0)
{
开关(dataTypeName)
{
案例“Int32”:
clndaint[j,0]=将.Convert.ToInt32(dt.Rows[j][fieldNames[i]]);
打破
“双重”情况:
clndadouble[j,0]=Convert.ToDouble(dt.Rows[j][fieldNames[i]];
打破
案例“日期时间”:
if(fieldNames[i].ToLower().Contains(“time”))
clnDataString[j,0]=Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToShortTimeString();
else if(fieldNames[i].ToLower().Contains(“日期”))
clnDataString[j,0]=Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToShortDateString();
其他的
clnDataString[j,0]=Convert.ToDateTime(dt.Rows[j][fieldNames[i]]).ToString();
打破
违约:
CLN字符串[j,0]=dt.Rows[j][fieldNames[i]].ToString();
打破
}
}
其他的
CLN字符串[j,0]=string.Empty;
}
//在图纸中设置值。
如果(dataTypeName==“Int32”)
rngExcel.set_值(缺少.Value,CLN绘制);
else if(dataTypeName==“Double”)
rngExcel.set_值(缺少.Value,CLNDADOUBLE);
其他的
rngExcel.set_值(缺少.Value,CLNDASTRING);
}
//计算最后一列的字母(支持1个字母的列名)
字符串lastColumn=char.ConvertFromUtf32(“A”.tocharray()[0]+columnNames.Length-1);
//使标题范围加粗
headerrage=xlWk.get_范围(“A1”,最后一列+“1”);
headerrage.Font.Bold=true;
//自动调整以获得更好的视图
xlWk.Columns.AutoFit();
}
最后
{
释放对象(headerRange);
释放对象(rngExcel);
}
}
私有无效释放对象(对象obj)
{
尝试
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj=null;
}
抓住
{
obj=null;
}
最后
{
GC.Collect();
}
}
互操作本质上非常缓慢。
每次呼叫都会带来很大的开销。
要加快速度,请尝试在一条赋值语句中将数据的对象数组写回一个单元格区域
或者,如果这是一个严重的问题,请尝试使用托管代码Excel扩展之一,该扩展可以通过XLL接口使用托管代码读/写数据。(Addin Express、Managed XLL等)我同意Charles的观点。互操作真的很慢。但是试试这个:
private void RenderDataTableOnXlSheet(DataTable dt, Excel.Worksheet xlWk,
string [] columnNames, string [] fieldNames)
{
// render the column names (e.g. headers)
int columnLength = columnNames.Length;
for (int i = 0; i < columnLength; i++)
xlWk.Cells[1, i + 1] = columnNames[i];
// render the data
int fieldLength = fieldNames.Length;
int rowCount = dt.Rows.Count;
for (int j = 0; j < rowCount; j++)
{
for (int i = 0; i < fieldLength; i++)
{
xlWk.Cells[j + 2, i + 1] = dt.Rows[j][fieldNames[i]].ToString();
}
}
}
private void RenderDataTableOnXlSheet(DataTable dt、Excel.Workbench xlWk、,
字符串[]列名称,字符串[]字段名称)
{
//呈现列名(例如标题)
int columnLength=columnNames.Length;
for(int i=0;iusing ADODB;
using Microsoft.Office.Interop;
//--- datatable --- already exists
DataTable dt_data = new DataTable();
//--- or your dt code is here ..........
//--- mine has 3 columns ------
//--- code to populate ADO rs with DataTable data --- nothing special
//--- create empty rs .....
ADODB.Recordset rs = new ADODB.Recordset();
rs.CursorType = CursorTypeEnum.adOpenKeyset;
rs.CursorLocation = CursorLocationEnum.adUseClient;
rs.LockType = LockTypeEnum.adLockOptimistic;
rs.Fields.Append("employee_id",DataTypeEnum.adBSTR,255,FieldAttributeEnum.adFldIsNullable);
rs.Fields.Append("full_name", DataTypeEnum.adBSTR, 255, FieldAttributeEnum.adFldIsNullable);
rs.Fields.Append("start_date", DataTypeEnum.adBSTR, 10, FieldAttributeEnum.adFldIsNullable);
rs.Open();
//--- populate ADO rs with DataTable data ----
for (int i = 0; i < dt_data.Rows.Count; i++)
{
rs.AddNew();
rs.Fields["employee_id"].Value = dt_data.Rows[i]["employee_id"].ToString();
rs.Fields["full_name"].Value = dt_data.Rows[i]["full_name"].ToString();
//--- if date is empty......
if (dt_data.Rows[i]["start_date"].ToString().Length > 0)
{
rs.Fields["start_date"].Value = dt_data.Rows[i]["start_date"].ToString();
}
rs.Update();
}
Microsoft.Office.Interop.Excel.Application xlexcel;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlexcel = new Microsoft.Office.Interop.Excel.Application();
xlexcel.Visible = true;
xlWorkBook = xlexcel.Workbooks.Add(misValue);
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
//--- populate columns from rs --
for (int i = 0; i < rs.Fields.Count; i++)
{
xlWorkSheet.Cells[1, i + 1] = rs.Fields[i].Name.ToString();
};
//----- .CopyFromRecordset method -- (rs object, MaxRows, MaxColumns) --- in this case 3 columns but it can 1,2,3 etc ------
xlWorkSheet.Cells[2, 1].CopyFromRecordset(CloneFilteredRecordset(rs), rs.RecordCount, 3);