How do I check if a CELL in excel sheet is empty and doesn't have any content inside it? I am traversing a row from left to right, and want to stop when I encounter an empty cell. I am using
cell.getType()==CellType.EMPTY
but it doesn't seem to work. Also,
if(cell.getContents() == "") is also not working.
What is the condition to check if the cell is a blank cell?
Thanks
Abhishek S
List cellDataList = new ArrayList();
XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator rows = sheet.rowIterator();
int number=sheet.getLastRowNum();
int lineNumber = 0;
while (rows.hasNext())
{
XSSFRow row = ((XSSFRow) rows.next());
lineNumber++;
if(lineNumber==1){continue;}
Iterator cells = row.cellIterator();
List cellTempList = new ArrayList();
int current = 0, next =1;
while(cells.hasNext())
{
XSSFCell cell = (XSSFCell) cells.next();
current = cell.getColumnIndex();
if(current<next){
}
else{
int loop = current-next;
for(int k=0;k<loop+1;k++){
cellTempList.add(null);
next = next + 1;
}
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
System.out.println(cell.getRichStringCellValue().getString());
cellTempList.add(cell.getRichStringCellValue().getString());
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.println(cell.getNumericCellValue());
cellTempList.add(String.valueOf(cell.getNumericCellValue()));
break;
case Cell.CELL_TYPE_BOOLEAN:
System.out.println(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
System.out.println(cell.getCellFormula());
cellTempList.add(cell.getCellFormula());
break;
default:
System.out.println("Inside default");
}
next = next + 1;
}
cellDataList.add(cellTempList);
}
String contents = cell.getContents();
if (contents != null && contents.length() != 0)
From the following link JExcel API, check cell.isEmpty() method to test.
Related
When i System.err.println the cell type, one of the columns cell type show in result is the formula for vlookup which i've included in excel, how can i get the cell value instead of the formula ? Please help , thanks.
Excel data : Click here to view my current excel file
Java code:
while(rowIter.hasNext())
{
HSSFRow row = (HSSFRow) rowIter.next();
Iterator cellIter = row.cellIterator();
Vector cellStoreVector=new Vector();
if(row.getRowNum()>0)
{
for (int colnum=0; colnum<colsize; colnum++)
{
HSSFCell cell = (HSSFCell) row.getCell(colnum);
//System.err.println("colsize==="+cell);
if(cell == null)
{
value= "";
}
else
{
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
value = dateFormat.format(cell.getDateCellValue());
}
else
{
double value2 = cell.getNumericCellValue();
if( Math.floor(value2) == value2 )
{
int value3 = (int)value2;
value = ""+value3;
}else{
value = String.valueOf(value2);
}
}
break;
case HSSFCell.CELL_TYPE_STRING:
value = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_BLANK:
value = "";
break;
}
}
cellStoreVector.addElement(value+"");
}
cellVectorHolder.addElement(cellStoreVector);
}
}
result :
colsize===null
colsize===null
colsize===null
colsize===null
colsize===null
colsize===IF(ISBLANK(E926),"",VLOOKUP(E926,BANKCODE,2,FALSE))
colsize===null
Use FormulaEvaluator as described in documents https://poi.apache.org/spreadsheet/eval.html
There are three method to evaluate formula with FormulaEvaluator
evaluate formula and just return result: evaluate(Cell cell)
evaluate formula and replace formula with result: evaluateInCell(Cell cell)
evaluate formula and write result in cell alongside with formula: evaluateFormulaCell(Cell cell)
Quote from POI documentation for last option:
Using FormulaEvaluator.evaluateFormulaCell(Cell cell)
evaluateFormulaCell(Cell cell) will check to see if the supplied cell is a formula cell. If it isn't, then no changes will be made to it. If it is, then the formula is evaluated. The value for the formula is saved alongside it, to be displayed in excel. The formula remains in the cell, just with a new value
The return of the function is the type of the formula result, such as Cell.CELL_TYPE_BOOLEAN
FileInputStream fis = new FileInputStream("/somepath/test.xls");
Workbook wb = new HSSFWorkbook(fis); //or new XSSFWorkbook("/somepath/test.xls")
Sheet sheet = wb.getSheetAt(0);
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
// suppose your formula is in B3
CellReference cellReference = new CellReference("B3");
Row row = sheet.getRow(cellReference.getRow());
Cell cell = row.getCell(cellReference.getCol());
if (cell!=null) {
switch (evaluator.evaluateFormulaCell(cell)) {
case Cell.CELL_TYPE_BOOLEAN:
System.out.println(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.println(cell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
System.out.println(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_ERROR:
System.out.println(cell.getErrorCellValue());
break;
// CELL_TYPE_FORMULA will never occur
case Cell.CELL_TYPE_FORMULA:
break;
}
}
im developing one tool for uploading excel and validate it, but excel file is large and the row count is about 65536.
here is my code used for uploading and reading the excel sheet values
int firstColNo = 1;
int rowcount = sheet.getRows();
int colCount = sheet.getColumns();
int row = 0;
String comp = "";
for (row = 1; row < rowcount; row++) {
if (labelCell != null) {
cell = sheet.getCell(firstColNo, row);
if (cell.getContents() != null && cell.getContents().length() > 0){
String compoundId = cell.getContents();
System.out.println(compoundId);
} else {
System.out.println("-");
}
}
}
by reading the row values it takes more to time to read, is there any way to make it faster else any code modifications need to be done in my code?
can anybody help me to overcome this issue.
Here is an example for you
HSSFWorkbook workbook = new HSSFWorkbook(file);
//Get first sheet from the workbook
HSSFSheet sheet = workbook.getSheetAt(0);
//Iterate through each rows from first sheet
Iterator<Row> rowIterator = sheet.iterator();
while(rowIterator.hasNext()) {
Row row = rowIterator.next();
//For each row, iterate through each columns
Iterator<Cell> cellIterator = row.cellIterator();
while(cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch(cell.getCellType()) {
case Cell.CELL_TYPE_BOOLEAN:
System.out.print(cell.getBooleanCellValue() + "\t\t");
break;
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "\t\t");
break;
}
}
System.out.println("");
}
I'm having a problem in excel while using Apache POI. I can read across rows, but sometimes I'm in a situation where I would like to read a particular column only.
So is it possible to read any particular column like only the 'A' column only or the column 'C' only.
I'm using the Java language for this.
heikkim is right, here is some sample code adapted from some code I have:
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Row;
...
for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
row = sheet.getRow(rowIndex);
if (row != null) {
Cell cell = row.getCell(colIndex);
if (cell != null) {
// Found column and there is value in the cell.
cellValueMaybeNull = cell.getStringCellValue();
// Do something with the cellValueMaybeNull here ...
// break; ???
}
}
}
For the colCount use something like row.getPhysicalNumberOfCells()
Sheet sheet = workBook.getSheetAt(0); // Get Your Sheet.
for (Row row : sheet) { // For each Row.
Cell cell = row.getCell(0); // Get the Cell at the Index / Column you want.
}
My solution, a bit simpler code wise.
Okay, from your question, you just simply want to read a particular column. So, while iterating over a row and then on its cells, your can simply check the index of the column.
Iterator<Row> rowIterator = mySheet.iterator(); // Traversing over each row of XLSX file
while (rowIterator.hasNext()) {
Row row = rowIterator.next(); // For each row, iterate through each columns
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
println "column index"+cell.getColumnIndex()//You will have your columns fixed in Excel file
if(cell.getColumnIndex()==3)//for example of c
{
print "done"
}
}
}
I am using POI 3.12-- 'org.apache.poi:poi:3.12'
Hope it helps. Cheers!
You could just loop the rows and read the same cell from each row (doesn't this comprise a column?).
import java.io.*;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.ss.usermodel.*;
import java.text.*;
public class XSLXReader {
static DecimalFormat df = new DecimalFormat("#####0");
public static void main(String[] args) {
FileWriter fostream;
PrintWriter out = null;
String strOutputPath = "H:\\BLR_Team\\Kavitha\\Excel-to-xml\\";
String strFilePrefix = "Master_5.2-B";
try {
InputStream inputStream = new FileInputStream(new File("H:\\BLR_Team\\Kavitha\\Excel-to-xml\\Stack-up 20L pure storage 11-0039-01 ISU_USA-A 1-30-17-Rev_exm.xls"));
Workbook wb = WorkbookFactory.create(inputStream);
// Sheet sheet = wb.getSheet(0);
Sheet sheet =null;
Integer noOfSheets= wb.getNumberOfSheets();
for(int i=0;i<noOfSheets;i++){
sheet = wb.getSheetAt(i);
System.out.println("Sheet : "+i + " " + sheet.getSheetName());
System.out.println("Sheet : "+i + " " + sheet.getFirstRowNum());
System.out.println("Sheet : "+i + " " + sheet.getLastRowNum());
//Column 29
fostream = new FileWriter(strOutputPath + "\\" + strFilePrefix+i+ ".xml");
out = new PrintWriter(new BufferedWriter(fostream));
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.println("<Bin-code>");
boolean firstRow = true;
for (Row row : sheet) {
if (firstRow == true) {
firstRow = false;
continue;
}
out.println("\t<DCT>");
out.println(formatElement("\t\t", "ID", formatCell(row.getCell(0))));
out.println(formatElement("\t\t", "Table_name", formatCell(row.getCell(1))));
out.println(formatElement("\t\t", "isProddaten", formatCell(row.getCell(2))));
out.println(formatElement("\t\t", "isR3P01Data", formatCell(row.getCell(3))));
out.println(formatElement("\t\t", "LayerNo", formatCell(row.getCell(29))));
out.println("\t</DCT>");
}
CellReference ref = new CellReference("A13");
Row r = sheet.getRow(ref.getRow());
if (r != null) {
Cell c = r.getCell(ref.getCol());
System.out.println(c.getRichStringCellValue().getString());
}
for (Row row : sheet) {
for (Cell cell : row) {
CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());
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;
case Cell.CELL_TYPE_BLANK:
System.out.println();
break;
default:
System.out.println();
}
}
}
out.write("</Bin-code>");
out.flush();
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String formatCell(Cell cell)
{
if (cell == null) {
return "";
}
switch(cell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
return "";
case Cell.CELL_TYPE_BOOLEAN:
return Boolean.toString(cell.getBooleanCellValue());
case Cell.CELL_TYPE_ERROR:
return "*error*";
case Cell.CELL_TYPE_NUMERIC:
return XSLXReader.df.format(cell.getNumericCellValue());
case Cell.CELL_TYPE_STRING:
return cell.getStringCellValue();
default:
return "<unknown value>";
}
}
private static String formatElement(String prefix, String tag, String value) {
StringBuilder sb = new StringBuilder(prefix);
sb.append("<");
sb.append(tag);
if (value != null && value.length() > 0) {
sb.append(">");
sb.append(value);
sb.append("</");
sb.append(tag);
sb.append(">");
} else {
sb.append("/>");
}
return sb.toString();
}
}
This code does 3 things:
Excel to XML file generation. Eng. Name Dong Kim
Prints the content of a particular cell : A13
Also print the excel content into normal text format. Jars to be imported: poi-3.9.jar,poi-ooxml-3.9.jar,poi-ooxml-schemas-3.9.jar,xbean-2.3.0.jar,xmlbeans-xmlpublic-2.4.0.jar,dom4j-1.5.jar
Here is the code to read the excel data by column.
public ArrayList<String> extractExcelContentByColumnIndex(int columnIndex){
ArrayList<String> columndata = null;
try {
File f = new File("sample.xlsx")
FileInputStream ios = new FileInputStream(f);
XSSFWorkbook workbook = new XSSFWorkbook(ios);
XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
columndata = new ArrayList<>();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if(row.getRowNum() > 0){ //To filter column headings
if(cell.getColumnIndex() == columnIndex){// To match column index
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
columndata.add(cell.getNumericCellValue()+"");
break;
case Cell.CELL_TYPE_STRING:
columndata.add(cell.getStringCellValue());
break;
}
}
}
}
}
ios.close();
System.out.println(columndata);
} catch (Exception e) {
e.printStackTrace();
}
return columndata;
}
Please be aware, that iterating through the columns using row cell iterator ( Iterator<Cell> cellIterator = row.cellIterator();) may lead to silent skipping columns. I have just encountered a document that was exposing such behaviour.
Iterating using indexes in a for loop and using row.getCell(i) was not skipping columns and was returning values at the correct column indexes.
Somehow I manage to create new rows between two rows in an existing excel file. The problem is, some of the formatting were not include along the shifting of the rows.
One of this, is the row that are hide are not relatively go along during the shift. What I mean is(ex.), rows from 20 to 30 is hidden, but when a create new rows the formating still there. The hidden rows must also move during the insertion/creation of new rows, it should be 21 to 31.
Another thing is, the other object in the sheet that are not in the cell. Like the text box are not move along after the new row is created. Its like the position of these object are fixed. But I want it to move, the same thing as I insert a new row or paste row in excel. If there is a function of inserting a new row, please let me know.
This what I have right now, just a snippet from my code.
HSSFWorkbook wb = new HSSFWorkbook(template); //template is the source of file
HSSFSheet sheet = wb.getSheet("SAMPLE");
HSSFRow newRow;
HSSFCell cellData;
int createNewRowAt = 9; //Add the new row between row 9 and 10
sheet.shiftRows(createNewRowAt, sheet.getLastRowNum(), 1, true, false);
newRow = sheet.createRow(createNewRowAt);
newRow = sheet.getRow(createNewRowAt);
If copy and paste of rows is possible that would be big help. But I already ask it here and can't find a solution. So I decided to create a row as an interim solution. I'm done with it but having a problem like this.
Any help will be much appreciated. Thanks!
Helper function to copy rows shamelessly adapted from here
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellRangeAddress;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class RowCopy {
public static void main(String[] args) throws Exception{
HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream("c:/input.xls"));
HSSFSheet sheet = workbook.getSheet("Sheet1");
copyRow(workbook, sheet, 0, 1);
FileOutputStream out = new FileOutputStream("c:/output.xls");
workbook.write(out);
out.close();
}
private static void copyRow(HSSFWorkbook workbook, HSSFSheet worksheet, int sourceRowNum, int destinationRowNum) {
// Get the source / new row
HSSFRow newRow = worksheet.getRow(destinationRowNum);
HSSFRow sourceRow = worksheet.getRow(sourceRowNum);
// If the row exist in destination, push down all rows by 1 else create a new row
if (newRow != null) {
worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
} else {
newRow = worksheet.createRow(destinationRowNum);
}
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
// Grab a copy of the old/new cell
HSSFCell oldCell = sourceRow.getCell(i);
HSSFCell newCell = newRow.createCell(i);
// If the old cell is null jump to next cell
if (oldCell == null) {
newCell = null;
continue;
}
// Copy style from old cell and apply to new cell
HSSFCellStyle newCellStyle = workbook.createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
;
newCell.setCellStyle(newCellStyle);
// If there is a cell comment, copy
if (oldCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
newCell.setCellValue(oldCell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
// If there are are any merged regions in the source row, copy to new row
for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
)),
cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
worksheet.addMergedRegion(newCellRangeAddress);
}
}
}
}
For people who are looking to insert a row between two rows in an existing excel with XSSF (Apache POI), there is already a method "copyRows" implemented in the XSSFSheet.
import org.apache.poi.ss.usermodel.CellCopyPolicy;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class App2 throws Exception{
public static void main(String[] args){
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("input.xlsx"));
XSSFSheet sheet = workbook.getSheet("Sheet1");
sheet.copyRows(0, 2, 3, new CellCopyPolicy());
FileOutputStream out = new FileOutputStream("output.xlsx");
workbook.write(out);
out.close();
}
}
Referencing Qwerty's answer, you can avoid to inflate XL size by re-using cellStyle.
And when the type is CELL_TYPE_BLANK, getStringCellValue returns "" instead of null.
private static void copyRow(Sheet worksheet, int sourceRowNum, int destinationRowNum) {
// Get the source / new row
Row newRow = worksheet.getRow(destinationRowNum);
Row sourceRow = worksheet.getRow(sourceRowNum);
// If the row exist in destination, push down all rows by 1 else create a new row
if (newRow != null) {
worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
} else {
newRow = worksheet.createRow(destinationRowNum);
}
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
// Grab a copy of the old/new cell
Cell oldCell = sourceRow.getCell(i);
Cell newCell = newRow.createCell(i);
// If the old cell is null jump to next cell
if (oldCell == null) {
newCell = null;
continue;
}
// Use old cell style
newCell.setCellStyle(oldCell.getCellStyle());
// If there is a cell comment, copy
if (newCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(oldCell.getCellFormula());
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
}
}
}
Referencing Qwerty's answer, if the destRow isnot null, sheet.shiftRows() will change the destRow's reference to the next row; so we should always create a new row:
if (destRow != null) {
sheet.shiftRows(destination, sheet.getLastRowNum(), 1);
}
destRow = sheet.createRow(destination);
I merged some of the other answers and comments in the following implementation, tested with Apache POI v3.9.
I have only one rownum parameter because I shift down the target row and copy it in the new empty row. Formulas are handled as expected, they are not copied verbatim, with one exception: references to cells that are above the copied line are not updated; the workaround is to replace these explicit references (if any) with references calculated using INDIRECT() as suggested by this post.
protected void copyRow(Sheet worksheet, int rowNum) {
Row sourceRow = worksheet.getRow(rowNum);
//Save the text of any formula before they are altered by row shifting
String[] formulasArray = new String[sourceRow.getLastCellNum()];
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
if (sourceRow.getCell(i) != null && sourceRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA)
formulasArray[i] = sourceRow.getCell(i).getCellFormula();
}
worksheet.shiftRows(rowNum, worksheet.getLastRowNum(), 1);
Row newRow = sourceRow; //Now sourceRow is the empty line, so let's rename it
sourceRow = worksheet.getRow(rowNum + 1); //Now the source row is at rowNum+1
// Loop through source columns to add to new row
for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
// Grab a copy of the old/new cell
Cell oldCell = sourceRow.getCell(i);
Cell newCell;
// If the old cell is null jump to next cell
if (oldCell == null) {
continue;
} else {
newCell = newRow.createCell(i);
}
// Copy style from old cell and apply to new cell
CellStyle newCellStyle = worksheet.getWorkbook().createCellStyle();
newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
newCell.setCellStyle(newCellStyle);
// If there is a cell comment, copy
if (oldCell.getCellComment() != null) {
newCell.setCellComment(oldCell.getCellComment());
}
// If there is a cell hyperlink, copy
if (oldCell.getHyperlink() != null) {
newCell.setHyperlink(oldCell.getHyperlink());
}
// Set the cell data type
newCell.setCellType(oldCell.getCellType());
// Set the cell data value
switch (oldCell.getCellType()) {
case Cell.CELL_TYPE_BLANK:
break;
case Cell.CELL_TYPE_BOOLEAN:
newCell.setCellValue(oldCell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_ERROR:
newCell.setCellErrorValue(oldCell.getErrorCellValue());
break;
case Cell.CELL_TYPE_FORMULA:
newCell.setCellFormula(formulasArray[i]);
break;
case Cell.CELL_TYPE_NUMERIC:
newCell.setCellValue(oldCell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING:
newCell.setCellValue(oldCell.getRichStringCellValue());
break;
default:
break;
}
}
// If there are any merged regions in the source row, copy to new row
for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
(newRow.getRowNum() +
(cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
)),
cellRangeAddress.getFirstColumn(),
cellRangeAddress.getLastColumn());
worksheet.addMergedRegion(newCellRangeAddress);
}
}
}
I'm using this implementation in production code.
I've implemented this in Kotlin like this:
fun Sheet.buildRow ( rowNum:Int ) : Row {
val templateRow = this.getRow( rowNum )
this.shiftRows( rowNum+1, sheet.lastRowNum, 1 )
val newRow = this.createRow( rowNum+1 )
templateRow.cellIterator().forEach {
newRow.createCell( it.columnIndex ).cellStyle = it.cellStyle
}
return templateRow
}
It doesn't copy the cell values, just the format.
Should be applicable to Java as well.
As to formulas being "updated" in the new row, since all the copying occurs after the shift, the old row (now one index up from the new row) has already had its formula shifted, so copying it to the new row will make the new row reference the old rows cells. A solution would be to parse out the formulas BEFORE the shift, then apply those (a simple String array would do the job. I'm sure you can code that in a few lines).
At start of function:
ArrayList<String> fArray = new ArrayList<String>();
Row origRow = sheet.getRow(sourceRow);
for (int i = 0; i < origRow.getLastCellNum(); i++) {
if (origRow.getCell(i) != null && origRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA)
fArray.add(origRow.getCell(i).getCellFormula());
else fArray.add(null);
}
Then when applying the formula to a cell:
newCell.setCellFormula(fArray.get(i));
I came across the same issue recently. I had to insert new rows in a document with hidden rows and faced the same issues with you. After some search and some emails in apache poi list, it seems like a bug in shiftrows() when a document has hidden rows.
I have a huge excel file with tons of columns which looks like this :-
Column1 Column2 Column3 Column4 Column5
abc def ghi
mno pqr
......
This is the code that I wrote to print these values:
try {
FileInputStream inputStr = new FileInputStream(fileName);
XSSFWorkbook xssfWork = new XSSFWorkbook(inputStr) ;
XSSFSheet sheet1 = xssfWork.getSheetAt(0);
Iterator rowItr = sheet1.rowIterator();
while ( rowItr.hasNext() ) {
XSSFRow row = (XSSFRow) rowItr.next();
System.out.println("ROW:-->");
Iterator cellItr = row.cellIterator();
while ( cellItr.hasNext() ) {
XSSFCell cell = (XSSFCell) cellItr.next();
System.out.println("CELL:-->"+cell.toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
The output generated by this code is :-
ROW:-->
CELL:-->Column1
CELL:-->Column2
CELL:-->Column3
CELL:-->Column4
CELL:-->Column5
ROW:-->
CELL:-->abc
CELL:-->def
CELL:-->ghi
ROW:-->
CELL:-->mno
CELL:-->pqr
So, If we look at the output above we can note that the cells where I left blank values was not picked up by the POI library , is there a way in which I can get these values as null. or a way to recognize that the values presented skipped blank cells?
Thanks.
If you want to get all cells, no matter if they exist or not, then the iterator isn't for you. Instead, you need to manually fetch the appropriate cells, likely with a missing cell policy
for(Row row : sheet) {
for(int cn=0; cn<row.getLastCellNum(); cn++) {
// If the cell is missing from the file, generate a blank one
// (Works by specifying a MissingCellPolicy)
Cell cell = row.getCell(cn, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// Print the cell for debugging
System.out.println("CELL: " + cn + " --> " + cell.toString());
}
}
There's more details on all of this in the Apache POI documentation on iterating over cells
I have been frustrated by this same problem. Here is what I found with poi-3.7-20101029 and poi-3.8.
RowIterator and CellIterator do not support iterating over NULL cells or rows -- only physically defined cells (which can be BLANK).
The solution that returns what I expect requires using the 0-based Row.getCell([int], Row.CREATE_NULL_AS_BLANK), much like Chavira's answer alludes to (assuming 8 cell rows). Or you can use the Cell.columnIndex value while iterating to check for jumping numbers...
Annoyingly, after creating blank cells using method #1, the iterators will return the now created BLANK cells. I consider it a bug that MissingCellPolicy is ignored by CellIterator.
The reason is quite simple: Excel files can contain as many rows and as many columns as possibles, so returning all available blank rows and columns will render the cells huge and memory intensive.
Assuming you have a 10x10 sheet, in Excel, it's not "exactly" 10x10 since you can add 11x10 very easily with blank cell, so should POI return the 11th column?
One way to do what you're requesting is to use HSSFCell.getColumnIndex().
Example:
//Assuming your have a 2 dimensional array.
String[][] values = ......;// It is assigned
POIFSFileSystem fileSystem = new POIFSFileSystem(new FileInputStream(fileName));
HSSFWorkbook workbook = new HSSFWorkbook(fileSystem);
//Going through every worksheet.
for (int sheetPos = 0; sheetPos < workbook.getNumberOfSheets(); sheetPos++) {
HSSFSheet sheet = workbook.getSheetAt(sheetPos);
int rowPos = 0;
Iterator<Row> rows = sheet.rowIterator();
while (rows.hasNext()) {
HSSFRow row = (HSSFRow) rows.next();
Iterator<Cell> cells = row.cellIterator();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
String value = "";
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_NUMERIC:
value = BigDecimal.valueOf(cell.getNumericCellValue()).toPlainString();
break;
case HSSFCell.CELL_TYPE_STRING:
value = cell.getStringCellValue();
break;
case HSSFCell.CELL_TYPE_BLANK:
value = "";
break;
case HSSFCell.CELL_TYPE_FORMULA:
value = cell.getCellFormula();
break;
default:
break;
}
values[rowPos][cell.getColumnIndex()] = value;
}
rowPos++;
}
}
Below is what worked for me. The "row.CREATE_NULL_AS_BLANK" did not appear to be valid but that could be lack of NPOI knowledge.
HSSFCell dataCell= (HSSFCell)row.GetCell(column, NPOI.SS.UserModel.MissingCellPolicy.CREATE_NULL_AS_BLANK);
for(org.apache.poi.ss.usermodel.Row tmp : hssfSheet){
for(int i = 0; i<8;i++){
System.out.println(tmp.getCell(i));
}
}
This worked for me....
int rowNumber;
int previousCell;
int currentCell;
int currentRowNumber;
HSSFCell cell;
while (rows.hasNext()) {
previousCell = -1;
currentCell = 0;
while (cellIterator.hasNext()) {
cell = (HSSFCell) cellIterator.next();
currentCell = cell.getColumnIndex();
if (previousCell == currentCell-1) {
//...
}
else {
System.out.println("Blank cell found");
}
previousCell = currentCell;
}
}
List cellDataList = new ArrayList();
int lineNumber = 0;
while (rowIterator.hasNext()) {
HSSFRow hssfRow = (HSSFRow) rowIterator.next();
//System.out.println("Befor If");
lineNumber++;
if(lineNumber==1){continue;}
//System.out.println("Out side if ");
Iterator<Cell> iterator = hssfRow.cellIterator();
List<Cell> cellTempList = new ArrayList();
int current = 0, next = 1;
while (iterator.hasNext()) {
Cell hssfCell = iterator.next();
current = hssfCell.getColumnIndex();
if(current<next){
System.out.println("Condition Satisfied");
}
else{
int loop = current-next;
System.out.println("inside else Loop value : "+(loop));
for(int k=0;k<loop+1;k++){
System.out.println("Adding nulls");
cellTempList.add(null);
next = next + 1;
}
}
cellTempList.add(hssfCell);
next = next + 1;
System.out.println("At End next value is : "+next);
}
cellDataList.add(cellTempList);
}
public String[] rowToString(Row row)
{
Iterator<Cell> cells = row.cellIterator() ;
String[] data = new String[row.getLastCellNum()] ;
int previousCell = 0 ;
Cell cell = cells.next() ;
int currentCell = cell.getColumnIndex();
while (true)
{
if (previousCell == currentCell) {
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
data[previousCell] = cell.getNumericCellValue()+"" ;
break;
case Cell.CELL_TYPE_STRING:
data[previousCell] = cell.getStringCellValue() ;
break;
/* // there could be other cases here.
case Cell.CELL_TYPE_FORMULA:
data[previousCell] =eval.evaluateFormulaCell(cell);
break;
case Cell.CELL_TYPE_BOOLEAN:
data[previousCell] = cell.getBooleanCellValue();
break;
case Cell.CELL_TYPE_BLANK:
data[previousCell] = "";
break;
case Cell.CELL_TYPE_ERROR:
data[previousCell] = "ERROR";
break;
*/
}
if(cells.hasNext()){
cell = cells.next() ;
currentCell = cell.getColumnIndex();
} else {
break ;
}
} else {
data[previousCell] = "";
}
previousCell++ ;
}
return data ;
}
for (Row row: sheet){
// This will return null if cell is empty / blank
Cell cell = row.getCell(columnNumber);
}