关键词:
【中文标题】在 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=>s.SheetId.Value)
比调用 .Select(s=>s.SheetId.Value).Max()
更干净。同样,您不需要List<String> columns
,因为DataRow
有一个DataColumn
索引器;第二个foreach
也可以迭代table.Columns
。
哦,好吧,我猜这只是为了教育目的:) 谢谢
我自己想通了。要完成这项工作,有必要向项目添加WindowsBase
和DocumentFormat.OpenXml
引用。 SpreadsheetDocument
和 WorksheetPart
也在 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
它非常容易使用。
只需将您要写入的文件名和DataTable
、DataSet
或List<>
传递给它。
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
【讨论】:
如何从 Word 文档中复制富文本内容控件的内容并使用 Open XML SDK 删除控件本身
】如何从Word文档中复制富文本内容控件的内容并使用OpenXMLSDK删除控件本身【英文标题】:HowtocopycontentofRichTextContentControlfromWorddocumentandremovethecontrolitselfusingOpenXMLSDK【发布时间】:2021-04-2716:58:08【问题描述】:我正在尝试将富文... 查看详情
如何使用 c# 在 Open Office Calc 表中插入超过 256 列?
】如何使用c#在OpenOfficeCalc表中插入超过256列?【英文标题】:Howtoinsertmorethan256columnsinaOpenOfficeCalcsheetusingc#?【发布时间】:2010-03-1112:22:25【问题描述】:嗨!朋友我的表格包含457列,我需要将此表格数据导出到OpenOfficeCalc电子表... 查看详情
在 C# 中,如何使用大量精美的标记将 POCO 序列化为 XML?
】在C#中,如何使用大量精美的标记将POCO序列化为XML?【英文标题】:InC#,howcanIserializeaPOCOtoXMLwithalotoffancymarkup?【发布时间】:2021-11-1500:41:55【问题描述】:要使用SOAP服务,我需要以XML格式发送消息,如下所示:<soap:Envelopexmln... 查看详情
如何在 C# 中使用添加的自定义标签将 JSON 转换为 XML
】如何在C#中使用添加的自定义标签将JSON转换为XML【英文标题】:HowtoconvertJSONtoXMLwithaddedcustomtaginC#【发布时间】:2021-11-1010:40:13【问题描述】:我有一些这种格式的JSON示例:"id":"532-513jg-5ujkl-5jiklf","externalGuid":"93804jlkfes","tagNumber"... 查看详情
如何在 C# 控制台应用程序中使用 XmlTextReader 将 XML 数据插入 SQL Server 表?
】如何在C#控制台应用程序中使用XmlTextReader将XML数据插入SQLServer表?【英文标题】:HowtoinsertXMLdataintoSQLServertableusingXmlTextReaderinC#consoleapp?【发布时间】:2018-12-2023:50:50【问题描述】:我有一个4GB的XML文件。我必须将它的一些值插... 查看详情
使用 C# 在 XML 文件中选择节点属性
】使用C#在XML文件中选择节点属性【英文标题】:SelectnodesattributeinXMLfileusingC#【发布时间】:2014-02-1210:07:34【问题描述】:在以下XML文件中,我尝试将所有id属性保存在一个列表中:<?xmlversion="1.0"?><PressReleases><PressReleas... 查看详情
在 C# 桌面应用程序中使用 Open*** 实现拆分和隧道
】在C#桌面应用程序中使用Open***实现拆分和隧道【英文标题】:ImplementSplitandTunnelingusingOpen***inC#desktopapplication【发布时间】:2021-10-2603:54:14【问题描述】:我创建了使用Open***Community连接到***服务器的应用程序,它工作正常并且... 查看详情
我应该在哪里使用 C# 调用方法 connection.Open()?
】我应该在哪里使用C#调用方法connection.Open()?【英文标题】:WhereamIsupposedtocallthemethodconnection.Open()usingC#?【发布时间】:2014-02-0919:02:46【问题描述】:您好,我正在尝试从文本框中显示的数据库中获取数据。为此,我创建了三个... 查看详情
有没有办法在 python 中运行 C# 的不和谐 SDK 代码?
...0-09-1815:40:56【问题描述】:我试图在我的python应用程序上使用discordSDK,唯一的非统一和非虚幻方法是使用C#我完全不知道如何用C#编写代码,但Discord说我只需要一行代码我尝试将我的应用程序转换为C#,但C#不支持pyth 查看详情
使用 C# 将 xml 反序列化为超类对象
】使用C#将xml反序列化为超类对象【英文标题】:DeserializexmlintosuperclassobjectwithC#【发布时间】:2013-06-2123:20:41【问题描述】:我正在创建一个程序,允许用户使用4种基本操作定义公式:使用XML的加法、减法、除法、乘法。举个... 查看详情
在c#中保存xml文件
】在c#中保存xml文件【英文标题】:Savexmlfileinc#【发布时间】:2014-06-0121:43:02【问题描述】:我有一个程序,它将接受名称和分数,它将分数与位于xml文件中的记分板进行比较,然后将其从最高到最低排序。它一直有效,直到我... 查看详情
在 C# 中使用设置类
】在C#中使用设置类【英文标题】:UsingSettingsClassinC#【发布时间】:2012-11-2408:36:00【问题描述】:我正在使用Properties.Settings类来保存应用程序设置。我想知道,一旦我在客户端系统中部署,设置是否会在应用程序重启和系统重... 查看详情
在 C# 中使用 XML 文字?
】在C#中使用XML文字?【英文标题】:UseXMLLiteralsinC#?【发布时间】:2021-05-2210:37:27【问题描述】:是否可以在C#代码文件中添加文字XML数据?我目前正在使用多行字符串文字,但如您所见,它变得混乱。有更好的方法吗?stringXML=... 查看详情
为 AWS C# S3 SDK 使用内存流而不是文件流而不将完整文件写入 S3
】为AWSC#S3SDK使用内存流而不是文件流而不将完整文件写入S3【英文标题】:UsingmemorystreaminsteadoffilestreamforAWSC#S3SDKnotwritingfullfiletoS3【发布时间】:2021-12-2814:58:19【问题描述】:我有一些用于在AWSS3存储桶上创建文件的代码。当我... 查看详情
在 C# 中安全地解析 XML
...变的,并且在完成处理后我无法擦除这些值。我目前正在使用System.XML.XmlReader将值解析为字符串(参见下面的代码)。在不让我的代 查看详情
如何将datagridview导出到Open Office Excel c#
...dview导出到OpenOfficeExcel。我不知道在我的OpenOffice项目中要使用哪些 查看详情
将 XML 转换为动态 C# 对象
...amicC#object【发布时间】:2012-10-2117:06:25【问题描述】:我使用以下C#代码通过JSON.Net框架将JSON数据字符串转换为动态对象://Createsadynamic.NetobjectrepresentingtheJSONdatavarProductDB=JsonConvert.DeserializeObject<d 查看详情
在 C# 中使用 Xmldocument 修改 xml
】在C#中使用Xmldocument修改xml【英文标题】:ModifyxmlwithXmldocumentinC#【发布时间】:2021-11-2822:27:24【问题描述】:我正在尝试按照此处HowtomodifyexistingXMLfilewithXmlDocumentandXmlNodeinC#的另一篇文章中的说明编辑xml文档的值。这是我的代码... 查看详情