JAVA POI库操作 Excel之 获取单元格的自定义颜色--踩坑记录

最近半个月都在玩Excel,首先POI库很强大,同时也存在很多坑。
今天需要获取某一行的指定单元格底色然后设置到指定单元格的时候一直获取不到。于是就有了今天这片水文,希望能帮助到正在被Excel搞到头皮发麻的码友。

首先我们需要知道 POI库是有内置的颜色的,有64种基础颜色,但是在日常使用是不能够满足我们花里胡哨的需求所以就有很多自定义的颜色不在POI库里面。

/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.ss.usermodel;

/**
 * A deprecated indexing scheme for colours that is still required for some records, and for backwards
 *  compatibility with OLE2 formats.
 *
 * <p>
 * Each element corresponds to a color index (zero-based). When using the default indexed color palette,
 * the values are not written out, but instead are implied. When the color palette has been modified from default,
 * then the entire color palette is used.
 * </p>
 *
 * @author Yegor Kozlov
 */
public enum IndexedColors {

    // 0-7 duplicates of 8-15 for compatibility (OOXML spec pt.1 sec. 18.8.27)
   ,
    WHITE1(1),
    RED1(2),
    BRIGHT_GREEN1(3),
    BLUE1(4),
    YELLOW1(5),
    PINK1(6),
    TURQUOISE1(7),
    BLACK(8),
    WHITE(9),
    RED(10),
    BRIGHT_GREEN(11),
    BLUE(12),
    YELLOW(13),
    PINK(14),
    TURQUOISE(15),
    DARK_RED(16),
    GREEN(17),
    DARK_BLUE(18),
    DARK_YELLOW(19),
    VIOLET(20),
    TEAL(21),
    GREY_25_PERCENT(22),
    GREY_50_PERCENT(23),
    CORNFLOWER_BLUE(24),
    MAROON(25),
    LEMON_CHIFFON(26),
    LIGHT_TURQUOISE1(27),
    ORCHID(28),
    CORAL(29),
    ROYAL_BLUE(30),
    LIGHT_CORNFLOWER_BLUE(31),
    SKY_BLUE(40),
    LIGHT_TURQUOISE(41),
    LIGHT_GREEN(42),
    LIGHT_YELLOW(43),
    PALE_BLUE(44),
    ROSE(45),
    LAVENDER(46),
    TAN(47),
    LIGHT_BLUE(48),
    AQUA(49),
    LIME(50),
    GOLD(51),
    LIGHT_ORANGE(52),
    ORANGE(53),
    BLUE_GREY(54),
    GREY_40_PERCENT(55),
    DARK_TEAL(56),
    SEA_GREEN(57),
    DARK_GREEN(58),
    OLIVE_GREEN(59),
    BROWN(60),
    PLUM(61),
    INDIGO(62),
    GREY_80_PERCENT(63),
    AUTOMATIC(64);

    private final static IndexedColors[] _values = new IndexedColors[65];
    static {
        for (IndexedColors color : values()) {
            _values[color.index] = color;
        }
    }
    
    public final short index;

    IndexedColors(int idx){
        index = (short)idx;
    }

    /**
     * Returns index of this color
     *
     * @return index of this color
     */
    public short getIndex(){
        return index;
    }
    
    /**
     * 
     *
     * @param index the index of the color
     * @return the corresponding IndexedColors enum
     * @throws IllegalArgumentException if index is not a valid IndexedColors
     * @since 3.15-beta2
     */
    public static IndexedColors fromInt(int index) {
        if (index < 0 || index >= _values.length) {
            throw new IllegalArgumentException("Illegal IndexedColor index: " + index);
        }
        IndexedColors color = _values[index];
        if (color == null) {
            throw new IllegalArgumentException("Illegal IndexedColor index: " + index);
        }
        return color;
    }
}

好那么问题来了,如我我们Excel颜色是自定义的,并且在POI设定的颜色之外,那么就会出现读取不到返回的索引就是  0(BLACK1 黑色)

一般看到设置填充色的方法是

setFillForegroundColor(short fg);

想着简单点直接从源单元格获取填充色对象设置进去就行了,但是直接获取填充色居然是POI默认的黑色,一脸懵逼。走了Degub才看到试上面图片那样的。

后面再网站了解到 下面这个方法:

XSSFColor customColor = (XSSFColor)  sourceCell.getCellStyle().getFillForegroundColorColor();

关键点来了 ,将获取到的 返回值强转成 XSSFColor对象,这样就可以获取到里面的RGB色值,从而根据RGB色值去设置底色。

于是就尝试了

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

