1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "pivotcachebuffer.hxx"
23 #include <com/sun/star/container/XIndexAccess.hpp>
24 #include <com/sun/star/container/XNameAccess.hpp>
25 #include <com/sun/star/container/XNamed.hpp>
26 #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
27 #include <com/sun/star/sheet/DataPilotFieldGroupInfo.hpp>
28 #include <com/sun/star/sheet/XDataPilotFieldGrouping.hpp>
29 #include <osl/diagnose.h>
30 #include <rtl/ustrbuf.hxx>
31 #include <oox/core/filterbase.hxx>
32 #include <oox/helper/attributelist.hxx>
33 #include <oox/helper/containerhelper.hxx>
34 #include <oox/helper/propertyset.hxx>
35 #include <oox/token/properties.hxx>
36 #include "biffinputstream.hxx"
37 #include "defnamesbuffer.hxx"
38 #include "excelhandlers.hxx"
39 #include "pivotcachefragment.hxx"
40 #include "sheetdatabuffer.hxx"
41 #include "tablebuffer.hxx"
42 #include "unitconverter.hxx"
43 #include "worksheetbuffer.hxx"
48 using namespace ::com::sun::star::container
;
49 using namespace ::com::sun::star::sheet
;
50 using namespace ::com::sun::star::table
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::util
;
54 using ::oox::core::Relations
;
58 const sal_uInt16 BIFF12_PCDFIELD_SERVERFIELD
= 0x0001;
59 const sal_uInt16 BIFF12_PCDFIELD_NOUNIQUEITEMS
= 0x0002;
60 const sal_uInt16 BIFF12_PCDFIELD_DATABASEFIELD
= 0x0004;
61 const sal_uInt16 BIFF12_PCDFIELD_HASCAPTION
= 0x0008;
62 const sal_uInt16 BIFF12_PCDFIELD_MEMBERPROPFIELD
= 0x0010;
63 const sal_uInt16 BIFF12_PCDFIELD_HASFORMULA
= 0x0100;
64 const sal_uInt16 BIFF12_PCDFIELD_HASPROPERTYNAME
= 0x0200;
66 const sal_uInt16 BIFF12_PCDFSITEMS_HASSEMIMIXED
= 0x0001;
67 const sal_uInt16 BIFF12_PCDFSITEMS_HASNONDATE
= 0x0002;
68 const sal_uInt16 BIFF12_PCDFSITEMS_HASDATE
= 0x0004;
69 const sal_uInt16 BIFF12_PCDFSITEMS_HASSTRING
= 0x0008;
70 const sal_uInt16 BIFF12_PCDFSITEMS_HASBLANK
= 0x0010;
71 const sal_uInt16 BIFF12_PCDFSITEMS_HASMIXED
= 0x0020;
72 const sal_uInt16 BIFF12_PCDFSITEMS_ISNUMERIC
= 0x0040;
73 const sal_uInt16 BIFF12_PCDFSITEMS_ISINTEGER
= 0x0080;
74 const sal_uInt16 BIFF12_PCDFSITEMS_HASLONGTEXT
= 0x0200;
76 const sal_uInt16 BIFF12_PCITEM_ARRAY_DOUBLE
= 0x0001;
77 const sal_uInt16 BIFF12_PCITEM_ARRAY_STRING
= 0x0002;
78 const sal_uInt16 BIFF12_PCITEM_ARRAY_ERROR
= 0x0010;
79 const sal_uInt16 BIFF12_PCITEM_ARRAY_DATE
= 0x0020;
81 const sal_uInt8 BIFF12_PCDFRANGEPR_AUTOSTART
= 0x01;
82 const sal_uInt8 BIFF12_PCDFRANGEPR_AUTOEND
= 0x02;
83 const sal_uInt8 BIFF12_PCDFRANGEPR_DATEGROUP
= 0x04;
85 const sal_uInt8 BIFF12_PCDEFINITION_SAVEDATA
= 0x01;
86 const sal_uInt8 BIFF12_PCDEFINITION_INVALID
= 0x02;
87 const sal_uInt8 BIFF12_PCDEFINITION_REFRESHONLOAD
= 0x04;
88 const sal_uInt8 BIFF12_PCDEFINITION_OPTIMIZEMEMORY
= 0x08;
89 const sal_uInt8 BIFF12_PCDEFINITION_ENABLEREFRESH
= 0x10;
90 const sal_uInt8 BIFF12_PCDEFINITION_BACKGROUNDQUERY
= 0x20;
91 const sal_uInt8 BIFF12_PCDEFINITION_UPGRADEONREFR
= 0x40;
92 const sal_uInt8 BIFF12_PCDEFINITION_TUPELCACHE
= 0x80;
94 const sal_uInt8 BIFF12_PCDEFINITION_HASUSERNAME
= 0x01;
95 const sal_uInt8 BIFF12_PCDEFINITION_HASRELID
= 0x02;
96 const sal_uInt8 BIFF12_PCDEFINITION_SUPPORTSUBQUERY
= 0x04;
97 const sal_uInt8 BIFF12_PCDEFINITION_SUPPORTDRILL
= 0x08;
99 const sal_uInt8 BIFF12_PCDWBSOURCE_HASRELID
= 0x01;
100 const sal_uInt8 BIFF12_PCDWBSOURCE_HASSHEET
= 0x02;
102 const sal_uInt16 BIFF_PC_NOSTRING
= 0xFFFF;
104 const sal_uInt16 BIFF_PCDFIELD_HASITEMS
= 0x0001;
105 const sal_uInt16 BIFF_PCDFIELD_HASPARENT
= 0x0008;
106 const sal_uInt16 BIFF_PCDFIELD_RANGEGROUP
= 0x0010;
107 const sal_uInt16 BIFF_PCDFIELD_ISNUMERIC
= 0x0020;
108 const sal_uInt16 BIFF_PCDFIELD_HASSEMIMIXED
= 0x0080;
109 const sal_uInt16 BIFF_PCDFIELD_HASLONGINDEX
= 0x0200;
110 const sal_uInt16 BIFF_PCDFIELD_HASNONDATE
= 0x0400;
111 const sal_uInt16 BIFF_PCDFIELD_HASDATE
= 0x0800;
112 const sal_uInt16 BIFF_PCDFIELD_SERVERFIELD
= 0x2000;
113 const sal_uInt16 BIFF_PCDFIELD_NOUNIQUEITEMS
= 0x4000;
115 const sal_uInt16 BIFF_PCDFRANGEPR_AUTOSTART
= 0x0001;
116 const sal_uInt16 BIFF_PCDFRANGEPR_AUTOEND
= 0x0002;
118 const sal_uInt16 BIFF_PCDEFINITION_SAVEDATA
= 0x0001;
119 const sal_uInt16 BIFF_PCDEFINITION_INVALID
= 0x0002;
120 const sal_uInt16 BIFF_PCDEFINITION_REFRESHONLOAD
= 0x0004;
121 const sal_uInt16 BIFF_PCDEFINITION_OPTIMIZEMEMORY
= 0x0008;
122 const sal_uInt16 BIFF_PCDEFINITION_BACKGROUNDQUERY
= 0x0010;
123 const sal_uInt16 BIFF_PCDEFINITION_ENABLEREFRESH
= 0x0020;
125 /** Adjusts the weird date format read from binary streams.
127 Dates before 1900-Mar-01 are stored including the non-existing leap day
128 1900-02-29. tools::Time values (without date) are stored as times of day
129 1900-Jan-00. Nothing has to be done when the workbook is stored in 1904
130 date mode (dates before 1904-Jan-01 will not occur in this case).
132 void lclAdjustBinDateTime( css::util::DateTime
& orDateTime
)
134 if( (orDateTime
.Year
== 1900) && (orDateTime
.Month
<= 2) )
136 OSL_ENSURE( (orDateTime
.Month
== 1) || ((orDateTime
.Month
== 2) && (orDateTime
.Day
> 0)), "lclAdjustBinDateTime - invalid date" );
137 switch( orDateTime
.Month
)
139 case 2: if( orDateTime
.Day
> 1 ) --orDateTime
.Day
; else { orDateTime
.Day
+= 30; --orDateTime
.Month
; } break;
140 case 1: if( orDateTime
.Day
> 1 ) --orDateTime
.Day
; else { orDateTime
.Day
+= 30; orDateTime
.Month
= 12; --orDateTime
.Year
; } break;
147 PivotCacheItem::PivotCacheItem() :
148 mnType( XML_m
), mbUnused( false )
152 void PivotCacheItem::readString( const AttributeList
& rAttribs
)
154 maValue
<<= rAttribs
.getXString( XML_v
, OUString() );
158 void PivotCacheItem::readNumeric( const AttributeList
& rAttribs
)
160 maValue
<<= rAttribs
.getDouble( XML_v
, 0.0 );
162 mbUnused
= rAttribs
.getBool( XML_u
, false );
165 void PivotCacheItem::readDate( const AttributeList
& rAttribs
)
167 maValue
<<= rAttribs
.getDateTime( XML_v
, css::util::DateTime() );
171 void PivotCacheItem::readBool( const AttributeList
& rAttribs
)
173 maValue
<<= rAttribs
.getBool( XML_v
, false );
177 void PivotCacheItem::readError( const AttributeList
& rAttribs
, const UnitConverter
& rUnitConverter
)
179 maValue
<<= static_cast< sal_Int32
>( rUnitConverter
.calcBiffErrorCode( rAttribs
.getXString( XML_v
, OUString() ) ) );
183 void PivotCacheItem::readIndex( const AttributeList
& rAttribs
)
185 maValue
<<= rAttribs
.getInteger( XML_v
, -1 );
189 void PivotCacheItem::readString( SequenceInputStream
& rStrm
)
191 maValue
<<= BiffHelper::readString( rStrm
);
195 void PivotCacheItem::readDouble( SequenceInputStream
& rStrm
)
197 maValue
<<= rStrm
.readDouble();
201 void PivotCacheItem::readDate( SequenceInputStream
& rStrm
)
203 css::util::DateTime aDateTime
;
204 aDateTime
.Year
= rStrm
.readuInt16();
205 aDateTime
.Month
= rStrm
.readuInt16();
206 aDateTime
.Day
= rStrm
.readuInt8();
207 aDateTime
.Hours
= rStrm
.readuInt8();
208 aDateTime
.Minutes
= rStrm
.readuInt8();
209 aDateTime
.Seconds
= rStrm
.readuInt8();
210 lclAdjustBinDateTime( aDateTime
);
211 maValue
<<= aDateTime
;
215 void PivotCacheItem::readBool( SequenceInputStream
& rStrm
)
217 maValue
<<= (rStrm
.readuInt8() != 0);
221 void PivotCacheItem::readError( SequenceInputStream
& rStrm
)
223 maValue
<<= static_cast< sal_Int32
>( rStrm
.readuInt8() );
227 void PivotCacheItem::readIndex( SequenceInputStream
& rStrm
)
229 maValue
<<= rStrm
.readInt32();
233 void PivotCacheItem::readString( BiffInputStream
& rStrm
, const WorkbookHelper
& rHelper
)
235 maValue
<<= (rHelper
.getBiff() == BIFF8
) ? rStrm
.readUniString() : rStrm
.readByteStringUC( true, rHelper
.getTextEncoding() );
239 void PivotCacheItem::readDouble( BiffInputStream
& rStrm
)
241 maValue
<<= rStrm
.readDouble();
245 void PivotCacheItem::readInteger( BiffInputStream
& rStrm
)
247 maValue
<<= rStrm
.readInt16();
248 mnType
= XML_i
; // fake, used for BIFF only
251 void PivotCacheItem::readDate( BiffInputStream
& rStrm
)
253 css::util::DateTime aDateTime
;
254 aDateTime
.Year
= rStrm
.readuInt16();
255 aDateTime
.Month
= rStrm
.readuInt16();
256 aDateTime
.Day
= rStrm
.readuInt8();
257 aDateTime
.Hours
= rStrm
.readuInt8();
258 aDateTime
.Minutes
= rStrm
.readuInt8();
259 aDateTime
.Seconds
= rStrm
.readuInt8();
260 lclAdjustBinDateTime( aDateTime
);
261 maValue
<<= aDateTime
;
265 void PivotCacheItem::readBool( BiffInputStream
& rStrm
)
267 maValue
<<= (rStrm
.readuInt8() != 0);
271 void PivotCacheItem::readError( BiffInputStream
& rStrm
)
273 maValue
<<= static_cast< sal_Int32
>( rStrm
.readuInt8() );
277 void PivotCacheItem::setStringValue( const OUString
& sString
)
283 OUString
PivotCacheItem::getName() const
287 case XML_m
: return OUString();
288 case XML_s
: return maValue
.get
< OUString
>();
289 case XML_n
: return OUString::number( maValue
.get
< double >() ); // !TODO
290 case XML_i
: return OUString::number( maValue
.get
< sal_Int32
>() );
291 case XML_d
: return OUString(); // !TODO
292 case XML_b
: return OUString::boolean( maValue
.get
< bool >() ); // !TODO
293 case XML_e
: return OUString(); // !TODO
295 OSL_FAIL( "PivotCacheItem::getName - invalid data type" );
299 PivotCacheItemList::PivotCacheItemList( const WorkbookHelper
& rHelper
) :
300 WorkbookHelper( rHelper
)
304 void PivotCacheItemList::importItem( sal_Int32 nElement
, const AttributeList
& rAttribs
)
306 PivotCacheItem
& rItem
= createItem();
309 case XLS_TOKEN( m
): break;
310 case XLS_TOKEN( s
): rItem
.readString( rAttribs
); break;
311 case XLS_TOKEN( n
): rItem
.readNumeric( rAttribs
); break;
312 case XLS_TOKEN( d
): rItem
.readDate( rAttribs
); break;
313 case XLS_TOKEN( b
): rItem
.readBool( rAttribs
); break;
314 case XLS_TOKEN( e
): rItem
.readError( rAttribs
, getUnitConverter() ); break;
315 default: OSL_FAIL( "PivotCacheItemList::importItem - unknown element type" );
319 void PivotCacheItemList::importItem( sal_Int32 nRecId
, SequenceInputStream
& rStrm
)
321 if( nRecId
== BIFF12_ID_PCITEM_ARRAY
)
323 importArray( rStrm
);
327 PivotCacheItem
& rItem
= createItem();
330 case BIFF12_ID_PCITEM_MISSING
:
331 case BIFF12_ID_PCITEMA_MISSING
: break;
332 case BIFF12_ID_PCITEM_STRING
:
333 case BIFF12_ID_PCITEMA_STRING
: rItem
.readString( rStrm
); break;
334 case BIFF12_ID_PCITEM_DOUBLE
:
335 case BIFF12_ID_PCITEMA_DOUBLE
: rItem
.readDouble( rStrm
); break;
336 case BIFF12_ID_PCITEM_DATE
:
337 case BIFF12_ID_PCITEMA_DATE
: rItem
.readDate( rStrm
); break;
338 case BIFF12_ID_PCITEM_BOOL
:
339 case BIFF12_ID_PCITEMA_BOOL
: rItem
.readBool( rStrm
); break;
340 case BIFF12_ID_PCITEM_ERROR
:
341 case BIFF12_ID_PCITEMA_ERROR
: rItem
.readError( rStrm
); break;
342 default: OSL_FAIL( "PivotCacheItemList::importItem - unknown record type" );
346 void PivotCacheItemList::importItemList( BiffInputStream
& rStrm
, sal_uInt16 nCount
)
349 for( sal_uInt16 nItemIdx
= 0; bLoop
&& (nItemIdx
< nCount
); ++nItemIdx
)
351 bLoop
= rStrm
.startNextRecord();
352 if( bLoop
) switch( rStrm
.getRecId() )
354 case BIFF_ID_PCITEM_MISSING
: createItem(); break;
355 case BIFF_ID_PCITEM_STRING
: createItem().readString( rStrm
, *this ); break;
356 case BIFF_ID_PCITEM_DOUBLE
: createItem().readDouble( rStrm
); break;
357 case BIFF_ID_PCITEM_INTEGER
: createItem().readInteger( rStrm
); break;
358 case BIFF_ID_PCITEM_DATE
: createItem().readDate( rStrm
); break;
359 case BIFF_ID_PCITEM_BOOL
: createItem().readBool( rStrm
); break;
360 case BIFF_ID_PCITEM_ERROR
: createItem().readError( rStrm
); break;
361 default: rStrm
.rewindRecord(); bLoop
= false;
364 OSL_ENSURE( bLoop
, "PivotCacheItemList::importItemList - could not read all cache item records" );
367 const PivotCacheItem
* PivotCacheItemList::getCacheItem( sal_Int32 nItemIdx
) const
369 return ContainerHelper::getVectorElement( maItems
, nItemIdx
);
372 void PivotCacheItemList::applyItemCaptions( const IdCaptionPairList
& vCaptions
)
374 for( IdCaptionPairList::const_iterator aIt
= vCaptions
.begin(), aEnd
= vCaptions
.end(); aIt
!= aEnd
; ++aIt
)
376 if ( static_cast<sal_uInt32
>( aIt
->first
) < maItems
.size() )
377 maItems
[ aIt
->first
].setStringValue( aIt
->second
);
381 void PivotCacheItemList::getCacheItemNames( ::std::vector
< OUString
>& orItemNames
) const
384 orItemNames
.reserve( maItems
.size() );
385 for( CacheItemVector::const_iterator aIt
= maItems
.begin(), aEnd
= maItems
.end(); aIt
!= aEnd
; ++aIt
)
386 orItemNames
.push_back( aIt
->getName() );
389 // private --------------------------------------------------------------------
391 PivotCacheItem
& PivotCacheItemList::createItem()
393 maItems
.resize( maItems
.size() + 1 );
394 return maItems
.back();
397 void PivotCacheItemList::importArray( SequenceInputStream
& rStrm
)
399 sal_uInt16 nType
= rStrm
.readuInt16();
400 sal_Int32 nCount
= rStrm
.readInt32();
401 for( sal_Int32 nIdx
= 0; !rStrm
.isEof() && (nIdx
< nCount
); ++nIdx
)
405 case BIFF12_PCITEM_ARRAY_DOUBLE
: createItem().readDouble( rStrm
); break;
406 case BIFF12_PCITEM_ARRAY_STRING
: createItem().readString( rStrm
); break;
407 case BIFF12_PCITEM_ARRAY_ERROR
: createItem().readError( rStrm
); break;
408 case BIFF12_PCITEM_ARRAY_DATE
: createItem().readDate( rStrm
); break;
410 OSL_FAIL( "PivotCacheItemList::importArray - unknown data type" );
416 PCFieldModel::PCFieldModel() :
422 mbDatabaseField( true ),
423 mbServerField( false ),
424 mbUniqueList( true ),
425 mbMemberPropField( false )
429 PCSharedItemsModel::PCSharedItemsModel() :
430 mbHasSemiMixed( true ),
431 mbHasNonDate( true ),
436 mbIsNumeric( false ),
437 mbIsInteger( false ),
438 mbHasLongText( false ),
439 mbHasLongIndexes( false )
443 PCFieldGroupModel::PCFieldGroupModel() :
449 mnGroupBy( XML_range
),
450 mbRangeGroup( false ),
451 mbDateGroup( false ),
457 void PCFieldGroupModel::setBiffGroupBy( sal_uInt8 nGroupBy
)
459 static const sal_Int32 spnGroupBy
[] = { XML_range
,
460 XML_seconds
, XML_minutes
, XML_hours
, XML_days
, XML_months
, XML_quarters
, XML_years
};
461 mnGroupBy
= STATIC_ARRAY_SELECT( spnGroupBy
, nGroupBy
, XML_range
);
464 PivotCacheField::PivotCacheField( const WorkbookHelper
& rHelper
, bool bIsDatabaseField
) :
465 WorkbookHelper( rHelper
),
466 maSharedItems( rHelper
),
467 maGroupItems( rHelper
)
469 maFieldModel
.mbDatabaseField
= bIsDatabaseField
;
472 void PivotCacheField::importCacheField( const AttributeList
& rAttribs
)
474 maFieldModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
475 maFieldModel
.maCaption
= rAttribs
.getXString( XML_caption
, OUString() );
476 maFieldModel
.maPropertyName
= rAttribs
.getXString( XML_propertyName
, OUString() );
477 maFieldModel
.maFormula
= rAttribs
.getXString( XML_formula
, OUString() );
478 maFieldModel
.mnNumFmtId
= rAttribs
.getInteger( XML_numFmtId
, 0 );
479 maFieldModel
.mnSqlType
= rAttribs
.getInteger( XML_sqlType
, 0 );
480 maFieldModel
.mnHierarchy
= rAttribs
.getInteger( XML_hierarchy
, 0 );
481 maFieldModel
.mnLevel
= rAttribs
.getInteger( XML_level
, 0 );
482 maFieldModel
.mnMappingCount
= rAttribs
.getInteger( XML_mappingCount
, 0 );
483 maFieldModel
.mbDatabaseField
= rAttribs
.getBool( XML_databaseField
, true );
484 maFieldModel
.mbServerField
= rAttribs
.getBool( XML_serverField
, false );
485 maFieldModel
.mbUniqueList
= rAttribs
.getBool( XML_uniqueList
, true );
486 maFieldModel
.mbMemberPropField
= rAttribs
.getBool( XML_memberPropertyField
, false );
489 void PivotCacheField::importSharedItems( const AttributeList
& rAttribs
)
491 OSL_ENSURE( maSharedItems
.empty(), "PivotCacheField::importSharedItems - multiple shared items elements" );
492 maSharedItemsModel
.mbHasSemiMixed
= rAttribs
.getBool( XML_containsSemiMixedTypes
, true );
493 maSharedItemsModel
.mbHasNonDate
= rAttribs
.getBool( XML_containsNonDate
, true );
494 maSharedItemsModel
.mbHasDate
= rAttribs
.getBool( XML_containsDate
, false );
495 maSharedItemsModel
.mbHasString
= rAttribs
.getBool( XML_containsString
, true );
496 maSharedItemsModel
.mbHasBlank
= rAttribs
.getBool( XML_containsBlank
, false );
497 maSharedItemsModel
.mbHasMixed
= rAttribs
.getBool( XML_containsMixedTypes
, false );
498 maSharedItemsModel
.mbIsNumeric
= rAttribs
.getBool( XML_containsNumber
, false );
499 maSharedItemsModel
.mbIsInteger
= rAttribs
.getBool( XML_containsInteger
, false );
500 maSharedItemsModel
.mbHasLongText
= rAttribs
.getBool( XML_longText
, false );
503 void PivotCacheField::importSharedItem( sal_Int32 nElement
, const AttributeList
& rAttribs
)
505 maSharedItems
.importItem( nElement
, rAttribs
);
508 void PivotCacheField::importFieldGroup( const AttributeList
& rAttribs
)
510 maFieldGroupModel
.mnParentField
= rAttribs
.getInteger( XML_par
, -1 );
511 maFieldGroupModel
.mnBaseField
= rAttribs
.getInteger( XML_base
, -1 );
514 void PivotCacheField::importRangePr( const AttributeList
& rAttribs
)
516 maFieldGroupModel
.maStartDate
= rAttribs
.getDateTime( XML_startDate
, css::util::DateTime() );
517 maFieldGroupModel
.maEndDate
= rAttribs
.getDateTime( XML_endDate
, css::util::DateTime() );
518 maFieldGroupModel
.mfStartValue
= rAttribs
.getDouble( XML_startNum
, 0.0 );
519 maFieldGroupModel
.mfEndValue
= rAttribs
.getDouble( XML_endNum
, 0.0 );
520 maFieldGroupModel
.mfInterval
= rAttribs
.getDouble( XML_groupInterval
, 1.0 );
521 maFieldGroupModel
.mnGroupBy
= rAttribs
.getToken( XML_groupBy
, XML_range
);
522 maFieldGroupModel
.mbRangeGroup
= true;
523 maFieldGroupModel
.mbDateGroup
= maFieldGroupModel
.mnGroupBy
!= XML_range
;
524 maFieldGroupModel
.mbAutoStart
= rAttribs
.getBool( XML_autoStart
, true );
525 maFieldGroupModel
.mbAutoEnd
= rAttribs
.getBool( XML_autoEnd
, true );
528 void PivotCacheField::importDiscretePrItem( sal_Int32 nElement
, const AttributeList
& rAttribs
)
530 OSL_ENSURE( nElement
== XLS_TOKEN( x
), "PivotCacheField::importDiscretePrItem - unexpected element" );
531 if( nElement
== XLS_TOKEN( x
) )
532 maDiscreteItems
.push_back( rAttribs
.getInteger( XML_v
, -1 ) );
535 void PivotCacheField::importGroupItem( sal_Int32 nElement
, const AttributeList
& rAttribs
)
537 maGroupItems
.importItem( nElement
, rAttribs
);
540 void PivotCacheField::importPCDField( SequenceInputStream
& rStrm
)
543 nFlags
= rStrm
.readuInt16();
544 maFieldModel
.mnNumFmtId
= rStrm
.readInt32();
545 maFieldModel
.mnSqlType
= rStrm
.readInt16();
546 maFieldModel
.mnHierarchy
= rStrm
.readInt32();
547 maFieldModel
.mnLevel
= rStrm
.readInt32();
548 maFieldModel
.mnMappingCount
= rStrm
.readInt32();
549 rStrm
>> maFieldModel
.maName
;
550 if( getFlag( nFlags
, BIFF12_PCDFIELD_HASCAPTION
) )
551 rStrm
>> maFieldModel
.maCaption
;
552 if( getFlag( nFlags
, BIFF12_PCDFIELD_HASFORMULA
) )
553 rStrm
.skip( ::std::max
< sal_Int32
>( rStrm
.readInt32(), 0 ) );
554 if( maFieldModel
.mnMappingCount
> 0 )
555 rStrm
.skip( ::std::max
< sal_Int32
>( rStrm
.readInt32(), 0 ) );
556 if( getFlag( nFlags
, BIFF12_PCDFIELD_HASPROPERTYNAME
) )
557 rStrm
>> maFieldModel
.maPropertyName
;
559 maFieldModel
.mbDatabaseField
= getFlag( nFlags
, BIFF12_PCDFIELD_DATABASEFIELD
);
560 maFieldModel
.mbServerField
= getFlag( nFlags
, BIFF12_PCDFIELD_SERVERFIELD
);
561 maFieldModel
.mbUniqueList
= !getFlag( nFlags
, BIFF12_PCDFIELD_NOUNIQUEITEMS
);
562 maFieldModel
.mbMemberPropField
= getFlag( nFlags
, BIFF12_PCDFIELD_MEMBERPROPFIELD
);
565 void PivotCacheField::importPCDFSharedItems( SequenceInputStream
& rStrm
)
568 nFlags
= rStrm
.readuInt16();
569 maSharedItemsModel
.mbHasSemiMixed
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASSEMIMIXED
);
570 maSharedItemsModel
.mbHasNonDate
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASNONDATE
);
571 maSharedItemsModel
.mbHasDate
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASDATE
);
572 maSharedItemsModel
.mbHasString
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASSTRING
);
573 maSharedItemsModel
.mbHasBlank
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASBLANK
);
574 maSharedItemsModel
.mbHasMixed
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASMIXED
);
575 maSharedItemsModel
.mbIsNumeric
= getFlag( nFlags
, BIFF12_PCDFSITEMS_ISNUMERIC
);
576 maSharedItemsModel
.mbIsInteger
= getFlag( nFlags
, BIFF12_PCDFSITEMS_ISINTEGER
);
577 maSharedItemsModel
.mbHasLongText
= getFlag( nFlags
, BIFF12_PCDFSITEMS_HASLONGTEXT
);
580 void PivotCacheField::importPCDFSharedItem( sal_Int32 nRecId
, SequenceInputStream
& rStrm
)
582 maSharedItems
.importItem( nRecId
, rStrm
);
585 void PivotCacheField::importPCDFieldGroup( SequenceInputStream
& rStrm
)
587 maFieldGroupModel
.mnParentField
= rStrm
.readInt32();
588 maFieldGroupModel
.mnBaseField
= rStrm
.readInt32();
591 void PivotCacheField::importPCDFRangePr( SequenceInputStream
& rStrm
)
593 sal_uInt8 nGroupBy
, nFlags
;
594 nGroupBy
= rStrm
.readuChar();
595 nFlags
= rStrm
.readuChar();
596 maFieldGroupModel
.mfStartValue
= rStrm
.readDouble();
597 maFieldGroupModel
.mfEndValue
= rStrm
.readDouble();
598 maFieldGroupModel
.mfInterval
= rStrm
.readDouble();
600 maFieldGroupModel
.setBiffGroupBy( nGroupBy
);
601 maFieldGroupModel
.mbRangeGroup
= true;
602 maFieldGroupModel
.mbDateGroup
= getFlag( nFlags
, BIFF12_PCDFRANGEPR_DATEGROUP
);
603 maFieldGroupModel
.mbAutoStart
= getFlag( nFlags
, BIFF12_PCDFRANGEPR_AUTOSTART
);
604 maFieldGroupModel
.mbAutoEnd
= getFlag( nFlags
, BIFF12_PCDFRANGEPR_AUTOEND
);
606 OSL_ENSURE( maFieldGroupModel
.mbDateGroup
== (maFieldGroupModel
.mnGroupBy
!= XML_range
), "PivotCacheField::importPCDFRangePr - wrong date flag" );
607 if( maFieldGroupModel
.mbDateGroup
)
609 maFieldGroupModel
.maStartDate
= getUnitConverter().calcDateTimeFromSerial( maFieldGroupModel
.mfStartValue
);
610 maFieldGroupModel
.maEndDate
= getUnitConverter().calcDateTimeFromSerial( maFieldGroupModel
.mfEndValue
);
614 void PivotCacheField::importPCDFDiscretePrItem( sal_Int32 nRecId
, SequenceInputStream
& rStrm
)
616 OSL_ENSURE( nRecId
== BIFF12_ID_PCITEM_INDEX
, "PivotCacheField::importPCDFDiscretePrItem - unexpected record" );
617 if( nRecId
== BIFF12_ID_PCITEM_INDEX
)
618 maDiscreteItems
.push_back( rStrm
.readInt32() );
621 void PivotCacheField::importPCDFGroupItem( sal_Int32 nRecId
, SequenceInputStream
& rStrm
)
623 maGroupItems
.importItem( nRecId
, rStrm
);
626 void PivotCacheField::importPCDField( BiffInputStream
& rStrm
)
628 sal_uInt16 nFlags
, nGroupItems
, nBaseItems
, nSharedItems
;
630 maFieldGroupModel
.mnParentField
= rStrm
.readuInt16();
631 maFieldGroupModel
.mnBaseField
= rStrm
.readuInt16();
632 rStrm
.skip( 2 ); // number of unique items (either shared or group)
633 rStrm
>> nGroupItems
>> nBaseItems
>> nSharedItems
;
634 maFieldModel
.maName
= (getBiff() == BIFF8
) ? rStrm
.readUniString() : rStrm
.readByteStringUC( true, getTextEncoding() );
636 maFieldModel
.mbServerField
= getFlag( nFlags
, BIFF_PCDFIELD_SERVERFIELD
);
637 maFieldModel
.mbUniqueList
= !getFlag( nFlags
, BIFF_PCDFIELD_NOUNIQUEITEMS
);
638 maSharedItemsModel
.mbHasSemiMixed
= getFlag( nFlags
, BIFF_PCDFIELD_HASSEMIMIXED
);
639 maSharedItemsModel
.mbHasNonDate
= getFlag( nFlags
, BIFF_PCDFIELD_HASNONDATE
);
640 maSharedItemsModel
.mbHasDate
= getFlag( nFlags
, BIFF_PCDFIELD_HASDATE
);
641 maSharedItemsModel
.mbIsNumeric
= getFlag( nFlags
, BIFF_PCDFIELD_ISNUMERIC
);
642 maSharedItemsModel
.mbHasLongIndexes
= getFlag( nFlags
, BIFF_PCDFIELD_HASLONGINDEX
);
643 maFieldGroupModel
.mbRangeGroup
= getFlag( nFlags
, BIFF_PCDFIELD_RANGEGROUP
);
645 // in BIFF, presence of parent group field is denoted by a flag
646 if( !getFlag( nFlags
, BIFF_PCDFIELD_HASPARENT
) )
647 maFieldGroupModel
.mnParentField
= -1;
649 // following PCDFSQLTYPE record contains SQL type
650 if( (rStrm
.getNextRecId() == BIFF_ID_PCDFSQLTYPE
) && rStrm
.startNextRecord() )
651 maFieldModel
.mnSqlType
= rStrm
.readInt16();
653 // read group items, if any
654 if( nGroupItems
> 0 )
657 !getFlag(nFlags
, BIFF_PCDFIELD_HASITEMS
), "sc.filter",
658 "PivotCacheField::importPCDField - missing items flag");
659 maGroupItems
.importItemList( rStrm
, nGroupItems
);
661 sal_uInt16 nNextRecId
= rStrm
.getNextRecId();
662 bool bHasRangePr
= nNextRecId
== BIFF_ID_PCDFRANGEPR
;
663 bool bHasDiscretePr
= nNextRecId
== BIFF_ID_PCDFDISCRETEPR
;
665 OSL_ENSURE( bHasRangePr
|| bHasDiscretePr
, "PivotCacheField::importPCDField - missing group properties record" );
666 OSL_ENSURE( bHasRangePr
== maFieldGroupModel
.mbRangeGroup
, "PivotCacheField::importPCDField - invalid range grouping flag" );
667 if( bHasRangePr
&& rStrm
.startNextRecord() )
668 importPCDFRangePr( rStrm
);
669 else if( bHasDiscretePr
&& rStrm
.startNextRecord() )
670 importPCDFDiscretePr( rStrm
);
673 // read the shared items, if any
674 if( nSharedItems
> 0 )
677 !getFlag(nFlags
, BIFF_PCDFIELD_HASITEMS
), "sc.filter",
678 "PivotCacheField::importPCDField - missing items flag");
679 maSharedItems
.importItemList( rStrm
, nSharedItems
);
683 void PivotCacheField::importPCDFRangePr( BiffInputStream
& rStrm
)
687 maFieldGroupModel
.setBiffGroupBy( extractValue
< sal_uInt8
>( nFlags
, 2, 3 ) );
688 maFieldGroupModel
.mbRangeGroup
= true;
689 maFieldGroupModel
.mbDateGroup
= maFieldGroupModel
.mnGroupBy
!= XML_range
;
690 maFieldGroupModel
.mbAutoStart
= getFlag( nFlags
, BIFF_PCDFRANGEPR_AUTOSTART
);
691 maFieldGroupModel
.mbAutoEnd
= getFlag( nFlags
, BIFF_PCDFRANGEPR_AUTOEND
);
693 /* Start, end, and interval are stored in 3 separate item records. Type of
694 the items is dependent on numeric/date mode. Numeric groups expect
695 three PCITEM_DOUBLE records, date groups expect two PCITEM_DATE records
696 and one PCITEM_INT record. */
697 PivotCacheItemList
aLimits( *this );
698 aLimits
.importItemList( rStrm
, 3 );
699 OSL_ENSURE( aLimits
.size() == 3, "PivotCacheField::importPCDFRangePr - missing grouping records" );
700 const PivotCacheItem
* pStartValue
= aLimits
.getCacheItem( 0 );
701 const PivotCacheItem
* pEndValue
= aLimits
.getCacheItem( 1 );
702 const PivotCacheItem
* pInterval
= aLimits
.getCacheItem( 2 );
703 if( pStartValue
&& pEndValue
&& pInterval
)
705 if( maFieldGroupModel
.mbDateGroup
)
707 bool bHasTypes
= (pStartValue
->getType() == XML_d
) && (pEndValue
->getType() == XML_d
) && (pInterval
->getType() == XML_i
);
708 OSL_ENSURE( bHasTypes
, "PivotCacheField::importPCDFRangePr - wrong data types in grouping items" );
711 maFieldGroupModel
.maStartDate
= pStartValue
->getValue().get
< css::util::DateTime
>();
712 maFieldGroupModel
.maEndDate
= pEndValue
->getValue().get
< css::util::DateTime
>();
713 maFieldGroupModel
.mfInterval
= pInterval
->getValue().get
< sal_Int16
>();
718 bool bHasTypes
= (pStartValue
->getType() == XML_n
) && (pEndValue
->getType() == XML_n
) && (pInterval
->getType() == XML_n
);
719 OSL_ENSURE( bHasTypes
, "PivotCacheField::importPCDFRangePr - wrong data types in grouping items" );
722 maFieldGroupModel
.mfStartValue
= pStartValue
->getValue().get
< double >();
723 maFieldGroupModel
.mfEndValue
= pEndValue
->getValue().get
< double >();
724 maFieldGroupModel
.mfInterval
= pInterval
->getValue().get
< double >();
730 void PivotCacheField::importPCDFDiscretePr( BiffInputStream
& rStrm
)
732 sal_Int32 nCount
= static_cast< sal_Int32
>( rStrm
.size() / 2 );
733 for( sal_Int32 nIndex
= 0; !rStrm
.isEof() && (nIndex
< nCount
); ++nIndex
)
734 maDiscreteItems
.push_back( rStrm
.readuInt16() );
737 const PivotCacheItem
* PivotCacheField::getCacheItem( sal_Int32 nItemIdx
) const
739 if( hasGroupItems() )
740 return maGroupItems
.getCacheItem( nItemIdx
);
741 if( hasSharedItems() )
742 return maSharedItems
.getCacheItem( nItemIdx
);
746 void PivotCacheField::applyItemCaptions( const IdCaptionPairList
& vCaptions
)
748 if( hasGroupItems() )
749 maGroupItems
.applyItemCaptions( vCaptions
);
750 if( hasSharedItems() )
751 maSharedItems
.applyItemCaptions( vCaptions
);
754 void PivotCacheField::getCacheItemNames( ::std::vector
< OUString
>& orItemNames
) const
756 if( hasGroupItems() )
757 maGroupItems
.getCacheItemNames( orItemNames
);
758 else if( hasSharedItems() )
759 maSharedItems
.getCacheItemNames( orItemNames
);
762 const PivotCacheItemList
& PivotCacheField::getCacheItems() const
764 if( hasGroupItems() )
766 return maSharedItems
;
769 void PivotCacheField::convertNumericGrouping( const Reference
< XDataPilotField
>& rxDPField
) const
771 OSL_ENSURE( hasGroupItems() && hasNumericGrouping(), "PivotCacheField::convertNumericGrouping - not a numeric group field" );
772 PropertySet
aPropSet( rxDPField
);
773 if( hasGroupItems() && hasNumericGrouping() && aPropSet
.is() )
775 DataPilotFieldGroupInfo aGroupInfo
;
776 aGroupInfo
.HasAutoStart
= maFieldGroupModel
.mbAutoStart
;
777 aGroupInfo
.HasAutoEnd
= maFieldGroupModel
.mbAutoEnd
;
778 aGroupInfo
.HasDateValues
= sal_False
;
779 aGroupInfo
.Start
= maFieldGroupModel
.mfStartValue
;
780 aGroupInfo
.End
= maFieldGroupModel
.mfEndValue
;
781 aGroupInfo
.Step
= maFieldGroupModel
.mfInterval
;
782 aGroupInfo
.GroupBy
= 0;
783 aPropSet
.setProperty( PROP_GroupInfo
, aGroupInfo
);
787 OUString
PivotCacheField::createDateGroupField( const Reference
< XDataPilotField
>& rxBaseDPField
) const
789 OSL_ENSURE( hasGroupItems() && hasDateGrouping(), "PivotCacheField::createDateGroupField - not a numeric group field" );
790 Reference
< XDataPilotField
> xDPGroupField
;
791 PropertySet
aPropSet( rxBaseDPField
);
792 if( hasGroupItems() && hasDateGrouping() && aPropSet
.is() )
794 bool bDayRanges
= (maFieldGroupModel
.mnGroupBy
== XML_days
) && (maFieldGroupModel
.mfInterval
>= 2.0);
796 DataPilotFieldGroupInfo aGroupInfo
;
797 aGroupInfo
.HasAutoStart
= maFieldGroupModel
.mbAutoStart
;
798 aGroupInfo
.HasAutoEnd
= maFieldGroupModel
.mbAutoEnd
;
799 aGroupInfo
.HasDateValues
= sal_True
;
800 aGroupInfo
.Start
= getUnitConverter().calcSerialFromDateTime( maFieldGroupModel
.maStartDate
);
801 aGroupInfo
.End
= getUnitConverter().calcSerialFromDateTime( maFieldGroupModel
.maEndDate
);
802 aGroupInfo
.Step
= bDayRanges
? maFieldGroupModel
.mfInterval
: 0.0;
804 using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy
;
805 switch( maFieldGroupModel
.mnGroupBy
)
807 case XML_years
: aGroupInfo
.GroupBy
= YEARS
; break;
808 case XML_quarters
: aGroupInfo
.GroupBy
= QUARTERS
; break;
809 case XML_months
: aGroupInfo
.GroupBy
= MONTHS
; break;
810 case XML_days
: aGroupInfo
.GroupBy
= DAYS
; break;
811 case XML_hours
: aGroupInfo
.GroupBy
= HOURS
; break;
812 case XML_minutes
: aGroupInfo
.GroupBy
= MINUTES
; break;
813 case XML_seconds
: aGroupInfo
.GroupBy
= SECONDS
; break;
814 default: OSL_FAIL( "PivotCacheField::convertRangeGrouping - unknown date/time interval" );
819 Reference
< XDataPilotFieldGrouping
> xDPGrouping( rxBaseDPField
, UNO_QUERY_THROW
);
820 xDPGroupField
= xDPGrouping
->createDateGroup( aGroupInfo
);
827 Reference
< XNamed
> xFieldName( xDPGroupField
, UNO_QUERY
);
828 return xFieldName
.is() ? xFieldName
->getName() : OUString();
831 OUString
PivotCacheField::createParentGroupField( const Reference
< XDataPilotField
>& rxBaseDPField
, const PivotCacheField
& rBaseCacheField
, PivotCacheGroupItemVector
& orItemNames
) const
833 OSL_ENSURE( hasGroupItems() && !maDiscreteItems
.empty(), "PivotCacheField::createParentGroupField - not a group field" );
834 OSL_ENSURE( maDiscreteItems
.size() == orItemNames
.size(), "PivotCacheField::createParentGroupField - number of item names does not match grouping info" );
835 Reference
< XDataPilotFieldGrouping
> xDPGrouping( rxBaseDPField
, UNO_QUERY
);
836 if( !xDPGrouping
.is() ) return OUString();
838 // map the group item indexes from maGroupItems to all item indexes from maDiscreteItems
839 typedef ::std::vector
< sal_Int32
> GroupItemList
;
840 typedef ::std::vector
< GroupItemList
> GroupItemMap
;
841 GroupItemMap
aItemMap( maGroupItems
.size() );
842 for( IndexVector::const_iterator aBeg
= maDiscreteItems
.begin(), aIt
= aBeg
, aEnd
= maDiscreteItems
.end(); aIt
!= aEnd
; ++aIt
)
844 if( GroupItemList
* pItems
= ContainerHelper::getVectorElementAccess( aItemMap
, *aIt
) )
846 if ( const PivotCacheItem
* pItem
= rBaseCacheField
.getCacheItems().getCacheItem( aIt
- aBeg
) )
848 // Skip unspecified or ununsed entries or errors
849 if ( pItem
->isUnused() || ( pItem
->getType() == XML_m
) || ( pItem
->getType() == XML_e
) )
852 pItems
->push_back( static_cast< sal_Int32
>( aIt
- aBeg
) );
856 // process all groups
857 Reference
< XDataPilotField
> xDPGroupField
;
858 for( GroupItemMap::iterator aBeg
= aItemMap
.begin(), aIt
= aBeg
, aEnd
= aItemMap
.end(); aIt
!= aEnd
; ++aIt
)
860 OSL_ENSURE( !aIt
->empty(), "PivotCacheField::createParentGroupField - item/group should not be empty" );
863 /* Insert the names of the items that are part of this group. Calc
864 expects the names of the members of the field whose members are
865 grouped (which may be the names of groups too). Excel provides
866 the names of the base field items instead (no group names
867 involved). Therefore, the passed collection of current item
868 names as they are already grouped is used here to resolve the
870 ::std::vector
< OUString
> aMembers
;
871 for( GroupItemList::iterator aBeg2
= aIt
->begin(), aIt2
= aBeg2
, aEnd2
= aIt
->end(); aIt2
!= aEnd2
; ++aIt2
)
872 if( const PivotCacheGroupItem
* pName
= ContainerHelper::getVectorElement( orItemNames
, *aIt2
) )
873 if( ::std::find( aMembers
.begin(), aMembers
.end(), pName
->maGroupName
) == aMembers
.end() )
874 aMembers
.push_back( pName
->maGroupName
);
876 /* Check again, that this is not just a group that is not grouped
877 further with other items. */
878 if( !aMembers
.empty() ) try
880 // only the first call of createNameGroup() returns the new field
881 Reference
< XDataPilotField
> xDPNewField
= xDPGrouping
->createNameGroup( ContainerHelper::vectorToSequence( aMembers
) );
882 OSL_ENSURE( xDPGroupField
.is() != xDPNewField
.is(), "PivotCacheField::createParentGroupField - missing group field" );
883 if( !xDPGroupField
.is() )
884 xDPGroupField
= xDPNewField
;
886 // get current grouping info
887 DataPilotFieldGroupInfo aGroupInfo
;
888 PropertySet
aPropSet( xDPGroupField
);
889 aPropSet
.getProperty( aGroupInfo
, PROP_GroupInfo
);
891 /* Find the group object and the auto-generated group name.
892 The returned field contains all groups derived from the
893 previous field if that is grouped too. To find the correct
894 group, the first item used to create the group is serached.
895 Calc provides the original item names of the base field
896 when the group is querried for its members. Its does not
897 provide the names of members that are already groups in the
898 field used to create the new groups. (Is this a bug?)
899 Therefore, a name from the passed list of original item
900 names is used to find the correct group. */
902 if( const PivotCacheGroupItem
* pName
= ContainerHelper::getVectorElement( orItemNames
, aIt
->front() ) )
903 aFirstItem
= pName
->maOrigName
;
904 Reference
< XNamed
> xGroupName
;
906 Reference
< XIndexAccess
> xGroupsIA( aGroupInfo
.Groups
, UNO_QUERY_THROW
);
907 for( sal_Int32 nIdx
= 0, nCount
= xGroupsIA
->getCount(); (nIdx
< nCount
) && (aAutoName
.isEmpty()); ++nIdx
) try
909 Reference
< XNameAccess
> xItemsNA( xGroupsIA
->getByIndex( nIdx
), UNO_QUERY_THROW
);
910 if( xItemsNA
->hasByName( aFirstItem
) )
912 xGroupName
.set( xGroupsIA
->getByIndex( nIdx
), UNO_QUERY_THROW
);
913 aAutoName
= xGroupName
->getName();
919 OSL_ENSURE( !aAutoName
.isEmpty(), "PivotCacheField::createParentGroupField - cannot find auto-generated group name" );
921 // get the real group name from the list of group items
923 if( const PivotCacheItem
* pGroupItem
= maGroupItems
.getCacheItem( static_cast< sal_Int32
>( aIt
- aBeg
) ) )
924 aGroupName
= pGroupItem
->getName();
925 OSL_ENSURE( !aGroupName
.isEmpty(), "PivotCacheField::createParentGroupField - cannot find group name" );
926 if( aGroupName
.isEmpty() )
927 aGroupName
= aAutoName
;
929 if( xGroupName
.is() && !aGroupName
.isEmpty() )
931 // replace the auto-generated group name with the real name
932 if( aAutoName
!= aGroupName
)
934 xGroupName
->setName( aGroupName
);
935 aPropSet
.setProperty( PROP_GroupInfo
, aGroupInfo
);
937 // replace original item names in passed vector with group name
938 for( GroupItemList::iterator aIt2
= aIt
->begin(), aEnd2
= aIt
->end(); aIt2
!= aEnd2
; ++aIt2
)
939 if( PivotCacheGroupItem
* pName
= ContainerHelper::getVectorElementAccess( orItemNames
, *aIt2
) )
940 pName
->maGroupName
= aGroupName
;
949 Reference
< XNamed
> xFieldName( xDPGroupField
, UNO_QUERY
);
950 return xFieldName
.is() ? xFieldName
->getName() : OUString();
953 void PivotCacheField::writeSourceHeaderCell( WorksheetHelper
& rSheetHelper
, sal_Int32 nCol
, sal_Int32 nRow
) const
956 aModel
.maCellAddr
= CellAddress( rSheetHelper
.getSheetIndex(), nCol
, nRow
);
957 rSheetHelper
.getSheetData().setStringCell( aModel
, maFieldModel
.maName
);
960 void PivotCacheField::writeSourceDataCell( WorksheetHelper
& rSheetHelper
, sal_Int32 nCol
, sal_Int32 nRow
, const PivotCacheItem
& rItem
) const
962 bool bHasIndex
= rItem
.getType() == XML_x
;
963 OSL_ENSURE( bHasIndex
!= maSharedItems
.empty(), "PivotCacheField::writeSourceDataCell - shared items missing or not expected" );
965 writeSharedItemToSourceDataCell( rSheetHelper
, nCol
, nRow
, rItem
.getValue().get
< sal_Int32
>() );
967 writeItemToSourceDataCell( rSheetHelper
, nCol
, nRow
, rItem
);
970 void PivotCacheField::importPCRecordItem( SequenceInputStream
& rStrm
, WorksheetHelper
& rSheetHelper
, sal_Int32 nCol
, sal_Int32 nRow
) const
972 if( hasSharedItems() )
974 writeSharedItemToSourceDataCell( rSheetHelper
, nCol
, nRow
, rStrm
.readInt32() );
978 PivotCacheItem aItem
;
979 if( maSharedItemsModel
.mbIsNumeric
)
980 aItem
.readDouble( rStrm
);
981 else if( maSharedItemsModel
.mbHasDate
&& !maSharedItemsModel
.mbHasString
)
982 aItem
.readDate( rStrm
);
984 aItem
.readString( rStrm
);
985 writeItemToSourceDataCell( rSheetHelper
, nCol
, nRow
, aItem
);
989 void PivotCacheField::importPCItemIndex( BiffInputStream
& rStrm
, WorksheetHelper
& rSheetHelper
, sal_Int32 nCol
, sal_Int32 nRow
) const
991 OSL_ENSURE( hasSharedItems(), "PivotCacheField::importPCItemIndex - invalid call, no shared items found" );
992 sal_Int32 nIndex
= maSharedItemsModel
.mbHasLongIndexes
? rStrm
.readuInt16() : rStrm
.readuInt8();
993 writeSharedItemToSourceDataCell( rSheetHelper
, nCol
, nRow
, nIndex
);
996 // private --------------------------------------------------------------------
998 void PivotCacheField::writeItemToSourceDataCell( WorksheetHelper
& rSheetHelper
,
999 sal_Int32 nCol
, sal_Int32 nRow
, const PivotCacheItem
& rItem
)
1001 if( rItem
.getType() != XML_m
)
1004 aModel
.maCellAddr
= CellAddress( rSheetHelper
.getSheetIndex(), nCol
, nRow
);
1005 SheetDataBuffer
& rSheetData
= rSheetHelper
.getSheetData();
1006 switch( rItem
.getType() )
1008 case XML_s
: rSheetData
.setStringCell( aModel
, rItem
.getValue().get
< OUString
>() ); break;
1009 case XML_n
: rSheetData
.setValueCell( aModel
, rItem
.getValue().get
< double >() ); break;
1010 case XML_i
: rSheetData
.setValueCell( aModel
, rItem
.getValue().get
< sal_Int16
>() ); break;
1011 case XML_d
: rSheetData
.setDateTimeCell( aModel
, rItem
.getValue().get
< css::util::DateTime
>() ); break;
1012 case XML_b
: rSheetData
.setBooleanCell( aModel
, rItem
.getValue().get
< bool >() ); break;
1013 case XML_e
: rSheetData
.setErrorCell( aModel
, static_cast< sal_uInt8
>( rItem
.getValue().get
< sal_Int32
>() ) ); break;
1014 default: OSL_FAIL( "PivotCacheField::writeItemToSourceDataCell - unexpected item data type" );
1019 void PivotCacheField::writeSharedItemToSourceDataCell(
1020 WorksheetHelper
& rSheetHelper
, sal_Int32 nCol
, sal_Int32 nRow
, sal_Int32 nItemIdx
) const
1022 if( const PivotCacheItem
* pCacheItem
= maSharedItems
.getCacheItem( nItemIdx
) )
1023 writeItemToSourceDataCell( rSheetHelper
, nCol
, nRow
, *pCacheItem
);
1026 PCDefinitionModel::PCDefinitionModel() :
1027 mfRefreshedDate( 0.0 ),
1029 mnMissItemsLimit( 0 ),
1030 mnDatabaseFields( 0 ),
1033 mbRefreshOnLoad( false ),
1034 mbOptimizeMemory( false ),
1035 mbEnableRefresh( true ),
1036 mbBackgroundQuery( false ),
1037 mbUpgradeOnRefresh( false ),
1038 mbTupleCache( false ),
1039 mbSupportSubquery( false ),
1040 mbSupportDrill( false )
1044 PCSourceModel::PCSourceModel() :
1045 mnSourceType( XML_TOKEN_INVALID
),
1050 PCWorksheetSourceModel::PCWorksheetSourceModel()
1052 maRange
.StartColumn
= maRange
.StartRow
= maRange
.EndColumn
= maRange
.EndRow
= -1;
1055 PivotCache::PivotCache( const WorkbookHelper
& rHelper
) :
1056 WorkbookHelper( rHelper
),
1058 mbValidSource( false ),
1059 mbDummySheet( false )
1063 void PivotCache::importPivotCacheDefinition( const AttributeList
& rAttribs
)
1065 maDefModel
.maRelId
= rAttribs
.getString( R_TOKEN( id
), OUString() );
1066 maDefModel
.maRefreshedBy
= rAttribs
.getXString( XML_refreshedBy
, OUString() );
1067 maDefModel
.mfRefreshedDate
= rAttribs
.getDouble( XML_refreshedDate
, 0.0 );
1068 maDefModel
.mnRecords
= rAttribs
.getInteger( XML_recordCount
, 0 );
1069 maDefModel
.mnMissItemsLimit
= rAttribs
.getInteger( XML_missingItemsLimit
, 0 );
1070 maDefModel
.mbInvalid
= rAttribs
.getBool( XML_invalid
, false );
1071 maDefModel
.mbSaveData
= rAttribs
.getBool( XML_saveData
, true );
1072 maDefModel
.mbRefreshOnLoad
= rAttribs
.getBool( XML_refreshOnLoad
, false );
1073 maDefModel
.mbOptimizeMemory
= rAttribs
.getBool( XML_optimizeMemory
, false );
1074 maDefModel
.mbEnableRefresh
= rAttribs
.getBool( XML_enableRefresh
, true );
1075 maDefModel
.mbBackgroundQuery
= rAttribs
.getBool( XML_backgroundQuery
, false );
1076 maDefModel
.mbUpgradeOnRefresh
= rAttribs
.getBool( XML_upgradeOnRefresh
, false );
1077 maDefModel
.mbTupleCache
= rAttribs
.getBool( XML_tupleCache
, false );
1078 maDefModel
.mbSupportSubquery
= rAttribs
.getBool( XML_supportSubquery
, false );
1079 maDefModel
.mbSupportDrill
= rAttribs
.getBool( XML_supportAdvancedDrill
, false );
1082 void PivotCache::importCacheSource( const AttributeList
& rAttribs
)
1084 maSourceModel
.mnSourceType
= rAttribs
.getToken( XML_type
, XML_TOKEN_INVALID
);
1085 maSourceModel
.mnConnectionId
= rAttribs
.getInteger( XML_connectionId
, 0 );
1088 void PivotCache::importWorksheetSource( const AttributeList
& rAttribs
, const Relations
& rRelations
)
1090 maSheetSrcModel
.maRelId
= rAttribs
.getString( R_TOKEN( id
), OUString() );
1091 maSheetSrcModel
.maSheet
= rAttribs
.getXString( XML_sheet
, OUString() );
1092 maSheetSrcModel
.maDefName
= rAttribs
.getXString( XML_name
, OUString() );
1094 // resolve URL of external document
1095 maTargetUrl
= rRelations
.getExternalTargetFromRelId( maSheetSrcModel
.maRelId
);
1096 // store range address unchecked with sheet index 0, will be resolved/checked later
1097 AddressConverter::convertToCellRangeUnchecked( maSheetSrcModel
.maRange
, rAttribs
.getString( XML_ref
, OUString() ), 0 );
1100 void PivotCache::importPCDefinition( SequenceInputStream
& rStrm
)
1102 sal_uInt8 nFlags1
, nFlags2
;
1103 rStrm
.skip( 3 ); // create/refresh version id's
1104 nFlags1
= rStrm
.readuChar();
1105 maDefModel
.mnMissItemsLimit
= rStrm
.readInt32();
1106 maDefModel
.mfRefreshedDate
= rStrm
.readDouble();
1107 nFlags2
= rStrm
.readuChar();
1108 maDefModel
.mnRecords
= rStrm
.readInt32();
1109 if( getFlag( nFlags2
, BIFF12_PCDEFINITION_HASUSERNAME
) )
1110 rStrm
>> maDefModel
.maRefreshedBy
;
1111 if( getFlag( nFlags2
, BIFF12_PCDEFINITION_HASRELID
) )
1112 rStrm
>> maDefModel
.maRelId
;
1114 maDefModel
.mbInvalid
= getFlag( nFlags1
, BIFF12_PCDEFINITION_INVALID
);
1115 maDefModel
.mbSaveData
= getFlag( nFlags1
, BIFF12_PCDEFINITION_SAVEDATA
);
1116 maDefModel
.mbRefreshOnLoad
= getFlag( nFlags1
, BIFF12_PCDEFINITION_REFRESHONLOAD
);
1117 maDefModel
.mbOptimizeMemory
= getFlag( nFlags1
, BIFF12_PCDEFINITION_OPTIMIZEMEMORY
);
1118 maDefModel
.mbEnableRefresh
= getFlag( nFlags1
, BIFF12_PCDEFINITION_ENABLEREFRESH
);
1119 maDefModel
.mbBackgroundQuery
= getFlag( nFlags1
, BIFF12_PCDEFINITION_BACKGROUNDQUERY
);
1120 maDefModel
.mbUpgradeOnRefresh
= getFlag( nFlags1
, BIFF12_PCDEFINITION_UPGRADEONREFR
);
1121 maDefModel
.mbTupleCache
= getFlag( nFlags1
, BIFF12_PCDEFINITION_TUPELCACHE
);
1122 maDefModel
.mbSupportSubquery
= getFlag( nFlags2
, BIFF12_PCDEFINITION_SUPPORTSUBQUERY
);
1123 maDefModel
.mbSupportDrill
= getFlag( nFlags2
, BIFF12_PCDEFINITION_SUPPORTDRILL
);
1126 void PivotCache::importPCDSource( SequenceInputStream
& rStrm
)
1128 sal_Int32 nSourceType
;
1129 nSourceType
= rStrm
.readInt32();
1130 maSourceModel
.mnConnectionId
= rStrm
.readInt32();
1131 static const sal_Int32 spnSourceTypes
[] = { XML_worksheet
, XML_external
, XML_consolidation
, XML_scenario
};
1132 maSourceModel
.mnSourceType
= STATIC_ARRAY_SELECT( spnSourceTypes
, nSourceType
, XML_TOKEN_INVALID
);
1135 void PivotCache::importPCDSheetSource( SequenceInputStream
& rStrm
, const Relations
& rRelations
)
1137 sal_uInt8 nIsDefName
, nIsBuiltinName
, nFlags
;
1138 nIsDefName
= rStrm
.readuChar();
1139 nIsBuiltinName
= rStrm
.readuChar();
1140 nFlags
= rStrm
.readuChar();
1141 if( getFlag( nFlags
, BIFF12_PCDWBSOURCE_HASSHEET
) )
1142 rStrm
>> maSheetSrcModel
.maSheet
;
1143 if( getFlag( nFlags
, BIFF12_PCDWBSOURCE_HASRELID
) )
1144 rStrm
>> maSheetSrcModel
.maRelId
;
1146 // read cell range or defined name
1147 if( nIsDefName
== 0 )
1151 // store range address unchecked with sheet index 0, will be resolved/checked later
1152 AddressConverter::convertToCellRangeUnchecked( maSheetSrcModel
.maRange
, aBinRange
, 0 );
1156 rStrm
>> maSheetSrcModel
.maDefName
;
1157 if( nIsBuiltinName
!= 0 )
1158 maSheetSrcModel
.maDefName
= "_xlnm." + maSheetSrcModel
.maDefName
;
1161 // resolve URL of external document
1162 maTargetUrl
= rRelations
.getExternalTargetFromRelId( maSheetSrcModel
.maRelId
);
1165 void PivotCache::importPCDefinition( BiffInputStream
& rStrm
)
1167 sal_uInt16 nFlags
, nUserNameLen
;
1168 rStrm
>> maDefModel
.mnRecords
;
1169 rStrm
.skip( 2 ); // repeated cache ID
1171 rStrm
.skip( 2 ); // unused
1172 rStrm
>> maDefModel
.mnDatabaseFields
;
1173 rStrm
.skip( 6 ); // total field count, report record count, (repeated) cache type
1174 rStrm
>> nUserNameLen
;
1175 if( nUserNameLen
!= BIFF_PC_NOSTRING
)
1176 maDefModel
.maRefreshedBy
= (getBiff() == BIFF8
) ?
1177 rStrm
.readUniString( nUserNameLen
) :
1178 rStrm
.readCharArrayUC( nUserNameLen
, getTextEncoding() );
1180 maDefModel
.mbInvalid
= getFlag( nFlags
, BIFF_PCDEFINITION_INVALID
);
1181 maDefModel
.mbSaveData
= getFlag( nFlags
, BIFF_PCDEFINITION_SAVEDATA
);
1182 maDefModel
.mbRefreshOnLoad
= getFlag( nFlags
, BIFF_PCDEFINITION_REFRESHONLOAD
);
1183 maDefModel
.mbOptimizeMemory
= getFlag( nFlags
, BIFF_PCDEFINITION_OPTIMIZEMEMORY
);
1184 maDefModel
.mbEnableRefresh
= getFlag( nFlags
, BIFF_PCDEFINITION_ENABLEREFRESH
);
1185 maDefModel
.mbBackgroundQuery
= getFlag( nFlags
, BIFF_PCDEFINITION_BACKGROUNDQUERY
);
1187 if( (rStrm
.getNextRecId() == BIFF_ID_PCDEFINITION2
) && rStrm
.startNextRecord() )
1188 rStrm
>> maDefModel
.mfRefreshedDate
;
1191 PivotCacheField
& PivotCache::createCacheField( bool bInitDatabaseField
)
1193 bool bIsDatabaseField
= !bInitDatabaseField
|| (maFields
.size() < maDefModel
.mnDatabaseFields
);
1194 PivotCacheFieldVector::value_type
xCacheField( new PivotCacheField( *this, bIsDatabaseField
) );
1195 maFields
.push_back( xCacheField
);
1196 return *xCacheField
;
1199 void PivotCache::finalizeImport()
1201 // collect all fields that are based on source data (needed to finalize source data below)
1202 OSL_ENSURE( !maFields
.empty(), "PivotCache::finalizeImport - no pivot cache fields found" );
1203 for( PivotCacheFieldVector::const_iterator aIt
= maFields
.begin(), aEnd
= maFields
.end(); aIt
!= aEnd
; ++aIt
)
1205 if( (*aIt
)->isDatabaseField() )
1207 OSL_ENSURE( (aIt
== maFields
.begin()) || (*(aIt
- 1))->isDatabaseField(),
1208 "PivotCache::finalizeImport - database field follows a calculated field" );
1209 maDatabaseIndexes
.push_back( static_cast< sal_Int32
>( maDatabaseFields
.size() ) );
1210 maDatabaseFields
.push_back( *aIt
);
1214 maDatabaseIndexes
.push_back( -1 );
1217 OSL_ENSURE( !maDatabaseFields
.empty(), "PivotCache::finalizeImport - no pivot cache source fields found" );
1219 // finalize source data depending on source type
1220 switch( maSourceModel
.mnSourceType
)
1224 // decide whether an external document is used
1225 bool bInternal
= maTargetUrl
.isEmpty() && maSheetSrcModel
.maRelId
.isEmpty();
1226 bool bExternal
= !maTargetUrl
.isEmpty(); // relation ID may be empty, e.g. BIFF import
1227 OSL_ENSURE( bInternal
|| bExternal
, "PivotCache::finalizeImport - invalid external document URL" );
1229 finalizeInternalSheetSource();
1230 else if( bExternal
)
1231 finalizeExternalSheetSource();
1235 // currently, we only support worksheet data sources
1238 case XML_consolidation
:
1245 sal_Int32
PivotCache::getCacheFieldCount() const
1247 return static_cast< sal_Int32
>( maFields
.size() );
1250 const PivotCacheField
* PivotCache::getCacheField( sal_Int32 nFieldIdx
) const
1252 return maFields
.get( nFieldIdx
).get();
1255 sal_Int32
PivotCache::getCacheDatabaseIndex( sal_Int32 nFieldIdx
) const
1257 return ContainerHelper::getVectorElement( maDatabaseIndexes
, nFieldIdx
, -1 );
1260 void PivotCache::writeSourceHeaderCells( WorksheetHelper
& rSheetHelper
) const
1262 OSL_ENSURE( static_cast< size_t >( maSheetSrcModel
.maRange
.EndColumn
- maSheetSrcModel
.maRange
.StartColumn
+ 1 ) == maDatabaseFields
.size(),
1263 "PivotCache::writeSourceHeaderCells - source cell range width does not match number of source fields" );
1264 sal_Int32 nCol
= maSheetSrcModel
.maRange
.StartColumn
;
1265 sal_Int32 nMaxCol
= getAddressConverter().getMaxApiAddress().Column
;
1266 sal_Int32 nRow
= maSheetSrcModel
.maRange
.StartRow
;
1268 updateSourceDataRow( rSheetHelper
, nRow
);
1269 for( PivotCacheFieldVector::const_iterator aIt
= maDatabaseFields
.begin(), aEnd
= maDatabaseFields
.end(); (aIt
!= aEnd
) && (nCol
<= nMaxCol
); ++aIt
, ++nCol
)
1270 (*aIt
)->writeSourceHeaderCell( rSheetHelper
, nCol
, nRow
);
1273 void PivotCache::writeSourceDataCell( WorksheetHelper
& rSheetHelper
, sal_Int32 nColIdx
, sal_Int32 nRowIdx
, const PivotCacheItem
& rItem
) const
1275 sal_Int32 nCol
= maSheetSrcModel
.maRange
.StartColumn
+ nColIdx
;
1276 OSL_ENSURE( (maSheetSrcModel
.maRange
.StartColumn
<= nCol
) && (nCol
<= maSheetSrcModel
.maRange
.EndColumn
), "PivotCache::writeSourceDataCell - invalid column index" );
1277 sal_Int32 nRow
= maSheetSrcModel
.maRange
.StartRow
+ nRowIdx
;
1278 OSL_ENSURE( (maSheetSrcModel
.maRange
.StartRow
< nRow
) && (nRow
<= maSheetSrcModel
.maRange
.EndRow
), "PivotCache::writeSourceDataCell - invalid row index" );
1279 updateSourceDataRow( rSheetHelper
, nRow
);
1280 if( const PivotCacheField
* pCacheField
= maDatabaseFields
.get( nColIdx
).get() )
1281 pCacheField
->writeSourceDataCell( rSheetHelper
, nCol
, nRow
, rItem
);
1284 void PivotCache::importPCRecord( SequenceInputStream
& rStrm
, WorksheetHelper
& rSheetHelper
, sal_Int32 nRowIdx
) const
1286 sal_Int32 nRow
= maSheetSrcModel
.maRange
.StartRow
+ nRowIdx
;
1287 OSL_ENSURE( (maSheetSrcModel
.maRange
.StartRow
< nRow
) && (nRow
<= maSheetSrcModel
.maRange
.EndRow
), "PivotCache::importPCRecord - invalid row index" );
1288 sal_Int32 nCol
= maSheetSrcModel
.maRange
.StartColumn
;
1289 sal_Int32 nMaxCol
= getAddressConverter().getMaxApiAddress().Column
;
1290 for( PivotCacheFieldVector::const_iterator aIt
= maDatabaseFields
.begin(), aEnd
= maDatabaseFields
.end(); !rStrm
.isEof() && (aIt
!= aEnd
) && (nCol
<= nMaxCol
); ++aIt
, ++nCol
)
1291 (*aIt
)->importPCRecordItem( rStrm
, rSheetHelper
, nCol
, nRow
);
1294 void PivotCache::importPCItemIndexList( BiffInputStream
& rStrm
, WorksheetHelper
& rSheetHelper
, sal_Int32 nRowIdx
) const
1296 sal_Int32 nRow
= maSheetSrcModel
.maRange
.StartRow
+ nRowIdx
;
1297 OSL_ENSURE( (maSheetSrcModel
.maRange
.StartRow
< nRow
) && (nRow
<= maSheetSrcModel
.maRange
.EndRow
), "PivotCache::importPCItemIndexList - invalid row index" );
1298 sal_Int32 nCol
= maSheetSrcModel
.maRange
.StartColumn
;
1299 sal_Int32 nMaxCol
= getAddressConverter().getMaxApiAddress().Column
;
1300 for( PivotCacheFieldVector::const_iterator aIt
= maDatabaseFields
.begin(), aEnd
= maDatabaseFields
.end(); !rStrm
.isEof() && (aIt
!= aEnd
) && (nCol
<= nMaxCol
); ++aIt
, ++nCol
)
1301 if( (*aIt
)->hasSharedItems() )
1302 (*aIt
)->importPCItemIndex( rStrm
, rSheetHelper
, nCol
, nRow
);
1305 // private --------------------------------------------------------------------
1307 void PivotCache::finalizeInternalSheetSource()
1309 // resolve sheet name to sheet index
1310 sal_Int16 nSheet
= getWorksheets().getCalcSheetIndex( maSheetSrcModel
.maSheet
);
1312 // if cache is based on a defined name or table, try to resolve to cell range
1313 if( !maSheetSrcModel
.maDefName
.isEmpty() )
1315 // local or global defined name
1316 if( const DefinedName
* pDefName
= getDefinedNames().getByModelName( maSheetSrcModel
.maDefName
, nSheet
).get() )
1318 mbValidSource
= pDefName
->getAbsoluteRange( maSheetSrcModel
.maRange
);
1321 else if( const Table
* pTable
= getTables().getTable( maSheetSrcModel
.maDefName
).get() )
1323 // get original range from table, but exclude the totals row(s)
1324 maSheetSrcModel
.maRange
= pTable
->getOriginalRange();
1325 mbValidSource
= (pTable
->getHeight() - pTable
->getTotalsRows()) > 1;
1327 maSheetSrcModel
.maRange
.EndRow
-= pTable
->getTotalsRows();
1330 // else try the cell range (if the sheet exists)
1331 else if( nSheet
>= 0 )
1333 // insert sheet index into the range, range address will be checked below
1334 maSheetSrcModel
.maRange
.Sheet
= nSheet
;
1335 mbValidSource
= true;
1337 // else sheet has been deleted, generate the source data from cache
1338 else if( !maSheetSrcModel
.maSheet
.isEmpty() )
1340 prepareSourceDataSheet();
1341 // return here to skip the source range check below
1345 // check range location, do not allow ranges that overflow the sheet partly
1346 mbValidSource
= mbValidSource
&&
1347 getAddressConverter().checkCellRange( maSheetSrcModel
.maRange
, false, true ) &&
1348 (maSheetSrcModel
.maRange
.StartRow
< maSheetSrcModel
.maRange
.EndRow
);
1351 void PivotCache::finalizeExternalSheetSource()
1353 /* If pivot cache is based on external sheet data, try to restore sheet
1354 data from cache records. No support for external defined names or tables,
1355 sheet name and path to cache records fragment (OOXML only) are required. */
1356 bool bHasRelation
= (getFilterType() == FILTER_BIFF
) || !maDefModel
.maRelId
.isEmpty();
1357 if( bHasRelation
&& maSheetSrcModel
.maDefName
.isEmpty() && !maSheetSrcModel
.maSheet
.isEmpty() )
1358 prepareSourceDataSheet();
1361 void PivotCache::prepareSourceDataSheet()
1363 CellRangeAddress
& rRange
= maSheetSrcModel
.maRange
;
1364 // data will be inserted in top-left cell, sheet index is still set to 0 (will be set below)
1365 rRange
.EndColumn
-= rRange
.StartColumn
;
1366 rRange
.StartColumn
= 0;
1367 rRange
.EndRow
-= rRange
.StartRow
;
1368 rRange
.StartRow
= 0;
1369 // check range location, do not allow ranges that overflow the sheet partly
1370 if( getAddressConverter().checkCellRange( rRange
, false, true ) )
1372 maColSpans
.insert( ValueRange( rRange
.StartColumn
, rRange
.EndColumn
) );
1373 OUString aSheetName
= "DPCache_" + maSheetSrcModel
.maSheet
;
1374 rRange
.Sheet
= getWorksheets().insertEmptySheet( aSheetName
, false );
1375 mbValidSource
= mbDummySheet
= rRange
.Sheet
>= 0;
1379 void PivotCache::updateSourceDataRow( WorksheetHelper
& rSheetHelper
, sal_Int32 nRow
) const
1381 if( mnCurrRow
!= nRow
)
1383 rSheetHelper
.getSheetData().setColSpans( nRow
, maColSpans
);
1388 PivotCacheBuffer::PivotCacheBuffer( const WorkbookHelper
& rHelper
) :
1389 WorkbookHelper( rHelper
)
1393 void PivotCacheBuffer::registerPivotCacheFragment( sal_Int32 nCacheId
, const OUString
& rFragmentPath
)
1395 OSL_ENSURE( nCacheId
>= 0, "PivotCacheBuffer::registerPivotCacheFragment - invalid pivot cache identifier" );
1396 OSL_ENSURE( maFragmentPaths
.count( nCacheId
) == 0, "PivotCacheBuffer::registerPivotCacheFragment - fragment path exists already" );
1397 if( (nCacheId
>= 0) && !rFragmentPath
.isEmpty() )
1398 maFragmentPaths
[ nCacheId
] = rFragmentPath
;
1401 PivotCache
* PivotCacheBuffer::importPivotCacheFragment( sal_Int32 nCacheId
)
1403 switch( getFilterType() )
1405 /* OOXML/BIFF12 filter: On first call for the cache ID, the pivot
1406 cache object is created and inserted into maCaches. Then, the cache
1407 definition fragment is read and the cache is returned. On
1408 subsequent calls, the created cache will be found in maCaches and
1409 returned immediately. */
1412 // try to find an imported pivot cache
1413 if( PivotCache
* pCache
= maCaches
.get( nCacheId
).get() )
1416 // check if a fragment path exists for the passed cache identifier
1417 FragmentPathMap::iterator aIt
= maFragmentPaths
.find( nCacheId
);
1418 if( aIt
== maFragmentPaths
.end() )
1421 /* Import the cache fragment. This may create a dummy data sheet
1422 for external sheet sources. */
1423 PivotCache
& rCache
= createPivotCache( nCacheId
);
1424 importOoxFragment( new PivotCacheDefinitionFragment( *this, aIt
->second
, rCache
) );
1428 /* BIFF filter: Pivot table provides 0-based index into list of pivot
1429 cache source links (PIVOTCACHE/PCDSOURCE/... record blocks in
1430 workbook stream). First, this index has to be resolved to the cache
1431 identifier that is used to manage the cache stream names (the
1432 maFragmentPaths member). The cache object itself exists already
1433 before the first call for the cache source index, because source data
1434 link is part of workbook data, not of the cache stream. To detect
1435 subsequent calls with an already initialized cache, the entry in
1436 maFragmentPaths will be removed after reading the cache stream. */
1439 /* Resolve cache index to cache identifier and try to find pivot
1440 cache. Cache must exist already for a valid cache index. */
1441 nCacheId
= ContainerHelper::getVectorElement( maCacheIds
, nCacheId
, -1 );
1442 PivotCache
* pCache
= maCaches
.get( nCacheId
).get();
1446 /* Try to find fragment path entry (stream name). If missing, the
1447 stream has been read already, and the cache can be returned. */
1448 FragmentPathMap::iterator aIt
= maFragmentPaths
.find( nCacheId
);
1449 if( aIt
!= maFragmentPaths
.end() )
1451 /* Import the cache stream. This may create a dummy data sheet
1452 for external sheet sources. */
1453 BiffPivotCacheFragment( *this, aIt
->second
, *pCache
).importFragment();
1454 // remove the fragment entry to mark that the cache is initialized
1455 maFragmentPaths
.erase( aIt
);
1460 case FILTER_UNKNOWN
:
1461 OSL_FAIL( "PivotCacheBuffer::importPivotCacheFragment - unknown filter type" );
1466 PivotCache
& PivotCacheBuffer::createPivotCache( sal_Int32 nCacheId
)
1468 maCacheIds
.push_back( nCacheId
);
1469 PivotCacheMap::mapped_type
& rxCache
= maCaches
[ nCacheId
];
1470 rxCache
.reset( new PivotCache( *this ) );
1477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */