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
}
}
}
Related
I am looking for some help. I have an excel sheet A which has around 700 records. It has 5 columns where one of the column is Lifecycle. I want to split the file into two different files based on the Lifecycle cell value. For example if the cell value of Lifecycle column is X, put the record in A_X.xlsx file else put the records in A_Y.xlsx file.
I am using Apache POI.
Thanks in advance.
You can read from excel file using Workbook
Like this: Workbook workbook = WorkbookFactory.create(new File(EXCEL_FILE_PATH));
Then you need to get your sheet like this: Sheet sheet = workbook.getSheetAt(YOUR_SHEET_POSITION);
But remember that sheets position starts from 0.
Then you can iterate over rows and cells using Iterator, for-each, and Java 8 foreEach with Lamba
Like this:
Using Iterator
Iterator<Row> rowIterator = sheet.rowIterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
// there you can check if cell.someValue == yourNeed to save on files that you need
if(cell.yourValue == SOMETHING) {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_ONE);
} else {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_TWO);
}
}
}
Using for-each
for (Row row: sheet) {
for(Cell cell: row) {
// there you can check if cell.someValue == yourNeed to save on files that you need
if(cell.yourValue == SOMETHING) {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_ONE);
} else {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_TWO);
}
}
}
Using Java 8 forEach with lamdas
sheet.forEach(row -> {
row.forEach(cell -> {
// there you can check if cell.someValue == yourNeed to save on files that you need
if(cell.yourValue == SOMETHING) {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_ONE);
} else {
saveOnExcelFile(YOUR_EXCEL_FILE_PATH_TWO);
}
});
});
And in the end, don't forget to close the workbook using workbook.close()
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!
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!!
I have an Excel spreadsheet that is full of label cells to the left of corresponding value cells. Like this:
E F
3 Invoice Number "ABC123"
4 Issue Date "2018-04-01"
5 Amount Due 298.43
I cannot rely on the values I want being in the same static cell location with each spreadsheet I process.
I want to use a regex to find the label cell (column E) that corresponds to the value I want (column F), then set the value to a variable.
I am refactoring into Java (using Apache POI library) legacy code originally written using Python. The Python code uses the following syntax to achieve the above goal:
for row in range(startrow, row+1):
if str(rowdata[0].lower().find("invoice number")) > -1:
invoice_number = rowdata[i+1]
I can't find equivalent functionality in the Apache POI documentation.
A pseudocode example of what I'm trying to do:
String invoiceNumber;
Iterator<Row> rowIterator = sheet.iterator;
while(rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> = row.cellIterator();
while(cellIterator.hasNext()) {
if (cell.matches("invoice number") {
invoiceNumber = cell + 1
}
}
}
Any push in the right direction would be greatly appreciated.
String invoiceNumber ;
Iterator<Sheet> sheetIt = wb.sheetIterator();
while (sheetIt.hasNext()) {
Sheet sheet= sheetIt.next();
Iterator<Row> rowIterator = sheet.rowIterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIt = row.cellIterator();
while (cellIt.hasNext()) {
Cell cell = cellIt.next();
if(cell.getStringCellValue().equals("Invoice Number")) {
invoiceNumber= row.getCell(cell.getColumnIndex()+1).getStringCellValue();
}
}
}
}
Can I read a excel sheet column wise using apache poi..?(without using row Iterator)
for (Row row : sheet) {
Cell firstCell = row.getCell(0);
// Printing Stuff
}
I know, the above one will do the same. But I need to get first column's data without using Row Iterator.
You can iterate over the sheet without using iterator
Workbook wb = WorkbookFactory.create(new FileInputStream("file.xls"));
Sheet sheet = wb.getSheetAt(0);
for (int j=0; j< sheet.getLastRowNum() + 1; j++) {
Row row = sheet.getRow(j);
Cell cell = row.getCell(0); //get first cell
// Printing Stuff
}