Interesting discussion at StackOverflow:
Create Excel (.XLS and .XLSX) file from C#
If you want to see how to combine NPOI + Excel Table and Chart,
take a look at the post titled NPOI with Excel Table and dynamic Chart.
Recently I had to implement some code to create an Excel spreadsheet/report using C#.
The task was: given an Excel spreadsheet template - a .XLS file (with formulas, pivot tables, macros, etc) I had to fill some data in one of the sheets of the spreadsheet and send this modified spreadsheet back to the user requesting such an operation (Excel report).
The following attests the need for Excel nowadays:
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, pivot tables and the possibility to perform “what if” analysis, make it the “must have” business intelligence tool.
by John Tunnicliffe
I had a great time while studying the possible ways of doing what the task asks for.
It appears to be a simple task at first but as the time passes by you get to know that this is not the case, well, till the moment this blog post was written at least, I think. :-)
Firstly I tried automating Excel through COM automation, but as the application was meant to be used in a web context it is not recommended to use automation. Why? Because COM automation for Excel is not thread safe, that is, EXCEL.EXE was not constructed to be used by concurrent users accessing the same process, in this case EXCEL.EXE; besides, Microsoft Excel must be installed on the server what is not always possible.
For more details on why you shouldn’t use Excel on the server, read this article on Microsoft Help and Support site: Considerations for server-side Automation of Office. The key part is this:
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
I’ve just experienced the above. EXCEL.EXE insisted in being alive in task manager even after processing the data and being closed in code. Each call to process a spreadsheet opens an EXCEL.EXE process on the server. With such EXCEL.EXE processes don’t being closed as they should you get lots of those processes on memory which could overload the server.
Do not use COM automation if you are developing server-side code.
After struggling with COM automation I finally got to know ExcelPackage which works with Office Open Document Format (OOXML). It can read an .XLSX (Microsoft Excel 2007) template and create another .XLSX file based on such template, giving you lots of possibilities to work with the template copy.
I’ve gotten really happy because I had found a way of doing what the task was asking for but with a minor detail: ExcelPackage works only with .XLSX file format letting the .XLS (Microsoft Excel 2003) format out of the game. Well it turned out to be a big impediment because the client (software buyer) wouldn’t allow us to install the famous Microsoft Office Compatibility Pack for Word, Excel, and PowerPoint 2007 File Formats on user machines so that users could open and save OOXML file formats even using Microsoft Office 2003 suite.
Discovering ExcelPackage was good but it didn’t do the trick that implies the use of an .XLS template.
I got back Googling again and strived to find an open source library that would allow me to do what I wanted. After some time I finally discovered NPOI. Wow, it could read the .XLS template and generate the end result I wanted. Great. I downloaded NPOI 1.2.1 for .NET 2.0 binaries immediately and started playing with it to see what it could really do.
OK, after this short story, I’ll show you how to use both open source projects (ExcelPackage and NPOI).
I’ve created a new ASP.NET MVC project as can be seen in this picture:
In the Content folder I’ve placed the template spreadsheets.
In the Libs folder I’ve placed the DLLs necessary to use both ExcelPackage and NPOI open source projects.
The controller that interests us is the one called ExcelWriterController:
The methods that handle the creation of the spreadsheet are: ExcelPackageCreate and NPOICreate.
For each controller action (method) there’s a corresponding view that renders the UI to the user. Those views are the ones shown inside the ExcelWriter folder: ExcelPackage.aspx and NPOI.aspx.
This is the Home Page of the Excel Writer MVC Application - take a look at the tabs (ExcelPackage and NPOI) that lead you to the View pages:

Each view has a button which when clicked calls the corresponding action method on the ExcelWriterController.
This is the NPOI view page:
I’ll play with a simple spreadsheet I filled with the data I got from Excel’s blog post titled Formula to Access a List of Values Interspersed with Zeros or Blanks.
Let’s see the code that goes into the ExcelPackageCreate method:
/// <summary> /// Creates a new Excel spreadsheet based on a template using the ExcelPackage library. /// A new file is created on the server based on a template. /// </summary> /// <returns>Excel report</returns> [AcceptVerbs(HttpVerbs.Post)] public ActionResult ExcelPackageCreate() { try { FileInfo template = new FileInfo(Server.MapPath(@"\Content\ExcelPackageTemplate.xlsx")); FileInfo newFile = new FileInfo(Server.MapPath(@"\Content\ExcelPackageNewFile.xlsx")); // Using the template to create the newFile... using(ExcelPackage excelPackage = new ExcelPackage(newFile, template)) { // Getting the complete workbook... ExcelWorkbook myWorkbook = excelPackage.Workbook; // Getting the worksheet by its name... ExcelWorksheet myWorksheet = myWorkbook.Worksheets["Sheet1"]; // Setting the value 77 at row 5 column 1... myWorksheet.Cell(5, 1).Value = 77.ToString(); // Saving the change... excelPackage.Save(); } TempData["Message"] = "Excel report created successfully!"; return RedirectToAction("ExcelPackage"); } catch(Exception ex) { TempData["Message"] = "Oops! Something went wrong."; return RedirectToAction("ExcelPackage"); } }
Let’s see the code that goes into the NPOICreate method:
/// <summary> /// Creates a new Excel spreadsheet based on a template using the NPOI library. /// The template is changed in memory and a copy of it is sent to /// the user computer through a file stream. /// </summary> /// <returns>Excel report</returns> [AcceptVerbs(HttpVerbs.Post)] public ActionResult NPOICreate() { try { // Opening the Excel template... FileStream fs = new FileStream(Server.MapPath(@"\Content\NPOITemplate.xls"), FileMode.Open, FileAccess.Read); // Getting the complete workbook... HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true); // Getting the worksheet by its name... HSSFSheet sheet = templateWorkbook.GetSheet("Sheet1"); // Getting the row... 0 is the first row. HSSFRow dataRow = sheet.GetRow(4); // Setting the value 77 at row 5 column 1 dataRow.GetCell(0).SetCellValue(77); // Forcing formula recalculation... sheet.ForceFormulaRecalculation = true; MemoryStream ms = new MemoryStream(); // Writing the workbook content to the FileStream... templateWorkbook.Write(ms); TempData["Message"] = "Excel report created successfully!"; // Sending the server processed data back to the user computer... return File(ms.ToArray(), "application/vnd.ms-excel", "NPOINewFile.xls"); } catch(Exception ex) { TempData["Message"] = "Oops! Something went wrong."; return RedirectToAction("NPOI"); } }
One drawback of the ExcelPackage library is that it must create a file on the server. There are some modifications to the library that enables you to create the template copy on memory and send it to the user as the NPOI library does. Take a look at the ExcelPackage’s discussion page at CodePlex and specifically this thread: Why create Excel spreadsheets on the server?
The great thing about NPOI of course is that it enables you to work with the template in code and then send a copy of the spreadsheet directly to the user. The template remains intact and the user receives a modified copy of the template which contains the data processed by the application.
With NPOI when you click on the Create Excel report button you get the download dialog window:
With ExcelPackage you’d have to get the path of the file created on the server, in this case \Content\ExcelPackageNewFile.xlsx and then send that file to the user. This is an extra step and adds an additional burden to the server. I didn’t implement it and so I let this as an exercise to you.
Well, the spreadsheet included in this simple project has only formulas but you can for sure have an Excel template with lots of formulas, pivot tables, macros, etc. This gives you the power of Excel in code in a clean fashion.
Hope this helps shed some light on this topic!
Note
Using the open source libraries presented in this post you won’t need Microsoft Excel installed on the server.
Updated on 9/22/2010
There’s now EPPlus that extends ExcelPackage.
EPPlus is a .net library that reads and writes Excel 2007 files using the Open Office XML format (XLSX).
EPPlus supports ranges, cell styling, charts, pictures, shapes, named ranges, autofilters and a lot of other stuff.
Updated on 6/2/2010
I’m working on an ASP.NET project that uses .NET Framework 1.1. In such a case I needed to use NPOI 1.2.1 for .NET 1.1.
The code you’ll use with NPOI 1.2.1 for .NET 1.1 is the same presented on this post. Just pay attention to include this using directive inside your C# code:
using NPOI.HSSF.UserModel
Updated on 1/3/2010
If you like NPOI, help spread the word about it voting up on this ad:
Visual Studio 2008 C# ASP.NET MVC Web Application
You can get the Microsoft Visual Studio Project at:
http://sites.google.com/site/leniel/blog/ExcelWriterMvcProject.zip
To try out the code you can use the free Microsoft Visual Web Developer 2008 Express Edition that you can get at: http://www.microsoft.com/express/vwd/Default.aspx
References
ExcelPackage: Office Open XML Format file creation
http://excelpackage.codeplex.com/
ExcelPackage binaries download
http://excelpackage.codeplex.com/Release/ProjectReleases.aspx
NPOI
http://npoi.codeplex.com/
NPOI 1.2.1 for .NET 1.1
http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=33203
NPOI 1.2.1 for .NET 2.0
http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=19351
NPOI samples
http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=19351#DownloadId=70100




