我正在使用Apache POI 3.12:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.12</version>
</dependency>
如何更改数据透视表中的字体? 将一个单元格(I7)的字体更改为大小为8pt后检查生成的.xlsx会显示以下更改:
styles.xml,在标记内作为第二个条目:
<font>
<sz val="8"/>
<color indexed="8"/>
<name val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</font>
within the <cellXfs> tag as the 5th entry:
<xf numFmtId="0" fontId="1" fillId="0" borderId="0" xfId="0" applyNumberFormat="1" applyFont="1"/>
New tag: dxfs:
<dxfs count="1">
<dxf>
<font>
<sz val="8"/>
</font>
</dxf>
</dxfs>
pivottable.xml
<formats count="1">
<format dxfId="0">
<pivotArea collapsedLevelsAreSubtotals="1" fieldPosition="0">
<references count="2">
<reference field="4294967294" count="1" selected="0">
<x v="0"/>
</reference>
<reference field="0" count="1">
<x v="0"/>
</reference>
</references>
</pivotArea>
</format>
</formats>
sheet1.xml
<c r="I7" s="4">
注意:我可以将其作为自我答案关闭,因为我仍在尝试自己解决。但是,我已经有近一个星期了。 POI Pivot table sample
答案 0 :(得分:1)
这是一个部分答案,因为它需要使用excel来设置而不是纯粹的poi。
一般步骤:
代码:
private static CTFormats getFormats(XSSFPivotTable pivotTable) {
CTFormats formats = pivotTable.getCTPivotTableDefinition().getFormats();
if(formats==null)
formats=pivotTable.getCTPivotTableDefinition().addNewFormats();
return formats;
}
private static int createDXFs(XSSFWorkbook wb,int font) {
CTDxfs dxfs=wb.getStylesSource().getCTStylesheet().getDxfs();
if(dxfs==null)
dxfs=wb.getStylesSource().getCTStylesheet().addNewDxfs();
dxfs.setCount(dxfs.getCount()+1);
CTDxf dxf=dxfs.addNewDxf();
CTFontSize fontSize=dxf.addNewFont().addNewSz();
fontSize.setVal(font);
return (int) dxfs.getCount()-1;
}
public static void setAxisFont(CTFormats pivotTableFormats,int dxfId) {
CTFormat format=pivotTableFormats.addNewFormat();
format.setDxfId(dxfId);
CTPivotArea pivotArea = format.addNewPivotArea();
pivotArea.setDataOnly(false);
pivotArea.setLabelOnly(true);
pivotArea.setOutline(false);
pivotArea.setFieldPosition(0L);
pivotArea.setAxis(STAxis.AXIS_ROW);
pivotArea.setType(STPivotAreaType.BUTTON);
}
public static void setColHeaderFont(CTFormats pivotTableFormats,int dxfId,int colInd) {
CTFormat format=pivotTableFormats.addNewFormat();
format.setDxfId(dxfId);
CTPivotArea pivotArea = format.addNewPivotArea();
pivotArea.setDataOnly(false);
pivotArea.setLabelOnly(true);
pivotArea.setOutline(false);
CTPivotAreaReferences references = pivotArea.addNewReferences();
CTPivotAreaReference reference = references.addNewReference();
reference.setField(new Long(Integer.MAX_VALUE)*2);
CTIndex x = reference.addNewX();
x.setV(colInd); //Column
}
public static void setLabelFont(CTFormats pivotTableFormats,int dxfId, int rowInd) {
CTFormat format=pivotTableFormats.addNewFormat();
format.setDxfId(dxfId);
CTPivotArea pivotArea = format.addNewPivotArea();
pivotArea.setDataOnly(false);
pivotArea.setLabelOnly(true);
pivotArea.setFieldPosition(0L);
CTPivotAreaReferences references = pivotArea.addNewReferences();
CTPivotAreaReference reference = references.addNewReference();
reference.setField(0L);
CTIndex x = reference.addNewX();
x.setV(rowInd); //Row
}
public static void setDataElementFont(CTFormats pivotTableFormats,int dxfId,int col,int row) {
CTFormat format=pivotTableFormats.addNewFormat();
format.setDxfId(dxfId);
CTPivotArea pivotArea = format.addNewPivotArea();
//Default values, don't need to explicitly define.
//pivotArea.setDataOnly(true);
//pivotArea.setLabelOnly(false);
CTPivotAreaReferences references = pivotArea.addNewReferences();
CTPivotAreaReference reference = references.addNewReference();
reference.setField(new Long(Integer.MAX_VALUE)*2);
CTIndex x = reference.addNewX();
x.setV(col); //Column
reference = references.addNewReference();
reference.setField(0L);
x = reference.addNewX();
x.setV(row); //Row
}
注意:
警告 maven for poi 3.12使用的poi-ooxml-schemas不包含CTFormats。这可以通过排除它并包括1.1版本来覆盖:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.1</version>
</dependency>
答案 1 :(得分:1)
这是一个完整的答案,但比使用excel的先前答案更为复杂。
一般步骤:
第2步本身看起来很无害,但却是整个过程的关键。当Excel打开.xlsx文档时,它会重新验证所有pivotTable条目,删除任何不再存在的条目,包括CTDXfs条目。然后它生成缓存,然后它应用任何格式。但是,如果缓存尚不存在,则在验证过程中会删除所有格式规则!
下面是我用来生成pivotCache的代码块。这比普通的stackOverflow答案要长得多,但不确定这是否是首选或&#34;一般指导&#34;如何做到这一点。
如果您需要维护或扩展它,请将.xlsx重命名为.zip,解压缩,然后在excel中保存之前和之后查看xl \ pivotTables \ pivotTable1.xml,xl \ pivotCache \ pivotCacheDefinition1.xml。如果这个工作正常,那么在将其保存在excel中之后,pivotCacheDefinition应该基本不变。
public class PivotUtilitiesExample {
public static void updateCache(XSSFPivotTable pivotTable) {
updateCache(pivotTable,STAxis.AXIS_ROW);
updateCache(pivotTable,STAxis.AXIS_COL);
updateCache(pivotTable,STAxis.AXIS_PAGE);
}
/**
* Updates the pivotCacheDefinition.xml file. This must be run before any formatting is done.
* However, it must also be run *AFTER* the pivotTable's source data is created and all label definitions are defined.
* the labels are sorted by default.
* @param pivotTable
* @param rowLabel if true, updates rowLabels, if false, updates columnLabels.
*/
private static void updateCache(XSSFPivotTable pivotTable,STAxis.Enum axisType) {
XSSFSheet sheet=(XSSFSheet) pivotTable.getDataSheet();
AreaReference pivotArea = new AreaReference(pivotTable.getPivotCacheDefinition().
getCTPivotCacheDefinition().getCacheSource().getWorksheetSource().getRef());
CellReference firstCell = pivotArea.getFirstCell();
CellReference lastCell = pivotArea.getLastCell();
List<Integer> labelColumns=getLabelColumns(pivotTable,axisType);
for(int labelCtr=0;labelCtr<labelColumns.size();++labelCtr) {
CTSharedItems sharedItems=getSharedItems(pivotTable,labelColumns.get(labelCtr));
//The pivotField entry associated will be the nth axis="axisRow" entry where N is the row label #.
CTPivotField pivotField=getPivotField(pivotTable,axisType,labelCtr);
CTItems items=pivotField.getItems();
ArrayList<String> toCache=new ArrayList<String>(lastCell.getRow()-firstCell.getRow());
//To make this work, sharedItems and pivotFields must be properly populated.
//sharedItems should look like:
//<cacheField name="Names" numFmtId="0"> (Cell A1)
//<sharedItems count="3"> (Count of unique rows)
//<s v="Jane"/> (Cell B1)
//<s v="Tarzan"/> (Cell C1)
//<s v="Terk"/> (Cell D1)
//</sharedItems>
//pivotFields should have an entry like this:
//<pivotField axis="axisRow" showAll="0">
//<items count="4">
//<item x="0"/>
//<item x="1"/>
//<item x="2"/>
//<item t="default"/>
//</items>
//Initially, POI will populate with:
//<pivotField axis="axisRow" showAll="0">
//<items count="4">
//<item t="default"/>
//<item t="default"/>
//<item t="default"/>
//<item t="default"/>
//</items>
//Start with firstCell.getRow()+1 since the first row is the column name.
for(int i=firstCell.getRow()+1;i<=lastCell.getRow();++i) {
String s=sheet.getRow(i).getCell(firstCell.getCol()+labelColumns.get(labelCtr)).getStringCellValue();
//Only add unique entries.
if(!toCache.contains(s))
toCache.add(s);
}
//Blank entries cannot be sorted unless they are specially entered after an M tag.
// For most projects this'll be overkill.
boolean containsBlank=false;
if(toCache.contains("")) {
toCache.remove("");
containsBlank=true;
}
//Remove the old cache list.
for(int i=items.sizeOfItemArray()-1;i>=0;--i)
items.removeItem(i);
for(int i=sharedItems.sizeOfBArray()-1;i>=0;--i)
sharedItems.removeB(i);
for(int i=sharedItems.sizeOfDArray()-1;i>=0;--i)
sharedItems.removeD(i);
for(int i=sharedItems.sizeOfEArray()-1;i>=0;--i)
sharedItems.removeE(i);
for(int i=sharedItems.sizeOfMArray()-1;i>=0;--i)
sharedItems.removeM(i);
for(int i=sharedItems.sizeOfNArray()-1;i>=0;--i)
sharedItems.removeN(i);
for(int i=sharedItems.sizeOfSArray()-1;i>=0;--i)
sharedItems.removeS(i);
sharedItems.setCount(sharedItems.getDomNode().getChildNodes().getLength());
items.setCount(items.sizeOfItemArray());
for(int i=0;i<toCache.size();++i) {
CTString string;
CTItem item;
string=sharedItems.addNewS();
sharedItems.setCount(sharedItems.getDomNode().getChildNodes().getLength());
string.setV(toCache.get(i));
item=items.addNewItem();
items.setCount(items.sizeOfItemArray());
item.setX(i);
}
//Create the special blank tag.
if(containsBlank) {
int mPosition;
sharedItems.addNewM();
mPosition=sharedItems.sizeOfSArray();
CTString s=sharedItems.addNewS();
s.setV("");
s.setU(true);
sharedItems.setCount(sharedItems.getDomNode().getChildNodes().getLength());
sharedItems.setContainsBlank(true);
CTItem item=items.addNewItem();
item.setM(true);
item.setX(sharedItems.sizeOfSArray());
item=items.addNewItem();
item.setX(mPosition);
items.setCount(items.sizeOfItemArray());
}
//Add the t="default" entry, required for subtotals.
if(!pivotField.isSetDefaultSubtotal() || pivotField.getDefaultSubtotal()==true) {
CTItem item;
item=items.addNewItem();
items.setCount(items.sizeOfItemArray());
item.setT(STItemType.DEFAULT);
}
}
}
//Returns the label columns for all AXIS. Default POI only has a method for RowLabelColumns.
private static List<Integer> getLabelColumns(XSSFPivotTable pivotTable,STAxis.Enum axisType) {
List<Integer> labelColumns;
if(axisType.equals(STAxis.AXIS_ROW))
labelColumns=pivotTable.getRowLabelColumns();
else if(axisType.equals(STAxis.AXIS_COL)) {
List<CTField> fieldList = pivotTable.getCTPivotTableDefinition().getColFields().getFieldList();
labelColumns=new ArrayList(fieldList.size());
for(CTField field:fieldList)
labelColumns.add(field.getX());
} else if(axisType.equals(STAxis.AXIS_PAGE)) {
List<CTPageField> fieldList = pivotTable.getCTPivotTableDefinition().getPageFields().getPageFieldList();
labelColumns=new ArrayList(fieldList.size());
for(CTPageField field:fieldList)
labelColumns.add(field.getFld());
} else {
throw new UnsupportedOperationException("Error, STAxis: "+axisType+" is not supported");
}
return labelColumns;
}
//Returns the sharedItems entry associated with a particular labelColumn.
private static CTSharedItems getSharedItems(XSSFPivotTable pivotTable,int columnIndex) {
XSSFSheet sheet=(XSSFSheet) pivotTable.getDataSheet();
AreaReference pivotArea = new AreaReference(pivotTable.getPivotCacheDefinition().
getCTPivotCacheDefinition().getCacheSource().getWorksheetSource().getRef());
CellReference firstCell = pivotArea.getFirstCell();
String labelName=sheet.getRow(firstCell.getRow()).getCell(firstCell.getCol()+columnIndex).getStringCellValue();
List<CTCacheField> cacheFieldList = pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldList();
CTSharedItems sharedItems=null;
//The sharedItem entry associated will have name=labelColumn's name.
for(int i=0;i<cacheFieldList.size();++i)
if(labelName.equals(cacheFieldList.get(i).getName())) {
sharedItems=cacheFieldList.get(i).getSharedItems();
break;
}
//Should never be true.
if(sharedItems==null) {
throw new RuntimeException("Error, unable to find sharedItems entry in pivotCacheDefinition.xml");
}
return sharedItems;
}
//Return the nth pivotField entry from the pivotTable definition of a particular Axis.
private static CTPivotField getPivotField(XSSFPivotTable pivotTable,STAxis.Enum axisType,int index) {
CTPivotFields pivotFields = pivotTable.getCTPivotTableDefinition().getPivotFields();
CTPivotField pivotField=null;
for(int i=0,axisRowNum=-1;i<pivotFields.getPivotFieldList().size();++i) {
if(axisType.equals(pivotFields.getPivotFieldList().get(i).getAxis()))
++axisRowNum;
if(axisRowNum==index) {
pivotField=pivotFields.getPivotFieldList().get(i);
break;
}
}
if(pivotField==null)
throw new RuntimeException("Error, unable to find pivotField entry in pivotTable.xml");
return pivotField;
}
}