I'm writing a program to read an xslx file using Apache POI in java, and create a search algorithm to search for s string in the records. I've written the code to print all the records but I can't seem to find how to create the search algorithm. It's meant to show records with "zgheib" only. I would really appreciate a hand. This is my code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class test {
public static void main(String[] args) throws IOException {
try
{
FileInputStream file = new FileInputStream(new File("C:\\Users\\Junaid\\Documents\\IntelliJ Projects\\ReadExcel_Bashar\\src\\assignment.xlsx"));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext())
{
Cell cell = cellIterator.next();
//Check the cell type and format accordingly
switch (cell.getCellType())
{
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "\t");
break;
}
}
System.out.println("");
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
If the need is to get only rows where cell values contain a search string, then this can be achieved by traversing all rows and cells in the sheet and get the cell values. If the cell value contains the search string, then add the row to a list of rows List<Row>. Since all cell values must be converted to string as the search value is a string, DataFormatter can be used. The formatCellValue methods of DataFormatter get all cell values as formatted strings. To support formula cells too, DataFormatter must be used together with FormulaEvaluator.
The following example provides a method
List<Row> getRows(Sheet sheet, DataFormatter formatter, FormulaEvaluator evaluator, String searchValue) {
List<Row> result = new ArrayList<Row>();
String cellValue = "";
for (Row row : sheet) {
for (Cell cell : row) {
cellValue = formatter.formatCellValue(cell, evaluator);
if (cellValue.contains(searchValue)) {
result.add(row);
break;
}
}
}
return result;
}
This method traverses the given sheet and gets all cell values using DataFormatter and FormulaEvaluator. If found cell value contains the search value, the row is added to the list, else not. So the result is a List<Row> which only contains rows where cells contain the search string.
Complete example:
import org.apache.poi.ss.usermodel.*;
import java.io.FileInputStream;
import java.util.List;
import java.util.ArrayList;
class ReadExcelRows {
//get only rows where cell values contain search string
static List<Row> getRows(Sheet sheet, DataFormatter formatter, FormulaEvaluator evaluator, String searchValue) {
List<Row> result = new ArrayList<Row>();
String cellValue = "";
for (Row row : sheet) {
for (Cell cell : row) {
cellValue = formatter.formatCellValue(cell, evaluator);
if (cellValue.contains(searchValue)) {
result.add(row);
break;
}
}
}
return result;
}
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("./inputFile.xlsx"));
//Workbook workbook = WorkbookFactory.create(new FileInputStream("./inputFile.xls"));
DataFormatter formatter = new DataFormatter();
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
Sheet sheet = workbook.getSheetAt(0);
List<Row> filteredRows = getRows(sheet, formatter, evaluator, "zgheib");
for (Row row : filteredRows) {
for (Cell cell : row) {
System.out.print(cell.getAddress()+ ":" + formatter.formatCellValue(cell, evaluator));
System.out.print(" ");
}
System.out.println();
}
workbook.close();
}
}
Related
I'm trying to get the pre-existing data validation information out of an Excel cell with Apache POI. For example, if a cell already has a data validation constraint that only allows integers between 0 and 100, I'd like to be able to pull that information out of the cell.
On the Data Validation section of the Quick Guide, the examples only seem to cover adding validation to cells, not retrieving it. I've found the DataValidationEvaluator object that appears to do what I am looking for with its getValidationForCell method. However, I cannot figure out how to properly instantiate an instance of this object since its constructor requires a WorkbookEvaluatorProvider which, according to its official documentation, is for internal POI use only.
Any help or guidance on this would be greatly appreciated! Maybe one of you will know a much easier and better way to get this information. Here is a snippet of code that demonstrates what I would like to do:
// The impossible (?) bit
WorkbookEvaluatorProvider wep = ...???...
// Easy through here
DataValidationEvaluator dve = new DataValidationEvaluator(wb, wep)
CellReference cRef = aRef.getFirstCell();
DataValidation dv = dve.getValidationForCell(cRef);
We can have a method which gets the data validation constraint out of the given Cell.
First we need get sheet's data validations and then for each data validation get Excel cell ranges the data validation applies to. If the cell is in one of that cell ranges then return that validation constraint.
Example:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.FileInputStream;
import java.util.List;
import java.util.Arrays;
public class ExcelGetDataValidationConstraints {
static DataValidationConstraint getDataValidationConstraint(Cell cell) {
Sheet sheet = cell.getSheet();
List<? extends DataValidation> dataValidations = sheet.getDataValidations(); // get sheet's data validations
for (DataValidation dataValidation : dataValidations) {
CellRangeAddressList addressList = dataValidation.getRegions(); // get Excel cell ranges the data validation applies to
CellRangeAddress[] addresses = addressList.getCellRangeAddresses();
for (CellRangeAddress address : addresses) {
if (address.isInRange(cell)) { // if the cell is in that cell range
DataValidationConstraint constraint = dataValidation.getValidationConstraint();
return constraint; // return this
}
}
}
return null; // per default return null
}
public static void main(String[] args) throws Exception {
//String filePath = "ExcelWorkbook.xls";
String filePath = "ExcelWorkbook.xlsx";
Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
DataValidationConstraint constraint = getDataValidationConstraint(cell);
System.out.println(cell.getAddress());
System.out.println(constraint);
if (constraint != null) {
System.out.println("DataValidationConstraint.ValidationType: " + constraint.getValidationType());
//https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/DataValidationConstraint.ValidationType.html
System.out.println("Formula1: " + constraint.getFormula1());
System.out.println("DataValidationConstraint.OperatorType: " + constraint.getOperator());
//https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/DataValidationConstraint.OperatorType.html
System.out.println("Formula2: " + constraint.getFormula2());
String[] listValues = constraint.getExplicitListValues();
if (listValues != null) System.out.println("List values: " + Arrays.asList(listValues));
}
System.out.println();
}
}
workbook.close();
}
}
See How to get datavalidation source for a cell in java using poi? for working with differnt types of list constraints.
To answer your question about using WorkbookEvaluatorProvider:
WorkbookEvaluatorProvider is an interface which is implemented by all FormulaElevators. So to get a WorkbookEvaluatorProvider we need creating a FormulaEvaluator. This can be done using CreationHelper.html#createFormulaEvaluator. The CreationHelper can be got form the Workbook.
So what you have described could be done using method:
DataValidation getDataValidationFromDataValidationEvaluator (Cell cell) {
Sheet sheet = cell.getSheet();
Workbook workbook = sheet.getWorkbook();
WorkbookEvaluatorProvider workbookEvaluatorProvider =
(WorkbookEvaluatorProvider)workbook.getCreationHelper().createFormulaEvaluator();
DataValidationEvaluator dataValidationEvaluator = new DataValidationEvaluator(workbook, workbookEvaluatorProvider);
DataValidation dataValidation = dataValidationEvaluator.getValidationForCell(new CellReference(cell));
return dataValidation;
}
Complete example:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import org.apache.poi.ss.formula.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import java.io.FileInputStream;
import java.util.List;
import java.util.Arrays;
public class ExcelGetDataValidationFromDataValidationEvaluator {
static DataValidation getDataValidationFromDataValidationEvaluator (Cell cell) {
Sheet sheet = cell.getSheet();
Workbook workbook = sheet.getWorkbook();
WorkbookEvaluatorProvider workbookEvaluatorProvider =
(WorkbookEvaluatorProvider)workbook.getCreationHelper().createFormulaEvaluator();
DataValidationEvaluator dataValidationEvaluator = new DataValidationEvaluator(workbook, workbookEvaluatorProvider);
DataValidation dataValidation = dataValidationEvaluator.getValidationForCell(new CellReference(cell));
return dataValidation;
}
public static void main(String[] args) throws Exception {
//String filePath = "ExcelWorkbook.xls";
String filePath = "ExcelWorkbook.xlsx";
Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
System.out.println(cell.getAddress());
DataValidation dataValidation = getDataValidationFromDataValidationEvaluator(cell);
if (dataValidation!=null) {
DataValidationConstraint constraint = dataValidation.getValidationConstraint();
System.out.println(dataValidation);
System.out.println(constraint);
if (constraint != null) {
System.out.println("DataValidationConstraint.ValidationType: " + constraint.getValidationType());
//https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/DataValidationConstraint.ValidationType.html
System.out.println("Formula1: " + constraint.getFormula1());
System.out.println("DataValidationConstraint.OperatorType: " + constraint.getOperator());
//https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/DataValidationConstraint.OperatorType.html
System.out.println("Formula2: " + constraint.getFormula2());
String[] listValues = constraint.getExplicitListValues();
if (listValues != null) System.out.println("List values: " + Arrays.asList(listValues));
}
}
System.out.println();
}
}
workbook.close();
}
}
Worth testing what approach is more performant.
i am writing java code for a library sorting project, what i want it to do is to search for a string across all cells within a specific column and then print the ones that contain the given substring, i want to do it through columns because i have a column for each piece of info about the book (author, title, ISBN), so is there a way to do this? i have written the following code so far for this (without the import statements though) and all it does is print the whole row for the book that contains a substring, i only need it to print a specific cell from that row after it selects it
public class testf {
static List<Row> getRows(Sheet sheet, DataFormatter formatter, FormulaEvaluator evaluator, String searchValue) {
List<Row> result = new ArrayList<Row>();
String cellValue = "";
for (Row row : sheet) {
for (Cell cell : row) {
cellValue = formatter.formatCellValue(cell, evaluator);
if (cellValue.contains(searchValue)) {
result.add(row);
break;
}
}
}
return result;
}
public static void main(String[] args) throws IOException, InvalidFormatException {
try
{
FileInputStream file = new FileInputStream(new File("C:\\\\Users\\\\abdul\\\\Desktop\\\\University Files\\\\Object-Oriented Programming\\\\Project files\\\\Book class\\\\Books & DDC.xlsx"));
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
DataFormatter formatter = new DataFormatter();
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
Scanner a = new Scanner(System.in);
List<Row> filteredRows = getRows(sheet, formatter, evaluator, "y");
for (Row row : filteredRows) {
for (Cell cell : row) {
System.out.print(formatter.formatCellValue(cell, evaluator));
System.out.print("\t \t");
}
System.out.println();
}
file.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
That's because the method getRows returns all the rows where there is a cell with the wanted criteria, but it doesn't tell you which cell exactly, so what you need to do is return the cells.
getRows -> getCells
and the code for that method will be :
static List<Cell> getCells(Sheet sheet, DataFormatter formatter, FormulaEvaluator evaluator, String searchValue) {
List<Cell> result = new ArrayList<>();
String cellValue = "";
for (Row row : sheet) {
for (Cell cell : row) {
cellValue = formatter.formatCellValue(cell, evaluator);
if (cellValue.contains(searchValue)) {
result.add(cell);
break;
}
}
}
return result;
}
and as far as printing goes, you just loop through the list of cells and you pritn them normally, and if you for whatever reason need the row for a particular cell, you just call cell.getRow()
List<Cell> filteredCells = getCells(sheet, formatter, evaluator, "whatever");
for (Cell cell : filteredCells) {
System.out.print(formatter.formatCellValue(cell, evaluator));
System.out.print("\t \t");
Row cellsRow = cell.getRow();// if you need the full row
}
by the way, I don't know about the specifications that you have, but the break that you have in your filtering method means that if a row has multiple cells with the wanted value, you'll only get the first cell, so be careful about that, i would recommend removing that break unless it's exactly what you want
I use Apache-poi 3.9 into my Struts 1.3.10 project.
I have two errors when i compile in this functionality:
private boolean parserHSSFSheet(HSSFSheet pageAccord, StringBuffer idPaa, StringBuffer idGroupe,
StringBuffer idFournisseur, StringBuffer idFamille, StringBuffer periode, Map<Integer, Marque> mapMarque,
Map<Integer, Ristournable> mapRistournable, Map<Integer, PerimetreProduitEnum> mapTypeDeclaration,
Map<Integer, FamilleDeProduitsNomenclature> mapFamille, Map<Integer, String> mapMarqueProduit,
TreeMap<Integer, TreeMap<Integer, BigDecimal>> mapColonneAdherentMontant,
TreeMap<Integer, BigDecimal> mapAdherentQuantite) throws Exception {
...
for (Iterator<HSSFRow> rit = pageAccord.rowIterator(); rit.hasNext();) {
HSSFRow row = (HSSFRow) rit.next();
String typeCellule = "";
for (Iterator<HSSFCell> cit = (Iterator<HSSFCell>) row.cellIterator(); cit.hasNext();) {
HSSFCell cell = cit.next();
if (cell.getCellNum() == ((short) 0)) {
...
}
Errors:
pageAccord.rowIterator();
Type mismatch: cannot convert from Iterator to Iterator
And
(Iterator<HSSFCell>) row.cellIterator();
Cannot cast from Iterator to Iterator
Have you seen the docs?? https://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFSheet.html says that rowIterator returns java.util.Iterator<Row> so you cannot cast it "onwards". The same is regarding cell etc.
change
Iterator<HSSFRow> rit = pageAccord.rowIterator(); rit.hasNext();
To
Iterator<Row> rit = pageAccord.rowIterator(); rit.hasNext();
And do the same for the cellIterator
Second cast, Cell into HSSFCell should work if iterator indeed will return compatibile type with HSSFCell.
As per the API docs a call to
pageAccord.rowIterator() returns a java.util.Iterator<Row>. See here.
row.cellIterator() returns a java.util.Iterator<Cell>. See here.
Both Row and Cell are only interfaces. Still I would work with those when possible and defer the explicit downcasting to places where this is actually necessary (and allowed).
Thus: Amend your iterators to comply with the types listed above (this could also mean using a generic Iterator<?> in places) and only downcast later (such as in your HSSFRow row = (HSSFRow) rit.next();).
Please find the below program for the quick solution
workbook = WorkbookFactory.create(new FileInputStream(envFilePath + "\\"+ listOfFiles[i].getName()));
// Get the first sheet.
Sheet sheet = workbook.getSheetAt(0);
// Get the first cell.
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
Test program which can help you
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class TestExcelFile {
public static void main(String[] args) {
String envFilePath = System.getenv("AZURE_FILE_PATH");
// upload list of files/directory to blob storage
File folder = new File(envFilePath);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
System.out.println("File " + listOfFiles[i].getName());
Workbook workbook;
try {
workbook = WorkbookFactory.create(new FileInputStream(envFilePath + "\\"+ listOfFiles[i].getName()));
// Get the first sheet.
Sheet sheet = workbook.getSheetAt(0);
// Get the first cell.
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
// Show what is being read.
System.out.println(cell.toString());
for (Cell cell1 : row) {
System.out.println(cell1.toString());
}
} catch (InvalidFormatException | IOException e) {
e.printStackTrace();
}
}
}
}
}
I'm writing a Java program to fetch data from Excel sheet.
From the below program, i'm able to retrieve the entire data.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.formula.functions.Column;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadData {
#SuppressWarnings({ "resource", "null" })
public static void main(String[] args) throws IOException {
// get file
FileInputStream fin = new FileInputStream(
new File("C:\\A2015.xlsx"));
// create book holding object
XSSFWorkbook wb = new XSSFWorkbook(fin);
// get sheet
XSSFSheet sheet = wb.getSheetAt(0);
// iterate through rows
Iterator<Row> rowIt = sheet.rowIterator();
while (rowIt.hasNext()) {
XSSFRow row = (XSSFRow) rowIt.next();
// iterate through Columns
Iterator<Cell> colIt = row.cellIterator();
while (colIt.hasNext()) {
Cell cell = colIt.next();
System.out.println(cell.toString());
}
System.out.println();
}
}
}
But here my case is there are nearly 45-47 columns and out of there there is some data which is not required(for me, but needed for some other teams). Every column has a heading, and out of these 45-47 columns i want to pull data only from 12 columns, and there are randomly placed between the rest of columns in Excel sheet.
My question is, is there a way to iterate through all the rows and get data from these 12 columns only by using the Heading, If so can you please let me know how to extract it.
I'm using Apache POI.
Thanks
public static short getCellNum(String cellCode)throws InvalidNameException{
char[] cellCodeU = cellCode.toUpperCase().toCharArray();
int length = cellCodeU.length;
int cellNumber = 0;
for (int j=0;j<length;j++){
if (cellCodeU[j]<'A' || cellCodeU[j]>'Z')
throw new InvalidNameException("Wrong column index: " + cellCode);
cellNumber = cellNumber*CELL_NUMBER_IN_SHEET + (cellCodeU[j]-64);
}
cellNumber-=1;
if (cellNumber<0)
throw new InvalidNameException("Wrong column index: " + cellCode);
return (short)cellNumber;
}
String columnsToRead = new String[]{"AA", "AB", "AU"};
while (rowIt.hasNext()) {
XSSFRow row = (XSSFRow) rowIt.next();
for (int a = 0; a < columnsToRead.length; a++){
Cell cell = getCell(getCellNum(columnsToRead[a]));
System.out.println(cell.toString());
}
}
I realize the question is a little confusing, but I didn't know how else to word it. Anyway, here is the original code:
private void readFile(String excelFileName) throws FileNotFoundException, IOException {
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(excelFileName));
if (workbook.getNumberOfSheets() > 1){
System.out.println("Please make sure there is only one sheet in the excel workbook.");
}
XSSFSheet sheet = workbook.getSheetAt(0);
int numOfPhysRows = sheet.getPhysicalNumberOfRows();
XSSFRow row;
XSSFCell num;
for(int y = 1;y < numOfPhysRows;y++){ //start at the 2nd row since 1st should be category names
row = sheet.getRow(y);
poNum = row.getCell(1);
item = new Item(Integer.parseInt(poNum.getStringCellValue());
itemList.add(item);
y++;
}
}
private int poiConvertFromStringtoInt(XSSFCell cell){
int x = Integer.parseInt(Double.toString(cell.getNumericCellValue()));
return x;
}
I am getting the following error:
Exception in thread "main" java.lang.IllegalStateException: Cannot get a numeric value from a text cell
at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781)
at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199)
Even if I change it to get either a string using XSSFCell.getStringCellValue() or even XFFSCell.getRichTextValue, I get the reverse of the above error message (and I am making sure to ultimately make it an int using Integer.parseInt(XSSFCell.getStringCellValue()).
The error then reads:
Exception in thread "main" java.lang.IllegalStateException: Cannot get a text value from a numeric cell
at org.apache.poi.xssf.usermodel.XSSFCell.typeMismatch(XSSFCell.java:781)
at org.apache.poi.xssf.usermodel.XSSFCell.getNumericCellValue(XSSFCell.java:199)
I know for a fact that the excel spreadsheet column is in fact a string. I can't change the excel sheet as it is uploaded else where always using the same format and formatting each column first takes up to much processing time.
Any suggestions?
[Solution] Here is the solution code I came up with from #Wivani's help:
private long poiGetCellValue(XSSFCell cell){
long x;
if(cell.getCellType() == 0)
x = (long)cell.getNumericCellValue();
else if(cell.getCellType() == 1)
x = Long.parseLong(cell.getStringCellValue());
else
x = -1;
return x;
}
Use This as reference
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
System.out.println(cell.getRichStringCellValue().getString());
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
System.out.println(cell.getDateCellValue());
} else {
System.out.println(cell.getNumericCellValue());
}
break;
case Cell.CELL_TYPE_BOOLEAN:
System.out.println(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
System.out.println(cell.getCellFormula());
break;
default:
System.out.println();
}
You can get value as String using the format defined for this cell :
final DataFormatter df = new DataFormatter();
final XSSFCell cell = row.getCell(cellIndex);
String valueAsString = df.formatCellValue(cell);
Thanks to this answer.
Just use cell.setCellType(1); before reading cell value and get it as String always, after that you can use it in your own format(type).
Ravi
Use the below code to read any data type from xcels using poi.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
*
* #author nirmal
*/
public class ReadWriteExcel {
public static void main(String ar[]) {
ReadWriteExcel rw = new ReadWriteExcel();
rw.readDataFromExcel();
}
Object[][] data = null;
public File getFile() throws FileNotFoundException {
File here = new File("test/com/javaant/ssg/tests/test/data.xlsx");
return new File(here.getAbsolutePath());
}
public Object[][] readDataFromExcel() {
final DataFormatter df = new DataFormatter();
try {
FileInputStream file = new FileInputStream(getFile());
//Create Workbook instance holding reference to .xlsx file
XSSFWorkbook workbook = new XSSFWorkbook(file);
//Get first/desired sheet from the workbook
XSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows one by one
Iterator<Row> rowIterator = sheet.iterator();
int rownum = 0;
int colnum = 0;
Row r=rowIterator.next();
int rowcount=sheet.getLastRowNum();
int colcount=r.getPhysicalNumberOfCells();
data = new Object[rowcount][colcount];
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
//For each row, iterate through all the columns
Iterator<Cell> cellIterator = row.cellIterator();
colnum = 0;
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
//Check the cell type and format accordingly
data[rownum][colnum] = df.formatCellValue(cell);
System.out.print(df.formatCellValue(cell));
colnum++;
System.out.println("-");
}
rownum++;
System.out.println("");
}
file.close();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
}
I got also this bug with POI version 3.12final.
I think that the bug is registered there : https://bz.apache.org/bugzilla/show_bug.cgi?id=56702 and I put a comment there with my analysis.
Here is the workaround I used : The exception was risen by HSSFCell.getNumericCellValue which was called by DateUtil.isCellDateFormatted. DateUtil.isCellDateFormatted does 2 things :
1) check the value type of the cell by calling HSSFCell.getNumericCellValue and then DateUtil.isValidExcelDate(), which is almost pointless here I think.
2) check if the format of the cell is a date format
I copied the code of topic 2) above in a new function 'myIsADateFormat' and used it instead of DateUtil.isCellDateFormatted (that is quite dirty to copy library code, but it works...) :
private boolean myIsADateFormat(Cell cell){
CellStyle style = cell.getCellStyle();
if(style == null) return false;
int formatNo = style.getDataFormat();
String formatString = style.getDataFormatString();
boolean result = DateUtil.isADateFormat(formatNo, formatString);
return result;
}
If you need to check the value type first, you can use this too :
CellValue cellValue = evaluator.evaluate(cell);
int cellValueType = cellValue.getCellType();
if(cellValueType == Cell.CELL_TYPE_NUMERIC){
if(myIsADateFormat(cell){
....
}
}
Documentation clearly says not to setCellType to 1 instead use the DataFormatter like how Thierry has explained:
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#setCellType(int)
Ravi's solution works :
Just use cell.setCellType(1); before reading cell value and get it as String always, after that you can use it in your own format(type).