public class Main {
    public static void main(String[] args) {
        // 创建一个新的工作簿
        Workbook workbook = new XSSFWorkbook();
        // 创建一个新的工作表
        Sheet sheet = workbook.createSheet("Sheet1");

        // 创建第一个单元格,并设置背景颜色为红色
        Row row1 = sheet.createRow(0);
        Cell cell1 = row1.createCell(0);
        XSSFCellStyle cellStyle1 = (XSSFCellStyle) workbook.createCellStyle();
        cellStyle1.setFillForegroundColor(new XSSFColor(new java.awt.Color(255, 0, 0)));
        cell1.setCellStyle(cellStyle1);

        // 读取第一个单元格的背景颜色
        XSSFColor color1 = (XSSFColor) cell1.getCellStyle().getFillForegroundColorColor();
        byte[] rgb1 = color1.getRGB();

        // 创建第二个单元格,并将背景颜色设置为第一个单元格的颜色
        Row row2 = sheet.createRow(1);
        Cell cell2 = row2.createCell(0);
        XSSFCellStyle cellStyle2 = (XSSFCellStyle) workbook.createCellStyle();
        cellStyle2.setFillForegroundColor(new XSSFColor(rgb1, null));
        cell2.setCellStyle(cellStyle2);

        // 将工作簿写入文件
        try {
            FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
            workbook.write(fileOut);
            fileOut.close();
            workbook.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
但是有些情况下面获取到的RBG值是错误的,这可能是获取的前填充色和背景色有关系。
当然也可以直接获取 XSSFColor 对象直接设置不用去拿 RBG再次设置
                /** 说明: 对于单元格的自定义底色是不在poi库的【poi只有基础的64种颜色】,所以单纯获取是获取不到的,
                 *        所以需要转换成 XSSFColor对象,获取RPG色值,然后再设置进去单元格才可以准确设置单元格底色 */

                // 第源行的底色
                XSSFColor customColor = (XSSFColor)  sourceCell.getCellStyle().getFillForegroundColorColor(); // 旧单元格样式

                //如果是公式就加上淡蓝色底色
                XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                //设置底色
                cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                cellStyle.setFillForegroundColor(customColor);

最终封装后的方法:
 


    /**
     * 复制单元格底色
     * @param workbook  工作簿
     * @param sourceRowNum  源行数(获取的行)
     * @param objectiveRowNum 目标行数(设置的行)
     */
    private static void copyTheCellColor( Workbook workbook,int sourceRowNum,int objectiveRowNum) {

        Sheet sheet = workbook.getSheetAt(0); // 默认工作表

        //指定遍历行数据,判断当前单元格的底色为空,就拷贝上一行的底色设置进去
        Row objectiveRow = sheet.getRow(objectiveRowNum);
        Row sourceRow = sheet.getRow(sourceRowNum);
        for (int i = 0; i < objectiveRow.getLastCellNum(); i++) {
            Cell objectiveCell = objectiveRow.getCell(i);
            Cell sourceCell = sourceRow.getCell(i);

            //判断当前单元格的底色为空,并且上一行的底色不为空,就拷贝上一行的底色设置进去
            if (objectiveCell.getCellStyle().getFillPattern() == FillPatternType.NO_FILL && sourceCell.getCellStyle().getFillPattern() == FillPatternType.SOLID_FOREGROUND){

                /** 说明: 对于单元格的自定义底色是不在poi库的【poi只有基础的64种颜色】,所以单纯获取是获取不到的,
                 *        所以需要转换成 XSSFColor对象,获取RPG色值,然后再设置进去单元格才可以准确设置单元格底色 */

                // 第源行的底色
                XSSFColor customColor = (XSSFColor)  sourceCell.getCellStyle().getFillForegroundColorColor(); // 旧单元格样式

                //如果是公式就加上淡蓝色底色
                XSSFCellStyle cellStyle = (XSSFCellStyle) workbook.createCellStyle();
                cellStyle.setBorderTop(BorderStyle.THIN);
                cellStyle.setBorderBottom(BorderStyle.THIN);
                cellStyle.setBorderLeft(BorderStyle.THIN);
                cellStyle.setBorderRight(BorderStyle.THIN);
                //设置底色
                cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                cellStyle.setFillForegroundColor(customColor);


                // 设置单元格格式以显示两位小数
                DataFormat dataFormat = workbook.createDataFormat();
                cellStyle.setDataFormat(dataFormat.getFormat("0.00"));

                Font font = workbook.createFont();
                // 字体
                font.setFontName("Arial");
                // 字体高度
                font.setFontHeightInPoints((short) 10);
                // 字体颜色:黑色
                font.setColor(IndexedColors.BLACK.getIndex());
                cellStyle.setFont(font);

                objectiveCell.setCellStyle(cellStyle);


            }
        }
    }

水完,收工~~~~~~

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值