39 comments:
Hello, nice post.
I have a question about NPOI and templates.
I have a sheet containing a table with different columns, I set up a chart that takes data from this table to draw itself.
When I add in Excel data in the row just under the table, it extends the table, adds the row to the table and updates the chart.
But, if I add rows using NPOI in C#, rows added under the table won't be automatically included in the table, and my chart is not updated the way I would like it to be.
How can I work around this problem?
Hello Zip,
Have you tried
// Forcing formula recalculation...
sheet.ForceFormulaRecalculation = true;
after inserting rows with NPOI?
If this doesn't work, could you please send me your Excel workbook so that I can analyze this?
One thing worth mentioning is that NPOI 1.2.1 (the current release) doesn't support Excel Chart yet. Take a look over the Unsupported Features list at: http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=19351
Although you're working with a table linked to a chart, this may have nothing to do with NPOI not supporting Charts yet because you're not working with the chart directly in the code.
I think NPOI is not recognizing the table inside the sheet. If this holds true, we need to look for a way of making it aware of the table.
I haven't worked with tables when using NPOI. I'd be glad to help you if you could send me your test workbook and the code you're working on. You can get my e-mail on my resume (link to my resume is on the blog's menu above).
Leniel Macaferi
Hey Zip,
I've found a way of doing what you want.
I'll write a new post to show you how to that.
Keep an eye here on the blog! :)
Leniel Macaferi
Zip,
You can go to the post NPOI with Excel Table and dynamic Chart to see the workaround.
Hope this helps you,
Leniel Macaferi
Interesting post... I have a question about NPOI. Can it do cell formatting like Office Interop? Or can ExcelPackage read an .xls file and output to a formatted .xlsx (like adjust column widths, add borders...)?
Wilbert,
Yes, NPOI can do cell formatting. For this purpose you can take a look at the following projects:
- ColorfulMatrix
- ApplyFontInXls
Both projects are part of NPOI samples package - you can download the samples package at http://npoi.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=19351#DownloadId=70100.
You work with HSSFCellStyle object. Take a look at it.
NPOI.HSSF.UserModel.HSSFCell has the CellStyle property that you can set using an HSSFCellStyle object.
In the same way, NPOI.HSSF.UserModel.HSSFRow has the RowStyle property that you can set using an HSSFCellStyle object.
Other option you have is to work with an Excel template workbook. You format this template workbook the way you want and then fill it with data and save a copy of it to the user for example.
ExcelPackage as described in this post doesn't allow you to work with .XLS files (Office 2003 and previous) format.
Leniel Macaferi
Hi! Thank you for this great tutorial for NPOI.
I like to ask and hope you can help, there is formula cell which I need to copy to another cell. If the source cell formula is =SUM(B11:J11), the next formula for the next row should =SUM(B12:J12)
Hi Daniel,
Thank you for stopping by and for asking!
What you wanna do is a simple task with NPOI.
Let's say you have a template as I describe in the post. In cell K11 you have the formula =SUM(B11:J11).
If your cell values are:
B11=1
C11=2
D11=3
E11=4
F11=5
G11=6
H11=7
I11=8
J11=9
K11=45
In an Excel template define/set your formula inside cell K11 and copy/paste it to K12, K13, K14... and so on. To copy/paste, expand your formula clicking in the minuscule handle in the lower-right corner of cell K11. This handle gives you a way to expand the formula to other rows. Doing this, cell K12=SUM(B12:J12), K13=SUM(B13:J13), K14=SUM(B14:J14), etc.
In your code, do the following:
//Add values into rows 11, 12, 13, 14...
// Force formula recalculation...
sheet.ForceFormulaRecalculation = true;
When you open your workbook created with NPOI, you'll see that your formulas were calculated and that now you have the correct values in column K, that is, you formulas will be applied througut your worksheet.
You can also set the formula in the code doing the following:
// Creating rows 11..14
// 0 is the first row...
for(int i = 10; i < 14; i++)
{
HSSFRow row = sheet.CreateRow(i);
// Setting the value 1 at row 11 column B
row.CreateCell(1).SetCellValue(1);
// Setting the value 2 at row 11 column C
row.CreateCell(2).SetCellValue(2);
// Setting the value 3 at row 11 column D
row.CreateCell(3).SetCellValue(3);
// Setting the value 4 at row 11 column E
row.CreateCell(4).SetCellValue(4);
// Setting the value 5 at row 11 column F
row.CreateCell(5).SetCellValue(5);
// Setting the value 6 at row 11 column G
row.CreateCell(6).SetCellValue(6);
// Setting the value 7 at row 11 column H
row.CreateCell(7).SetCellValue(7);
// Setting the value 8 at row 11 column I
row.CreateCell(8).SetCellValue(8);
// Setting the value 9 at row 11 column J
row.CreateCell(9).SetCellValue(9);
row.CreateCell(10).SetCellFormula(string.Format("SUM(B{0}:J{1})", row.RowNum+1, row.RowNum+1));
}
// Forcing formula recalculation...
sheet.ForceFormulaRecalculation = true;
Hope this helps shed some light into this question.
Leniel Macaferi
Have you ever had problems with deployment with NPOI or are there any settings in .NET Framework security that need to be set once placed on a server? We can successfully use it on dev machines but get a UnauthorizedAccessException on any server (03,08) even with wide-open permissions on the directory targeted. Any hints? Thanks in advance
Doug,
It looks like you need to use NPOI in medium trust ASP.NET environment. If so, please use NPOI 1.2.2.
If the issue still exists, contact Tony Qu (the guy behind NPOI) directly - http://www.codeplex.com/site/users/view/tonyqus
All the best,
Leniel Macaferi
Oh, I hadn't seen your answer. I can't believe it didn't send any notification.
It looks like this will actually get the job done (even if it's annoying to have to know beforehand an upper-bound for the number of rows in the table).
Thanks a lot for your answer!
Valeu
I am trying that code and its working fine for .xls but when I am trying to upload the .xlsx its giving error.
"The supplied data appears to be in the Office 2007+ XML. POI only supports OLE2 Office documents "
Can you please tell me how to fix this issue? I googled it but have not found any solution for this.
byte[] buffer = new byte[(int)FileUpload1.FileContent.Length];
Stream fs = new MemoryStream(buffer);
HSSFWorkbook hwbk = new HSSFWorkbook(fs, true);
I am using it by above code.
Thanks in advance.
Anonymous,
As the post states, NPOI can only handle .xls files. You won't be able to work with .xlsx files using NPOI.
The alternative is ExcelPackage described in this post too. ExcelPackage can handle .xlsx files.
All the best,
Leniel Macaferi
Hi..
Thanks for the excellent series of posts here...I am having an issue with NPOI and charts and thought maybe you could help.
I have a template with a chart and when I use NPOI to populate the table that has that chart data, the chart does not update.
I have to open the spreadsheet and then re-save it and then the chart is populated.
I have tried the ForceForumlaRecalculation option to no avail...Are there other options to make formulas/charts update?
Thanks again..I can't imagine how many people out there you have helped with these posts...
Hi Greg,
You're welcome.
This post may be of some help:
NPOI with Excel Table and dynamic Chart
All the best,
Leniel Macaferi
Hi,
I am using NPOI to work with excel files. I open a .xls file and want to add a comment to a cell. When I create a new sheet and create a row and cell, then add comment to cell, it works truly(according to SetCellComment sample). But when I add comment to a cell in a sheet that contains comment or chart or picture does not work. It is assigned in debug mode to CellComment, but when save to a file the comment does not exist. Can you help me?
Thanks a lot
Leniel,
I hope you might be able to steer me in the correct direction on my issue.
I am using NPOI to export data for my users from another application. When my users open up the document, all of the datetimes display as doubles. How can I assign a datetime value format to the cell so that it will be interpreted correctly as a datetime when excel opens instead of being displayed as a double which is confusing my users.
Leniel -
I hope you can help with this. I need to force a value format for a date column when I create my excel document. For some reason, when I open the document up in excel, it still displays the date as the double value that NPOI translated it too and not as a datetime.
How can I set a value format for that cell when I create the document?
Thanks!
Jason,
Create an Excel template that has the number of columns/formats that you need.
For the DateTime column, still inside Excel select the entire column and right click it. Select Format Cells... (I'm using Excel 2010 here) then select Date as the default for that column. Save this Excel template and reference it the way I show in this post.
Using this template you should be able to fill it correctly, that is, when you insert data on the DateTime column, you'll see the correct values shown in the Date format you've chosen.
Note: it's obvious that the data you're inserting in this column should be a DateTime.
Unfortunatey that isn't an option. This is an export of a dynamic data grid so the columns can be different everytime.
I tried writing my own setcellformat method in the hssfdataformatter that sets the format index of a cell's cellstyle.
unfortunately that applied the format to all cells deriving that style. If I change my code so taht it creates a new style for that cell and applies that format to the new style, should that fix my issue?
Jason,
Take a look at the project named SetDateCellInXls that is part of NPOI Examples package - http://npoi.codeplex.com/releases/view/19351#DownloadId=70100
Here goes the code:
HSSFSheet sheet = hssfworkbook.CreateSheet("new sheet");
// Create a row and put some cells in it. Rows are 0 based.
HSSFRow row = sheet.CreateRow(0);
// Create a cell and put a date value in it. The first cell is not styled as a date.
HSSFCell cell = row.CreateCell(0);
cell.SetCellValue(DateTime.Now);
// Style the second cell as a date (and time). It is important to Create a new cell style from the workbook
// otherwise you can end up modifying the built in style and effecting not only this cell but other cells.
HSSFCellStyle cellStyle = hssfworkbook.CreateCellStyle();
cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("m/d/yy h:mm");
cell.CellStyle=cellStyle;
//set chinese date format
HSSFCell cell2 = row.CreateCell(1);
cell2.SetCellValue(new DateTime(2008, 5, 5));
HSSFCellStyle cellStyle2 = hssfworkbook.CreateCellStyle();
HSSFDataFormat format = hssfworkbook.CreateDataFormat();
cellStyle2.DataFormat = format.GetFormat("yyyy年m月d日");
cell2.CellStyle = cellStyle2;
Hope this helps.
Hi Leniel,
This is a very helpful post. I have a quick question, though, that I thought you might be able to help me with. In order to populate the .xls file, I would like to create a Class with the following members:
* Name: The name of the field used in the database. This is a STRING.
* Description: Description of the field which will appear in the Excel file next to the field itself. This is also a STRING
* DataType: The type of data contained in the field (for example, int, string, decimal, etc.). Question: what type should this member be declared as?
* Contents: The contents of the field. Should be declared with the data type specified in DataType above. Question: is it possible to declare a member with a type specified by another member?
* Row: INTEGER containing the row number of the field
* Column: INTEGER containing the column number of the field
Is it possible to create the DataType and Contents members as I have described above in C#?
Many thanks in advance for your help.
A number of these objects are IDisposable (HSSFWorkbook, HSSFSheet, streams). You might want to wrap these in using blocks to insure that resources are cleaned up immediately.
Hi Spenser,
Based on your description, it's difficult to tell what data you have in the database.
Questions I have:
1 - How is your database table designed? What columns does your table have? What is the type of each column?
2 - Each row of the database table would be mapped to an instance of this class?
If I cannot answer your question here, feel free to ask it at StackOverflow - http://stackoverflow.com/
StackOverflow: best place to share/learn programming
Hi Mr Leniel,
My question is similar to the first comments. How do I attach new row using NPOI ? Lets say :
row 1 = report title
row 2 = start report table
If I want to attach new row between row 1 and 2, what do I have to do? I tried Sheet.CreateRow, but unfortunately row 2 is not automatically became row 3, the new row replaced to row 3 itself...please help me
many thanks in advance
YD
Yeddy,
Your best bet is this post: NPOI with Excel Table and dynamic Chart.
This is a workaround to overcome a current limitation of NPOI.
Hope it helps,
Leniel
GrSP,
First off, sorry for taking so long to answer your comment.
I haven't tried to work with cell comments yet.
The advice I can give you is:
Search for this problem and then if don't find anything related, open a thread at the Issue Tracker or Discussions page at the NPOI project page:
Issue Tracker:
http://npoi.codeplex.com/workitem/list/basic
Discussions:
http://npoi.codeplex.com/discussions
Hope this helps,
Leniel
Hi all,
Could somebody post a mirror of the original project?
Apparently, the file
http://leniel.googlepages.com/ExcelWriterMvcProject.zip
has been deleted :(
thx in advance
and great article btw.
Hi Nelson,
Thanks for letting me know that link no longer works.
It's giving a 404 error: The URL you have requested could not be found. (404)
The problem is because Google renamed the service called Google Pages to Google Sites. There was a redirect system in action that pointed all my files from Google Pages to this new Google Sites place. It seems the redirect system stopped working.
I'm updating the post with the new link. Check it.
Regards,
Leniel
Hi,
Please be aware that NPOI uses Apache licence and ExcelPackage uses GPL licence. In other words, NPOI can be used in commercial software adn ExcelPackage cannot.
Cheers,
James
Awesome article. I use NPOI but this looks like a great example of how to save using templates. Thx.
Excellent article and thanks for pointing me in the direction of NPOI.
Hi,
Can we use NPOI to save Excel in CSV format?
Hi Etienne,
I've forwarded your question to Tony Qu ( the guy responsible for NPOI development ) since I haven't used NPOI for this purpose.
This is the answer he has sent me:
"No. I suggest him use some third-party CSV solution. CSV is much
easier than XLS formats. However, if NPOI supported CSV, what if they set
CellStyle and saved as CSV. What should NPOI do? Throw exception? In
Excel UI, it will warn you that some style will be lost. That's the main
concern and why I don't want NPOI to support CSV."All the best,Leniel
Hi Leniel, can we use NPOI to read data from xls as well as xlsx files ? or its only xls ? I am having a tough time with COM, will npoin solve my problem of needing a faster access. pls help thanks
Sandepku
Hi sandepku,
As the post shows, NPOI does XLS and not XLSX. ExcelPackage does XLSX.
NPOI is really fast as far as I can tell you.
All the best.
I would like to use this with monotouch and IOS5. Does this support IOS5 ?
Hi Richard,
From what I could read at Mono Touch website: http://xamarin.com/monotouch you should be able to use existing .NET code in your projects.
Reuse existing code
Import existing .NET libraries and use them in your
MonoTouch apps. Easily bind existing C and Objective-C libraries as well.
I don't know about anyone that has already used NPOI with Mono Touch apps but given the lines above it appears that NPOI can be easily integrated... just give it a try and tell us here if it really works as expected.
what i did was made the reference to the several dll's
then using
HSSFWorkbook templateWorkbook = new HSSFWorkbook()
results in an internal error.
I don't know if IOS5 is responsible for this. The dll's are from 2009
Post a Comment