DataFormatter on cell containing date renders two digits years - java

I needed to get cell data from Excel files as they look like and bumped to DataFormatter class of Apache PO. This works like a charm except for cells containing date. Below is my code:
while (rowIterator.hasNext())
{
Row row = rowIterator.next();
StringBuilder rowDataBuilder = new StringBuilder();
int iCellCount = row.getLastCellNum();
for (int i = 0; i < iCellCount; i++)
{
Cell cell = row.getCell(i, Row.CREATE_NULL_AS_BLANK);
rowDataBuilder.append(dataFormatter.formatCellValue(cell));
rowDataBuilder.append(" | ");
}
_LOG.info("-----> row data: " + rowDataBuilder.toString());
}
For example, a cell contains 5/3/2013, I only get 5/3/13. Would there be any solutions for this?

For fetching the date in desired format you can use following:
SimpleDateFormat DtFormat = new SimpleDateFormat("dd/MM/yyyy");
Date date=Test.getRow(RowNum).getCell(CellNum).getDateCellValue();
System.out.println(DtFormat.format(date).toString());
And now if the cell value is 05/03/2013, it will give o/p as 05/03/2013. I hope this will resolve your problem.

Related

Loop to create multiple rows with different names in excel using Apache PoI

As it stands right now I have 241 lines of code used to created 46 rows and populate the first column of each row in excel using HSSFRow. Each row is named so I can reference it later on to add more columns to that particular row.
I am trying to create a loop that will create these row's for me and save me 200+ lines of code which is just plain boring to read over. Is there anyway to dynamically name and create rows using loops?
Here is a chunk of my code that works just fine but is repeated an insane amount. The only difference between the blocks(Besides the index which is easy to loop over and change) are the variable names that I put a ** by:
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet worksheet = workbook.createSheet("Ions");
HSSFRow **name = worksheet.createRow((short) 0);
HSSFCell **cellA1 = **name.createCell((short) 0);
**cellA1.setCellValue("Name: ");
HSSFRow **lot = worksheet.createRow((short) 1);
HSSFCell **cellA2 = **lot.createCell((short) 0);
**cellA2.setCellValue("Lot #: ");
//..... This is done 46 more times!
I have created some arrays that hold the strings that I want to be the variable names but cannot figure out how to implement this if it is even possible. So far this is what I was thinking, it doesn't work but shows the idea I am trying to get to:
String[] nameString = {"name", "lot",...etc};
String[] cells = new String[50];//cellA1-A46
for(int i=0; i<46; i++){
cells[i] = "cellA"+(i+1);
System.out.print(cells[i] + ", ");
}
String[] text = {"Name: ", "Lot #: ",...etc};
for(int i = 0; i < 46; i++){
//creates row named from the index of nameString[].
HSSFRow nameString[i] = worksheet.createRow((short) i);
//creates cell named from index of cells[].
HSSFCell cells[i] = nameString[i].createCell((short) 0);
//sets that created cell equal to the index of text[]
cells[i].setCellValue(text[i]);
If anyone has any ideas please share!
Thanks! -pdatric

Missing cell policy of Apache POI Java

Can somebody please explain about the Missing cell policy of Apache POI ? What are exactly missing cells ? I didn't find the Apache POI docs link to be self-explanatory on what exactly are missing cells.
Did you read the Apache POI Excel Busy Developer's Guide?
In some cases, when iterating, you need full control over how missing or blank rows and 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).
In cases such as these, you should fetch the first and last column information for a row, then call getCell(int, MissingCellPolicy) to fetch the cell. Use a MissingCellPolicy to control how blank or null cells are handled.
If you're iterating over columns in a row, some cells that are blank may not even exist, which may causing unsuspecting code to throw a NullPointerException. A MissingCellPolicy, when passed to getCell, guides and simplifies code that tells Apache POI how to handle these kinds of cells.
CREATE_NULL_AS_BLANK - If the Cell returned doesn't exist, instead of returning null, create a new Cell with a cell type of "blank". This can help avoid NullPointerExceptions conveniently.
RETURN_BLANK_AS_NULL - Even if the cell exists but has a cell type of "blank", return null. This can allow you ignore blank cells that do exist easily.
RETURN_NULL_AND_BLANK - Don't modify the existing structure; return null for cells that don't really exist and return the blank Cell if it exists but its cell type is blank. This is the behavior of the getCell overload that doesn't take a MissingCellPolicy.
I'm using the code in java as below, it's working good for me :) hope it helps.
ArrayList<ArrayList<String>> cellArrayListHolder = new ArrayList<ArrayList<String>>();
FileInputStream excelFile = new FileInputStream(new File(fileName));
Workbook workbook = new XSSFWorkbook(excelFile);
Sheet datatypeSheet = workbook.getSheetAt(0);
Iterator<Row> iterator = datatypeSheet.iterator();
while (iterator.hasNext())
{
ArrayList<String> cellStoreArrayList = new ArrayList<String>();
Row currentRow = iterator.next();
Iterator<Cell> cellIterator = currentRow.iterator();
int column_counting = 0;
int patched_count = 0;
while (cellIterator.hasNext() && column_counting < read_column_size) {
column_counting ++;
Cell currentCell = cellIterator.next();
int missed_column = 1 - column_counting + currentCell.getColumnIndex() - patched_count;
for(int i=0; i<missed_column; i++){
cellStoreArrayList.add("");
patched_count++;
}
switch (currentCell.getCellType()){
case Cell.CELL_TYPE_STRING:
cellStoreArrayList.add(String.valueOf(currentCell).trim());
break;
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(currentCell)) {
DateFormat db_df = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy");
cellStoreArrayList.add(db_df.format(currentCell.getDateCellValue()));
} else {
cellStoreArrayList.add(String.valueOf(currentCell.getNumericCellValue()));
}
break;
case Cell.CELL_TYPE_BOOLEAN:
cellStoreArrayList.add(String.valueOf(currentCell.getBooleanCellValue()));
break;
default:
cellStoreArrayList.add("");
break;
}
}
cellArrayListHolder.add(cellStoreArrayList);
}

