Expanding an existing table in Excel using Apache POI - java

I've got an table in excel with formulae I would like to add data to.
My motivation for this is the fact that tables in excel can dynamically expand to the range of data you add to them, meaning that the formula rows automatically keep up with the amount of data rows.
I'm however having a hard time finding out if this is possible using apache-POI.
One thing I was going to try (see code below) was to expand the AreaReference of the table to cover the data, however both AreaReference(CR,CR2); (as used in this example) and AreaReference(CR,CR2, SpreadsheetVersion.EXCEL2007) (seen in the apache docs) give "constructor is undefined".
No idea what is causing that constructor error as I do have org.apache.poi.ss.util imported.
The other option on the apache docs AreaReference(java.lang.String reference) lets me compile and run but instead gives a "NoSuchMethod" error.
List<XSSFTable> tableList = spreadSheet.getTables();
CellReference CR = new CellReference(0, 0);
CellReference CR2 = new CellReference(5, 2);
AreaReference my_data_range = new AreaReference(CR,CR2);
tableList.get(0).setArea(my_data_range);
Any help will be appreciated.

The main problem using apache poi until now is that it is not ready to be used without having detailed knowledge about Microsoft Office as such and about the storage of Microsoft Office files. There are many things only half way ready and there are regressions often in new versions (bugs occur again which were solved already).
So your requirement: "Expanding an existing table in Excel using Apache POI" is not possible only simply using apache poi. One must know that Office Open XML files *.xlsx are simply ZIP archives which can be unzipped. And after unzipping we find /xl/tables/table1.xml for storage of the table. This XML we can analyzing and comparing it with XML which was created using Excel's GUI. So we can find problems which results from shortcomings of apache poi. Same is with the sheet's XML in /xl/tables/sheet1.xml.
Also we need to know that apache poi builds on the low level classes of ooxml-schemas. Partially we need using those classes because of the halfway readiness of apache poi. In the following example we need ooxml-schemas-1.4.jar additionally because apache poi's poi-ooxml-schemas-4.0.0.jar has not included org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableFormula until now. Unfortunately there is no documentation about ooxml-schemas public available. So we need downloading the sources and doing javadoc our own.
The following example works for me using apache poi 4.0.0. If you get problems while compiling or running, the reason might be that multiple different versions of apache poi jars are in class path while compile time and/or run time. Do not mix different apache poi versions. Also, as said already, my code needs the full jar of all of the schemas ooxml-schemas-1.4.jar.
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.SpreadsheetVersion;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
class ExcelExpandingTable {
static void addRowToTable(XSSFTable table) {
int lastTableRow = table.getEndCellReference().getRow();
int totalsRowCount = table.getTotalsRowCount();
int lastTableDataRow = lastTableRow - totalsRowCount;
// we will add one row in table data
lastTableRow++;
lastTableDataRow++;
// new table area plus one row
AreaReference newTableArea = new AreaReference(
table.getStartCellReference(),
new CellReference(
lastTableRow,
table.getEndCellReference().getCol()
),
SpreadsheetVersion.EXCEL2007
);
// new table data area plus one row
AreaReference newTableDataArea = new AreaReference(
table.getStartCellReference(),
new CellReference(
lastTableDataRow,
table.getEndCellReference().getCol()
),
SpreadsheetVersion.EXCEL2007
);
XSSFSheet sheet = table.getXSSFSheet();
if (totalsRowCount > 0) {
//if we have totals rows, shift totals rows down
sheet.shiftRows(lastTableDataRow, lastTableRow, 1);
// correcting bug that shiftRows does not adjusting references of the cells
// if row 3 is shifted down, then reference in the cells remain r="A3", r="B3", ...
// they must be adjusted to the new row thoug: r="A4", r="B4", ...
// apache poi 3.17 has done this properly but had have other bugs in shiftRows.
for (int r = lastTableDataRow; r < lastTableRow + 1; r++) {
XSSFRow row = sheet.getRow(r);
if (row != null) {
long rRef = row.getCTRow().getR();
for (Cell cell : row) {
String cRef = ((XSSFCell)cell).getCTCell().getR();
((XSSFCell)cell).getCTCell().setR(cRef.replaceAll("[0-9]", "") + rRef);
}
}
}
// end correcting bug
}
// if there are CalculatedColumnFormulas do filling them to the new row
XSSFRow row = sheet.getRow(lastTableDataRow); if (row == null) row = sheet.createRow(lastTableDataRow);
int firstTableCol = table.getStartCellReference().getCol();
for (CTTableColumn tableCol : table.getCTTable().getTableColumns().getTableColumnList()) {
if (tableCol.getCalculatedColumnFormula() != null) {
int id = (int)tableCol.getId();
String formula = tableCol.getCalculatedColumnFormula().getStringValue();
XSSFCell cell = row.getCell(firstTableCol + id - 1); if (cell == null) cell = row.createCell(firstTableCol + id - 1);
cell.setCellFormula(formula);
}
}
table.setArea(newTableArea);
// correcting bug that Autofilter includes possible TotalsRows after setArea new
// Autofilter must only contain data area
table.getCTTable().getAutoFilter().setRef(newTableDataArea.formatAsString());
// end correcting bug
table.updateReferences();
}
public static void main(String[] args) throws Exception {
try (Workbook workbook = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
FileOutputStream out = new FileOutputStream("SAMPLE_NEW.xlsx")) {
XSSFSheet sheet = ((XSSFWorkbook)workbook).getSheetAt(0);
XSSFTable table = sheet.getTables().get(0);
addRowToTable(table);
workbook.write(out);
}
}
}
The above was 2018. Now we have 2022.
Using current apache poi 5.2.2 the code may be like follows:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.SpreadsheetVersion;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
class ExcelExpandingTable {
static XSSFRow addRowToTable(XSSFTable table) {
int lastTableRow = table.getEndCellReference().getRow();
int totalsRowCount = table.getTotalsRowCount();
int lastTableDataRow = lastTableRow - totalsRowCount;
int firstTableCol = table.getStartCellReference().getCol();
// we will add one row in table data
lastTableRow++;
lastTableDataRow++;
// new table area plus one row
AreaReference newTableArea = new AreaReference(
table.getStartCellReference(),
new CellReference(
lastTableRow,
table.getEndCellReference().getCol()
),
SpreadsheetVersion.EXCEL2007
);
XSSFSheet sheet = table.getXSSFSheet();
if (totalsRowCount > 0) {
//if we have totals rows, shift totals rows down
sheet.shiftRows(lastTableDataRow, lastTableRow, 1);
//correct all sheet table-reference-formulas which probably got damaged after shift rows
for (CTTableColumn tableCol : table.getCTTable().getTableColumns().getTableColumnList()) {
if (tableCol.getCalculatedColumnFormula() != null) {
int id = (int)tableCol.getId();
String formula = tableCol.getCalculatedColumnFormula().getStringValue();
int rFirst = table.getStartCellReference().getRow() + table.getHeaderRowCount();
int rLast = table.getEndCellReference().getRow() - table.getTotalsRowCount();
int c = table.getStartCellReference().getCol() + id - 1;
sheet.getWorkbook().setCellFormulaValidation(false);
for (int r = rFirst; r <= rLast; r++) {
XSSFRow row = sheet.getRow(r); if (row == null) row = sheet.createRow(r);
XSSFCell cell = row.getCell(c); if (cell == null) cell = row.createCell(c);
cell.setCellFormula(formula);
}
}
}
}
// if there are CalculatedColumnFormulas do filling them to the new row
XSSFRow row = sheet.getRow(lastTableDataRow); if (row == null) row = sheet.createRow(lastTableDataRow);
for (CTTableColumn tableCol : table.getCTTable().getTableColumns().getTableColumnList()) {
if (tableCol.getCalculatedColumnFormula() != null) {
int id = (int)tableCol.getId();
String formula = tableCol.getCalculatedColumnFormula().getStringValue();
XSSFCell cell = row.getCell(firstTableCol + id - 1); if (cell == null) cell = row.createCell(firstTableCol + id - 1);
cell.getSheet().getWorkbook().setCellFormulaValidation(false); // see https://bz.apache.org/bugzilla/show_bug.cgi?id=66039
cell.setCellFormula(formula);
}
}
// copy cell styles to the new row from the row above
row = sheet.getRow(lastTableDataRow); if (row == null) row = sheet.createRow(lastTableDataRow);
XSSFRow rowAbove = sheet.getRow(lastTableDataRow - 1); if (row == null) row = sheet.createRow(lastTableDataRow - 1);
for (CTTableColumn tableCol : table.getCTTable().getTableColumns().getTableColumnList()) {
int id = (int)tableCol.getId();
XSSFCell cellAbove = rowAbove.getCell(firstTableCol + id - 1);
if (cellAbove != null) {
XSSFCellStyle styleAbove = cellAbove.getCellStyle();
XSSFCell cell = row.getCell(firstTableCol + id - 1); if (cell == null) cell = row.createCell(firstTableCol + id - 1);
cell.setCellStyle(styleAbove);
}
}
// set new table area
table.setArea(newTableArea);
// update table references
table.updateReferences();
return sheet.getRow(lastTableDataRow);
}
public static void main(String[] args) throws Exception {
try (Workbook workbook = WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
FileOutputStream out = new FileOutputStream("SAMPLE_NEW.xlsx")) {
XSSFSheet sheet = ((XSSFWorkbook)workbook).getSheetAt(0);
XSSFTable table = sheet.getTables().get(0);
XSSFRow row = addRowToTable(table);
workbook.write(out);
}
}
}
According to FAQ, this code needs poi-ooxml-full-5.2.2.jar instead of ooxml-schemas-1.4.jar now for run using apache poi 5.2.2.
Some bugs are fixed. But there is one new bug when using XSSFCell.setCellFormula when formula contains table references. But XSSFWorkbook.setCellFormulaValidation(false) avoids this.

