对于 OpenXML Excel 文档,MemoryStream 为空

Dar*_*ght 6 c# excel openxml openxml-sdk asp.net-core

我通常会使用 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);
}
Run Code Online (Sandbox Code Playgroud)

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

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");
        }
Run Code Online (Sandbox Code Playgroud)

文件下载,但长度为 0 字节。正在使用的任何内存流也是如此。

有人能指出我正确的方向吗?

ren*_*ene 9

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);
Run Code Online (Sandbox Code Playgroud)

  • 还添加: documentStream.Position = 0; 使用块后。我在 Web API 应用程序中使用它,在服务器内存中创建 Excel 并将其发送回 Angular 应用程序,该应用程序将文件下载到用户下载文件夹。我无法打开下载的 Excel,直到我在 using 块中添加 document.close() 并在其后添加 documentStream.Position = 0 。谢谢雷内! (3认同)