You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core从Base64字符串生成Excel时如何保留原格式(含日期类型)

解决方案

核心思路:直接读取Excel单元格的显示文本而非原始值,同时优化大文件处理效率

1. 借助高效类库(推荐,无额外开发成本且性能可控)

使用EPPlus(适配xlsx)或NPOI(兼容xls/xlsx)这类成熟库,它们能直接获取单元格的显示文本,无需手动遍历做格式转换,且支持流式处理大文件:

EPPlus 示例(ASP.NET Core 6)

// 将Base64转为内存流
byte[] excelBytes = Convert.FromBase64String(base64String);
using var stream = new MemoryStream(excelBytes);
using var package = new ExcelPackage(stream);

var worksheet = package.Workbook.Worksheets.First();
var xmlBuilder = new StringBuilder();
xmlBuilder.Append("<Root>");

// 流式逐行读取,降低内存占用
for (int row = worksheet.Dimension.Start.Row; row <= worksheet.Dimension.End.Row; row++)
{
    xmlBuilder.Append("<Row>");
    for (int col = worksheet.Dimension.Start.Column; col <= worksheet.Dimension.End.Column; col++)
    {
        var cell = worksheet.Cells[row, col];
        // 直接获取单元格显示文本,与Excel界面一致
        string cellText = cell.Text;
        xmlBuilder.Append($"<Column>{SecurityElement.Escape(cellText)}</Column>");
    }
    xmlBuilder.Append("</Row>");
}
xmlBuilder.Append("</Root>");

string xmlData = xmlBuilder.ToString();
// 后续将xmlData存入数据库
  • 优势:cell.Text直接返回格式化后的文本,日期保留原始显示格式;流式读取避免大文件一次性加载,效率远高于全量遍历。
  • 注意:EPPlus 5+需商业授权,若需开源免费可选择NPOI。

NPOI 示例

byte[] excelBytes = Convert.FromBase64String(base64String);
using var stream = new MemoryStream(excelBytes);
IWorkbook workbook = WorkbookFactory.Create(stream);
var worksheet = workbook.GetSheetAt(0);

var xmlBuilder = new StringBuilder();
xmlBuilder.Append("<Root>");

// 用DataFormatter获取显示文本
var formatter = new DataFormatter();
for (int rowNum = worksheet.FirstRowNum; rowNum <= worksheet.LastRowNum; rowNum++)
{
    var row = worksheet.GetRow(rowNum);
    if (row == null) continue;
    xmlBuilder.Append("<Row>");
    for (int colNum = row.FirstCellNum; colNum < row.LastCellNum; colNum++)
    {
        var cell = row.GetCell(colNum);
        string cellText = formatter.FormatCellValue(cell);
        xmlBuilder.Append($"<Column>{SecurityElement.Escape(cellText)}</Column>");
    }
    xmlBuilder.Append("</Row>");
}
xmlBuilder.Append("</Root>");

string xmlData = xmlBuilder.ToString();
  • 优势:完全开源免费,DataFormatter.FormatCellValue()精准还原单元格显示格式,性能稳定。

2. 无类库方案(不推荐,开发成本高且性能难保障)

若必须不依赖第三方类库,可直接解析xlsx的底层ZIP结构:

  • xlsx本质是ZIP包,解压后读取xl/worksheets/sheet1.xml,其中<t>标签存储显示文本,<v>标签存储原始值,直接提取<t>内容即可。
  • 代码示例思路:
    byte[] excelBytes = Convert.FromBase64String(base64String);
    using var zipStream = new MemoryStream(excelBytes);
    using var archive = new ZipArchive(zipStream);
    var sheetEntry = archive.GetEntry("xl/worksheets/sheet1.xml");
    if (sheetEntry == null) throw new InvalidOperationException("工作表不存在");
    
    using var sheetStream = sheetEntry.Open();
    var doc = XDocument.Load(sheetStream);
    XNamespace ns = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
    var cells = doc.Descendants(ns + "c");
    
    var xmlBuilder = new StringBuilder("<Root><Row>");
    foreach (var cell in cells)
    {
        var tElement = cell.Element(ns + "t");
        string cellText = tElement?.Value ?? cell.Element(ns + "v")?.Value ?? string.Empty;
        xmlBuilder.Append($"<Column>{SecurityElement.Escape(cellText)}</Column>");
        // 需自行通过单元格r属性处理行分隔逻辑
    }
    xmlBuilder.Append("</Row></Root>");
    
  • 缺点:需自行处理命名空间、行号分割、合并单元格等复杂逻辑,大文件内存占用高,且无法解析xls二进制格式,维护成本极高。

关键注意事项

  • 禁止将Excel转为文本格式后读取,否则日期会变为序列号,丢失原始格式。
  • 大文件处理必须用流式逐行读取,避免一次性加载所有数据到内存,大幅提升效率。

内容的提问来源于stack exchange,提问作者BINULAL L B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:58:08