c#怎么将datatable数据保存到excel中

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#怎么将datatable数据保存到excel中相关的知识,希望对你有一定的参考价值。

参考技术A

采用第三方类库工具是一种可快速导出数据的方法,如下spire.xla for .net的导出方法:

//创建一个workbook对象,默认创建03版的Excel

Workbook workbook = new Workbook();

 

//指定版本信息,07及以上版本最多可以插入1048576行数据

workbook.Version = ExcelVersion.Version2013;

 

//获取第一张sheet

Worksheet sheet = workbook.Worksheets[0];

 

//得到在datatable里的数据

DataTable dt = GetDataTable();

 

//从第一行第一列开始插入数据,true代表数据包含列名

sheet.InsertDataTable(dt, true, 1, 1);

 

//保存文件

workbook.SaveToFile("ExportDataToExcel.xlsx",ExcelVersion.Version2013);

代码整理参考自原文。

在 c# 中使用 Open Xml SDK 将 DataTable 导出到 Excel

【中文标题】在 c# 中使用 Open Xml SDK 将 DataTable 导出到 Excel【英文标题】:Export DataTable to Excel with Open Xml SDK in c# 【发布时间】:2012-08-04 18:42:59 【问题描述】:

我的程序能够将一些数据和 DataTable 导出到 Excel 文件(模板) 在模板中,我将数据插入到一些占位符中。它工作得很好,但我也需要插入一个 DataTable ...... 我的示例代码:

using (Stream OutStream = new MemoryStream())

    // read teamplate
    using (var fileStream = File.OpenRead(templatePath))
        fileStream.CopyTo(OutStream);

    // exporting
    Exporting(OutStream);
         
    // to start
    OutStream.Seek(0L, SeekOrigin.Begin);
            
    // out
    using (var resultFile = File.Create(resultPath))
        OutStream.CopyTo(resultFile);

下一个导出方法

private void Exporting(Stream template)

    using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings                           AutoSave = true ))
    
        // Replace shared strings
        SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
        IEnumerable<Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<Text>();
           
        DoReplace(sharedStringTextElements);
        // Replace inline strings
        IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
          
        foreach (var worksheet in worksheetParts)
        
            DoReplace(worksheet.Worksheet.Descendants<Text>());
        

        int z = 40;
        foreach (System.Data.DataRow row in ExcelWorkXLSX.ToOut.Rows)
        
            for (int i = 0; i < row.ItemArray.Count(); i++)
             
                ExcelWorkXLSX.InsertText(workbook, row.ItemArray.ElementAt(i).ToString(), getColumnName(i), Convert.ToUInt32(z)); 
                z++;
            
         
        
    

但是这个片段输出DataTable slooooooooooooooooooooowwwwwww...

如何快速、真实地将 DataTable 导出到 Excel?

【问题讨论】:

需要使用open xml sdk吗? 嗯...不,但打开 xml sdk 快速读/写 excel 文件。在我的程序中,我读取 xlsx 文件,将数据抓取到 datagridview(使用 DataTable),重新检查数据。首先我使用互操作,但它需要excel并且非常慢。我的问题只是出口。但是,我现在不想重写很多代码:) 【参考方案1】:

我写了这个简单的例子。这个对我有用。我只用一个数据集测试了它,里面有一张表,但我想这对你来说可能就足够了。

考虑到我将所有单元格视为字符串(甚至不是 SharedStrings)。如果您想使用 SharedStrings,您可能需要稍微调整一下我的示例。

编辑:要完成这项工作,需要将 WindowsBase 和 DocumentFormat.OpenXml 引用添加到项目中。

享受,

private void ExportDataSet(DataSet ds, string destination)
        
            using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
            
                var workbookPart = workbook.AddWorkbookPart();

                workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();

                workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();

                foreach (System.Data.DataTable table in ds.Tables) 

                    var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
                    var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
                    sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);

                    DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
                    string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);

                    uint sheetId = 1;
                    if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
                    
                        sheetId =
                            sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
                    

                    DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet()  Id = relationshipId, SheetId = sheetId, Name = table.TableName ;
                    sheets.Append(sheet);

                    DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();

                    List<String> columns = new List<string>();
                    foreach (System.Data.DataColumn column in table.Columns) 
                        columns.Add(column.ColumnName);

                        DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                        cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                        cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
                        headerRow.AppendChild(cell);
                    


                    sheetData.AppendChild(headerRow);

                    foreach (System.Data.DataRow dsrow in table.Rows)
                    
                        DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
                        foreach (String col in columns)
                        
                            DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                            cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                            cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
                            newRow.AppendChild(cell);
                        

                        sheetData.AppendChild(newRow);
                    

                
            
        

【讨论】:

我认为 workbook.WorkbookPart.Workbook = new...workbook.WorkbookPart.Workbook.Sheets = new 应该移到 foreach 循环之外。否则,循环的每次迭代都会替换工作表,导致 excel 文件仅包含最终的 DataTable @Brian ,感谢您指出这一点。它最初是有效的,因为我只用一张桌子进行了测试。我刚刚修好了,现在还好吗? 是的,看起来不错。顺便说一句,调用 .Max(s=&gt;s.SheetId.Value) 比调用 .Select(s=&gt;s.SheetId.Value).Max() 更干净。同样,您不需要List&lt;String&gt; columns,因为DataRow 有一个DataColumn 索引器;第二个foreach 也可以迭代table.Columns 哦,好吧,我猜这只是为了教育目的:) 谢谢 我自己想通了。要完成这项工作,有必要向项目添加WindowsBaseDocumentFormat.OpenXml 引用。 SpreadsheetDocumentWorksheetPart 也在 DocumentFormat.OpenXml.Packaging 命名空间中【参考方案2】:

eburgos,我稍微修改了您的代码,因为当您的数据集中有多个数据表时,它只是在电子表格中覆盖它们,因此您在工作簿中只剩下一张工作表。我基本上只是将创建工作簿的部分移出循环。这是更新后的代码。

