Basic question: How do I load an Excel template for use with POI and then save it to an XLS file?
Edit:
The answer is:
FileInputStream inputStream = new FileInputStream(new File(templateFile));
Workbook workbook = new HSSFWorkbook(inputStream);
(Just load the template as a workbook and then write the workbook as an XLS file elsewhere.)
You can directly load an .xls that will act as the template, and modify it.
POIFSFileSystem fs = new POIFSFileSystem(
new FileInputStream("template.xls"));
HSSFWorkbook wb = new HSSFWorkbook(fs, true);
Will load an xls, preserving its structure (macros included). You can then modify it,
HSSFSheet sheet1 = wb.getSheet("Data");
...
and then save it.
FileOutputStream fileOut = new FileOutputStream("new.xls");
wb.write(fileOut);
fileOut.close();
Hope this helps.
Have you tried loading it up as a standard .xls using POI, amending it and then saving it ?
This is the approach I've used for inserting macros in a POI-generated .xls. I create the file with the macro (admittedly as an .xls) and then load it into my app, populate with data and save as a newly-created .xls. That all worked fine.
You can also use internal template as a resource.
InputStream fis = ChartSample.class.getResourceAsStream("/templates.xls");
HSSFWorkbook wb = new HSSFWorkbook(fis);
fis.close();
HSSFSheet sh = wb.getSheetAt(0);
//Here you go
And save that:
out = new FileOutputStream("./new.xls");
wb.write(out);
out.close();
You can create a XLS file from a XLS template.
But, to do this, you need to create a copy of the template every time you need to use the template. If not, you will edit the original template (what you not want).
So, you need first get your template file:
URL url = Thread.currentThread().getContextClassLoader().getResource("templates/template.xls");
File file = new File(url.getPath());
Copy the template file:
try (FileOutputStream fileOutputStream = new FileOutputStream("/home/jake/fileCopiedFromTemplate.xls")) {
Files.copy(file.toPath(), fileOutputStream);
Workbook workbook = new HSSFWorkbook();
workbook.write(fileOutputStream);
}
Access the new copied file:
FileInputStream inp = new FileInputStream("/home/jake/fileCopiedFromTemplate.xls");
Create a Workbook, so you can write in your new file:
Workbook workbook = WorkbookFactory.create(inp);
After write in your workbook:
try (FileOutputStream fileOut = new FileOutputStream("/home/jake/fileCopiedFromTemplate.xls")) {
workbook.write(fileOut);
}
A tip to create a XLS template file is mark the template with some variable for you localize the position that you would like to fill. Like:
------------------------------------
| | Columna A | Column B |
------------------------------------
| 1 | Some description |
------------------------------------
| 2 | {person.name} | {person.age} |
------------------------------------
For excel-files with .xlsx use the following:
FileInputStream inputStream = new FileInputStream(new File("template.xlsx"));
#SuppressWarnings("resource")
Workbook wb = new XSSFWorkbook(inputStream);
Sheet sheet = wb.getSheet("sheet1");
You can use XSSF by adding poi-ooxml dependency in your maven pom.xml if you want to save it in 2007+ format.
If you have template.xlsx file with a summary sheet in this xmls and you want to change a particular cell you can do it as:
XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream("template.xlsx"));
FileOutputStream fileOut = new FileOutputStream("new.xlsx");
XSSFSheet sheet1 = wb.getSheet("Summary");
XSSFRow row = sheet1.getRow(15);
XSSFCell cell = row.getCell(3);
cell.setCellValue("Bharthan");
wb.write(fileOut);
log.info("Written xls file");
fileOut.close();
Related
try {
File file = new File("file4.xls");
if (!file.exists()) file.createNewFile();
FileInputStream fis = new FileInputStream(file);
POIFSFileSystem fileSystem = new POIFSFileSystem(fis);
// FileInputStream fis = new FileInputStream(file);
HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
//Sheet sheet = workbook.createSheet("sheet0");
Sheet sheet = workbook.getSheet("sheet1");
sheet.createRow(0).createCell(0).setCellValue("HelloWorld");
Cell cell = sheet.createRow(1).createCell(0);
cell.setCellValue("Value_1_1");
fis.close();
FileOutputStream fos = new FileOutputStream(file);
workbook.write(fos);
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
I am trying to create simple excel file using java. I am getting above mentioned error.
Open the file once.
Check your file once on click save as. If it is generated from HTML it will show as Web page(*.htm , .html) below drop down to the file.
You can save as Excel 97-2003 Workbook (.xls) and retry to read from code. It worked in my case.
Your problem is this line here:
if (!file.exists()) file.createNewFile();
That creates a brand new 0 byte file, which is not a valid Excel file. That's why POI objects.
Also, you're using an old version of Apache POI. Newer ones give a more helpful exception if you're silly enough to ask them to read a zero byte file
Taking account of the advice on Files vs InputStreams, but noting you're doing an in-place write which isn't yet fully supported on an opened File, change your code to be more like:
Workbook workbook = null;
File file = new File("file4.xls");
if (!file.exists()) {
if (file.toString().endsWith(".xlsx")) {
workbook = new XSSFWorkbook();
} else {
workbook = new HSSFWorkbook();
}
} else {
workbook = WorkbookFactory.create(new FileInputStream(file));
}
That will work for both .xls and .xlsx files, and avoids your errro
Though you really ought to upgrade your version of Apache POI too...
I don't know why the file I write using POI cant be opened by Ms Excel 2013, but the file is still readable by POI. (cell value can be changed)
this is the error from file
here is the code
FileInputStream fis = null;
try {
fis = new FileInputStream(fileUri); //not error at fileUri
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String urii = fileUri.replace(".xls", "0.xls"); //not error
File fisx = new File(urii);
Workbook workbook = null;
workbook = new HSSFWorkbook(fis);
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
String p = cell.getStringCellValue();
TextView a = (TextView) findViewById(R.id.txtUri);
cell.setCellValue(new String("popo"));
String x = cell.getStringCellValue();
TextView b = (TextView) findViewById(R.id.txtFile);
a.setText(p);
b.setText(x);
OutputStream fos = null;
fos = new FileOutputStream(fisx);
workbook.write(fos); //main problem
fos.flush();
fos.close();
Thanks for your help!!
There are two issues with your code. Firstly this:
FileInputStream fis = null;
try {
fis = new FileInputStream(fileUri);
As explained in the Apache POI Docs, don't use an InputStream if you have a File!
Secondly, this:
Workbook workbook = null;
workbook = new HSSFWorkbook(fis);
That will only work for .xls files, not for .xlsx ones. Instead, you need to use WorkbookFactory which identifies the type and gives you the right workbook for the format
So, change your code to be
File file = new File(fileUri);
Workbook workbook = WorkbookFactory.create(file);
The major problem that i see here is:
Workbook workbook = null;
workbook = new HSSFWorkbook(fis);
Instead you have to use:
Workbook workbook = null;
workbook = new XSSFWorkbook(fis);
TO be readable by MS EXCEL 2013.
Solved :
by using real android device instead of bluestack emulator,
I dont know why, but it works!!
Thanks everyone :D
You are calling getSheetAt(0) but you did not create any sheet before (workbook.createSheet(“name”)
The solution is to use the .xls extension and NOT .xlsx, as outlined in this answer
I'm trying to change value of cell in .xls document.
In .xls file i have got only 1 cell - A1 with abc value inside.
My code:
File fo = new File("D:\\TMP\\Zeszyt1.xls");
HSSFWorkbook a = new HSSFWorkbook(new FileInputStream(fo));
HSSFSheet my_sheet = a.getSheetAt(0);
HSSFRow my_row = my_sheet.getRow(0);
HSSFCell myCell;
myCell = my_row.getCell(0);
myCell.setCellValue("NEW VALUE");
How to commit this changes? When i open .xls file i still have got abc value inside A1.
You have to write to the file.
FileOutputStream outputStream = new FileOutputStream(new File("abc.xls"));
workbook.write(outputStream);
outputStream.close();//Close in finally if possible
When I try to open a .xlsx file in POI, I get an exception:
java.lang.IllegalArgumentException: The supplied POIFSFileSystem does not contain a BIFF8 'Workbook' entry. Is it really an excel file?
at org.apache.poi.hssf.usermodel.HSSFWorkbook.getWorkbookDirEntryName(HSSFWorkbook.java:223)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:245)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:188)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:170)
InputStream input = new BufferedInputStream( new FileInputStream(fileName));
POIFSFileSystem file = new POIFSFileSystem( input );
//Create Workbook instance holding reference to .xls file
HSSFWorkbook wb = new HSSFWorkbook(file);
//Get first/desired sheet from the workbook
HSSFSheet sheet = wb.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
just trying to read the data that .xls file contain but cannot open it !
Don't create an HSSFWorkbook on a .xlsx file. An HSSFWorkbook represents an .xls file, and an XSSFWorkbook represents an .xlsx file.
In fact, usually your code doesn't even need to know which it's working with. Create your Workbook with WorkbookFactory, as this example from the Busy Developer's Guide shows:
// Use a file
Workbook wb = WorkbookFactory.create(new File("MyExcel.xls"));
// Use an InputStream, needs more memory
Workbook wb = WorkbookFactory.create(new FileInputStream("MyExcel.xlsx"));
If you must, you can create an XSSFWorkbook directly:
XSSFWorkbook wb = new XSSFWorkbook(inputStream); // You can use a FileInputStream
or with an OPCPackage.
OPCPackage pkg = OPCPackage.open(myInputStream);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
I'm a little confused, I used to do this:
HSSFWorkbook wb = new HFFSWorkbook();
But with the new POI, I dont have to do that.
I can't do this:
Workbook wb = new Workbook();
I understand WorkbookFactory.create, but that is for opening a file.
How do I set up a new workbook with this ss model?
You can still use the SS model but need to decide on the file format at the time of creation.
For xls -> Workbook wb = new HSSFWorkbook();
For xlsx -> Workbook wb = new XSSFWorkbook();
In "New POI", you can write/read both XLS files and XLSX files. In any case, for XLS file-format you were using:
HSSFWorkbook wb = new HSSFWorkbook();
So for XLSX file-format, you have to use:
XSSFWorkbook wb = new XSSFWorkbook();
// you could also do below
// Workbook wb = new XSSFWorkbook();
Also it would be helpful for you if you refer below links for starting with XLS to XLSX migration.
1. http://poi.apache.org/apidocs/org/apache/poi/xssf/usermodel/XSSFWorkbook.html
2. http://poi.apache.org/spreadsheet/converting.html
Make sure you download and add the POI JAR file to your project’s class path before running the code. The Apache POI JAR file can be found here.
public void main(String[] args) throws IOException {
// Directory path where the xls file will be created
String destinationFilePath = "C:/Users/devesh_/Documents/HelloWorld.xls";
// Create object of FileOutputStream
FileOutputStream fout = new FileOutputStream(destinationFilePath);
// Build the Excel File
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
HSSFWorkbook workBook = new HSSFWorkbook();
// Create the spreadsheet
HSSFSheet spreadSheet = workBook.createSheet("Hello_World");
// Create the first row
HSSFRow row = spreadSheet.createRow((short) 0);
// Create the cells and write to the file
HSSFCell cell;
// Write Hello
cell = row.createCell(0);
cell.setCellValue(new HSSFRichTextString("Hello"));
// Write World
cell = row.createCell(1);
cell.setCellValue(new HSSFRichTextString("World"));
workBook.write(outputStream);
outputStream.writeTo(fout);
outputStream.close();
fout.close();
}
When creating a file, you need to decide up front what format it'll be - you can't just wait until write-out time to do that. You code would be something like:
Workbook wb = null;
if (shouldBeXLS) {
wb = new HSSFWorkbook();
} else {
wb = new XSSFWorkbook();
}
// work on the file in a generic way
// save, with a suitable name
String filename = "test.xls";
if (!shouldBeXLS) { filename = filename + "x"; }
FileOutputStream fout = new FileOutputStream(filename);
wb.write(fout);
fout.close();
At the start, decide what format you want for this particular instance, and create that. Treat it as a general workbook, and write to it in the common way. At the end, remember what it is so you can give the file the right extension!
(When reading a file in, WorkbookFactory will let you load the appropriate instance for the file type. When creating a new file, you have to pick yourself as there's nothing there yet!)