Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何加快将数据表转储到Excel工作表的速度?_C#_Performance_Excel_Interop_.net 2.0 - Fatal编程技术网

C# 如何加快将数据表转储到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

我有以下例程将数据表转储到Excel工作表中

    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);