【问题标题】:MemoryStream is empty for an OpenXML Excel document对于 OpenXML Excel 文档,MemoryStream 为空
【发布时间】:2018-01-15 16:36:22
【问题描述】:

我通常会使用 ClosedXML 来生成 Excel 文件。一个核心项目迫使我只使用 OpenXML。

将下载生成的 Excel 文件。

我遇到了一个问题,即提供给 SpreadsheetDocument 的内存流为空。

我尝试了多种方法来生成流。下面的代码代表了一个精简版本,仅创建基本要素。同样,内存流的长度为0

我知道我应该使用using() 等。这只是精简代码以尝试使其正常工作。

生成excel的代码;这是来自File 对象的构造函数。 AsMemoryStream 是声明为 public MemoryStream AsMemoryStream { get; private set; } 的属性

public File(IList<T> items)
        {
            if (!items.Any())
                throw new InvalidOperationException("items cannot be empty");


            MemoryStream documentStream = new MemoryStream();
            SpreadsheetDocument document = SpreadsheetDocument.Create(documentStream, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook);

            WorkbookPart workbookPart = document.AddWorkbookPart();
            workbookPart.Workbook = new Workbook();

            WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
            worksheetPart.Worksheet = new Worksheet();

            Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
            Sheet sheet = new Sheet { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Export" };

            sheets.Append(sheet);

            // have tried various Save() calls
            // worksheetPart.Worksheet.Save(); 
            // workbookPart.Workbook.Save();

            AsMemoryStream = new MemoryStream();
            documentStream.CopyTo(AsMemoryStream);
}

我在控制器中,将文件下载为:

public IActionResult TransactionDetails(int transactionId)
        {

            IList<Partner> details = _dataService.GetTransactionPartners(transactionId).Result;
            MemoryStream excelStream = _excelRepository.TransactionDetailExcel(details).AsMemoryStream;
            ContentDisposition contentDisposition = new ContentDisposition
            {
                FileName = "transactionDetails.xlsx",
                Inline = false
            };
            Response.Headers.Add("content-disposition", contentDisposition.ToString());
            return File(excelStream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        }

文件下载,但长度为 0 字节。与正在使用的任何内存流一样。

谁能指出我正确的方向?

【问题讨论】:

  • @rene - 没有。虽然我确实尝试在复制之前刷新documentStream。我现在将尝试处理文档。
  • @rene - 非常感谢。处置为我解决了这个问题。现在试图弄清楚为什么我的行数据没有提交到工作表.. urgh。再次感谢!随意添加答案,如果您愿意,我会标记它。

标签: c# excel asp.net-core openxml openxml-sdk


【解决方案1】:

SpreadSheetDocument 跟踪需要写入流的内容。只有在调用 Close 或 Dispose 时才会这样做。在那之前,它不会创建任何 OpenXmlPackage,因为它无法确定文档是否完整。

以下是修复代码的方法:

MemoryStream documentStream = new MemoryStream();
using(SpreadsheetDocument document = SpreadsheetDocument.Create(documentStream, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook))
{
    WorkbookPart workbookPart = document.AddWorkbookPart();

    workbookPart.Workbook = new Workbook();

    WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
    worksheetPart.Worksheet = new Worksheet();

    Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
    Sheet sheet = new Sheet { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Export" };

    sheets.Append(sheet);
    document.Close();
}

// the stream is complete here
AsMemoryStream = new MemoryStream();
documentStream.CopyTo(AsMemoryStream);

【讨论】:

  • 另外添加:documentStream.Position = 0;使用块后。我在 web api 应用程序中使用它,该应用程序在服务器内存中创建 excel 并将其发送回 angular 应用程序,该应用程序将文件下载到用户下载文件夹。直到在 using 块中添加 document.close() 并在其后添加 documentStream.Position = 0 后,我才能打开下载的 Excel。谢谢雷内!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多