I have a excel file named abc.xls in my c: drive (local computer) , now in that excel file in the first sheet itself there is a table as shown below and this below table can lie in any range with in the sheet so i have developed the below java program which will scan the entire sheet first by row basis and then on column basis and will find the cell where
TradeRef is there
TradeRef TMS Deal Date
12 45 DRT 23/97/2014
23 36 QWE 21/07/2015
now the problem in my below program is that it captures the cell where TradeRef is there and then it iterates over the columns and then in similar fashion it captures the next row and iterating over the columns
but the logic that i want to apply is that when it captures the TradeRef cell and iterating over the columns and reached to the last column of the table which is Date in the above table then it should further scan the next 20 columns within the same row and if within the next 20 columns there is no cell having any value then it should move to the next row and if within the 20 columns it mite be that any cell can have value then in that case it should read that cell value
so it would be like
TradeRef TMS Deal Date <----- scan next 20 columns is there is no value in next 20 cells then move to next row else include that cell value also------->
12 45 DRT 23/97/2014
23 36 QWE 21/07/2015
so please advise how to implement the above logic of scanning the next 20 columns within the row below is my earlier implementation that is
public class AAA {
public static void main(String[] args) throws IOException {
FileInputStream file = null ;
try {
file = new FileInputStream(new File("C:\\abc.xls"));
HSSFWorkbook workbook = new HSSFWorkbook(file);
HSSFSheet firstSheet = workbook.getSheetAt(0);
Iterator<Row> iterator = firstSheet.iterator();
Cell c = findFirstRow(firstSheet);
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
file.close();
}
}
public static Cell findFirstRow(HSSFSheet firstSheet) {
for (Row row : firstSheet) {
for (Cell cell : row) {
cell.setCellType(cell.CELL_TYPE_STRING);
if ("TradeRef".equals(cell.getStringCellValue())) {
int row1 = cell.getRowIndex() + 1;
int col = cell.getColumnIndex();
if (firstSheet.getRow(row1) == null)
throw new RuntimeException("Row " + row1 + 1 + " is empty!");
Cell startOfFirstDataRow = firstSheet.getRow(row1).getCell(col);
if (startOfFirstDataRow == null) {
CellReference ref = new CellReference(row1, col);
throw new RuntimeException("Data not found at " + ref.formatAsString());
}
return startOfFirstDataRow;
}
}
}
throw new RuntimeException("TradingRef header cell not found!");
}
}
so please advise how can i implement the above logic of scanning next 20 columns
First, you should probably use the org.apache.poi.ss.usermodel API, which work with all Excel files while the HSSF* classes only work with .xls files.
The org.apache.poi.ss.usermodel.Sheet class has a getFirstRow() method that you can use to start your search. Next you want to find a sequence of Cells containing the given Strings, like:
// This is an array containing the headers
final String[] headers = { "TradeRef", "TMS", "Deal", "Date" };
// now we take row from above to be the Row object where we seek our headers
int last = row.getLastCellNum();
for (int c = row.getFirstCellNum(); c < last; c++) {
int h = 0;
// check if the cell at (c + h) has the required value
for (; h < headers.length && c + h < last; h++) {
if (!headers[h].equals(row.getCell(c + h).getStringCellValue())) {
break; // if the cell value differs from our header
}
}
if (h == headers.length) // this means the break was never invoked
return c; // found it
}
return -1; // not found
if you want to skip column you can use
while (cellsInRow.hasNext()) {
Cell currentCell = cellsInRow.next();
if (currentCell.getColumnIndex() >= 3 && currentCell.getColumnIndex() <= 6) {
continue;
}
}
to skip column 4, 5, 6 and 7 from excel file. index starts at 0
Related
I am trying to merge two cells into one
for (String cellLLL : sheetNumd) {
XSSFSheet sheets = workbook.getSheet(cellLLL);
if (sheets != null) {
for (int rowNum = 4; rowNum < sheets.getLastRowNum() + 1; rowNum++) {
Row row = sheets.getRow(rowNum);
//sheets.addMergedRegion(new CellRangeAddress(4, 5, 6, 6));
if (row != null) {
for (Cell cell : row) {
int columnIndex = cell.getColumnIndex();
switch (columnIndex) {
case 6:
cellValue6 = cell.getStringCellValue();
break;
}
}
}
if (cellLLL.equals("Sheet1")) {
list6.add(cellValue6);
}
The cells I want to merge are G5 and G6
In my example I comment out the code where I am trying to do it. But if I run it, then I get an error -
java.lang.IllegalStateException: Cannot add merged region G5:G6 to sheet because it overlaps with an existing merged region (G5:G6).
Maybe I'm doing something wrong. Please tell me
The library I am using is Apache Poi
I am trying to export excel file which contains pivot using apache poi but for one of the cell where data have more than 255 characters, it is getting exported but after opening excel file it is showing me below error:
Repaired Records: PivotTable report from /xl/pivotCache/pivotCacheDefinition1.xml part (PivotTable cache)
And I using below code to do it.
void addRowLabel(XSSFPivotTable pivotTable, Sheet dataSheet, AreaReference areaReference,
int column, boolean isColumn) {
try {
DataFormatter formatter = new DataFormatter(java.util.Locale.US);
java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (int r = areaReference.getFirstCell().getRow() + 1; r < areaReference.getLastCell().getRow()
+ 1; r++) {
uniqueItems.add(formatter.formatCellValue(dataSheet.getRow(r).getCell(column)));
}
// build pivot table and cache
pivotTable.addRowLabel(column);
CTPivotField ctPivotField = pivotTable.getCTPivotTableDefinition().getPivotFields()
.getPivotFieldArray(column);
int i = 0;
for (String item : uniqueItems) {
// take the items as numbered items: <item x="0"/><item x="1"/>
ctPivotField.getItems().getItemArray(i).unsetT();
ctPivotField.getItems().getItemArray(i).setX((long) i);
// build a cache definition which has shared elements for those items
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields()
.getCacheFieldArray(column).getSharedItems().addNewS().setV(item);
i++;
}
ctPivotField.setOutline(false); // no outline format
ctPivotField.setDefaultSubtotal(false); // no subtotals for this field
if (ctPivotField.getDefaultSubtotal())
i++; // let one default item be if there shall be subtotals
for (int k = ctPivotField.getItems().getItemList().size() - 1; k >= i; k--) {
ctPivotField.getItems().removeItem(k);
}
ctPivotField.getItems().setCount(i);
} catch (Exception e) {
e.printStackTrace();
}
}
And the record which is not getting not working is something as below:
2046 Fidfl HCA-Varofter that see dosfiwrd dpbigeufs norsslettnt priutyits l\u0027abnesce d\u0027acte iotewwuptif de prescription appn de pouiprr lty annlwqr. Melkje en place un dikdfgitif de sqwei des dolocvprs ahjocaghjres indus qer n\u0027ont psd entype faft l\u0027obrtt d\u0027un plan d\u0027action en pltouvrement.
If someone knows how to allow string with greater than 255 characters in pivot using poi please help me out on it.
In case if anyone get help from this below line will help to add text with more than 255 characters:
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldArray(column).getSharedItems().setLongText(true);
Full code below:
void addRowLabel(XSSFPivotTable pivotTable, Sheet dataSheet, AreaReference areaReference,
int column, boolean isColumn) {
try {
DataFormatter formatter = new DataFormatter(java.util.Locale.US);
java.util.TreeSet<String> uniqueItems = new java.util.TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (int r = areaReference.getFirstCell().getRow() + 1; r < areaReference.getLastCell().getRow()
+ 1; r++) {
uniqueItems.add(formatter.formatCellValue(dataSheet.getRow(r).getCell(column)));
}
pivotTable.addRowLabel(column);
CTPivotField ctPivotField = pivotTable.getCTPivotTableDefinition().getPivotFields()
.getPivotFieldArray(column);
int i = 0;
for (String item : uniqueItems) {
// take the items as numbered items: <item x="0"/><item x="1"/>
ctPivotField.getItems().getItemArray(i).unsetT();
ctPivotField.getItems().getItemArray(i).setX((long) i);
// here you can add that line
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields()
.getCacheFieldArray(column).getSharedItems().setLongText(true);
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields()
.getCacheFieldArray(column).getSharedItems().addNewS().setV(item);
i++;
}
ctPivotField.setOutline(false); // no outline format
ctPivotField.setDefaultSubtotal(false); // no subtotals for this field
if (ctPivotField.getDefaultSubtotal())
i++; // let one default item be if there shall be subtotals
for (int k = ctPivotField.getItems().getItemList().size() - 1; k >= i; k--) {
ctPivotField.getItems().removeItem(k);
}
ctPivotField.getItems().setCount(i);
} catch (Exception e) {
e.printStackTrace();
}
}
I am using the APACHE POI library to read an excel file in xlsx format.
My problem is that I want to remove the last row from each sheet of this excel, I found a way to find the last row to remove, but it returns an int. The method sheet.removeRow(Row var1); would solve my problem.
Well, having the row number that I want to delete and a method to delete that row. I just need to convert the lastRow (int) in a Row type so I can use the sheet.removeRow method.
To do that I used the following code: Row a = sheet.getRow(lastRow) this method should return a Row with that index. But instead it returns NULL.
Any idea what I'm doing wrong or how to convert the line number I want to remove into a Row type?
Appreciate your help!
Here is an excerpt of the code that read my excel file
public static List<Measure> excelToMeasures(InputStream is, ProjectMeasureFile projectMeasureFile) throws IOException {
List<Measure> measures = new ArrayList<>();
try (Workbook workbook = new XSSFWorkbook(is)) {
for (int i = 0; i < 3; i++) {
Sheet sheet = workbook.getSheetAt(i);
int lastRow = sheet.getPhysicalNumberOfRows() -1;
removeRow(sheet, lastRow);
int rowNumber = 0;
for (Row row : sheet) {
// skip header
if (rowNumber == 0) {
rowNumber++;
continue;
}
Iterator<Cell> cellIterator = row.iterator();
List<Cell> cellObject = new ArrayList<>();
while (cellIterator.hasNext()) {
cellObject.add(cellIterator.next());
}
if (cellObject.size() > 0) {
Measure measure = new Measure();
measure.setArea(sheet.getSheetName());
measure.setCode(convertStringCell(cellObject.get(0)));
measure.setBehavior(convertStringCell(cellObject.get(1)));
measure.setHumanDependencyFactor(convertNumericCell(cellObject.get(2)));
Double measureType = convertToPercentage(measure.getHumanDependencyFactor());
measure.setHumanDependencyFactor(measureType);
measure.setMeasurementResults(convertNumericCell(cellObject.get(3)));
Double value = convertToPercentage(measure.getMeasurementResults());
measure.setMeasurementResults(value);
measure.setProjectMeasureFile(projectMeasureFile);
measures.add(measure);
}
rowNumber++;
}
}
} catch (Exception e) {
log.error("An error occurred when trying to parse the file.");
e.printStackTrace();
}
return measures;
}
And here is the method for removing a row:
public static void removeRow(Sheet sheet, int rowIndex) {
int lastRowNum = sheet.getPhysicalNumberOfRows() -1;
if (rowIndex == lastRowNum) {
Row removingRow = sheet.getRow(rowIndex);
sheet.getRow(rowIndex);
Row a = sheet.getRow(rowIndex);
if (removingRow != null) {
System.out.println(sheet.getRow(lastRowNum).getCell(0).toString());
sheet.removeRow(removingRow);
}
}
}
At first to title of your question: Sheet.getRow will return NULL by design. It returns NULL if the row behind the row index is not stored in sheet. So you always need to check for NULL after Sheet.getRow. Same is for Row.getCell which returns NULL by design for cells which are not stored in the row.
And Sheet.getPhysicalNumberOfRows is not the correct way to get the last row in sheet.
A Excel sheet only physically contains rows having cells stored in them. Rows which are completely empty are not physically stored. So if a sheet only contains data in rows 1, 2, 5, 6 and 7, then Sheet.getPhysicalNumberOfRows will return 5 but last row is 7.
There is Sheet.getLastRowNum to get the last row number (0-based) in sheet. So that would return 6 in the example above and sheet.getRow(6) would get the last row and not NULL.
But there is another problem to consider. In Excel rows might not be totally empty but only contains cells which are blank. Blank cells might be stored because they have cell formats or they had content before. Sheet.getLastRowNum gets the last stored row, even if this row only contains blank cells. So you need to check whether the row behind Sheet.getLastRowNum contains only blank cells by iterating over the cells and check for CellType.BLANK if you need the last filled row.
The following method gets the last filled row in a sheet. It returns NULL if no filled row was found.
Row getLastFilledRow(Sheet sheet) {
int lastStoredRowNum = sheet.getLastRowNum();
for (int r = lastStoredRowNum; r >= 0; r--) {
Row row = sheet.getRow(r);
if (row != null) {
for (Cell cell : row) {
if (cell.getCellType() != CellType.BLANK) return row;
}
}
}
return null;
}
I'm try to make a export Excel, and i need some formula for count number in my excel , but i have a data from database and it will be more than one. so i wanna clone that formula to next data.
it goes well , but the reference cell can't change to next cell, like if we tried copy cell from excel
cellOne[data].setCellFormula(celltwo[data].getCellFormula());
i want to copy count from data1 to data2
Instead of manipulating the formula strings to update formula references, best practice is really using a FormulaParser in my opinion. Advantage is that really all possible formulas can be updated as long as the FormulaParser knows them. Manipulating the formula strings easily leads to problems. For example a formula template like "SUM(H%d;I%d)" has %d as a variable to be replaced. But the percent sign could also be a not variable part in some formulas.
The apache poi has a FormulaParser which can be used. In Apache POI update formula references when copying I have shown this already for XSSF only.
Since this question is about HSSF I will show an String copyFormula(Sheet sheet, String formula, int coldiff, int rowdiff) method which works for SS that is for HSSFas well as for XSSF.
import java.io.FileOutputStream;
import org.apache.poi.ss.formula.*;
import org.apache.poi.ss.formula.ptg.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
public class ExcelCopyFormula {
private static String copyFormula(Sheet sheet, String formula, int coldiff, int rowdiff) {
Workbook workbook = sheet.getWorkbook();
EvaluationWorkbook evaluationWorkbook = null;
if (workbook instanceof HSSFWorkbook) {
evaluationWorkbook = HSSFEvaluationWorkbook.create((HSSFWorkbook) workbook);
} else if (workbook instanceof XSSFWorkbook) {
evaluationWorkbook = XSSFEvaluationWorkbook.create((XSSFWorkbook) workbook);
}
Ptg[] ptgs = FormulaParser.parse(formula, (FormulaParsingWorkbook)evaluationWorkbook,
FormulaType.CELL, sheet.getWorkbook().getSheetIndex(sheet));
for (int i = 0; i < ptgs.length; i++) {
if (ptgs[i] instanceof RefPtgBase) { // base class for cell references
RefPtgBase ref = (RefPtgBase) ptgs[i];
if (ref.isColRelative())
ref.setColumn(ref.getColumn() + coldiff);
if (ref.isRowRelative())
ref.setRow(ref.getRow() + rowdiff);
}
else if (ptgs[i] instanceof AreaPtgBase) { // base class for range references
AreaPtgBase ref = (AreaPtgBase) ptgs[i];
if (ref.isFirstColRelative())
ref.setFirstColumn(ref.getFirstColumn() + coldiff);
if (ref.isLastColRelative())
ref.setLastColumn(ref.getLastColumn() + coldiff);
if (ref.isFirstRowRelative())
ref.setFirstRow(ref.getFirstRow() + rowdiff);
if (ref.isLastRowRelative())
ref.setLastRow(ref.getLastRow() + rowdiff);
}
}
formula = FormulaRenderer.toFormulaString((FormulaRenderingWorkbook)evaluationWorkbook, ptgs);
return formula;
}
public static void main(String[] args) throws Exception {
//String type = "XSSF";
String type = "HSSF";
try (Workbook workbook = ("XSSF".equals(type))?new XSSFWorkbook():new HSSFWorkbook();
FileOutputStream out = new FileOutputStream(("XSSF".equals(type))?"Excel.xlsx":"Excel.xls") ) {
Sheet sheet = workbook.createSheet();
for (int r = 2 ; r < 10; r++) {
Row row = sheet.createRow(r);
for (int c = 2 ; c < 5; c++) {
Cell cell = row.createCell(c);
if (r == 2) {
if (c == 2) cell.setCellValue("No");
if (c == 3) cell.setCellValue("Number One");
if (c == 4) cell.setCellValue("Number Two");
} else {
if (c == 2) cell.setCellValue("data" + (r-2));
if (c == 3) cell.setCellValue(r*c);
if (c == 4) cell.setCellValue(r*c);
}
}
}
for (int r = 2 ; r < 10; r++) {
Row row = sheet.getRow(r);
Cell cell = row.createCell(5);
String formula = "D4+E4";
if (r == 2) cell.setCellValue("Formula");
else cell.setCellFormula(copyFormula(sheet, formula, 0, r-3));
}
for (int r = 2 ; r < 10; r++) {
Row row = sheet.getRow(r);
Cell cell = row.createCell(6);
String formula = "G4+F5";
if (r == 2) cell.setCellValue("Cumulative");
else if (r == 3) cell.setCellFormula("F4");
else cell.setCellFormula(copyFormula(sheet, formula, 0, r-4));
}
workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();
workbook.write(out);
}
}
}
I don't find how to remove a column with the Apache POI API.
I would appreciate a sample code or help on this point.
Alan Williamson on the mailing list wrote a small helper for column removal
package org.alanwilliamson.openbd.plugin.spreadsheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
/*
* Helper functions to aid in the management of sheets
*/
public class SheetUtility extends Object {
/**
* Given a sheet, this method deletes a column from a sheet and moves
* all the columns to the right of it to the left one cell.
*
* Note, this method will not update any formula references.
*
* #param sheet
* #param column
*/
public static void deleteColumn( Sheet sheet, int columnToDelete ){
int maxColumn = 0;
for ( int r=0; r < sheet.getLastRowNum()+1; r++ ){
Row row = sheet.getRow( r );
// if no row exists here; then nothing to do; next!
if ( row == null )
continue;
// if the row doesn't have this many columns then we are good; next!
int lastColumn = row.getLastCellNum();
if ( lastColumn > maxColumn )
maxColumn = lastColumn;
if ( lastColumn < columnToDelete )
continue;
for ( int x=columnToDelete+1; x < lastColumn + 1; x++ ){
Cell oldCell = row.getCell(x-1);
if ( oldCell != null )
row.removeCell( oldCell );
Cell nextCell = row.getCell( x );
if ( nextCell != null ){
Cell newCell = row.createCell( x-1, nextCell.getCellType() );
cloneCell(newCell, nextCell);
}
}
}
// Adjust the column widths
for ( int c=0; c < maxColumn; c++ ){
sheet.setColumnWidth( c, sheet.getColumnWidth(c+1) );
}
}
/*
* Takes an existing Cell and merges all the styles and forumla
* into the new one
*/
private static void cloneCell( Cell cNew, Cell cOld ){
cNew.setCellComment( cOld.getCellComment() );
cNew.setCellStyle( cOld.getCellStyle() );
switch ( cNew.getCellType() ){
case Cell.CELL_TYPE_BOOLEAN:{
cNew.setCellValue( cOld.getBooleanCellValue() );
break;
}
case Cell.CELL_TYPE_NUMERIC:{
cNew.setCellValue( cOld.getNumericCellValue() );
break;
}
case Cell.CELL_TYPE_STRING:{
cNew.setCellValue( cOld.getStringCellValue() );
break;
}
case Cell.CELL_TYPE_ERROR:{
cNew.setCellValue( cOld.getErrorCellValue() );
break;
}
case Cell.CELL_TYPE_FORMULA:{
cNew.setCellFormula( cOld.getCellFormula() );
break;
}
}
}
}
The answer of cporte is perfectly fine but imho a bit hard to read.
The Idea:
For every row, delete the cell representing the column which shall be deleted and move all cells to the right of this column one to the left.
The simplified Implementation:
//Variables for completeness
Sheet sheet;
int columnToDelete;
for (int rId = 0; rId <= sheet.getLastRowNum(); rId++) {
Row row = sheet.getRow(rId);
for (int cID = columnToDelete; cID < row.getLastCellNum(); cID++) {
Cell cOld = row.getCell(cID);
if (cOld != null) {
row.removeCell(cOld);
}
Cell cNext = row.getCell(cID + 1);
if (cNext != null) {
Cell cNew = row.createCell(cID, cNext.getCellType());
cloneCell(cNew, cNext);
sheet.setColumnWidth(cID, sheet.getColumnWidth(cID + 1));
}
}
}
The clone cell method copied from the other answer for completeness:
private static void cloneCell( Cell cNew, Cell cOld ){
cNew.setCellComment( cOld.getCellComment() );
cNew.setCellStyle( cOld.getCellStyle() );
switch ( cNew.getCellType() ){
case Cell.CELL_TYPE_BOOLEAN:{
cNew.setCellValue( cOld.getBooleanCellValue() );
break;
}
case Cell.CELL_TYPE_NUMERIC:{
cNew.setCellValue( cOld.getNumericCellValue() );
break;
}
case Cell.CELL_TYPE_STRING:{
cNew.setCellValue( cOld.getStringCellValue() );
break;
}
case Cell.CELL_TYPE_ERROR:{
cNew.setCellValue( cOld.getErrorCellValue() );
break;
}
case Cell.CELL_TYPE_FORMULA:{
cNew.setCellFormula( cOld.getCellFormula() );
break;
}
}
}
codewing's solution worked for me like a charm with the following minor changes:
When we clone the cell, the call should be cloneCell(cNew, cNext)
We should set the column width only for the first row.
I'm using version 3.17 of the api, so a few things changed (like CellType changed from int to an enum).
Full code is below (for clarity):
private void deleteColumn(Sheet sheet, int columnToDelete) {
for (int rId = 0; rId < sheet.getLastRowNum(); rId++) {
Row row = sheet.getRow(rId);
for (int cID = columnToDelete; cID < row.getLastCellNum(); cID++) {
Cell cOld = row.getCell(cID);
if (cOld != null) {
row.removeCell(cOld);
}
Cell cNext = row.getCell(cID + 1);
if (cNext != null) {
Cell cNew = row.createCell(cID, cNext.getCellTypeEnum());
cloneCell(cNew, cNext);
//Set the column width only on the first row.
//Other wise the second row will overwrite the original column width set previously.
if(rId == 0) {
sheet.setColumnWidth(cID, sheet.getColumnWidth(cID + 1));
}
}
}
}
}
private void cloneCell(Cell cNew, Cell cOld) {
cNew.setCellComment(cOld.getCellComment());
cNew.setCellStyle(cOld.getCellStyle());
if (CellType.BOOLEAN == cNew.getCellTypeEnum()) {
cNew.setCellValue(cOld.getBooleanCellValue());
} else if (CellType.NUMERIC == cNew.getCellTypeEnum()) {
cNew.setCellValue(cOld.getNumericCellValue());
} else if (CellType.STRING == cNew.getCellTypeEnum()) {
cNew.setCellValue(cOld.getStringCellValue());
} else if (CellType.ERROR == cNew.getCellTypeEnum()) {
cNew.setCellValue(cOld.getErrorCellValue());
} else if (CellType.FORMULA == cNew.getCellTypeEnum()) {
cNew.setCellValue(cOld.getCellFormula());
}
}
I think you have to go down each HSSFRow and call HSSFRow.getCell and then HSSFRow.removeCell. The API is oriented towards rows, rather than columns, and very few operations work at the whole column level.
Sample code (untested):
HSSFSheet sheet = ...
int colToRemove = 5;
Iterator rowIter = sheet.iterator();
while (rowIter.hasNext()) {
HSSFRow row = (HSSFRow)rowIter.next();
HSSFCell cell = row.getCell(colToRemove);
row.removeCell(cell);
}
There is a term confusion: the action that author author would like to achieve is called column shift it terms of Apache POI interface. org.apache.poi.ss.usermodel.Sheet interface provide a clean method to do such thing:
sheet.shiftColumns(startRangeIndex, endRangeIndex, directionQuantifier);
For instance, moving Column B to one position left is easily achievable by calling:
Sheet sheet = loadRequiredSheet();
sheet.shiftColumns(2, 3, -1);
Column A Column B Column C
Data here to be removed <- t should be moved to the left
The code above is working perfectly but I did some modification over the POI version which we are using in case you are using POI version4.0.0.
You can refer the code below for deleting column in excel by using java and POI.
public static void deleteColumn(XSSFSheet sheet, int columnToDelete) {
for (int rId = 0; rId < sheet.getLastRowNum(); rId++) {
Row row = sheet.getRow(rId);
for (int cID = columnToDelete; cID < row.getLastCellNum(); cID++) {
Cell cOld = row.getCell(cID);
if (cOld != null) {
row.removeCell(cOld);
}
Cell cNext = row.getCell(cID + 1);
if (cNext != null) {
Cell cNew = row.createCell(cID, cNext.getCellType());
cloneCell(cNew, cNext);
//Set the column width only on the first row.
//Other wise the second row will overwrite the original column width set previously.
if(rId == 0) {
sheet.setColumnWidth(cID, sheet.getColumnWidth(cID + 1));
}
}
}
}
}
public static void cloneCell(Cell cNew, Cell cOld) {
cNew.setCellComment(cOld.getCellComment());
cNew.setCellStyle(cOld.getCellStyle());
if (CellType.BOOLEAN == cNew.getCellType()) {
cNew.setCellValue(cOld.getBooleanCellValue());
} else if (CellType.NUMERIC == cNew.getCellType()) {
cNew.setCellValue(cOld.getNumericCellValue());
} else if (CellType.STRING == cNew.getCellType()) {
cNew.setCellValue(cOld.getStringCellValue());
} else if (CellType.ERROR == cNew.getCellType()) {
cNew.setCellValue(cOld.getErrorCellValue());
} else if (CellType.FORMULA == cNew.getCellType()) {
cNew.setCellValue(cOld.getCellFormula());
}
}