Apache POI throwing IOException when reading XLSX workbook - java

I'm trying to get the following code to run and am getting an IOException:
String cellText = null;
InputStream is = null;
try {
// Find /mydata/myworkbook.xlsx
is = new FileInputStream("/mydata/myworkbook.xlsx");
is.close();
System.out.println("Found the file!");
// Read it in as a workbook and then obtain the "widgets" sheet.
Workbook wb = new XSSFWorkbook(is);
Sheet sheet = wb.getSheet("widgets");
System.out.println("Obtained the widgets sheet!");
// Grab the 2nd row in the sheet (that contains the data we want).
Row row = sheet.getRow(1);
// Grab the 7th cell/col in the row (containing the Plot 500 English Description).
Cell cell = row.getCell(6);
cellText = cell.getStringCellValue();
System.out.println("Cell text is: " + cellText);
} catch(Throwable throwable) {
System.err.println(throwable.getMessage());
} finally {
if(is != null) {
try {
is.close();
} catch(IOException ioexc) {
ioexc.printStackTrace();
}
}
}
The output from running this in Eclipse is:
Found the file!
Stream Closed
java.io.IOException: Stream Closed
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:236)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at java.io.PushbackInputStream.read(PushbackInputStream.java:186)
at java.util.zip.ZipInputStream.readFully(ZipInputStream.java:414)
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:247)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:91)
at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:51)
at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:83)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:267)
at org.apache.poi.util.PackageHelper.open(PackageHelper.java:39)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:204)
at me.myorg.MyAppRunner.run(MyAppRunner.java:39)
at me.myorg.MyAppRunner.main(MyAppRunner.java:25)
The exception is coming from the line:
Workbook wb = new XSSFWorkbook(is);
According to the XSSFWorkbook Java Docs this is a valid constructor for an XSSFWorkbook object, and I don't see anything "jumping out" at me to indicate that I'm using my InputStream incorrectly. Can any POI gurus help spot where I'm going awrye? Thanks in advance.

The problem is simple:
is = new FileInputStream("/mydata/myworkbook.xlsx");
is.close();
You are closing your output stream before passing it to the constructor and it cannot be read.
Simply delete the is.close() here to fix the issue, as it will be cleaned up in the finally statement at the end.

you are closing the stream is.close();
and then using it, don't close it until you have used it.

As the others have pointed out, you are closing your InputStream which is breaking things
However, you really shouldn't be using an InputStream in the first place! POI uses less memory when given the File object directly rather than going through an InputStream.
I'd suggest you have a read through the POI FAQ on File vs InputStream, then change your code to be:
OPCPackage pkg = OPCPackage.open(new File("/mydata/myworkbook.xlsx"));
Workbook wb = new XSSFWorkbook(pkg);

Related

Excel POI Unexpected missing row when some rows already present

