有没有办法知道CellStyle已经存在于工作簿中(重用)使用POI或仅复制Celstyle obj而不是参考

时间:2017-02-07 03:38:21

标签: java excel apache-poi

我想在excel中写一些记录,但我知道 XSSFWorkbook中的最大单元格样式是64000 。但是记录超过64000并认为我想应用新的每个单元格cellstyle我将使用现有的单元格样式进行克隆。

即使要克隆我也需要采用默认的单元格样式workbook.createCellStyle();,但这超过了64001记录,这导致java.lang.IllegalStateException: The maximum number of cell styles was exceeded.

  

无论如何,在POI中已经知道特定的细胞样式了   出现并利用它或何时需要克隆/创建   默认的cellstyle和clone。

克隆的原因是:有时列/行cellstyle现有的excel cellstyle 可能会有所不同,因此采用默认的单元格样式并克隆col&行和单元格cellstyles到它。

即使我尝试将默认样式添加到地图map.put("defStyle",workbook.createCellStyle();),但这不会正确克隆,因为它会在首次尝试克隆时发生变化,因为 It wont get the Object it will copy the reference 甚至是对象克隆这里也不可能,因为cellstyle没有实现cloneable interface

2 个答案:

答案 0 :(得分:3)

通常,没有必要创建尽可能多的单元格样式,使它们超过可能的单元格样式的最大数量。要根据内容格式化单元格,可以使用条件格式。另外,为了格式化行(例如,奇数/偶数行不同),可以使用条件格式。也适用于列。

因此,通常不应使用单元格样式格式化每个单元格或大量单元格。相反,应该创建更少的单元格样式,然后将其用作默认单元格样式,或者在单个情况下,如果实际上无法实现条件格式化。

在我的例子中,我有一个所有单元格的默认单元格样式和第一行的单行单元格样式(即使这可以使用条件格式实现)。

要将默认单元格样式应用于所有列后保持其工作,必须将其应用于所有apache poi个新创建的单元格。为此,我提供了一种方法getPreferredCellStyle(Cell cell)Excel本身会自动将列(或行)单元格样式应用于新填充的单元格。

如果仍然需要格式化不同的单个单元格,那么应该使用CellUtil。这提供了各种处理样式的方法,允许您根据需要创建CellStyles。将样式更改应用于单元格时,代码将尝试查看是否已存在满足您需求的样式。如果没有,那么它将创建一个新的风格。这是为了防止创建太多样式。 Excel中可以支持的样式数量有一个上限。"请参阅我的示例中的注释。

import java.io.*;

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

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

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

public class CarefulCreateCellStyles {

 public CellStyle getPreferredCellStyle(Cell cell) {
  // a method to get the preferred cell style for a cell
  // this is either the already applied cell style
  // or if that not present, then the row style (default cell style for this row)
  // or if that not present, then the column style (default cell style for this column)
  CellStyle cellStyle = cell.getCellStyle();
  if (cellStyle.getIndex() == 0) cellStyle = cell.getRow().getRowStyle();
  if (cellStyle == null) cellStyle = cell.getSheet().getColumnStyle(cell.getColumnIndex());
  if (cellStyle == null) cellStyle = cell.getCellStyle();
  return cellStyle;
 }

