I'm using Apache POI 3.17 to read some excel data. My second column (index of 1 because of 0 index) is empty and I want to be able to read it, but can't get my code to read the cell as empty. I have this which isn't working:
Cell c = row.getCell(1, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// do whatever
}
But the second parameter can't be taken in. I get "RETURN_BLANK_AS_NULL cannot be resolved or is not a field"
The constants in the Row class itself were deprecated as of POI-3.15-beta2, marked for removal as of POI-3.17. This diff shows when those constants were deprecated in June 2016. They were removed in 3.17.
Before 3.17, the enum Row.MissingCellPolicy was already defined as a replacement. If you're using 3.17, then you must use that enum; it is defined as a member of the Row interface. Try
Cell c = row.getCell(1, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
Try using org.apache.poi.ss.usermodel.DataFormatter.
DataFormatter formatter = new DataFormatter();
Workbook workbook = WorkbookFactory.create(new File("yourFileName.xls"));
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for(Cell cell : row)
{
String text = formatter.formatCellValue(cell);
System.out.println(text);
}
}
workbook.close();
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'd like to find a cell in an Excel sheet by its text. The text is something like %t:
sheet.findCell("%t"); // pseudo-code, not working
My goal is to enable the user to provide kind of template, in which data is written. Colours and fonts, as well as data's position can be configured by the user in an Excel file. This %t cell is the top-left corner of the data table.
Additional question: Is there a more elegant way to get this job done?
EDIT I'm iterating over the rows and cells to find it. I'm afraid it's not really efficient, but it works so far:
public static Cell findCell(XSSFSheet sheet, String text) {
for(Row row : sheet) {
for(Cell cell : row) {
if(text.equals(cell.getStringCellValue()))
return cell;
}
}
return null;
}
You can iterate through the cells of the sheet and investigate the contents. I don't think there is an easier method.
Its an old post but still i want to publish my code.
You can define a file path.
String inputFile = "src\main\resources\file.xlsx";
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream(inputFile));
DataFormatter formatter = new DataFormatter();
for (XSSFSheet sheet : xssfWorkbook) {
for (Row row : sheet) {
for (Cell cell : row) {
if (formatter.formatCellValue(cell).contains("name")){
cell.setCellValue("test");
}
}
}
}
xssfWorkbook.write(new FileOutputStream(inputFile));
I wanted to get the value of a Numeric cell as a simple string.
Suppose there the type of cell is numeric with value 90%.
Now I cannot use cell.getStringCellValue() as it will throw exception.
I also cannot use cell.getNumericCellValue() as it will return me .9 and not 90%.
I want to store in db which is of type varchar2, so I want the value in string only.
I cannot change the cell type in xls as its the end user job, I have to handle this in code itself.
Also formatter does't work well as there could be different cell types in the xls...dd:mm,dd:mm:ss,formula etc.
All I want is that whatever the cell type is I need to get its value as simple String.
You can force the value to be returned as a String using the methods below
HSSFDataFormatter hdf = new HSSFDataFormatter();
System.out.println (hdf.formatCellValue(mycell));
will return "90%"
The API for this method is at http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/DataFormatter.html#formatCellValue%28org.apache.poi.ss.usermodel.Cell%29
This works directly even with an HSSFCell
it worked for me even when my Cell is an HSSFCell
i've also tried this cast - which works.
HSSFCell cell1 = (HSSFCell) row1.getCell(2);
HSSFDataFormatter hdf = new HSSFDataFormatter();
System.out.println ("formatted "+ hdf.formatCellValue(cell1));
Try
cell.getRichStringCellValue ().getString();
Have a look at this example
Here is Doc
The following code is using current apache poi versions of 2021. Now DataFormatter can be used for XSSF (Office Open XML *.xlsx) as well as for HSSF (BIFF *.xls) formats. It should be used together with FormulaEvaluator to get values from formula cells too.
import org.apache.poi.ss.usermodel.*;
import java.io.FileInputStream;
class ReadExcel {
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("Excel.xlsx"));
//Workbook workbook = WorkbookFactory.create(new FileInputStream("Excel.xls"));
DataFormatter dataFormatter = new DataFormatter(java.util.Locale.US);
FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
String cellValue = "";
for (Sheet sheet: workbook) {
System.out.println(sheet.getSheetName());
for (Row row : sheet) {
for (Cell cell : row) {
cellValue = dataFormatter.formatCellValue(cell, formulaEvaluator);
System.out.println(cell.getAddress() + ":" + cellValue);
// do something with cellValue
}
}
}
workbook.close();
}
}