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
Related
I am reading cells from an Excel spreadsheet. I am reading the first cell in each row, and comparing them to a String object that I have passed into the function. The function correctly iterates over all rows and accesses the first cell in each row, but when comparing them to the String object parameter, the IF statement does not execute, despite both the value obtained from the cell and the String parameter printing the same thing. I have used '==' operators, as well as .equals() but nothing seems to let the IF statement execute.
public static ArrayList<Integer> returnCurrency(String currency, String fileName) throws IOException
{
FileInputStream excelFile = new FileInputStream(newFile(fileName));
Workbook workbook = new XSSFWorkbook(excelFile);
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> iterator = sheet.iterator();
ArrayList<Double> currencyRateArray = new ArrayList<Double>();
for( int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++)
{
Row row = sheet.getRow(rowNum);
Cell tempCell = row.getCell(0);
System.out.printf("temp cell has value of:%s\n",tempCell.getStringCellValue());
System.out.printf("currency variable is: %s\n", currency);
if(currency.equals(tempCellString))
{
System.out.println("Found the currency\n");
}
}
}
When I pass the parameter String as "USD", both print statements print "USD", but it will never print "Found the currency" as that IF statement does not execute. Any help would be appreciated :)
Found the answer - the cell in the database had the value 'USD ' instead of 'USD'.
I have 2 excel sheets:
Sheet 1 has lot of id and specific data for that ids
Sheet 2 only has some of the ids
I need to get relevant data from sheet 1 to sheet 2.
Sheet 2:
String input2 = "C:/Users/CHATHURANGA/Desktop/fiverr/New folder/Sheet2.xlsx";
FileInputStream excelFile2 = new FileInputStream(new File(input2));
Workbook workbook3 = new XSSFWorkbook(excelFile2);
Sheet datatypeSheet2 = workbook3.getSheetAt(0);
Iterator<Row> iterator2 = datatypeSheet2.iterator();
while (iterator2.hasNext()) {
Row currentRow = iterator2.next();
Iterator<Cell> cellIterator2 = currentRow.iterator();
while (cellIterator2.hasNext()) {
Cell currentCell = cellIterator2.next();
//getCellTypeEnum shown as deprecated for version 3.15
//getCellTypeEnum ill be renamed to getCellType starting from version 4.0
if (currentCell.getCellTypeEnum() == CellType.STRING) {
System.out.print(currentCell.getStringCellValue() + "--");
} else if (currentCell.getCellTypeEnum() == CellType.NUMERIC) {
System.out.print(currentCell.getNumericCellValue() + "--");
}
}
System.out.println();
}
I will read sheet 1 in the same way as shown above.
How do I match the ids from sheet 2 with the relevant data from sheet 1?
A prototype for you:
Create function read data from sheet1:
public HashMap<String, String> getSheet1Data (Sheet sheet1){
HashMap<String, String> map = new HashMap<>();
for (Row row : sheet1){
map.put (row.getCell(1).getValueAsString(), row.getCell(2).getValueAsString());
}
return map;
}
In main class create a function to populate data to sheet2
public void populateSheet2 (HashMap<String, String> map, Sheet sheet2){
for (Row row : sheet2){
String id = row.getCell(1).getValueAsString();
String data = map.get(id);
row.createCell(2).setValue(data);
}
}
I using Apache poi to import an .xlsx file that I have in my desktop area.
With the below code I can read the hole sheet that I want.
But I want to read only one line per time and only specific columns per line (for example I want only column A, F and G from the first line and save it as object, then the same for the second line, third line etc )
How can I do it?
public class main {
public static void main( String[] args ) throws Exception {
InputStream ExcelFileToRead = new FileInputStream("C:/User/Desktop/test.xlsx");
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
XSSFSheet sheet=wb.getSheetAt(0);
XSSFRow row;
XSSFCell cell;
Iterator rows = sheet.rowIterator();
while (rows.hasNext())
{
row=(XSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext())
{
cell=(XSSFCell) cells.next();
if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING)
{
System.out.print(cell.getStringCellValue()+" ");
}
else if(cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC)
{
System.out.print(cell.getNumericCellValue()+" ");
}
else
{
}
}
System.out.println();
}
}
}
A specific row can be retrieved from the Sheet object using
Sheet.getRow(index)
Where index is a zero based row number. That is, to read row 1, you must get the row at index zero, row 2 is at index 1 and so on. Similarly a specific cell can be retrieved from it's Row object using
Row.getCell(index)
Once again index is a zero based cell number where cell column A is at index 0, column B is at index 1 and so on. Therefore to retrieve the Cell at B2, you could use
Cell cell = Sheet.getRow(1).getCell(1);
below is the code for reading the excel file using poi: which is working fine
public class ReadExcelDemo {
public static void main(String[] args) {
try {
FileInputStream file = new FileInputStream(new File("demo.xlsx"));
List sheetData = new ArrayList();
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
ArrayList<Form> vipList = new ArrayList<Form>();
Iterator<Row> rowIterator = sheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
List data = new ArrayList();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
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;
}
}
}
}
Now if excel contains duplicate records I should be able to print a simple error message. How do I do that?
Example:
ID Firstname Lastname Address
1 Ron wills Paris
1 Ron wills London
Now i want to check the duplicates only for the 3 columns: ID,Firstname and Lastname together. If these columns together contain same data as shown in the above example then it needs to be considered duplicate.
I have a pojo class Form consisting of the id,firstname and lastname with getters
and setters. Each record read is written to the pojo class using the setter methods. Then I am getting the values using getters and adding them to the arraylist object. Now the list object contains all the records. How do I compare them?
Throw the data in a set and check contains before every new entry. If you use a HashSet it will be quite quick. You can just pretend everything is Strings for the compare.
Set data = new HashSet();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if(data.contains(cell.getStringCellValue())
trow new IllegalDataException()
data.add(cell.getStringCellValue();
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;
}
}
If you need to actually compare the whole row you can create a class with all the fields, and then just override the equals method. Then throw that in a set and compare.
public class ProcessAction extends DispatchAction {
String dupValue = null;
ArrayList<String> dupList = new ArrayList<String>();
private String validateDuplicateRecords(ProcessForm process) {
String errorMessage = null;
dupValue = process.getId.trim()+" "+process.getFirstname().trim()+" "+process.getLastanme().trim();
mLogger.debug("order id,ctn,item id: "+dupValue);
if (dupList.contains(dupValue)){
mLogger.debug("value not added");
errorMessage = "Duplicate Record Exists";
} else {
dupList.add(dupValue);
}
return errorMessage;
}
}
Don't forget to clear the duplicate arraylist. I my case after performing certain tasks like writing the arraylist to a file i am clearing the duplicate arraylist using:
dupList.clear();
If you don't do this then what happens is when you upload the same data once more even if the records are not duplicate it will say duplicate since the dupList arraylist contains the previous uploaded data.
Here's a tip. While you loop, add your id (value to check the duplication based on) in a hashmap. if the size of the map did not change, then it is a duplicated record because keys overwrite each other if they already exist. Here's an example from a code of mine:
switch(cellType)
{
case 0:
your_id = cell1.getNumericCellValue();
mapSize = map.size();
map.put(your_id, your_id);
mapSizeAfterPut = map.size();
if(mapSize == mapSizeAfterPut)
{
duplicatedRecordsList.add(index);
}
break;
case 1:
your_id = cell1.getStringCellValue();
mapSize = map.size();
map.put(your_id , your_id);
mapSizeAfterPut = map.size();
if(mapSize == mapSizeAfterPut)
{
duplicatedRecordsList.add(index);
}
break;
default:break;
}
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.