 public CarefulCreateCellStyles() throws Exception {

   Workbook workbook = new XSSFWorkbook();

   // at first we are creating needed fonts
   Font defaultFont = workbook.createFont();
   defaultFont.setFontName("Arial");
   defaultFont.setFontHeightInPoints((short)14);

   Font specialfont = workbook.createFont();
   specialfont.setFontName("Courier New");
   specialfont.setFontHeightInPoints((short)18);
   specialfont.setBold(true);

   // now we are creating a default cell style which will then be applied to all cells
   CellStyle defaultCellStyle = workbook.createCellStyle();
   defaultCellStyle.setFont(defaultFont);

   // maybe sone rows need their own default cell style
   CellStyle aRowCellStyle = workbook.createCellStyle();
   aRowCellStyle.cloneStyleFrom(defaultCellStyle);
   aRowCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
   aRowCellStyle.setFillForegroundColor((short)3);


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

   // apply default cell style as column style to all columns
   org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol cTCol = 
      ((XSSFSheet)sheet).getCTWorksheet().getColsArray(0).addNewCol();
   cTCol.setMin(1);
   cTCol.setMax(workbook.getSpreadsheetVersion().getLastColumnIndex());
   cTCol.setWidth(20 + 0.7109375);
   cTCol.setStyle(defaultCellStyle.getIndex());

   // creating cells
   Row row = sheet.createRow(0);
   row.setRowStyle(aRowCellStyle);
   Cell cell = null;
   for (int c = 0; c  < 3; c++) {
    cell = CellUtil.createCell(row, c, "Header " + (c+1));
    // we get the preferred cell style for each cell we are creating
    cell.setCellStyle(getPreferredCellStyle(cell));
   }

   System.out.println(workbook.getNumCellStyles()); // 3 = 0(default) and 2 just created

   row = sheet.createRow(1);
   cell = CellUtil.createCell(row, 0, "centered");
   cell.setCellStyle(getPreferredCellStyle(cell));
   CellUtil.setAlignment(cell, HorizontalAlignment.CENTER);

   System.out.println(workbook.getNumCellStyles()); // 4 = 0 and 3 just created

   cell = CellUtil.createCell(row, 1, "bordered");
   cell.setCellStyle(getPreferredCellStyle(cell));
   Map<String, Object> properties = new HashMap<String, Object>();
   properties.put(CellUtil.BORDER_LEFT, BorderStyle.THICK);
   properties.put(CellUtil.BORDER_RIGHT, BorderStyle.THICK);
   properties.put(CellUtil.BORDER_TOP, BorderStyle.THICK);
   properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.THICK);
   CellUtil.setCellStyleProperties(cell, properties);

   System.out.println(workbook.getNumCellStyles()); // 5 = 0 and 4 just created

   cell = CellUtil.createCell(row, 2, "other font");
   cell.setCellStyle(getPreferredCellStyle(cell));
   CellUtil.setFont(cell, specialfont);

   System.out.println(workbook.getNumCellStyles()); // 6 = 0 and 5 just created

// until now we have always created new cell styles. but from now on CellUtil will use
// already present cell styles if they matching the needed properties.

   row = sheet.createRow(2);
   cell = CellUtil.createCell(row, 0, "bordered");
   cell.setCellStyle(getPreferredCellStyle(cell));
   properties = new HashMap<String, Object>();
   properties.put(CellUtil.BORDER_LEFT, BorderStyle.THICK);
   properties.put(CellUtil.BORDER_RIGHT, BorderStyle.THICK);
   properties.put(CellUtil.BORDER_TOP, BorderStyle.THICK);
   properties.put(CellUtil.BORDER_BOTTOM, BorderStyle.THICK);
   CellUtil.setCellStyleProperties(cell, properties);

   System.out.println(workbook.getNumCellStyles()); // 6 = nothing new created

   cell = CellUtil.createCell(row, 1, "other font");
   cell.setCellStyle(getPreferredCellStyle(cell));
   CellUtil.setFont(cell, specialfont);

   System.out.println(workbook.getNumCellStyles()); // 6 = nothing new created

   cell = CellUtil.createCell(row, 2, "centered");
   cell.setCellStyle(getPreferredCellStyle(cell));
   CellUtil.setAlignment(cell, HorizontalAlignment.CENTER);

   System.out.println(workbook.getNumCellStyles()); // 6 = nothing new created


   workbook.write(new FileOutputStream("CarefulCreateCellStyles.xlsx"));
   workbook.close();  
 }

 public static void main(String[] args) throws Exception {
  CarefulCreateCellStyles carefulCreateCellStyles = new CarefulCreateCellStyles();
 }
}

答案 1 :(得分:1)

不容易。我提前定义了我需要的样式,然后将它们显式应用于每个单元格,而不是仅为每个单元格创建一个新样式。请注意,我不在这些预定义的样式中包含边框,只包括字体,颜色和有时填充。对于边框,我稍后会将它们绘制到电子表格中以简化代码。