1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #pragma once 21 22 #include <com/sun/star/util/DateTime.hpp> 23 #include <oox/helper/containerhelper.hxx> 24 #include <oox/helper/refvector.hxx> 25 #include "workbookhelper.hxx" 26 27 namespace oox { class AttributeList; } 28 namespace oox { class SequenceInputStream; } 29 30 namespace com::sun::star { 31 namespace sheet { class XDataPilotField; } 32 } 33 34 namespace oox::core { class Relations; } 35 36 class ScDPSaveDimension; 37 class ScDPObject; 38 class DateTime; 39 40 namespace oox::xls { 41 42 class WorksheetHelper; 43 44 typedef ::std::pair< sal_Int32, OUString > IdCaptionPair; 45 typedef ::std::vector< IdCaptionPair > IdCaptionPairList; 46 47 class PivotCacheItem 48 { 49 public: 50 explicit PivotCacheItem(); 51 52 /** Reads the string value from a pivot cache item. */ 53 void readString( const AttributeList& rAttribs ); 54 /** Reads the double value from a pivot cache item. */ 55 void readNumeric( const AttributeList& rAttribs ); 56 /** Reads the date/time value from a pivot cache item. */ 57 void readDate( const AttributeList& rAttribs ); 58 /** Reads the boolean value from a pivot cache item. */ 59 void readBool( const AttributeList& rAttribs ); 60 /** Reads the error code value from a pivot cache item. */ 61 void readError( const AttributeList& rAttribs ); 62 /** Reads the index of a shared item. */ 63 void readIndex( const AttributeList& rAttribs ); 64 65 /** Reads the string value from a pivot cache item. */ 66 void readString( SequenceInputStream& rStrm ); 67 /** Reads the double value from a pivot cache item. */ 68 void readDouble( SequenceInputStream& rStrm ); 69 /** Reads the date/time value from a pivot cache item. */ 70 void readDate( SequenceInputStream& rStrm ); 71 /** Reads the boolean value from a pivot cache item. */ 72 void readBool( SequenceInputStream& rStrm ); 73 /** Reads the error code value from a pivot cache item. */ 74 void readError( SequenceInputStream& rStrm ); 75 /** Reads the index of a shared item. */ 76 void readIndex( SequenceInputStream& rStrm ); 77 78 /** Returns the type of the item. */ getType() const79 sal_Int32 getType() const { return mnType; } 80 /** Returns the value of the item. */ getValue() const81 const css::uno::Any& getValue() const { return maValue; } 82 /** Returns the string representation of the item. */ 83 OUString getName() const; 84 85 /** Returns the string representation of the item, using the actual formatting. */ 86 OUString getFormattedName(const ScDPSaveDimension& rSaveDim, ScDPObject* pObj, const DateTime& rNullDate) const; 87 /** Returns true if the item is unused. */ isUnused() const88 bool isUnused() const { return mbUnused; } 89 90 private: 91 friend class PivotCacheItemList; 92 // #FIXME hack Sets the value of this item to the given string ( and overwrites type if necessary 93 void setStringValue( const OUString& sName ); 94 css::uno::Any maValue; /// Value of the item. 95 sal_Int32 mnType; /// Value type (OOXML token identifier). 96 bool mbUnused; 97 }; 98 99 class PivotCacheItemList : public WorkbookHelper 100 { 101 public: 102 explicit PivotCacheItemList( const WorkbookHelper& rHelper ); 103 104 /** Imports the item from the passed attribute list. */ 105 void importItem( sal_Int32 nElement, const AttributeList& rAttribs ); 106 /** Imports the item from the passed stream and record. */ 107 void importItem( sal_Int32 nRecId, SequenceInputStream& rStrm ); 108 109 /** Returns true, if this item list is empty. */ empty() const110 bool empty() const { return maItems.empty(); } 111 /** Returns the size of the item list. */ size() const112 size_t size() const { return maItems.size(); } 113 114 /** Returns the specified item. */ 115 const PivotCacheItem* getCacheItem( sal_Int32 nItemIdx ) const; 116 /** Returns the names of all items. */ 117 void getCacheItemNames( ::std::vector< OUString >& orItemNames ) const; 118 void applyItemCaptions( const IdCaptionPairList& vCaptions ); 119 120 private: 121 /** Creates and returns a new item at the end of the items list. */ 122 PivotCacheItem& createItem(); 123 /** Imports an array of items from the PCITEM_ARRAY record */ 124 void importArray( SequenceInputStream& rStrm ); 125 126 private: 127 std::vector< PivotCacheItem > maItems; /// All items of this list. 128 }; 129 130 struct PCFieldModel 131 { 132 OUString maName; /// Fixed name of the cache field. 133 OUString maCaption; /// Caption of the cache field. 134 OUString maPropertyName; /// OLAP property name. 135 OUString maFormula; /// Formula of a calculated field. 136 sal_Int32 mnNumFmtId; /// Number format for all items. 137 sal_Int32 mnSqlType; /// Data type from ODBC data source. 138 sal_Int32 mnHierarchy; /// Hierarchy this field is part of. 139 sal_Int32 mnLevel; /// Hierarchy level this field is part of. 140 sal_Int32 mnMappingCount; /// Number of property mappings. 141 bool mbDatabaseField; /// True = field from source data; false = calculated field. 142 bool mbServerField; /// True = ODBC server-based page field. 143 bool mbUniqueList; /// True = list of unique ODBC items exists. 144 bool mbMemberPropField; /// True = contains OLAP member properties. 145 146 explicit PCFieldModel(); 147 }; 148 149 struct PCSharedItemsModel 150 { 151 bool mbHasSemiMixed; /// True = has (blank|string|bool|error) item(s), maybe other types. 152 bool mbHasNonDate; /// True = has non-date item(s), maybe date items. 153 bool mbHasDate; /// True = has date item(s), maybe other types. 154 bool mbHasString; /// True = has (string|bool|error) item(s), maybe other types. 155 bool mbHasBlank; /// True = has blank item(s), maybe other types. 156 bool mbHasMixed; /// True = has [(string|bool|error) and (number|date)] or (number and date). 157 bool mbIsNumeric; /// True = has numeric item(s), maybe other types except date. 158 bool mbIsInteger; /// True = has numeric item(s) with only integers, maybe other types except date. 159 bool mbHasLongText; /// True = contains strings with >255 characters. 160 161 explicit PCSharedItemsModel(); 162 }; 163 164 struct PCFieldGroupModel 165 { 166 css::util::DateTime maStartDate; /// Manual or calculated start date for range grouping. 167 css::util::DateTime maEndDate; /// Manual or calculated end date for range grouping. 168 double mfStartValue; /// Manual or calculated start value for range grouping. 169 double mfEndValue; /// Manual or calculated end value for range grouping. 170 double mfInterval; /// Interval for numeric range grouping. 171 sal_Int32 mnParentField; /// Index of cache field that contains item groups based on this field. 172 sal_Int32 mnBaseField; /// Index of cache field this grouped field is based on. 173 sal_Int32 mnGroupBy; /// Type of numeric or date range grouping. 174 bool mbRangeGroup; /// True = items are grouped by numeric ranges or date ranges. 175 bool mbDateGroup; /// True = items are grouped by date ranges or by item names. 176 bool mbAutoStart; /// True = start value for range groups is calculated from source data. 177 bool mbAutoEnd; /// True = end value for range groups is calculated from source data. 178 OUString msFinalGroupName ; /// Finalized group name of this field used in internal pivot table collection. 179 180 181 explicit PCFieldGroupModel(); 182 183 /** Sets the group-by value for BIFF import. */ 184 void setBiffGroupBy( sal_uInt8 nGroupBy ); 185 }; 186 187 /** Helper struct for mapping original item names from/to group item names. */ 188 struct PivotCacheGroupItem 189 { 190 OUString maOrigName; 191 OUString maGroupName; 192 PivotCacheGroupItemoox::xls::PivotCacheGroupItem193 explicit PivotCacheGroupItem( const OUString& rItemName ) : 194 maOrigName( rItemName ), maGroupName( rItemName ) {} 195 }; 196 197 typedef ::std::vector< PivotCacheGroupItem > PivotCacheGroupItemVector; 198 199 class PivotCacheField : public WorkbookHelper 200 { 201 public: 202 explicit PivotCacheField( const WorkbookHelper& rHelper, bool bIsDatabaseField ); 203 204 /** Imports pivot cache field settings from the cacheField element. */ 205 void importCacheField( const AttributeList& rAttribs ); 206 /** Imports shared items settings from the sharedItems element. */ 207 void importSharedItems( const AttributeList& rAttribs ); 208 /** Imports a shared item from the passed element. */ 209 void importSharedItem( sal_Int32 nElement, const AttributeList& rAttribs ); 210 /** Imports grouping settings from the fieldGroup element. */ 211 void importFieldGroup( const AttributeList& rAttribs ); 212 /** Imports numeric grouping settings from the rangePr element. */ 213 void importRangePr( const AttributeList& rAttribs ); 214 /** Imports an item of the mapping between group items and base items from the passed element. */ 215 void importDiscretePrItem( sal_Int32 nElement, const AttributeList& rAttribs ); 216 /** Imports a group item from the passed element. */ 217 void importGroupItem( sal_Int32 nElement, const AttributeList& rAttribs ); 218 219 /** Imports pivot cache field settings from the PCDFIELD record. */ 220 void importPCDField( SequenceInputStream& rStrm ); 221 /** Imports shared items settings from the PCDFSHAREDITEMS record. */ 222 void importPCDFSharedItems( SequenceInputStream& rStrm ); 223 /** Imports one or more shared items from the passed record. */ 224 void importPCDFSharedItem( sal_Int32 nRecId, SequenceInputStream& rStrm ); 225 /** Imports grouping settings from the PCDFIELDGROUP record. */ 226 void importPCDFieldGroup( SequenceInputStream& rStrm ); 227 /** Imports numeric grouping settings from the PCDFRANGEPR record. */ 228 void importPCDFRangePr( SequenceInputStream& rStrm ); 229 /** Imports an item of the mapping between group items and base items from the passed record. */ 230 void importPCDFDiscretePrItem( sal_Int32 nRecId, SequenceInputStream& rStrm ); 231 /** Imports one or more group items from the passed record. */ 232 void importPCDFGroupItem( sal_Int32 nRecId, SequenceInputStream& rStrm ); 233 234 /** Apply user Captions to imported group data */ 235 void applyItemCaptions( const IdCaptionPairList& vCaptions ); 236 237 /** Returns true, if the field is based on source data, or false if it is grouped or calculated. */ isDatabaseField() const238 bool isDatabaseField() const { return maFieldModel.mbDatabaseField; } 239 240 /** Returns true, if the field contains a list of shared items. */ hasSharedItems() const241 bool hasSharedItems() const { return !maSharedItems.empty(); } 242 /** Returns true, if the field contains a list of grouping items. */ hasGroupItems() const243 bool hasGroupItems() const { return !maGroupItems.empty(); } 244 /** Returns true, if the field has inplace numeric grouping settings. */ hasNumericGrouping() const245 bool hasNumericGrouping() const { return maFieldGroupModel.mbRangeGroup && !maFieldGroupModel.mbDateGroup; } 246 /** Returns true, if the field has inplace date grouping settings. */ hasDateGrouping() const247 bool hasDateGrouping() const { return maFieldGroupModel.mbRangeGroup && maFieldGroupModel.mbDateGroup; } 248 /** Returns true, if the field has a parent group field that groups the items of this field. */ hasParentGrouping() const249 bool hasParentGrouping() const { return maFieldGroupModel.mnParentField >= 0; } 250 251 /** Returns the name of the cache field. */ getName() const252 const OUString& getName() const { return maFieldModel.maName; } 253 /** Returns the index of the parent group field that groups the items of this field. */ getParentGroupField() const254 sal_Int32 getParentGroupField() const { return maFieldGroupModel.mnParentField; } 255 /** Returns the index of the base field grouping is based on. */ getGroupBaseField() const256 sal_Int32 getGroupBaseField() const { return maFieldGroupModel.mnBaseField; } 257 /** Returns the finalized group name of this field. */ getFinalGroupName() const258 const OUString& getFinalGroupName() const { return maFieldGroupModel.msFinalGroupName; } 259 /** Set the finalized group name of this field. */ setFinalGroupName(const OUString & rFinalGroupName)260 void setFinalGroupName(const OUString& rFinalGroupName) { maFieldGroupModel.msFinalGroupName = rFinalGroupName; } 261 262 /** Returns the shared or group item with the specified index. */ 263 const PivotCacheItem* getCacheItem( sal_Int32 nItemIdx ) const; 264 /** Returns the names of all shared or group items. */ 265 void getCacheItemNames( ::std::vector< OUString >& orItemNames ) const; 266 /** Returns shared or group items. */ 267 const PivotCacheItemList& getCacheItems() const; 268 269 /** Creates inplace numeric grouping settings. */ 270 void convertNumericGrouping( 271 const css::uno::Reference< css::sheet::XDataPilotField >& rxDPField ) const; 272 /** Creates inplace date grouping settings or a new date group field. */ 273 OUString createDateGroupField( 274 const css::uno::Reference< css::sheet::XDataPilotField >& rxBaseDPField ) const; 275 /** Creates a new grouped DataPilot field and returns its name. */ 276 OUString createParentGroupField( 277 const css::uno::Reference< css::sheet::XDataPilotField >& rxBaseDPField, 278 const PivotCacheField& rBaseCacheField, 279 PivotCacheGroupItemVector& orItemNames ) const; 280 281 /** Writes the title of the field into the passed sheet at the passed address. */ 282 void writeSourceHeaderCell( const WorksheetHelper& rSheetHelper, 283 sal_Int32 nCol, sal_Int32 nRow ) const; 284 /** Writes a source field item value into the passed sheet. */ 285 void writeSourceDataCell( const WorksheetHelper& rSheetHelper, 286 sal_Int32 nCol, sal_Int32 nRow, 287 const PivotCacheItem& rItem ) const; 288 289 /** Reads an item from the PCRECORD record and writes it to the passed sheet. */ 290 void importPCRecordItem( SequenceInputStream& rStrm, 291 const WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const; 292 293 private: 294 /** Tries to write the passed value to the passed sheet position. */ 295 static void writeItemToSourceDataCell( const WorksheetHelper& rSheetHelper, 296 sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ); 297 /** Tries to write the value of a shared item to the passed sheet position. */ 298 void writeSharedItemToSourceDataCell( const WorksheetHelper& rSheetHelper, 299 sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nItemIdx ) const; 300 301 private: 302 typedef ::std::vector< sal_Int32 > IndexVector; 303 304 PivotCacheItemList maSharedItems; /// All shared items of this field. 305 PivotCacheItemList maGroupItems; /// All group items of this field. 306 IndexVector maDiscreteItems; /// Mapping between group and base items. 307 PCFieldModel maFieldModel; /// Settings for this cache field. 308 PCSharedItemsModel maSharedItemsModel; /// Settings for shared items. 309 PCFieldGroupModel maFieldGroupModel; /// Settings for item grouping. 310 }; 311 312 struct PCDefinitionModel 313 { 314 OUString maRelId; /// Relation identifier for cache records fragment. 315 OUString maRefreshedBy; /// Name of user who last refreshed the cache. 316 double mfRefreshedDate; /// Date/time of last refresh. 317 sal_Int32 mnRecords; /// Number of data records in the cache. 318 sal_Int32 mnMissItemsLimit; /// Limit for discarding unused items. 319 bool mbInvalid; /// True = cache needs refresh. 320 bool mbSaveData; /// True = cached item values are present. 321 bool mbRefreshOnLoad; /// True = try to refresh cache on load. 322 bool mbOptimizeMemory; /// True = application may optimize memory usage. 323 bool mbEnableRefresh; /// True = refreshing cache is enabled in UI. 324 bool mbBackgroundQuery; /// True = application queries data asynchronously. 325 bool mbUpgradeOnRefresh; /// True = application may upgrade cache version. 326 bool mbTupleCache; /// True = cache stores OLAP functions. 327 bool mbSupportSubquery; /// True = data source supports subqueries. 328 bool mbSupportDrill; /// True = data source supports drilldown. 329 330 explicit PCDefinitionModel(); 331 }; 332 333 struct PCSourceModel 334 { 335 sal_Int32 mnSourceType; /// Type of the source data (sheet, consolidation, scenario, external). 336 sal_Int32 mnConnectionId; /// Connection identifier for external data source. 337 338 explicit PCSourceModel(); 339 }; 340 341 struct PCWorksheetSourceModel 342 { 343 OUString maRelId; /// Relation identifier for an external document URL. 344 OUString maSheet; /// Sheet name for cell range or sheet-local defined names. 345 OUString maDefName; /// Defined name containing a cell range if present. 346 ScRange maRange; /// Source cell range of the data. 347 348 explicit PCWorksheetSourceModel(); 349 }; 350 351 class PivotCache : public WorkbookHelper 352 { 353 public: 354 explicit PivotCache( const WorkbookHelper& rHelper ); 355 356 /** Reads pivot cache global settings from the pivotCacheDefinition element. */ 357 void importPivotCacheDefinition( const AttributeList& rAttribs ); 358 /** Reads cache source settings from the cacheSource element. */ 359 void importCacheSource( const AttributeList& rAttribs ); 360 /** Reads sheet source settings from the worksheetSource element. */ 361 void importWorksheetSource( const AttributeList& rAttribs, const ::oox::core::Relations& rRelations ); 362 363 /** Reads pivot cache global settings from the PCDEFINITION record. */ 364 void importPCDefinition( SequenceInputStream& rStrm ); 365 /** Reads cache source settings from the PCDSOURCE record. */ 366 void importPCDSource( SequenceInputStream& rStrm ); 367 /** Reads sheet source settings from the PCDSHEETSOURCE record. */ 368 void importPCDSheetSource( SequenceInputStream& rStrm, const ::oox::core::Relations& rRelations ); 369 370 /** Creates and returns a new pivot cache field. */ 371 PivotCacheField& createCacheField(); 372 /** Checks validity of source data and creates a dummy data sheet for external sheet sources. */ 373 void finalizeImport(); 374 375 /** Returns true, if the pivot cache is based on a valid data source, so 376 that pivot tables can be created based on this pivot cache. */ isValidDataSource() const377 bool isValidDataSource() const { return mbValidSource; } 378 /** Returns true, if the pivot cache is based on a dummy sheet created in finalizeImport. */ isBasedOnDummySheet() const379 bool isBasedOnDummySheet() const { return mbDummySheet; } 380 /** Returns the internal cell range the cache is based on. */ 381 const ScRange& getSourceRange() const382 getSourceRange() const { return maSheetSrcModel.maRange; } 383 /** Returns the relation identifier of the pivot cache records fragment. */ getRecordsRelId() const384 const OUString& getRecordsRelId() const { return maDefModel.maRelId; } 385 386 /** Returns the cache field with the specified index. */ 387 PivotCacheField* getCacheField( sal_Int32 nFieldIdx ); 388 const PivotCacheField* getCacheField( sal_Int32 nFieldIdx ) const; 389 /** Returns the source column index of the field with the passed index. */ 390 sal_Int32 getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const; 391 392 /** Writes the titles of all source fields into the passed sheet. */ 393 void writeSourceHeaderCells( const WorksheetHelper& rSheetHelper ) const; 394 /** Writes a source field item value into the passed sheet. */ 395 void writeSourceDataCell( const WorksheetHelper& rSheetHelper, 396 sal_Int32 nColIdx, sal_Int32 nRowIdx, 397 const PivotCacheItem& rItem ) const; 398 399 /** Reads a PCRECORD record and writes all item values to the passed sheet. */ 400 void importPCRecord( SequenceInputStream& rStrm, 401 const WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const; 402 403 private: 404 405 /** Finalizes the pivot cache if it is based on internal sheet data. */ 406 void finalizeInternalSheetSource(); 407 /** Finalizes the pivot cache if it is based on sheet data of an external spreadsheet document. */ 408 void finalizeExternalSheetSource(); 409 /** Creates a dummy sheet that will be filled with the pivot cache data. */ 410 void prepareSourceDataSheet(); 411 /** Checks, if the row index has changed since last call, and initializes the sheet data buffer. */ 412 void updateSourceDataRow( const WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const; 413 414 private: 415 typedef RefVector< PivotCacheField > PivotCacheFieldVector; 416 typedef ::std::vector< sal_Int32 > IndexVector; 417 418 PivotCacheFieldVector maFields; /// All pivot cache fields. 419 PivotCacheFieldVector maDatabaseFields; /// All cache fields that are based on source data. 420 IndexVector maDatabaseIndexes; /// Database field index for all fields. 421 PCDefinitionModel maDefModel; /// Global pivot cache settings. 422 PCSourceModel maSourceModel; /// Pivot cache source settings. 423 PCWorksheetSourceModel maSheetSrcModel; /// Sheet source data if cache type is sheet. 424 ValueRangeSet maColSpans; /// Column spans used by SheetDataBuffer for optimized cell import. 425 OUString maTargetUrl; /// URL of an external source document. 426 mutable sal_Int32 mnCurrRow; /// Current row index in dummy sheet. 427 bool mbValidSource; /// True = pivot cache is based on supported data source. 428 bool mbDummySheet; /// True = pivot cache is based on a dummy sheet. 429 }; 430 431 class PivotCacheBuffer : public WorkbookHelper 432 { 433 public: 434 explicit PivotCacheBuffer( const WorkbookHelper& rHelper ); 435 436 /** Registers a pivot cache definition fragment. The fragment will be loaded on demand (OOXML/BIFF12 only). */ 437 void registerPivotCacheFragment( sal_Int32 nCacheId, const OUString& rFragmentPath ); 438 439 /** Imports and stores a pivot cache definition fragment on first call, 440 returns the imported cache on subsequent calls with the same identifier. */ 441 PivotCache* importPivotCacheFragment( sal_Int32 nCacheId ); 442 443 private: 444 /** Creates and returns a new pivot cache object with the passed identifier. */ 445 PivotCache& createPivotCache( sal_Int32 nCacheId ); 446 447 private: 448 typedef ::std::map< sal_Int32, OUString > FragmentPathMap; 449 typedef RefMap< sal_Int32, PivotCache > PivotCacheMap; 450 451 FragmentPathMap maFragmentPaths; 452 PivotCacheMap maCaches; 453 std::vector< sal_Int32 > maCacheIds; 454 }; 455 456 } // namespace oox::xls 457 458 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 459