Related

Can't change row text in .docx file once row is added to table

I have the problem with the following code:
XWPFTable table = <get table somehow>;
CTRow firstRow = table.getRow(0).getCtRow();
for (int i = 0; i < data.getRowCount(); i++) {
CTRow ctRow = (CTRow) firstRow.copy();
XWPFTableRow row = new XWPFTableRow(ctRow, table);
XWPFRun[] cellRuns = row.getTableCells()
.stream()
.map(c -> c.getParagraphs().get(0))
.map(p -> p.getRuns().isEmpty() ? p.createRun() : p.getRuns().get(0))
.toArray(XWPFRun[]::new);
for (int j = 0; j < cellRuns.length; j++) {
cellRuns[j].setText(data.getValueAt(i, j).toString(), 0);
}
table.addRow(row);
}
table.getRow(1).getTableCells()
.get(0).getParagraphs()
.get(0).getRuns()
.get(0).setText("FooBar", 0); //change text in some added row
This code is copying the first row of the table several times and then copying values from data. Works perfectly fine (except text style) except the last operator, which was supposed to change the text in some added table row. Also, the "FooBar" string doesn't even appear in document.xml of created WORD document. I failed to see any clues from debug, because it seems, that table.addRow(row); operator just copies row pointer to it's internal list of rows. Also, I didn't have problems with altering already existing rows. So do you have any ideas why this could happen?
To reproducing the problem do having a source.docx having a first table having at least two rows.
Then do running following code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
public class WordInsertTableRow {
static XWPFTableRow insertNewTableRow(XWPFTableRow sourceTableRow, int pos) throws Exception {
XWPFTable table = sourceTableRow.getTable();
CTRow newCTRrow = CTRow.Factory.parse(sourceTableRow.getCtRow().newInputStream());
XWPFTableRow tableRow = new XWPFTableRow(newCTRrow, table);
table.addRow(tableRow, pos);
return tableRow;
}
static void commitTableRows(XWPFTable table) {
int rowNr = 0;
for (XWPFTableRow tableRow : table.getRows()) {
table.getCTTbl().setTrArray(rowNr++, tableRow.getCtRow());
}
}
public static void main(String[] args) throws Exception {
XWPFDocument doc = new XWPFDocument(new FileInputStream("source.docx"));
boolean weMustCommitTableRows = false;
XWPFTable table = doc.getTableArray(0);
// insert new row, which is a copy of row 2, as new row 3:
XWPFTableRow sourceTableRow = table.getRow(1);
XWPFTableRow newRow3 = insertNewTableRow(sourceTableRow, 2);
// now changing something in that new row:
int i = 1;
for (XWPFTableCell cell : newRow3.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
run.setText("New row 3 run " + i++, 0);
}
}
}
System.out.println(newRow3.getCtRow()); // was changed
System.out.println(table.getRow(2).getCtRow()); // even this is changed
System.out.println(table.getCTTbl().getTrArray(2)); // but this was not changed, why not?
weMustCommitTableRows = true;
if (weMustCommitTableRows) commitTableRows(table); // now it is changed
FileOutputStream out = new FileOutputStream("result.docx");
doc.write(out);
out.close();
doc.close();
}
}
This code creates a copy of second row and inserts it as third row in the table. Then it does changing something in that new third row.
The issue ist, that the changings do appearing in low level CTRow of the row itself but do not appearing in low Level CTTbl of the table. For me this is not logically and I cannot get the reason of that. It looks as if the new CTRow elements are not part of the CTTbl at all. But they were added to it using ctTbl.setTrArray in XWPFTable.addRow. So I suspect there is something wrong with setTrArray in org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl. It seems updating the XML correctly but losing the object relations in the array (or list) of CTRows in CTTbl. But this is very hard to determining because of the kind of programming the org.openxmlformats.schemas classes. At least I was not able to do so. Maybe another of the professional and enthusiast programmers here may be able?
I am using the same approach for inserting rows having tthe same styling as a given source row. But after I have done this, I am setting boolean weMustCommitTableRows = true; and then I am doing if (weMustCommitTableRows) commitTableRows(table); before writing out the document. Then all changings will be committed.

