Apache POI xls column Remove

前端 未结 5 433
孤城傲影
孤城傲影 2020-12-17 17:47

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.

相关标签:
5条回答
  • 2020-12-17 18:12

    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;
                }
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-12-17 18:12

    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);
    }
    
    0 讨论(0)
  • 2020-12-17 18:23

    codewing's solution worked for me like a charm with the following minor changes:

    1. When we clone the cell, the call should be cloneCell(cNew, cNext)
    2. We should set the column width only for the first row.
    3. 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());
        }
    }
    
    0 讨论(0)
  • 2020-12-17 18:29

    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
    
    0 讨论(0)
  • 2020-12-17 18:36

    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;
            }
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题