简体   繁体   English

对于OpenXML Excel文档,MemoryStream为空

[英]MemoryStream is empty for an OpenXML Excel document

I would normally use ClosedXML to generate Excel files. 我通常会使用ClosedXML生成Excel文件。 A Core project is forcing me to use only OpenXML. 一个核心项目迫使我只能使用OpenXML。

The resulting Excel file will be downloaded. 生成的Excel文件将被下载。

I am having an issue where the memory stream given to the SpreadsheetDocument is empty. 我遇到的问题是分配给SpreadsheetDocument的内存流为空。

I have tried multiple ways to generate a stream. 我尝试了多种方法来生成流。 The code below represents a slimmed down version to create just the bare essentials. 下面的代码表示一个精简版本,仅创建基本要点。 Again, memory streams are 0 in length. 同样,内存流的长度为0

I am aware i should be using using() etc. This is just slimmed down code to try and get it working. 我知道我应该使用using()等。这只是精简代码以尝试使其正常工作。

Code to generate the excel; 生成excel的代码; this is coming out of a constructor on a File object. 这是从File对象的构造函数中得出的。 AsMemoryStream is a property declared as public MemoryStream AsMemoryStream { get; private set; } AsMemoryStream是一个声明为public MemoryStream AsMemoryStream { get; private set; }的属性public MemoryStream AsMemoryStream { get; private set; } 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);
}

I am, in a controller, downloading the file as: 我在控制器中以以下方式下载文件:

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");
        }

The file downloads, though is 0 bytes in length. 虽然下载文件的长度为0个字节,但仍为0。 As are any of the memory streams being used. 就像正在使用的任何内存流一样。

Can anybody point me in the right direction? 有人能指出我正确的方向吗?

SpreadSheetDocument keeps track of the content that needs to be written to the stream. SpreadSheetDocument跟踪需要写入流的内容。 It only does so when either Close or Dispose is called. 只有在调用Close或Dispose时才这样做。 Until that moment it will not create any of the OpenXmlPackage as it can't be sure if the document is complete. 在此之前,它将无法创建任何OpenXmlPackage,因为无法确定文档是否完整。

Here is how you can fix your code: 这是修复代码的方法:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM