首页 文章

如何使用HSSF(Apache POI)在现有Excel中的两行之间插入行

提问于
浏览
46

不知何故,我设法在现有的excel文件中的两行之间创建新行 . 问题是,一些格式化不包括行的移位 .

其中之一就是隐藏的行在转换期间不相对 . 我的意思是(例如),隐藏了20到30行,但是当创建新行时,仍然存在格式化 . 隐藏的行也必须在插入/创建新行期间移动,它应该是21到31 .

另一件事是,工作表中的另一个对象不在单元格中 . 在创建新行之后,文本框不会移动 . 它就像这些物体的位置是固定的 . 但我想让它移动,就像我在excel中插入一个新行或粘贴行一样 . 如果有插入新行的功能,请告诉我 .

这就是我现在所拥有的,只是我代码中的一个片段 .

HSSFWorkbook wb = new HSSFWorkbook(template); //template is the source of file
HSSFSheet sheet = wb.getSheet("SAMPLE");
HSSFRow newRow;
HSSFCell cellData;

int createNewRowAt = 9; //Add the new row between row 9 and 10

sheet.shiftRows(createNewRowAt, sheet.getLastRowNum(), 1, true, false);
newRow = sheet.createRow(createNewRowAt);
newRow = sheet.getRow(createNewRowAt);

如果可以复制和粘贴行,那将是很大的帮助 . 但是我已经在这里问过它并且找不到解决方案 . 所以我决定创建一个行作为临时解决方案 . 我已经完成了它,但有这样的问题 .

任何帮助都感激不尽 . 谢谢!

8 回答

  • 0

    我在Kotlin中实现了这样:

    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
    }
    

    它不会复制单元格值,只复制格式 . 也应该适用于Java .

  • 8

    辅助函数复制行无耻地改编自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);
                }
            }
        }
    }
    
  • 2

    引用Qwerty's answer,可以避免通过重新使用 cellStyle 来扩大XL大小 . 当类型为 CELL_TYPE_BLANK 时, getStringCellValue 返回 "" 而不是 null .

    private static void copyRow(Sheet worksheet, int sourceRowNum, int destinationRowNum) {
      // Get the source / new row
      Row newRow = worksheet.getRow(destinationRowNum);
      Row 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
        Cell oldCell = sourceRow.getCell(i);
        Cell newCell = newRow.createCell(i);
    
        // If the old cell is null jump to next cell
        if (oldCell == null) {
          newCell = null;
          continue;
        }
    
        // Use old cell style
        newCell.setCellStyle(oldCell.getCellStyle());
    
        // If there is a cell comment, copy
        if (newCell.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:
          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;
        }
      }
    }
    
  • 1

    对于希望使用XSSF(Apache POI)在现有Excel中的两行之间插入行的人,已经在XSSFSheet中实现了一个方法“copyRows” .

    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

    引用Qwerty's answer,如果destRow不为null,则sheet.shiftRows()将更改destRow对下一行的引用;所以我们应该总是创建一个新行:

    if (destRow != null) {
      sheet.shiftRows(destination, sheet.getLastRowNum(), 1);
    }
    destRow = sheet.createRow(destination);
    
  • 63

    我在以下实现中合并了一些其他答案和注释,并使用Apache POI v3.9进行了测试 .

    我只有一个 rownum 参数,因为我向下移动目标行并将其复制到新的空行中 . 公式按预期处理,不会逐字复制,但有一个例外:对复制行的单元格的引用不会更新;解决方法是将这些显式引用(如果有)替换为使用 INDIRECT() 计算的引用,如this post所示 .

    protected void copyRow(Sheet worksheet, int rowNum) {
        Row sourceRow = worksheet.getRow(rowNum);
    
        //Save the text of any formula before they are altered by row shifting
        String[] formulasArray = new String[sourceRow.getLastCellNum()];
        for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
            if (sourceRow.getCell(i) != null && sourceRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA) 
                formulasArray[i] = sourceRow.getCell(i).getCellFormula();
        }
    
        worksheet.shiftRows(rowNum, worksheet.getLastRowNum(), 1);
        Row newRow = sourceRow;  //Now sourceRow is the empty line, so let's rename it
        sourceRow = worksheet.getRow(rowNum + 1);  //Now the source row is at rowNum+1
    
        // 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
            Cell oldCell = sourceRow.getCell(i);
            Cell newCell;
    
            // If the old cell is null jump to next cell
            if (oldCell == null) {
                continue;
            } else {
                newCell = newRow.createCell(i);
            }
    
            // Copy style from old cell and apply to new cell
            CellStyle newCellStyle = worksheet.getWorkbook().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:
                    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(formulasArray[i]);
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    newCell.setCellValue(oldCell.getNumericCellValue());
                    break;
                case Cell.CELL_TYPE_STRING:
                    newCell.setCellValue(oldCell.getRichStringCellValue());
                    break;
                default:   
                    break; 
            }
        }
    
        // If there 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);
            }
        }
    }
    

    我在 生产环境 代码中使用此实现 .

  • 5

    对于在新行中“更新”的公式,由于所有复制都发生在移位之后,旧行(现在从新行开始的一个索引)已经移动了其公式,因此将其复制到新行将使新行引用旧行单元格 . 一个解决方案是在移位之前解析公式,然后应用它们(一个简单的String数组就能完成这项工作 . 我相信你可以在几行中编写代码) .

    在功能开始时:

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

    然后将公式应用于单元格时:

    newCell.setCellFormula(fArray.get(i));
    
  • 0

    我最近遇到了同样的问题 . 我不得不在包含隐藏行的文档中插入新行,并面临同样的问题 . 在apache poi列表中进行了一些搜索和一些电子邮件之后,当文档隐藏行时,它似乎是shiftrows()中的一个错误 .

相关问题