2016-05-18 2 views
2

У меня возникла проблема с методом setDefaultSubtotal для pivotFields axisRow. Когда я устанавливаю значение false для поля RowLabel, Excel не нравится. Вручную создавая вещи, как я хочу их в Excel, а затем сохраняя, получается значительно другой XML, слишком отличный для меня, чтобы рассмотреть возможность фиксации за кулисами. Я не могу (пока) манипулировать XML, чтобы таблица электронных таблиц POI открывалась в Excel.Apache POI XSSFPivotTable setDefaultSubtotal

Фактический код немного длинный и громоздкий для размещения, но вот работоспособная часть с той же проблемой:

private static void sample() throws IOException{ 
    Workbook wb = new XSSFWorkbook(); 
    String[][] data = new String[][]{{"STATUS","PASSED","VALUE"},{"BLUE","Y","20"},{"RED","N","10"},{"BLUE","N","30"}}; 

    XSSFSheet sheet = (XSSFSheet) wb.createSheet("data"); 
    XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary"); 
    for(String[] dataRow : data){ 
     XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); 
     for(String dataCell : dataRow){ 
      XSSFCell cell = row.createCell(row.getPhysicalNumberOfCells()); 
      cell.setCellValue(dataCell); 
     } 
    } 

    XSSFTable table = sheet.createTable();  
    CTTable cttable = table.getCTTable(); 
    table.setDisplayName("table"); 
    cttable.setRef("A1:C4"); 
    cttable.setId(1); 

    CTTableColumns columns = cttable.addNewTableColumns(); 
    columns.setCount(3); 

    int i = 1; 
    for (String colName : data[0]){ 
     CTTableColumn column = columns.addNewTableColumn(); 
     column.setId(++i); 
     column.setName(colName);  
    } 

    XSSFPivotTable pivotTable = pivot.createPivotTable(new AreaReference("A1:C4", SpreadsheetVersion.EXCEL2007), new CellReference("A4"), sheet); 

    pivotTable.addRowLabel(0); 
    CTPivotField fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(0); 
    fld.setOutline(false); 

    //fld.setDefaultSubtotal(false); // uncomment and Excel has problems 

    pivotTable.addRowLabel(1); 
    fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(1); 
    fld.setOutline(false); 

    //fld.setDefaultSubtotal(false); // uncomment and Excel has problems 

    pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 2, "test"); 

    FileOutputStream fileOut = new FileOutputStream("c:/temp/pivotsample.xlsx"); 
    wb.write(fileOut); 
    wb.close(); 

} 

Когда я произвожу версию POI, они являются расположение и pivotFields элементами сводная таблица XML внутри архива:

<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="F10:G11" colPageCount="1"/> 
<pivotFields count="5"> 
    <pivotField axis="axisRow" showAll="false" compact="true" outline="false" defaultSubtotal="false"> 
     <items count="4"> 
      <item t="default"/> 
      <item t="default"/> 
      <item t="default"/> 
      <item t="default"/> 
     </items> 
    </pivotField> 
    <pivotField dataField="true" showAll="false"/> 
    <pivotField dataField="true" showAll="false"/> 
    <pivotField axis="axisPage" showAll="false"> 
     <items count="4"> 
      <item t="default"/> 
      <item t="default"/> 
      <item t="default"/> 
      <item t="default"/> 
     </items> 
    </pivotField> 
    <pivotField axis="axisRow" showAll="false" compact="true" outline="false" defaultSubtotal="false"> 
     <items count="4"> 
      <item t="default"/> 
      <item t="default"/> 
      <item t="default"/> 
      <item t="default"/> 
     </items> 
    </pivotField> 
</pivotFields> 

Когда я открываю в Excel и позволить ему восстановить лист, я затем внести изменения в Excel, чтобы делать то, что я хотел, а именно две строки этикетки без подытог в табличной форме , это то, что сохраняет Excel:

<location ref="F10:I15" firstHeaderRow="1" firstDataRow="2" firstDataCol="2" rowPageCount="1" colPageCount="1"/> 
<pivotFields count="5"> 
    <pivotField axis="axisRow" outline="0" showAll="0" defaultSubtotal="0"> 
     <items count="3"> 
      <item x="0"/> 
      <item x="1"/> 
      <item x="2"/> 
     </items> 
    </pivotField> 
    <pivotField dataField="1" showAll="0"/> 
    <pivotField dataField="1" showAll="0"/> 
    <pivotField axis="axisPage" showAll="0"> 
     <items count="3"> 
      <item x="0"/> 
      <item x="1"/> 
      <item t="default"/> 
     </items> 
    </pivotField> 
    <pivotField axis="axisRow" outline="0" showAll="0" defaultSubtotal="0"> 
     <items count="2"> 
      <item x="0"/> 
      <item x="1"/> 
     </items> 
    </pivotField> 
</pivotFields> 

Я попытался просто обо всем, и я понимаю, формат Excel, но это зависит от pivotCacheRecords, так что я бы в конечном итоге, чтобы написать код, чтобы заполнить это. Если есть кто-нибудь, кто может понять, почему этот код терпит неудачу, я был бы признателен за указатель.

+0

