Apache POI:默认 Excel 单元格样式
Apache POI: default Excel cell styles
有没有办法在 Apache POI 中使用默认的 Excel 单元格样式(见下文),类似于 BuiltinFormats 中的默认数据格式?
如果“一种使用默认 Excel 单元格样式的方法”意味着能够使用 apache poi
使用命名单元格样式来设置单元格样式,那么不,这是不可能的。
单元格样式模板就是这个,单元格样式模板。如果在 Excel GUI 中选择,GUI 会根据所选模板在工作簿级别创建单元格样式,然后将该单元格样式应用于单元格。不可能仅将单元格样式的名称存储到 Excel 文件中,然后期望 Excel 相应地设置单元格样式。 Apache poi
也必须这样做。但是它必须知道单个模板定义的是什么。但这似乎没有记录在任何地方。 CellStyle Class 状态:
Annex H contains a listing of cellStyles whose corresponding
formatting records are implied rather than explicitly saved in the
file. In this case, a builtinId attribute is written on the cellStyle
record, but no corresponding formatting records are written.
但是我在任何地方都找不到附件 H。可能是我太笨没找到。
我们唯一能做的就是创建自己的自定义命名单元格样式,然后就可以使用了。
而且,如果我们以某种方式获得内置单元格样式模板的 builtinId
,那么我们就可以创建单元格样式来覆盖那些内置单元格样式模板。但是 trial/error 只能通过 trial/error 获取内置单元格样式模板的 builtinId
,因为它们没有记录:
创建一个 Excel 文件,该文件使用一些内置的单元格样式模板。将该文件另存为 *.xlsx
文件。然后解压缩 *.xlsx
文件并查看 /xl/styles.xml
。看看他们有什么builtinId
:
<cellStyles count="4">
<cellStyle name="Gut" xfId="1" builtinId="26"/>
<cellStyle name="Neutral" xfId="3" builtinId="28"/>
<cellStyle name="Schlecht" xfId="2" builtinId="27"/>
<cellStyle name="Standard" xfId="0" builtinId="0"/>
</cellStyles>
下面的完整示例同时执行了这两项操作。它创建三个命名的自定义单元格样式,然后在单元格样式模板列表中可见。
它还会覆盖具有 builtinId="26" 的命名单元格样式。这是名为“Good”的单元格样式。
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.model.StylesTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyles;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyleXfs;
public class CreateExcelNamedXSSFCellStyle {
static void setNamedCellStyle(XSSFWorkbook workbook, XSSFCellStyle style, String name, long builtinId) throws Exception {
StylesTable stylestable = workbook.getStylesSource();
CTStylesheet ctstylesheet = stylestable.getCTStylesheet();
CTCellStyles ctcellstyles = ctstylesheet.getCellStyles();
CTXf ctxfcore = style.getCoreXf();
if (ctcellstyles == null) {
ctcellstyles = ctstylesheet.addNewCellStyles();
ctcellstyles.setCount(2);
CTCellStyle ctcellstyle = ctcellstyles.addNewCellStyle(); //CellStyle for default built-in cell style
ctcellstyle.setXfId(0);
ctcellstyle.setBuiltinId(0);
ctcellstyle = ctcellstyles.addNewCellStyle();
ctcellstyle.setXfId(1);
ctcellstyle.setName(name);
ctxfcore.setXfId(1);
} else {
long stylescount = ctcellstyles.getCount();
ctcellstyles.setCount(stylescount+1);
CTCellStyle ctcellstyle = ctcellstyles.addNewCellStyle();
ctcellstyle.setXfId(stylescount);
ctcellstyle.setName(name);
if (builtinId > -1) ctcellstyle.setBuiltinId(builtinId);
ctxfcore.setXfId(stylescount);
}
CTXf ctxfstyle = CTXf.Factory.newInstance();
ctxfstyle.setNumFmtId(ctxfcore.getNumFmtId());
ctxfstyle.setFontId(ctxfcore.getFontId());
ctxfstyle.setFillId(ctxfcore.getFillId());
ctxfstyle.setBorderId(ctxfcore.getBorderId());
stylestable.putCellStyleXf(ctxfstyle);
}
static XSSFCellStyle getNamedCellStyle(XSSFWorkbook workbook, String name) {
StylesTable stylestable = workbook.getStylesSource();
CTStylesheet ctstylesheet = stylestable.getCTStylesheet();
CTCellStyles ctcellstyles = ctstylesheet.getCellStyles();
if (ctcellstyles != null) {
int i = 0;
XSSFCellStyle style = null;
while((style = stylestable.getStyleAt(i++)) != null) {
CTXf ctxfcore = style.getCoreXf();
long xfid = ctxfcore.getXfId();
for (CTCellStyle ctcellstyle : ctcellstyles.getCellStyleList()) {
if (ctcellstyle.getXfId() == xfid && name.equals(ctcellstyle.getName())) {
return style;
}
}
}
}
return workbook.getCellStyleAt(0); //if nothing found return default cell style
}
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
//The following creates three named custom cell styles
IndexedColorMap colorMap = workbook.getStylesSource().getIndexedColors();
XSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{(byte)255, 0, 0}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "My Custom Style 1", -1);
style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{0, (byte)255, 0}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "My Custom Style 2", -1);
style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{0, 0, (byte)255}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "My Custom Style 3", -1);
//The following uses the custom named cell styles
XSSFSheet sheet = workbook.createSheet("TestSheet");
XSSFRow row = sheet.createRow(0);
for (int i = 0; i < 3; i++) {
XSSFCell cell = row.createCell(i);
style = getNamedCellStyle(workbook, "My Custom Style " + (i+1));
cell.setCellStyle(style);
}
row = sheet.createRow(2);
XSSFCell cell = row.createCell(0);
style = getNamedCellStyle(workbook, "not found");
cell.setCellStyle(style);
//The following overwrites the named cell style having builtinId="26". This is the cell style named "Good".
style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{(byte)198, (byte)239, (byte)206}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "Good", 26);
cell = row.createCell(1);
style = getNamedCellStyle(workbook, "Good");
cell.setCellStyle(style);
FileOutputStream out = new FileOutputStream("CreateExcelNamedXSSFCellStyle.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
有没有办法在 Apache POI 中使用默认的 Excel 单元格样式(见下文),类似于 BuiltinFormats 中的默认数据格式?
如果“一种使用默认 Excel 单元格样式的方法”意味着能够使用 apache poi
使用命名单元格样式来设置单元格样式,那么不,这是不可能的。
单元格样式模板就是这个,单元格样式模板。如果在 Excel GUI 中选择,GUI 会根据所选模板在工作簿级别创建单元格样式,然后将该单元格样式应用于单元格。不可能仅将单元格样式的名称存储到 Excel 文件中,然后期望 Excel 相应地设置单元格样式。 Apache poi
也必须这样做。但是它必须知道单个模板定义的是什么。但这似乎没有记录在任何地方。 CellStyle Class 状态:
Annex H contains a listing of cellStyles whose corresponding formatting records are implied rather than explicitly saved in the file. In this case, a builtinId attribute is written on the cellStyle record, but no corresponding formatting records are written.
但是我在任何地方都找不到附件 H。可能是我太笨没找到。
我们唯一能做的就是创建自己的自定义命名单元格样式,然后就可以使用了。
而且,如果我们以某种方式获得内置单元格样式模板的 builtinId
,那么我们就可以创建单元格样式来覆盖那些内置单元格样式模板。但是 trial/error 只能通过 trial/error 获取内置单元格样式模板的 builtinId
,因为它们没有记录:
创建一个 Excel 文件,该文件使用一些内置的单元格样式模板。将该文件另存为 *.xlsx
文件。然后解压缩 *.xlsx
文件并查看 /xl/styles.xml
。看看他们有什么builtinId
:
<cellStyles count="4">
<cellStyle name="Gut" xfId="1" builtinId="26"/>
<cellStyle name="Neutral" xfId="3" builtinId="28"/>
<cellStyle name="Schlecht" xfId="2" builtinId="27"/>
<cellStyle name="Standard" xfId="0" builtinId="0"/>
</cellStyles>
下面的完整示例同时执行了这两项操作。它创建三个命名的自定义单元格样式,然后在单元格样式模板列表中可见。
它还会覆盖具有 builtinId="26" 的命名单元格样式。这是名为“Good”的单元格样式。
import java.io.FileOutputStream;
import java.io.FileInputStream;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.model.StylesTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyles;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyleXfs;
public class CreateExcelNamedXSSFCellStyle {
static void setNamedCellStyle(XSSFWorkbook workbook, XSSFCellStyle style, String name, long builtinId) throws Exception {
StylesTable stylestable = workbook.getStylesSource();
CTStylesheet ctstylesheet = stylestable.getCTStylesheet();
CTCellStyles ctcellstyles = ctstylesheet.getCellStyles();
CTXf ctxfcore = style.getCoreXf();
if (ctcellstyles == null) {
ctcellstyles = ctstylesheet.addNewCellStyles();
ctcellstyles.setCount(2);
CTCellStyle ctcellstyle = ctcellstyles.addNewCellStyle(); //CellStyle for default built-in cell style
ctcellstyle.setXfId(0);
ctcellstyle.setBuiltinId(0);
ctcellstyle = ctcellstyles.addNewCellStyle();
ctcellstyle.setXfId(1);
ctcellstyle.setName(name);
ctxfcore.setXfId(1);
} else {
long stylescount = ctcellstyles.getCount();
ctcellstyles.setCount(stylescount+1);
CTCellStyle ctcellstyle = ctcellstyles.addNewCellStyle();
ctcellstyle.setXfId(stylescount);
ctcellstyle.setName(name);
if (builtinId > -1) ctcellstyle.setBuiltinId(builtinId);
ctxfcore.setXfId(stylescount);
}
CTXf ctxfstyle = CTXf.Factory.newInstance();
ctxfstyle.setNumFmtId(ctxfcore.getNumFmtId());
ctxfstyle.setFontId(ctxfcore.getFontId());
ctxfstyle.setFillId(ctxfcore.getFillId());
ctxfstyle.setBorderId(ctxfcore.getBorderId());
stylestable.putCellStyleXf(ctxfstyle);
}
static XSSFCellStyle getNamedCellStyle(XSSFWorkbook workbook, String name) {
StylesTable stylestable = workbook.getStylesSource();
CTStylesheet ctstylesheet = stylestable.getCTStylesheet();
CTCellStyles ctcellstyles = ctstylesheet.getCellStyles();
if (ctcellstyles != null) {
int i = 0;
XSSFCellStyle style = null;
while((style = stylestable.getStyleAt(i++)) != null) {
CTXf ctxfcore = style.getCoreXf();
long xfid = ctxfcore.getXfId();
for (CTCellStyle ctcellstyle : ctcellstyles.getCellStyleList()) {
if (ctcellstyle.getXfId() == xfid && name.equals(ctcellstyle.getName())) {
return style;
}
}
}
}
return workbook.getCellStyleAt(0); //if nothing found return default cell style
}
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
//The following creates three named custom cell styles
IndexedColorMap colorMap = workbook.getStylesSource().getIndexedColors();
XSSFCellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{(byte)255, 0, 0}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "My Custom Style 1", -1);
style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{0, (byte)255, 0}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "My Custom Style 2", -1);
style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{0, 0, (byte)255}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "My Custom Style 3", -1);
//The following uses the custom named cell styles
XSSFSheet sheet = workbook.createSheet("TestSheet");
XSSFRow row = sheet.createRow(0);
for (int i = 0; i < 3; i++) {
XSSFCell cell = row.createCell(i);
style = getNamedCellStyle(workbook, "My Custom Style " + (i+1));
cell.setCellStyle(style);
}
row = sheet.createRow(2);
XSSFCell cell = row.createCell(0);
style = getNamedCellStyle(workbook, "not found");
cell.setCellStyle(style);
//The following overwrites the named cell style having builtinId="26". This is the cell style named "Good".
style = workbook.createCellStyle();
style.setFillForegroundColor(new XSSFColor(new byte[]{(byte)198, (byte)239, (byte)206}, colorMap));
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
setNamedCellStyle(workbook, style, "Good", 26);
cell = row.createCell(1);
style = getNamedCellStyle(workbook, "Good");
cell.setCellStyle(style);
FileOutputStream out = new FileOutputStream("CreateExcelNamedXSSFCellStyle.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}