Apache POI - java.lang.OutOfMemoryError - Read and Write - apache-poi

I'm facing OutOfMemoryError when I try to read, format and write a line from a xlsx file with 23MB. I have a requirement to format only the header of the file.
I've tried with InputStream, File and OPCPackage:
1)
InputStream inp = new FileInputStream(path);
XSSFWorkbook wb = (XSSFWorkbook) WorkbookFactory.create(inp);
2)
InputStream inp = new FileInputStream(path);
File file = new File(path);
Files.copy(inp, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
XSSFWorkbook wb = (XSSFWorkbook) WorkbookFactory.create(file);
3)
OPCPackage pkg = OPCPackage.open(path);
XSSFWorkbook wb = (XSSFWorkbook) WorkbookFactory.create(pkg);
No success at all.
I have seen some examples using XSSFReader, SXSSFWorkbook, but it couldn't resolve my case because I need to overwrite the line, so I think I really need a Workbook.
Does anybody have implemented a read and write operation using Apache POI with a large xlsx file?
PS: In case the solution is to generate another file I need the format of the original file because the content is already formatted.

I updated POI version from 3.17 from "Sep, 2017" to 5.0.0 from "Jan, 2021". And also commons-compress from 1.4.1 to 1.20.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.0.0</version>
</dependency>
Now I can open the file and make changes.

Related

Not to read hidden sheets of xlsb file using XSSFBReader in apache poi

I am reading xlsb file using XSSFBReader class from apache poi library. I do not find any way to read only visible sheets of xlsb file. Currently, code reads all the sheets of xlsb file.
How to read only visible sheets using XSSFBReader ?
pkg = OPCPackage.open(filename, PackageAccess.READ_WRITE);
XSSFBReader r = new XSSFBReader(pkg);
XSSFBReader.SheetIterator it = (XSSFBReader.SheetIterator) r.getSheetsData();
while (it.hasNext()) { //This iterates over all sheets of xlsb file
InputStream is = it.next();
String sheetName = it.getSheetName();
//some processing
}

Modifying an Excel File in Google Drive with Apache POI

I need to modify some cells of an Excel file stored in Google Drive. I'm using Apache POI to manipulate the Excel file and I can read and modify the file, but when I commit it to Google Drive it seems to work, it returns a success code but the file is not changed in Drive. The function I'm using to save the file is:
ParcelFileDescriptor file=result.getDriveContents().getParcelFileDescriptor();
InputStream in=new FileInputStream(file.getFileDescriptor());
HSSFWorkbook wb = new HSSFWorkbook(in);
for(Componente c:listaComponentes){
HSSFSheet sheet=wb.getSheetAt(c.getHoja());
HSSFRow fila=sheet.getRow(c.getFila());
fila.getCell(celdaSerie).setCellValue(c.getSerie());
}
FileOutputStream fileOut = new FileOutputStream(file.getFileDescriptor());
wb.write(fileOut);
result.getDriveContents().commit(mGoogleApiClient, null);

to read a big excel file in java

I am trying to read a excel file through java apache poi in netbeans containing about 8000 columns and 1200 rows for which I am getting the following exception. I have also tried to increase the heap size in netbeans with –Xmx2048m but it doesn’t help me out.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3039)
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3060)
at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3250)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportStartTag(Piccolo.java:1082)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseAttributesNS(PiccoloLexer.java:1802)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseOpenTagNS(PiccoloLexer.java:1521)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseTagNS(PiccoloLexer.java:1362)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXMLNS(PiccoloLexer.java:1293)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXML(PiccoloLexer.java:1261)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.yylex(PiccoloLexer.java:4808)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yylex(Piccolo.java:1290)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yyparse(Piccolo.java:1400)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:714)
at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3439)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1270)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1257)
at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:188)
at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:180)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:300)
at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:159)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:221)
at testdoc.Testdoc.main(Testdoc.java:26)
Java Result: 1
BUILD SUCCESSFUL (total time: 49 seconds)
The line no 26 is
File excel = new File ("E:\\Project\\Rapid out\\"+filename+""+type+".xlsx");
FileInputStream fis = new FileInputStream(excel);
Line 26:: XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet ws = wb.getSheet("Sheet2");
Instead of using InputStream, can you try with File:
XSSFWorkbook wb = new XSSFWorkbook(excel);
From POI Guide
When opening a workbook, either a .xls HSSFWorkbook, or a .xlsx XSSFWorkbook, the Workbook can be loaded from either a File or an InputStream. Using a File object allows for lower memory consumption, while an InputStream requires more memory as it has to buffer the whole file.

Protect a sheet results in a corrupt workbook

I want to copy an Excel Workbook with apache poi. The copy must be protected but the user should be able to resize the columns. I prepared a template and picked "columns format" on the first sheet in the template. When I use the following snippet
InputStream is = new FileInputStream(
new File(DIR, "template.xlsx"));
XSSFWorkbook wb = (XSSFWorkbook) WorkbookFactory.create(is);
XSSFSheet s = wb.getSheetAt(0);
s.protectSheet("");
FileOutputStream os = new FileOutputStream(new File(DIR, "test.xlsx"));
wb.write(os);
os.close();
I get a corrupt Excelsheet. I use apache poi 3.8 and Excel 2007.
Is there a workaround for protecting the sheets but allow to resize the columns?
Any help would be greatly appreciated
stephan
I know this is an old post, but I just solved this problem. You can use the following code:
//just initialize these
XSSFWorkbook xwb;
XSSFSheet xsheet;
xsheet.protectSheet("1234");
xsheet.getCTWorksheet().getSheetProtection().setFormatColumns(false);
xsheet.enableLocking();
xwb.lockStructure();
Hope this helps somebody in the future! :D

Creating excel sheet from template in Java, new versions of Excel

I found the following code to create a excel sheet from an existing template with formats and add data to it and save it to a new file
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();
This works absolutely fine. But my issue is that I am dealing with new versions of excel now. So I need to develop a similar code to handle new version of template. Can someone suggest how can I do this? I tried changing HSSWorkbook to XSSFWorkbook. however XSSFWorkbook doesn't have a constructor that lets me pass a boolean. Also. when i tried it, it copies the data but the rows with data do not retain the formatting of the columns that the template has.
This should work fine (though it's always best to use the latest version of POI for all the bug fixes):
Workbook wb = new XSSFWorkbook( OPCPackage.open("template.xlsx") );
Sheet sheet = wb.getSheetAt(0);
// Make changes to the sheet
sheet.getRow(2).getCell(0).setCellValue("Changed value"); // For example
// All done
FileOutputStream fileOut = new FileOutputStream("new.xls");
wb.write(fileOut);
fileOut.close();
If you code against the interfaces, then you can just swap between HSSF and XSSF in your constructor, and have your code work for both formats
I used XSSF and it is working fine.
XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream("template.xlsx"));
FileOutputStream fileOut = new FileOutputStream("new.xlsx");
//Sheet mySheet = wb.getSheetAt(0);
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();
Just need to add this dependency in pom.xml of maven
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8-beta4</version>
</dependency>

Resources