Я получаю тот же вопрос. Можете ли вы рассказать мне, как вы решили это по-другому. Будет здорово, если вы дадите мне пример кода. –

+0

Извините, @RajKantaria, я еще не сделал этого с этим, теперь перешел на некоторые другие вопросы, вернусь к нему в конце концов. Удачи. –

+0

@RajKantaria, ответ ниже работает отлично, надеюсь, что он и для вас. –

ответ

5

См. Также How to set default value in Apache POI pivot table report filter.

До сих пор apache poi добавляет столько элементов поворотного поля типа «по умолчанию» (<item t="default"/>), что и строки, присутствующие в диапазоне данных, если поля поворота используются в качестве полей оси. Это связано с тем, что они не хотят смотреть на данные, и поэтому они принимают столько разных значений, сколько строк в данных.

Это прекрасно, потому что Excel будет восстанавливать сводный кеш при открытии. Но если мы хотим изменить значения по умолчанию, то это не нормально. Тогда мы должны знать, какие предметы есть.

Таким образом, нам нужно по крайней мере, столько же элементов, как и разные из них в данных, в виде нумерованных пунктов: <item x="0"/><item x="1"/>

И нам нужно создать определение кэша, который совместно элементы для этих элементов.

Пример:

import org.apache.poi.xssf.usermodel.*; 
import org.apache.poi.ss.usermodel.*; 
import org.apache.poi.ss.util.*; 
import org.apache.poi.ss.*; 

import java.io.*; 

import org.openxmlformats.schemas.spreadsheetml.x2006.main.*; 

class PivotTableTest6 { 

public static void main(String[] args) throws IOException{ 
    Workbook wb = new XSSFWorkbook(); 
    String[][] data = new String[][]{{"STATUS","PASSED","VALUE"},{"BLUE","Y","20"},{"RED","N","10"},{"BLUE","N","30"}}; 

    XSSFSheet sheet = (XSSFSheet) wb.createSheet("data"); 
    XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary"); 
    for(String[] dataRow : data){ 
     XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows()); 
     for(String dataCell : dataRow){ 
      XSSFCell cell = row.createCell(row.getPhysicalNumberOfCells()); 
      cell.setCellValue(dataCell); 
     } 
    } 

    XSSFTable table = sheet.createTable();  
    CTTable cttable = table.getCTTable(); 
    table.setDisplayName("table"); 
    cttable.setRef("A1:C4"); 
    cttable.setId(1); 

    CTTableColumns columns = cttable.addNewTableColumns(); 
    columns.setCount(3); 

    int i = 1; 
    for (String colName : data[0]){ 
     CTTableColumn column = columns.addNewTableColumn(); 
     column.setId(++i); 
     column.setName(colName);  
    } 

    XSSFPivotTable pivotTable = pivot.createPivotTable(new AreaReference("A1:C4", SpreadsheetVersion.EXCEL2007), new CellReference("A4"), sheet); 

    pivotTable.addRowLabel(0); 
    CTPivotField fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(0); 
    fld.setOutline(false); 

    /* 
    Apache poi adds 4 pivot field items of type "default" (<item t="default"/>) here. 
    This is because there are 4 rows (A1:C4) and, because they don't have a look at the data, 
    they are assuming max 4 different values. This is fine because Excel will rebuild its pivot cache while opening. 

    But if we want changing defaults, then this is not fine. Then we must know what items there are. 

    So we need at least as much items, as are different ones in the data, as numbered items: <item x="0"/><item x="1"/> 

    And we must build a cache definition which has shared elements for those items. 
    */ 

    for (i = 0; i < 2; i++) { 
    //take the first 2 items as numbered items: <item x="0"/><item x="1"/> 
    fld.getItems().getItemArray(i).unsetT(); 
    fld.getItems().getItemArray(i).setX((long)i); 
    } 
    for (i = 3; i > 1; i--) { 
    //remove further items 
    fld.getItems().removeItem(i); 
    } 
    //set new items count 
    fld.getItems().setCount(2); 

    //build a cache definition which has shared elements for those items 
    //<sharedItems><s v="Y"/><s v="N"/></sharedItems> 
    pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldList().get(0).getSharedItems().addNewS().setV("Y"); 
    pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().getCacheFields().getCacheFieldList().get(0).getSharedItems().addNewS().setV("N"); 

    fld.setDefaultSubtotal(false); 

    pivotTable.addRowLabel(1); 
    fld = pivotTable.getCTPivotTableDefinition().getPivotFields().getPivotFieldList().get(1); 
    fld.setOutline(false); 

    pivotTable.addColumnLabel(DataConsolidateFunction.COUNT, 2, "test"); 

    FileOutputStream fileOut = new FileOutputStream("pivotsample6.xlsx"); 
    wb.write(fileOut); 
    wb.close(); 

} 
} 
+0

Спасибо, спасибо за объяснение. Я дам награду, когда мне позволено. Рассматривая это в моем конкретном случае, кажется, не имеет значения, для чего я устанавливаю значения поля или даже если у меня достаточно, чтобы покрыть различные значения из набора данных в массиве элементов поля. Будут ли какие-либо побочные эффекты, если я просто установил одно значение в определении кеша, равное первой записи для этого столбца в исходной таблице? –