Someone have already seen this error ?
I get it just when I create my HSSFWorkbook
try {
LOGGER.info("Open Excel file: " + filename);
InputStream inputStream = new FileInputStream(filename);
Workbook wb = new HSSFWorkbook(inputStream);
Sheet sheet = wb.getSheetAt(0);
/* save excel */
FileOutputStream fileOut = new FileOutputStream(filenameOutput);
wb.write(fileOut);
fileOut.close();
wb.close();
inputStream.close();
} catch (IOException e1) {
LOGGER.log(Level.SEVERE, e1.getMessage(), e1);
}
error is on new HSSFWorkbook(inputstream)
Exception in thread "main" java.lang.RuntimeException: Unexpected missing row when some rows already present
at org.apache.poi.hssf.usermodel.HSSFSheet.setPropertiesFromSheet(HSSFSheet.java:212)
at org.apache.poi.hssf.usermodel.HSSFSheet.<init>(HSSFSheet.java:137)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:338)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:289)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:224)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:382)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:364)
Any idea ?
I have seen this question on http://apache-poi.1045710.n5.nabble.com/Unexpected-missing-row-when-some-rows-already-present-td5527417.html but they don't give good answer
I use POI 3.12
UPDATE : My excel contain 53 rows and hundreds columns so he is not empty. The excel was generated with Buisness Object and some people have the very same issues with no solution.
Source code of HSSFSheet is here
Ok I've found the solution.
Upgrade to 3.14 solve the problem.
The exception in 3.13 and previous is generated by this code
RowRecord row = sheet.getNextRow();
boolean rowRecordsAlreadyPresent = row != null;
207 if (hrow == null) {
208 // Some tools (like Perl module Spreadsheet::WriteExcel - bug 41187) skip the RowRecords
209 // Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too.
210 if (rowRecordsAlreadyPresent) {
211 // if at least one row record is present, all should be present.
212 throw new RuntimeException("Unexpected missing row when some rows already present");
213 }
But on 3.14 they just comment it
if (hrow == null) {
/* we removed this check, see bug 47245 for the discussion around this
// Some tools (like Perl module Spreadsheet::WriteExcel - bug 41187) skip the RowRecords
// Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too.
if (rowRecordsAlreadyPresent) {
// if at least one row record is present, all should be present.
throw new RuntimeException("Unexpected missing row when some rows already present");
}*/
// create the row record on the fly now.
RowRecord rowRec = new RowRecord(cval.getRow());
sheet.addRow(rowRec);
hrow = createRowFromRecord(rowRec);
}
As they said, some tools skip the RowRec, in my case it's when i generate my .xls with Buisness Object
example:
Workbook workbook = null;
try {
workbook = WorkbookFactory.create(is);
} catch (IOException e) {
e.printStackTrace();
} catch (InvalidFormatException e) {
e.printStackTrace();
}
Sheet sheet = workbook.getSheetAt(0);
XSSF or HSSF doesn't matter, both should work well.

Write captured data to Excel using java

In my below script, an Excel is created but failed to write the data to the sheet. Could anybody sort this out.
FileOutputStream fo = new FileOutputStream("D:\\Output.xls");
WritableWorkbook wb = Workbook.createWorkbook(fo);
WritableSheet ws = wb.createSheet("Sheet1",0);
String OutText = driver.findElement(By.xpath("gbqfqdss")).getText();
int y=0;
Label label1 = new Label(0,y,OutText);
ws.addCell(label1);
Thread.sleep(1000);
//System.out.print(OutText);
wb.write();
y++;
Thread.sleep(1000);
driver.findElement(By.id("gbqfq")).clear();
Thread.sleep(1000);
}
wb.close();
driver.quit();
With the same code, working fine in my lappy.
How you are confirming that it is not writing to excel sheet?
Mostly the cause should be "OutText" string value which is coming from getText() is null/blank value.
Try to print the value of string first & see.
Try the examples in the following link-:
http://howtodoinjava.com/2013/06/19/readingwriting-excel-files-in-java-poi-tutorial/

Null pointer exception with jexcel while writing

I need to append contents to an existing excel file using JExcel.
I am trying the following approach:
Read from existing workbook
workbook = Workbook.getWorkbook(new File(errorFilePath));
Create writable workbook from exisitng workbook into a temp file
if (!tempFile.exists()) {
tempFile.getParentFile().mkdirs();
tempFile.createNewFile();
}
newCopy = Workbook.createWorkbook(tempFile, workbook);
excelSheet = newCopy.getSheet(0);
Write to writable workbook(times is a writable cell format variable)
Label label;
label = new Label(column, row, stringData, times);
excelSheet .addCell(label);
Close both exisitng and writable workbook->Delete exisitng workbook
in finally block -> Rename temp file name to existing(now deleted) workbook name
finally {
if (null != newCopy) {
newCopy.write();
newCopy.close();
}
if (null != workbook) {
workbook.close();
}
if (null != errorFile && errorFile.exists()) {
errorFile.delete();
}
if (null != tempFile) {
tempFile.renameTo(new File(errorFilePath));
}
}
The problem is everything works fine for the first run(without redeploying).
But whenever I change some java code, and the web application redeploys I get a null pointer exception while closing the newly created workbook(after writing).
I am getting the following stack trace(originating from line newCopy.write())
java.lang.NullPointerException
at jxl.write.biff.CellValue.getData(CellValue.java:259)
at jxl.write.biff.LabelRecord.getData(LabelRecord.java:141)
at jxl.biff.WritableRecordData.getBytes(WritableRecordData.java:71)
at jxl.write.biff.File.write(File.java:147)
at jxl.write.biff.RowRecord.writeCells(RowRecord.java:329)
at jxl.write.biff.SheetWriter.write(SheetWriter.java:479)
at jxl.write.biff.WritableSheetImpl.write(WritableSheetImpl.java:1514)
at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:950)
Java Version : 1.6
JExcel Version : 2.6.10
Windows 7
Well, first suspicion is, in this line:
label = new Label(column, row, stringData, times);
you pass null argument(s).
I faced the same issue.
I was trying to add rows to the sheet dynamically in a loop using insertRow. After spending several hours it was probably a bug in the latest version of jxl api.
JXL api after 2.6.9 seem to have bug in insertRow. I switched to 2.6.9 from 2.6.12.

POI - Excel remains held by some process and cannot be edited