How to loop over values of a certain column in an excel sheet to get the index of a value using java apache poi

I am still new to Java trying only to loop over an excel column.
The Excel sheet:
I want to have in HashMap or Array so that I can compare these dates later on with another column.
My Code is giving me yet a string as you see in the screenshot:
How can I change this String to a another Data structure to access the "index" of the values. Something like dates.get(0) --> So 01-Jul-2018. I would change the time format later.
The Code section:
XSSFWorkbook workbook = new XSSFWorkbook(fsIP);
XSSFSheet sheet = workbook.getSheetAt(0);
for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
Row row = sheet.getRow(rowIndex);
if (row != null) {
Cell cell = row.getCell(0); // getColumn(0)
if (cell != null) {
System.out.print(cell);
}
}
}
What would you like to know further from me?
I would be thankful for every help!

How to set Multiple default value in Apache POI pivot table report filter

I need some help, I'm working on a project where I need to create a pivot table with report filter. Now I want to set Multiple default value to the report filter. I've gone through this previously posted question Click here!
I couldn't find anything online related this. Thanks in advance.
There has not much changed at creating pivot tables using apache poi since my last answer. So my code in the linked Q/A in your question only can extended a little bit for fulfilling the requirement selecting multiple items as default in page filter. A code which would be general able creating pivot tables from all kind of data, as Excel can do, is further on not possible.
If the need is selecting multiple items, first MultipleItemSelectionAllowed needs to be set in appropriate pivot field.
Then for each item which not shall be selected H(idden) needs set true.
Example:
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.SpreadsheetVersion;
import java.util.Random;
import java.io.*;
class PivotTableTest4 {
private static void setCellData(Sheet sheet) {
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("Name");
cell = row.createCell(1);
cell.setCellValue("Value1");
cell = row.createCell(2);
cell.setCellValue("Value2");
cell = row.createCell(3);
cell.setCellValue("City");
for (int r = 1; r < 15; r++) {
row = sheet.createRow(r);
cell = row.createCell(0);
cell.setCellValue("Name " + ((r-1) % 5 + 1));
cell = row.createCell(1);
cell.setCellValue(r * new java.util.Random().nextDouble());
cell = row.createCell(2);
cell.setCellValue(r * new java.util.Random().nextDouble());
cell = row.createCell(3);
cell.setCellValue("City " + ((r-1) % 4 + 1));
}
}
public static void main(String[] args) {
try {
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet();
//Create some data to build the pivot table on
setCellData(sheet);
XSSFPivotTable pivotTable = sheet.createPivotTable(
new AreaReference(new CellReference("A1"), new CellReference("D15"), SpreadsheetVersion.EXCEL2007), new CellReference("H5"));
//Configure the pivot table
//Use first column as row label
pivotTable.addRowLabel(0);
//Sum up the second column
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 1);
//Avarage the third column
pivotTable.addColumnLabel(DataConsolidateFunction.AVERAGE, 2);
//Add fourth column as page filter
pivotTable.addReportFilter(3);
/*
Apache poi adds 15 pivot field items of type "default" (<item t="default"/>) here.
This is because there are 15 rows (A1:D15) and, because they don't have a look at the data,
they are assuming max 15 different values. This is fine because Excel will rebuild its pivot cache while opening.
But if we want preselect items, then this is not fine. Then we must know what items there are that can be preselected.
So we need at least as much items as we want preselecting as numbered items: <item x="0"/><item x="1"/><item x="2"/>...
And we must build a cache definition which has shared elements for those items.
*/
for (int i = 0; i < 4; i++) {
//take the first 4 items as numbered items: <item x="0"/><item x="1"/><item x="2"/><item x="3"/>
pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).getItems().getItemArray(i).unsetT();
pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).getItems().getItemArray(i).setX((long)i);
//build a cache definition which has shared elements for those items
//<sharedItems><s v="City 1"/><s v="City 2"/><s v="City 3"/><s v="City 4"/></sharedItems>
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(3).getSharedItems().addNewS().setV("City " + (i+1));
}
//Now we can predefinite a page filter. Second item, which is "City 2", in this case.
//pivotTable.getCTPivotTableDefinition().getPageFields().getPageFieldArray(0).setItem(1);
//If the need is selecting multiple items, first MultipleItemSelectionAllowed needs to be set.
pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).setMultipleItemSelectionAllowed(true);
//Then set H(idden) true for all items which not shall be selected. First ("City 1") and fourth ("City 4") in this case.
pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).getItems().getItemArray(0).setH(true);
pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldArray(3).getItems().getItemArray(3).setH(true);
FileOutputStream fileOut = new FileOutputStream("PivotTableTest4.xlsx");
wb.write(fileOut);
fileOut.close();
wb.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This needs the full jar of all of the schemas, ooxml-schemas-1.3.jar, as mentioned in the FAQ.

