如何从Excel工作簿内存流中获取Date Last Saved属性(C#)
获取XLSX流的最后保存日期并转换为DataTable
我之前也碰到过EPPlus的Workbook.Properties.Modified返回默认值的问题,其实XLSX本质是ZIP格式的OpenXML包,我们可以直接用OpenXML SDK从流里读取正确的最后保存日期,不用依赖EPPlus的属性封装,也完全不需要把文件存到磁盘。下面是具体的解决方案:
步骤1:安装OpenXML SDK NuGet包
首先需要安装官方的OpenXML处理库:
Install-Package DocumentFormat.OpenXml
步骤2:从流中读取正确的最后保存日期
直接操作MemoryStream打开OpenXML包,读取核心属性里的Modified字段——这就是Excel的"Date Last Saved"属性:
private DateTime? GetXlsxLastSavedDate(MemoryStream stream) { // 重置流的位置到开头,避免读取失败 stream.Position = 0; using (var package = DocumentFormat.OpenXml.Packaging.Package.Open(stream, FileMode.Open, FileAccess.Read)) { var corePropertiesPart = package.GetPartsOfType<DocumentFormat.OpenXml.Packaging.CoreFilePropertiesPart>().FirstOrDefault(); if (corePropertiesPart != null && corePropertiesPart.Properties != null) { return corePropertiesPart.Properties.Modified?.Value; } return null; } }
步骤3:整合到你的现有方法中
把这个日期读取逻辑和你原来的EPPlus转换逻辑结合,获取到正确日期后添加到DataTable的新列:
public DataTable Transform_closed_XML(byte[] dataBytesArray) { logger.LogInformation("XLSX Transform"); using (MemoryStream stream = new MemoryStream(dataBytesArray)) { // 先获取最后保存日期 DateTime? lastSavedDate = GetXlsxLastSavedDate(stream); // 重置流位置,避免后续EPPlus读取失败 stream.Position = 0; MemoryStream stream_xlsx = XLSXTransformerHelper.XLSX_Formatter(stream); var workBook = new XLWorkbook(stream_xlsx); var pubDate = workBook.Properties.Created; // 创建日期 // 处理日期为null的情况,用默认值兜底 DateTime finalLastSaved = lastSavedDate ?? DateTime.MinValue; // 读取工作表内容到DataTable(这里替换成你实际的内容读取逻辑) DataTable resultTable = workBook.Worksheets.First().AsDataTable(); // 添加最后保存日期列并赋值 resultTable.Columns.Add("Last Saved Date", typeof(DateTime)); foreach (DataRow row in resultTable.Rows) { row["Last Saved Date"] = finalLastSaved; } return resultTable; } }
关键说明
- 为什么EPPlus的属性不对?:EPPlus对OpenXML元数据的封装可能存在解析偏差,直接操作OpenXML包的核心属性部分是最可靠的方式——这是Excel存储"Date Last Saved"的标准位置。
- 流位置重置:每次读取流后一定要把
Position重置到0,否则后续EPPlus会从流的末尾开始读取,导致无法加载工作簿。 - 异常处理:你可以根据业务需求添加异常捕获(比如包损坏、属性不存在的情况),提升方法的健壮性。
内容的提问来源于stack exchange,提问作者Izzy888