I am using POI to read,edit and write excel files.
My process flow is like write an excel, read it and again write it.
Then if I try to edit the file using normal desktop excel application while my Java app is still running, the excel cannot be saved, it says some process is holding the excel,
I am properly closing all file handles.
Please help and tell me how to fix this issue.
SXSSFWorkbook wb = new SXSSFWorkbook(WINDOW_SIZE);
Sheet sheet = getCurrentSheet();//stores the current sheet in a instance variable
for (int rowNum = 0; rowNum < data.size(); rowNum++) {
if (rowNum > RECORDS_PER_SHEET) {
if (rowNum % (RECORDS_PER_SHEET * numberOfSheets) == 1) {
numberOfSheets++;
setCurrentSheet(wb.getXSSFWorkbook().createSheet());
sheet = getCurrentSheet();
}
}
final Row row = sheet.createRow(effectiveRowCnt);
for (int columnCount = 0; columnCount < data.get(rowNum).size(); columnCount++) {
final Object value = data.get(rowNum).get(columnCount);
final Cell cell = row.createCell(columnCount);
//This method creates the row and cell at the given loc and adds value
createContent(value, cell, effectiveRowCnt, columnCount, false, false);
}
}
public void closeFile(boolean toOpen) {
FileOutputStream out = null;
try {
out = new FileOutputStream(getFileName());
wb.write(out);
}
finally {
try {
if (out != null) {
out.close();
out = null;
if(toOpen){
// Open the file for user with default program
final Desktop dt = Desktop.getDesktop();
dt.open(new File(getFileName()));
}
}
}
}
}
The code looks correct. After out.close();, there shouldn't be any locks left.
Things that could still happen:
You have another Java process (for example hanging in a debugger). Your new process tries to write the file, fails (because of process 1) and in the finally, it tries to open Excel which sees the same problem. Make sure you log all exceptions that happen in wb.write(out);
Note: The code above looks correct in this respect, since it only starts Excel when out != null and that should only be the case when Java could open the file.
Maybe the file wasn't written completely (i.e. there was an exception during write()). Excel tries to open the corrupt file and gives you the wrong error message.
Use a tool like Process Explorer to find out which process keeps a lock on a file.
I tried all the options. After looking thoroughly, it seems the problem is the Event User model.
I am using the below code for reading the data:
final OPCPackage pkg = OPCPackage.open(getFileName());
final XSSFReader r = new XSSFReader(pkg);
final SharedStringsTable sst = r.getSharedStringsTable();
final XMLReader parser = fetchSheetParser(sst);
final Iterator<InputStream> sheets = r.getSheetsData();
while (sheets.hasNext()) {
final InputStream sheet = sheets.next();
final InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
I assume the excel is for some reason held by this process for some time. If I remove this code and use the below code:
final File file = new File(getFileName());
final FileInputStream fis = new FileInputStream(file);
final XSSFWorkbook xWb = new XSSFWorkbook(fis);
The process works fine an the excel does not remain locked.
I figured it out actually.
A very simple line was required but some some reason it was not explained in the New Halloween Document (http://poi.apache.org/spreadsheet/how-to.html#sxssf)
I checked the Busy Developer's Guide and got the solution.
I needed to add
pkg.close(); //To close the OPCPackage
This added my code works fine with any number of reads and writes on the same excel file.

Why do I failed to read Excel 2007 using POI?

When I try to initialize a Workbook object I always get this error:
The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
But I followed the office sample to do this, following is my code:
File inputFile = new File(inputFileName);
InputStream is = new FileInputStream(inputFile);
Workbook wb = new XSSFWorkbook(is);
Exception occurs at code line:
Workbook wb = new XSSFWorkbook(is);
Here is POI jar including:
poi-3.8-20120326.jar
poi-ooxml-3.8-20120326.jar
poi-ooxml-schemas-3.8-20120326.jar
xmlbeans-2.3.0.jar
Can any guys give me guidance? An example showing how to read a complete Excel 2007 document will be appreciated. Thanks in advance!
I assume that you have recheck that your original file is indeed in Office 2007+XML format, right?
Edit:
Then, if you are sure the format is ok, and it works for you using the WorkbookFactory.create, you can find the answer in the code of such method:
/**
* Creates the appropriate HSSFWorkbook / XSSFWorkbook from
* the given InputStream.
* Your input stream MUST either support mark/reset, or
* be wrapped as a {#link PushbackInputStream}!
*/
public static Workbook create(InputStream inp) throws IOException, InvalidFormatException {
// If clearly doesn't do mark/reset, wrap up
if(! inp.markSupported()) {
inp = new PushbackInputStream(inp, 8);
}
if(POIFSFileSystem.hasPOIFSHeader(inp)) {
return new HSSFWorkbook(inp);
}
if(POIXMLDocument.hasOOXMLHeader(inp)) {
return new XSSFWorkbook(OPCPackage.open(inp));
}
throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
}
This is the bit that you were missing: new XSSFWorkbook(OPCPackage.open(inp))

Categories