XSSF(POI) - 更改数据透视表上的字体

时间:2015-09-28 17:25:26

标签: java excel apache-poi pivot-table xssf

我正在使用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

2 个答案:

答案 0 :(得分:1)

这是一个部分答案,因为它需要使用excel来设置而不是纯粹的poi。

一般步骤:

  1. 使用excel中的数据透视表创建电子表格,或使用sample获取poi。
  2. 在Excel中打开电子表格,然后保存
  3. 在poi中打开电子表格。
  4. 创建CTDxfs条目。这是表格的“字体”。
  5. 使用CTDXfs id创建pivotArea定义。
  6. 代码:

    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
    }
    

    注意:

      访问列标题时需要
    • setOutline(false)
    • setDataOnly(false)允许更改影响标签和数据。
    • setLabelOnly(true)仅限制对标签值的更改。如果要更改整个列/行,请设置为false。
    • unsigned int max value的引用字段值将引用定义为列,另一个有效值为0,将引用定义为行。
    • 如果col / row引用未定义,例如setColHeaderFont / setLabel字体,则会影响整个列/行。这可能适用于格式化特定列。

    警告 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的先前答案更为复杂。

一般步骤:

  1. 使用excel中的数据透视表创建电子表格,或使用sample获取poi。
  2. 创建数据透视缓存定义。
  3. 创建CTDxfs条目。这是&#34; font&#34;对于表格。 (见其他答案)
  4. 使用CTDXfs id创建pivotArea定义。 (见其他答案)
  5. 第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;
        }
    }