Раскраска ячеек столбца с помощью пользовательского rgb для создания шаблона градиента в столбце, где каждая ячейка имеет свой собственный rgb, используя apache poi - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь создать шаблон градиента в столбце, каждая ячейка которого имеет значение 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 в настоящее время рассчитывается как случайный.)

Выход: - Выходное изображение

Где я иду не так?

1 Ответ

0 голосов
/ 05 июля 2018

Есть много проблем с вашим кодом, что приводит к множеству разных проблем. Так что ответ будет немного длинным.

Сначала о том, как структурирована книга Excel:

Рабочая книга состоит как минимум из одного, но может быть нескольких листов, каждый из которых имеет несколько строк, каждый из которых имеет несколько ячеек. Каждая клетка может иметь стиль. Но настройки стиля хранятся не в ячейке, а в таблице стилей (таблица стилей) на уровне рабочей книги. Таким образом, стили хранятся в ячейках, строках и даже листах. Несколько ячеек могут иметь одинаковый сохраненный стиль, если они имеют одинаковый вид. То же самое для цветов. Цвета также хранятся на уровне рабочей книги. И, к сожалению, в формате *.xls BIFF цвета ограничены индексированными цветами в цветовой палитре. В BIFF8 имеется 49 (индекс 16–64) в пользовательской записи ПАЛИТРА, плюс еще несколько. Эти 49 могут быть перезаписаны, но их нельзя увеличить.

Теперь к вашему коду:

Вы выписываете всю книгу каждый раз, когда меняете ячейку в строке листа. Вы не должны этого делать. Вместо этого вы должны выписать рабочую книгу один раз, если с ней покончено.

Вы создаете новый стиль ячейки для каждой ячейки, в которой вам нужно надеть стиль. Вы не должны этого делать. Excel *.xls ограничен примерно 4000 различными комбинациями форматов ячеек. Поэтому вам нужно проверить, присутствует ли нужный вам стиль в рабочей книге. Это может быть очень утомительно, но есть 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

Отказ от ответственности:

Код протестирован и работает с использованием последней стабильной версии 3.17 из apache poi. Ваш код использовал более старую версию (я знаю, потому что использовал HSSFColor.GOLD.index).

Кстати:

Что я действительно хотел бы предложить, так это обновить формат файла Excel до современного формата *.xlsx Office Open XML. Мало того, что ограничение по цвету прошло, вы можете просто использовать Условное форматирование с Цветовые шкалы , что, вероятно, удовлетворяет вашим требованиям еще лучше.

...