[英]Making workbook readonly from MVC Controller with OpenXML
我正在使用Open XML從MVC生成Excel文檔。
代碼如下:
public ActionResult ExcelReport()
{
var custId = 1234; //ToDo get from session when it is set
using (MemoryStream mem = new MemoryStream())
{
ExcelReportGenerator excel = new ExcelReportGenerator();
excel.CreateExcelDoc(mem);
var reportName = string.Format("MyReport_{0}.xlsx", custId);
return File(mem.ToArray(), System.Net.Mime.MediaTypeNames.Application.Octet, reportName);
}
}
我的CreateExcelDoc方法如下:
public void CreateExcelDoc(MemoryStream mem)
{
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(mem, SpreadsheetDocumentType.Workbook);
//SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(mem, false);
//Code removed for brevity
worksheetPart.Worksheet.Save();
spreadsheetDocument.Close();
}
使用create方法,excel表正按預期下載。 但是,我想將工作簿設置為只讀,因此嘗試將.Open方法傳遞給mem流並將isEditable設置為false但是當我使用錯誤Exception Details: System.IO.FileFormatException: Archive file cannot be size 0.
命中控制器時,我得到一個YSOD Exception Details: System.IO.FileFormatException: Archive file cannot be size 0.
使excel只讀的簡單方法是保護工作表(參見鏈接中的步驟2) 。
執行此操作的OpenXML代碼是每張一行:
workSheet.Append(new SheetProtection() { Sheet = true, Objects = true, Scenarios = true });
我已經推出了使用這種技術的新版本的參考實現 MVC。 Excel 2007中似乎支持SheetProtection,其中僅在Excel 2013之后支持標記為Final。
調用SpreadsheetDocument.Open
不會生成只讀文件。 它只是以只讀模式打開內存流。 ( isEditable
為false)這將isEditable
流被其余代碼更改。 這解釋了為什么您可能在添加該調用之前生成excel,以及在添加該調用后獲得空存檔異常的原因。 不要為此目的使用SpreadsheetDocument.Open
。
我不建議您嘗試將Excel作為只讀文件發送。 用戶可以在任何操作系統上下載它並重命名它並根據需要更改文件權限。
我建議添加openXML代碼, 將Excel標記為final 。 Microsoft將此功能添加到Office文檔中,因為它更正式地阻止用戶對文件進行更改,而不是簡單的文件權限。 對其中一個文件的任何更改都需要新的文件名。
推薦的OpenXml代碼將生成自定義屬性,因此當用戶下載文件時,它將被標記為“最終”以阻止用戶編輯。
以下是添加自定義屬性的方法:
private void GenerateCustomFilePropertiesPart1Content(CustomFilePropertiesPart customFilePropertiesPart1)
{
Op.Properties properties2 = new Op.Properties();
properties2.AddNamespaceDeclaration("vt", "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes");
Op.CustomDocumentProperty customDocumentProperty1 = new Op.CustomDocumentProperty() { FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", PropertyId = 2, Name = "_MarkAsFinal" };
Vt.VTBool vTBool1 = new Vt.VTBool();
vTBool1.Text = "true";
customDocumentProperty1.Append(vTBool1);
properties2.Append(customDocumentProperty1);
customFilePropertiesPart1.Properties = properties2;
}
我編寫了一個簡單的MVC應用程序,它生成一個標記為final的空Excel文件作為參考實現。 代碼托管在GitHub上 。 當您運行它時,單擊最右側的菜單鏈接“下載Excel”。 這將下載一個名為Walter's Workbook的工作簿並且沒有數據的Excel。 excel將標記為final。 Custom Property的代碼是使用OpenXML Productivity Tool生成的。 祝你的項目好運。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.