1*ca5ec200SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*ca5ec200SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*ca5ec200SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*ca5ec200SAndrew Rist * distributed with this work for additional information 6*ca5ec200SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*ca5ec200SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*ca5ec200SAndrew Rist * "License"); you may not use this file except in compliance 9*ca5ec200SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*ca5ec200SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*ca5ec200SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*ca5ec200SAndrew Rist * software distributed under the License is distributed on an 15*ca5ec200SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*ca5ec200SAndrew Rist * KIND, either express or implied. See the License for the 17*ca5ec200SAndrew Rist * specific language governing permissions and limitations 18*ca5ec200SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*ca5ec200SAndrew Rist *************************************************************/ 21*ca5ec200SAndrew Rist 22*ca5ec200SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "oox/xls/pivotcachefragment.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include "oox/helper/attributelist.hxx" 27cdf0e10cSrcweir #include "oox/xls/addressconverter.hxx" 28cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx" 29cdf0e10cSrcweir #include "oox/xls/pivotcachebuffer.hxx" 30cdf0e10cSrcweir 31cdf0e10cSrcweir namespace oox { 32cdf0e10cSrcweir namespace xls { 33cdf0e10cSrcweir 34cdf0e10cSrcweir // ============================================================================ 35cdf0e10cSrcweir 36cdf0e10cSrcweir using namespace ::com::sun::star::uno; 37cdf0e10cSrcweir using namespace ::oox::core; 38cdf0e10cSrcweir 39cdf0e10cSrcweir using ::rtl::OUString; 40cdf0e10cSrcweir 41cdf0e10cSrcweir // ============================================================================ 42cdf0e10cSrcweir 43cdf0e10cSrcweir PivotCacheFieldContext::PivotCacheFieldContext( WorkbookFragmentBase& rFragment, PivotCacheField& rCacheField ) : 44cdf0e10cSrcweir WorkbookContextBase( rFragment ), 45cdf0e10cSrcweir mrCacheField( rCacheField ) 46cdf0e10cSrcweir { 47cdf0e10cSrcweir } 48cdf0e10cSrcweir 49cdf0e10cSrcweir ContextHandlerRef PivotCacheFieldContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) 50cdf0e10cSrcweir { 51cdf0e10cSrcweir switch( getCurrentElement() ) 52cdf0e10cSrcweir { 53cdf0e10cSrcweir case XLS_TOKEN( cacheField ): 54cdf0e10cSrcweir if( nElement == XLS_TOKEN( sharedItems ) ) { mrCacheField.importSharedItems( rAttribs ); return this; } 55cdf0e10cSrcweir if( nElement == XLS_TOKEN( fieldGroup ) ) { mrCacheField.importFieldGroup( rAttribs ); return this; } 56cdf0e10cSrcweir break; 57cdf0e10cSrcweir 58cdf0e10cSrcweir case XLS_TOKEN( fieldGroup ): 59cdf0e10cSrcweir switch( nElement ) 60cdf0e10cSrcweir { 61cdf0e10cSrcweir case XLS_TOKEN( rangePr ): mrCacheField.importRangePr( rAttribs ); break; 62cdf0e10cSrcweir case XLS_TOKEN( discretePr ): return this; 63cdf0e10cSrcweir case XLS_TOKEN( groupItems ): return this; 64cdf0e10cSrcweir } 65cdf0e10cSrcweir break; 66cdf0e10cSrcweir 67cdf0e10cSrcweir case XLS_TOKEN( sharedItems ): mrCacheField.importSharedItem( nElement, rAttribs ); break; 68cdf0e10cSrcweir case XLS_TOKEN( discretePr ): mrCacheField.importDiscretePrItem( nElement, rAttribs ); break; 69cdf0e10cSrcweir case XLS_TOKEN( groupItems ): mrCacheField.importGroupItem( nElement, rAttribs ); break; 70cdf0e10cSrcweir } 71cdf0e10cSrcweir return 0; 72cdf0e10cSrcweir } 73cdf0e10cSrcweir 74cdf0e10cSrcweir void PivotCacheFieldContext::onStartElement( const AttributeList& rAttribs ) 75cdf0e10cSrcweir { 76cdf0e10cSrcweir if( isRootElement() ) 77cdf0e10cSrcweir mrCacheField.importCacheField( rAttribs ); 78cdf0e10cSrcweir } 79cdf0e10cSrcweir 80cdf0e10cSrcweir ContextHandlerRef PivotCacheFieldContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 81cdf0e10cSrcweir { 82cdf0e10cSrcweir switch( getCurrentElement() ) 83cdf0e10cSrcweir { 84cdf0e10cSrcweir case BIFF12_ID_PCDFIELD: 85cdf0e10cSrcweir switch( nRecId ) 86cdf0e10cSrcweir { 87cdf0e10cSrcweir case BIFF12_ID_PCDFSHAREDITEMS: mrCacheField.importPCDFSharedItems( rStrm ); return this; 88cdf0e10cSrcweir case BIFF12_ID_PCDFIELDGROUP: mrCacheField.importPCDFieldGroup( rStrm ); return this; 89cdf0e10cSrcweir } 90cdf0e10cSrcweir break; 91cdf0e10cSrcweir 92cdf0e10cSrcweir case BIFF12_ID_PCDFIELDGROUP: 93cdf0e10cSrcweir switch( nRecId ) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir case BIFF12_ID_PCDFRANGEPR: mrCacheField.importPCDFRangePr( rStrm ); break; 96cdf0e10cSrcweir case BIFF12_ID_PCDFDISCRETEPR: return this; 97cdf0e10cSrcweir case BIFF12_ID_PCDFGROUPITEMS: return this; 98cdf0e10cSrcweir } 99cdf0e10cSrcweir break; 100cdf0e10cSrcweir 101cdf0e10cSrcweir case BIFF12_ID_PCDFSHAREDITEMS: mrCacheField.importPCDFSharedItem( nRecId, rStrm ); break; 102cdf0e10cSrcweir case BIFF12_ID_PCDFDISCRETEPR: mrCacheField.importPCDFDiscretePrItem( nRecId, rStrm ); break; 103cdf0e10cSrcweir case BIFF12_ID_PCDFGROUPITEMS: mrCacheField.importPCDFGroupItem( nRecId, rStrm ); break; 104cdf0e10cSrcweir } 105cdf0e10cSrcweir return 0; 106cdf0e10cSrcweir } 107cdf0e10cSrcweir 108cdf0e10cSrcweir void PivotCacheFieldContext::onStartRecord( SequenceInputStream& rStrm ) 109cdf0e10cSrcweir { 110cdf0e10cSrcweir if( isRootElement() ) 111cdf0e10cSrcweir mrCacheField.importPCDField( rStrm ); 112cdf0e10cSrcweir } 113cdf0e10cSrcweir 114cdf0e10cSrcweir // ============================================================================ 115cdf0e10cSrcweir 116cdf0e10cSrcweir PivotCacheDefinitionFragment::PivotCacheDefinitionFragment( 117cdf0e10cSrcweir const WorkbookHelper& rHelper, const OUString& rFragmentPath, PivotCache& rPivotCache ) : 118cdf0e10cSrcweir WorkbookFragmentBase( rHelper, rFragmentPath ), 119cdf0e10cSrcweir mrPivotCache( rPivotCache ) 120cdf0e10cSrcweir { 121cdf0e10cSrcweir } 122cdf0e10cSrcweir 123cdf0e10cSrcweir ContextHandlerRef PivotCacheDefinitionFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) 124cdf0e10cSrcweir { 125cdf0e10cSrcweir switch( getCurrentElement() ) 126cdf0e10cSrcweir { 127cdf0e10cSrcweir case XML_ROOT_CONTEXT: 128cdf0e10cSrcweir if( nElement == XLS_TOKEN( pivotCacheDefinition ) ) { mrPivotCache.importPivotCacheDefinition( rAttribs ); return this; } 129cdf0e10cSrcweir break; 130cdf0e10cSrcweir 131cdf0e10cSrcweir case XLS_TOKEN( pivotCacheDefinition ): 132cdf0e10cSrcweir switch( nElement ) 133cdf0e10cSrcweir { 134cdf0e10cSrcweir case XLS_TOKEN( cacheSource ): mrPivotCache.importCacheSource( rAttribs ); return this; 135cdf0e10cSrcweir case XLS_TOKEN( cacheFields ): return this; 136cdf0e10cSrcweir } 137cdf0e10cSrcweir break; 138cdf0e10cSrcweir 139cdf0e10cSrcweir case XLS_TOKEN( cacheSource ): 140cdf0e10cSrcweir if( nElement == XLS_TOKEN( worksheetSource ) ) mrPivotCache.importWorksheetSource( rAttribs, getRelations() ); 141cdf0e10cSrcweir break; 142cdf0e10cSrcweir 143cdf0e10cSrcweir case XLS_TOKEN( cacheFields ): 144cdf0e10cSrcweir if( nElement == XLS_TOKEN( cacheField ) ) return new PivotCacheFieldContext( *this, mrPivotCache.createCacheField() ); 145cdf0e10cSrcweir break; 146cdf0e10cSrcweir } 147cdf0e10cSrcweir return 0; 148cdf0e10cSrcweir } 149cdf0e10cSrcweir 150cdf0e10cSrcweir ContextHandlerRef PivotCacheDefinitionFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 151cdf0e10cSrcweir { 152cdf0e10cSrcweir switch( getCurrentElement() ) 153cdf0e10cSrcweir { 154cdf0e10cSrcweir case XML_ROOT_CONTEXT: 155cdf0e10cSrcweir if( nRecId == BIFF12_ID_PCDEFINITION ) { mrPivotCache.importPCDefinition( rStrm ); return this; } 156cdf0e10cSrcweir break; 157cdf0e10cSrcweir 158cdf0e10cSrcweir case BIFF12_ID_PCDEFINITION: 159cdf0e10cSrcweir switch( nRecId ) 160cdf0e10cSrcweir { 161cdf0e10cSrcweir case BIFF12_ID_PCDSOURCE: mrPivotCache.importPCDSource( rStrm ); return this; 162cdf0e10cSrcweir case BIFF12_ID_PCDFIELDS: return this; 163cdf0e10cSrcweir } 164cdf0e10cSrcweir break; 165cdf0e10cSrcweir 166cdf0e10cSrcweir case BIFF12_ID_PCDSOURCE: 167cdf0e10cSrcweir if( nRecId == BIFF12_ID_PCDSHEETSOURCE ) mrPivotCache.importPCDSheetSource( rStrm, getRelations() ); 168cdf0e10cSrcweir break; 169cdf0e10cSrcweir 170cdf0e10cSrcweir case BIFF12_ID_PCDFIELDS: 171cdf0e10cSrcweir if( nRecId == BIFF12_ID_PCDFIELD ) return new PivotCacheFieldContext( *this, mrPivotCache.createCacheField() ); 172cdf0e10cSrcweir break; 173cdf0e10cSrcweir } 174cdf0e10cSrcweir return 0; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir 177cdf0e10cSrcweir const RecordInfo* PivotCacheDefinitionFragment::getRecordInfos() const 178cdf0e10cSrcweir { 179cdf0e10cSrcweir static const RecordInfo spRecInfos[] = 180cdf0e10cSrcweir { 181cdf0e10cSrcweir { BIFF12_ID_PCDEFINITION, BIFF12_ID_PCDEFINITION + 1 }, 182cdf0e10cSrcweir { BIFF12_ID_PCDFDISCRETEPR, BIFF12_ID_PCDFDISCRETEPR + 1 }, 183cdf0e10cSrcweir { BIFF12_ID_PCDFGROUPITEMS, BIFF12_ID_PCDFGROUPITEMS + 1 }, 184cdf0e10cSrcweir { BIFF12_ID_PCDFIELD, BIFF12_ID_PCDFIELD + 1 }, 185cdf0e10cSrcweir { BIFF12_ID_PCDFIELDGROUP, BIFF12_ID_PCDFIELDGROUP + 1 }, 186cdf0e10cSrcweir { BIFF12_ID_PCDFIELDS, BIFF12_ID_PCDFIELDS + 1 }, 187cdf0e10cSrcweir { BIFF12_ID_PCDFRANGEPR, BIFF12_ID_PCDFRANGEPR + 1 }, 188cdf0e10cSrcweir { BIFF12_ID_PCDFSHAREDITEMS, BIFF12_ID_PCDFSHAREDITEMS + 1 }, 189cdf0e10cSrcweir { BIFF12_ID_PCITEM_ARRAY, BIFF12_ID_PCITEM_ARRAY + 1 }, 190cdf0e10cSrcweir { BIFF12_ID_PCDSHEETSOURCE, BIFF12_ID_PCDSHEETSOURCE + 1 }, 191cdf0e10cSrcweir { BIFF12_ID_PCDSOURCE, BIFF12_ID_PCDSOURCE + 1 }, 192cdf0e10cSrcweir { -1, -1 } 193cdf0e10cSrcweir }; 194cdf0e10cSrcweir return spRecInfos; 195cdf0e10cSrcweir } 196cdf0e10cSrcweir 197cdf0e10cSrcweir void PivotCacheDefinitionFragment::finalizeImport() 198cdf0e10cSrcweir { 199cdf0e10cSrcweir // finalize the cache (check source range etc.) 200cdf0e10cSrcweir mrPivotCache.finalizeImport(); 201cdf0e10cSrcweir 202cdf0e10cSrcweir // load the cache records, if the cache is based on a deleted or an external worksheet 203cdf0e10cSrcweir if( mrPivotCache.isValidDataSource() && mrPivotCache.isBasedOnDummySheet() ) 204cdf0e10cSrcweir { 205cdf0e10cSrcweir OUString aRecFragmentPath = getRelations().getFragmentPathFromRelId( mrPivotCache.getRecordsRelId() ); 206cdf0e10cSrcweir if( aRecFragmentPath.getLength() > 0 ) 207cdf0e10cSrcweir { 208cdf0e10cSrcweir sal_Int16 nSheet = mrPivotCache.getSourceRange().Sheet; 209cdf0e10cSrcweir WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, nSheet ); 210cdf0e10cSrcweir if( xSheetGlob.get() ) 211cdf0e10cSrcweir importOoxFragment( new PivotCacheRecordsFragment( *xSheetGlob, aRecFragmentPath, mrPivotCache ) ); 212cdf0e10cSrcweir } 213cdf0e10cSrcweir } 214cdf0e10cSrcweir } 215cdf0e10cSrcweir 216cdf0e10cSrcweir // ============================================================================ 217cdf0e10cSrcweir 218cdf0e10cSrcweir PivotCacheRecordsFragment::PivotCacheRecordsFragment( const WorksheetHelper& rHelper, 219cdf0e10cSrcweir const OUString& rFragmentPath, const PivotCache& rPivotCache ) : 220cdf0e10cSrcweir WorksheetFragmentBase( rHelper, rFragmentPath ), 221cdf0e10cSrcweir mrPivotCache( rPivotCache ), 222cdf0e10cSrcweir mnColIdx( 0 ), 223cdf0e10cSrcweir mnRowIdx( 0 ), 224cdf0e10cSrcweir mbInRecord( false ) 225cdf0e10cSrcweir { 226cdf0e10cSrcweir // prepare sheet: insert column header names into top row 227cdf0e10cSrcweir rPivotCache.writeSourceHeaderCells( *this ); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir 230cdf0e10cSrcweir ContextHandlerRef PivotCacheRecordsFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) 231cdf0e10cSrcweir { 232cdf0e10cSrcweir switch( getCurrentElement() ) 233cdf0e10cSrcweir { 234cdf0e10cSrcweir case XML_ROOT_CONTEXT: 235cdf0e10cSrcweir if( nElement == XLS_TOKEN( pivotCacheRecords ) ) return this; 236cdf0e10cSrcweir break; 237cdf0e10cSrcweir 238cdf0e10cSrcweir case XLS_TOKEN( pivotCacheRecords ): 239cdf0e10cSrcweir if( nElement == XLS_TOKEN( r ) ) { startCacheRecord(); return this; } 240cdf0e10cSrcweir break; 241cdf0e10cSrcweir 242cdf0e10cSrcweir case XLS_TOKEN( r ): 243cdf0e10cSrcweir { 244cdf0e10cSrcweir PivotCacheItem aItem; 245cdf0e10cSrcweir switch( nElement ) 246cdf0e10cSrcweir { 247cdf0e10cSrcweir case XLS_TOKEN( m ): break; 248cdf0e10cSrcweir case XLS_TOKEN( s ): aItem.readString( rAttribs ); break; 249cdf0e10cSrcweir case XLS_TOKEN( n ): aItem.readNumeric( rAttribs ); break; 250cdf0e10cSrcweir case XLS_TOKEN( d ): aItem.readDate( rAttribs ); break; 251cdf0e10cSrcweir case XLS_TOKEN( b ): aItem.readBool( rAttribs ); break; 252cdf0e10cSrcweir case XLS_TOKEN( e ): aItem.readError( rAttribs, getUnitConverter() ); break; 253cdf0e10cSrcweir case XLS_TOKEN( x ): aItem.readIndex( rAttribs ); break; 254cdf0e10cSrcweir default: OSL_ENSURE( false, "PivotCacheRecordsFragment::onCreateContext - unexpected element" ); 255cdf0e10cSrcweir } 256cdf0e10cSrcweir mrPivotCache.writeSourceDataCell( *this, mnColIdx, mnRowIdx, aItem ); 257cdf0e10cSrcweir ++mnColIdx; 258cdf0e10cSrcweir } 259cdf0e10cSrcweir break; 260cdf0e10cSrcweir } 261cdf0e10cSrcweir return 0; 262cdf0e10cSrcweir } 263cdf0e10cSrcweir 264cdf0e10cSrcweir ContextHandlerRef PivotCacheRecordsFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) 265cdf0e10cSrcweir { 266cdf0e10cSrcweir switch( getCurrentElement() ) 267cdf0e10cSrcweir { 268cdf0e10cSrcweir case XML_ROOT_CONTEXT: 269cdf0e10cSrcweir if( nRecId == BIFF12_ID_PCRECORDS ) return this; 270cdf0e10cSrcweir break; 271cdf0e10cSrcweir 272cdf0e10cSrcweir case BIFF12_ID_PCRECORDS: 273cdf0e10cSrcweir switch( nRecId ) 274cdf0e10cSrcweir { 275cdf0e10cSrcweir case BIFF12_ID_PCRECORD: importPCRecord( rStrm ); break; 276cdf0e10cSrcweir case BIFF12_ID_PCRECORDDT: startCacheRecord(); break; 277cdf0e10cSrcweir default: importPCRecordItem( nRecId, rStrm ); break; 278cdf0e10cSrcweir } 279cdf0e10cSrcweir break; 280cdf0e10cSrcweir } 281cdf0e10cSrcweir return 0; 282cdf0e10cSrcweir } 283cdf0e10cSrcweir 284cdf0e10cSrcweir const RecordInfo* PivotCacheRecordsFragment::getRecordInfos() const 285cdf0e10cSrcweir { 286cdf0e10cSrcweir static const RecordInfo spRecInfos[] = 287cdf0e10cSrcweir { 288cdf0e10cSrcweir { BIFF12_ID_PCRECORDS, BIFF12_ID_PCRECORDS + 1 }, 289cdf0e10cSrcweir { -1, -1 } 290cdf0e10cSrcweir }; 291cdf0e10cSrcweir return spRecInfos; 292cdf0e10cSrcweir } 293cdf0e10cSrcweir 294cdf0e10cSrcweir // private -------------------------------------------------------------------- 295cdf0e10cSrcweir 296cdf0e10cSrcweir void PivotCacheRecordsFragment::startCacheRecord() 297cdf0e10cSrcweir { 298cdf0e10cSrcweir mnColIdx = 0; 299cdf0e10cSrcweir ++mnRowIdx; 300cdf0e10cSrcweir mbInRecord = true; 301cdf0e10cSrcweir } 302cdf0e10cSrcweir 303cdf0e10cSrcweir void PivotCacheRecordsFragment::importPCRecord( SequenceInputStream& rStrm ) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir startCacheRecord(); 306cdf0e10cSrcweir mrPivotCache.importPCRecord( rStrm, *this, mnRowIdx ); 307cdf0e10cSrcweir mbInRecord = false; 308cdf0e10cSrcweir } 309cdf0e10cSrcweir 310cdf0e10cSrcweir void PivotCacheRecordsFragment::importPCRecordItem( sal_Int32 nRecId, SequenceInputStream& rStrm ) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir if( mbInRecord ) 313cdf0e10cSrcweir { 314cdf0e10cSrcweir PivotCacheItem aItem; 315cdf0e10cSrcweir switch( nRecId ) 316cdf0e10cSrcweir { 317cdf0e10cSrcweir case BIFF12_ID_PCITEM_MISSING: break; 318cdf0e10cSrcweir case BIFF12_ID_PCITEM_STRING: aItem.readString( rStrm ); break; 319cdf0e10cSrcweir case BIFF12_ID_PCITEM_DOUBLE: aItem.readDouble( rStrm ); break; 320cdf0e10cSrcweir case BIFF12_ID_PCITEM_DATE: aItem.readDate( rStrm ); break; 321cdf0e10cSrcweir case BIFF12_ID_PCITEM_BOOL: aItem.readBool( rStrm ); break; 322cdf0e10cSrcweir case BIFF12_ID_PCITEM_ERROR: aItem.readError( rStrm ); break; 323cdf0e10cSrcweir case BIFF12_ID_PCITEM_INDEX: aItem.readIndex( rStrm ); break; 324cdf0e10cSrcweir default: OSL_ENSURE( false, "PivotCacheRecordsFragment::importPCRecordItem - unexpected record" ); 325cdf0e10cSrcweir } 326cdf0e10cSrcweir mrPivotCache.writeSourceDataCell( *this, mnColIdx, mnRowIdx, aItem ); 327cdf0e10cSrcweir ++mnColIdx; 328cdf0e10cSrcweir } 329cdf0e10cSrcweir } 330cdf0e10cSrcweir 331cdf0e10cSrcweir // ============================================================================ 332cdf0e10cSrcweir // ============================================================================ 333cdf0e10cSrcweir 334cdf0e10cSrcweir namespace { 335cdf0e10cSrcweir 336cdf0e10cSrcweir bool lclSeekToPCDField( BiffInputStream& rStrm ) 337cdf0e10cSrcweir { 338cdf0e10cSrcweir sal_Int64 nRecHandle = rStrm.getRecHandle(); 339cdf0e10cSrcweir while( rStrm.startNextRecord() ) 340cdf0e10cSrcweir if( rStrm.getRecId() == BIFF_ID_PCDFIELD ) 341cdf0e10cSrcweir return true; 342cdf0e10cSrcweir rStrm.startRecordByHandle( nRecHandle ); 343cdf0e10cSrcweir return false; 344cdf0e10cSrcweir } 345cdf0e10cSrcweir 346cdf0e10cSrcweir } // namespace 347cdf0e10cSrcweir 348cdf0e10cSrcweir // ---------------------------------------------------------------------------- 349cdf0e10cSrcweir 350cdf0e10cSrcweir BiffPivotCacheFragment::BiffPivotCacheFragment( 351cdf0e10cSrcweir const WorkbookHelper& rHelper, const OUString& rStrmName, PivotCache& rPivotCache ) : 352cdf0e10cSrcweir BiffWorkbookFragmentBase( rHelper, rStrmName, true ), 353cdf0e10cSrcweir mrPivotCache( rPivotCache ) 354cdf0e10cSrcweir { 355cdf0e10cSrcweir } 356cdf0e10cSrcweir 357cdf0e10cSrcweir bool BiffPivotCacheFragment::importFragment() 358cdf0e10cSrcweir { 359cdf0e10cSrcweir BiffInputStream& rStrm = getInputStream(); 360cdf0e10cSrcweir if( rStrm.startNextRecord() && (rStrm.getRecId() == BIFF_ID_PCDEFINITION) ) 361cdf0e10cSrcweir { 362cdf0e10cSrcweir // read PCDEFINITION and optional PCDEFINITION2 records 363cdf0e10cSrcweir mrPivotCache.importPCDefinition( rStrm ); 364cdf0e10cSrcweir 365cdf0e10cSrcweir // read cache fields as long as another PCDFIELD record can be found 366cdf0e10cSrcweir while( lclSeekToPCDField( rStrm ) ) 367cdf0e10cSrcweir mrPivotCache.createCacheField( true ).importPCDField( rStrm ); 368cdf0e10cSrcweir 369cdf0e10cSrcweir // finalize the cache (check source range etc.) 370cdf0e10cSrcweir mrPivotCache.finalizeImport(); 371cdf0e10cSrcweir 372cdf0e10cSrcweir // load the cache records, if the cache is based on a deleted or an external worksheet 373cdf0e10cSrcweir if( mrPivotCache.isValidDataSource() && mrPivotCache.isBasedOnDummySheet() ) 374cdf0e10cSrcweir { 375cdf0e10cSrcweir /* Last call of lclSeekToPCDField() failed and kept stream position 376cdf0e10cSrcweir unchanged. Stream should point to source data table now. */ 377cdf0e10cSrcweir sal_Int16 nSheet = mrPivotCache.getSourceRange().Sheet; 378cdf0e10cSrcweir WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, nSheet ); 379cdf0e10cSrcweir if( xSheetGlob.get() ) 380cdf0e10cSrcweir { 381cdf0e10cSrcweir BiffPivotCacheRecordsContext aContext( *xSheetGlob, mrPivotCache ); 382cdf0e10cSrcweir while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) 383cdf0e10cSrcweir aContext.importRecord( rStrm ); 384cdf0e10cSrcweir } 385cdf0e10cSrcweir } 386cdf0e10cSrcweir } 387cdf0e10cSrcweir 388cdf0e10cSrcweir return rStrm.getRecId() == BIFF_ID_EOF; 389cdf0e10cSrcweir } 390cdf0e10cSrcweir 391cdf0e10cSrcweir // ============================================================================ 392cdf0e10cSrcweir 393cdf0e10cSrcweir BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext( const WorksheetHelper& rHelper, const PivotCache& rPivotCache ) : 394cdf0e10cSrcweir BiffWorksheetContextBase( rHelper ), 395cdf0e10cSrcweir mrPivotCache( rPivotCache ), 396cdf0e10cSrcweir mnColIdx( 0 ), 397cdf0e10cSrcweir mnRowIdx( 0 ), 398cdf0e10cSrcweir mbHasShared( false ), 399cdf0e10cSrcweir mbInRow( false ) 400cdf0e10cSrcweir { 401cdf0e10cSrcweir // prepare sheet: insert column header names into top row 402cdf0e10cSrcweir mrPivotCache.writeSourceHeaderCells( *this ); 403cdf0e10cSrcweir 404cdf0e10cSrcweir // find all fields without shared items, remember column indexes in source data 405cdf0e10cSrcweir for( sal_Int32 nFieldIdx = 0, nFieldCount = mrPivotCache.getCacheFieldCount(), nCol = 0; nFieldIdx < nFieldCount; ++nFieldIdx ) 406cdf0e10cSrcweir { 407cdf0e10cSrcweir const PivotCacheField* pCacheField = mrPivotCache.getCacheField( nFieldIdx ); 408cdf0e10cSrcweir if( pCacheField && pCacheField->isDatabaseField() ) 409cdf0e10cSrcweir { 410cdf0e10cSrcweir if( pCacheField->hasSharedItems() ) 411cdf0e10cSrcweir mbHasShared = true; 412cdf0e10cSrcweir else 413cdf0e10cSrcweir maUnsharedCols.push_back( nCol ); 414cdf0e10cSrcweir ++nCol; 415cdf0e10cSrcweir } 416cdf0e10cSrcweir } 417cdf0e10cSrcweir } 418cdf0e10cSrcweir 419cdf0e10cSrcweir void BiffPivotCacheRecordsContext::importRecord( BiffInputStream& rStrm ) 420cdf0e10cSrcweir { 421cdf0e10cSrcweir if( rStrm.getRecId() == BIFF_ID_PCITEM_INDEXLIST ) 422cdf0e10cSrcweir { 423cdf0e10cSrcweir OSL_ENSURE( mbHasShared, "BiffPivotCacheRecordsContext::importRecord - unexpected PCITEM_INDEXLIST record" ); 424cdf0e10cSrcweir // PCITEM_INDEXLIST record always in front of a new data row 425cdf0e10cSrcweir startNextRow(); 426cdf0e10cSrcweir mrPivotCache.importPCItemIndexList( rStrm, *this, mnRowIdx ); 427cdf0e10cSrcweir mbInRow = !maUnsharedCols.empty(); // mbInRow remains true, if unshared items are expected 428cdf0e10cSrcweir return; 429cdf0e10cSrcweir } 430cdf0e10cSrcweir 431cdf0e10cSrcweir PivotCacheItem aItem; 432cdf0e10cSrcweir switch( rStrm.getRecId() ) 433cdf0e10cSrcweir { 434cdf0e10cSrcweir case BIFF_ID_PCITEM_MISSING: break; 435cdf0e10cSrcweir case BIFF_ID_PCITEM_STRING: aItem.readString( rStrm, *this ); break; 436cdf0e10cSrcweir case BIFF_ID_PCITEM_DOUBLE: aItem.readDouble( rStrm ); break; 437cdf0e10cSrcweir case BIFF_ID_PCITEM_INTEGER: aItem.readInteger( rStrm ); break; 438cdf0e10cSrcweir case BIFF_ID_PCITEM_DATE: aItem.readDate( rStrm ); break; 439cdf0e10cSrcweir case BIFF_ID_PCITEM_BOOL: aItem.readBool( rStrm ); break; 440cdf0e10cSrcweir case BIFF_ID_PCITEM_ERROR: aItem.readError( rStrm ); break; 441cdf0e10cSrcweir default: return; // unknown record, ignore 442cdf0e10cSrcweir } 443cdf0e10cSrcweir 444cdf0e10cSrcweir // find next column index, might start new row if no fields with shared items exist 445cdf0e10cSrcweir if( mbInRow && (mnColIdx == maUnsharedCols.size()) ) 446cdf0e10cSrcweir { 447cdf0e10cSrcweir OSL_ENSURE( !mbHasShared, "BiffPivotCacheRecordsContext::importRecord - PCITEM_INDEXLIST record missing" ); 448cdf0e10cSrcweir mbInRow = mbHasShared; // do not leave current row if PCITEM_INDEXLIST is expected 449cdf0e10cSrcweir } 450cdf0e10cSrcweir // start next row on first call, or on row wrap without shared items 451cdf0e10cSrcweir if( !mbInRow ) 452cdf0e10cSrcweir startNextRow(); 453cdf0e10cSrcweir 454cdf0e10cSrcweir // write the item data to the sheet cell 455cdf0e10cSrcweir OSL_ENSURE( mnColIdx < maUnsharedCols.size(), "BiffPivotCacheRecordsContext::importRecord - invalid column index" ); 456cdf0e10cSrcweir if( mnColIdx < maUnsharedCols.size() ) 457cdf0e10cSrcweir mrPivotCache.writeSourceDataCell( *this, maUnsharedCols[ mnColIdx ], mnRowIdx, aItem ); 458cdf0e10cSrcweir ++mnColIdx; 459cdf0e10cSrcweir } 460cdf0e10cSrcweir 461cdf0e10cSrcweir void BiffPivotCacheRecordsContext::startNextRow() 462cdf0e10cSrcweir { 463cdf0e10cSrcweir mnColIdx = 0; 464cdf0e10cSrcweir ++mnRowIdx; 465cdf0e10cSrcweir mbInRow = true; 466cdf0e10cSrcweir } 467cdf0e10cSrcweir 468cdf0e10cSrcweir // ============================================================================ 469cdf0e10cSrcweir 470cdf0e10cSrcweir } // namespace xls 471cdf0e10cSrcweir } // namespace oox 472