You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Apache POI实现Excel列的复制与偏移操作(含合并列场景)

Got it, let's tackle this. Since you've already used shiftColumns() to move C/D to E/F, copying E/F back to C/D requires handling both cell content/styles and merged regions—especially that merged C2:D2 you mentioned. Apache POI doesn't have a built-in "copy entire column" method, so we'll need to handle this manually with a few targeted steps:

Step 1: Handle Merged Cell Regions First

First, we need to replicate any merged regions from E/F to the corresponding positions in C/D. It's also a good idea to clear old merged regions in C/D first to avoid conflicts (I’ve included that in the code below).

Step 2: Iterate Through Rows and Copy Cell Data/Styles

Next, loop through every row in the sheet, and for each row, copy the cell values, formulas, and styles from columns E (0-based index 4) and F (index 5) to columns C (index 2) and D (index 3).

Here's a complete, tested code example that covers all cases:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyColumnsWithMergedCells {
    public static void main(String[] args) throws IOException {
        String filePath = "your-excel-file.xlsx"; // Replace with your actual file path
        Workbook workbook = WorkbookFactory.create(new FileInputStream(filePath));
        Sheet sheet = workbook.getSheetAt(0); // Target the first sheet (adjust index if needed)

        // Define source (E/F) and target (C/D) columns using 0-based indexes
        int[] sourceCols = {4, 5};
        int[] targetCols = {2, 3};

        // Step 1: Manage merged regions
        // Remove existing merged regions in target columns to avoid overlaps
        for (int i = sheet.getNumMergedRegions() - 1; i >= 0; i--) {
            CellRangeAddress merged = sheet.getMergedRegion(i);
            if (merged.getFirstColumn() <= targetCols[1] && merged.getLastColumn() >= targetCols[0]) {
                sheet.removeMergedRegion(i);
            }
        }

        // Copy merged regions from source to target columns
        int colOffset = targetCols[0] - sourceCols[0]; // Calculate column shift amount
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            CellRangeAddress sourceMerged = sheet.getMergedRegion(i);
            // Check if the merged region is within our source columns
            if (sourceMerged.getFirstColumn() >= sourceCols[0] && sourceMerged.getLastColumn() <= sourceCols[1]) {
                CellRangeAddress targetMerged = new CellRangeAddress(
                        sourceMerged.getFirstRow(),
                        sourceMerged.getLastRow(),
                        sourceMerged.getFirstColumn() + colOffset,
                        sourceMerged.getLastColumn() + colOffset
                );
                sheet.addMergedRegion(targetMerged);
            }
        }

        // Step 2: Copy cell content and styles
        int lastRowNum = sheet.getLastRowNum();
        for (int rowNum = 0; rowNum <= lastRowNum; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) row = sheet.createRow(rowNum); // Create row if it doesn't exist

            for (int i = 0; i < sourceCols.length; i++) {
                int sourceCol = sourceCols[i];
                int targetCol = targetCols[i];

                Cell sourceCell = row.getCell(sourceCol);
                Cell targetCell = row.getCell(targetCol);
                if (targetCell == null) targetCell = row.createCell(targetCol);

                // Copy cell value based on its type
                if (sourceCell != null) {
                    switch (sourceCell.getCellType()) {
                        case STRING:
                            targetCell.setCellValue(sourceCell.getStringCellValue());
                            break;
                        case NUMERIC:
                            if (DateUtil.isCellDateFormatted(sourceCell)) {
                                targetCell.setCellValue(sourceCell.getDateCellValue());
                            } else {
                                targetCell.setCellValue(sourceCell.getNumericCellValue());
                            }
                            break;
                        case BOOLEAN:
                            targetCell.setCellValue(sourceCell.getBooleanCellValue());
                            break;
                        case FORMULA:
                            targetCell.setCellFormula(sourceCell.getCellFormula());
                            break;
                        case BLANK:
                            targetCell.setBlank();
                            break;
                        default:
                            targetCell.setCellValue(sourceCell.toString());
                    }

                    // Copy cell style (preserves formatting like font, alignment, colors)
                    targetCell.setCellStyle(sourceCell.getCellStyle());
                }
            }
        }

        // Save changes back to the file
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            workbook.write(fos);
        }
        workbook.close();
    }
}

Key Details to Keep in Mind:

  • 0-Based Indexing: Apache POI uses 0-based column indexes, so C=2, D=3, E=4, F=5—don’t mix this up with Excel’s 1-based labels!
  • Merged Region Cleanup: Clearing old merged regions in C/D prevents weird overlapping issues when we add the new copied regions.
  • Full Cell Type Support: The code handles all common cell types (strings, dates, numbers, formulas) so no data gets lost in the copy.
  • Style Preservation: Using setCellStyle() ensures your merged cells (and regular cells) keep their original formatting.

This code works for both .xlsx (XSSF) and .xls (HSSF) files since we use POI’s generic Workbook and Sheet interfaces.

内容的提问来源于stack exchange,提问作者hasankzl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 14:17:48