java - 使用自定义 rgb 对列的单元格进行着色,以在列中创建渐变图案,每个单元格使用 apache poi 都有自己的 rgb

标签 java excel apache-poi

我正在尝试在列中创建渐变图案,每个单元格都有其 rgb 值。我面临的问题是 RGB 颜色在该列的其​​他单元格中被覆盖。因此,最后生成的 RGB 颜色将被赋予该列中的所有单元格。我尝试在每次迭代的循环中创建新对象,但覆盖仍然存在。

public static void giveGradientToColumn(HSSFWorkbook workbook, HSSFSheet sheet, String yemi, Double minimum, Double maximum) throws IOException {

    int columnIndex = 5;
    int maxRows = sheet.getPhysicalNumberOfRows();
    Random rand = new Random();

    int i = maxRows+1;
    for(int rowIndex = maxRows-1 ; rowIndex > 0 ; rowIndex--){

        Row row = CellUtil.getRow(rowIndex, sheet);
        Cell cell = CellUtil.getCell(row, columnIndex);
        String cellContent = cell.toString();
        String percentvalue = cellContent.split("%")[0];
        if(!(percentvalue.equals("NaN")))
        {   
            FileOutputStream fileOut = new FileOutputStream(yemi);
            double value;
            HSSFWorkbook workbook1 = workbook;
            try{
                value = Double.parseDouble(percentvalue);
            }
            catch(Exception e){
                continue;
            }
            double ratio;
            if(maximum!=minimum)
                ratio = 2 * (value-minimum) / (maximum - minimum);
            else
                ratio = 1;

            int b = (max(0, 255*(1 - ratio)));
            int r = (max(0, 255*(ratio - 1)));
            int g = 255 - b - r;

            r = rand.nextInt(255);
            g = rand.nextInt(255);
            b = rand.nextInt(255);

            System.out.println(r+" "+g+" "+b);
            HSSFCellStyle style = workbook1.createCellStyle();
            HSSFPalette palette = workbook1.getCustomPalette();
            HSSFColor myColor = setColor(workbook1, (byte) r, (byte) g, (byte) b);
            short palIndex = myColor.getIndex();
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND); 
            style.setFillForegroundColor(palIndex);

            cell.setCellStyle(style);
            workbook1.write(fileOut);
            fileOut.close();

        }
    }
}




@SuppressWarnings("deprecation")
public static HSSFColor setColor(HSSFWorkbook workbook, byte r,byte g, byte b){
    HSSFPalette palette = workbook.getCustomPalette();
    HSSFColor hssfColor = null;
    try {
        hssfColor= palette.findColor(r, g, b); 
        if (hssfColor == null)
        {
            palette.setColorAtIndex(HSSFColor.GOLD.index, r, g, b);
            hssfColor = palette.getColor(HSSFColor.GOLD.index);
        }
    } catch (Exception e) {
        System.out.println(e);
    }

    return hssfColor;
}

我正在打印 rgb 值以进行调试,并且最后打印的颜色值将被赋予该列中的所有单元格。 (RGB目前是随机计算的。)

输出:- Output Image

我哪里出错了?

最佳答案

您的代码存在多个问题,导致多个不同的问题。所以答案会有点长。

首先了解 Excel 工作簿的结构:

工作簿由至少一个但也可能是多个工作表组成,每个工作表具有多行,每行具有多个单元格。每个单元格都可以有样式。但样式设置不存储在单元格中,而是存储在工作簿级别的样式表(样式表)中。因此,样式可以跨单元格、行甚至工作表存储。如果多个单元格具有相同的外观,则它们可以共享相同的存储样式。颜色也是如此。颜色也存储在工作簿级别。不幸的是,在 *.xls BIFF 格式中,颜色仅限于调色板中的索引颜色。在 BIFF8 中,用户定义的 PALETTE 记录中有 49 个(索引 16 到 64),另外还有一些。这 49 个可以被覆盖,但数量不能增加。

现在看你的代码:

每次更改工作表行中的一个单元格时,您都会写出整个工作簿。你不应该这样做。相反,如果您完成了工作簿,则应该将其写出来。

您正在为每个需要添加样式的单元格创建一个新的单元格样式。你不应该这样做。 Excel *.xls 仅限于大约 4,000 种不同的单元格格式组合。因此,您需要检查工作簿中是否已存在您不需要的样式。这可能非常乏味,但有 CellUtil ,您已经找到并已在代码中使用它。这提供了 setCellStyleProperties,它“尝试查找与单元格当前样式以及属性中的样式属性相匹配的现有 CellStyle。如果工作簿不包含匹配的样式,则会创建一个新样式。”。