How to handle an empty numeric cell in POI

Is there any particular reason POI creates a numeric cell when in fact, it's actually empty? What happens is that by the time I get to that cell I obviously get an runtime error as I can't get the string value (it's a numeric cell, after all) and I can't get the numeric value either (can't get a number from an empty string) so my 2 questions would be:
How does POI got there?
Is there any way I can handle this scenario without having to explicitly go to my excel file?
UPDATE I:
After reading / parsing my excel file, POI generates the following XML for this particular cell:
<x:c r="AA2" t="n">
<x:v/>
</x:c>
My method is something like this:
final FileInputStream inputStream = new FileInputStream(new File("PATH/TO/FILE.xml"));
final XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
final XSSFSheet sheet = workbook.getSheet("SHEET_NAME");
final int columnCount = sheet.getRow(0).getLastCellNum();
for (int rowNumber = 0; rowNumber <= sheet.getLastRowNum(); rowNumber++)
{
final XSSFRow row = sheet.getRow(rowNumber);
for (int column = 0; column < columnCount; column++)
{
// By now my cell would throw an exception if I attempt cell.getStringCellValue() or cell.getNumericCellValue() as cell.getCellType() returns "0" / NUMERIC
final XSSFCell cell = row.getCell(column);
...
}
}
I was thinking about adding an additional validation to determine whether the cell is empty by using the getRawValue() method, but not sure if there's a better way to handle this as it was obviously wrongly parsed.
UPDATE II
I've been able to reproduce this scenario by doing adding this as part of a unit test (I still don't understand why POI would fall into this scenario though):
final XLSXSheetConverterImpl xlsxSheetConverter = new XLSXSheetConverterImpl();
xlsxSheetConverter.setSheetName(SHEET_NAME);
xlsxSheetConverter.setFilePrefix(FILE_PREFIX);
XSSFWorkbook workbook = new XSSFWorkbook();
final XSSFSheet sheet = workbook.createSheet(SHEET_NAME);
final XSSFRow row = sheet.createRow(0);
XSSFCell cell = row.createCell(0);
final CTCellImpl ctCell = (CTCellImpl) cell.getCTCell();
ctCell.setT(STCellType.N);
ctCell.setV("");
Thanks in advance!
This is a known bug in older POI versions, see: https://bz.apache.org/bugzilla/show_bug.cgi?id=56702
It's been fixed since 3.11 version
Thank you all for your help!!

Apache POI blank values

I am using Apache POI to import data from excel file to database.(newbie to APACHE POI)
In which I am allowing user to select columns from excel sheet and Map those columns to the Database columns. After mapping the columns, when I try to insert the records from Excel to Database then:
If Columns with NO blank values in them are Mapped then Proper data is inserted into the database
If columns are Mapped with BLANK values in them, then if a Excel Cell has blank value then previous value of that column is assigned.
Source Code:
FileInputStream file = new FileInputStream(new File("C:/Temp.xls"));
HSSFWorkbook workbook = new HSSFWorkbook(file); //Get the workbook instance for XLS file
HSSFSheet sheet = workbook.getSheetAt(0); //Get first sheet from the workbook
Iterator<Row> rowIterator = sheet.iterator(); //Iterate through each rows from first sheet
while (rowIterator.hasNext())
{
HSSFRow hssfRow = (HSSFRow) rowIterator.next();
Iterator<Cell> iterator = hssfRow.cellIterator();
int current = 0, next = 1;
while (iterator.hasNext())
{
HSSFCell hssfCell = (HSSFCell) iterator.next();
current = hssfCell.getColumnIndex();
for(int i=0;i<arrIndex.length;i++) //arrayIndex is array of Excel cell Indexes selected by the user
{
if(arrIndex[i] == hssfCell.getColumnIndex())
{
if(current<next)
{
//System.out.println("Condition Satisfied");
}
else
{
System.out.println( "pstmt.setString("+next+",null);");
pstmt.setString(next,null);
next = next + 1;
}
System.out.println( "pstmt.setString("+next+","+((Object)hssfCell).toString()+");");
pstmt.setString(next,((Object)hssfCell).toString());
next = next + 1;
}
}
}
pstmt.addBatch();
}
I have look for similar questions on SO, but still not able to solve the issue.. So any help will be appreciated.
Thanks in advance..
You've made a very common mistake, which has been covered in rather a lot of past StackOverflow questions
As the Apache POI documentation on cell iterating says
In some cases, when iterating, you need full control over how missing or blank cells are treated, and you need to ensure you visit every cell and not just those defined in the file. (The CellIterator will only return the cells defined in the file, which is largely those with values or stylings, but it depends on Excel).
It sounds like you are in that situation, where you need to care about hitting every row/cell, and not just grabbing all the available cells without worrying about the gaps
You'll want to change you code to look somewhat like the example in the POI docs:
// Decide which rows to process
int rowStart = Math.min(15, sheet.getFirstRowNum());
int rowEnd = Math.max(1400, sheet.getLastRowNum());
for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
Row r = sheet.getRow(rowNum);
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
for (int cn = 0; cn < lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
// Mark it as blank in the database if needed
} else {
// Do something useful with the cell's contents
}
}
}

Categories