15

我找不到如何使用 Apache POI API 删除列。
在这一点上,我将不胜感激示例代码或帮助。

4

5 回答 5

18

邮件列表上的 Alan Williamson了一个小帮手,用于移除列

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;
            }
        }

    }
}
于 2012-09-25T13:32:10.597 回答
4

cporte 的答案非常好,但恕我直言有点难以阅读。


理念:

对于每一行,删除代表要删除的列的单元格,并将该列右侧的所有单元格向左移动一个。


简化的实现:

//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));
        }
    }
}


为了完整性,从另一个答案复制了克隆单元方法:

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;
        }
    }

}
于 2017-04-28T14:07:08.530 回答
3

codewing 的解决方案对我来说就像一个魅力,有以下细微的变化:

  1. 当我们克隆单元格时,调用应该是 cloneCell(cNew, cNext)
  2. 我们应该只为第一行设置列宽。
  3. 我使用的是 3.17 版的 api,所以有些地方发生了变化(比如 CellType 从 int 变为 enum)。

完整代码如下(为清楚起见):

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());
    }
}
于 2017-11-18T01:00:55.103 回答
1

我认为您必须访问每个 HSSFRow 并调用 HSSFRow.getCell,然后调用 HSSFRow.removeCell。API 面向行,而不是列,很少有操作在整个列级别进行。

示例代码(未经测试):

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);
}
于 2009-07-24T21:39:06.897 回答
0

有一个术语混淆:作者作者想要实现的操作称为列移位它术语 Apache POI 接口。org.apache.poi.ss.usermodel.Sheet接口提供了一个干净的方法来做这样的事情:

sheet.shiftColumns(startRangeIndex, endRangeIndex, directionQuantifier);

例如,将 B 列向左移动一个位置很容易通过调用来实现:

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
于 2020-07-31T03:00:07.667 回答