Using ExcelPackage to Create Excel 2007 Files on the Server
Introduction
The adoption of XML as the native file format for Excel 2007 has opened up a whole host of new possibilities. Now, for the first time, you can use standard tools to create native Excel files on the server. No longer is there a need to pollute your beautiful server room with a headless PC running Excel and an old VB6 app that uses OLE Automation to create reports. Such things can be consigned to the trash heap of IT history.
However, the Office Open XML standard is so new there are precious few good code samples. This article aims to correct the situation by providing a flexible set of open source class libraries that you can use to create Excel spreadsheets on the server.
Why Create Excel Spreadsheets on the Server?
Excel has long been recognized as the de facto standard when it comes to presenting management reports. The unique combination of great calculation engine, excellent charting facilities, and the possibility to perform "what if" analysis make it the "must have" business intelligence tool.
So, when I came to replace my aging management reporting infrastructure, I set one key requirement: the new system must be web-based and provide a "download in Excel" option. For mt business intelligence project, I built the data warehouse using SQL Server 2005 populated from PeopleSoft and Novient implementations using SQL Server 2005 Integration Services (SSIS). The OLAP cube was built on SQL Server 2005 Analysis Services (SSAS). SQL Server 2005 Reporting Services (SSRS) provides the web-based access to management reports and the all important "download in Excel" option. So, why do you need to create Excel on the server?
The problem with SQL Server 2005 Reporting Services is that it the Excel spreadsheets it generates are "dumb." They contain no formula—just the raw data. So, the recipient cannot perform a "what if" analysis by changing a few values and expecting the spreadsheet to recalculate.
I considered a number of ways to overcome this issue, but by far the most attractive is to create the Excel spreadsheet on the server, straight from the OLAP cube data. So, I created a web-part for SharePoint Server 2007 so the user could enter their criteria and view the report online via Excel Services. Of course, users can download the file for off-line viewing in Excel 2007 or even Excel 2003 file format. This SharePoint web-part and its associated web service that does the file format conversion will be the topic of another article.
The Open Source ExcelPackage Assembly
The ExcelPackage assembly is a set of classes and wrappers around the .NET 3.0 System.IO.Packaging API and the new SpreadsheetML file format. It extracts away the complexity of dealing with the individual XML components that make up the new Excel 2007 file format. The classes are published as an assembly called ExcelPackage that you can install in the GAC and use as the basis of your own applications. In the sprit of open source projects, if you want to help extend the functionality offered by the ExcelPackage assembly, join the team over at the ExcelPackage Open XML project.
Creating an Excel Spreadsheet from Scratch
Sample 1 shows how to create a new Excel spreadsheet containing some basic data and calculations. See how this is achieved.
using OfficeOpenXml; // namespace for the ExcelPackage assembly
b&
FileInfo newFile = new FileInfo(@"C:\mynewfile.xlsx");
using (ExcelPackage xlPackage = new ExcelPackage(newFile)) { b& }
This creates a new instance of the all-important ExcelPackage class that gives you access to the Excel workbook and worksheets. If mynewfile.xlsx already exists, ExcelPackage will open the existing file. Otherwise, mynewfile.xlsx will be created from scratch.
Start by adding a new worksheet called "Tinned Goods" and adding some basic data and a simple calculation:
ExcelWorksheet worksheet =
xlPackage.Workbook.Worksheets.Add("Tinned Goods");
// write some titles into column 1
worksheet.Cell(1, 1).Value = "Product";
b&
worksheet.Cell(4, 1).Value = "Peas";
worksheet.Cell(5, 1).Value = "Total";
// write some values into column 2
worksheet.Cell(1, 2).Value = "Tins Sold";
ExcelCell cell = worksheet.Cell(2, 2);
cell.Value = "15"; // tins of Beans sold
string calcStartAddress = // we want this for the formula
cell.CellAddress;
worksheet.Cell(3, 2).Value = "32"; // tins of Carrots sold
b&
worksheet.Cell(5, 2).Formula = string.Format(SUM({0}:{1})",
calcStartAddress, calcEndAddress);
If all this seems a bit too easy—well, yes it is! The ExcelPackage assembly does all the hard work of creating the XML elements that are needed to represent an Excel worksheet, the Excel rows, the Excel cells, and so forth. All you need to do is connect in the data! The ExcelWorksheet class has all the properties and methods needed to create and manipulate worksheets. A number of supporting classes (such as ExcelCell, ExcelRow, ExcelColumn, ExcelHeaderFooter, and so on) provide properties and methods of each worksheet component. They also provide helper functions that make it easy to manipulate Excel data. For example, the ExcelCell.GetCellAddress(iRow, iColumn) method turns your row and column integers into Excel-style cell addresses.
Ok, so in the sample some of the data is too wide for the column; you can change the column size:
worksheet.Column(1).Width = 15;
Next, add some headers and footers to the spreadsheet. Note how to use the PageNumber and NumberOfPages constants to insert codes into the footer text. This causes Excel to insert the page number and the number of pages in the document footer.
worksheet.HeaderFooter.oddHeader.CenteredText = "Tinned Goods Sales";
// add the page number to the footer plus the total number of pages
worksheet.HeaderFooter.oddFooter.RightAlignedText =
string.Format("Page {0} of {1}", ExcelHeaderFooter.PageNumber,
ExcelHeaderFooter.NumberOfPages);
Okay, write some real hard code. Insert a line into the worksheet so you can add some more data. This will screw up your formula because it will reference the wrong set of rows (in other words, the new row will not be included in the total).
worksheet.InsertRow(3);
Well no, the formula is correct. The InsertRow method not only updates all the row and cell references in the underlying XML, but also updates all the formulas in the spreadsheet! Okay, you now have your report, but you want to ensure your corporate search engine can find the file later. So, add some standard and custom document properties.
xlPackage.Workbook.Properties.Title = "Sample 1";
xlPackage.Workbook.Properties.Author = "John Tunnicliffe";
xlPackage.Workbook.Properties.SetCustomPropertyValue
("EmployeeID", "1147");
Now, save the file and all its components.
xlPackage.Save();
Below is a screenshot of the final output showing the header and the document properties.

Comments
There are no comments yet. Be the first to comment!