2017-04-21 51 views
2

我使用Open XML从MVC生成Excel文档。使用OpenXML从MVC控制器只读工作簿

的代码如下:

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

} 

随着创建方法如预期的Excel工作表被下载。不过,我想使工作簿只读的,因此试图在。开方法传递MEM流和isEditable设置为false,但我得到一个YSOD时,我打了控制器错误Exception Details: System.IO.FileFormatException: Archive file cannot be size 0.

回答

1

呼叫SpreadsheetDocument.Open不会导致只读文件。 It merely opens the memory stream in read only mode. (isEditable is false)这会锁定来自其他代码更改的流。这就解释了为什么您在添加该调用之前很可能会生成excel罚款,以及在添加该调用后为什么会收到空归档异常。不要为此使用SpreadsheetDocument.Open

我不建议您尝试将Excel作为只读文件发送。用户可以在任何操作系统上下载并重命名它,并根据需要更改文件权限。我建议添加openXML代码mark your Excel as final。微软将此功能添加到Office文档中,因为它更正式地阻止用户对文件进行未来更改,而不是简单的文件许可权。对这些文件之一进行的任何更改都需要新的文件名。

推荐的OpenXml代码将generate a Custom Property,所以当用户下载文件时,它将被标记为最终以阻止用户编辑。

这里是将添加自定义属性的方法:

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应用程序生成标记为最终你作为一个参考实现一个空的Excel文件。 The code is hosted on GitHub。当你运行它时,点击最右边的菜单链接“下载Excel”。这将下载一个名为Walter's Workbook的工作簿并且没有数据。该excel将被标记为final。 Custom Property的代码是使用OpenXML Productivity Tool生成的。祝你的项目好运。

+0

重大疾病给了这一去。我的最终用户可能会有更旧版本的Excel..office 2003。如果最终不使用OpenXML可能需要查看另一个库..aspose是我之前使用过的,但它可能是昂贵的 –