Apache POI 设置单元格边框不起作用
Apache POI set cell border is not working
我遇到了 Apache POI (v 4.1.2) 无法将边框设置为 THIN 的问题。
XLS 和 XLSX 扩展都支持我的代码。当我将数据导出到 XLSX 文件时,一切正常,但是对于 XLS 文件,它不会绘制从单元格 K5 到最后的边框。
这是我的代码:
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);
}
我不知道为什么对于 XLS 文件它只绘制从单元格 K5 开始的边框。该代码不会引发错误或异常。
感谢大家的支持。
有Excel limits for unique cell formats/cell styles as well as for fonts个。单元格样式和字体存储在工作簿级别。它们为所有工作表中的所有单元格共享。当前 Excel 版本限制为:
Unique cell formats/cell styles: 65,490
和
Unique font types: 1,024 global fonts available for use; 512 per
workbook
Excel(二进制 *.xls)的早期版本限制更小。
因此,如果您像现在一样为每个单元格创建单独的单元格样式,您将很快达到极限。 XSSF
可能会因为限制更大而起作用。但是 Excel(二进制 *.xls)的旧版本有更小的限制。这就是为什么它不使用 HSSF
.
的原因
所以要做的是,根据工作簿的需要在工作簿级别创建尽可能多的单元格样式一次。在单元格填充过程之外执行此操作。在创建单元格本身时,仅使用 cell.setCellStyle
应用单元格样式。但此时无法创建。
让我们用一个完整的例子来说明这一点。它部分使用了您的 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);
}
}
我遇到了 Apache POI (v 4.1.2) 无法将边框设置为 THIN 的问题。 XLS 和 XLSX 扩展都支持我的代码。当我将数据导出到 XLSX 文件时,一切正常,但是对于 XLS 文件,它不会绘制从单元格 K5 到最后的边框。
这是我的代码:
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);
}
我不知道为什么对于 XLS 文件它只绘制从单元格 K5 开始的边框。该代码不会引发错误或异常。
感谢大家的支持。
有Excel limits for unique cell formats/cell styles as well as for fonts个。单元格样式和字体存储在工作簿级别。它们为所有工作表中的所有单元格共享。当前 Excel 版本限制为:
Unique cell formats/cell styles: 65,490
和
Unique font types: 1,024 global fonts available for use; 512 per workbook
Excel(二进制 *.xls)的早期版本限制更小。
因此,如果您像现在一样为每个单元格创建单独的单元格样式,您将很快达到极限。 XSSF
可能会因为限制更大而起作用。但是 Excel(二进制 *.xls)的旧版本有更小的限制。这就是为什么它不使用 HSSF
.
所以要做的是,根据工作簿的需要在工作簿级别创建尽可能多的单元格样式一次。在单元格填充过程之外执行此操作。在创建单元格本身时,仅使用 cell.setCellStyle
应用单元格样式。但此时无法创建。
让我们用一个完整的例子来说明这一点。它部分使用了您的 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);
}
}