So I’ve been using NPOI all week and decide to do a quick “demo” for my team today. My demo was to show how to use NPOI to populate (update) an Excel template that includes various charts. Even though NPOI does not support creating charts from scratch, it does support updating files that already include (hence template) charts. I started by going to the Microsoft website where they have a bunch of free “pretty” templates on, randomly choosing one with a bunch of formulas and charts. It took me about an hour to build the complete demo using very simple and easy to read code. Most of the updates or just putting values in cells, but the actual process of opening/reading/inserting/saving a new or existing file in NPOI is very easy for a novice programmers.
Development Summary ( Step-by-Step )
- Get a template, I grabbed mine from here ( office.microsoft.com ).
** I only used the first sheet and deleted all the sample data - Create a new ASP.NET 3.5 Web Application projecct
- Download NPOI binaries and include in your project
- Build a UI that will be used to populate your template.
** This could also be populated by a data sources (db, XML, etc..)
** NOTE: I used Excel to create the form using Excel formulas - Add some c# code “magic” to load data into the template using NPOI
Sounds simple because it is… Here is the code to add the form contents into the Excel template.
// Open Template
FileStream fs = new FileStream(Server.MapPath(@"\template\Template_EventBudget.xls"), FileMode.Open, FileAccess.Read);
// Load the template into a NPOI workbook
HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true);
// Load the sheet you are going to use as a template into NPOI
HSSFSheet sheet = templateWorkbook.GetSheet("Event Budget");
// Insert data into template
sheet.GetRow(1).GetCell(1).SetCellValue(EventName.Value); // Inserting a string value into Excel
sheet.GetRow(1).GetCell(5).SetCellValue(DateTime.Parse(EventDate.Value)); // Inserting a date value into Excel
sheet.GetRow(5).GetCell(2).SetCellValue(Double.Parse(Roomandhallfees.Value)); // Inserting a number value into Excel
sheet.GetRow(6).GetCell(2).SetCellValue(Double.Parse(Sitestaff.Value));
sheet.GetRow(7).GetCell(2).SetCellValue(Double.Parse(Equipment.Value));
sheet.GetRow(8).GetCell(2).SetCellValue(Double.Parse(Tablesandchairs.Value));
sheet.GetRow(12).GetCell(2).SetCellValue(Double.Parse(Flowers.Value));
sheet.GetRow(13).GetCell(2).SetCellValue(Double.Parse(Candles.Value));
sheet.GetRow(14).GetCell(2).SetCellValue(Double.Parse(Lighting.Value));
sheet.GetRow(15).GetCell(2).SetCellValue(Double.Parse(Balloons.Value));
sheet.GetRow(16).GetCell(2).SetCellValue(Double.Parse(Papersupplies.Value));
sheet.GetRow(20).GetCell(2).SetCellValue(Double.Parse(Graphicswork.Value));
sheet.GetRow(21).GetCell(2).SetCellValue(Double.Parse(Photocopying_Printing.Value));
sheet.GetRow(22).GetCell(2).SetCellValue(Double.Parse(Postage.Value));
sheet.GetRow(26).GetCell(2).SetCellValue(Double.Parse(Telephone.Value));
sheet.GetRow(27).GetCell(2).SetCellValue(Double.Parse(Transportation.Value));
sheet.GetRow(28).GetCell(2).SetCellValue(Double.Parse(Stationerysupplies.Value));
sheet.GetRow(29).GetCell(2).SetCellValue(Double.Parse(Faxservices.Value));
sheet.GetRow(33).GetCell(2).SetCellValue(Double.Parse(Food.Value));
sheet.GetRow(34).GetCell(2).SetCellValue(Double.Parse(Drinks.Value));
sheet.GetRow(35).GetCell(2).SetCellValue(Double.Parse(Linens.Value));
sheet.GetRow(36).GetCell(2).SetCellValue(Double.Parse(Staffandgratuities.Value));
sheet.GetRow(40).GetCell(2).SetCellValue(Double.Parse(Performers.Value));
sheet.GetRow(41).GetCell(2).SetCellValue(Double.Parse(Speakers.Value));
sheet.GetRow(42).GetCell(2).SetCellValue(Double.Parse(Travel.Value));
sheet.GetRow(43).GetCell(2).SetCellValue(Double.Parse(Hotel.Value));
sheet.GetRow(44).GetCell(2).SetCellValue(Double.Parse(Other.Value));
sheet.GetRow(48).GetCell(2).SetCellValue(Double.Parse(Ribbons_Plaques_Trophies.Value));
sheet.GetRow(49).GetCell(2).SetCellValue(Double.Parse(Gifts.Value));
// Force formulas to update with new data we added
sheet.ForceFormulaRecalculation = true;
// Save the NPOI workbook into a memory stream to be sent to the browser, could have saved to disk.
MemoryStream ms = new MemoryStream();
templateWorkbook.Write(ms);
// Send the memory stream to the browser
ExportDataTableToExcel(ms, "EventExpenseReport.xls");
Here are the screen shots of the form and completed template…
Here is demo UI.
Here is a populated template.
Here is a copy of the XLS file created in the program: NPOI – ASP.NET Form merged with Excel template
Here is a copy of the source code for the demo: NPOI – Visual Studio 2008 (ASP.NET 3.5) Template Merge Demo
** There was a caveat during the development process. During the demo I found a bug with NPOI opening my XLS file and I had to download the source code and make two changes to get NPOI to open my XLS template (bug states this issue is caused when you save a XLSX file as XLS in Excel 2007). Read this post to see the fix or use the DLLs for NPOI included in my demo project.
** NPOI is a active Open Source project, the bugs found have probably already been fixed and if you download the latest code from CodePlex, you’ll probably have no problems running the demo.
Pingback: [SOLVED] fill a custom excel template from sql server proc with multiple result sets? – BugsFixing
#1 by kailash on May 21, 2014 - 10:36 pm
Dear Sir,
http://office.microsoft.com/en-us/templates/event-budget-TC010336274.aspx?pid=CT101172321033
Not working in VS 2010 (asp.net) i have already using NPOI 1.2.3 Version for export excel
#2 by Zach on May 23, 2014 - 6:41 am
This might be a breaking change in NPOI 1.2.3, what is the error you are getting ?
#3 by Zreecu on May 2, 2013 - 11:54 pm
Hi Zach,
I am using Visual Studio 2008. I have a requirement where in I have to create an combo box in excel with a set of values. The end user can export the excel and can make necessary changes in the combo box values and import it back into my application. How to add an combo box to the exported excel sheet?
Thanks in Advance
#4 by Zach on May 3, 2013 - 11:13 pm
One easy way to create it in the output would be to link you ComboBox to a named range (http://www.contextures.com/xlDataVal11.html), then add/remove items to the named range (http://poi.apache.org/spreadsheet/quick-guide.html#NamedRanges). I use a similar approach to populating templates that I want to dynamically expand. Let me know if this works for you, good luck!
#5 by Tracey on September 10, 2012 - 4:21 pm
Hi Zach,
I am using Visual Studio 2008, and now could be able to get data from database & load to template, but the graph won’t pick up the value from the table value, the table value showing the correct data, but the graph won’t draw.
Any idea ,please help
Many thanks
#6 by Zach on September 11, 2012 - 8:27 am
Great job figuring out how to load the data into your template. Did you call “sheet.ForceFormulaRecalculation = true;” on the sheet when you were done making changes? This will trigger the sheet to recalculate and update.
#7 by Tracey on September 6, 2012 - 9:52 pm
Hi Zach,
I am new to NPOI, would you pls send me code how to get data from database & load to template please.
Thanks
#8 by Nick on July 31, 2012 - 11:55 am
I am using a template to create a new workbook. I am trying to create multiple new sheets in my new workbook using the same one template (this has one sheet only). How do I do that? I see only one API wb.createSheet(), how do I then copy the template into this new sheet? Or am I missing something?
#9 by Zach on July 31, 2012 - 3:08 pm
There is no easy way to do this (copying 1 template sheet into a workbook multiple times). There is a thread here where somebody wrote a copy worksheet routine, but it results in a corrupt workbook. The quickest “work-around”, would be to create a sheet with lets say 10 worksheets with the same template. Then populate the sheets you plan to use and delete the rest, it’s a bit of a dirty hack but it’s a quick way to work around the problem.
#10 by Max on April 6, 2012 - 10:18 am
Hi,
I want to create a spreadsheet using NPOI. I have got the code working for all my requirements EXCEPT that I also need to have a DropDownList with hardcoded values in the spreadsheet.
I referred to http://poi.apache.org/spreadsheet/quick-guide.html (and googled for NPOI dropdown) but I Cannot find
a WorkSheet.AddValidationData() method.
This is really a critical need for my client. Any suggestions or thoughts will help! Do you know of any way using NPOI to add a dropdown list with prepopulated values to a Spreadsheet?
#11 by Zach on April 9, 2012 - 2:36 pm
This feature isn’t support in NPOI and since XLS has been obsolete since Office 2007, I doubt there will be any major enhancements to NPOI. The library is OS, if you really want the feature you can port it over from POI to NPOI, I’ve done this on a bunch of random features I’ve needed in the past and is why I no longer use the core NPOI build. Other options are; EPPlus, OpenExcel, Open XML SDK 2.0. I think there are a few more, but lots of options with XLSX since it no longer uses binary files and it’s the current standard used by Excel.
#12 by sasi on November 30, 2011 - 4:34 am
Hi Zach,
Can you advise me how to deal with an excel template which has images in it? I was able to open the teamplat and update it with data and save it with a different name. However when i open the new excel even though the content is all good HSSFWorkbook is corrupting the content and not letting me save it. Can you please suggest me the way forward? Thank you.
#13 by IG on July 22, 2011 - 9:00 am
Hi Zach
I created a new .xls file and it has simple macro that populates a cell with a value. When I use my website to populate the .xls from another machine i get prompted to enable macros, which I do. But then I get an error of “An error occured while loading ‘Module 1’, do you want to continue loading project.
Do you I need to save the Excel file as another file type maybe?
Many thanks
#14 by IG on July 22, 2011 - 2:24 am
Hi Zach
I was wondering if I coudl ask a question about Macros and NPOI. I have created a simple template as described in the above. In the template I have added a Button, on click it calls a Sub Button1_Click which just outputs a msgbox saying hellow world.
The macro works fine when I am on my dev machine (machine that created spreadsheet) however when I try it from another machine I get errors such as
“An error while loading ‘ThisWorkbook’. Do you want to continue loadiung this project”
“An error occured while loading ‘Module1’ Do you still want to continue loading the project
Any ideas why this is happening? Can I use Macros with NPOI
Many thanks in advance
#15 by Zach on July 22, 2011 - 7:53 am
IG, I’ve put some basic Macro’s in my templates before and they worked but I’ve never tried adding a button. Can you confirm the following.
1. Create a new EXCEL file with a w/macro (don’t have to create button, just record something and save).
2. Add some data using NPOI.
3. Open the XLS document in EXCEL and manually run macro.
If this does not work, I suggest you post your XLS file to the NPOI forum / bug section to see if somebody will take some time debugging it. The most important thing is being able to recreate the error, it’s very common for XLS files to get corruption… so make sure you start your test by creating a new XLS file.
#16 by Laurie on June 24, 2011 - 11:33 am
Hello Zach,
Thank you so much for your reply. I think I used your DBA’s approach to load data from SQL to Excel. There is only one column having formacting issue. In my template, I set it as percentage, but my output column did not apply that at all. So that was the reason I searched ExcelPackage to accomplish this, but SSIS only can return xls file. Is there a way to convert xls to xlsx programmatically without using Microsoft office on the server side?
Thank you!
Laurie
#17 by Zach on June 24, 2011 - 11:51 am
There is no way to “auto convert” XLS to XLSX that will preserve all formatting. You can easily convert the raw data, but that doesn’t sound too helpful in your case.
Here are some work around ideas:
1. Create a auto-run macro that formats the sheet when the user opens it?
2. Format the values in SQL before inserting into Excel.
3. Fill a column with a formula/format that will compute the percent and display correct.
Example: Cost = Export, Price = Export, Margin = Calculated / Formatted Field
#18 by Laurie on June 24, 2011 - 8:55 am
Hi Zach,
I am new to NPOI. I have used SSIS to output xls file using my predifned template. Now the outputed xls file included my predefined clomun names and associated cell format in the first row, and predefined sample data with the right cell formact in the second row, and the output data satrting from row 4 to row 780 without any formatcting. I need to use NPOI to force all cloumn row from 4 to 780 using same cell formact as row 2. I was able to use excelPackage to do that but I need to manually open xls file in Excel and renamed to xlsx. Do you think it is possible to use NPOI to convert xls to xlsx and reused my working codes with ExcelPackage, or I have to use NPOI to do all the work?
Thank you for your help!
Laurie
#19 by Zach on June 24, 2011 - 9:04 am
Laurie,
I have not personally used SSIS to output XLS files, but my DBA at work has and all her reports are fully formatted from the First Row to Last Row. It sounds like there is a problem with your template that SSIS is using. Is you template completely formatted, did you apply the formatting on the column? You should try fixing the template versus using ExcelPackage/NPOI to double process your Excel file. Let me know what happens after you apply your formatting to the column, if it doesn’t work I can look at one of my DBA’s file to see how she setup her report template for SSIS.
Zach
#20 by Zach on June 24, 2011 - 9:31 am
I just checked one of her templates, she creates a named range and applies the formatting to the column. Then, when she loads the data from SQL to EXCEL, she sets the named range as her target. This way she can put a header and other data at the top of the sheet and append her data into the named range. This results in formatting being applied to every cell in every row.
#21 by IG on June 17, 2011 - 6:05 pm
Hi Zach
Was just wondering if you were able to replicate the problem above?
Cheers
#22 by IG on June 16, 2011 - 3:46 am
Hi Zach
Thanks for your post. I think im getting closer to the problem. If I use your spreadsheet it works. However if I add a new sheet to your spreadsheet eg Sheet1, Save it and then run web app to load Sheet1 it gives an error. Is there something I need to do to the sheet or cells to make them editable?
Cheers
#23 by Zach on June 20, 2011 - 9:00 am
In order to use a “new empty” sheet, you need to create the rows & cells. In the default state (a new sheet with no data), nothing is initialized so nothing is accessible. To start using a blank sheet, you need to create a row and then create the cell.
Sheet sheet = workbook.CreateSheet("Sheet1");
Row row = sheet.CreateRow(0);
row.CreateCell(0).SetCellValue("Cell A1");
#24 by IG on June 15, 2011 - 1:39 am
Hi Zach
Thanks for the reply. The row exists. I have just tried creating the sheet using templateWorkbook.CreateSheet(“test”) and I still get the same error. I really cant see why this doesnt work? I really want to use NPOI but just cant seem to get it to work. Any help would be much appreciated
Cheer
#25 by Zach on June 15, 2011 - 10:33 am
I just downloaded the demo using the link on the blog post, converted to 4.0 and it ran perfectly (changed all the values in the template with the values entered via the web). Are you testing with the demo or your own file? Try the demo and see if it works, if it works then it’s something with your file. If you need help with your file, you can send it to me or you can post it on the NPOI forums for help. Just give an example of what you what your trying to change and the error message you get when it blows up.
#26 by IG on June 14, 2011 - 2:59 am
Hi i have tried the above and I get an object not set to an instance errror. I have tried GetCell and CreateCell and both give same error. My code is below, any ideas where im going wrong? Many thanks
Dim fs As New FileStream(Server.MapPath(“Template.xls”), FileMode.Open, FileAccess.Read)
Dim templateWorkbook As New HSSFWorkbook(fs, True)
Dim sheet As HSSFSheet = templateWorkbook.GetSheet(“Sheet1”)
sheet.GetRow(1).GetCell(2).SetCellValue(“test”)
sheet.GetRow(1).CreateCell(1).SetCellValue(“test”)
#27 by Zach on June 14, 2011 - 6:10 pm
Do you know if your row exists yet, maybe row #1 does not exist yet and you need to add it. You might test by creating a sheet with a bunch of rows of data and try changing one of the existing values.
#28 by Matt on June 9, 2011 - 8:13 am
Or maybe it would be possible by using a macro to run PDFCreator?
http://www.excelguru.ca/node/21
#29 by Zach on June 9, 2011 - 1:51 pm
After looking at this link, it looks like it would be possible to create a clunky conversion routine but it would fail if you have 1+ users trying to download a PDF at the same time. It also looks like it will generate a static file to disk, versus creating a PDF on the fly in memory. ASPOSE is the only product I know right now that can convert XLS to PDF in memory, which would be my preferred way. Have you considered a different solution, like using Reporting Services? Depending on what your building, it may be a good option for you. It’s very easy to use and it’s easy to wrap in ASP.NET so it looks fully integrated into your web application.
#30 by Matt on June 9, 2011 - 7:52 am
A previous comment mentioned using NPOI and a PDF library.
Staying in the open source world, would it be possible to use a tool like PDFCreator to convert the excel file to a pdf in code behind, and thereby offer a PDF for download? http://www.pdfforge.org/pdfcreator
I saw a comment in a stackoverflow post about making use of the PrintDocument class. http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx
Presenting the options of both XLS download and PDF download
would be pretty cool.
#31 by Matt on June 6, 2011 - 6:00 pm
First, thanks for writing articles on NPOI.
I had some trouble getting the code working, as posted here.
http://stackoverflow.com/questions/6259509/error-attempting-to-use-npoi-to-fill-excel-template
Also, I’m curious as how to handle NPOI if you’re using ASP.NET and you have a multiple datatables, some of which could have hundreds of rows…
#32 by Zach on June 7, 2011 - 7:29 am
I primarily use NPOI for ASP.NET (99% of the time). Your limits (sheets & rows) are limited by the BIFF (xls) format specification. Since everything is going to be processed in memory, I like to pull out my data first then use the data to populate my worksheets. I’ve never had a problems loading multiple worksheets, and I’ve even filled workbooks that with 10 tabs of ~60K rows each without any issues. If you run into a specific problem, let me know… NPOI is your best (and FREE) solution for using Excel (XLS) in ASP.NET.
#33 by Ari on March 2, 2011 - 8:15 pm
I m new using NPOI and just try an example from NPOI (GenerateXlsFromXlsTemplate) and running well; but i found bug : Object reference not set to an instance of an object, if i change :
sheet1.GetRow(2).GetCell(1).SetCellValue(300);
with
sheet1.GetRow(1).GetCell(2).SetCellValue(300);
it seems the row 1, cell 2 (cell C2) not created / detected yet.
How to activated that cell in excel template then?
#34 by Zach on March 2, 2011 - 11:57 pm
So your trying to insert a value into A3 (row 1, cell 3) but your getting a object error. This can happen when the cell is not initialized yet, if you change the code to sheet1.GetRow(1).CreateCell(2) it will probably solve your problem. Anytime I’m editing an exiting file, I always check if the cell exists before trying to manipulate it.
#35 by Seiko on February 21, 2011 - 1:49 am
I managed to create a template and use it to generate new .xls files. The problem is NPOI seem to be failing to pick the values that that were inserted into the template when i try to read the file again. But it’s picking the values that were part of the template. Any Help will be most welcome guys.
#36 by Zach on February 22, 2011 - 8:58 am
Hard to tell without any code, can you post an excerpt of where your trying to update/insert data into your template with NPOI. Have you tried an example/sample posted online? I use NPOI with templates all the time, so I know it works.
#37 by PKSpence on February 2, 2011 - 11:16 am
@hiep
Are you trying to add an new row at the bottom of the worksheet? If so, this will do it (ws is a worksheet contained a workbook)
// create the row
HSSFRow row = ws.CreateRow(ws.LastRowNum + 1);
// populate the 1st two columns
row.CreateCell(0).SetCellValue = “hello”;
row.CreateCell(1).SetCellValue = “world”;
#38 by hiep on December 3, 2010 - 1:49 am
I tried to insert a new row in excel file contains data, but it does not automatically add new row, the data in the file is deleted, how do you fix this. please show me
mail to me if you can. PLEASE !!!
#39 by eka on September 29, 2010 - 4:04 pm
1. sorry for dummy question, can i use on my desktop c# project ?
2. with this, can i create new row in the existing xls template ?
thanks before.
#40 by Zach on October 6, 2010 - 8:13 am
Eka,
Yes, you can use any type of C# project (Console, Web, etc…). As for creating a new row in your template, this is possible. All your template realy is, is a nicely formatted XLS documents. Using NPOI, you can edit this instance of the XLS document anyway you want (e.g. Add rows, delete cell, etc…). If your planning to create a dynamic number of rows (example load from 5-100 rows) and you want them all formatted nice, you should see the article on the NPOI website.
Zach
#41 by Zach on July 27, 2010 - 7:05 am
email me a copy of your sheet zachary dot hunter at gmail.com an I’ll try debugging it. I’ve not had any problems opening/reading XLS data for awhile, so without more details I’m not sure what it could be. Just make sure your using the latest build, since there has been some important bug fixes…
#42 by Shock on July 26, 2010 - 4:39 am
Hi, I have a problem. My excel templates do not load correctly, I mean that I get null reference exception. When I use your template – everything works fine. When I created a new sheet in your template and tried to load it – the same error ocurred. Can you tell me, is there any hidden option which allows to correctly load templates to NPOI or what am I doing wrong ??/
Thanks in advance
#43 by Dane on July 16, 2010 - 7:32 am
Thank you for this article. I was able to get NPOI to work with your help. Right now my code returns my populated template to the user in a httpresponse object and they can save it, however I want to convert it to pdf. I have the pdfconversion all working fine with a test.xls file that I have on my server, but I can’t seem to figure out how to programmatically save the HSSFworkbook as an excel file rather than delivering it to the user so I can do the conversion all in the background. Any ideas for me? Again thanks for this article it really was golden.
#44 by Zach on July 20, 2010 - 1:31 pm
I’m not sure which PDF library you are using, but if you want to put your workbook into a memory stream to then convert into a PDF, then create a “MemoryStream” and call “workbook.write(memorystream)” to load it with your XLS file. Now that you have a XLS file in memory, you can use your PDF to put the file to PDF.
Let me know if you have any more questions.
#45 by samiran on June 2, 2010 - 3:39 am
hey zach i got your mail and have done it successfully..thanks a lot for this example and ur quick response..u rock
#46 by Zach on May 28, 2010 - 8:54 am
samiran i’ve replied to your email, give me a bit more details and I’ll try to help out. the example is based on inserting data into existing cells/rows in a template, if your trying to add/insert something based on rows I’m not sure what your referring to.
#47 by samiran on May 28, 2010 - 12:54 am
hiee i have downloaded and tired your source code but i am unable to create more then 54 rows. please help its very urgent. if possible reply me in my mail..
Thanks in advance.