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