繁体   English   中英

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

[英]XSSF (POI) - Changing the font on a pivot table

我正在使用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数据透视表示例

这是部分答案,因为它需要使用excel进行设置,而不是使用纯poi。

常规步骤:

  1. 在excel中创建带有数据透视表的电子表格,或将示例用于poi。
  2. 在excel中打开电子表格并保存
  3. 在poi中打开电子表格。
  4. 创建一个CTDxfs条目。 这是表格的“字体”。
  5. 使用CTDXfs ID创建一个ivotArea定义。

转到代码:

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。
  • 无符号int max值的引用字段值将引用定义为列,另一个有效值为0,将引用定义为行。
  • 如果未定义col / row引用(例如setColHeaderFont / setLabel字体),则它将影响整个列/行。 这对于格式化特定列可能是理想的。

警告 maven用于poi 3.12的poi-ooxml-schemas不包含CTFormats。 可以通过排除它并包括1.1版本来覆盖它:

<dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>ooxml-schemas</artifactId>
        <version>1.1</version>
</dependency>

这是一个完整的答案,但是比使用excel的先前答案要复杂得多。

一般步骤:

  1. 在excel中创建带有数据透视表的电子表格,或将示例用于poi。
  2. 创建数据透视表缓存定义。
  3. 创建一个CTDxfs条目。 这是表格的“字体”。 (请参阅其他答案)
  4. 使用CTDXfs ID创建一个ivotArea定义。 (请参阅其他答案)

步骤2本身看起来是如此无害,但它是整个过程的关键。 当Excel打开.xlsx文档时,它将重新验证所有数据透视表条目,删除其中不再存在的所有条目,包括CTDXfs条目。 然后,它生成缓存,然后应用任何格式。 但是,如果还不存在缓存,则在验证过程中将删除所有格式规则!

以下是我用来生成ivotCache的代码块。 这比正常的stackOverflow答案要长得多,但是不确定这是首选还是“通用指南”。

如果需要维护或扩展它,请将.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;
    }
}

暂无
暂无

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

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