Donnerstag, Juni 4, 2020

Apache POI xls-Spalte Entfernen

Ich nicht finden, so entfernen Sie eine Spalte mit der Apache POI API.

Ich würde schätzen, ein Beispiel-code oder Hilfe zu diesem Punkt.

InformationsquelleAutor | 2009-07-24

4 Kommentare

  1. 14

    Alan Williamson auf der mailing-Liste schrieb ein kleiner Helfer für Spalte entfernen

    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;
                }
            }
    
        }
    }
    • Die Spaltenbreite sollte eingestellt werden, nachdem der gelöschten Spalte. Also der loop, passt sich die Spaltenbreite sollte folgendermaßen beginnen: for ( int c=columnToDelete; c < maxColumn; c++ ) …
    • Nicht schlecht, aber funktioniert nicht, wenn die zusammengeführten Spalte im header oder wo auch immer
    • Nur ein heads-up auf, dass code, da einige der verwendeten Funktionen sind jetzt veraltet: Auf „deleteColumn“, Anstelle von „Zeile.createCell( x-1, nextCell.getCellType () ) “ haben, müssen Sie auf „Zeile.createCell(x-1, nextCell.getCellTypeEnum());“ Auch in „cloneCell“ ändern „cNew.getCellType“ für „cNew.getCellTypeEnum“ und die Fälle für Ihre neuen Kollegen (auch das hinzufügen ein „NONE“ – Fall).
  2. 4

    Die Antwort von cporte ist völlig in Ordnung, aber imho ein bisschen schwer zu Lesen.


    Die Idee:

    Für jede Zeile, löschen Sie die Zelle für die Spalte, die gelöscht werden sollen, und verschieben alle Zellen rechts von dieser Spalte auf der linken Seite.


    Die vereinfachte Umsetzung:

    //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(cNext, cNew);
                sheet.setColumnWidth(cID, sheet.getColumnWidth(cID + 1));
            }
        }
    }


    Die Klon-cell-Methode kopiert aus dem anderen beantworten, der Vollständigkeit halber:

    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;
            }
        }
    
    }
    • funktioniert wie ein sharm nach dem fixieren einige kleine Probleme
    • für einschließlich alle Zeilen, die Sie haben, korrigieren Sie diese Zeile aus for(int rId = 0; rId < sheet.getLastRowNum(); rId++) zu for (int rId = 0; rId <= sheet.getLastRowNum(); rId++)
    • Ich habe aktualisiert, um dieses Problem zu beheben. Ich erinnere mich, dass ich fix hatte, dass in meinem code auch, aber vergessen, Sie zu aktualisieren hier. also vielen Dank für diesen Hinweis
  3. 2

    codewing Lösung für mich arbeitete wie ein Charme mit folgenden geringfügigen änderungen:

    1. Wenn wir duplizieren Sie die Zelle, wird der Anruf sollte cloneCell(cNew, cNext)
    2. Müssen wir die Spaltenbreite nur für die erste Zeile.
    3. Ich mit der version 3.17 der api, so dass ein paar Dinge geändert (wie CellType geändert von int, enum).

    Vollständigen code weiter unten (für die übersichtlichkeit):

    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());
        }
    }
  4. 0

    Ich denke, man muss sich für jede HSSFRow und rufen HSSFRow.getCell und dann HSSFRow.removeCell. Die API orientiert sich an Zeilen statt aus Spalten, und nur sehr wenige Operationen auf die ganze Spalte Ebene.

    Beispielcode (ungetestet):

    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);
    }
    • NÖ. funktioniert nicht, dieser entfernt alle Daten von dieser Zelle (wie Inhalt, Stil, …) aber die Spalte ist noch da.
    • Sie müssten dann verschieben Sie alle relevanten Zellen einer Spalte auf der linken Seite.
    • Das ist gut für die Letzte Spalte

Kostenlose Online-Tests