【问题标题】:Making workbook readonly from MVC Controller with OpenXML使用 OpenXML 从 MVC 控制器制作工作簿只读
【发布时间】:2017-04-21 13:51:48
【问题描述】:

我正在使用 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.

【问题讨论】:

    标签: c# asp.net-mvc excel openxml openxml-sdk


    【解决方案1】:

    让您的 Excel 成为只读的更简单方法是 Protect the worksheet (see Step 2 at link)

    执行此操作的 OpenXML 代码是每张纸一行:

    workSheet.Append(new SheetProtection() { Sheet = true, Objects = true, Scenarios = true });
    

    我已经推送了一个使用这种技术的new version of the reference implementation MVC。 Excel 2007 似乎支持 SheetProtection,其中仅从 Excel 2013 开始支持标记为 Final。

    【讨论】:

    • 这正是我需要的 - 谢谢 :)
    【解决方案2】:

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

    我不建议您尝试将 Excel 作为只读文件发送。用户可以在任何操作系统上下载它并重命名它并根据需要更改文件权限。

    我建议添加mark your Excel as final 的openXML 代码。 Microsoft 将此功能添加到 Office 文档中,因为它更正式地阻止用户将来更改文件而不是简单的文件权限。对这些文件之一的任何更改都需要一个新的文件名。

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

    下面是添加自定义属性的方法:

    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 文件,作为参考实现。 The code is hosted on GitHub。运行它时,单击最右侧的菜单链接“下载 Excel”。这将下载一个 Excel,其中包含一个名为 Walter's Workbook 的工作簿,但没有数据。 excel将被标记为final。自定义属性的代码是使用 OpenXML Productivity Tool 生成的。祝你的项目好运。

    【讨论】:

    • 太糟糕了,试一试。我的最终用户可能拥有旧版本的 Excel..office 2003。如果最终无法与 OpenXML 一起使用,则可能需要查看另一个库..aspose 是我以前使用过的,但它可能很昂贵
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 2012-09-14
    • 2013-03-11
    • 1970-01-01
    相关资源
    最近更新 更多