POI读取单元格信息及单元格公式

本文介绍使用Java POI库高效操作Excel文件的方法,包括复制单元格样式、读取和写入公式等内容。适用于处理Excel 2007及以上版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java操作EXCEL的利器一般都是POI和JXL,鄙人只是POI的忠实粉丝。(其实我是没有用过JXL)。

现在大多数的excel都是07以上的版本,所以我一般是用07的基础上使用POI。

  1. 一、读取单元格

单元格有样式和值,以及值得类型。

样式复制封装成一个函数:

public XSSFCellStyle cloneAllCellStyle(XSSFCell sourceCell, XSSFWorkbook targetWb){

        //创建一个样式
        XSSFCellStyle tempStyle = targetWb.createCellStyle(); //样式
        //数值格式,创建字符及数字格式
        DataFormat format= targetWb.createDataFormat();
        //字体
        XSSFFont font= targetWb.createFont();
        try{
            tempStyle.setDataFormat(format.getFormat( sourceCell.getCellStyle().getDataFormatString()));
        }catch(NullPointerException e){
            tempStyle.setDataFormat((short)0);
        }
        font.setColor(sourceCell.getCellStyle().getFont().getXSSFColor());
        font.setBold(sourceCell.getCellStyle().getFont().getBold());
        font.setBoldweight(sourceCell.getCellStyle().getFont().getBoldweight());
        try{
            font.setCharSet(sourceCell.getCellStyle().getFont().getCharSet());
        }catch(POIXMLException e){
            font.setCharSet(0);
        }
        //        font.setCharSet(sourceCell.getCellStyle().getFont().getCharSet());

        font.setFamily(sourceCell.getCellStyle().getFont().getFamily());
        font.setFontHeight(sourceCell.getCellStyle().getFont().getFontHeight());
        font.setFontHeightInPoints(sourceCell.getCellStyle().getFont().getFontHeightInPoints());
        font.setFontName(sourceCell.getCellStyle().getFont().getFontName());
        font.setItalic(sourceCell.getCellStyle().getFont().getItalic());
        font.setStrikeout(sourceCell.getCellStyle().getFont().getStrikeout());
        //        font.setThemeColor(sourceCell.getCellStyle().getFont().getThemeColor());
        font.setTypeOffset(sourceCell.getCellStyle().getFont().getTypeOffset());
        font.setUnderline(sourceCell.getCellStyle().getFont().getUnderline());

        tempStyle.setAlignment( sourceCell.getCellStyle().getAlignment());
        tempStyle.setVerticalAlignment(sourceCell.getCellStyle().getVerticalAlignment());
        tempStyle.setBorderBottom(sourceCell.getCellStyle().getBorderBottom());
        tempStyle.setBorderLeft(sourceCell.getCellStyle().getBorderLeft());
        tempStyle.setBorderRight(sourceCell.getCellStyle().getBorderRight());
        tempStyle.setBorderTop(sourceCell.getCellStyle().getBorderTop());
        tempStyle.setBottomBorderColor(sourceCell.getCellStyle().getBottomBorderXSSFColor());
        tempStyle.setLeftBorderColor(sourceCell.getCellStyle().getLeftBorderXSSFColor());
        tempStyle.setRightBorderColor(sourceCell.getCellStyle().getRightBorderXSSFColor());
        tempStyle.setTopBorderColor(sourceCell.getCellStyle().getTopBorderXSSFColor());
        tempStyle.setFillBackgroundColor(sourceCell.getCellStyle().getFillBackgroundColorColor());
        tempStyle.setFont(font);
        try{
            tempStyle.setFillForegroundColor(sourceCell.getCellStyle().getFillForegroundColorColor());
        }catch(NullPointerException e){
            tempStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
        }
        tempStyle.setFillPattern(sourceCell.getCellStyle().getFillPattern());
        tempStyle.setRotation(sourceCell.getCellStyle().getRotation());
        tempStyle.setHidden(sourceCell.getCellStyle().getHidden());
        tempStyle.setWrapText(sourceCell.getCellStyle().getWrapText());
        tempStyle.setIndention(sourceCell.getCellStyle().getIndention());
        tempStyle.setLocked(sourceCell.getCellStyle().getLocked());

        return tempStyle;

    }

调用直接获取单元格的样式内容。

获取单元格值的类型:cell.getCellType()

根据值类型不同获取不同的值:

    switch (cell.getCellType()) {
                        case Cell.CELL_TYPE_BLANK:
                            tempValue.add("");
                            break;
                        case Cell.CELL_TYPE_BOOLEAN:
                            tempValue.add(cell.getBooleanCellValue());
                            break;
                        case Cell.CELL_TYPE_ERROR:
                            tempValue.add(cell.getErrorCellString());
                            break;
                        case Cell.CELL_TYPE_FORMULA:
                            tempValue.add(cell.getCellFormula());
                            map.put("formulaFlag", true);
                            break;
                        case Cell.CELL_TYPE_NUMERIC:
                            tempValue.add(cell.getNumericCellValue());
                            break;
                        case Cell.CELL_TYPE_STRING:
                            tempValue.add(cell.getStringCellValue());
                            break;
                        default:
                            break;
                        }

创建内容

//工作空间
        XSSFWorkbook targetWb = new XSSFWorkbook();        
     //sheet
        XSSFSheet targetSheet = targetWb.createSheet("行汇总");
     //       删除sheet
           targetWb.removeSheetAt(index);  //index表示第几个sheet,从0开始计数
          //row
XSSFRow row=targetSheet.createRow(i+num1-startRow+1); 
 //cell
      XSSFCell  cell=row.createCell(j);    //j 行

二、 操作单元格函数

POI能够读取函数,然后再把函数写入到单元格中,excel自己计算函数。而函数操作单元格的位置,一般是固定的,所以操作的单元格无法改变。

1、读取函数和写入函数

cell.getCellFormula()

 

       上面的代码中,获取函数的内容,类型为string。

       写入函数:

        

cell.setCellFormula((String)cellValues.get(j));

 

 

2、获取函数计算之后的值:

  有的地方直接写:

   cell.getNumberValue();这样有时候会报错,当cell的内容不是值得时候。

  最后做一个异常抛出。

当然有时候也读不出值,读出的值是0.0(double)

  读取函数值得另一种方法:

  XSSFFormulaEvaluator evaluator=new XSSFFormulaEvaluator(targetWb);

                                CellValue tempCellValue = evaluator.evaluate(cell); 

                                 

                                double cellValue1 =

tempCellValue.getNumberValue(); 

                                  

 

       

       

     如何你是获取excel的值之后,再写入另一个单元格,建议写入值之前,先改变单元的值类型,变成数值型:

    

   cell.set(XSSFCell.CELL_TYPE_NUMERIC);

 

转载于:https://www.cnblogs.com/roychenyi/p/5893370.html

