Search code examples
c#asp.net-mvcexcelopenxmlopenxml-sdk

Making workbook readonly from MVC Controller with OpenXML


I am generating an Excel Document from MVC using Open XML.

The code is as below:

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

}

My CreateExcelDoc method is as below:

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

}

With the create method the excel sheet is downloading as expected. However, I wanted to make the workbook read-only so was trying the .Open method passing the mem stream and the isEditable set to false but I am getting a YSOD when I hit the controller with an Error Exception Details: System.IO.FileFormatException: Archive file cannot be size 0.


Solution

  • A simpler way of making your excel read only is to Protect the worksheet (see Step 2 at link).

    The OpenXML code to do this is one line per sheet:

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

    I have pushed a new version of the reference implementation MVC that uses this technique. The SheetProtection seems to be supported in Excel 2007, where the marking as Final is only supported since Excel 2013.