xref: /trunk/main/oox/source/xls/pivottablebuffer.cxx (revision 3756c4e7)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "oox/xls/pivottablebuffer.hxx"
25 
26 #include <set>
27 #include <com/sun/star/container/XIndexAccess.hpp>
28 #include <com/sun/star/container/XNameAccess.hpp>
29 #include <com/sun/star/sheet/CellFlags.hpp>
30 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
31 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
32 #include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
33 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
34 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
35 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
36 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
37 #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
38 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
39 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
40 #include <com/sun/star/sheet/GeneralFunction.hpp>
41 #include <com/sun/star/sheet/XDataPilotDataLayoutFieldSupplier.hpp>
42 #include <com/sun/star/sheet/XDataPilotField.hpp>
43 #include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
44 #include <com/sun/star/sheet/XSheetOperation.hpp>
45 #include "oox/helper/attributelist.hxx"
46 #include "oox/helper/containerhelper.hxx"
47 #include "oox/helper/propertyset.hxx"
48 #include "oox/xls/addressconverter.hxx"
49 #include "oox/xls/biffinputstream.hxx"
50 
51 namespace oox {
52 namespace xls {
53 
54 // ============================================================================
55 
56 using namespace ::com::sun::star::container;
57 using namespace ::com::sun::star::sheet;
58 using namespace ::com::sun::star::table;
59 using namespace ::com::sun::star::uno;
60 
61 using ::rtl::OUString;
62 
63 // ============================================================================
64 
65 namespace {
66 
67 const sal_Int32 OOX_PT_DATALAYOUTFIELD              = -2;           /// Placeholder index of data layout field.
68 
69 const sal_Int32 OOX_PT_PREVIOUS_ITEM                = 0x001000FC;   /// Calculation of data item result is based on previous item.
70 const sal_Int32 OOX_PT_NEXT_ITEM                    = 0x001000FD;   /// Calculation of data item result is based on next item.
71 
72 // ----------------------------------------------------------------------------
73 
74 const sal_uInt32 BIFF12_PTFIELD_DATAFIELD           = 0x00000008;
75 const sal_uInt32 BIFF12_PTFIELD_DEFAULT             = 0x00000100;
76 const sal_uInt32 BIFF12_PTFIELD_SUM                 = 0x00000200;
77 const sal_uInt32 BIFF12_PTFIELD_COUNTA              = 0x00000400;
78 const sal_uInt32 BIFF12_PTFIELD_AVERAGE             = 0x00000800;
79 const sal_uInt32 BIFF12_PTFIELD_MAX                 = 0x00001000;
80 const sal_uInt32 BIFF12_PTFIELD_MIN                 = 0x00002000;
81 const sal_uInt32 BIFF12_PTFIELD_PRODUCT             = 0x00004000;
82 const sal_uInt32 BIFF12_PTFIELD_COUNT               = 0x00008000;
83 const sal_uInt32 BIFF12_PTFIELD_STDDEV              = 0x00010000;
84 const sal_uInt32 BIFF12_PTFIELD_STDDEVP             = 0x00020000;
85 const sal_uInt32 BIFF12_PTFIELD_VAR                 = 0x00040000;
86 const sal_uInt32 BIFF12_PTFIELD_VARP                = 0x00080000;
87 
88 const sal_uInt32 BIFF12_PTFIELD_SHOWALL             = 0x00000020;
89 const sal_uInt32 BIFF12_PTFIELD_OUTLINE             = 0x00000040;
90 const sal_uInt32 BIFF12_PTFIELD_INSERTBLANKROW      = 0x00000080;
91 const sal_uInt32 BIFF12_PTFIELD_SUBTOTALTOP         = 0x00000100;
92 const sal_uInt32 BIFF12_PTFIELD_INSERTPAGEBREAK     = 0x00000800;
93 const sal_uInt32 BIFF12_PTFIELD_AUTOSORT            = 0x00001000;
94 const sal_uInt32 BIFF12_PTFIELD_SORTASCENDING       = 0x00002000;
95 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOW            = 0x00004000;
96 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOWTOP         = 0x00008000;
97 const sal_uInt32 BIFF12_PTFIELD_MULTIPAGEITEMS      = 0x00080000;
98 
99 const sal_uInt16 BIFF12_PTFITEM_HIDDEN              = 0x0001;
100 const sal_uInt16 BIFF12_PTFITEM_HIDEDETAILS         = 0x0002;
101 
102 const sal_uInt8 BIFF12_PTPAGEFIELD_HASNAME          = 0x01;
103 const sal_uInt8 BIFF12_PTPAGEFIELD_HASOLAPCAPTION   = 0x02;
104 const sal_Int32 BIFF12_PTPAGEFIELD_MULTIITEMS       = 0x001000FE;
105 
106 const sal_uInt16 BIFF12_PTFILTER_HASNAME            = 0x0001;
107 const sal_uInt16 BIFF12_PTFILTER_HASDESCRIPTION     = 0x0002;
108 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE1       = 0x0004;
109 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE2       = 0x0008;
110 
111 const sal_uInt8 BIFF12_TOP10FILTER_TOP              = 0x01;
112 const sal_uInt8 BIFF12_TOP10FILTER_PERCENT          = 0x02;
113 
114 const sal_uInt32 BIFF12_PTDEF_SHOWITEMS             = 0x00000100;
115 const sal_uInt32 BIFF12_PTDEF_DISABLEFIELDLIST      = 0x00000400;
116 const sal_uInt32 BIFF12_PTDEF_HIDECALCMEMBERS       = 0x00001000;
117 const sal_uInt32 BIFF12_PTDEF_WITHHIDDENTOTALS      = 0x00002000;
118 const sal_uInt32 BIFF12_PTDEF_HIDEDRILL             = 0x00100000;
119 const sal_uInt32 BIFF12_PTDEF_PRINTDRILL            = 0x00200000;
120 const sal_uInt32 BIFF12_PTDEF_HIDEHEADERS           = 0x80000000;
121 
122 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYROW          = 0x00000004;
123 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYCOL          = 0x00000008;
124 const sal_uInt32 BIFF12_PTDEF_ENABLEDRILL           = 0x00000020;
125 const sal_uInt32 BIFF12_PTDEF_PRESERVEFORMATTING    = 0x00000080;
126 const sal_uInt32 BIFF12_PTDEF_USEAUTOFORMAT         = 0x00000100;
127 const sal_uInt32 BIFF12_PTDEF_SHOWERROR             = 0x00000200;
128 const sal_uInt32 BIFF12_PTDEF_SHOWMISSING           = 0x00000400;
129 const sal_uInt32 BIFF12_PTDEF_PAGEOVERTHENDOWN      = 0x00000800;
130 const sal_uInt32 BIFF12_PTDEF_SUBTOTALHIDDENITEMS   = 0x00001000;
131 const sal_uInt32 BIFF12_PTDEF_ROWGRANDTOTALS        = 0x00002000;
132 const sal_uInt32 BIFF12_PTDEF_COLGRANDTOTALS        = 0x00004000;
133 const sal_uInt32 BIFF12_PTDEF_FIELDPRINTTITLES      = 0x00008000;
134 const sal_uInt32 BIFF12_PTDEF_ITEMPRINTTITLES       = 0x00020000;
135 const sal_uInt32 BIFF12_PTDEF_MERGEITEM             = 0x00040000;
136 const sal_uInt32 BIFF12_PTDEF_HASDATACAPTION        = 0x00080000;
137 const sal_uInt32 BIFF12_PTDEF_HASGRANDTOTALCAPTION  = 0x00100000;
138 const sal_uInt32 BIFF12_PTDEF_HASPAGESTYLE          = 0x00200000;
139 const sal_uInt32 BIFF12_PTDEF_HASPIVOTTABLESTYLE    = 0x00400000;
140 const sal_uInt32 BIFF12_PTDEF_HASVACATEDSTYLE       = 0x00800000;
141 const sal_uInt32 BIFF12_PTDEF_APPLYNUMFMT           = 0x01000000;
142 const sal_uInt32 BIFF12_PTDEF_APPLYFONT             = 0x02000000;
143 const sal_uInt32 BIFF12_PTDEF_APPLYALIGNMENT        = 0x04000000;
144 const sal_uInt32 BIFF12_PTDEF_APPLYBORDER           = 0x08000000;
145 const sal_uInt32 BIFF12_PTDEF_APPLYFILL             = 0x10000000;
146 const sal_uInt32 BIFF12_PTDEF_APPLYPROTECTION       = 0x20000000;
147 const sal_uInt32 BIFF12_PTDEF_HASTAG                = 0x40000000;
148 
149 const sal_uInt32 BIFF12_PTDEF_NOERRORCAPTION        = 0x00000040;
150 const sal_uInt32 BIFF12_PTDEF_NOMISSINGCAPTION      = 0x00000080;
151 const sal_uInt32 BIFF12_PTDEF_HASROWHEADERCAPTION   = 0x00000400;
152 const sal_uInt32 BIFF12_PTDEF_HASCOLHEADERCAPTION   = 0x00000800;
153 const sal_uInt32 BIFF12_PTDEF_FIELDLISTSORTASC      = 0x00001000;
154 const sal_uInt32 BIFF12_PTDEF_NOCUSTOMLISTSORT      = 0x00004000;
155 
156 const sal_uInt8 BIFF12_PTDEF_ROWAXIS                = 1;
157 const sal_uInt8 BIFF12_PTDEF_COLAXIS                = 2;
158 
159 // ----------------------------------------------------------------------------
160 
161 const sal_uInt16 BIFF_PT_NOSTRING                   = 0xFFFF;
162 
163 const sal_uInt16 BIFF_PTFIELD_DATAFIELD             = 0x0008;
164 const sal_uInt16 BIFF_PTFIELD_DEFAULT               = 0x0001;
165 const sal_uInt16 BIFF_PTFIELD_SUM                   = 0x0002;
166 const sal_uInt16 BIFF_PTFIELD_COUNTA                = 0x0004;
167 const sal_uInt16 BIFF_PTFIELD_AVERAGE               = 0x0008;
168 const sal_uInt16 BIFF_PTFIELD_MAX                   = 0x0010;
169 const sal_uInt16 BIFF_PTFIELD_MIN                   = 0x0020;
170 const sal_uInt16 BIFF_PTFIELD_PRODUCT               = 0x0040;
171 const sal_uInt16 BIFF_PTFIELD_COUNT                 = 0x0080;
172 const sal_uInt16 BIFF_PTFIELD_STDDEV                = 0x0100;
173 const sal_uInt16 BIFF_PTFIELD_STDDEVP               = 0x0200;
174 const sal_uInt16 BIFF_PTFIELD_VAR                   = 0x0400;
175 const sal_uInt16 BIFF_PTFIELD_VARP                  = 0x0800;
176 
177 const sal_uInt32 BIFF_PTFIELD2_SHOWALL              = 0x00000001;
178 const sal_uInt32 BIFF_PTFIELD2_AUTOSORT             = 0x00000200;
179 const sal_uInt32 BIFF_PTFIELD2_SORTASCENDING        = 0x00000400;
180 const sal_uInt32 BIFF_PTFIELD2_AUTOSHOW             = 0x00000800;
181 const sal_uInt32 BIFF_PTFIELD2_AUTOSHOWTOP          = 0x00001000;
182 const sal_uInt32 BIFF_PTFIELD2_OUTLINE              = 0x00200000;
183 const sal_uInt32 BIFF_PTFIELD2_INSERTBLANKROW       = 0x00400000;
184 const sal_uInt32 BIFF_PTFIELD2_SUBTOTALTOP          = 0x00800000;
185 
186 const sal_uInt16 BIFF_PTFITEM_HIDDEN                = 0x0001;
187 const sal_uInt16 BIFF_PTFITEM_HIDEDETAILS           = 0x0002;
188 
189 const sal_uInt16 BIFF_PTDEF_ROWGRANDTOTALS          = 0x0001;
190 const sal_uInt16 BIFF_PTDEF_COLGRANDTOTALS          = 0x0002;
191 
192 const sal_uInt8 BIFF_PTDEF_ROWAXIS                  = 1;
193 const sal_uInt8 BIFF_PTDEF_COLAXIS                  = 2;
194 
195 const sal_uInt32 BIFF_PTDEF2_PAGEOVERTHENDOWN       = 0x00000001;
196 const sal_uInt32 BIFF_PTDE2F_ENABLEDRILL            = 0x00020000;
197 const sal_uInt32 BIFF_PTDEF2_PRESERVEFORMATTING     = 0x00080000;
198 const sal_uInt32 BIFF_PTDEF2_MERGEITEM              = 0x00100000;
199 const sal_uInt32 BIFF_PTDEF2_SHOWERROR              = 0x00200000;
200 const sal_uInt32 BIFF_PTDEF2_SHOWMISSING            = 0x00400000;
201 const sal_uInt32 BIFF_PTDEF2_SUBTOTALHIDDENITEMS    = 0x00800000;
202 
203 const sal_Int16 BIFF_PTPAGEFIELDS_ALLITEMS          = 0x7FFD;
204 
205 const sal_Int16 BIFF_PTDATAFIELD_PREVIOUS           = 0x7FFB;
206 const sal_Int16 BIFF_PTDATAFIELD_NEXT               = 0x7FFC;
207 
208 // ----------------------------------------------------------------------------
209 
lclReadPivotString(const WorkbookHelper & rHelper,BiffInputStream & rStrm,sal_uInt16 nLen)210 OUString lclReadPivotString( const WorkbookHelper& rHelper, BiffInputStream& rStrm, sal_uInt16 nLen )
211 {
212     if( nLen == BIFF_PT_NOSTRING )
213         return OUString();
214     return (rHelper.getBiff() == BIFF8) ? rStrm.readUniStringBody( nLen ) : rStrm.readCharArrayUC( nLen, rHelper.getTextEncoding() );
215 }
216 
217 } // namespace
218 
219 // ============================================================================
220 
PTFieldItemModel()221 PTFieldItemModel::PTFieldItemModel() :
222     mnCacheItem( -1 ),
223     mnType( XML_data ),
224     mbShowDetails( true ),
225     mbHidden( false )
226 {
227 }
228 
setBiffType(sal_uInt16 nType)229 void PTFieldItemModel::setBiffType( sal_uInt16 nType )
230 {
231     static const sal_Int32 spnTypes[] = { XML_data, XML_default,
232         XML_sum, XML_countA, XML_avg, XML_max, XML_min, XML_product, XML_count,
233         XML_stdDev, XML_stdDevP, XML_var, XML_varP, XML_grand, XML_blank };
234     mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_data );
235 }
236 
237 // ----------------------------------------------------------------------------
238 
PTFieldModel()239 PTFieldModel::PTFieldModel() :
240     mnAxis( XML_TOKEN_INVALID ),
241     mnNumFmtId( 0 ),
242     mnAutoShowItems( 10 ),
243     mnAutoShowRankBy( -1 ),
244     mnSortType( XML_manual ),
245     mnSortRefField( -1 ),
246     mnSortRefItem( -1 ),
247     mbDataField( false ),
248     mbDefaultSubtotal( true ),
249     mbSumSubtotal( false ),
250     mbCountASubtotal( false ),
251     mbAverageSubtotal( false ),
252     mbMaxSubtotal( false ),
253     mbMinSubtotal( false ),
254     mbProductSubtotal( false ),
255     mbCountSubtotal( false ),
256     mbStdDevSubtotal( false ),
257     mbStdDevPSubtotal( false ),
258     mbVarSubtotal( false ),
259     mbVarPSubtotal( false ),
260     mbShowAll( true ),
261     mbOutline( true ),
262     mbSubtotalTop( true ),
263     mbInsertBlankRow( false ),
264     mbInsertPageBreak( false ),
265     mbAutoShow( false ),
266     mbTopAutoShow( true ),
267     mbMultiPageItems( false )
268 {
269 }
270 
setBiffAxis(sal_uInt8 nAxis)271 void PTFieldModel::setBiffAxis( sal_uInt8 nAxis )
272 {
273     /*  Weird. The axis field is organized as bit field, but only one of the
274         row/col/page flags are allowed at the same time and refer to the values
275         'axisRow', 'axisCol', and 'axisPage' of the XML attribute
276         'pivotField@axis'. Additionally, the fourth bit determines if the field
277         is a data field, which may appear combined with the row/col/page flags.
278         Therefore, this bit is unrelated to the 'axisValues' value of the
279         'pivotField@axis' attribute, but refers to the 'pivotField@dataField'
280         boolean attribute. */
281     static const sal_Int32 spnAxisIds[] = { XML_TOKEN_INVALID, XML_axisRow, XML_axisCol, XML_TOKEN_INVALID, XML_axisPage };
282     mnAxis = STATIC_ARRAY_SELECT( spnAxisIds, nAxis, XML_TOKEN_INVALID );
283 }
284 
285 // ----------------------------------------------------------------------------
286 
PTPageFieldModel()287 PTPageFieldModel::PTPageFieldModel() :
288     mnField( -1 ),
289     mnItem( BIFF12_PTPAGEFIELD_MULTIITEMS )
290 {
291 }
292 
293 // ----------------------------------------------------------------------------
294 
PTDataFieldModel()295 PTDataFieldModel::PTDataFieldModel() :
296     mnField( -1 ),
297     mnSubtotal( XML_sum ),
298     mnShowDataAs( XML_normal ),
299     mnBaseField( -1 ),
300     mnBaseItem( -1 ),
301     mnNumFmtId( 0 )
302 {
303 }
304 
setBiffSubtotal(sal_Int32 nSubtotal)305 void PTDataFieldModel::setBiffSubtotal( sal_Int32 nSubtotal )
306 {
307     static sal_Int32 spnSubtotals[] = { XML_sum, XML_count, XML_average, XML_max, XML_min, XML_product, XML_countNums, XML_stdDev, XML_stdDevp, XML_var, XML_varp };
308     mnSubtotal = STATIC_ARRAY_SELECT( spnSubtotals, nSubtotal, XML_TOKEN_INVALID );
309 }
310 
setBiffShowDataAs(sal_Int32 nShowDataAs)311 void PTDataFieldModel::setBiffShowDataAs( sal_Int32 nShowDataAs )
312 {
313     static sal_Int32 spnShowDataAs[] = { XML_normal, XML_difference, XML_percent, XML_percentDiff, XML_runTotal, XML_percentOfRow, XML_percentOfCol, XML_percentOfTotal, XML_index };
314     mnShowDataAs = STATIC_ARRAY_SELECT( spnShowDataAs, nShowDataAs, XML_TOKEN_INVALID );
315 }
316 
317 // ----------------------------------------------------------------------------
318 
PivotTableField(PivotTable & rPivotTable,sal_Int32 nFieldIndex)319 PivotTableField::PivotTableField( PivotTable& rPivotTable, sal_Int32 nFieldIndex ) :
320     WorkbookHelper( rPivotTable ),
321     mrPivotTable( rPivotTable ),
322     mnFieldIndex( nFieldIndex )
323 {
324 }
325 
importPivotField(const AttributeList & rAttribs)326 void PivotTableField::importPivotField( const AttributeList& rAttribs )
327 {
328     /*  The documentation mentions a value 'axisValues' for the attribute
329         'pivotField@axis'. But this value is not used to mark a data field, as
330         data fields may be inserted in one of the row/column/page dimensions at
331         the same time. Therefore, the boolean attribute 'pivotField@dataField'
332         is really used to mark data fields. */
333     maModel.mnAxis            = rAttribs.getToken( XML_axis, XML_TOKEN_INVALID );
334     maModel.mnNumFmtId        = rAttribs.getInteger( XML_numFmtId, 0 );
335     maModel.mnAutoShowItems   = rAttribs.getInteger( XML_itemPageCount, 10 );
336     maModel.mnAutoShowRankBy  = rAttribs.getInteger( XML_rankBy, -1 );
337     maModel.mnSortType        = rAttribs.getToken( XML_sortType, XML_manual );
338     maModel.mbDataField       = rAttribs.getBool( XML_dataField, false );
339     maModel.mbDefaultSubtotal = rAttribs.getBool( XML_defaultSubtotal, true );
340     maModel.mbSumSubtotal     = rAttribs.getBool( XML_sumSubtotal, false );
341     maModel.mbCountASubtotal  = rAttribs.getBool( XML_countASubtotal, false );
342     maModel.mbAverageSubtotal = rAttribs.getBool( XML_avgSubtotal, false );
343     maModel.mbMaxSubtotal     = rAttribs.getBool( XML_maxSubtotal, false );
344     maModel.mbMinSubtotal     = rAttribs.getBool( XML_minSubtotal, false );
345     maModel.mbProductSubtotal = rAttribs.getBool( XML_productSubtotal, false );
346     maModel.mbCountSubtotal   = rAttribs.getBool( XML_countSubtotal, false );
347     maModel.mbStdDevSubtotal  = rAttribs.getBool( XML_stdDevSubtotal, false );
348     maModel.mbStdDevPSubtotal = rAttribs.getBool( XML_stdDevPSubtotal, false );
349     maModel.mbVarSubtotal     = rAttribs.getBool( XML_varSubtotal, false );
350     maModel.mbVarPSubtotal    = rAttribs.getBool( XML_varPSubtotal, false );
351     maModel.mbShowAll         = rAttribs.getBool( XML_showAll, true );
352     maModel.mbOutline         = rAttribs.getBool( XML_outline, true );
353     maModel.mbSubtotalTop     = rAttribs.getBool( XML_subtotalTop, true );
354     maModel.mbInsertBlankRow  = rAttribs.getBool( XML_insertBlankRow, false );
355     maModel.mbInsertPageBreak = rAttribs.getBool( XML_insertPageBreak, false );
356     maModel.mbAutoShow        = rAttribs.getBool( XML_autoShow, false );
357     maModel.mbTopAutoShow     = rAttribs.getBool( XML_topAutoShow, true );
358     maModel.mbMultiPageItems  = rAttribs.getBool( XML_multipleItemSelectionAllowed, false );
359 }
360 
importItem(const AttributeList & rAttribs)361 void PivotTableField::importItem( const AttributeList& rAttribs )
362 {
363     PTFieldItemModel aModel;
364     aModel.mnCacheItem   = rAttribs.getInteger( XML_x, -1 );
365     aModel.mnType        = rAttribs.getToken( XML_t, XML_data );
366     aModel.mbShowDetails = rAttribs.getBool( XML_sd, true );
367     aModel.mbHidden      = rAttribs.getBool( XML_h, false );
368     maItems.push_back( aModel );
369 }
370 
importReference(const AttributeList & rAttribs)371 void PivotTableField::importReference( const AttributeList& rAttribs )
372 {
373     // field index is stored as unsigned integer
374     maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsigned( XML_field, SAL_MAX_UINT32 ) );
375 }
376 
importReferenceItem(const AttributeList & rAttribs)377 void PivotTableField::importReferenceItem( const AttributeList& rAttribs )
378 {
379     maModel.mnSortRefItem = rAttribs.getInteger( XML_v, -1 );
380 }
381 
importPTField(SequenceInputStream & rStrm)382 void PivotTableField::importPTField( SequenceInputStream& rStrm )
383 {
384     sal_uInt32 nFlags1, nFlags2;
385     rStrm >> nFlags1 >> maModel.mnNumFmtId >> nFlags2 >> maModel.mnAutoShowItems >> maModel.mnAutoShowRankBy;
386 
387     maModel.setBiffAxis( extractValue< sal_uInt8 >( nFlags1, 0, 3 ) );
388     maModel.mbDataField       = getFlag( nFlags1, BIFF12_PTFIELD_DATAFIELD );
389     maModel.mbDefaultSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_DEFAULT );
390     maModel.mbSumSubtotal     = getFlag( nFlags1, BIFF12_PTFIELD_SUM );
391     maModel.mbCountASubtotal  = getFlag( nFlags1, BIFF12_PTFIELD_COUNTA );
392     maModel.mbAverageSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_AVERAGE );
393     maModel.mbMaxSubtotal     = getFlag( nFlags1, BIFF12_PTFIELD_MAX );
394     maModel.mbMinSubtotal     = getFlag( nFlags1, BIFF12_PTFIELD_MIN );
395     maModel.mbProductSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_PRODUCT );
396     maModel.mbCountSubtotal   = getFlag( nFlags1, BIFF12_PTFIELD_COUNT );
397     maModel.mbStdDevSubtotal  = getFlag( nFlags1, BIFF12_PTFIELD_STDDEV );
398     maModel.mbStdDevPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEVP );
399     maModel.mbVarSubtotal     = getFlag( nFlags1, BIFF12_PTFIELD_VAR );
400     maModel.mbVarPSubtotal    = getFlag( nFlags1, BIFF12_PTFIELD_VARP );
401 
402     maModel.mbShowAll         = getFlag( nFlags2, BIFF12_PTFIELD_SHOWALL );
403     maModel.mbOutline         = getFlag( nFlags2, BIFF12_PTFIELD_OUTLINE );
404     maModel.mbSubtotalTop     = getFlag( nFlags2, BIFF12_PTFIELD_SUBTOTALTOP );
405     maModel.mbInsertBlankRow  = getFlag( nFlags2, BIFF12_PTFIELD_INSERTBLANKROW );
406     maModel.mbInsertPageBreak = getFlag( nFlags2, BIFF12_PTFIELD_INSERTPAGEBREAK );
407     maModel.mbAutoShow        = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOW );
408     maModel.mbTopAutoShow     = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOWTOP );
409     maModel.mbMultiPageItems  = getFlag( nFlags2, BIFF12_PTFIELD_MULTIPAGEITEMS );
410 
411     bool bAutoSort = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSORT );
412     bool bAscending = getFlag( nFlags2, BIFF12_PTFIELD_SORTASCENDING );
413     maModel.mnSortType = bAutoSort ? (bAscending ? XML_ascending : XML_descending) : XML_manual;
414 }
415 
importPTFItem(SequenceInputStream & rStrm)416 void PivotTableField::importPTFItem( SequenceInputStream& rStrm )
417 {
418     PTFieldItemModel aModel;
419     sal_uInt8 nType;
420     sal_uInt16 nFlags;
421     rStrm >> nType >> nFlags >> aModel.mnCacheItem;
422 
423     aModel.setBiffType( nType );
424     aModel.mbShowDetails = !getFlag( nFlags, BIFF12_PTFITEM_HIDEDETAILS );
425     aModel.mbHidden      = getFlag( nFlags, BIFF12_PTFITEM_HIDDEN );
426 
427     maItems.push_back( aModel );
428 }
429 
importPTReference(SequenceInputStream & rStrm)430 void PivotTableField::importPTReference( SequenceInputStream& rStrm )
431 {
432     rStrm >> maModel.mnSortRefField;
433 }
434 
importPTReferenceItem(SequenceInputStream & rStrm)435 void PivotTableField::importPTReferenceItem( SequenceInputStream& rStrm )
436 {
437     rStrm >> maModel.mnSortRefItem;
438 }
439 
importPTField(BiffInputStream & rStrm)440 void PivotTableField::importPTField( BiffInputStream& rStrm )
441 {
442     sal_uInt16 nAxis, nSubtCount, nSubtotals;
443     rStrm >> nAxis >> nSubtCount >> nSubtotals;
444     rStrm.skip( 2 );    // item count
445 
446     maModel.setBiffAxis( extractValue< sal_uInt8 >( nAxis, 0, 3 ) );
447     maModel.mbDataField       = getFlag( nAxis, BIFF_PTFIELD_DATAFIELD );
448 
449     maModel.mbDefaultSubtotal = getFlag( nSubtotals, BIFF_PTFIELD_DEFAULT );
450     maModel.mbSumSubtotal     = getFlag( nSubtotals, BIFF_PTFIELD_SUM );
451     maModel.mbCountASubtotal  = getFlag( nSubtotals, BIFF_PTFIELD_COUNTA );
452     maModel.mbAverageSubtotal = getFlag( nSubtotals, BIFF_PTFIELD_AVERAGE );
453     maModel.mbMaxSubtotal     = getFlag( nSubtotals, BIFF_PTFIELD_MAX );
454     maModel.mbMinSubtotal     = getFlag( nSubtotals, BIFF_PTFIELD_MIN );
455     maModel.mbProductSubtotal = getFlag( nSubtotals, BIFF_PTFIELD_PRODUCT );
456     maModel.mbCountSubtotal   = getFlag( nSubtotals, BIFF_PTFIELD_COUNT );
457     maModel.mbStdDevSubtotal  = getFlag( nSubtotals, BIFF_PTFIELD_STDDEV );
458     maModel.mbStdDevPSubtotal = getFlag( nSubtotals, BIFF_PTFIELD_STDDEVP );
459     maModel.mbVarSubtotal     = getFlag( nSubtotals, BIFF_PTFIELD_VAR );
460     maModel.mbVarPSubtotal    = getFlag( nSubtotals, BIFF_PTFIELD_VARP );
461 
462     // set different defaults for BIFF
463     maModel.mbShowAll = maModel.mbOutline = maModel.mbSubtotalTop = false;
464 
465     // read following items
466     while( (rStrm.getNextRecId() == BIFF_ID_PTFITEM) && rStrm.startNextRecord() )
467         importPTFItem( rStrm );
468 
469     // read following PTFIELD2 record with additional field settings
470     if( (getBiff() == BIFF8) && (rStrm.getNextRecId() == BIFF_ID_PTFIELD2) && rStrm.startNextRecord() )
471         importPTField2( rStrm );
472 }
473 
importPTField2(BiffInputStream & rStrm)474 void PivotTableField::importPTField2( BiffInputStream& rStrm )
475 {
476     sal_uInt32 nFlags;
477     rStrm >> nFlags;
478     maModel.mnSortRefItem    = rStrm.readInt16();
479     maModel.mnAutoShowRankBy = rStrm.readInt16();
480     maModel.mnNumFmtId       = rStrm.readuInt16();
481 
482     maModel.mnAutoShowItems   = extractValue< sal_Int32 >( nFlags, 24, 8 );
483     maModel.mbShowAll         = getFlag( nFlags, BIFF_PTFIELD2_SHOWALL );
484     maModel.mbOutline         = getFlag( nFlags, BIFF_PTFIELD2_OUTLINE );
485     maModel.mbSubtotalTop     = getFlag( nFlags, BIFF_PTFIELD2_SUBTOTALTOP );
486     maModel.mbInsertBlankRow  = getFlag( nFlags, BIFF_PTFIELD2_INSERTBLANKROW );
487     maModel.mbAutoShow        = getFlag( nFlags, BIFF_PTFIELD2_AUTOSHOW );
488     maModel.mbTopAutoShow     = getFlag( nFlags, BIFF_PTFIELD2_AUTOSHOWTOP );
489 
490     bool bAutoSort = getFlag( nFlags, BIFF_PTFIELD2_AUTOSORT );
491     bool bAscending = getFlag( nFlags, BIFF_PTFIELD2_SORTASCENDING );
492     maModel.mnSortType = bAutoSort ? (bAscending ? XML_ascending : XML_descending) : XML_manual;
493     // mnSortRefField == OOX_PT_DATALAYOUTFIELD will indicate sorting by data field
494     if( maModel.mnSortRefItem >= 0 )
495         maModel.mnSortRefField = OOX_PT_DATALAYOUTFIELD;
496 }
497 
importPTFItem(BiffInputStream & rStrm)498 void PivotTableField::importPTFItem( BiffInputStream& rStrm )
499 {
500     PTFieldItemModel aModel;
501     sal_uInt16 nType, nFlags;
502     sal_Int16 nCacheItem;
503     rStrm >> nType >> nFlags >> nCacheItem;
504 
505     aModel.setBiffType( nType );
506     aModel.mnCacheItem = nCacheItem;
507     aModel.mbShowDetails = !getFlag( nFlags, BIFF_PTFITEM_HIDEDETAILS );
508     aModel.mbHidden      = getFlag( nFlags, BIFF_PTFITEM_HIDDEN );
509 
510     maItems.push_back( aModel );
511 }
512 
finalizeImport(const Reference<XDataPilotDescriptor> & rxDPDesc)513 void PivotTableField::finalizeImport( const Reference< XDataPilotDescriptor >& rxDPDesc )
514 {
515     /*  Process all fields based on source data, other fields (e.g. group
516         fields) are processed from here. PivotCacahe::getDatabaseIndex()
517         returns -1 for all fields not based on source data. */
518     Reference< XDataPilotField > xDPField;
519     sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
520     if( (nDatabaseIdx >= 0) && rxDPDesc.is() ) try
521     {
522         // try to get the source field and its name from passed DataPilot descriptor
523         Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
524         xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
525         Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
526         maDPFieldName = xDPFieldName->getName();
527         OSL_ENSURE( maDPFieldName.getLength() > 0, "PivotTableField::finalizeImport - no field name in source data found" );
528 
529         // try to convert grouping settings
530         if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
531         {
532             // numeric grouping is done inplace, no nested group fields will appear
533             if( pCacheField->hasNumericGrouping() )
534             {
535                 pCacheField->convertNumericGrouping( xDPField );
536             }
537             else if( pCacheField->hasDateGrouping() )
538             {
539                 // first date group settings are inplace
540                 pCacheField->createDateGroupField( xDPField );
541                 // create all nested group fields (if any)
542                 mrPivotTable.finalizeDateGroupingImport( xDPField, mnFieldIndex );
543             }
544             else if( pCacheField->hasParentGrouping() )
545             {
546                 // create a list of all item names, needed to map between original and group items
547                 ::std::vector< OUString > aItems;
548                 pCacheField->getCacheItemNames( aItems );
549                 PivotCacheGroupItemVector aItemNames;
550                 for( ::std::vector< OUString >::iterator aIt = aItems.begin(), aEnd = aItems.end(); aIt != aEnd; ++aIt )
551                     aItemNames.push_back( PivotCacheGroupItem( *aIt ) );
552                 // create all nested group fields (if any)
553                 mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, aItemNames );
554             }
555         }
556     }
557     catch( Exception& )
558     {
559     }
560 }
561 
finalizeDateGroupingImport(const Reference<XDataPilotField> & rxBaseDPField,sal_Int32 nBaseFieldIdx)562 void PivotTableField::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
563 {
564     if( maDPFieldName.getLength() == 0 )    // prevent endless loops if file format is broken
565     {
566         if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
567         {
568             if( !pCacheField->isDatabaseField() && pCacheField->hasDateGrouping() && (pCacheField->getGroupBaseField() == nBaseFieldIdx) )
569             {
570                 maDPFieldName = pCacheField->createDateGroupField( rxBaseDPField );
571                 OSL_ENSURE( maDPFieldName.getLength() > 0, "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
572             }
573         }
574     }
575 }
576 
finalizeParentGroupingImport(const Reference<XDataPilotField> & rxBaseDPField,PivotCacheGroupItemVector & orItemNames)577 void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, PivotCacheGroupItemVector& orItemNames )
578 {
579     if( maDPFieldName.getLength() == 0 )    // prevent endless loops if file format is broken
580     {
581         if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
582         {
583             maDPFieldName = pCacheField->createParentGroupField( rxBaseDPField, orItemNames );
584             // on success, try to create nested group fields
585             Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
586             if( xDPField.is() )
587                 mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, orItemNames );
588         }
589     }
590 }
591 
convertRowField()592 void PivotTableField::convertRowField()
593 {
594     convertRowColPageField( XML_axisRow );
595 }
596 
convertColField()597 void PivotTableField::convertColField()
598 {
599     convertRowColPageField( XML_axisCol );
600 }
601 
convertHiddenField()602 void PivotTableField::convertHiddenField()
603 {
604     convertRowColPageField( XML_TOKEN_INVALID );
605 }
606 
convertPageField(const PTPageFieldModel & rPageField)607 void PivotTableField::convertPageField( const PTPageFieldModel& rPageField )
608 {
609     OSL_ENSURE( rPageField.mnField == mnFieldIndex, "PivotTableField::convertPageField - wrong field index" );
610     // convert all settings common for row/column/page fields
611     Reference< XDataPilotField > xDPField = convertRowColPageField( XML_axisPage );
612 
613     if( xDPField.is() )
614     {
615         PropertySet aPropSet( xDPField );
616         using namespace ::com::sun::star::sheet;
617 
618         // find cache item used as 'selected page'
619         sal_Int32 nCacheItem = -1;
620         if( maModel.mbMultiPageItems )
621         {
622             // multiple items may be selected
623             OSL_ENSURE( rPageField.mnItem == BIFF12_PTPAGEFIELD_MULTIITEMS, "PivotTableField::convertPageField - unexpected cache item index" );
624             // try to find a single visible item
625             bool bHasMultiItems = false;
626             for( ItemModelVector::iterator aIt = maItems.begin(), aEnd = maItems.end(); (aIt != aEnd) && !bHasMultiItems; ++aIt )
627             {
628                 if( (aIt->mnType == XML_data) && !aIt->mbHidden )
629                 {
630                     bHasMultiItems = nCacheItem >= 0;
631                     nCacheItem = bHasMultiItems ? -1 : aIt->mnCacheItem;
632                 }
633             }
634         }
635         else
636         {
637             // single item may be selected
638             if( (0 <= rPageField.mnItem) && (rPageField.mnItem < static_cast< sal_Int32 >( maItems.size() )) )
639                 nCacheItem = maItems[ rPageField.mnItem ].mnCacheItem;
640         }
641 
642         if( nCacheItem >= 0 )
643         {
644             if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
645             {
646                 if( const PivotCacheItem* pSharedItem = pCacheField->getCacheItem( nCacheItem ) )
647                 {
648                     OUString aSelectedPage = pSharedItem->getName();
649                     aPropSet.setProperty( PROP_SelectedPage, aSelectedPage );
650                 }
651             }
652         }
653     }
654 }
655 
convertDataField(const PTDataFieldModel & rDataField)656 void PivotTableField::convertDataField( const PTDataFieldModel& rDataField )
657 {
658     OSL_ENSURE( rDataField.mnField == mnFieldIndex, "PivotTableField::convertDataField - wrong field index" );
659     OSL_ENSURE( maModel.mbDataField, "PivotTableField::convertDataField - not a data field" );
660     Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
661     if( xDPField.is() )
662     {
663         PropertySet aPropSet( xDPField );
664         using namespace ::com::sun::star::sheet;
665 
666         // field orientation
667         aPropSet.setProperty( PROP_Orientation, DataPilotFieldOrientation_DATA );
668 
669         /*  Field aggregation function. Documentation is a little bit confused
670             about which names to use for the count functions. The name 'count'
671             means 'count all', and 'countNum' means 'count numbers'. On the
672             other hand, for subtotals, 'countA' means 'count all', and 'count'
673             means 'count numbers' (see above). */
674         GeneralFunction eAggFunc = GeneralFunction_SUM;
675         switch( rDataField.mnSubtotal )
676         {
677             case XML_sum:       eAggFunc = GeneralFunction_SUM;         break;
678             case XML_count:     eAggFunc = GeneralFunction_COUNT;       break;
679             case XML_average:   eAggFunc = GeneralFunction_AVERAGE;     break;
680             case XML_max:       eAggFunc = GeneralFunction_MAX;         break;
681             case XML_min:       eAggFunc = GeneralFunction_MIN;         break;
682             case XML_product:   eAggFunc = GeneralFunction_PRODUCT;     break;
683             case XML_countNums: eAggFunc = GeneralFunction_COUNTNUMS;   break;
684             case XML_stdDev:    eAggFunc = GeneralFunction_STDEV;       break;
685             case XML_stdDevp:   eAggFunc = GeneralFunction_STDEVP;      break;
686             case XML_var:       eAggFunc = GeneralFunction_VAR;         break;
687             case XML_varp:      eAggFunc = GeneralFunction_VARP;        break;
688             default:            OSL_ENSURE( false, "PivotTableField::convertDataField - unknown aggregation function" );
689         }
690         aPropSet.setProperty( PROP_Function, eAggFunc );
691 
692         // field reference ('show data as')
693         DataPilotFieldReference aReference;
694         aReference.ReferenceType = DataPilotFieldReferenceType::NONE;
695         switch( rDataField.mnShowDataAs )
696         {
697             case XML_difference:        aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_DIFFERENCE;            break;
698             case XML_percent:           aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE;            break;
699             case XML_percentDiff:       aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE; break;
700             case XML_runTotal:          aReference.ReferenceType = DataPilotFieldReferenceType::RUNNING_TOTAL;              break;
701             case XML_percentOfRow:      aReference.ReferenceType = DataPilotFieldReferenceType::ROW_PERCENTAGE;             break;
702             case XML_percentOfCol:      aReference.ReferenceType = DataPilotFieldReferenceType::COLUMN_PERCENTAGE;          break;
703             case XML_percentOfTotal:    aReference.ReferenceType = DataPilotFieldReferenceType::TOTAL_PERCENTAGE;           break;
704             case XML_index:             aReference.ReferenceType = DataPilotFieldReferenceType::INDEX;                      break;
705         }
706         if( aReference.ReferenceType != DataPilotFieldReferenceType::NONE )
707         {
708             if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( rDataField.mnBaseField ) )
709             {
710                 aReference.ReferenceField = pCacheField->getName();
711                 switch( rDataField.mnBaseItem )
712                 {
713                     case OOX_PT_PREVIOUS_ITEM:
714                         aReference.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
715                     break;
716                     case OOX_PT_NEXT_ITEM:
717                         aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
718                     break;
719                     default:
720                         aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
721                         if( const PivotCacheItem* pCacheItem = pCacheField->getCacheItem( rDataField.mnBaseItem ) )
722                             aReference.ReferenceItemName = pCacheItem->getName();
723                 }
724                 aPropSet.setProperty( PROP_Reference, aReference );
725             }
726         }
727     }
728 }
729 
730 // private --------------------------------------------------------------------
731 
convertRowColPageField(sal_Int32 nAxis)732 Reference< XDataPilotField > PivotTableField::convertRowColPageField( sal_Int32 nAxis )
733 {
734     bool bDataLayout = mnFieldIndex == OOX_PT_DATALAYOUTFIELD;
735     Reference< XDataPilotField > xDPField = bDataLayout ? mrPivotTable.getDataLayoutField() : mrPivotTable.getDataPilotField( maDPFieldName );
736     OSL_ENSURE( bDataLayout || (nAxis == maModel.mnAxis), "PivotTableField::convertRowColPageField - field axis mismatch" );
737 
738     if( xDPField.is() )
739     {
740         PropertySet aPropSet( xDPField );
741         using namespace ::com::sun::star::sheet;
742 
743         // field orientation
744         DataPilotFieldOrientation eFieldOrient = DataPilotFieldOrientation_HIDDEN;
745         switch( nAxis )
746         {
747             case XML_axisRow:   eFieldOrient = DataPilotFieldOrientation_ROW;       break;
748             case XML_axisCol:   eFieldOrient = DataPilotFieldOrientation_COLUMN;    break;
749             case XML_axisPage:  eFieldOrient = DataPilotFieldOrientation_PAGE;      break;
750         }
751         if( eFieldOrient != DataPilotFieldOrientation_HIDDEN )
752             aPropSet.setProperty( PROP_Orientation, eFieldOrient );
753 
754         // all other settings not for the data layout field
755         if( !bDataLayout )
756         {
757             /*  Field subtotal functions. Ignore the 'defaultSubtotal' flag, if
758                 explicit functions are set. This is different behaviour between
759                 XML (where 'defaultSubtotal' is set regardless of other
760                 functions) and binary formats (where 'defaultSubtotal' is not
761                 set if other functions are set). */
762             ::std::vector< GeneralFunction > aSubtotals;
763             /*  Order of subtotals is fixed in Excel. Documentation is a little
764                 bit confused about which names to use for the count functions.
765                 For subtotals, 'countA' means 'count all', and 'count' means
766                 'count numbers'. On the other hand, for the data field
767                 aggregation function, 'count' means 'count all', and 'countNum'
768                 means 'count numbers' (see below). */
769             if( maModel.mbSumSubtotal )     aSubtotals.push_back( GeneralFunction_SUM );
770             if( maModel.mbCountASubtotal )  aSubtotals.push_back( GeneralFunction_COUNT );
771             if( maModel.mbAverageSubtotal ) aSubtotals.push_back( GeneralFunction_AVERAGE );
772             if( maModel.mbMaxSubtotal )     aSubtotals.push_back( GeneralFunction_MAX );
773             if( maModel.mbMinSubtotal )     aSubtotals.push_back( GeneralFunction_MIN );
774             if( maModel.mbProductSubtotal ) aSubtotals.push_back( GeneralFunction_PRODUCT );
775             if( maModel.mbCountSubtotal )   aSubtotals.push_back( GeneralFunction_COUNTNUMS );
776             if( maModel.mbStdDevSubtotal )  aSubtotals.push_back( GeneralFunction_STDEV );
777             if( maModel.mbStdDevPSubtotal ) aSubtotals.push_back( GeneralFunction_STDEVP );
778             if( maModel.mbVarSubtotal )     aSubtotals.push_back( GeneralFunction_VAR );
779             if( maModel.mbVarPSubtotal )    aSubtotals.push_back( GeneralFunction_VARP );
780             // if no function is set manually, check the 'defaultSubtotal' flag
781             if( aSubtotals.empty() && maModel.mbDefaultSubtotal )
782                 aSubtotals.push_back( GeneralFunction_AUTO );
783             aPropSet.setProperty( PROP_Subtotals, ContainerHelper::vectorToSequence( aSubtotals ) );
784 
785             // layout settings
786             DataPilotFieldLayoutInfo aLayoutInfo;
787             aLayoutInfo.LayoutMode = maModel.mbOutline ?
788                 (maModel.mbSubtotalTop ? DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP : DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM) :
789                 DataPilotFieldLayoutMode::TABULAR_LAYOUT;
790             aLayoutInfo.AddEmptyLines = maModel.mbInsertBlankRow;
791             aPropSet.setProperty( PROP_LayoutInfo, aLayoutInfo );
792             aPropSet.setProperty( PROP_ShowEmpty, maModel.mbShowAll );
793 
794             // auto show (OOXML/BIFF12 only)
795             if( maModel.mbAutoShow )
796             {
797                 DataPilotFieldAutoShowInfo aAutoShowInfo;
798                 aAutoShowInfo.IsEnabled = sal_True;
799                 aAutoShowInfo.ShowItemsMode = maModel.mbTopAutoShow ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
800                 aAutoShowInfo.ItemCount = maModel.mnAutoShowItems;
801                 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheFieldOfDataField( maModel.mnAutoShowRankBy ) )
802                     aAutoShowInfo.DataField = pCacheField->getName();
803                 aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
804             }
805 
806             // auto sort
807             DataPilotFieldSortInfo aSortInfo;
808             aSortInfo.IsAscending = maModel.mnSortType == XML_ascending;
809             if( (maModel.mnSortType != XML_ascending) && (maModel.mnSortType != XML_descending) )
810             {
811                 aSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
812             }
813             else
814             {
815                 const PivotCacheField* pCacheField = (maModel.mnSortRefField == OOX_PT_DATALAYOUTFIELD) ?
816                     mrPivotTable.getCacheFieldOfDataField( maModel.mnSortRefItem ) : 0;
817                 if( pCacheField )
818                 {
819                     aSortInfo.Mode = DataPilotFieldSortMode::DATA;
820                     aSortInfo.Field = pCacheField->getName();
821                 }
822                 else
823                 {
824                     aSortInfo.Mode = DataPilotFieldSortMode::NAME;
825                 }
826             }
827             aPropSet.setProperty( PROP_SortInfo, aSortInfo );
828 
829             // item settings
830             if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) ) try
831             {
832                 Reference< XNameAccess > xDPItemsNA( xDPField->getItems(), UNO_QUERY_THROW );
833                 for( ItemModelVector::iterator aIt = maItems.begin(), aEnd = maItems.end(); aIt != aEnd; ++aIt )
834                 {
835                     if( aIt->mnType == XML_data )
836                     {
837                         if( const PivotCacheItem* pSharedItem = pCacheField->getCacheItem( aIt->mnCacheItem ) ) try
838                         {
839                             PropertySet aItemProp( xDPItemsNA->getByName( pSharedItem->getName() ) );
840                             aItemProp.setProperty( PROP_ShowDetail, aIt->mbShowDetails );
841                             aItemProp.setProperty( PROP_IsHidden, aIt->mbHidden );
842                         }
843                         catch( Exception& )
844                         {
845                             // catch every failed container access to be able to process following items
846                         }
847                     }
848                 }
849             }
850             catch( Exception& )
851             {
852             }
853         }
854     }
855     return xDPField;
856 }
857 
858 // ============================================================================
859 
PTFilterModel()860 PTFilterModel::PTFilterModel() :
861     mfValue( 0.0 ),
862     mnField( -1 ),
863     mnMemPropField( -1 ),
864     mnType( XML_TOKEN_INVALID ),
865     mnEvalOrder( 0 ),
866     mnId( -1 ),
867     mnMeasureField( -1 ),
868     mnMeasureHier( -1 ),
869     mbTopFilter( true )
870 {
871 }
872 
873 // ----------------------------------------------------------------------------
874 
PivotTableFilter(const PivotTable & rPivotTable)875 PivotTableFilter::PivotTableFilter( const PivotTable& rPivotTable ) :
876     WorkbookHelper( rPivotTable ),
877     mrPivotTable( rPivotTable )
878 {
879 }
880 
importFilter(const AttributeList & rAttribs)881 void PivotTableFilter::importFilter( const AttributeList& rAttribs )
882 {
883     maModel.maName         = rAttribs.getXString( XML_name, OUString() );
884     maModel.maDescription  = rAttribs.getXString( XML_description, OUString() );
885     maModel.maStrValue1    = rAttribs.getXString( XML_stringValue1, OUString() );
886     maModel.maStrValue2    = rAttribs.getXString( XML_stringValue2, OUString() );
887     maModel.mnField        = rAttribs.getInteger( XML_fld, -1 );
888     maModel.mnMemPropField = rAttribs.getInteger( XML_mpFld, -1 );
889     maModel.mnType         = rAttribs.getToken( XML_type, XML_TOKEN_INVALID );
890     maModel.mnEvalOrder    = rAttribs.getInteger( XML_evalOrder, 0 );
891     maModel.mnId           = rAttribs.getInteger( XML_id, -1 );
892     maModel.mnMeasureField = rAttribs.getInteger( XML_iMeasureFld, -1 );
893     maModel.mnMeasureHier  = rAttribs.getInteger( XML_iMeasureHier, -1 );
894 }
895 
importTop10(const AttributeList & rAttribs)896 void PivotTableFilter::importTop10( const AttributeList& rAttribs )
897 {
898     OSL_ENSURE( rAttribs.getBool( XML_percent, false ) == (maModel.mnType == XML_percent),
899         "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
900     maModel.mfValue     = rAttribs.getDouble( XML_val, 0.0 );
901     maModel.mbTopFilter = rAttribs.getBool( XML_top, true );
902 }
903 
importPTFilter(SequenceInputStream & rStrm)904 void PivotTableFilter::importPTFilter( SequenceInputStream& rStrm )
905 {
906     sal_Int32 nType;
907     sal_uInt16 nFlags;
908     rStrm >> maModel.mnField >> maModel.mnMemPropField >> nType;
909     rStrm.skip( 4 );    // unused
910     rStrm >> maModel.mnId >> maModel.mnMeasureField >> maModel.mnMeasureHier >> nFlags;
911     if( getFlag( nFlags, BIFF12_PTFILTER_HASNAME ) )
912         rStrm >> maModel.maName;
913     if( getFlag( nFlags, BIFF12_PTFILTER_HASDESCRIPTION ) )
914         rStrm >> maModel.maDescription;
915     if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE1 ) )
916         rStrm >> maModel.maStrValue1;
917     if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE2 ) )
918         rStrm >> maModel.maStrValue2;
919 
920     static sal_Int32 spnTypes[] =
921     {
922         XML_unknown,
923         // data field top10 filter (1-3)
924         XML_count, XML_percent, XML_sum,
925         // caption filter (4-17)
926         XML_captionEqual, XML_captionNotEqual,
927         XML_captionBeginsWith, XML_captionNotBeginsWith, XML_captionEndsWith, XML_captionNotEndsWith,
928         XML_captionContains, XML_captionNotContains, XML_captionGreaterThan, XML_captionGreaterThanOrEqual,
929         XML_captionLessThan, XML_captionLessThanOrEqual, XML_captionBetween, XML_captionNotBetween,
930         // value filter (18-25)
931         XML_valueEqual, XML_valueNotEqual, XML_valueGreaterThan, XML_valueGreaterThanOrEqual,
932         XML_valueLessThan, XML_valueLessThanOrEqual, XML_valueBetween, XML_valueNotBetween,
933         // date filter (26-65)
934         XML_dateEqual, XML_dateOlderThan, XML_dateNewerThan, XML_dateBetween,
935         XML_tomorrow, XML_today, XML_yesterday, XML_nextWeek, XML_thisWeek, XML_lastWeek,
936         XML_nextMonth, XML_thisMonth, XML_lastMonth, XML_nextQuarter, XML_thisQuarter, XML_lastQuarter,
937         XML_nextYear, XML_thisYear, XML_lastYear, XML_yearToDate, XML_Q1, XML_Q2, XML_Q3, XML_Q4,
938         XML_M1, XML_M2, XML_M3, XML_M4, XML_M5, XML_M6, XML_M7, XML_M8, XML_M9, XML_M10, XML_M11, XML_M12,
939         XML_dateNotEqual, XML_dateOlderThanOrEqual, XML_dateNewerThanOrEqual, XML_dateNotBetween
940     };
941     maModel.mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
942 }
943 
importTop10Filter(SequenceInputStream & rStrm)944 void PivotTableFilter::importTop10Filter( SequenceInputStream& rStrm )
945 {
946     sal_uInt8 nFlags;
947     rStrm >> nFlags >> maModel.mfValue;
948 
949     OSL_ENSURE( getFlag( nFlags, BIFF12_TOP10FILTER_PERCENT ) == (maModel.mnType == XML_percent),
950         "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
951     maModel.mbTopFilter = getFlag( nFlags, BIFF12_TOP10FILTER_TOP );
952 }
953 
finalizeImport()954 void PivotTableFilter::finalizeImport()
955 {
956     // only simple top10 filter supported
957     if( maModel.mnType == XML_count )
958     {
959         PropertySet aPropSet( mrPivotTable.getDataPilotField( maModel.mnField ) );
960         if( aPropSet.is() )
961         {
962             using namespace ::com::sun::star::sheet;
963             DataPilotFieldAutoShowInfo aAutoShowInfo;
964             aAutoShowInfo.IsEnabled = sal_True;
965             aAutoShowInfo.ShowItemsMode = maModel.mbTopFilter ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
966             aAutoShowInfo.ItemCount = getLimitedValue< sal_Int32, double >( maModel.mfValue, 0, SAL_MAX_INT32 );
967             if( const PivotCacheField* pCacheField = mrPivotTable.getCacheFieldOfDataField( maModel.mnMeasureField ) )
968                 aAutoShowInfo.DataField = pCacheField->getName();
969             aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
970         }
971     }
972 }
973 
974 // ============================================================================
975 
PTDefinitionModel()976 PTDefinitionModel::PTDefinitionModel() :
977     mnCacheId( -1 ),
978     mnDataPosition( 0 ),
979     mnPageWrap( 0 ),
980     mnIndent( 1 ),
981     mnChartFormat( 0 ),
982     mnRowFields( 0 ),
983     mnColFields( 0 ),
984     mbDataOnRows( false ),
985     mbShowError( false ),
986     mbShowMissing( true ),
987     mbShowItems( true ),
988     mbDisableFieldList( false ),
989     mbShowCalcMembers( true ),
990     mbVisualTotals( true ),
991     mbShowDrill( true ),
992     mbPrintDrill( false ),
993     mbEnableDrill( true ),
994     mbPreserveFormatting( true ),
995     mbUseAutoFormat( false ),
996     mbPageOverThenDown( false ),
997     mbSubtotalHiddenItems( false ),
998     mbRowGrandTotals( true ),
999     mbColGrandTotals( true ),
1000     mbFieldPrintTitles( false ),
1001     mbItemPrintTitles( false ),
1002     mbMergeItem( false ),
1003     mbShowEmptyRow( false ),
1004     mbShowEmptyCol( false ),
1005     mbShowHeaders( true ),
1006     mbFieldListSortAsc( false ),
1007     mbCustomListSort( true )
1008 {
1009 }
1010 
1011 // ----------------------------------------------------------------------------
1012 
PTLocationModel()1013 PTLocationModel::PTLocationModel() :
1014     mnFirstHeaderRow( 0 ),
1015     mnFirstDataRow( 0 ),
1016     mnFirstDataCol( 0 ),
1017     mnRowPageCount( 0 ),
1018     mnColPageCount( 0 )
1019 {
1020 }
1021 
1022 // ----------------------------------------------------------------------------
1023 
PivotTable(const WorkbookHelper & rHelper)1024 PivotTable::PivotTable( const WorkbookHelper& rHelper ) :
1025     WorkbookHelper( rHelper ),
1026     maDataField( *this, OOX_PT_DATALAYOUTFIELD ),
1027     mpPivotCache( 0 )
1028 {
1029 }
1030 
importPivotTableDefinition(const AttributeList & rAttribs)1031 void PivotTable::importPivotTableDefinition( const AttributeList& rAttribs )
1032 {
1033     maDefModel.maName                = rAttribs.getXString( XML_name, OUString() );
1034     maDefModel.maDataCaption         = rAttribs.getXString( XML_dataCaption , OUString() );
1035     maDefModel.maGrandTotalCaption   = rAttribs.getXString( XML_grandTotalCaption, OUString() );
1036     maDefModel.maRowHeaderCaption    = rAttribs.getXString( XML_rowHeaderCaption, OUString() );
1037     maDefModel.maColHeaderCaption    = rAttribs.getXString( XML_colHeaderCaption, OUString() );
1038     maDefModel.maErrorCaption        = rAttribs.getXString( XML_errorCaption, OUString() );
1039     maDefModel.maMissingCaption      = rAttribs.getXString( XML_missingCaption, OUString() );
1040     maDefModel.maPageStyle           = rAttribs.getXString( XML_pageStyle, OUString() );
1041     maDefModel.maPivotTableStyle     = rAttribs.getXString( XML_pivotTableStyle, OUString() );
1042     maDefModel.maVacatedStyle        = rAttribs.getXString( XML_vacatedStyle, OUString() );
1043     maDefModel.maTag                 = rAttribs.getXString( XML_tag, OUString() );
1044     maDefModel.mnCacheId             = rAttribs.getInteger( XML_cacheId, -1 );
1045     maDefModel.mnDataPosition        = rAttribs.getInteger( XML_dataPosition, 0 );
1046     maDefModel.mnPageWrap            = rAttribs.getInteger( XML_pageWrap, 0 );
1047     maDefModel.mnIndent              = rAttribs.getInteger( XML_indent, 1 );
1048     maDefModel.mnChartFormat         = rAttribs.getInteger( XML_chartFormat, 0 );
1049     maDefModel.mnAutoFormatId        = rAttribs.getInteger( XML_autoFormatId, 0 );
1050     maDefModel.mbDataOnRows          = rAttribs.getBool( XML_dataOnRows, false );
1051     maDefModel.mbShowError           = rAttribs.getBool( XML_showError, false );
1052     maDefModel.mbShowMissing         = rAttribs.getBool( XML_showMissing, true );
1053     maDefModel.mbShowItems           = rAttribs.getBool( XML_showItems, true );
1054     maDefModel.mbDisableFieldList    = rAttribs.getBool( XML_disableFieldList, false );
1055     maDefModel.mbShowCalcMembers     = rAttribs.getBool( XML_showCalcMbrs, true );
1056     maDefModel.mbVisualTotals        = rAttribs.getBool( XML_visualTotals, true );
1057     maDefModel.mbShowDrill           = rAttribs.getBool( XML_showDrill, true );
1058     maDefModel.mbPrintDrill          = rAttribs.getBool( XML_printDrill, false );
1059     maDefModel.mbEnableDrill         = rAttribs.getBool( XML_enableDrill, true );
1060     maDefModel.mbPreserveFormatting  = rAttribs.getBool( XML_preserveFormatting, true );
1061     maDefModel.mbUseAutoFormat       = rAttribs.getBool( XML_useAutoFormatting, false );
1062     maDefModel.mbPageOverThenDown    = rAttribs.getBool( XML_pageOverThenDown, false );
1063     maDefModel.mbSubtotalHiddenItems = rAttribs.getBool( XML_subtotalHiddenItems, false );
1064     maDefModel.mbRowGrandTotals      = rAttribs.getBool( XML_rowGrandTotals, true );
1065     maDefModel.mbColGrandTotals      = rAttribs.getBool( XML_colGrandTotals, true );
1066     maDefModel.mbFieldPrintTitles    = rAttribs.getBool( XML_fieldPrintTitles, false );
1067     maDefModel.mbItemPrintTitles     = rAttribs.getBool( XML_itemPrintTitles, false );
1068     maDefModel.mbMergeItem           = rAttribs.getBool( XML_mergeItem, false );
1069     maDefModel.mbShowEmptyRow        = rAttribs.getBool( XML_showEmptyRow, false );
1070     maDefModel.mbShowEmptyCol        = rAttribs.getBool( XML_showEmptyCol, false );
1071     maDefModel.mbShowHeaders         = rAttribs.getBool( XML_showHeaders, true );
1072     maDefModel.mbFieldListSortAsc    = rAttribs.getBool( XML_fieldListSortAscending, false );
1073     maDefModel.mbCustomListSort      = rAttribs.getBool( XML_customListSort, true );
1074     maDefModel.mbApplyNumFmt         = rAttribs.getBool( XML_applyNumberFormats, false );
1075     maDefModel.mbApplyFont           = rAttribs.getBool( XML_applyFontFormats, false );
1076     maDefModel.mbApplyAlignment      = rAttribs.getBool( XML_applyAlignmentFormats, false );
1077     maDefModel.mbApplyBorder         = rAttribs.getBool( XML_applyBorderFormats, false );
1078     maDefModel.mbApplyFill           = rAttribs.getBool( XML_applyPatternFormats, false );
1079     // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
1080     maDefModel.mbApplyProtection     = rAttribs.getBool( XML_applyWidthHeightFormats, false );
1081 }
1082 
importLocation(const AttributeList & rAttribs,sal_Int16 nSheet)1083 void PivotTable::importLocation( const AttributeList& rAttribs, sal_Int16 nSheet )
1084 {
1085     getAddressConverter().convertToCellRangeUnchecked( maLocationModel.maRange, rAttribs.getString( XML_ref, OUString() ), nSheet );
1086     maLocationModel.mnFirstHeaderRow = rAttribs.getInteger( XML_firstHeaderRow, 0 );
1087     maLocationModel.mnFirstDataRow   = rAttribs.getInteger( XML_firstDataRow, 0 );
1088     maLocationModel.mnFirstDataCol   = rAttribs.getInteger( XML_firstDataCol, 0 );
1089     maLocationModel.mnRowPageCount   = rAttribs.getInteger( XML_rowPageCount, 0 );
1090     maLocationModel.mnColPageCount   = rAttribs.getInteger( XML_colPageCount, 0 );
1091 }
1092 
importRowField(const AttributeList & rAttribs)1093 void PivotTable::importRowField( const AttributeList& rAttribs )
1094 {
1095     importField( maRowFields, rAttribs );
1096 }
1097 
importColField(const AttributeList & rAttribs)1098 void PivotTable::importColField( const AttributeList& rAttribs )
1099 {
1100     importField( maColFields, rAttribs );
1101 }
1102 
importPageField(const AttributeList & rAttribs)1103 void PivotTable::importPageField( const AttributeList& rAttribs )
1104 {
1105     PTPageFieldModel aModel;
1106     aModel.maName      = rAttribs.getXString( XML_name, OUString() );
1107     aModel.mnField     = rAttribs.getInteger( XML_fld, -1 );
1108     // specification is wrong, XML_item is not the cache item, but the field item
1109     aModel.mnItem      = rAttribs.getInteger( XML_item, BIFF12_PTPAGEFIELD_MULTIITEMS );
1110     maPageFields.push_back( aModel );
1111 }
1112 
importDataField(const AttributeList & rAttribs)1113 void PivotTable::importDataField( const AttributeList& rAttribs )
1114 {
1115     PTDataFieldModel aModel;
1116     aModel.maName       = rAttribs.getXString( XML_name, OUString() );
1117     aModel.mnField      = rAttribs.getInteger( XML_fld, -1 );
1118     aModel.mnSubtotal   = rAttribs.getToken( XML_subtotal, XML_sum );
1119     aModel.mnShowDataAs = rAttribs.getToken( XML_showDataAs, XML_normal );
1120     aModel.mnBaseField  = rAttribs.getInteger( XML_baseField, -1 );
1121     aModel.mnBaseItem   = rAttribs.getInteger( XML_baseItem, -1 );
1122     aModel.mnNumFmtId   = rAttribs.getInteger( XML_numFmtId, 0 );
1123     maDataFields.push_back( aModel );
1124 }
1125 
importPTDefinition(SequenceInputStream & rStrm)1126 void PivotTable::importPTDefinition( SequenceInputStream& rStrm )
1127 {
1128     sal_uInt32 nFlags1, nFlags2, nFlags3;
1129     sal_uInt8 nDataAxis;
1130     rStrm >> nFlags1 >> nFlags2 >> nFlags3 >> nDataAxis;
1131     maDefModel.mnPageWrap = rStrm.readuInt8();
1132     rStrm.skip( 2 );    // refresh versions
1133     rStrm >> maDefModel.mnDataPosition;
1134     maDefModel.mnAutoFormatId = rStrm.readuInt16();
1135     rStrm.skip( 2 );    // unused
1136     rStrm >> maDefModel.mnChartFormat >> maDefModel.mnCacheId >> maDefModel.maName;
1137     if( getFlag( nFlags2, BIFF12_PTDEF_HASDATACAPTION ) )
1138         rStrm >> maDefModel.maDataCaption;
1139     if( getFlag( nFlags2, BIFF12_PTDEF_HASGRANDTOTALCAPTION ) )
1140         rStrm >> maDefModel.maGrandTotalCaption;
1141     if( !getFlag( nFlags3, BIFF12_PTDEF_NOERRORCAPTION ) )   // missing flag indicates existing string
1142         rStrm >> maDefModel.maErrorCaption;
1143     if( !getFlag( nFlags3, BIFF12_PTDEF_NOMISSINGCAPTION ) ) // missing flag indicates existing string
1144         rStrm >> maDefModel.maMissingCaption;
1145     if( getFlag( nFlags2, BIFF12_PTDEF_HASPAGESTYLE ) )
1146         rStrm >> maDefModel.maPageStyle;
1147     if( getFlag( nFlags2, BIFF12_PTDEF_HASPIVOTTABLESTYLE ) )
1148         rStrm >> maDefModel.maPivotTableStyle;
1149     if( getFlag( nFlags2, BIFF12_PTDEF_HASVACATEDSTYLE ) )
1150         rStrm >> maDefModel.maVacatedStyle;
1151     if( getFlag( nFlags2, BIFF12_PTDEF_HASTAG ) )
1152         rStrm >> maDefModel.maTag;
1153     if( getFlag( nFlags3, BIFF12_PTDEF_HASCOLHEADERCAPTION ) )   // TODO: right order (col/row)? spec is unclear
1154         rStrm >> maDefModel.maColHeaderCaption;
1155     if( getFlag( nFlags3, BIFF12_PTDEF_HASROWHEADERCAPTION ) )
1156         rStrm >> maDefModel.maRowHeaderCaption;
1157 
1158     OSL_ENSURE( (nDataAxis == BIFF12_PTDEF_ROWAXIS) || (nDataAxis == BIFF12_PTDEF_COLAXIS),
1159         "PivotTable::importPTDefinition - unexpected axis position for data field" );
1160 
1161     maDefModel.mnIndent              = extractValue< sal_uInt8 >( nFlags1, 24, 7 );
1162     maDefModel.mbDataOnRows          = nDataAxis == BIFF12_PTDEF_ROWAXIS;
1163     maDefModel.mbShowError           = getFlag( nFlags2, BIFF12_PTDEF_SHOWERROR );
1164     maDefModel.mbShowMissing         = getFlag( nFlags2, BIFF12_PTDEF_SHOWMISSING );
1165     maDefModel.mbShowItems           = getFlag( nFlags1, BIFF12_PTDEF_SHOWITEMS );
1166     maDefModel.mbDisableFieldList    = getFlag( nFlags1, BIFF12_PTDEF_DISABLEFIELDLIST );
1167     maDefModel.mbShowCalcMembers     = !getFlag( nFlags1, BIFF12_PTDEF_HIDECALCMEMBERS );
1168     maDefModel.mbVisualTotals        = !getFlag( nFlags1, BIFF12_PTDEF_WITHHIDDENTOTALS );
1169     maDefModel.mbShowDrill           = !getFlag( nFlags1, BIFF12_PTDEF_HIDEDRILL );
1170     maDefModel.mbPrintDrill          = getFlag( nFlags1, BIFF12_PTDEF_PRINTDRILL );
1171     maDefModel.mbEnableDrill         = getFlag( nFlags2, BIFF12_PTDEF_ENABLEDRILL );
1172     maDefModel.mbPreserveFormatting  = getFlag( nFlags2, BIFF12_PTDEF_PRESERVEFORMATTING );
1173     maDefModel.mbUseAutoFormat       = getFlag( nFlags2, BIFF12_PTDEF_USEAUTOFORMAT );
1174     maDefModel.mbPageOverThenDown    = getFlag( nFlags2, BIFF12_PTDEF_PAGEOVERTHENDOWN );
1175     maDefModel.mbSubtotalHiddenItems = getFlag( nFlags2, BIFF12_PTDEF_SUBTOTALHIDDENITEMS );
1176     maDefModel.mbRowGrandTotals      = getFlag( nFlags2, BIFF12_PTDEF_ROWGRANDTOTALS );
1177     maDefModel.mbColGrandTotals      = getFlag( nFlags2, BIFF12_PTDEF_COLGRANDTOTALS );
1178     maDefModel.mbFieldPrintTitles    = getFlag( nFlags2, BIFF12_PTDEF_FIELDPRINTTITLES );
1179     maDefModel.mbItemPrintTitles     = getFlag( nFlags2, BIFF12_PTDEF_ITEMPRINTTITLES );
1180     maDefModel.mbMergeItem           = getFlag( nFlags2, BIFF12_PTDEF_MERGEITEM );
1181     maDefModel.mbApplyNumFmt         = getFlag( nFlags2, BIFF12_PTDEF_APPLYNUMFMT );
1182     maDefModel.mbApplyFont           = getFlag( nFlags2, BIFF12_PTDEF_APPLYFONT );
1183     maDefModel.mbApplyAlignment      = getFlag( nFlags2, BIFF12_PTDEF_APPLYALIGNMENT );
1184     maDefModel.mbApplyBorder         = getFlag( nFlags2, BIFF12_PTDEF_APPLYBORDER );
1185     maDefModel.mbApplyFill           = getFlag( nFlags2, BIFF12_PTDEF_APPLYFILL );
1186     maDefModel.mbApplyProtection     = getFlag( nFlags2, BIFF12_PTDEF_APPLYPROTECTION );
1187     maDefModel.mbShowEmptyRow        = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYROW );
1188     maDefModel.mbShowEmptyCol        = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYCOL );
1189     maDefModel.mbShowHeaders         = !getFlag( nFlags1, BIFF12_PTDEF_HIDEHEADERS );
1190     maDefModel.mbFieldListSortAsc    = getFlag( nFlags3, BIFF12_PTDEF_FIELDLISTSORTASC );
1191     maDefModel.mbCustomListSort      = !getFlag( nFlags3, BIFF12_PTDEF_NOCUSTOMLISTSORT );
1192 }
1193 
importPTLocation(SequenceInputStream & rStrm,sal_Int16 nSheet)1194 void PivotTable::importPTLocation( SequenceInputStream& rStrm, sal_Int16 nSheet )
1195 {
1196     BinRange aBinRange;
1197     rStrm   >> aBinRange >> maLocationModel.mnFirstHeaderRow
1198             >> maLocationModel.mnFirstDataRow >> maLocationModel.mnFirstDataCol
1199             >> maLocationModel.mnRowPageCount >> maLocationModel.mnColPageCount;
1200     getAddressConverter().convertToCellRangeUnchecked( maLocationModel.maRange, aBinRange, nSheet );
1201 }
1202 
importPTRowFields(SequenceInputStream & rStrm)1203 void PivotTable::importPTRowFields( SequenceInputStream& rStrm )
1204 {
1205     importFields( maRowFields, rStrm );
1206 }
1207 
importPTColFields(SequenceInputStream & rStrm)1208 void PivotTable::importPTColFields( SequenceInputStream& rStrm )
1209 {
1210     importFields( maColFields, rStrm );
1211 }
1212 
importPTPageField(SequenceInputStream & rStrm)1213 void PivotTable::importPTPageField( SequenceInputStream& rStrm )
1214 {
1215     PTPageFieldModel aModel;
1216     sal_uInt8 nFlags;
1217     rStrm >> aModel.mnField >> aModel.mnItem;
1218     rStrm.skip( 4 );    // hierarchy
1219     rStrm >> nFlags;
1220     if( getFlag( nFlags, BIFF12_PTPAGEFIELD_HASNAME ) )
1221         rStrm >> aModel.maName;
1222     maPageFields.push_back( aModel );
1223 }
1224 
importPTDataField(SequenceInputStream & rStrm)1225 void PivotTable::importPTDataField( SequenceInputStream& rStrm )
1226 {
1227     PTDataFieldModel aModel;
1228     sal_Int32 nSubtotal, nShowDataAs;
1229     sal_uInt8 nHasName;
1230     rStrm >> aModel.mnField >> nSubtotal >> nShowDataAs >> aModel.mnBaseField >> aModel.mnBaseItem >> aModel.mnNumFmtId >> nHasName;
1231     if( nHasName == 1 )
1232         rStrm >> aModel.maName;
1233     aModel.setBiffSubtotal( nSubtotal );
1234     aModel.setBiffShowDataAs( nShowDataAs );
1235     maDataFields.push_back( aModel );
1236 }
1237 
importPTDefinition(BiffInputStream & rStrm,sal_Int16 nSheet)1238 void PivotTable::importPTDefinition( BiffInputStream& rStrm, sal_Int16 nSheet )
1239 {
1240     BinRange aBinRange;
1241     sal_uInt16 nFlags, nTabNameLen, nDataNameLen;
1242     rStrm >> aBinRange;
1243     maLocationModel.mnFirstHeaderRow = rStrm.readuInt16();
1244     maLocationModel.mnFirstDataRow   = rStrm.readuInt16();
1245     maLocationModel.mnFirstDataCol   = rStrm.readuInt16();
1246     maDefModel.mnCacheId             = rStrm.readuInt16();
1247     rStrm.skip( 2 );                 // unused
1248     maDefModel.mbDataOnRows          = rStrm.readuInt16() == BIFF_PTDEF_ROWAXIS;
1249     maDefModel.mnDataPosition        = rStrm.readInt16();
1250     rStrm.skip( 2 );                 // number of fields
1251     rStrm >> maDefModel.mnRowFields >> maDefModel.mnColFields;
1252     rStrm.skip( 8 );                 // number of page fields, data fields, data rows, data columns
1253     rStrm >> nFlags;
1254     maDefModel.mnChartFormat         = rStrm.readuInt16();
1255     rStrm >> nTabNameLen >> nDataNameLen;
1256     maDefModel.maName                = lclReadPivotString( *this, rStrm, nTabNameLen );
1257     maDefModel.maDataCaption         = lclReadPivotString( *this, rStrm, nDataNameLen );
1258 
1259     maDefModel.mbRowGrandTotals  = getFlag( nFlags, BIFF_PTDEF_ROWGRANDTOTALS );
1260     maDefModel.mbColGrandTotals  = getFlag( nFlags, BIFF_PTDEF_COLGRANDTOTALS );
1261 
1262     getAddressConverter().convertToCellRangeUnchecked( maLocationModel.maRange, aBinRange, nSheet );
1263 }
1264 
importPTDefinition2(BiffInputStream & rStrm)1265 void PivotTable::importPTDefinition2( BiffInputStream& rStrm )
1266 {
1267     if( getBiff() == BIFF8 )
1268     {
1269         sal_uInt16 nErrCaptLen, nMissCaptLen, nTagLen, nPageStyleLen, nTabStyleLen, nVacStyleLen;
1270         sal_uInt32 nFlags;
1271         rStrm.skip( 2 );    // number of formatting records
1272         rStrm >> nErrCaptLen >> nMissCaptLen >> nTagLen;
1273         rStrm.skip( 6 );    // number of selection records, page rows, page columns
1274         rStrm >> nFlags >> nPageStyleLen >> nTabStyleLen >> nVacStyleLen;
1275         maDefModel.maErrorCaption    = lclReadPivotString( *this, rStrm, nErrCaptLen );
1276         maDefModel.maMissingCaption  = lclReadPivotString( *this, rStrm, nMissCaptLen );
1277         maDefModel.maTag             = lclReadPivotString( *this, rStrm, nTagLen );
1278         maDefModel.maPageStyle       = lclReadPivotString( *this, rStrm, nPageStyleLen );
1279         maDefModel.maPivotTableStyle = lclReadPivotString( *this, rStrm, nTabStyleLen );
1280         maDefModel.maVacatedStyle    = lclReadPivotString( *this, rStrm, nVacStyleLen );
1281 
1282         maDefModel.mbShowError           = getFlag( nFlags, BIFF_PTDEF2_SHOWERROR );
1283         maDefModel.mbShowMissing         = getFlag( nFlags, BIFF_PTDEF2_SHOWMISSING );
1284         maDefModel.mbEnableDrill         = getFlag( nFlags, BIFF_PTDE2F_ENABLEDRILL );
1285         maDefModel.mbPreserveFormatting  = getFlag( nFlags, BIFF_PTDEF2_PRESERVEFORMATTING );
1286         maDefModel.mbPageOverThenDown    = getFlag( nFlags, BIFF_PTDEF2_PAGEOVERTHENDOWN );
1287         maDefModel.mbSubtotalHiddenItems = getFlag( nFlags, BIFF_PTDEF2_SUBTOTALHIDDENITEMS );
1288         maDefModel.mbMergeItem           = getFlag( nFlags, BIFF_PTDEF2_MERGEITEM );
1289     }
1290 }
1291 
importPTRowColFields(BiffInputStream & rStrm)1292 void PivotTable::importPTRowColFields( BiffInputStream& rStrm )
1293 {
1294     // first PTROWCOLFIELDS record contains row fields unless there are no row fields
1295     if( (maDefModel.mnRowFields > 0) && maRowFields.empty() )
1296         importFields( maRowFields, rStrm, maDefModel.mnRowFields );
1297     else if( (maDefModel.mnColFields > 0) && maColFields.empty() )
1298         importFields( maColFields, rStrm, maDefModel.mnColFields );
1299 }
1300 
importPTPageFields(BiffInputStream & rStrm)1301 void PivotTable::importPTPageFields( BiffInputStream& rStrm )
1302 {
1303     while( rStrm.getRemaining() >= 6 )
1304     {
1305         PTPageFieldModel aModel;
1306         sal_Int16 nField, nItem;
1307         rStrm >> nField >> nItem;
1308         rStrm.skip( 2 );    // dropdown object ID
1309         aModel.mnField = nField;
1310         aModel.mnItem = (nItem == BIFF_PTPAGEFIELDS_ALLITEMS) ? BIFF12_PTPAGEFIELD_MULTIITEMS : nItem;
1311         maPageFields.push_back( aModel );
1312     }
1313 }
1314 
importPTDataField(BiffInputStream & rStrm)1315 void PivotTable::importPTDataField( BiffInputStream& rStrm )
1316 {
1317     PTDataFieldModel aModel;
1318     sal_Int16 nField, nBaseField, nBaseItem;
1319     sal_uInt16 nSubtotal, nShowDataAs, nNumFmt, nNameLen;
1320     rStrm >> nField >> nSubtotal >> nShowDataAs >> nBaseField >> nBaseItem >> nNumFmt >> nNameLen;
1321     aModel.maName = lclReadPivotString( *this, rStrm, nNameLen );
1322 
1323     aModel.mnField = nField;
1324     aModel.setBiffSubtotal( nSubtotal );
1325     aModel.setBiffShowDataAs( nShowDataAs );
1326     aModel.mnBaseField = nBaseField;
1327     switch( nBaseItem )
1328     {
1329         case BIFF_PTDATAFIELD_PREVIOUS: aModel.mnBaseItem = OOX_PT_PREVIOUS_ITEM;   break;
1330         case BIFF_PTDATAFIELD_NEXT:     aModel.mnBaseItem = OOX_PT_NEXT_ITEM;       break;
1331         default:                        aModel.mnBaseItem = nBaseItem;
1332     }
1333     aModel.mnNumFmtId = nNumFmt;
1334 
1335     maDataFields.push_back( aModel );
1336 }
1337 
createTableField()1338 PivotTableField& PivotTable::createTableField()
1339 {
1340     sal_Int32 nFieldIndex = static_cast< sal_Int32 >( maFields.size() );
1341     PivotTableFieldVector::value_type xTableField( new PivotTableField( *this, nFieldIndex ) );
1342     maFields.push_back( xTableField );
1343     return *xTableField;
1344 }
1345 
createTableFilter()1346 PivotTableFilter& PivotTable::createTableFilter()
1347 {
1348     PivotTableFilterVector::value_type xTableFilter( new PivotTableFilter( *this ) );
1349     maFilters.push_back( xTableFilter );
1350     return *xTableFilter;
1351 }
1352 
finalizeImport()1353 void PivotTable::finalizeImport()
1354 {
1355     if( getAddressConverter().validateCellRange( maLocationModel.maRange, true, true ) )
1356     {
1357         mpPivotCache = getPivotCaches().importPivotCacheFragment( maDefModel.mnCacheId );
1358         if( mpPivotCache && mpPivotCache->isValidDataSource() && (maDefModel.maName.getLength() > 0) )
1359         {
1360             // clear destination area of the original pivot table
1361             try
1362             {
1363                 Reference< XSheetOperation > xSheetOp( getCellRangeFromDoc( maLocationModel.maRange ), UNO_QUERY_THROW );
1364                 using namespace ::com::sun::star::sheet::CellFlags;
1365                 xSheetOp->clearContents( VALUE | DATETIME | STRING | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED );
1366             }
1367             catch( Exception& )
1368             {
1369             }
1370 
1371             try
1372             {
1373                 // create a new data pilot descriptor based on the source data
1374                 Reference< XDataPilotTablesSupplier > xDPTablesSupp( getSheetFromDoc( maLocationModel.maRange.Sheet ), UNO_QUERY_THROW );
1375                 Reference< XDataPilotTables > xDPTables( xDPTablesSupp->getDataPilotTables(), UNO_SET_THROW );
1376                 mxDPDescriptor.set( xDPTables->createDataPilotDescriptor(), UNO_SET_THROW );
1377                 mxDPDescriptor->setSourceRange( mpPivotCache->getSourceRange() );
1378                 mxDPDescriptor->setTag( maDefModel.maTag );
1379 
1380                 // global data pilot properties
1381                 PropertySet aDescProp( mxDPDescriptor );
1382                 aDescProp.setProperty( PROP_ColumnGrand, maDefModel.mbColGrandTotals );
1383                 aDescProp.setProperty( PROP_RowGrand, maDefModel.mbRowGrandTotals );
1384                 aDescProp.setProperty( PROP_ShowFilterButton, false );
1385                 aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill );
1386 
1387                 // finalize all fields, this finds field names and creates grouping fields
1388                 maFields.forEachMem( &PivotTableField::finalizeImport, ::boost::cref( mxDPDescriptor ) );
1389 
1390                 // all row fields
1391                 for( IndexVector::iterator aIt = maRowFields.begin(), aEnd = maRowFields.end(); aIt != aEnd; ++aIt )
1392                     if( PivotTableField* pField = getTableField( *aIt ) )
1393                         pField->convertRowField();
1394 
1395                 // all column fields
1396                 for( IndexVector::iterator aIt = maColFields.begin(), aEnd = maColFields.end(); aIt != aEnd; ++aIt )
1397                     if( PivotTableField* pField = getTableField( *aIt ) )
1398                         pField->convertColField();
1399 
1400                 // all page fields
1401                 for( PageFieldVector::iterator aIt = maPageFields.begin(), aEnd = maPageFields.end(); aIt != aEnd; ++aIt )
1402                     if( PivotTableField* pField = getTableField( aIt->mnField ) )
1403                         pField->convertPageField( *aIt );
1404 
1405                 // all hidden fields
1406                 ::std::set< sal_Int32 > aVisFields;
1407                 aVisFields.insert( maRowFields.begin(), maRowFields.end() );
1408                 aVisFields.insert( maColFields.begin(), maColFields.end() );
1409                 for( PageFieldVector::iterator aIt = maPageFields.begin(), aEnd = maPageFields.end(); aIt != aEnd; ++aIt )
1410                     aVisFields.insert( aIt->mnField );
1411                 for( PivotTableFieldVector::iterator aBeg = maFields.begin(), aIt = aBeg, aEnd = maFields.end(); aIt != aEnd; ++aIt )
1412                     if( aVisFields.count( static_cast< sal_Int32 >( aIt - aBeg ) ) == 0 )
1413                         (*aIt)->convertHiddenField();
1414 
1415                 // all data fields
1416                 for( DataFieldVector::iterator aIt = maDataFields.begin(), aEnd = maDataFields.end(); aIt != aEnd; ++aIt )
1417                     if( PivotTableField* pField = getTableField( aIt->mnField ) )
1418                         pField->convertDataField( *aIt );
1419 
1420                 // filters
1421                 maFilters.forEachMem( &PivotTableFilter::finalizeImport );
1422 
1423                 // calculate base position of table
1424                 CellAddress aPos( maLocationModel.maRange.Sheet, maLocationModel.maRange.StartColumn, maLocationModel.maRange.StartRow );
1425                 /*  If page fields exist, include them into the destination
1426                     area (they are excluded in Excel). Add an extra blank row. */
1427                 if( !maPageFields.empty() )
1428                     aPos.Row = ::std::max< sal_Int32 >( static_cast< sal_Int32 >( aPos.Row - maPageFields.size() - 1 ), 0 );
1429 
1430                 // insert the DataPilot table into the sheet
1431                 xDPTables->insertNewByName( maDefModel.maName, aPos, mxDPDescriptor );
1432             }
1433             catch( Exception& )
1434             {
1435                 OSL_ENSURE( false, "PivotTable::finalizeImport - exception while creating the DataPilot table" );
1436             }
1437         }
1438     }
1439 }
1440 
finalizeDateGroupingImport(const Reference<XDataPilotField> & rxBaseDPField,sal_Int32 nBaseFieldIdx)1441 void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
1442 {
1443     // process all fields, there is no chaining information in the cache fields
1444     maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, ::boost::cref( rxBaseDPField ), nBaseFieldIdx );
1445 }
1446 
finalizeParentGroupingImport(const Reference<XDataPilotField> & rxBaseDPField,const PivotCacheField & rBaseCacheField,PivotCacheGroupItemVector & orItemNames)1447 void PivotTable::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField,
1448         const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
1449 {
1450     // try to create parent group fields that group the items of the passed base field
1451     if( PivotTableField* pParentTableField = maFields.get( rBaseCacheField.getParentGroupField() ).get() )
1452         pParentTableField->finalizeParentGroupingImport( rxBaseDPField, orItemNames );
1453 }
1454 
getDataPilotField(const OUString & rFieldName) const1455 Reference< XDataPilotField > PivotTable::getDataPilotField( const OUString& rFieldName ) const
1456 {
1457     Reference< XDataPilotField > xDPField;
1458     if( (rFieldName.getLength() > 0) && mxDPDescriptor.is() ) try
1459     {
1460         Reference< XNameAccess > xDPFieldsNA( mxDPDescriptor->getDataPilotFields(), UNO_QUERY_THROW );
1461         xDPField.set( xDPFieldsNA->getByName( rFieldName ), UNO_QUERY );
1462     }
1463     catch( Exception& )
1464     {
1465     }
1466     return xDPField;
1467 }
1468 
getDataPilotField(sal_Int32 nFieldIdx) const1469 Reference< XDataPilotField > PivotTable::getDataPilotField( sal_Int32 nFieldIdx ) const
1470 {
1471     Reference< XDataPilotField > xDPField;
1472     if( const PivotTableField* pTableField = maFields.get( nFieldIdx ).get() )
1473         xDPField = getDataPilotField( pTableField->getDPFieldName() );
1474     return xDPField;
1475 }
1476 
getDataLayoutField() const1477 Reference< XDataPilotField > PivotTable::getDataLayoutField() const
1478 {
1479     Reference< XDataPilotField > xDPField;
1480     try
1481     {
1482         Reference< XDataPilotDataLayoutFieldSupplier > xDPDataFieldSupp( mxDPDescriptor, UNO_QUERY_THROW );
1483         xDPField = xDPDataFieldSupp->getDataLayoutField();
1484     }
1485     catch( Exception& )
1486     {
1487     }
1488     return xDPField;
1489 }
1490 
getCacheField(sal_Int32 nFieldIdx) const1491 const PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx ) const
1492 {
1493     return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : 0;
1494 }
1495 
getCacheFieldOfDataField(sal_Int32 nDataItemIdx) const1496 const PivotCacheField* PivotTable::getCacheFieldOfDataField( sal_Int32 nDataItemIdx ) const
1497 {
1498     const PTDataFieldModel* pDataField = ContainerHelper::getVectorElement( maDataFields, nDataItemIdx );
1499     return pDataField ? getCacheField( pDataField->mnField ) : 0;
1500 }
1501 
getCacheDatabaseIndex(sal_Int32 nFieldIdx) const1502 sal_Int32 PivotTable::getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const
1503 {
1504     return mpPivotCache ? mpPivotCache->getCacheDatabaseIndex( nFieldIdx ) : -1;
1505 }
1506 
1507 // private --------------------------------------------------------------------
1508 
getTableField(sal_Int32 nFieldIdx)1509 PivotTableField* PivotTable::getTableField( sal_Int32 nFieldIdx )
1510 {
1511     return (nFieldIdx == OOX_PT_DATALAYOUTFIELD) ? &maDataField : maFields.get( nFieldIdx ).get();
1512 }
1513 
importField(IndexVector & orFields,const AttributeList & rAttribs)1514 void PivotTable::importField( IndexVector& orFields, const AttributeList& rAttribs )
1515 {
1516     orFields.push_back( rAttribs.getInteger( XML_x, -1 ) );
1517 }
1518 
importFields(IndexVector & orFields,SequenceInputStream & rStrm)1519 void PivotTable::importFields( IndexVector& orFields, SequenceInputStream& rStrm )
1520 {
1521     OSL_ENSURE( orFields.empty(), "PivotTable::importFields - multiple record instances" );
1522     orFields.clear();
1523     sal_Int32 nCount = rStrm.readInt32();
1524     OSL_ENSURE( 4 * nCount == rStrm.getRemaining(), "PivotTable::importFields - invalid field count" );
1525     nCount = static_cast< sal_Int32 >( rStrm.getRemaining() / 4 );
1526     for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1527         orFields.push_back( rStrm.readInt32() );
1528 }
1529 
importFields(IndexVector & orFields,BiffInputStream & rStrm,sal_Int32 nCount)1530 void PivotTable::importFields( IndexVector& orFields, BiffInputStream& rStrm, sal_Int32 nCount )
1531 {
1532     OSL_ENSURE( orFields.empty(), "PivotTable::importFields - multiple record instances" );
1533     orFields.clear();
1534     OSL_ENSURE( 2 * nCount == rStrm.getRemaining(), "PivotTable::importFields - invalid field count" );
1535     nCount = static_cast< sal_Int32 >( rStrm.getRemaining() / 2 );
1536     for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1537         orFields.push_back( rStrm.readInt16() );
1538 }
1539 
1540 // ============================================================================
1541 
PivotTableBuffer(const WorkbookHelper & rHelper)1542 PivotTableBuffer::PivotTableBuffer( const WorkbookHelper& rHelper ) :
1543     WorkbookHelper( rHelper )
1544 {
1545 }
1546 
createPivotTable()1547 PivotTable& PivotTableBuffer::createPivotTable()
1548 {
1549     PivotTableVector::value_type xTable( new PivotTable( *this ) );
1550     maTables.push_back( xTable );
1551     return *xTable;
1552 }
1553 
finalizeImport()1554 void PivotTableBuffer::finalizeImport()
1555 {
1556     maTables.forEachMem( &PivotTable::finalizeImport );
1557 }
1558 
1559 // ============================================================================
1560 
1561 } // namespace xls
1562 } // namespace oox
1563