MemoryStream在OpenXML Excel文档中为空。

7

我通常使用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。现在我将尝试处理该文档。 - Darren Wainwright
@rene - 非常感谢。Disposing解决了我的问题。现在正在尝试弄清楚为什么我的行数据没有提交到工作表..呃。再次感谢!如果您愿意,可以添加一个答案,我会标记它。 - Darren Wainwright
1个回答

11

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

4
在使用代码块后添加:documentStream.Position = 0;。我在Web API应用程序中使用它,在服务器内存中创建Excel文件并将其发送回Angular应用程序,该应用程序将文件下载到用户的下载文件夹中。在使用代码块中添加了document.close()和 documentStream.Position = 0之后,才能打开下载的Excel文件。感谢Rene! - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接