Wie zu beschleunigen dumping eine DataTable in ein Excel-Arbeitsblatt?

Habe ich die folgende routine, die dumps einer DataTable ein Excel-Arbeitsblatt.

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

Aus welchem Grund auch immer, dumping DataTable mit 25 Spalten und 400 Zeilen dauert etwa 10-15 Sekunden auf meinem relativ modernen PC. Noch länger dauert Tester " Maschinen.

Gibt es irgendetwas, was ich tun kann, um die Geschwindigkeit dieser code? Oder ist interop einfach von Natur aus langsame?

LÖSUNG: Basierend auf Anregungen von Helen Toomik, ich habe Sie geändert, die Methode und es sollte jetzt funktionieren für verschiedene gängige Datentypen wie int32, double, datetime, string). Fühlen Sie sich frei, um es zu erweitern. Die Geschwindigkeit für die Verarbeitung meiner dataset ging von 15 Sekunden der unter 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();
        }
    }
Ich weiß, Sie haben bereits eine Antwort, aber ich wollte den link zu der Bibliothek, die ich erwähnt in meinem Beitrag. Ich aktualisiert die post mit dem link. npoi.codeplex.com
Danke. Sieht interessant aus.
Das ist sehr gut. Das einzige, was ich empfehlen würde, ist der Typ-Vergleich Sachen außerhalb der for-Schleife für die Zeilen. Es würde bedeuten, man müsste eine Schleife für jeden geben, aber dann müssen Sie nicht haben, um zu vergleichen-Typen für jede Zeile. Aber so oder so, sehr hilfreich.

InformationsquelleAutor AngryHacker | 2010-04-22

Schreibe einen Kommentar