fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / oox / pivotcachebuffer.cxx
blobe35eaaeb00f0f5da91a6882e5c674c7f40ba1e09
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
22 #include <set>
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"
45 namespace oox {
46 namespace xls {
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;
56 namespace {
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;
145 } // namespace
147 PivotCacheItem::PivotCacheItem() :
148 mnType( XML_m ), mbUnused( false )
152 void PivotCacheItem::readString( const AttributeList& rAttribs )
154 maValue <<= rAttribs.getXString( XML_v, OUString() );
155 mnType = XML_s;
158 void PivotCacheItem::readNumeric( const AttributeList& rAttribs )
160 maValue <<= rAttribs.getDouble( XML_v, 0.0 );
161 mnType = XML_n;
162 mbUnused = rAttribs.getBool( XML_u, false );
165 void PivotCacheItem::readDate( const AttributeList& rAttribs )
167 maValue <<= rAttribs.getDateTime( XML_v, css::util::DateTime() );
168 mnType = XML_d;
171 void PivotCacheItem::readBool( const AttributeList& rAttribs )
173 maValue <<= rAttribs.getBool( XML_v, false );
174 mnType = XML_b;
177 void PivotCacheItem::readError( const AttributeList& rAttribs, const UnitConverter& rUnitConverter )
179 maValue <<= static_cast< sal_Int32 >( rUnitConverter.calcBiffErrorCode( rAttribs.getXString( XML_v, OUString() ) ) );
180 mnType = XML_e;
183 void PivotCacheItem::readIndex( const AttributeList& rAttribs )
185 maValue <<= rAttribs.getInteger( XML_v, -1 );
186 mnType = XML_x;
189 void PivotCacheItem::readString( SequenceInputStream& rStrm )
191 maValue <<= BiffHelper::readString( rStrm );
192 mnType = XML_s;
195 void PivotCacheItem::readDouble( SequenceInputStream& rStrm )
197 maValue <<= rStrm.readDouble();
198 mnType = XML_n;
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;
212 mnType = XML_d;
215 void PivotCacheItem::readBool( SequenceInputStream& rStrm )
217 maValue <<= (rStrm.readuInt8() != 0);
218 mnType = XML_b;
221 void PivotCacheItem::readError( SequenceInputStream& rStrm )
223 maValue <<= static_cast< sal_Int32 >( rStrm.readuInt8() );
224 mnType = XML_e;
227 void PivotCacheItem::readIndex( SequenceInputStream& rStrm )
229 maValue <<= rStrm.readInt32();
230 mnType = XML_x;
233 void PivotCacheItem::readString( BiffInputStream& rStrm, const WorkbookHelper& rHelper )
235 maValue <<= (rHelper.getBiff() == BIFF8) ? rStrm.readUniString() : rStrm.readByteStringUC( true, rHelper.getTextEncoding() );
236 mnType = XML_s;
239 void PivotCacheItem::readDouble( BiffInputStream& rStrm )
241 maValue <<= rStrm.readDouble();
242 mnType = XML_n;
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;
262 mnType = XML_d;
265 void PivotCacheItem::readBool( BiffInputStream& rStrm )
267 maValue <<= (rStrm.readuInt8() != 0);
268 mnType = XML_b;
271 void PivotCacheItem::readError( BiffInputStream& rStrm )
273 maValue <<= static_cast< sal_Int32 >( rStrm.readuInt8() );
274 mnType = XML_e;
277 void PivotCacheItem::setStringValue( const OUString& sString )
279 mnType = XML_s;
280 maValue <<= sString;
283 OUString PivotCacheItem::getName() const
285 switch( mnType )
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" );
296 return OUString();
299 PivotCacheItemList::PivotCacheItemList( const WorkbookHelper& rHelper ) :
300 WorkbookHelper( rHelper )
304 void PivotCacheItemList::importItem( sal_Int32 nElement, const AttributeList& rAttribs )
306 PivotCacheItem& rItem = createItem();
307 switch( nElement )
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 );
324 return;
327 PivotCacheItem& rItem = createItem();
328 switch( nRecId )
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 )
348 bool bLoop = true;
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
383 orItemNames.clear();
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 )
403 switch( nType )
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;
409 default:
410 OSL_FAIL( "PivotCacheItemList::importArray - unknown data type" );
411 nIdx = nCount;
416 PCFieldModel::PCFieldModel() :
417 mnNumFmtId( 0 ),
418 mnSqlType( 0 ),
419 mnHierarchy( 0 ),
420 mnLevel( 0 ),
421 mnMappingCount( 0 ),
422 mbDatabaseField( true ),
423 mbServerField( false ),
424 mbUniqueList( true ),
425 mbMemberPropField( false )
429 PCSharedItemsModel::PCSharedItemsModel() :
430 mbHasSemiMixed( true ),
431 mbHasNonDate( true ),
432 mbHasDate( false ),
433 mbHasString( true ),
434 mbHasBlank( false ),
435 mbHasMixed( false ),
436 mbIsNumeric( false ),
437 mbIsInteger( false ),
438 mbHasLongText( false ),
439 mbHasLongIndexes( false )
443 PCFieldGroupModel::PCFieldGroupModel() :
444 mfStartValue( 0.0 ),
445 mfEndValue( 0.0 ),
446 mfInterval( 1.0 ),
447 mnParentField( -1 ),
448 mnBaseField( -1 ),
449 mnGroupBy( XML_range ),
450 mbRangeGroup( false ),
451 mbDateGroup( false ),
452 mbAutoStart( true ),
453 mbAutoEnd( true )
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 )
542 sal_uInt16 nFlags;
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 )
567 sal_uInt16 nFlags;
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;
629 rStrm >> nFlags;
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 )
656 SAL_WARN_IF(
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 )
676 SAL_WARN_IF(
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 )
685 sal_uInt16 nFlags;
686 rStrm >> nFlags;
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" );
709 if( bHasTypes )
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 >();
716 else
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" );
720 if( bHasTypes )
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 );
743 return 0;
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() )
765 return maGroupItems;
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 );
822 catch( Exception& )
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 ) )
850 continue;
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" );
861 if( !aIt->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
869 item names. */
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. */
901 OUString aFirstItem;
902 if( const PivotCacheGroupItem* pName = ContainerHelper::getVectorElement( orItemNames, aIt->front() ) )
903 aFirstItem = pName->maOrigName;
904 Reference< XNamed > xGroupName;
905 OUString aAutoName;
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();
916 catch( Exception& )
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
922 OUString aGroupName;
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;
943 catch( Exception& )
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
955 CellModel aModel;
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" );
964 if( bHasIndex )
965 writeSharedItemToSourceDataCell( rSheetHelper, nCol, nRow, rItem.getValue().get< sal_Int32 >() );
966 else
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() );
976 else
978 PivotCacheItem aItem;
979 if( maSharedItemsModel.mbIsNumeric )
980 aItem.readDouble( rStrm );
981 else if( maSharedItemsModel.mbHasDate && !maSharedItemsModel.mbHasString )
982 aItem.readDate( rStrm );
983 else
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 )
1003 CellModel aModel;
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 ),
1028 mnRecords( 0 ),
1029 mnMissItemsLimit( 0 ),
1030 mnDatabaseFields( 0 ),
1031 mbInvalid( false ),
1032 mbSaveData( true ),
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 ),
1046 mnConnectionId( 0 )
1050 PCWorksheetSourceModel::PCWorksheetSourceModel()
1052 maRange.StartColumn = maRange.StartRow = maRange.EndColumn = maRange.EndRow = -1;
1055 PivotCache::PivotCache( const WorkbookHelper& rHelper ) :
1056 WorkbookHelper( rHelper ),
1057 mnCurrRow( -1 ),
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 )
1149 BinRange aBinRange;
1150 rStrm >> aBinRange;
1151 // store range address unchecked with sheet index 0, will be resolved/checked later
1152 AddressConverter::convertToCellRangeUnchecked( maSheetSrcModel.maRange, aBinRange, 0 );
1154 else
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
1170 rStrm >> nFlags;
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 );
1212 else
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 )
1222 case XML_worksheet:
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" );
1228 if( bInternal )
1229 finalizeInternalSheetSource();
1230 else if( bExternal )
1231 finalizeExternalSheetSource();
1233 break;
1235 // currently, we only support worksheet data sources
1236 case XML_external:
1237 break;
1238 case XML_consolidation:
1239 break;
1240 case XML_scenario:
1241 break;
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;
1267 mnCurrRow = -1;
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 );
1320 // table
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;
1326 if( mbValidSource )
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
1342 return;
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 );
1384 mnCurrRow = nRow;
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. */
1410 case FILTER_OOXML:
1412 // try to find an imported pivot cache
1413 if( PivotCache* pCache = maCaches.get( nCacheId ).get() )
1414 return pCache;
1416 // check if a fragment path exists for the passed cache identifier
1417 FragmentPathMap::iterator aIt = maFragmentPaths.find( nCacheId );
1418 if( aIt == maFragmentPaths.end() )
1419 return 0;
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 ) );
1425 return &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. */
1437 case FILTER_BIFF:
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();
1443 if( !pCache )
1444 return 0;
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 );
1457 return pCache;
1460 case FILTER_UNKNOWN:
1461 OSL_FAIL( "PivotCacheBuffer::importPivotCacheFragment - unknown filter type" );
1463 return 0;
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 ) );
1471 return *rxCache;
1474 } // namespace xls
1475 } // namespace oox
1477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */