在ASP.NET MVC Core中,用户需要打印时,从事先做的Excel模板中把Sheet复制过来,然后填充数据,最后返回文件流,用epplus实现,关键代码如下:
using var template = new ExcelPackage(new FileInfo(templateFile));
using var stream = new MemoryStream();
using var package = new ExcelPackage(stream);
var sheet = package.Workbook.Worksheets.Add("报告", template.Workbook.Worksheets[0]);
//填充数据,略
package.Save();
return File(stream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{fileName}.xlsx");
代码本身没有问题,生成的文件中的数据和格式也没有问题。但是打印时发现,在模板文件设置好的打印区域,在新文件中“变大了”,也就是模板文件中一张A4纸刚好打印完的内容,在新文件中,一张A4纸打印不下了。
对照模板文件和新文件,打印设置完全一样。因为对Excel并不熟悉,epplus也没有完整文档,所以不清楚复制一个Sheet到另一个文件中,要想保持所有内容一模一样,是不是还有其它相关设置要处理。
即然只复制一个Sheet会有问题,那么复制整个文件应该不会有问题吧?于是按照这个思路修改代码:
using var template = new ExcelPackage(new FileInfo(templateFile));
using var stream = new MemoryStream();
//复制整个文件到内存流中
template.SaveAs(stream);
using var package = new ExcelPackage(stream);
//填充数据,略
package.Save();
return File(stream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{fileName}.xlsx");
打印没有问题了,另一个问题又出现:填充的数据以及其它修改都没有被保存!简单地说,就是package.Save()
这行代码仿佛没有调用一样。
最终解决方案如下:
using var template = new ExcelPackage(new FileInfo(templateFile));
using var stream = new MemoryStream();
//复制整个文件到内存流中
template.SaveAs(stream);
using var package = new ExcelPackage(stream);
//填充数据,略
//必须创建一个新的内存流,并且用SaveAs把内容保存到这个内存流中才可以,很奇怪。
using var outputStream = new MemoryStream();
package.SaveAs(outputStream);
return File(outputStream.GetBuffer(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{fileName}.xlsx");
因为缺少文档,问题虽然解决了,但原因还是没有搞清楚。