简体   繁体   English

Apache POI 设置单元格边界不起作用

[英]Apache POI set cell border is not working

I'm facing an issue with Apache POI (v 4.1.2) where it can't set the border as THIN.我遇到了 Apache POI (v 4.1.2) 的问题,它无法将边框设置为 THIN。 My code is supported for both XLS and XLSX extensions.我的代码同时支持 XLS 和 XLSX 扩展。 When I export data to XLSX file, everything is OK, but with XLS files, it doesn't draw the border from cell K5 to the end.当我将数据导出到 XLSX 文件时,一切正常,但是对于 XLS 文件,它不会从单元格K5到末尾绘制边框。

问题图片

Here is my code:这是我的代码:

private int populateExcelData(Workbook workbook, Sheet sheet, int rowNum, List<List<Object>> excelData,
            ExcelVo excelVo, Boolean isHeader) {
        if (CollectionUtils.isNotEmpty(excelData)) {
            int cellNum = 0;
            Row row;
            for (List<Object> objects : excelData) {
                cellNum = excelVo.getColPadding();
                row = sheet.createRow(rowNum++);
                Cell cell;
                for (Object object : objects) {
                    cell = row.createCell(cellNum++);
                    setCellValue(cell, object, excelVo);
                    configCellStyle(cell, workbook, excelVo, isHeader);
                }
            }
        }
        return rowNum;
    }

private void configCellStyle(Cell cell, Workbook workbook, ExcelVo excelVo, Boolean isHeader) {
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        if (isHeader) {
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setColor(excelVo.getFontColor().getIndex());
            cellStyle.setFont(headerFont);
            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            cellStyle.setFillForegroundColor(excelVo.getBackgroundColor().getIndex());
        }
        cell.setCellStyle(cellStyle);
    }

I don't know why with XLS files it ONLY draws the border from cell K5 onward.我不知道为什么使用 XLS 文件它只能从单元格K5开始绘制边框。 The code doesn't throw a bug or exception.该代码不会引发错误或异常。

Thank all for your support.感谢大家的支持。

There are Excel limits for unique cell formats/cell styles as well as for fonts . 对于独特的单元格格式/单元格 styles 以及 fonts 有 Excel 限制 Cell styles and fonts are stored on workbook level.单元格 styles 和 fonts 存储在工作簿级别。 They are shared for all cells in all worksheets.它们为所有工作表中的所有单元格共享。 Current Excel versions limits are:当前 Excel 版本限制为:

Unique cell formats/cell styles: 65,490独特的单元格格式/单元格 styles:65,490

and

Unique font types: 1,024 global fonts available for use;独有字体类型:1024种全局fonts可供使用; 512 per workbook每个工作簿 512

Former versions of Excel (binary *.xls) had even smaller limits. Excel(二进制 *.xls)的早期版本具有更小的限制。

So if you create a separate cell style for each cell, as you are doing, you will hit the limit very fast.因此,如果您为每个单元格创建单独的单元格样式,正如您所做的那样,您将很快达到极限。 XSSF may work as the limits are larger. XSSF可能会因为限制更大而起作用。 But former versions of Excel (binary *.xls) had even smaller limits.但以前版本的 Excel(二进制 *.xls)的限制更小。 Thats why it works not using HSSF .这就是它不使用HSSF的原因。

So what to do is, creating as much cell styles as needed for the workbook once on workbook level.所以要做的是,工作簿级别为工作簿创建尽可能多的单元 styles。 Do this outside the cell filling process.在细胞填充过程之外执行此操作。 While creating the cells itself, the cell style only gets applied using cell.setCellStyle .在创建单元格本身时,单元格样式只能使用cell.setCellStyle应用。 But it cannot be created then.但它不能在那时创建。

Let's have a complete example to show this.让我们有一个完整的例子来说明这一点。 It partially uses your code of populateExcelData but I only can hope it meets your ideas since you not had provided a complete example.它部分使用了您的populateExcelData代码,但我只希望它符合您的想法,因为您没有提供完整的示例。

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.util.GregorianCalendar;
import java.util.List;
import java.util.ArrayList;

import org.apache.commons.collections4.CollectionUtils;

public class CreateExcel {

 private Workbook workbook;
 private CellStyle textStyle;
 private CellStyle dateStyle;
 private CellStyle numberStyle;
 private CellStyle headerStyle;