<think>嗯,用户想知道如何使用Apache POI获取Excel中合并单元格的行列信息。我需要先回忆一下相关的知识。记得Apache POI处理Excel的时候,合并单元格信息是通过Sheet接口的getMergedRegions()方法获取的。这个方法返回一个列表,里面包含所有的CellRangeAddress对象,每个对象代表一个合并的区域。 首先,我应该确认用户的问题点。用户可能已经知道如何读取普通单元格,但合并单元格的结构比较复杂,因为它们跨越多个行和列。用户需要知道如何遍历这些合并区域,并获取它们的起始和结束行列索引。 接下来,我需要参考提供的引用内容。比如引用[2]提到了合并单元格的方法,使用addMergedRegion并传入CellRangeAddress。这可能意味着读取的时候也是通过类似的方式获取。引用[3]提到不能用row.getPhysicalNumberOfCells(),可能会有空cell,所以在处理合并单元格时需要注意空值的问题。 然后,我应该分步骤说明如何实现。首先,获取Sheet对象,然后调用getMergedRegions()得到所有合并区域。每个CellRangeAddress对象有getFirstRow()、getLastRow()、getFirstColumn()、getLastColumn()方法,可以获取合并区域的起始和结束的行列索引。 可能需要提醒用户注意,合并后的单元格内容只存在于第一个单元格中,其他单元格可能为空或重复,所以在读取数据时,需要判断单元格是否属于合并区域,并处理主单元格的值。此外,遍历所有合并区域,并存储这些信息,可能有助于后续的数据处理。 用户的问题还可能涉及到如何判断某个单元格是否属于合并区域。这时候可以通过遍历所有合并区域,检查该单元格的行列索引是否在某个CellRangeAddress的范围内。或者,使用Sheet的getMergedRegion(int index)方法来逐个检查。 另外,需要注意处理可能出现的异常情况,比如空单元格或者索引溢出的问题,引用[3]提到不能使用row.getPhysicalNumberOfCells(),所以可能需要其他方法,如row.getLastCellNum(),但需要处理可能的空值。 最后,可能需要给出一个示例代码,展示如何遍历合并区域并打印出它们的行列信息。同时,提醒用户在读取单元格数据时,要检查是否为合并区域的主单元格,避免重复或空值的问题。 总结一下,步骤大概是: 1. 获取Sheet对象。 2. 使用sheet.getMergedRegions()获取所有合并区域。 3. 遍历每个CellRangeAddress,获取其起始和结束的行列索引。 4.读取单元格数据时,判断该单元格是否属于某个合并区域,如果是,则可能需要处理主单元格的值。 需要确保代码示例正确,比如使用Java的Apache POI库,正确处理合并单元格信息。可能还需要提到如何判断某个单元格是否是合并单元格的一部分,以及如何获取其主单元格的值。</think>### 如何读取 Excel 合并单元格的行列信息 #### 一、获取合并单元格索引的核心方法 使用 Apache POI 读取合并单元格的行列信息,需要通过 `Sheet.getMergedRegions()` 方法获取所有合并区域,再通过 `CellRangeAddress` 对象解析具体范围。以下是具体步骤: 1. **获取合并区域集合** ```java List<CellRangeAddress> mergedRegions = sheet.getMergedRegions(); ``` 2. **解析合并范围** 每个 `CellRangeAddress` 对象包含以下关键方法: - `getFirstRow()`:起始行索引(从0开始) - `getLastRow()`:结束行索引 - `getFirstColumn()`:起始列索引(从0开始) - `getLastColumn()`:结束列索引 #### 二、完整代码示例 ```java import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; public class ReadMergedCells { public static void main(String[] args) throws Exception { Workbook workbook = WorkbookFactory.create(new File("input.xlsx")); Sheet sheet = workbook.getSheetAt(0); // 遍历所有合并区域 for (int i = 0; i < sheet.getNumMergedRegions(); i++) { CellRangeAddress mergedRegion = sheet.getMergedRegion(i); System.out.println("合并区域 " + (i+1) + ":"); System.out.println("起始行: " + mergedRegion.getFirstRow()); System.out.println("结束行: " + mergedRegion.getLastRow()); System.out.println("起始列: " + mergedRegion.getFirstColumn()); System.out.println("结束列: " + mergedRegion.getLastColumn()); System.out.println("-----------------------"); } } } ``` #### 三、关键注意事项 1. **数据读取策略**:合并区域中只有第一个单元格(左上角)包含有效数据,其他单元格需通过起始行列索引获取数据[^2] 2. **空单元格处理**:使用 `row.getCell(j)` 时需判空,避免空指针异常[^3] 3. **索引验证**:建议通过 `mergedRegion.isInRange(rowIndex, columnIndex)` 判断单元格是否在合并区域内 #### 四、典型应用场景 当需要处理以下情况时,必须获取合并区域信息: - 生成带合并格式的 Excel 报表 - 解析复杂表格结构(如财务报表) - 数据清洗时处理重复值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值