【发布时间】:2021-11-30 21:03:38
【问题描述】:
我已经搞砸了几个小时,但无济于事。我正在尝试复制一个 excel 文件,向其中添加一个新工作表,将文件放入 MemoryStream 中,然后返回流。
代码如下:
public Stream ProcessDocument()
{
var resultStream = new MemoryStream();
string sourcePath = "path\\to\\file";
string destinationPath = "path\\to\\file";
CopyFile(destinationPath, sourcePath);
var copiedFile = SpreadsheetDocument.Open(destinationPath, true);
var fileWithSheets = SpreadsheetDocument.Open("path\\to\\file", false);
AddCopyOfSheet(fileWithSheets.WorkbookPart, copiedFile.WorkbookPart, "foo");
using(var stream = new MemoryStream()){
copiedFile.WorkbookPart.Workbook.Save(stream);
stream.Position = 0;
stream.CopyTo(resultsStream);
}
return resultsStream;
}
public void CopyFile(string outputFullFilePath, string inputFileFullPath)
{
int bufferSize = 1024 * 1024;
using (var fileStream = new FileStream(outputFullFilePath, FileMode.OpenOrCreate))
{
var fs = new FileStream(inputFileFullPath, FileMode.Open, FileAccess.ReadWrite);
fileStream.SetLength(fs.Length);
int bytesRead = -1;
byte[] bytes = new byte[bufferSize];
while ((bytesRead = fs.Read(bytes, 0, bufferSize)) > 0)
{
fileStream.Write(bytes, 0, bytesRead);
}
fs.Close();
fileStream.Close();
}
}
public static void AddCopyOfSheet(WorkbookPart sourceDocument, WorkbookPart destinationDocument, string sheetName)
{
WorksheetPart sourceSheetPart = GetWorkSheetPart(sourceDocument, sheetName);
destinationDocument.AddPart(sourceSheetPart);
}
public static WorksheetPart GetWorksheetPart(WorkbookPart workbookPart, string sheetName)
{
string id = workbookPart.Workbook.Descendants<Sheet>().First(x => x.Name.Value.Contains(sheetName)).Id
return (WorksheetPart)workbookPart.GetPartById(id);
}
问题似乎来自copiedFile.WorkbookPart.Workbook.Save(stream)。
运行后,我收到一条错误消息,提示存在“System.ObjectDisposedException”类型的异常。文件复制良好,添加工作表似乎也可以正常工作。
这是我尝试过的:
- 使用不带流的 .Save() 作为参数。它什么都不做。
- 使用两个不同的流(因此代码中的 resultStream 卡顿)
- 使用纯 OpenXML 并将 WorkbookParts 直接复制到流中。用纯文本 excel 测试并且很好,但它破坏了所需的文件,因为它具有一些似乎不适用于 OpenXML 的高级格式。不过,如果有人知道我如何解决这个问题,我愿意重构。
我没有尝试过的:
- 创建副本的另一个副本并使用 SpreadsheetDocument.Create(stream, type) 方法。我觉得这会奏效,但它似乎是一个糟糕而缓慢的解决方案。
- 更新 OpenXML。我目前是 2.5。
非常感谢任何反馈或想法。谢谢!
PS:我的开发箱是气隙的,所以我不得不手写这段代码。如有错误请见谅。
【问题讨论】:
标签: c# openxml openxml-sdk