How to insert a row between two rows in an existing excel with HSSF (Apache POI)

前端 未结 8 928
自闭症患者
自闭症患者 2020-11-27 02:38

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.

相关标签:
8条回答
  • 2020-11-27 03:16

    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.

    0 讨论(0)
  • 2020-11-27 03:21

    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));
    
    0 讨论(0)
  • 2020-11-27 03:23

    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.

    0 讨论(0)
  • 2020-11-27 03:30

    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);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 03:35

    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();
        }
    }
    
    0 讨论(0)
  • 2020-11-27 03:37

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