private void ExportDSToExcel(DataSet ds, string destination)

    using (var workbook = SpreadsheetDocument.Create(destination, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
    
        var workbookPart = workbook.AddWorkbookPart();
        workbook.WorkbookPart.Workbook = new DocumentFormat.OpenXml.Spreadsheet.Workbook();
        workbook.WorkbookPart.Workbook.Sheets = new DocumentFormat.OpenXml.Spreadsheet.Sheets();

        uint sheetId = 1;

        foreach (DataTable table in ds.Tables)
        
            var sheetPart = workbook.WorkbookPart.AddNewPart<WorksheetPart>();
            var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
            sheetPart.Worksheet = new DocumentFormat.OpenXml.Spreadsheet.Worksheet(sheetData);                

            DocumentFormat.OpenXml.Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Sheets>();
            string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);

            if (sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Count() > 0)
            
                sheetId =
                    sheets.Elements<DocumentFormat.OpenXml.Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
            

            DocumentFormat.OpenXml.Spreadsheet.Sheet sheet = new DocumentFormat.OpenXml.Spreadsheet.Sheet()  Id = relationshipId, SheetId = sheetId, Name = table.TableName ;
            sheets.Append(sheet);

            DocumentFormat.OpenXml.Spreadsheet.Row headerRow = new DocumentFormat.OpenXml.Spreadsheet.Row();

            List<String> columns = new List<string>();
            foreach (DataColumn column in table.Columns)
            
                columns.Add(column.ColumnName);

                DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(column.ColumnName);
                headerRow.AppendChild(cell);
            

            sheetData.AppendChild(headerRow);

            foreach (DataRow dsrow in table.Rows)
            
                DocumentFormat.OpenXml.Spreadsheet.Row newRow = new DocumentFormat.OpenXml.Spreadsheet.Row();
                foreach (String col in columns)
                
                    DocumentFormat.OpenXml.Spreadsheet.Cell cell = new DocumentFormat.OpenXml.Spreadsheet.Cell();
                    cell.DataType = DocumentFormat.OpenXml.Spreadsheet.CellValues.String;
                    cell.CellValue = new DocumentFormat.OpenXml.Spreadsheet.CellValue(dsrow[col].ToString()); //
                    newRow.AppendChild(cell);
                

                sheetData.AppendChild(newRow);
            
        
    

【讨论】:

谢谢,刚刚看到布赖恩的评论,我也做了同样的事情。【参考方案3】:

我还写了一个 C#/VB.Net “导出到 Excel” 库,它使用 OpenXML 并且(更重要的是)也使用 OpenXmlWriter,因此在编写大文件时不会耗尽内存。

完整的源代码和演示可以在这里下载:

Export to Excel

它非常容易使用。 只需将您要写入的文件名和DataTableDataSetList&lt;&gt; 传递给它。

CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx");

如果您从 ASP.Net 应用程序调用它,请将 HttpResponse 传递给它以将文件写入。

CreateExcelFile.CreateExcelDocument(myDataSet, "MyFilename.xlsx", Response);

【讨论】:

对不起...!它现在又活过来了。 @MikeGledhill 是否有任何异步解决方法?尝试写入大文件时出现内存不足异常,我已经阅读了所有相关帖子,似乎它仅限于可用内存? @Afr0:不应该这样。我的库使用 OpenXmlWriter 来写出数据,而不是先尝试在内存中构建整个 Excel 文件。如果可能,请通过我的网站给我发电子邮件,我会看看是否可以提供帮助。 可能我得到的代码库的编写方式不太清楚。【参考方案4】:

我编写了自己的导出到 Excel 编写器,因为没有其他东西完全满足我的需求。它速度很快,并允许对单元格进行大量格式化。您可以在

查看它

https://openxmlexporttoexcel.codeplex.com/

希望对你有帮助。

【讨论】:

【参考方案5】:

您可以尝试看看这个库。我已将它用于我的一个项目,发现它非常易于使用、可靠且快速(我仅将其用于导出数据)。

http://epplus.codeplex.com/

【讨论】:

谢谢!这是一个想法!我会尝试仅用于出口。【参考方案6】:

你可以看看我的图书馆here。在文档部分下,您将找到如何导入数据表。

你只需要写

using (var doc = new SpreadsheetDocument(@"C:\OpenXmlPackaging.xlsx")) 
    Worksheet sheet1 = doc.Worksheets.Add("My Sheet");
    sheet1.ImportDataTable(ds.Tables[0], "A1", true);

希望对你有帮助!

【讨论】:

【参考方案7】:

我尝试了接受的答案,但在尝试打开时收到消息说生成的 excel 文件已损坏。我可以通过一些修改来修复它,比如在代码的行尾添加。

workbookPart.Workbook.Save();

我已经发布了完整代码@Export DataTable to Excel with Open XML in c#

【讨论】:

【参考方案8】:

我想添加这个答案,因为我使用了这个问题的主要答案作为我使用 OpenXML 从数据表导出到 Excel 的基础,但是当我发现它比上述方法快得多时转换到 OpenXMLWriter。

您可以在下面链接中的我的回答中找到完整的详细信息。不过我的代码是在 VB.NET 中的,所以你必须转换它。

How to export DataTable to Excel

【讨论】:

以上是关于c#怎么将datatable数据保存到excel中的主要内容,如果未能解决你的问题,请参考以下文章

c# winform 怎么查询datatable里面的数据

C#写ASP.NET,怎么导出一个DataTable到Excel

如何在.net 2.0中将数据从数据库或DataTable保存到Excel文件而没有响应

在 c# 中使用 Open Xml SDK 将 DataTable 导出到 Excel

c# 将Datatable数据导出到Excel表格中

C#将查询返回的数据(一行多列)怎么转换成一列多行dataTable?