Как сделать сплошной цвет для базы данных в apache.poi - PullRequest
0 голосов
/ 26 сентября 2019

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

Я использую следующие библиотеки:

  1. org.apache.poi:poi:4.1.0
  2. org.apache.poi:poi-ooxml:4.1.0
  3. org.apache.poi:poi-ooxml-schemas:4.1.0

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

1 Ответ

0 голосов
/ 28 сентября 2019

Все панели данных условного форматирования, определенные в Office Open XML, используют цвета градиента.Нет даже атрибута или свойства, чтобы изменить это.Более поздние версии Excel используют расширения из пространства имен x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main".Но они не являются частью Ecma Office Open XML File Formats Standard.

Apache poi до сих пор базируется только на Ecma Office Open XML File Formats Standard.Таким образом, единственный способ сделать сплошной цвет для панели данных условного форматирования в apache poi - это создать XML расширенного условного форматирования панели данных x14 с нуля.

Полный пример:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFDataBarFormatting;
import org.apache.poi.xssf.usermodel.XSSFConditionalFormattingRule;

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

import java.io.FileOutputStream;

import java.lang.reflect.Field;

public class ConditionalFormattingDataBars {

 public static void applyDataBars(SheetConditionalFormatting sheetCF, String region, ExtendedColor color) throws Exception {
  CellRangeAddress[] regions = { CellRangeAddress.valueOf(region) };
  ConditionalFormattingRule rule = sheetCF.createConditionalFormattingRule(color);
  DataBarFormatting dbf = rule.getDataBarFormatting();
  dbf.getMinThreshold().setRangeType(ConditionalFormattingThreshold.RangeType.NUMBER);
  dbf.getMinThreshold().setValue(0d);
  dbf.getMaxThreshold().setRangeType(ConditionalFormattingThreshold.RangeType.NUMBER);
  dbf.getMaxThreshold().setValue(100d);

  dbf.setIconOnly(true);

  dbf.setWidthMin(0); //cannot work for XSSFDataBarFormatting, see https://svn.apache.org/viewvc/poi/tags/REL_4_0_1/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java?view=markup#l57
  dbf.setWidthMax(100); //cannot work for XSSFDataBarFormatting, see https://svn.apache.org/viewvc/poi/tags/REL_4_0_1/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFDataBarFormatting.java?view=markup#l64

  if (dbf instanceof XSSFDataBarFormatting) {
   Field _databar = XSSFDataBarFormatting.class.getDeclaredField("_databar");
   _databar.setAccessible(true);
   org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar ctDataBar =
    (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataBar)_databar.get(dbf);
   ctDataBar.setMinLength(0);
   ctDataBar.setMaxLength(100);
  }

  // use extension from x14 namespace to set data bars not using gradient color 
  if (rule instanceof XSSFConditionalFormattingRule) {
   Field _cfRule = XSSFConditionalFormattingRule.class.getDeclaredField("_cfRule");
   _cfRule.setAccessible(true);
   org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule ctRule =
    (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCfRule)_cfRule.get(rule);
   org.openxmlformats.schemas.spreadsheetml.x2006.main.CTExtensionList extList =
    ctRule.addNewExtLst();
   String extXML = 
      "<ext uri=\"{B025F937-C7B1-47D3-B67F-A62EFF666E3E}\""
    + " xmlns:x14=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\">"
    + "<x14:id>{00000000-000E-0000-0000-000001000000}</x14:id>"
    + "</ext>";
   org.apache.xmlbeans.XmlObject xlmObject = org.apache.xmlbeans.XmlObject.Factory.parse(extXML);
   extList.set(xlmObject);

   Field _sh = XSSFConditionalFormattingRule.class.getDeclaredField("_sh");
   _sh.setAccessible(true);
   XSSFSheet sheet = (XSSFSheet)_sh.get(rule);
   extList = sheet.getCTWorksheet().addNewExtLst();
   extXML = 
      "<ext uri=\"{78C0D931-6437-407d-A8EE-F0AAD7539E65}\""
    + " xmlns:x14=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\">"
    + "<x14:conditionalFormattings>"
    + "<x14:conditionalFormatting xmlns:xm=\"http://schemas.microsoft.com/office/excel/2006/main\">"
    + "<x14:cfRule type=\"dataBar\" id=\"{00000000-000E-0000-0000-000001000000}\">"
    + "<x14:dataBar minLength=\"" + 0 + "\" maxLength=\"" + 100 + "\" gradient=\"" + false + "\">"
    + "<x14:cfvo type=\"num\"><xm:f>" + 0 + "</xm:f></x14:cfvo>"
    + "<x14:cfvo type=\"num\"><xm:f>" + 100 + "</xm:f></x14:cfvo>"
    + "</x14:dataBar>"
    + "</x14:cfRule>"
    + "<xm:sqref>" + region + "</xm:sqref>"
    + "</x14:conditionalFormatting>"
    + "</x14:conditionalFormattings>"
    + "</ext>";
   xlmObject = org.apache.xmlbeans.XmlObject.Factory.parse(extXML);
   extList.set(xlmObject);
  }

  sheetCF.addConditionalFormatting(regions, rule);
 }

 public static void main(String[] args) throws Exception {
  Workbook workbook = new XSSFWorkbook();

  Sheet sheet = workbook.createSheet("new sheet");

  double[] list = new double[]{0d, 10d, 20d, 30d, 40d, 50d, 60d, 70d, 80d, 90d, 100d};
  for (int i = 0; i < list.length; i++) {
   sheet.createRow(i+1).createCell(0).setCellValue(0d);
   sheet.getRow(i+1).createCell(1).setCellValue(list[i]);
   sheet.getRow(i+1).createCell(2).setCellValue(100d);
  }

  SheetConditionalFormatting sheetCF = sheet.getSheetConditionalFormatting();
  ExtendedColor color = workbook.getCreationHelper().createExtendedColor();
  color.setARGBHex("FF80C279");
  applyDataBars(sheetCF, "B2:B12", color);

  sheet.setColumnWidth(1, 50*256);

  FileOutputStream out = new FileOutputStream("ConditionalFormattingDataBars.xlsx");
  workbook.write(out);
  out.close();
  workbook.close();

 }
}
...