 public CreateExcel(String type, String path, List<List<Object>> headerData, List<List<Object>> excelData) {
  try {
   this.workbook = ("HSSF".equals(type)) ? new HSSFWorkbook() : new XSSFWorkbook(); 

   DataFormat dataFormat = workbook.createDataFormat();

   this.textStyle = workbook.createCellStyle();
   setCellStyleAllBorders(textStyle);

   this.dateStyle = workbook.createCellStyle();
   dateStyle.setDataFormat(dataFormat.getFormat("DDDD, MMMM, DD, YYYY"));
   setCellStyleAllBorders(dateStyle);

   this.numberStyle = workbook.createCellStyle();
   numberStyle.setDataFormat(dataFormat.getFormat("#,##0.00 \" Coins\""));
   setCellStyleAllBorders(numberStyle);

   this.headerStyle = workbook.createCellStyle();
   Font headerFont = workbook.createFont();
   headerFont.setBold(true);
   headerFont.setColor(IndexedColors.WHITE.getIndex());
   headerStyle.setFont(headerFont);
   headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
   headerStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex());
   setCellStyleAllBorders(headerStyle);

   Sheet sheet = workbook.createSheet(); 

   int rowNum = 0;
   rowNum = populateExcelData(workbook, sheet, rowNum, headerData, 1, true);

   rowNum = populateExcelData(workbook, sheet, rowNum, excelData, 1, false);
   
   System.out.println(rowNum);

   for (int c = 0; c < 256; c++) {
    sheet.autoSizeColumn(c); // this is very time consuming, would be better one can set column widths using Sheet.setColumnWidth(int columnIndex, int width) directly
   }

   FileOutputStream fileout = new FileOutputStream(path);
   this.workbook.write(fileout);
   fileout.close();
   this.workbook.close();

  } catch (Exception ex) {
   ex.printStackTrace(); 
  }
 }

 private int populateExcelData(Workbook workbook, Sheet sheet, int rowNum, List<List<Object>> excelData, Integer colPadding, Boolean isHeader) {
  if (CollectionUtils.isNotEmpty(excelData)) {
   int cellNum = 0;
   Row row;
   for (List<Object> objects : excelData) {
    cellNum = colPadding;
    row = sheet.createRow(rowNum++);
    Cell cell;
    for (Object object : objects) {
     cell = row.createCell(cellNum++);
     setCellValueAndStyle(cell, object, isHeader);
    }
   }
  }
  return rowNum;
 }

 private void setCellValueAndStyle(Cell cell, Object object, Boolean isHeader) {
  if (object instanceof String) {
   cell.setCellValue((String) object);
   if (!isHeader) cell.setCellStyle(this.textStyle);
  } else if (object instanceof Double) {
   cell.setCellValue((Double) object);
   if (!isHeader) cell.setCellStyle(this.numberStyle);
  } else if (object instanceof GregorianCalendar) {
   cell.setCellValue((GregorianCalendar) object);
   if (!isHeader) cell.setCellStyle(this.dateStyle);
  }
  if (isHeader) cell.setCellStyle(this.headerStyle);
 }

 private void setCellStyleAllBorders(CellStyle cellStyle) {
  cellStyle.setBorderBottom(BorderStyle.THIN);
  cellStyle.setBorderLeft(BorderStyle.THIN);
  cellStyle.setBorderRight(BorderStyle.THIN);
  cellStyle.setBorderTop(BorderStyle.THIN);
 }

 public static void main(String[] args) throws Exception {
  List<List<Object>> headerData = new ArrayList<>();
  List<Object> headerRow = new ArrayList<>();
  headerRow.add("Text"); headerRow.add("Value"); headerRow.add("Date");
  headerData.add(headerRow);
  headerRow = new ArrayList<>();
  headerRow.add("not formatted"); headerRow.add("in Coins"); headerRow.add("as long date");
  headerData.add(headerRow);

  List<List<Object>> excelData = new ArrayList<>();
  for (int r = 1; r < 1000; r++) {
   List<Object> excelRow = new ArrayList<>();
   excelRow.add("Text" + r); excelRow.add(123.45 * r); excelRow.add(new GregorianCalendar(2020, 0, r));
   excelData.add(excelRow);
  }

  CreateExcel test = new CreateExcel("HSSF", "./Excel.xls", headerData, excelData);
  test = new CreateExcel("XSSF", "./Excel.xlsx", headerData, excelData);
 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM