LibreOffice Module sc (master) 1
pivottablebuffer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <pivottablebuffer.hxx>
21
22#include <set>
23#include <com/sun/star/container/XIndexAccess.hpp>
24#include <com/sun/star/container/XNameAccess.hpp>
25#include <com/sun/star/sheet/CellFlags.hpp>
26#include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
27#include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
28#include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
29#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
30#include <com/sun/star/sheet/DataPilotFieldReference.hpp>
31#include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
32#include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
33#include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
34#include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
35#include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
36#include <com/sun/star/sheet/GeneralFunction.hpp>
37#include <com/sun/star/sheet/XDataPilotDataLayoutFieldSupplier.hpp>
38#include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
39#include <com/sun/star/sheet/XSheetOperation.hpp>
40#include <com/sun/star/xml/sax/XFastAttributeList.hpp>
41
43#include <o3tl/safeint.hxx>
44#include <osl/diagnose.h>
46#include <sal/log.hxx>
51#include <oox/token/properties.hxx>
52#include <oox/token/tokens.hxx>
53#include <addressconverter.hxx>
54#include <biffhelper.hxx>
55
56#include <dapiuno.hxx>
57#include <dpobject.hxx>
58#include <dpsave.hxx>
59#include <dpdimsave.hxx>
60#include <document.hxx>
61#include <documentimport.hxx>
62#include <workbooksettings.hxx>
63
64namespace oox::xls {
65
66using namespace ::com::sun::star::container;
67using namespace ::com::sun::star::sheet;
68using namespace ::com::sun::star::table;
69using namespace ::com::sun::star::uno;
70
71namespace {
72
73const sal_Int32 OOX_PT_DATALAYOUTFIELD = -2;
74
75const sal_Int32 OOX_PT_PREVIOUS_ITEM = 0x001000FC;
76const sal_Int32 OOX_PT_NEXT_ITEM = 0x001000FD;
77
78const sal_uInt32 BIFF12_PTFIELD_DATAFIELD = 0x00000008;
79const sal_uInt32 BIFF12_PTFIELD_DEFAULT = 0x00000100;
80const sal_uInt32 BIFF12_PTFIELD_SUM = 0x00000200;
81const sal_uInt32 BIFF12_PTFIELD_COUNTA = 0x00000400;
82const sal_uInt32 BIFF12_PTFIELD_AVERAGE = 0x00000800;
83const sal_uInt32 BIFF12_PTFIELD_MAX = 0x00001000;
84const sal_uInt32 BIFF12_PTFIELD_MIN = 0x00002000;
85const sal_uInt32 BIFF12_PTFIELD_PRODUCT = 0x00004000;
86const sal_uInt32 BIFF12_PTFIELD_COUNT = 0x00008000;
87const sal_uInt32 BIFF12_PTFIELD_STDDEV = 0x00010000;
88const sal_uInt32 BIFF12_PTFIELD_STDDEVP = 0x00020000;
89const sal_uInt32 BIFF12_PTFIELD_VAR = 0x00040000;
90const sal_uInt32 BIFF12_PTFIELD_VARP = 0x00080000;
91
92const sal_uInt32 BIFF12_PTFIELD_SHOWALL = 0x00000020;
93const sal_uInt32 BIFF12_PTFIELD_OUTLINE = 0x00000040;
94const sal_uInt32 BIFF12_PTFIELD_INSERTBLANKROW = 0x00000080;
95const sal_uInt32 BIFF12_PTFIELD_SUBTOTALTOP = 0x00000100;
96const sal_uInt32 BIFF12_PTFIELD_INSERTPAGEBREAK = 0x00000800;
97const sal_uInt32 BIFF12_PTFIELD_AUTOSORT = 0x00001000;
98const sal_uInt32 BIFF12_PTFIELD_SORTASCENDING = 0x00002000;
99const sal_uInt32 BIFF12_PTFIELD_AUTOSHOW = 0x00004000;
100const sal_uInt32 BIFF12_PTFIELD_AUTOSHOWTOP = 0x00008000;
101const sal_uInt32 BIFF12_PTFIELD_MULTIPAGEITEMS = 0x00080000;
102
103const sal_uInt16 BIFF12_PTFITEM_HIDDEN = 0x0001;
104const sal_uInt16 BIFF12_PTFITEM_HIDEDETAILS = 0x0002;
105
106const sal_uInt8 BIFF12_PTPAGEFIELD_HASNAME = 0x01;
107const sal_Int32 BIFF12_PTPAGEFIELD_MULTIITEMS = 0x001000FE;
108
109const sal_uInt16 BIFF12_PTFILTER_HASNAME = 0x0001;
110const sal_uInt16 BIFF12_PTFILTER_HASDESCRIPTION = 0x0002;
111const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE1 = 0x0004;
112const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE2 = 0x0008;
113
114const sal_uInt8 BIFF12_TOP10FILTER_TOP = 0x01;
115const sal_uInt8 BIFF12_TOP10FILTER_PERCENT = 0x02;
116
117const sal_uInt32 BIFF12_PTDEF_SHOWITEMS = 0x00000100;
118const sal_uInt32 BIFF12_PTDEF_DISABLEFIELDLIST = 0x00000400;
119const sal_uInt32 BIFF12_PTDEF_HIDECALCMEMBERS = 0x00001000;
120const sal_uInt32 BIFF12_PTDEF_WITHHIDDENTOTALS = 0x00002000;
121const sal_uInt32 BIFF12_PTDEF_HIDEDRILL = 0x00100000;
122const sal_uInt32 BIFF12_PTDEF_PRINTDRILL = 0x00200000;
123const sal_uInt32 BIFF12_PTDEF_HIDEHEADERS = 0x80000000;
124
125const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYROW = 0x00000004;
126const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYCOL = 0x00000008;
127const sal_uInt32 BIFF12_PTDEF_ENABLEDRILL = 0x00000020;
128const sal_uInt32 BIFF12_PTDEF_PRESERVEFORMATTING = 0x00000080;
129const sal_uInt32 BIFF12_PTDEF_USEAUTOFORMAT = 0x00000100;
130const sal_uInt32 BIFF12_PTDEF_SHOWERROR = 0x00000200;
131const sal_uInt32 BIFF12_PTDEF_SHOWMISSING = 0x00000400;
132const sal_uInt32 BIFF12_PTDEF_PAGEOVERTHENDOWN = 0x00000800;
133const sal_uInt32 BIFF12_PTDEF_SUBTOTALHIDDENITEMS = 0x00001000;
134const sal_uInt32 BIFF12_PTDEF_ROWGRANDTOTALS = 0x00002000;
135const sal_uInt32 BIFF12_PTDEF_COLGRANDTOTALS = 0x00004000;
136const sal_uInt32 BIFF12_PTDEF_FIELDPRINTTITLES = 0x00008000;
137const sal_uInt32 BIFF12_PTDEF_ITEMPRINTTITLES = 0x00020000;
138const sal_uInt32 BIFF12_PTDEF_MERGEITEM = 0x00040000;
139const sal_uInt32 BIFF12_PTDEF_HASDATACAPTION = 0x00080000;
140const sal_uInt32 BIFF12_PTDEF_HASGRANDTOTALCAPTION = 0x00100000;
141const sal_uInt32 BIFF12_PTDEF_HASPAGESTYLE = 0x00200000;
142const sal_uInt32 BIFF12_PTDEF_HASPIVOTTABLESTYLE = 0x00400000;
143const sal_uInt32 BIFF12_PTDEF_HASVACATEDSTYLE = 0x00800000;
144const sal_uInt32 BIFF12_PTDEF_APPLYNUMFMT = 0x01000000;
145const sal_uInt32 BIFF12_PTDEF_APPLYFONT = 0x02000000;
146const sal_uInt32 BIFF12_PTDEF_APPLYALIGNMENT = 0x04000000;
147const sal_uInt32 BIFF12_PTDEF_APPLYBORDER = 0x08000000;
148const sal_uInt32 BIFF12_PTDEF_APPLYFILL = 0x10000000;
149const sal_uInt32 BIFF12_PTDEF_APPLYPROTECTION = 0x20000000;
150const sal_uInt32 BIFF12_PTDEF_HASTAG = 0x40000000;
151
152const sal_uInt32 BIFF12_PTDEF_NOERRORCAPTION = 0x00000040;
153const sal_uInt32 BIFF12_PTDEF_NOMISSINGCAPTION = 0x00000080;
154const sal_uInt32 BIFF12_PTDEF_HASROWHEADERCAPTION = 0x00000400;
155const sal_uInt32 BIFF12_PTDEF_HASCOLHEADERCAPTION = 0x00000800;
156const sal_uInt32 BIFF12_PTDEF_FIELDLISTSORTASC = 0x00001000;
157const sal_uInt32 BIFF12_PTDEF_NOCUSTOMLISTSORT = 0x00004000;
158
159const sal_uInt8 BIFF12_PTDEF_ROWAXIS = 1;
160const sal_uInt8 BIFF12_PTDEF_COLAXIS = 2;
161
162} // namespace
163
165 mnCacheItem( -1 ),
166 mnType( XML_data ),
167 mbShowDetails( true ),
168 mbHidden( false )
169{
170}
171
173{
174 static const sal_Int32 spnTypes[] = { XML_data, XML_default,
175 XML_sum, XML_countA, XML_avg, XML_max, XML_min, XML_product, XML_count,
176 XML_stdDev, XML_stdDevP, XML_var, XML_varP, XML_grand, XML_blank };
177 mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_data );
178}
179
181 mnAxis( XML_TOKEN_INVALID ),
182 mnNumFmtId( 0 ),
183 mnAutoShowItems( 10 ),
184 mnAutoShowRankBy( -1 ),
185 mnSortType( XML_manual ),
186 mnSortRefField( -1 ),
187 mnSortRefItem( -1 ),
188 mbDataField( false ),
189 mbDefaultSubtotal( true ),
190 mbSumSubtotal( false ),
191 mbCountASubtotal( false ),
192 mbAverageSubtotal( false ),
193 mbMaxSubtotal( false ),
194 mbMinSubtotal( false ),
195 mbProductSubtotal( false ),
196 mbCountSubtotal( false ),
197 mbStdDevSubtotal( false ),
198 mbStdDevPSubtotal( false ),
199 mbVarSubtotal( false ),
200 mbVarPSubtotal( false ),
201 mbShowAll( true ),
202 mbOutline( true ),
203 mbSubtotalTop( true ),
204 mbCompact( false ),
205 mbInsertBlankRow( false ),
206 mbInsertPageBreak( false ),
207 mbAutoShow( false ),
208 mbTopAutoShow( true ),
209 mbMultiPageItems( false )
210{
211}
212
214{
215 /* Weird. The axis field is organized as bit field, but only one of the
216 row/col/page flags are allowed at the same time and refer to the values
217 'axisRow', 'axisCol', and 'axisPage' of the XML attribute
218 'pivotField@axis'. Additionally, the fourth bit determines if the field
219 is a data field, which may appear combined with the row/col/page flags.
220 Therefore, this bit is unrelated to the 'axisValues' value of the
221 'pivotField@axis' attribute, but refers to the 'pivotField@dataField'
222 boolean attribute. */
223 static const sal_Int32 spnAxisIds[] = { XML_TOKEN_INVALID, XML_axisRow, XML_axisCol, XML_TOKEN_INVALID, XML_axisPage };
224 mnAxis = STATIC_ARRAY_SELECT( spnAxisIds, nAxis, XML_TOKEN_INVALID );
225}
226
228 mnField( -1 ),
229 mnItem( BIFF12_PTPAGEFIELD_MULTIITEMS )
230{
231}
232
234 mnField( -1 ),
235 mnSubtotal( XML_sum ),
236 mnShowDataAs( XML_normal ),
237 mnBaseField( -1 ),
238 mnBaseItem( -1 ),
239 mnNumFmtId( 0 )
240{
241}
242
243void PTDataFieldModel::setBiffSubtotal( sal_Int32 nSubtotal )
244{
245 static const 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 };
246 mnSubtotal = STATIC_ARRAY_SELECT( spnSubtotals, nSubtotal, XML_TOKEN_INVALID );
247}
248
249void PTDataFieldModel::setBiffShowDataAs( sal_Int32 nShowDataAs )
250{
251 static const sal_Int32 spnShowDataAs[] = { XML_normal, XML_difference, XML_percent, XML_percentDiff, XML_runTotal, XML_percentOfRow, XML_percentOfCol, XML_percentOfTotal, XML_index };
252 mnShowDataAs = STATIC_ARRAY_SELECT( spnShowDataAs, nShowDataAs, XML_TOKEN_INVALID );
253}
254
255PivotTableField::PivotTableField( PivotTable& rPivotTable, sal_Int32 nFieldIndex ) :
256 WorkbookHelper( rPivotTable ),
257 mrPivotTable( rPivotTable ),
258 mnFieldIndex( nFieldIndex )
259{
260}
261
263{
264 /* The documentation mentions a value 'axisValues' for the attribute
265 'pivotField@axis'. But this value is not used to mark a data field, as
266 data fields may be inserted in one of the row/column/page dimensions at
267 the same time. Therefore, the boolean attribute 'pivotField@dataField'
268 is really used to mark data fields. */
269 maModel.mnAxis = rAttribs.getToken( XML_axis, XML_TOKEN_INVALID );
270 maModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
271 maModel.mnAutoShowItems = rAttribs.getInteger( XML_itemPageCount, 10 );
272 maModel.mnAutoShowRankBy = rAttribs.getInteger( XML_rankBy, -1 );
273 maModel.mnSortType = rAttribs.getToken( XML_sortType, XML_manual );
274 maModel.mbDataField = rAttribs.getBool( XML_dataField, false );
275 maModel.mbDefaultSubtotal = rAttribs.getBool( XML_defaultSubtotal, true );
276 maModel.mbSumSubtotal = rAttribs.getBool( XML_sumSubtotal, false );
277 maModel.mbCountASubtotal = rAttribs.getBool( XML_countASubtotal, false );
278 maModel.mbAverageSubtotal = rAttribs.getBool( XML_avgSubtotal, false );
279 maModel.mbMaxSubtotal = rAttribs.getBool( XML_maxSubtotal, false );
280 maModel.mbMinSubtotal = rAttribs.getBool( XML_minSubtotal, false );
281 maModel.mbProductSubtotal = rAttribs.getBool( XML_productSubtotal, false );
282 maModel.mbCountSubtotal = rAttribs.getBool( XML_countSubtotal, false );
283 maModel.mbStdDevSubtotal = rAttribs.getBool( XML_stdDevSubtotal, false );
284 maModel.mbStdDevPSubtotal = rAttribs.getBool( XML_stdDevPSubtotal, false );
285 maModel.mbVarSubtotal = rAttribs.getBool( XML_varSubtotal, false );
286 maModel.mbVarPSubtotal = rAttribs.getBool( XML_varPSubtotal, false );
287 maModel.mbShowAll = rAttribs.getBool( XML_showAll, true );
288 maModel.mbOutline = rAttribs.getBool( XML_outline, true );
289 maModel.mbSubtotalTop = rAttribs.getBool( XML_subtotalTop, true );
290 maModel.mbCompact = maModel.mbSubtotalTop && maModel.mbOutline && rAttribs.getBool( XML_compact, true );
291 maModel.mbInsertBlankRow = rAttribs.getBool( XML_insertBlankRow, false );
292 maModel.mbInsertPageBreak = rAttribs.getBool( XML_insertPageBreak, false );
293 maModel.mbAutoShow = rAttribs.getBool( XML_autoShow, false );
294 maModel.mbTopAutoShow = rAttribs.getBool( XML_topAutoShow, true );
295 maModel.mbMultiPageItems = rAttribs.getBool( XML_multipleItemSelectionAllowed, false );
296}
297
299{
300 PTFieldItemModel aModel;
301 aModel.mnCacheItem = rAttribs.getInteger( XML_x, -1 );
302 aModel.mnType = rAttribs.getToken( XML_t, XML_data );
303 aModel.mbShowDetails = rAttribs.getBool( XML_sd, true );
304 aModel.mbHidden = rAttribs.getBool( XML_h, false );
305 aModel.msCaption = rAttribs.getXString( XML_n, OUString() );
306 maItems.push_back( aModel );
307}
308
310{
311 // field index is stored as unsigned integer
312 maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsigned( XML_field, SAL_MAX_UINT32 ) );
313}
314
316{
317 maModel.mnSortRefItem = rAttribs.getInteger( XML_v, -1 );
318}
319
321{
322 sal_uInt32 nFlags1, nFlags2;
323 nFlags1 = rStrm.readuInt32();
324 maModel.mnNumFmtId = rStrm.readInt32();
325 nFlags2 = rStrm.readuInt32();
326 maModel.mnAutoShowItems = rStrm.readInt32();
327 maModel.mnAutoShowRankBy = rStrm.readInt32();
328
329 maModel.setBiffAxis( extractValue< sal_uInt8 >( nFlags1, 0, 3 ) );
330 maModel.mbDataField = getFlag( nFlags1, BIFF12_PTFIELD_DATAFIELD );
331 maModel.mbDefaultSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_DEFAULT );
332 maModel.mbSumSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_SUM );
333 maModel.mbCountASubtotal = getFlag( nFlags1, BIFF12_PTFIELD_COUNTA );
334 maModel.mbAverageSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_AVERAGE );
335 maModel.mbMaxSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_MAX );
336 maModel.mbMinSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_MIN );
337 maModel.mbProductSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_PRODUCT );
338 maModel.mbCountSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_COUNT );
339 maModel.mbStdDevSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEV );
340 maModel.mbStdDevPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEVP );
341 maModel.mbVarSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_VAR );
342 maModel.mbVarPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_VARP );
343
344 maModel.mbShowAll = getFlag( nFlags2, BIFF12_PTFIELD_SHOWALL );
345 maModel.mbOutline = getFlag( nFlags2, BIFF12_PTFIELD_OUTLINE );
346 maModel.mbSubtotalTop = getFlag( nFlags2, BIFF12_PTFIELD_SUBTOTALTOP );
347 maModel.mbInsertBlankRow = getFlag( nFlags2, BIFF12_PTFIELD_INSERTBLANKROW );
348 maModel.mbInsertPageBreak = getFlag( nFlags2, BIFF12_PTFIELD_INSERTPAGEBREAK );
349 maModel.mbAutoShow = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOW );
350 maModel.mbTopAutoShow = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOWTOP );
351 maModel.mbMultiPageItems = getFlag( nFlags2, BIFF12_PTFIELD_MULTIPAGEITEMS );
352
353 bool bAutoSort = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSORT );
354 bool bAscending = getFlag( nFlags2, BIFF12_PTFIELD_SORTASCENDING );
355 maModel.mnSortType = bAutoSort ? (bAscending ? XML_ascending : XML_descending) : XML_manual;
356}
357
359{
360 PTFieldItemModel aModel;
362 sal_uInt16 nFlags;
363 nType = rStrm.readuChar();
364 nFlags = rStrm.readuInt16();
365 aModel.mnCacheItem = rStrm.readInt32();
366
367 aModel.setBiffType( nType );
368 aModel.mbShowDetails = !getFlag( nFlags, BIFF12_PTFITEM_HIDEDETAILS );
369 aModel.mbHidden = getFlag( nFlags, BIFF12_PTFITEM_HIDDEN );
370
371 maItems.push_back( aModel );
372}
373
375{
376 maModel.mnSortRefField = rStrm.readInt32();
377}
378
380{
381 maModel.mnSortRefItem = rStrm.readInt32();
382}
383
384void PivotTableField::finalizeImport( const Reference< XDataPilotDescriptor >& rxDPDesc )
385{
386 /* Process all fields based on source data, other fields (e.g. group
387 fields) are processed from here. PivotCache::getCacheDatabaseIndex()
388 returns -1 for all fields not based on source data. */
389 Reference< XDataPilotField > xDPField;
390 sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
391 if( !((nDatabaseIdx >= 0) && rxDPDesc.is()) )
392 return;
393
394 try
395 {
396 // try to get the source field and its name from passed DataPilot descriptor
397 Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
398 xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
399 Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
400 maDPFieldName = xDPFieldName->getName();
401 OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeImport - no field name in source data found" );
402
403 // try to convert grouping settings
404 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
405 {
406 // numeric grouping is done inplace, no nested group fields will appear
407 if( pCacheField->hasNumericGrouping() )
408 {
409 pCacheField->convertNumericGrouping( xDPField );
410 }
411 else if( pCacheField->hasDateGrouping() )
412 {
413 // first date group settings are inplace
414 pCacheField->createDateGroupField( xDPField );
415 // create all nested group fields (if any)
417 }
418 else if( pCacheField->hasParentGrouping() )
419 {
420
421 // create a list of all item names, needed to map between original and group items
422 ::std::vector< OUString > aItems;
423 pCacheField->getCacheItemNames( aItems );
424 PivotCacheGroupItemVector aItemNames;
425 for( const auto& rItem : aItems )
426 aItemNames.emplace_back( rItem );
427 // create all nested group fields (if any)
428 mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, aItemNames );
429 }
430 }
431 }
432 catch( Exception& )
433 {
434 }
435}
436
437void PivotTableField::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
438{
439 if( maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
440 {
442 {
443 if( !pCacheField->isDatabaseField() && pCacheField->hasDateGrouping() && (pCacheField->getGroupBaseField() == nBaseFieldIdx) )
444 {
445 maDPFieldName = pCacheField->createDateGroupField( rxBaseDPField );
446 pCacheField->setFinalGroupName(maDPFieldName);
447 OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
448 }
449 }
450 }
451}
452
453void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
454{
455 if( !maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
456 return;
457
459 if( !pCacheField )
460 return;
461
462 // data field can have user defined groupname captions, apply them
463 // if they do
464 IdCaptionPairList captionList;
465 for( const auto& rItem : maItems )
466 {
467 if ( rItem.mnType == XML_data && rItem.msCaption.getLength() )
468 captionList.emplace_back( rItem.mnCacheItem, rItem.msCaption );
469 }
470 if ( !captionList.empty() )
471 pCacheField->applyItemCaptions( captionList );
472
473 maDPFieldName = pCacheField->createParentGroupField( rxBaseDPField, rBaseCacheField, orItemNames );
474 pCacheField->setFinalGroupName(maDPFieldName);
475 // on success, try to create nested group fields
476 Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
477 if( xDPField.is() )
478 mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, orItemNames );
479}
480
481void PivotTableField::finalizeImportBasedOnCache( const Reference< XDataPilotDescriptor >& rxDPDesc)
482{
483 /* Process all fields based on source data, other fields (e.g. group
484 fields) are processed based on cache fields.*/
485 Reference< XDataPilotField > xDPField;
486 sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
487 if( (nDatabaseIdx >= 0) && rxDPDesc.is() ) try
488 {
489 // Try to get the source field and its name from passed DataPilot descriptor
490 Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
491 xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
492 Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
493 maDPFieldName = xDPFieldName->getName();
494 SAL_WARN_IF( maDPFieldName.isEmpty(), "sc.filter", "PivotTableField::finalizeImportBasedOnCache - no field name in source data found" );
495 }
496 catch( Exception& )
497 {
498 }
499
500 // Use group names already generated for another table using the same group field.
501 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
502 {
503 if(!pCacheField->getFinalGroupName().isEmpty())
504 maDPFieldName = pCacheField->getFinalGroupName();
505 }
506}
507
509{
510 convertRowColPageField( XML_axisRow );
511}
512
514{
515 convertRowColPageField( XML_axisCol );
516}
517
519{
521}
522
524{
525 OSL_ENSURE( rPageField.mnField == mnFieldIndex, "PivotTableField::convertPageField - wrong field index" );
526 // convert all settings common for row/column/page fields
527 Reference< XDataPilotField > xDPField = convertRowColPageField( XML_axisPage );
528
529 if( !xDPField.is() )
530 return;
531
532 PropertySet aPropSet( xDPField );
533
534 // find cache item used as 'selected page'
535 sal_Int32 nCacheItem = -1;
537 {
538 // multiple items may be selected
539 OSL_ENSURE( rPageField.mnItem == BIFF12_PTPAGEFIELD_MULTIITEMS, "PivotTableField::convertPageField - unexpected cache item index" );
540 // try to find a single visible item
541 bool bHasMultiItems = false;
542 for( const auto& rItem : maItems )
543 {
544 if( (rItem.mnType == XML_data) && !rItem.mbHidden )
545 {
546 bHasMultiItems = nCacheItem >= 0;
547 nCacheItem = bHasMultiItems ? -1 : rItem.mnCacheItem;
548 }
549
550 if( bHasMultiItems )
551 break;
552 }
553 }
554 else
555 {
556 // single item may be selected
557 if( (0 <= rPageField.mnItem) && (o3tl::make_unsigned(rPageField.mnItem) < maItems.size()) )
558 nCacheItem = maItems[ rPageField.mnItem ].mnCacheItem;
559 }
560
561 if( nCacheItem < 0 )
562 return;
563
564 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
565 {
566 if( const PivotCacheItem* pSharedItem = pCacheField->getCacheItem( nCacheItem ) )
567 {
569 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
570 ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
571 OUString aSelectedPage = pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate()));
572 aPropSet.setProperty( PROP_SelectedPage, aSelectedPage );
573 }
574 }
575}
576
578{
579 OSL_ENSURE( rDataField.mnField == mnFieldIndex, "PivotTableField::convertDataField - wrong field index" );
580 OSL_ENSURE( maModel.mbDataField, "PivotTableField::convertDataField - not a data field" );
581 Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
582 if( !xDPField.is() )
583 return;
584
585 PropertySet aPropSet( xDPField );
586
587 // field orientation
588 aPropSet.setProperty( PROP_Orientation, DataPilotFieldOrientation_DATA );
589
590 if (!rDataField.maName.isEmpty())
591 aPropSet.setProperty(PROP_Name, rDataField.maName);
592
593 /* Field aggregation function. Documentation is a little bit confused
594 about which names to use for the count functions. The name 'count'
595 means 'count all', and 'countNum' means 'count numbers'. On the
596 other hand, for subtotals, 'countA' means 'count all', and 'count'
597 means 'count numbers' (see above). */
598 GeneralFunction eAggFunc = GeneralFunction_SUM;
599 switch( rDataField.mnSubtotal )
600 {
601 case XML_sum: eAggFunc = GeneralFunction_SUM; break;
602 case XML_count: eAggFunc = GeneralFunction_COUNT; break;
603 case XML_average: eAggFunc = GeneralFunction_AVERAGE; break;
604 case XML_max: eAggFunc = GeneralFunction_MAX; break;
605 case XML_min: eAggFunc = GeneralFunction_MIN; break;
606 case XML_product: eAggFunc = GeneralFunction_PRODUCT; break;
607 case XML_countNums: eAggFunc = GeneralFunction_COUNTNUMS; break;
608 case XML_stdDev: eAggFunc = GeneralFunction_STDEV; break;
609 case XML_stdDevp: eAggFunc = GeneralFunction_STDEVP; break;
610 case XML_var: eAggFunc = GeneralFunction_VAR; break;
611 case XML_varp: eAggFunc = GeneralFunction_VARP; break;
612 default: OSL_FAIL( "PivotTableField::convertDataField - unknown aggregation function" );
613 }
614 aPropSet.setProperty( PROP_Function, eAggFunc );
615
616 // field reference ('show data as')
617 DataPilotFieldReference aReference;
618 aReference.ReferenceType = DataPilotFieldReferenceType::NONE;
619 switch( rDataField.mnShowDataAs )
620 {
621 case XML_difference: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_DIFFERENCE; break;
622 case XML_percent: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE; break;
623 case XML_percentDiff: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE; break;
624 case XML_runTotal: aReference.ReferenceType = DataPilotFieldReferenceType::RUNNING_TOTAL; break;
625 case XML_percentOfRow: aReference.ReferenceType = DataPilotFieldReferenceType::ROW_PERCENTAGE; break;
626 case XML_percentOfCol: aReference.ReferenceType = DataPilotFieldReferenceType::COLUMN_PERCENTAGE; break;
627 case XML_percentOfTotal: aReference.ReferenceType = DataPilotFieldReferenceType::TOTAL_PERCENTAGE; break;
628 case XML_index: aReference.ReferenceType = DataPilotFieldReferenceType::INDEX; break;
629 }
630 if( aReference.ReferenceType == DataPilotFieldReferenceType::NONE )
631 return;
632
633 const PivotCacheField* pCacheField = mrPivotTable.getCacheField( rDataField.mnBaseField );
634 if( !pCacheField )
635 return;
636
637 aReference.ReferenceField = pCacheField->getName();
638 switch( rDataField.mnBaseItem )
639 {
640 case OOX_PT_PREVIOUS_ITEM:
641 aReference.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
642 break;
643 case OOX_PT_NEXT_ITEM:
644 aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
645 break;
646 default:
647 aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
648 if( const PivotCacheItem* pCacheItem = pCacheField->getCacheItem( rDataField.mnBaseItem ) )
649 aReference.ReferenceItemName = pCacheItem->getName();
650 }
651 aPropSet.setProperty( PROP_Reference, aReference );
652}
653
654// private --------------------------------------------------------------------
655
656Reference< XDataPilotField > PivotTableField::convertRowColPageField( sal_Int32 nAxis )
657{
658 bool bDataLayout = mnFieldIndex == OOX_PT_DATALAYOUTFIELD;
659 Reference< XDataPilotField > xDPField = bDataLayout ? mrPivotTable.getDataLayoutField() : mrPivotTable.getDataPilotField( maDPFieldName );
660 OSL_ENSURE( bDataLayout || (nAxis == maModel.mnAxis), "PivotTableField::convertRowColPageField - field axis mismatch" );
661
662 if( xDPField.is() )
663 {
664 // TODO: Use this to set properties directly, bypassing the slow uno layer.
666
667 PropertySet aPropSet( xDPField );
668
669 // field orientation
670 DataPilotFieldOrientation eFieldOrient = DataPilotFieldOrientation_HIDDEN;
671 switch( nAxis )
672 {
673 case XML_axisRow: eFieldOrient = DataPilotFieldOrientation_ROW; break;
674 case XML_axisCol: eFieldOrient = DataPilotFieldOrientation_COLUMN; break;
675 case XML_axisPage: eFieldOrient = DataPilotFieldOrientation_PAGE; break;
676 }
677 if( eFieldOrient != DataPilotFieldOrientation_HIDDEN )
678 aPropSet.setProperty( PROP_Orientation, eFieldOrient );
679
680 // all other settings not for the data layout field
681 if( !bDataLayout )
682 {
683 /* Field subtotal functions. Ignore the 'defaultSubtotal' flag, if
684 explicit functions are set. This is different behaviour between
685 XML (where 'defaultSubtotal' is set regardless of other
686 functions) and binary formats (where 'defaultSubtotal' is not
687 set if other functions are set). */
688 ::std::vector< GeneralFunction > aSubtotals;
689 /* Order of subtotals is fixed in Excel. Documentation is a little
690 bit confused about which names to use for the count functions.
691 For subtotals, 'countA' means 'count all', and 'count' means
692 'count numbers'. On the other hand, for the data field
693 aggregation function, 'count' means 'count all', and 'countNum'
694 means 'count numbers' (see below). */
695 if( maModel.mbSumSubtotal ) aSubtotals.push_back( GeneralFunction_SUM );
696 if( maModel.mbCountASubtotal ) aSubtotals.push_back( GeneralFunction_COUNT );
697 if( maModel.mbAverageSubtotal ) aSubtotals.push_back( GeneralFunction_AVERAGE );
698 if( maModel.mbMaxSubtotal ) aSubtotals.push_back( GeneralFunction_MAX );
699 if( maModel.mbMinSubtotal ) aSubtotals.push_back( GeneralFunction_MIN );
700 if( maModel.mbProductSubtotal ) aSubtotals.push_back( GeneralFunction_PRODUCT );
701 if( maModel.mbCountSubtotal ) aSubtotals.push_back( GeneralFunction_COUNTNUMS );
702 if( maModel.mbStdDevSubtotal ) aSubtotals.push_back( GeneralFunction_STDEV );
703 if( maModel.mbStdDevPSubtotal ) aSubtotals.push_back( GeneralFunction_STDEVP );
704 if( maModel.mbVarSubtotal ) aSubtotals.push_back( GeneralFunction_VAR );
705 if( maModel.mbVarPSubtotal ) aSubtotals.push_back( GeneralFunction_VARP );
706 // if no function is set manually, check the 'defaultSubtotal' flag
707 if( aSubtotals.empty() && maModel.mbDefaultSubtotal )
708 aSubtotals.push_back( GeneralFunction_AUTO );
709 aPropSet.setProperty( PROP_Subtotals, comphelper::containerToSequence( aSubtotals ) );
710
711 // layout settings
712 DataPilotFieldLayoutInfo aLayoutInfo;
713 if (maModel.mbCompact)
714 {
715 aLayoutInfo.LayoutMode = DataPilotFieldLayoutMode::COMPACT_LAYOUT;
716 }
717 else if (maModel.mbOutline)
718 {
720 aLayoutInfo.LayoutMode = DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP;
721 else
722 aLayoutInfo.LayoutMode = DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM;
723 }
724 else
725 {
726 aLayoutInfo.LayoutMode = DataPilotFieldLayoutMode::TABULAR_LAYOUT;
727 }
728
729 aLayoutInfo.AddEmptyLines = maModel.mbInsertBlankRow;
730 aPropSet.setProperty( PROP_LayoutInfo, aLayoutInfo );
731 aPropSet.setProperty( PROP_ShowEmpty, maModel.mbShowAll );
732
733 // auto show (OOXML/BIFF12 only)
734 if( maModel.mbAutoShow )
735 {
736 DataPilotFieldAutoShowInfo aAutoShowInfo;
737 aAutoShowInfo.IsEnabled = true;
738 aAutoShowInfo.ShowItemsMode = maModel.mbTopAutoShow ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
739 aAutoShowInfo.ItemCount = maModel.mnAutoShowItems;
741 aAutoShowInfo.DataField = pCacheField->getName();
742 aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
743 }
744
745 // auto sort
746 DataPilotFieldSortInfo aSortInfo;
747 aSortInfo.IsAscending = maModel.mnSortType == XML_ascending;
748 if( (maModel.mnSortType != XML_ascending) && (maModel.mnSortType != XML_descending) )
749 {
750 aSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
751 }
752 else
753 {
754 const PivotCacheField* pCacheField = (maModel.mnSortRefField == OOX_PT_DATALAYOUTFIELD) ?
756 if( pCacheField )
757 {
758 aSortInfo.Mode = DataPilotFieldSortMode::DATA;
759 aSortInfo.Field = pCacheField->getName();
760 }
761 else
762 {
763 aSortInfo.Mode = DataPilotFieldSortMode::NAME;
764 }
765 }
766 aPropSet.setProperty( PROP_SortInfo, aSortInfo );
767
768 // item settings
769 if (const PivotCacheField* pCacheField = mrPivotTable.getCacheField(mnFieldIndex))
770 {
771 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
772 ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
773 SAL_WARN_IF(!pDim, "sc.filter", "PivotTableField::convertRowColPageField - no Dimension found for: " << pCacheField->getName());
774
775 if (pDim) try
776 {
777 for( const auto& rItem : maItems )
778 {
779 if (rItem.mnType != XML_data)
780 continue;
781
782 const PivotCacheItem* pSharedItem = pCacheField->getCacheItem(rItem.mnCacheItem);
783 if (!pSharedItem)
784 continue;
785
786 try
787 {
788 ScDPSaveMember* pMem = pDim->GetMemberByName(pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate())));
789 pMem->SetShowDetails(rItem.mbShowDetails);
790 pMem->SetIsVisible(!rItem.mbHidden);
791 }
792 catch( Exception& )
793 {
794 // catch every failed container access to be able to process following items
795 }
796 }
797 }
798 catch (const Exception&) {}
799 }
800 }
801 }
802 return xDPField;
803}
804
806 mfValue( 0.0 ),
807 mnField( -1 ),
808 mnMemPropField( -1 ),
810 mnEvalOrder( 0 ),
811 mnId( -1 ),
812 mnMeasureField( -1 ),
813 mnMeasureHier( -1 ),
814 mbTopFilter( true )
815{
816}
817
819 WorkbookHelper( rPivotTable ),
820 mrPivotTable( rPivotTable )
821{
822}
823
825{
826 maModel.maName = rAttribs.getXString( XML_name, OUString() );
827 maModel.maDescription = rAttribs.getXString( XML_description, OUString() );
828 maModel.maStrValue1 = rAttribs.getXString( XML_stringValue1, OUString() );
829 maModel.maStrValue2 = rAttribs.getXString( XML_stringValue2, OUString() );
830 maModel.mnField = rAttribs.getInteger( XML_fld, -1 );
831 maModel.mnMemPropField = rAttribs.getInteger( XML_mpFld, -1 );
833 maModel.mnEvalOrder = rAttribs.getInteger( XML_evalOrder, 0 );
834 maModel.mnId = rAttribs.getInteger( XML_id, -1 );
835 maModel.mnMeasureField = rAttribs.getInteger( XML_iMeasureFld, -1 );
836 maModel.mnMeasureHier = rAttribs.getInteger( XML_iMeasureHier, -1 );
837}
838
840{
841 OSL_ENSURE( rAttribs.getBool( XML_percent, false ) == (maModel.mnType == XML_percent),
842 "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
843 maModel.mfValue = rAttribs.getDouble( XML_val, 0.0 );
844 maModel.mbTopFilter = rAttribs.getBool( XML_top, true );
845}
846
848{
849 sal_Int32 nType;
850 sal_uInt16 nFlags;
851 maModel.mnField = rStrm.readInt32();
852 maModel.mnMemPropField = rStrm.readInt32();
853 nType = rStrm.readInt32();
854 rStrm.skip( 4 ); // unused
855 maModel.mnId = rStrm.readInt32();
856 maModel.mnMeasureField = rStrm.readInt32();
857 maModel.mnMeasureHier = rStrm.readInt32();
858 nFlags = rStrm.readuInt16();
859 if( getFlag( nFlags, BIFF12_PTFILTER_HASNAME ) )
861 if( getFlag( nFlags, BIFF12_PTFILTER_HASDESCRIPTION ) )
863 if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE1 ) )
865 if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE2 ) )
867
868 static const sal_Int32 spnTypes[] =
869 {
870 XML_unknown,
871 // data field top10 filter (1-3)
872 XML_count, XML_percent, XML_sum,
873 // caption filter (4-17)
874 XML_captionEqual, XML_captionNotEqual,
875 XML_captionBeginsWith, XML_captionNotBeginsWith, XML_captionEndsWith, XML_captionNotEndsWith,
876 XML_captionContains, XML_captionNotContains, XML_captionGreaterThan, XML_captionGreaterThanOrEqual,
877 XML_captionLessThan, XML_captionLessThanOrEqual, XML_captionBetween, XML_captionNotBetween,
878 // value filter (18-25)
879 XML_valueEqual, XML_valueNotEqual, XML_valueGreaterThan, XML_valueGreaterThanOrEqual,
880 XML_valueLessThan, XML_valueLessThanOrEqual, XML_valueBetween, XML_valueNotBetween,
881 // date filter (26-65)
882 XML_dateEqual, XML_dateOlderThan, XML_dateNewerThan, XML_dateBetween,
883 XML_tomorrow, XML_today, XML_yesterday, XML_nextWeek, XML_thisWeek, XML_lastWeek,
884 XML_nextMonth, XML_thisMonth, XML_lastMonth, XML_nextQuarter, XML_thisQuarter, XML_lastQuarter,
885 XML_nextYear, XML_thisYear, XML_lastYear, XML_yearToDate, XML_Q1, XML_Q2, XML_Q3, XML_Q4,
886 XML_M1, XML_M2, XML_M3, XML_M4, XML_M5, XML_M6, XML_M7, XML_M8, XML_M9, XML_M10, XML_M11, XML_M12,
887 XML_dateNotEqual, XML_dateOlderThanOrEqual, XML_dateNewerThanOrEqual, XML_dateNotBetween
888 };
890}
891
893{
894 sal_uInt8 nFlags;
895 nFlags = rStrm.readuChar();
896 maModel.mfValue = rStrm.readDouble();
897
899 getFlag(nFlags, BIFF12_TOP10FILTER_PERCENT) != (maModel.mnType == XML_percent),
900 "sc.filter",
901 "PivotTableFilter::importTop10 - unexpected value of percent attribute");
902 maModel.mbTopFilter = getFlag( nFlags, BIFF12_TOP10FILTER_TOP );
903}
904
906{
907 // only simple top10 filter supported
908 if( maModel.mnType != XML_count )
909 return;
910
912 if( aPropSet.is() )
913 {
914 DataPilotFieldAutoShowInfo aAutoShowInfo;
915 aAutoShowInfo.IsEnabled = true;
916 aAutoShowInfo.ShowItemsMode = maModel.mbTopFilter ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
917 aAutoShowInfo.ItemCount = getLimitedValue< sal_Int32, double >( maModel.mfValue, 0, SAL_MAX_INT32 );
919 aAutoShowInfo.DataField = pCacheField->getName();
920 aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
921 }
922}
923
925 mnCacheId( -1 ),
926 mnDataPosition( 0 ),
927 mnPageWrap( 0 ),
928 mnIndent( 1 ),
929 mnChartFormat( 0 ),
930 mbDataOnRows( false ),
931 mbShowError( false ),
932 mbShowMissing( true ),
933 mbShowItems( true ),
934 mbDisableFieldList( false ),
935 mbShowCalcMembers( true ),
936 mbVisualTotals( true ),
937 mbShowDrill( true ),
938 mbPrintDrill( false ),
939 mbEnableDrill( true ),
940 mbPreserveFormatting( true ),
941 mbUseAutoFormat( false ),
942 mbPageOverThenDown( false ),
943 mbSubtotalHiddenItems( false ),
944 mbRowGrandTotals( true ),
945 mbColGrandTotals( true ),
946 mbFieldPrintTitles( false ),
947 mbItemPrintTitles( false ),
948 mbMergeItem( false ),
949 mbShowEmptyRow( false ),
950 mbShowEmptyCol( false ),
951 mbShowHeaders( true ),
952 mbFieldListSortAsc( false ),
953 mbCustomListSort( true )
954{
955}
956
958 mnFirstHeaderRow( 0 ),
959 mnFirstDataRow( 0 ),
960 mnFirstDataCol( 0 ),
961 mnRowPageCount( 0 ),
962 mnColPageCount( 0 )
963{
964}
965
967 WorkbookHelper( rHelper ),
968 mpDPObject(nullptr),
969 maDataField( *this, OOX_PT_DATALAYOUTFIELD ),
970 mpPivotCache( nullptr )
971{
972}
973
975{
976 maDefModel.maName = rAttribs.getXString( XML_name, OUString() );
977 maDefModel.maDataCaption = rAttribs.getXString( XML_dataCaption , OUString() );
978 maDefModel.maGrandTotalCaption = rAttribs.getXString( XML_grandTotalCaption, OUString() );
979 maDefModel.maRowHeaderCaption = rAttribs.getXString( XML_rowHeaderCaption, OUString() );
980 maDefModel.maColHeaderCaption = rAttribs.getXString( XML_colHeaderCaption, OUString() );
981 maDefModel.maErrorCaption = rAttribs.getXString( XML_errorCaption, OUString() );
982 maDefModel.maMissingCaption = rAttribs.getXString( XML_missingCaption, OUString() );
983 maDefModel.maPageStyle = rAttribs.getXString( XML_pageStyle, OUString() );
984 maDefModel.maPivotTableStyle = rAttribs.getXString( XML_pivotTableStyle, OUString() );
985 maDefModel.maVacatedStyle = rAttribs.getXString( XML_vacatedStyle, OUString() );
986 maDefModel.maTag = rAttribs.getXString( XML_tag, OUString() );
987 maDefModel.mnCacheId = rAttribs.getInteger( XML_cacheId, -1 );
988 maDefModel.mnDataPosition = rAttribs.getInteger( XML_dataPosition, 0 );
989 maDefModel.mnPageWrap = rAttribs.getInteger( XML_pageWrap, 0 );
990 maDefModel.mnIndent = rAttribs.getInteger( XML_indent, 1 );
991 maDefModel.mnChartFormat = rAttribs.getInteger( XML_chartFormat, 0 );
992 maDefModel.mnAutoFormatId = rAttribs.getInteger( XML_autoFormatId, 0 );
993 maDefModel.mbDataOnRows = rAttribs.getBool( XML_dataOnRows, false );
994 maDefModel.mbShowError = rAttribs.getBool( XML_showError, false );
995 maDefModel.mbShowMissing = rAttribs.getBool( XML_showMissing, true );
996 maDefModel.mbShowItems = rAttribs.getBool( XML_showItems, true );
997 maDefModel.mbDisableFieldList = rAttribs.getBool( XML_disableFieldList, false );
998 maDefModel.mbShowCalcMembers = rAttribs.getBool( XML_showCalcMbrs, true );
999 maDefModel.mbVisualTotals = rAttribs.getBool( XML_visualTotals, true );
1000 maDefModel.mbShowDrill = rAttribs.getBool( XML_showDrill, true );
1001 maDefModel.mbPrintDrill = rAttribs.getBool( XML_printDrill, false );
1002 maDefModel.mbEnableDrill = rAttribs.getBool( XML_enableDrill, true );
1003 maDefModel.mbPreserveFormatting = rAttribs.getBool( XML_preserveFormatting, true );
1004 maDefModel.mbUseAutoFormat = rAttribs.getBool( XML_useAutoFormatting, false );
1005 maDefModel.mbPageOverThenDown = rAttribs.getBool( XML_pageOverThenDown, false );
1006 maDefModel.mbSubtotalHiddenItems = rAttribs.getBool( XML_subtotalHiddenItems, false );
1007 maDefModel.mbRowGrandTotals = rAttribs.getBool( XML_rowGrandTotals, true );
1008 maDefModel.mbColGrandTotals = rAttribs.getBool( XML_colGrandTotals, true );
1009 maDefModel.mbFieldPrintTitles = rAttribs.getBool( XML_fieldPrintTitles, false );
1010 maDefModel.mbItemPrintTitles = rAttribs.getBool( XML_itemPrintTitles, false );
1011 maDefModel.mbMergeItem = rAttribs.getBool( XML_mergeItem, false );
1012 maDefModel.mbShowEmptyRow = rAttribs.getBool( XML_showEmptyRow, false );
1013 maDefModel.mbShowEmptyCol = rAttribs.getBool( XML_showEmptyCol, false );
1014 maDefModel.mbShowHeaders = rAttribs.getBool( XML_showHeaders, true );
1015 maDefModel.mbFieldListSortAsc = rAttribs.getBool( XML_fieldListSortAscending, false );
1016 maDefModel.mbCustomListSort = rAttribs.getBool( XML_customListSort, true );
1017 maDefModel.mbApplyNumFmt = rAttribs.getBool( XML_applyNumberFormats, false );
1018 maDefModel.mbApplyFont = rAttribs.getBool( XML_applyFontFormats, false );
1019 maDefModel.mbApplyAlignment = rAttribs.getBool( XML_applyAlignmentFormats, false );
1020 maDefModel.mbApplyBorder = rAttribs.getBool( XML_applyBorderFormats, false );
1021 maDefModel.mbApplyFill = rAttribs.getBool( XML_applyPatternFormats, false );
1022 // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
1023 maDefModel.mbApplyProtection = rAttribs.getBool( XML_applyWidthHeightFormats, false );
1024}
1025
1026void PivotTable::importLocation( const AttributeList& rAttribs, sal_Int16 nSheet )
1027{
1028 AddressConverter::convertToCellRangeUnchecked( maLocationModel.maRange, rAttribs.getString( XML_ref, OUString() ), nSheet );
1029 maLocationModel.mnFirstHeaderRow = rAttribs.getInteger( XML_firstHeaderRow, 0 );
1030 maLocationModel.mnFirstDataRow = rAttribs.getInteger( XML_firstDataRow, 0 );
1031 maLocationModel.mnFirstDataCol = rAttribs.getInteger( XML_firstDataCol, 0 );
1032 maLocationModel.mnRowPageCount = rAttribs.getInteger( XML_rowPageCount, 0 );
1033 maLocationModel.mnColPageCount = rAttribs.getInteger( XML_colPageCount, 0 );
1034}
1035
1037{
1038 importField( maRowFields, rAttribs );
1039}
1040
1042{
1043 importField( maColFields, rAttribs );
1044}
1045
1047{
1048 PTPageFieldModel aModel;
1049 aModel.maName = rAttribs.getXString( XML_name, OUString() );
1050 aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1051 // specification is wrong, XML_item is not the cache item, but the field item
1052 aModel.mnItem = rAttribs.getInteger( XML_item, BIFF12_PTPAGEFIELD_MULTIITEMS );
1053 maPageFields.push_back( aModel );
1054}
1055
1057{
1058 PTDataFieldModel aModel;
1059 aModel.maName = rAttribs.getXString( XML_name, OUString() );
1060 aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1061 aModel.mnSubtotal = rAttribs.getToken( XML_subtotal, XML_sum );
1062 aModel.mnShowDataAs = rAttribs.getToken( XML_showDataAs, XML_normal );
1063 aModel.mnBaseField = rAttribs.getInteger( XML_baseField, -1 );
1064 aModel.mnBaseItem = rAttribs.getInteger( XML_baseItem, -1 );
1065 aModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
1066 maDataFields.push_back( aModel );
1067}
1068
1069void PivotTable::putToInteropGrabBag(const OUString& sName, const AttributeList& rAttribs)
1070{
1071 if (auto xFastAttributeList = rAttribs.getFastAttributeList())
1072 {
1073 // Store both known and unknown attribute sequences to the grab bag as is
1074 css::uno::Sequence<css::xml::FastAttribute> aFast = xFastAttributeList->getFastAttributes();
1075 css::uno::Sequence<css::xml::Attribute> aUnk = xFastAttributeList->getUnknownAttributes();
1076 css::uno::Sequence<css::uno::Any> aVal{ css::uno::Any(aFast), css::uno::Any(aUnk) };
1077 maInteropGrabBag[sName] <<= aVal;
1078 }
1079}
1080
1082{
1083 sal_uInt32 nFlags1, nFlags2, nFlags3;
1084 sal_uInt8 nDataAxis;
1085 nFlags1 = rStrm.readuInt32();
1086 nFlags2 = rStrm.readuInt32();
1087 nFlags3 = rStrm.readuInt32();
1088 nDataAxis = rStrm.readuChar();
1089 maDefModel.mnPageWrap = rStrm.readuInt8();
1090 rStrm.skip( 2 ); // refresh versions
1091 maDefModel.mnDataPosition = rStrm.readInt32();
1092 maDefModel.mnAutoFormatId = rStrm.readuInt16();
1093 rStrm.skip( 2 ); // unused
1094 maDefModel.mnChartFormat = rStrm.readInt32();
1095 maDefModel.mnCacheId = rStrm.readInt32();
1097 if( getFlag( nFlags2, BIFF12_PTDEF_HASDATACAPTION ) )
1099 if( getFlag( nFlags2, BIFF12_PTDEF_HASGRANDTOTALCAPTION ) )
1101 if( !getFlag( nFlags3, BIFF12_PTDEF_NOERRORCAPTION ) ) // missing flag indicates existing string
1103 if( !getFlag( nFlags3, BIFF12_PTDEF_NOMISSINGCAPTION ) ) // missing flag indicates existing string
1105 if( getFlag( nFlags2, BIFF12_PTDEF_HASPAGESTYLE ) )
1107 if( getFlag( nFlags2, BIFF12_PTDEF_HASPIVOTTABLESTYLE ) )
1109 if( getFlag( nFlags2, BIFF12_PTDEF_HASVACATEDSTYLE ) )
1111 if( getFlag( nFlags2, BIFF12_PTDEF_HASTAG ) )
1113 if( getFlag( nFlags3, BIFF12_PTDEF_HASCOLHEADERCAPTION ) ) // TODO: right order (col/row)? spec is unclear
1115 if( getFlag( nFlags3, BIFF12_PTDEF_HASROWHEADERCAPTION ) )
1117
1119 (nDataAxis != BIFF12_PTDEF_ROWAXIS) && (nDataAxis != BIFF12_PTDEF_COLAXIS),
1120 "sc.filter",
1121 "PivotTable::importPTDefinition - unexpected axis position for data field");
1122
1123 maDefModel.mnIndent = extractValue< sal_uInt8 >( nFlags1, 24, 7 );
1124 maDefModel.mbDataOnRows = nDataAxis == BIFF12_PTDEF_ROWAXIS;
1125 maDefModel.mbShowError = getFlag( nFlags2, BIFF12_PTDEF_SHOWERROR );
1126 maDefModel.mbShowMissing = getFlag( nFlags2, BIFF12_PTDEF_SHOWMISSING );
1127 maDefModel.mbShowItems = getFlag( nFlags1, BIFF12_PTDEF_SHOWITEMS );
1128 maDefModel.mbDisableFieldList = getFlag( nFlags1, BIFF12_PTDEF_DISABLEFIELDLIST );
1129 maDefModel.mbShowCalcMembers = !getFlag( nFlags1, BIFF12_PTDEF_HIDECALCMEMBERS );
1130 maDefModel.mbVisualTotals = !getFlag( nFlags1, BIFF12_PTDEF_WITHHIDDENTOTALS );
1131 maDefModel.mbShowDrill = !getFlag( nFlags1, BIFF12_PTDEF_HIDEDRILL );
1132 maDefModel.mbPrintDrill = getFlag( nFlags1, BIFF12_PTDEF_PRINTDRILL );
1133 maDefModel.mbEnableDrill = getFlag( nFlags2, BIFF12_PTDEF_ENABLEDRILL );
1134 maDefModel.mbPreserveFormatting = getFlag( nFlags2, BIFF12_PTDEF_PRESERVEFORMATTING );
1135 maDefModel.mbUseAutoFormat = getFlag( nFlags2, BIFF12_PTDEF_USEAUTOFORMAT );
1136 maDefModel.mbPageOverThenDown = getFlag( nFlags2, BIFF12_PTDEF_PAGEOVERTHENDOWN );
1137 maDefModel.mbSubtotalHiddenItems = getFlag( nFlags2, BIFF12_PTDEF_SUBTOTALHIDDENITEMS );
1138 maDefModel.mbRowGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_ROWGRANDTOTALS );
1139 maDefModel.mbColGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_COLGRANDTOTALS );
1140 maDefModel.mbFieldPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_FIELDPRINTTITLES );
1141 maDefModel.mbItemPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_ITEMPRINTTITLES );
1142 maDefModel.mbMergeItem = getFlag( nFlags2, BIFF12_PTDEF_MERGEITEM );
1143 maDefModel.mbApplyNumFmt = getFlag( nFlags2, BIFF12_PTDEF_APPLYNUMFMT );
1144 maDefModel.mbApplyFont = getFlag( nFlags2, BIFF12_PTDEF_APPLYFONT );
1145 maDefModel.mbApplyAlignment = getFlag( nFlags2, BIFF12_PTDEF_APPLYALIGNMENT );
1146 maDefModel.mbApplyBorder = getFlag( nFlags2, BIFF12_PTDEF_APPLYBORDER );
1147 maDefModel.mbApplyFill = getFlag( nFlags2, BIFF12_PTDEF_APPLYFILL );
1148 maDefModel.mbApplyProtection = getFlag( nFlags2, BIFF12_PTDEF_APPLYPROTECTION );
1149 maDefModel.mbShowEmptyRow = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYROW );
1150 maDefModel.mbShowEmptyCol = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYCOL );
1151 maDefModel.mbShowHeaders = !getFlag( nFlags1, BIFF12_PTDEF_HIDEHEADERS );
1152 maDefModel.mbFieldListSortAsc = getFlag( nFlags3, BIFF12_PTDEF_FIELDLISTSORTASC );
1153 maDefModel.mbCustomListSort = !getFlag( nFlags3, BIFF12_PTDEF_NOCUSTOMLISTSORT );
1154}
1155
1157{
1158 BinRange aBinRange;
1159 rStrm >> aBinRange;
1161 maLocationModel.mnFirstDataRow = rStrm.readInt32();
1162 maLocationModel.mnFirstDataCol = rStrm.readInt32();
1163 maLocationModel.mnRowPageCount = rStrm.readInt32();
1164 maLocationModel.mnColPageCount = rStrm.readInt32();
1166}
1167
1169{
1171}
1172
1174{
1176}
1177
1179{
1180 PTPageFieldModel aModel;
1181 sal_uInt8 nFlags;
1182 aModel.mnField = rStrm.readInt32();
1183 aModel.mnItem = rStrm.readInt32();
1184 rStrm.skip( 4 ); // hierarchy
1185 nFlags = rStrm.readuChar();
1186 if( getFlag( nFlags, BIFF12_PTPAGEFIELD_HASNAME ) )
1187 rStrm >> aModel.maName;
1188 maPageFields.push_back( aModel );
1189}
1190
1192{
1193 PTDataFieldModel aModel;
1194 sal_Int32 nSubtotal, nShowDataAs;
1195 sal_uInt8 nHasName;
1196 aModel.mnField = rStrm.readInt32( );
1197 nSubtotal = rStrm.readInt32();
1198 nShowDataAs = rStrm.readInt32();
1199 aModel.mnBaseField = rStrm.readInt32();
1200 aModel.mnBaseItem = rStrm.readInt32();
1201 aModel.mnNumFmtId = rStrm.readInt32();
1202 nHasName = rStrm.readuChar();
1203 if( nHasName == 1 )
1204 rStrm >> aModel.maName;
1205 aModel.setBiffSubtotal( nSubtotal );
1206 aModel.setBiffShowDataAs( nShowDataAs );
1207 maDataFields.push_back( aModel );
1208}
1209
1211{
1212 sal_Int32 nFieldIndex = static_cast< sal_Int32 >( maFields.size() );
1213 PivotTableFieldVector::value_type xTableField = std::make_shared<PivotTableField>( *this, nFieldIndex );
1214 maFields.push_back( xTableField );
1215 return *xTableField;
1216}
1217
1219{
1220 PivotTableFilterVector::value_type xTableFilter = std::make_shared<PivotTableFilter>( *this );
1221 maFilters.push_back( xTableFilter );
1222 return *xTableFilter;
1223}
1224
1226{
1227 if( !getAddressConverter().validateCellRange( maLocationModel.maRange, true, true ) )
1228 return;
1229
1232 return;
1233
1234 // clear destination area of the original pivot table
1235 try
1236 {
1237 Reference< XSheetOperation > xSheetOp( getCellRangeFromDoc( maLocationModel.maRange ), UNO_QUERY_THROW );
1238 using namespace ::com::sun::star::sheet::CellFlags;
1239 xSheetOp->clearContents( VALUE | DATETIME | STRING | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED );
1240 }
1241 catch( Exception& )
1242 {
1243 }
1244
1245 try
1246 {
1247 // create a new data pilot descriptor based on the source data
1248 Reference< XDataPilotTablesSupplier > xDPTablesSupp( getSheetFromDoc( maLocationModel.maRange.aStart.Tab() ), UNO_QUERY_THROW );
1249 Reference< XDataPilotTables > xDPTables( xDPTablesSupp->getDataPilotTables(), UNO_SET_THROW );
1250 mxDPDescriptor.set( xDPTables->createDataPilotDescriptor(), UNO_SET_THROW );
1252 CellRangeAddress aCellRangeAddress( aRange.aStart.Tab(),
1253 aRange.aStart.Col(), aRange.aStart.Row(),
1254 aRange.aEnd.Col(), aRange.aEnd.Row() );
1255 mxDPDescriptor->setSourceRange( aCellRangeAddress );
1256 mxDPDescriptor->setTag( maDefModel.maTag );
1257
1258 // TODO: This is a hack. Eventually we need to convert the whole thing to the internal API.
1259 auto pImpl = dynamic_cast<ScDataPilotDescriptorBase*>(mxDPDescriptor.get());
1260 if (!pImpl)
1261 return;
1262
1263 mpDPObject = pImpl->GetDPObject();
1264 if (!mpDPObject)
1265 return;
1266
1267 // global data pilot properties
1268 PropertySet aDescProp( mxDPDescriptor );
1269 aDescProp.setProperty( PROP_ColumnGrand, maDefModel.mbColGrandTotals );
1270 aDescProp.setProperty( PROP_RowGrand, maDefModel.mbRowGrandTotals );
1271 aDescProp.setProperty( PROP_ShowFilterButton, false );
1272 aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill );
1273
1274 if (auto* pSaveData = mpDPObject->GetSaveData())
1275 pSaveData->SetExpandCollapse(maDefModel.mbShowDrill);
1276
1277 // finalize all fields, this finds field names and creates grouping fields
1279
1280 // all row fields
1281 for( const auto& rRowField : maRowFields )
1282 if( PivotTableField* pField = getTableField( rRowField ) )
1283 pField->convertRowField();
1284
1285 // all column fields
1286 for( const auto& rColField : maColFields )
1287 if( PivotTableField* pField = getTableField( rColField ) )
1288 pField->convertColField();
1289
1290 // all page fields
1291 for( const auto& rPageField : maPageFields )
1292 if( PivotTableField* pField = getTableField( rPageField.mnField ) )
1293 pField->convertPageField( rPageField );
1294
1295 // all hidden fields
1296 ::std::set< sal_Int32 > aVisFields;
1297 aVisFields.insert( maRowFields.begin(), maRowFields.end() );
1298 aVisFields.insert( maColFields.begin(), maColFields.end() );
1299 for( const auto& rPageField : maPageFields )
1300 aVisFields.insert( rPageField.mnField );
1301 sal_Int32 nIndex = 0;
1302 for( auto& rxField : maFields )
1303 {
1304 if( aVisFields.count( nIndex ) == 0 )
1305 rxField->convertHiddenField();
1306 ++nIndex;
1307 }
1308
1309 // all data fields
1310 for( auto& rDataField : maDataFields )
1311 {
1312 if( const PivotCacheField* pCacheField = getCacheField( rDataField.mnField ) )
1313 {
1314 if ( pCacheField-> getGroupBaseField() != -1 )
1315 rDataField.mnField = pCacheField-> getGroupBaseField();
1316 }
1317 if( PivotTableField* pField = getTableField( rDataField.mnField ) )
1318 pField->convertDataField( rDataField );
1319 }
1320
1321 // filters
1323
1324 // calculate base position of table
1326 /* If page fields exist, include them into the destination
1327 area (they are excluded in Excel). Add an extra blank row. */
1328 if( !maPageFields.empty() )
1329 aPos.Row = ::std::max< sal_Int32 >( static_cast< sal_Int32 >( aPos.Row - maPageFields.size() - 1 ), 0 );
1330
1331 // save interop grab bag
1333
1334 // insert the DataPilot table into the sheet
1335 xDPTables->insertNewByName( maDefModel.maName, aPos, mxDPDescriptor );
1336 }
1337 catch( Exception& )
1338 {
1339 TOOLS_WARN_EXCEPTION( "sc", "PivotTable::finalizeImport - exception while creating the DataPilot table" );
1340 }
1341}
1342
1344{
1345 if (maFields.empty())
1346 return;
1347
1348 /* Check whether group fields are already imported for another table
1349 sharing the same groups. */
1350 ScDPObject* pDPObj = getDPObject();
1351 const ScDocument& rDoc = getDocImport().getDoc();
1352 if (rDoc.HasPivotTable())
1353 {
1354 const ScDPCollection* pDPCollection = rDoc.GetDPCollection();
1355 assert(pDPCollection != nullptr);
1356 const ScDPDimensionSaveData* pGroups = nullptr;
1357 bool bRefFound = pDPCollection->GetReferenceGroups(*pDPObj, &pGroups);
1358 // Apply reference groups on this table.
1359 if (bRefFound && pGroups && pGroups->HasGroupDimensions()) {
1360 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1361 if (pSaveData) {
1362 pSaveData->SetDimensionData(pGroups);
1363 pDPObj->ReloadGroupTableData();
1365 return;
1366 }
1367
1368 }
1369 }
1371}
1372
1373void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
1374{
1375 // process all fields, there is no chaining information in the cache fields
1376 maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, ::std::cref(rxBaseDPField), nBaseFieldIdx );
1377}
1378
1379void PivotTable::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField,
1380 const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
1381{
1382 // try to create parent group fields that group the items of the passed base field
1383 if( PivotTableField* pParentTableField = maFields.get( rBaseCacheField.getParentGroupField() ).get() )
1384 pParentTableField->finalizeParentGroupingImport( rxBaseDPField, rBaseCacheField, orItemNames );
1385}
1386
1387Reference< XDataPilotField > PivotTable::getDataPilotField( const OUString& rFieldName ) const
1388{
1389 Reference< XDataPilotField > xDPField;
1390 if( !rFieldName.isEmpty() && mxDPDescriptor.is() ) try
1391 {
1392 Reference< XNameAccess > xDPFieldsNA( mxDPDescriptor->getDataPilotFields(), UNO_QUERY_THROW );
1393 xDPField.set( xDPFieldsNA->getByName( rFieldName ), UNO_QUERY );
1394 }
1395 catch( Exception& )
1396 {
1397 }
1398 return xDPField;
1399}
1400
1401Reference< XDataPilotField > PivotTable::getDataPilotField( sal_Int32 nFieldIdx ) const
1402{
1403 Reference< XDataPilotField > xDPField;
1404 if( const PivotTableField* pTableField = maFields.get( nFieldIdx ).get() )
1405 xDPField = getDataPilotField( pTableField->getDPFieldName() );
1406 return xDPField;
1407}
1408
1409Reference< XDataPilotField > PivotTable::getDataLayoutField() const
1410{
1411 Reference< XDataPilotField > xDPField;
1412 try
1413 {
1414 Reference< XDataPilotDataLayoutFieldSupplier > xDPDataFieldSupp( mxDPDescriptor, UNO_QUERY_THROW );
1415 xDPField = xDPDataFieldSupp->getDataLayoutField();
1416 }
1417 catch( Exception& )
1418 {
1419 }
1420 return xDPField;
1421}
1422
1424{
1425 return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1426}
1427
1428const PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx ) const
1429{
1430 return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1431}
1432
1433const PivotCacheField* PivotTable::getCacheFieldOfDataField( sal_Int32 nDataItemIdx ) const
1434{
1435 const PTDataFieldModel* pDataField = ContainerHelper::getVectorElement( maDataFields, nDataItemIdx );
1436 return pDataField ? getCacheField( pDataField->mnField ) : nullptr;
1437}
1438
1439sal_Int32 PivotTable::getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const
1440{
1441 return mpPivotCache ? mpPivotCache->getCacheDatabaseIndex( nFieldIdx ) : -1;
1442}
1443
1444// private --------------------------------------------------------------------
1445
1447{
1448 return (nFieldIdx == OOX_PT_DATALAYOUTFIELD) ? &maDataField : maFields.get( nFieldIdx ).get();
1449}
1450
1451void PivotTable::importField( IndexVector& orFields, const AttributeList& rAttribs )
1452{
1453 orFields.push_back( rAttribs.getInteger( XML_x, -1 ) );
1454}
1455
1457{
1458 OSL_ENSURE( orFields.empty(), "PivotTable::importFields - multiple record instances" );
1459 orFields.clear();
1460 sal_Int32 nCount = rStrm.readInt32();
1461 OSL_ENSURE( 4 * nCount == rStrm.getRemaining(), "PivotTable::importFields - invalid field count" );
1462 nCount = static_cast< sal_Int32 >( rStrm.getRemaining() / 4 );
1463 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1464 orFields.push_back( rStrm.readInt32() );
1465}
1466
1468 WorkbookHelper( rHelper )
1469{
1470}
1471
1473{
1474 PivotTableVector::value_type xTable = std::make_shared<PivotTable>( *this );
1475 maTables.push_back( xTable );
1476 return *xTable;
1477}
1478
1480{
1481 if(maTables.empty())
1482 return;
1483
1484 // Create formula groups. This needs to be done before pivot tables, because
1485 // import may lead to calling ScDPObject::GetSource(), which calls ScDPObject::CreateObjects(),
1486 // which will ensure all the cells are not dirty, causing recalculation even though
1487 // ScDPObject::GetSource() doesn't need it. And the recalculation is slower without formula
1488 // groups set up. Fixing that properly seems quite complex, given that do-everything approach
1489 // of ScDPObject, so at least ensure the calculation is efficient.
1490 ScDocument& rDoc = getDocImport().getDoc();
1491 rDoc.RegroupFormulaCells( ScRange( 0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), rDoc.GetMaxTableNumber()));
1492
1494}
1495
1496} // namespace oox
1497
1498/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SCTAB Tab() const
Definition: address.hxx:283
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject &rDPObj, const ScDPDimensionSaveData **pGroups) const
Definition: dpobject.cxx:3563
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:164
bool HasGroupDimensions() const
Definition: dpdimsave.cxx:693
void ReloadGroupTableData()
Definition: dpobject.cxx:810
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:141
void PutInteropGrabBag(std::map< OUString, css::uno::Any > &&val)
Definition: dpobject.hxx:265
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
Definition: dpsave.cxx:1211
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
Definition: dpsave.cxx:838
ScDPSaveMember * GetMemberByName(const OUString &rName)
Get a member object by its name.
Definition: dpsave.cxx:458
SC_DLLPUBLIC void SetIsVisible(bool bSet)
Definition: dpsave.cxx:97
SC_DLLPUBLIC void SetShowDetails(bool bSet)
Definition: dpsave.cxx:107
ScDocument & getDoc()
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:893
SC_DLLPUBLIC bool HasPivotTable() const
Definition: documen3.cxx:360
void RegroupFormulaCells(SCTAB nTab, SCCOL nCol)
Definition: document10.cxx:364
SCTAB GetMaxTableNumber() const
Definition: document.hxx:817
SC_DLLPUBLIC ScDPCollection * GetDPCollection()
Definition: documen3.cxx:365
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
std::optional< OUString > getXString(sal_Int32 nAttrToken) const
std::optional< sal_uInt32 > getUnsigned(sal_Int32 nAttrToken) const
std::optional< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
const css::uno::Reference< css::xml::sax::XFastAttributeList > & getFastAttributeList() const
std::optional< OUString > getString(sal_Int32 nAttrToken) const
std::optional< bool > getBool(sal_Int32 nAttrToken) const
std::optional< sal_Int32 > getToken(sal_Int32 nAttrToken) const
std::optional< double > getDouble(sal_Int32 nAttrToken) const
static const VectorType::value_type * getVectorElement(const VectorType &rVector, sal_Int32 nIndex)
bool is() const
bool setProperty(sal_Int32 nPropId, const Type &rValue)
value_type get(sal_Int32 nIndex) const
void forEachMem(FuncType pFunc) const
container_type::value_type value_type
static bool convertToCellRangeUnchecked(ScRange &orRange, std::u16string_view aString, sal_Int16 nSheet)
Converts the passed string to a cell range address, without checking any sheet limits.
PivotCache * importPivotCacheFragment(sal_Int32 nCacheId)
Imports and stores a pivot cache definition fragment on first call, returns the imported cache on sub...
OUString createParentGroupField(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, const PivotCacheField &rBaseCacheField, PivotCacheGroupItemVector &orItemNames) const
Creates a new grouped DataPilot field and returns its name.
const PivotCacheItem * getCacheItem(sal_Int32 nItemIdx) const
Returns the shared or group item with the specified index.
const OUString & getName() const
Returns the name of the cache field.
sal_Int32 getParentGroupField() const
Returns the index of the parent group field that groups the items of this field.
void applyItemCaptions(const IdCaptionPairList &vCaptions)
Apply user Captions to imported group data.
void setFinalGroupName(const OUString &rFinalGroupName)
Set the finalized group name of this field.
OUString getFormattedName(const ScDPSaveDimension &rSaveDim, ScDPObject *pObj, const DateTime &rNullDate) const
Returns the string representation of the item, using the actual formatting.
PivotCacheField * getCacheField(sal_Int32 nFieldIdx)
Returns the cache field with the specified index.
const ScRange & getSourceRange() const
Returns the internal cell range the cache is based on.
bool isValidDataSource() const
Returns true, if the pivot cache is based on a valid data source, so that pivot tables can be created...
sal_Int32 getCacheDatabaseIndex(sal_Int32 nFieldIdx) const
Returns the source column index of the field with the passed index.
PivotTableBuffer(const WorkbookHelper &rHelper)
PivotTable & createPivotTable()
Creates and returns a new pivot table.
void finalizeImport()
Inserts all pivot tables into the sheet.
void importPTReference(SequenceInputStream &rStrm)
Imports pivot field reference settings from the PTREFERENCE record.
sal_Int32 mnFieldIndex
Name of the field in DataPilot field collection.
void convertHiddenField()
Converts dimension and other settings for a hidden field.
void convertRowField()
Converts dimension and other settings for a row field.
void convertColField()
Converts dimension and other settings for a column field.
void finalizeImport(const css::uno::Reference< css::sheet::XDataPilotDescriptor > &rxDPDesc)
Finalizes the field after import, creates grouping and other settings.
void importPivotField(const AttributeList &rAttribs)
Imports pivot field settings from the pivotField element.
void convertPageField(const PTPageFieldModel &rPageField)
Converts dimension and other settings for a page field.
void finalizeDateGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, sal_Int32 nBaseFieldIdx)
Finalizes the grouped date field after import.
void importReference(const AttributeList &rAttribs)
Imports pivot field reference settings from the reference element.
void importReferenceItem(const AttributeList &rAttribs)
Imports pivot field item reference settings from the x element.
void importPTFItem(SequenceInputStream &rStrm)
Imports settings of an item in this pivot field from the PTFITEM record.
void finalizeImportBasedOnCache(const css::uno::Reference< css::sheet::XDataPilotDescriptor > &rxDPDesc)
void finalizeParentGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, const PivotCacheField &rBaseCacheField, PivotCacheGroupItemVector &orItemNames)
Finalizes the grouped field after import.
OUString maDPFieldName
Pivot field settings.
void importItem(const AttributeList &rAttribs)
Imports settings of an item in this pivot field from the item element.
PivotTableField(PivotTable &rPivotTable, sal_Int32 nFieldIndex)
css::uno::Reference< css::sheet::XDataPilotField > convertRowColPageField(sal_Int32 nAxis)
Converts dimension and other settings for row, column, page, or hidden fields.
ItemModelVector maItems
The parent pivot table object.
void importPTReferenceItem(SequenceInputStream &rStrm)
Imports pivot field item reference settings from the PTREFERENCEITEM record.
void convertDataField(const PTDataFieldModel &rDataField)
Converts dimension and other settings for a data field.
void importPTField(SequenceInputStream &rStrm)
Imports pivot field settings from the PTFIELD record.
PTFieldModel maModel
All items of this field.
PivotTableFilter(const PivotTable &rPivotTable)
void importFilter(const AttributeList &rAttribs)
Reads the settings of a field filter from the filter element.
void finalizeImport()
Applies the filter to the associated pivot table field if possible.
void importTop10Filter(SequenceInputStream &rStrm)
Reads additional settings of a field filter from the TOP10FILTER record.
void importPTFilter(SequenceInputStream &rStrm)
Reads the settings of a field filter from the PTFILTER record.
const PivotTable & mrPivotTable
void importTop10(const AttributeList &rAttribs)
Reads additional settings of a field filter from the top10 element.
void importPTDataField(SequenceInputStream &rStrm)
Reads the settings of a field located in the data dimension from the PTDATAFIELD record.
void finalizeImport()
Inserts the pivot table into the sheet.
void importDataField(const AttributeList &rAttribs)
Reads the settings of a field located in the data dimension from the dataField element.
PTLocationModel maLocationModel
Global pivot table settings.
css::uno::Reference< css::sheet::XDataPilotField > getDataLayoutField() const
Returns the data layout field used to store all data fields in row/col dimension.
IndexVector maColFields
Indexes to fields in row dimension.
css::uno::Reference< css::sheet::XDataPilotField > getDataPilotField(const OUString &rFieldName) const
Returns the associated data pilot field for the specified pivot table field.
PivotTableField & createTableField()
Creates and returns a new pivot table field.
void importPivotTableDefinition(const AttributeList &rAttribs)
Reads global pivot table settings from the pivotTableDefinition element.
void importLocation(const AttributeList &rAttribs, sal_Int16 nSheet)
Reads the location of the pivot table from the location element.
::std::vector< sal_Int32 > IndexVector
static void importField(IndexVector &orFields, const AttributeList &rAttribs)
Reads a field index for the row or column dimension.
sal_Int32 getCacheDatabaseIndex(sal_Int32 nFieldIdx) const
Returns the source column index of the pivot field with the passed index, or -1.
void finalizeDateGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, sal_Int32 nBaseFieldIdx)
Creates all date group fields for the specified cache field after import.
PivotTableFilterVector maFilters
Settings for all fields in data area.
PivotTableFieldVector maFields
static void importFields(IndexVector &orFields, SequenceInputStream &rStrm)
Reads an array of field indexes for the row or column dimension.
DataFieldVector maDataFields
Settings for all fields in page dimension.
ScDPObject * getDPObject()
PivotTable(const WorkbookHelper &rHelper)
void putToInteropGrabBag(const OUString &sName, const AttributeList &rAttribs)
Puts the attributes to the named grab bag value.
void importPTLocation(SequenceInputStream &rStrm, sal_Int16 nSheet)
Reads the location of the pivot table from the PTLOCATION record.
void finalizeParentGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, const PivotCacheField &rBaseCacheField, PivotCacheGroupItemVector &orItemNames)
Creates all grouped fields for the specified cache field after import.
void importColField(const AttributeList &rAttribs)
Reads the index of a field located in the column dimension.
PivotCacheField * getCacheField(sal_Int32 nFieldIdx)
Returns the cache field with the specified index.
PTDefinitionModel maDefModel
All field filters.
const PivotCacheField * getCacheFieldOfDataField(sal_Int32 nDataItemIdx) const
Returns the base cache field of the data field item with the specified index.
void importPTPageField(SequenceInputStream &rStrm)
Reads the settings of a field located in the page dimension from the PTPAGEFIELD record.
css::uno::Reference< css::sheet::XDataPilotDescriptor > mxDPDescriptor
The pivot cache this table is based on.
PivotCache * mpPivotCache
Location settings of the pivot table.
void importRowField(const AttributeList &rAttribs)
Reads the index of a field located in the row dimension.
PivotTableFilter & createTableFilter()
Creates and returns a new pivot table filter.
void importPTRowFields(SequenceInputStream &rStrm)
Reads the indexes of all fields located in the row dimension from a PTROWFIELDS record.
void importPageField(const AttributeList &rAttribs)
Reads the settings of a field located in the page dimension from the pageField element.
IndexVector maRowFields
Data layout field.
std::map< OUString, css::uno::Any > maInteropGrabBag
Descriptor of the DataPilot object.
void importPTColFields(SequenceInputStream &rStrm)
Reads the indexes of all fields located in the column dimension from a PTCOLFIELDS record.
PivotTableField * getTableField(sal_Int32 nFieldIdx)
Returns a pivot table field by its index.
void importPTDefinition(SequenceInputStream &rStrm)
Reads global pivot table settings from the PTDEFINITION record.
void finalizeFieldsImport()
Finalizes all fields, finds field names and creates grouping fields.
PageFieldVector maPageFields
Indexes to fields in column dimension.
PivotTableField maDataField
All pivot table fields.
Helper class to provide access to global workbook data.
css::uno::Reference< css::sheet::XSpreadsheet > getSheetFromDoc(sal_Int32 nSheet) const
Returns a reference to the specified spreadsheet in the document model.
PivotCacheBuffer & getPivotCaches() const
Returns the collection of pivot caches.
AddressConverter & getAddressConverter() const
Returns the converter for string to cell address/range conversion.
WorkbookSettings & getWorkbookSettings() const
Returns the global workbook settings object.
css::uno::Reference< css::table::XCellRange > getCellRangeFromDoc(const ScRange &rRange) const
Returns the XCellRange interface for the passed cell range address.
ScDocumentImport & getDocImport()
int nCount
sal_uInt16 mnId
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString sName
@ EDITATTR
Drawing objects.
@ HARDATTR
Formula cells.
STRING
#define STATIC_ARRAY_SELECT(array, index, def)
sal_Int32 nIndex
#define SAL_WARN_IF(condition, area, stream)
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
void SvStream & rStrm
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
::std::vector< IdCaptionPair > IdCaptionPairList
::std::vector< PivotCacheGroupItem > PivotCacheGroupItemVector
bool getFlag(Type nBitField, Type nMask)
XML_type
XML_TOKEN_INVALID
sal_Int32 mnNumFmtId
const PPTXLayoutInfo aLayoutInfo[LAYOUT_SIZE]
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
sal_Int32 mnType
bool mbApplyAlignment
True = apply font from autoformatting.
bool mbApplyNumFmt
Index of predefined autoformatting.
bool mbApplyFill
True = apply border from autoformatting.
bool mbApplyBorder
True = apply alignment from autoformatting.
bool mbApplyProtection
True = apply fill from autoformatting.
bool mbApplyFont
True = apply number format from autoformatting.
A 2D cell range address struct for binary filters.
sal_Int32 mnShowDataAs
Subtotal aggregation function.
sal_Int32 mnBaseField
Show data as, based on another field.
sal_Int32 mnSubtotal
Base pivot field.
void setBiffSubtotal(sal_Int32 nSubtotal)
Sets the subtotal aggregation function for BIFF import.
sal_Int32 mnBaseItem
Base field for 'show data as'.
void setBiffShowDataAs(sal_Int32 nShowDataAs)
Sets the 'show data as' type for BIFF import.
sal_Int32 mnField
Name of the data field.
sal_Int32 mnNumFmtId
Base item for 'show data as'.
PTDataFieldModel()
Number format for the result.
bool mbShowDetails
User caption of the item.
sal_Int32 mnType
Index to shared item in pivot cache.
PTFieldItemModel()
True = item is hidden.
OUString msCaption
Type of the item.
void setBiffType(sal_uInt16 nType)
Sets item type for BIFF import.
bool mbHidden
True = show item details (items of child fields).
bool mbVarSubtotal
True = show standard deviation of population subtotals.
bool mbCountASubtotal
True = show sum subtotals.
bool mbAutoShow
True = insert page breaks after items.
bool mbStdDevSubtotal
True = show count numbers subtotals.
bool mbVarPSubtotal
True = show variance subtotals.
bool mbProductSubtotal
True = show minimum subtotals.
bool mbTopAutoShow
True = auto show (top 10) filter enabled.
bool mbSumSubtotal
True = show default subtotals.
sal_Int32 mnSortRefField
Autosorting type.
void setBiffAxis(sal_uInt8 nAxisFlags)
Sets axis type for BIFF import.
sal_Int32 mnSortType
Index of the data field auto show filter is based on.
bool mbDataField
Item in reference field for autosorting.
sal_Int32 mnAutoShowRankBy
Number of items (or percent/sum) to be shown in auto show filter.
bool mbInsertPageBreak
True = insert blank rows after items.
bool mbStdDevPSubtotal
True = show standard deviation subtotals.
sal_Int32 mnNumFmtId
Axis this field is assigned to (none, row, column, page).
sal_Int32 mnSortRefItem
Reference field for autosorting.
bool mbSubtotalTop
True = show in outline view, false = show in tabular view.
bool mbCountSubtotal
True = show product subtotals.
bool mbMultiPageItems
True = auto show filter shows top entries, false = bottom.
bool mbDefaultSubtotal
True = field appears in data area.
bool mbOutline
True = show items without data.
sal_Int32 mnAutoShowItems
Number format for field items.
PTFieldModel()
True = multiple items selectable in page dimension.
bool mbInsertBlankRow
True = show in compact view, false = show in either outline or tabular view.
bool mbAverageSubtotal
True = show count all subtotals.
bool mbShowAll
True = show variance of population subtotals.
bool mbMinSubtotal
True = show maximum subtotals.
bool mbCompact
True = show subtotals on top of items in outline or compact mode.
bool mbMaxSubtotal
True = show average subtotals.
double mfValue
Second string value for label filter.
sal_Int32 mnMeasureHier
Data field for filter calculation.
sal_Int32 mnMemPropField
Base pivot field.
bool mbTopFilter
Hierarchy for filter calculation.
sal_Int32 mnEvalOrder
Filter type.
sal_Int32 mnId
Evaluation order index.
sal_Int32 mnType
Member property field.
PTFilterModel()
True = filter shows top entries, false = bottom.
OUString maStrValue2
First string value for label filter.
OUString maStrValue1
Description of the field filter.
sal_Int32 mnField
Number of items or percent or sum to be shown.
sal_Int32 mnMeasureField
Unique identifier.
OUString maDescription
Name of the field filter.
sal_Int32 mnRowPageCount
First column of data cells (relative in pivot table).
sal_Int32 mnFirstDataCol
First row of data cells (relative in pivot table).
sal_Int32 mnFirstHeaderRow
Target cell range for the pivot table.
sal_Int32 mnFirstDataRow
First row of header cells (relative in pivot table).
sal_Int32 mnColPageCount
Number of rows in page filter area.
PTLocationModel()
Number of columns in page filter area.
sal_Int32 mnItem
Base pivot field.
PTPageFieldModel()
Index of field item that is shown by the page field.
sal_Int32 mnField
Unique name of the page field.
unsigned char sal_uInt8
#define SAL_MAX_INT32
#define SAL_MAX_UINT32