Blank rows is skipped while reading data from the excel sheet

i try to read the data from excel and store in vector list. But i'm having two issue when applied the following code in my system, hope can get some guidance.
1) When i run the system it will read all the data from the excel file but it skipped those blank data. How can i make it as empty string rather than skipped. Result : from this Excel file you can see that between value 145 and 2DHatchback is blank data, but system will skipped it, how can i make it as empty string " "?.
[PAS, 04/01/2015, ALFA ROMEO, 145, 2D HATCHBACK, 5 SP MANUAL, 1598.42, GZ095G, 02, 01, 02, MULTI POINT F/INJ, ITALY, 9400, 7800]
2) When i tried to deleted few rows of data in excel, my vector result still will keep the deleted data but remain as empty.
Result: from this Excel file if i manually delete row 11 and row 12, when i system.out.println the vector result it will show as [, , ] , [, , ] for deleted rows.
Readexcel.java
public Vector getexcel(String filename)
{
String filetype = filename.substring(filename.lastIndexOf(".")+1);
Vector cellVectorHolder = new Vector();
try
{
Workbook workBook = WorkbookFactory.create(new FileInputStream(filename));
Sheet sheet = workBook.getSheetAt(0);
Iterator rowIter = sheet.rowIterator();
if(filetype.equals("xlsx"))
{
while(rowIter.hasNext())
{
XSSFRow row = (XSSFRow) rowIter.next();
Iterator cellIter = row.cellIterator();
Vector cellStoreVector=new Vector();
if(row.getRowNum()>1)
{
while(cellIter.hasNext())
{
XSSFCell cell = (XSSFCell) cellIter.next();
Integer cellType = cell.getCellType();
String cellTypeDesc = "";
String cellValue = "";
switch (cellType)
{
case 0:
cellTypeDesc = "NUMERIC";
String doubleValue = cell.getRawValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
if (HSSFDateUtil.isValidExcelDate(Double.parseDouble(doubleValue))) {
Date date = HSSFDateUtil.getJavaDate(Double.parseDouble(doubleValue));
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
cellValue = df.format(date);
}
} else {
cellValue = String.valueOf(doubleValue);
}
break;
case 1:
cellTypeDesc = "STRING";
cellValue = cell.getStringCellValue();
break;
case 3:
cellTypeDesc = "BLANK";
cellValue = "";
break;
}
cellStoreVector.addElement(cellValue);
}
}
cellVectorHolder.addElement(cellStoreVector);
}
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
return cellVectorHolder;
}
Excel stores empty fields, so you need to do manual checking
You should check for rows containing only empty cells. Just write a check before you add it to the cellStoreVector
Also, if the rowNumber increases by more than 1, you could add empty row-vectors yourself. So store the previous rowNumber and compare to the current rowNumber

Apache POI formatting double numbers in Excel files

I am using apache-poi for creating some reports. I have an issue with the decimal separator. Right now I have the following displayed in the excel file:
For 111.2343 -> 111.23
For 111.23 -> 111.23
For 111.2 -> 111.2
For 111 -> 111. (see the dot at the end)
The problem is with 111 number. I don't want to see the trailing dot (or comma, depending on language).
Here is my current code to format the cells. Can this be achieved using apache-poi?
Thank you,
Iulian
PS: Is there a way to use java.text.Format in poi? I see this has DecimalFormat setDecimalSeparatorAlwaysShown method which does what I want.
private void createColumnStyle(XSSFSheet sheet, int maxRows,int col)
{
XSSFWorkbook wb = sheet.getWorkbook();
XSSFFont font = wb.createFont();
font.setFontHeightInPoints((short)10);
font.setFontName("Calibri");
XSSFCellStyle colStyle = wb.createCellStyle();
colStyle.setFont(font);
colStyle.setAlignment(HorizontalAlignment.RIGHT);
colStyle.setBorderBottom(XSSFCellStyle.BORDER_THIN);
colStyle.setBorderTop(XSSFCellStyle.BORDER_THIN);
colStyle.setBorderRight(XSSFCellStyle.BORDER_THIN);
colStyle.setBorderLeft(XSSFCellStyle.BORDER_THIN);
CreationHelper createHelper = wb.getCreationHelper();
colStyle.setDataFormat(createHelper.createDataFormat().getFormat("#,##0.##"));
for (int i=3; i<maxRows; i++ )
{
XSSFCell cell = sheet.getRow(i).createCell(col);
cell.setCellStyle(colStyle);
}
}
Using DecimalFormat works fine for all the cases:
DecimalFormat dec = new DecimalFormat("#.00");
double cellValue = Double.valueOf(dec.format(111));
XSSFCell cell = sheet.createRow(0).createCell(0);
cell.setCellValue(cellValue);
this set the cell value to 111 only.

How to read Excel cell having Date with Apache POI?

I'm using Apache POI 3.6, I want to read an excel file which has a date like this 8/23/1991.
switch (cell.getCellType()) {
...
...
case HSSFCell.CELL_TYPE_NUMERIC:
value = "NUMERIC value=" + cell.getNumericCellValue();
break;
...
}
But it takes the numeric value type and returns the value like this 33473.0.
I've tried to use Numeric Cell Type although with no luck.
dbltemp=row.getCell(c, Row.CREATE_NULL_AS_BLANK).getNumericCellValue();
if (c == 6 || c == 9) {
strTemp= new String(dbltemp.toString().trim());
long tempDate = Long.parseLong(strTemp);
Date date = new Date(tempDate);
strVal = date.toString();
}
How can I fix my problem?
NOTE: HSSFDateUtil is deprecated
If you know which cell i.e. column position say 0 in each row is going to be a date, you can go for
row.getCell(0).getDateCellValue() directly.
http://poi.apache.org/apidocs/org/apache/poi/hssf/usermodel/HSSFCell.html#getDateCellValue()
UPDATE: Here is an example - you can apply this in your switch case code above. I am checking and printing the Numeric as well as Date value. In this case the first column in my sheet has dates, hence I use row.getCell(0).
You can use the if (HSSFDateUtil.isCellDateFormatted .. code block directly in your switch case.
if (row.getCell(0).getCellType() == HSSFCell.CELL_TYPE_NUMERIC)
System.out.println ("Row No.: " + row.getRowNum ()+ " " +
row.getCell(0).getNumericCellValue());
if (HSSFDateUtil.isCellDateFormatted(row.getCell(0))) {
System.out.println ("Row No.: " + row.getRowNum ()+ " " +
row.getCell(0).getDateCellValue());
}
}
The output is
Row No.: 0 39281.0
Row No.: 0 Wed Jul 18 00:00:00 IST 2007
Row No.: 1 39491.0
Row No.: 1 Wed Feb 13 00:00:00 IST 2008
Row No.: 2 39311.0
Row No.: 2 Fri Aug 17 00:00:00 IST 2007
Yes, I understood your problem.
If is difficult to identify cell has Numeric or Data value.
If you want data in format that shows in Excel, you just need to format cell using DataFormatter class.
DataFormatter dataFormatter = new DataFormatter();
String cellStringValue = dataFormatter.formatCellValue(row.getCell(0));
System.out.println ("Is shows data as show in Excel file" + cellStringValue); // Here it automcatically format data based on that cell format.
// No need for extra efforts
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
Row row = sheet.getRow(0);
Cell cell = row.getCell(0);
if(cell.getCellTypeEnum() == CellType.NUMERIC||cell.getCellTypeEnum() == CellType.FORMULA)
{
String cellValue=String.valueOf(cell.getNumericCellValue());
if(HSSFDateUtil.isCellDateFormatted(cell))
{
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date date = cell.getDateCellValue();
cellValue = df.format(date);
}
System.out.println(cellValue);
}
For reading date cells this method has proven to be robust so far:
private LocalDate readCellAsDate(final Row row, final int pos) {
if (pos == -1) {
return null;
}
final Cell cell = row.getCell(pos - 1);
if (cell != null) {
cell.setCellType(CellType.NUMERIC);
} else {
return null;
}
if (DateUtil.isCellDateFormatted(cell)) {
try {
return cell.getDateCellValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
} catch (final NullPointerException e) {
logger.error(e.getMessage());
return null;
}
}
return null;
}
You need the DateUtils: see this article for details.
Or, better yet, use Andy Khan's JExcel instead of POI.
Apache Poi has a DateUtil.isCellDateFormatted(XSSFCell) it works great.
Object objData = switch (cell.getCellType()){
case NUMERIC ->{
if(DateUtil.isCellDateFormatted(cell)){
yield cell.getDateCellValue();
}else{
yield cell.getNumericCellValue();
}
} //The rest of the cellTypes need to be implemented.
}
objData can now be tested for Date or Double.
You can use CellDateFormatter to fetch the Date in the same format as in excel cell. See the following code:
CellValue cv = formulaEv.evaluate(cell);
double dv = cv.getNumberValue();
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date date = HSSFDateUtil.getJavaDate(dv);
String df = cell.getCellStyle().getDataFormatString();
strValue = new CellDateFormatter(df).format(date);
}
If you know the cell number, then i would recommend using getDateCellValue() method
Here's an example for the same that worked for me -
java.util.Date date = row.getCell().getDateCellValue();
System.out.println(date);
Try this code.
XSSFWorkbook workbook = new XSSFWorkbook(new File(result));
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();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
if (cell.getNumericCellValue() != 0) {
//Get date
Date date = row.getCell(0).getDateCellValue();
//Get datetime
cell.getDateCellValue()
System.out.println(date.getTime());
}
break;
}
}
}
Hope is help.

Categories

Resources