您首先要搜索所需的颜色是否已存在。那挺好的。但如果没有,您将始终覆盖 GOLD 相同的颜色索引。由于颜色也存储在工作簿级别,因此只有最后覆盖的颜色值才会存储为GOLD。如果工作簿中需要存储不同的颜色,则需要覆盖不同颜色索引。

示例:

源 Excel:

enter image description here

代码:

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

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;

import org.apache.poi.ss.util.CellUtil;

import java.util.Map;
import java.util.HashMap;

public class ExcelSetHSSFCellStyleColors {

 static void giveGradientToColumn(HSSFSheet sheet, int columnIndex, double minimum, double maximum) throws Exception {
  DataFormatter formatter = new DataFormatter(java.util.Locale.US);

  short colorIndex = 16; //color indexes 0 to 15 should not be overwritten
  HSSFPalette palette = sheet.getWorkbook().getCustomPalette();

  for (Row row : sheet) {
   Cell cell = CellUtil.getCell(row, columnIndex);
   String cellContent = formatter.formatCellValue(cell);
System.out.println(cellContent);
   String percentValue = cellContent.split("%")[0];
   double value = Double.NaN;
   try {
    value = Double.valueOf(percentValue);
   } catch(Exception e){
    //percentValue was not numeric
   }
   if (!Double.isNaN(value) && value >= minimum && value <= maximum){
    double ratio = (value - minimum) / (maximum - minimum);
    byte r = (byte)Math.round(Math.max(0, 255 * (1 - ratio)));
    byte b = 0;
    byte g = (byte)Math.round(Math.max(0, 255 - (int)b - (int)r));
System.out.println(ratio + " " + String.format("%02X", r) + ":" + String.format("%02X", g) + ":" + String.format("%02X", b));

    HSSFColor hssfColor = palette.findColor(r, g, b); 
    if (hssfColor == null /*&& colorIndex < 64*/) {
     palette.setColorAtIndex(colorIndex, r, g, b);
     hssfColor = palette.getColor(colorIndex);
     colorIndex++;
    }
System.out.println("got color: " + ((hssfColor!=null)?hssfColor.getIndex() + ": " + hssfColor.getHexString():hssfColor)); //if not a index available, hssfColor may be null

    if (hssfColor != null) {
     Map<String, Object> styleproperties = styleproperties = new HashMap<String, Object>();
     styleproperties.put(CellUtil.FILL_FOREGROUND_COLOR, hssfColor.getIndex());
     styleproperties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
     CellUtil.setCellStyleProperties(cell, styleproperties);
    }
   }
  }
 }

 public static void main(String[] args) throws Exception {
  Workbook workbook = WorkbookFactory.create(new FileInputStream("ExcelTest.xls"));

  HSSFSheet sheet = (HSSFSheet)workbook.getSheetAt(0);

  giveGradientToColumn(sheet, 5, 10, 90);

  workbook.write(new FileOutputStream("ExcelTestNew.xls"));
  workbook.close();
 }  
}

结果:

enter image description here

免责声明:

代码经过测试,可使用 apache poi 的最新稳定版本 3.17 进行测试和运行。您的代码使用了旧版本(我知道是因为使用了 HSSFColor.GOLD.index)。

顺便说一句:

我真正建议的是将 Excel 文件格式升级为现代的 *.xlsx Office Open XML 文件格式。不仅颜色限制消失了,您还可以简单地使用 Conditional Formatting使用色阶可能会更好地满足您的要求。

关于java - 使用自定义 rgb 对列的单元格进行着色,以在列中创建渐变图案,每个单元格使用 apache poi 都有自己的 rgb,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51171098/

相关文章:

java - 带条件的 mongotemplate 聚合

sql - 使用 ColdFusion 导出数十万条记录

excel - 循环插入行、复制数据

java - 如何使用 Java 代码使用 HSSF 应用单元格背景颜色

java - 将 Ms Access 连接到 java

Java MemoryClassLoader(IllegalArgumentException)

java - 我的联系人类的 getter 和 setter 方法存在问题

java - 将 Post 请求中的 String 参数和对象传递给 RESTful 服务

excel - 如何自动过滤具有来自特定范围的值的列

java.lang.ClassNotFoundException : org. apache.poi.xssf.usermodel.XSSFWorkbook