perform operations on excel data sheet using java - java

there are four columns in excel sheet
I need to perform operations on three columns and display the result on the fourth one.
Image with data in excel
If I perform B9-D9 then the result is equal to C9.
when this happens the output should be as "matched".
i need to know how to access each row and column and perform the necessary operation on it.
See if you can help me and let me know if any additional details are required.
package com.infy;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
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.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReconMatch {
public static void main(String[] args) throws IOException,
FileNotFoundException{
// TODO Auto-generated method stub
String excelFilePath ="C:/Users/akshay.kuchankar/Documents/demo.xlsx";
FileInputStream inputStream = new FileInputStream(new
File(excelFilePath));
Workbook workbook = new XSSFWorkbook(inputStream);
Sheet firstSheet = workbook.getSheetAt(0);
Iterator<Row> iterator = firstSheet.iterator();
while (iterator.hasNext()) {
Row nextRow = iterator.next();
Iterator<Cell> cellIterator = nextRow.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
//what should be the basic approach or the syntax to perform the operaiton??
}
System.out.println();
}
workbook.close();
inputStream.close();
}
}
for(int i= 0; i<firstSheet.getRow(0).getCell(0).getNumericCellValue(); i++)
{
FGAmount = firstSheet.getRow(1).getCell(1).getNumericCellValue();
// System.out.println(FGAmount);
difference = firstSheet.getRow(1).getCell(3).getNumericCellValue();
value = FGAmount + difference;
}
alconAmount = firstSheet.getRow(1).getCell(2).getNumericCellValue();
// result = firstSheet.getRow(1).getCell(4).getStringCellValue();
}
}
try {
if(value== alconAmount){
firstSheet.getRow(1).getCell(4).setCellValue("Manual Matched");
System.out.println("matched");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
// System.out.println(result);
workbook.close();
inputStream.close();

Take a look at the API for your library:
https://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html
You can interact with the cell in a number of ways, for example:
cell.setCellValue("My new value");
As for how to get values form cells and check against them you can do something a bit like this example where we do a bit of math and compare the values:
//Value of row 9, column 1 (column B)
String B9 = firstSheet.getRow(9).getCell(1).getStringCellValue();
//Value of row 9, column 2 (column C)
String D9 = firstSheet.getRow(9).getCell(2).getStringCellValue();
//Value of row 9, column 3 (column D)
String D9 = firstSheet.getRow(9).getCell(3).getStringCellValue();
//do math B9 - D9
double value = Double.parseDouble(B9) - Double.parseDouble(D9);
//check if C9 matches the result of B9 - D9
if(value == Double.parseDouble(C9))
{
//if it matches set cell E9 to display "Matched" and print out a message
firstSheet.getRow(9).getCell(4).setCellValue("matched");
System.out.println("matched");
}
I have not tested this code, but it should point you in the right direction.
Obviously there are things you should do like putting this in a loop rather than hard coding values, and you should check the column name to the make sure you have the right column before getting your values, and then you should check that the cell is a number and not text etc.
Edit in reply to your comment. Here is some code that will go over every row in a sheet except row 1 and will do exactly the same thing as in my example above and write "matched" in column E if column B - column D is equal to column C:
Iterator<Row> iterator = firstSheet.iterator();
while (iterator.hasNext()) {
Row nextRow = iterator.next();
//Check to make sure we skip the first row because that has all the column names:
if (nextRow.getRowNum() != 0){
//Get cell values of the current row
String columnB = nextRow.getCell(1).getStringCellValue();
String columnC = nextRow.getCell(2).getStringCellValue();
String columnD = nextRow.getCell(3).getStringCellValue();
try{
//do math column B - column D
double value = Double.parseDouble(columnB) - Double.parseDouble(columnD);
//check if column C matches the result of (column B - column D)
if(value == Double.parseDouble(columnC)){
//if it matches set text in column E to "matched"
nextRow.getCell(4).setCellValue("matched");
//print to console showing if a row matched
System.out.println("Row " + (nextRow.getRowNum()+1) + " matched");
}
}
catch(NumberFormatException nfe){
//do nothing here, this will happen if a cell contains text instead of numbers
}
catch(NullPointerException npe){
//Something else happened, you can probably ignore this as well but it will pay to throw a stack trace just in case something is wrong with this code
npe.printStackTrace();
}
}
}

Related

How to read .xlsx file with apache poi?

See the picture below, I am trying to write a program that can "scan" a given row with no limit of from which cell to which cell, then, find all the "strings" that are identical the same. Is it possible to do that? Thank you.
To give an example so that this will not be very confusing, for ex.: On row H, you see there are customer's names, there are "Coresystem", "Huawei", "VIVO", etc... Now the problem is, what if the names are not grouped together, they are all split up, like, On H5, it will be "Huawei" and On H9, it will be "VIVO", etc, it's like, unlike the picture provided below, on row H all the names are split up, and I want apache POI to find all the customers that have the same name, for ex.: If user enter "coReSysteM", it should be able to find all the .equalsIgnoreCase of all Coresystem on row H (btw, the user should be able to enter the customer's name that they want to enter and the row they want to search for), and display from A5, B5, C5, D5, E5, F5, G5, H5 to A14, B14, C14, D14, E14, F14, G14, H5, is it possible?
I was thinking about setting a formula to find all the customer, for example: =CountIf
These are the code that I am currently trying to do, but then I am stuck with it:
package excel_reader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
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 ExcelReader2d {
ExcelReader link = new ExcelReader();
Scanner scan = new Scanner(System.in);
// instance data
private static int numberGrid[][] = null;
private static String stringGrid[][] = null;
// constructor
public ExcelReader2d(String desLink) {
}
// methods
public void ExeScan() throws FileNotFoundException, IOException {
Scanner scan = new Scanner(System.in);
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("C:\\Users\\Sonic\\Desktop\\20191223 IMPORTS.xlsx"));
XSSFSheet sheet = workbook.getSheetAt(0);
final int rowStart = Math.min(15, sheet.getFirstRowNum()), rowEnd = Math.max(1400, sheet.getLastRowNum());
System.out.print("Enter the rows that you want to search for: (for ex. the rows that stores customer's name) ");
int searchRows = scan.nextInt();
System.out.print("Enter the customer's name that you are looking for: ");
String name = scan.nextLine();
//int rowNum;
// Search given row
XSSFRow row = sheet.getRow(searchRows);
try {
for (int j = 4; j < rowEnd; j++) {
Row r = sheet.getRow(j);
if (name.equalsIgnoreCase(name)) {
row.getCell(j).getStringCellValue();
}
// skip to next iterate if that specific cell is empty
if (r == null)
continue;
}
} catch (Exception e){
System.out.println("Something went wrong.");
}
}
}
ps. I know that this will be very confusing, but please feel free to ask for any kind of questions to help you get rid of the confusion and help me either because this has been a problem for me. Thank you very much and I will super appreciated for your help. Currently using apache poi, vscode, java.
I would iterate over the rows in the sheet and get the string content of cell 7 (H) from each row. If that string fulfills the requirement equalsIgnoreCase the searched value, that row is one of the result rows, else not.
One could collect the result rows in a List<Row>. Then this List contains the result rows after that.
Example:
ExcelWorkbook.xlsx:
Code:
import org.apache.poi.ss.usermodel.*;
import java.util.List;
import java.util.ArrayList;
import java.io.FileInputStream;
public class ExcelReadRowsByColumnValue {
public static void main(String[] args) throws Exception {
String filePath = "./ExcelWorkbook.xlsx";
String toSearch = "coresystem";
int searchColumn = 7; // column H
List<Row> results = new ArrayList<Row>();
DataFormatter dataFormatter = new DataFormatter();
Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) { // iterate over all rows in the sheet
Cell cellInSearchColumn = row.getCell(searchColumn); // get the cell in seach column (H)
if (cellInSearchColumn != null) { // if that cell is present
String cellValue = dataFormatter.formatCellValue(cellInSearchColumn, formulaEvaluator); // get string cell value
if (toSearch.equalsIgnoreCase(cellValue)) { // if cell value equals the searched value
results.add(row); // add that row to the results
}
}
}
// print the results
System.out.println("Found results:");
for (Row row : results) {
int rowNumber = row.getRowNum()+1;
System.out.print("Row " + rowNumber + ":\t");
for (Cell cell : row) {
String cellValue = dataFormatter.formatCellValue(cell, formulaEvaluator);
System.out.print(cellValue + "\t");
}
System.out.println();
}
workbook.close();
}
}
Result:

How to check if excel file is blank?

I have excel file (*.xls or *.xlxs) which can have records or no records. First I store the file in some temp location, then copy the contents of the file and then tried to read the file. This scenario works fine if the excel sheet contains records but if the sheet has no record and the file is empty. This scenario does not work. I am using apache-poi to read the excel file contents.
public static boolean isRowEmpty(Row row) {
for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
Cell cell = row.getCell(c);
if (cell != null && cell.getCellType() != Cell.CELL_TYPE_BLANK) {
return false;
}
}
return true;
}
I get IOException : unable to read entire header 0 bytes read expected 512 bytes. Can somebody suggest me a way to get rid of this exception and check the excel file is empty?
Googling and some experiments with org.apache.poi library suggest to me that it is abnormal to check if xls file is empty without knowing even approximately the data structure within it. It's as hard as to say if, for example, Oracle BD is empty.
Any way, you are able to fetch quantity of sheets then iterate over all of them, check rows and cells and consider file is empty if you found nothing.
HSSFWorkbook wBook = new HSSFWorkbook(new FileInputStream("your_path"));
for(int i = 0; i < wBook.getNumberOfSheets(); i++){
System.out.println("Sheet " + i + " has data: " + isSheetEmpty(wBook.getSheetAt(i)));
}
boolean isSheetEmpty(HSSFSheet sheet){
Iterator rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
if(!cell.getStringCellValue().isEmpty()){
return true;
}
}
}
return false;
}
Using Apache Poi (org.apache.poi) for the solution and skipping the parts where I actually get the Workbook (excel) and get access to it's sheets.
If you want to know if sheet is empty use this, modify the solution to loop through sheets to find out if all of the sheets in the file are empty.
if (sheet.getLastRowNum() == 0 && sheet.getRow(0) == null) {
// This is the case when the sheet is empty!
}
getLastRowNum() - returns 0 in case of empty sheet or if there is only data in the first row
getRow(0) - returns null if there is no data in the row
NOTE: the solution doesn't take empty strings, spaces, empty lines and etc. into account
Below code worked for me.
import java.util.Iterator;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
XSSFSheet sheet = wb.getSheetAt(0);
private boolean isSheetEmpty(XSSFSheet sheet) {
Iterator rows = sheet.rowIterator();
Row row = null;
Cell cell = null;
while (rows.hasNext()) {
row = (Row) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext()) {
cell = (Cell) cells.next();
if (!cell.getStringCellValue().isEmpty()) {
return true;
}
}
}
return false;
}
if (cell == null || cell.getCellType() == Cell.CELL_TYPE_BLANK) {
return true;
}
return false;
Try this one !

Retrieve values from excel using poi

I am trying to get the column values for a specific row in a excel using poi methods.
I am able to get the values but the problem is I want the values only from second column.
public static ArrayList<String> GetBusinessComponentList() throws IOException{
String Tcname = "TC02_AggregateAutoByPassRO_CT";
ArrayList<String> arrayListBusinessFlow ;
arrayListBusinessFlow = new ArrayList<String>();
FileInputStream fileInput = new FileInputStream(oFile);
wb = new HSSFWorkbook(fileInput);
sheet = wb.getSheet("Business Flow");
int rownr = findRow(sheet, Tcname);
row = sheet.getRow(rownr);
for (Cell cell : row) {
String arr = cell.getStringCellValue();
arrayListBusinessFlow.add(arr);
}
return arrayListBusinessFlow;
}
private static int findRow(HSSFSheet sheet, String cellContent){
for (Row row : sheet) {
for (Cell cell : row) {
if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
if (cell.getRichStringCellValue().getString().trim().equals(cellContent)) {
return row.getRowNum();
}
}
}
}
return 0;
}
}
OUTPUT:
[TC02_AggregateAutoByPassRO_CT,
StrategicUINewBusiness.Login,
StrategicUINewBusiness.CustomerSearch,
StrategicUINewBusiness.NamedInsured,
StrategicUINewBusiness.InsuranceScoreByPass,
StrategicUINewBusiness.VehiclePage,
StrategicUINewBusiness.DriverPage,
StrategicUINewBusiness.ViolationPage,
StrategicUINewBusiness.UnderwritingPage,
StrategicUINewBusiness.CoveragePage,
StrategicUINewBusiness.Portfolio,
StrategicUINewBusiness.BillingPage,
StrategicUINewBusiness.FinalSalePage,
StrategicUINewBusiness.PolicyConfirmation, , , ]
But I do not want my test case name when I am getting.
Please help me what changes i needed to do. thanks!
Currently, the code you're using to iterate over cells only returns cells with content or styling, and skips totally empty ones. You need to change to one of the other ways of iterating over cells, so you can control it to read from the second column onwards.
If you look at the Apache POI Documentation on iterating over rows and cells, you'll see a lot more details on the two main ways to iterate.
For your case, you'll want something like:
// We want to read from the 2nd column onwards, zero based
int firstColumn = 1;
// Always fetch at least 4 columns
int MY_MINIMUM_COLUMN_COUNT = 5;
// Work out the last column to go to
int lastColumn = Math.max(r.getLastCellNum(), MY_MINIMUM_COLUMN_COUNT);
// To format cells into strings
DataFormatter df = new DataFormatter();
// Iterate over the cells
for (int cn = firstColumn; cn < lastColumn; cn++) {
Cell c = r.getCell(cn, Row.RETURN_BLANK_AS_NULL);
if (c == null) {
// The spreadsheet is empty in this cell
} else {
// Do something useful with the cell's contents
// eg get the cells value as a string
String cellAsString = df.formatCellValue(c);
}
}
Use Cell cell=row.getCell(1); and also you can use sheet.getLastRowNum() to get the number last row on the sheet.
for (int i=0;i<=row.getLastCellNum();i++) {
if (i!=1){
//your stuff
}
}

detecting and replacing variables in a string by values

I have an excel sheet whose first column contains following data "What is ${v1} % of ${v2}?", two more columns (v1 and v2) in this sheet contains {"type":"int", "minimum":15, "maximum":58} and {"type":"int", "minimum":30, "maximum":100}, these are the ranges of variable v1 and v2. I need to replace v1 and v2 in the expression with a random value from the given range and store the expression in another spread sheet using JAVA. How can I do this by making use of JETT?
For example: I should store "What is 25% of 50?"
This is what I have done,I am able to read the column in my java program but not replace the values
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
public class ACGS {
public static void main(String[] args) throws Exception {
//test file is located in your project path
FileInputStream fileIn = new FileInputStream("C://users/user/Desktop/Content.xls");
//read file
POIFSFileSystem fs = new POIFSFileSystem(fileIn);
HSSFWorkbook filename = new HSSFWorkbook(fs);
//open sheet 0 which is first sheet of your worksheet
HSSFSheet sheet = filename.getSheetAt(0);
//we will search for column index containing string "Your Column Name" in the row 0 (which is first row of a worksheet
String columnWanted = "${v1}";
Integer columnNo = null;
//output all not null values to the list
List<Cell> cells = new ArrayList<Cell>();
Row firstRow = sheet.getRow(0);
for(Cell cell:firstRow){
if (cell.getStringCellValue().contains(columnWanted)){
columnNo = cell.getColumnIndex();
System.out.println("cell contains "+cell.getStringCellValue());
}
}
if (columnNo != null){
for (Row row : sheet) {
Cell c = row.getCell(columnNo);
if (c == null || c.getCellType() == Cell.CELL_TYPE_BLANK) {
// Nothing in the cell in this row, skip it
} else {
cells.add(c);
}
}
} else{
System.out.println("could not find column " + columnWanted + " in first row of " + fileIn.toString());
}
}
}
First, it looks like you aren't using JETT at all. You appear to be attempting to read the spreadsheet yourself and do some processing.
Here is how you would do this in JETT. JETT doesn't provide its own random number support, but together with its Apache Commons JEXL expression support, and Java's own Random, you can publish the expected ranges of your random variables as beans to JETT, and you can calculate a random variable with an expression.
First, create your template spreadsheet, populating it with expressions (between ${ and }) that JETT will evaluate. One cell might contain something like this.
What is ${rnd.nextInt(v1Max - v1Min + 1) + v1Min}% of ${rnd.nextInt(v2Max - v2Min + 1) + v2Min}?
Next, create beans to be supplied to JETT. These beans are the named objects that are available to JEXL expressions in your spreadsheet template.
Map<String, Object> beans = new HashMap<String, Object>();
beans.put("v1Min", 15);
beans.put("v1Max", 58);
beans.put("v2Min", 30);
beans.put("v2Max", 100);
beans.put("rnd", new Random());
Next, create your code that invokes the JETT ExcelTransformer.
try
{
ExcelTransformer transformer = new ExcelTransformer();
// template file name, destination file name, beans
transformer.transform("Content.xls", "Populated.xls", beans);
}
catch (IOException e)
{
System.err.println("IOException caught: " + e.getMessage());
}
catch (InvalidFormatException e)
{
System.err.println("InvalidFormatException caught: " + e.getMessage());
}
In the resultant spreadsheet, you will see the expressions evaluated. In the cell that contained the expressions above, you will see for example:
What is 41% of 38?
(Or you will see different numbers, depending on the random numbers generated.)

When getting cell content using Apache-POI Library, I get both "Cannot get a numeric value from a text cell" and the reverse of that. How do I fix it?

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).

Categories