将DataTable转换为CSV的最有效方法

时间:2015-02-13 15:51:29

标签: c# performance csv datatable

我正在使用DataTable,我需要将它们转换为CSV文件格式。我正在使用的大多数表都有超过50,000条记录,所以我试图最小化转换它们所需的时间。

这是我目前的方法:

    public static string table_to_csv(DataTable table)
    {
        string file = "";

        foreach (DataColumn col in table.Columns)
            file = string.Concat(file, col.ColumnName, ",");

        file = file.Remove(file.LastIndexOf(','), 1);
        file = string.Concat(file, "\r\n");

        foreach (DataRow row in table.Rows)
        {
            foreach (object item in row.ItemArray)
                file = string.Concat(file, item.ToString(), ",");

            file = file.Remove(file.LastIndexOf(','), 1);
            file = string.Concat(file, "\r\n");
        }

        return file;
    }

有什么办法可以提高这种方法的效率吗?我欢迎您提出任何修改和想法!

3 个答案:

答案 0 :(得分:19)

是的,使用System.Text.StringBuilder表示大字符串。我实现了这个:

public static string DataTableToCSV(this DataTable datatable, char seperator)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < datatable.Columns.Count; i++)
    {
        sb.Append(datatable.Columns[i]);
        if (i < datatable.Columns.Count - 1)
            sb.Append(seperator);
    }
    sb.AppendLine();
    foreach (DataRow dr in datatable.Rows)
    {
        for (int i = 0; i < datatable.Columns.Count; i++)
        {
            sb.Append(dr[i].ToString());

            if (i < datatable.Columns.Count - 1)
                sb.Append(seperator);
        }
        sb.AppendLine();
    }
    return sb.ToString();
}

答案 1 :(得分:7)

这是我在Utility类中使用的方法。适合我正在做的事情。

 public static void GenerateCSV(DataTable dt)
    {  
        StringBuilder sb = new StringBuilder();
        try
        {
            int count = 1;
            int totalColumns = dt.Columns.Count;
            foreach (DataColumn dr in dt.Columns)
            {
                sb.Append(dr.ColumnName);

                if (count != totalColumns)
                {
                    sb.Append(",");
                }

                count++;
            }

            sb.AppendLine();

            string value = String.Empty;
            foreach (DataRow dr in dt.Rows)
            {
                for (int x = 0; x < totalColumns; x++)
                {
                    value = dr[x].ToString();

                    if (value.Contains(",") || value.Contains("\""))
                    {
                        value = '"' + value.Replace("\"", "\"\"") + '"';
                    }

                    sb.Append(value);

                    if (x != (totalColumns - 1))
                    {
                        sb.Append(",");
                    }
                }

                sb.AppendLine();
            }
        }
        catch (Exception ex)
        {
            // Do something
        }
    }

答案 2 :(得分:2)

我使用过这种方法,它将对象数组复制到Excel单元格区域,而不是逐行复制,然后逐列复制。事实证明这是非常有效的方式

    public void ExportToExcel(DataTable dataTable, String pathToSave)
    {
        // Create the Excel Application object
        var excelApp = new ApplicationClass();

        // Create a new Excel Workbook
        Workbook excelWorkbook = excelApp.Workbooks.Add(Type.Missing);

        int sheetIndex = 0;

        // Copy the DataTable to an object array
        var rawData = new object[dataTable.Rows.Count + 1, dataTable.Columns.Count];

        // Copy the column names to the first row of the object array
        for (var col = 0; col < dataTable.Columns.Count; col++)
        {
            rawData[0, col] = dataTable.Columns[col].ColumnName;
        }

        // Copy the values to the object array
        for (var col = 0; col < dataTable.Columns.Count; col++)
        {
            for (int row = 0; row < dataTable.Rows.Count; row++)
            {
                rawData[row + 1, col] = dataTable.Rows[row].ItemArray[col];
            }
        }

        // Calculate the final column letter
        string finalColLetter = string.Empty;
        const string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        int colCharsetLen = colCharset.Length;

        if (dataTable.Columns.Count > colCharsetLen)
        {
            finalColLetter = colCharset.Substring(
                (dataTable.Columns.Count - 1) / colCharsetLen - 1, 1);
        }

        finalColLetter += colCharset.Substring((dataTable.Columns.Count - 1) % colCharsetLen, 1);

        // Create a new Sheet
        var excelSheet = (Worksheet)excelWorkbook.Sheets.Add(excelWorkbook.Sheets.Item[++sheetIndex], Type.Missing, 1, XlSheetType.xlWorksheet);
        excelSheet.Name = dataTable.TableName;

        // Fast data export to Excel
        var excelRange = string.Format("A1:{0}{1}", finalColLetter, dataTable.Rows.Count + 1);
        excelSheet.Range[excelRange, Type.Missing].Value2 = rawData;

        // Mark the first row as BOLD and BLUE
        var headerColumnRange = (Range)excelSheet.Rows[1, Type.Missing];
        headerColumnRange.Font.Bold = true;
        headerColumnRange.Font.Color = 0xFF0000;
        headerColumnRange.EntireColumn.AutoFit();

        // Save and Close the Workbook
        excelWorkbook.SaveAs(pathToSave, XlFileFormat.xlWorkbookNormal, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlExclusive,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        excelWorkbook.Close(true, Type.Missing, Type.Missing);
        excelWorkbook = null;

        // Release the Application object
        excelApp.Quit();
        excelApp = null;

        // Collect the unreferenced objects
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }