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 #ifndef INCLUDED_SC_SOURCE_FILTER_INC_XEPIVOT_HXX
21 #define INCLUDED_SC_SOURCE_FILTER_INC_XEPIVOT_HXX
22 
23 #include "xerecord.hxx"
24 #include "xlpivot.hxx"
25 #include "xeroot.hxx"
26 
27 class ScDPObject;
28 class ScDPSaveData;
29 class ScDPSaveDimension;
30 class ScDPSaveMember;
31 class ScDPSaveGroupDimension;
32 struct ScDPNumGroupInfo;
33 
34 // Pivot cache
35 
36 /** Represents a data item in a pivot cache containing data of any type. */
37 class XclExpPCItem : public XclExpRecord, public XclPCItem
38 {
39 public:
40     explicit            XclExpPCItem( const OUString& rText );
41     explicit            XclExpPCItem( double fValue, const OUString& rText = OUString() );
42     explicit            XclExpPCItem( const DateTime& rDateTime, const OUString& rText = OUString() );
43     explicit            XclExpPCItem( sal_Int16 nValue );
44     explicit            XclExpPCItem( bool bValue, const OUString& rText );
45 
GetTypeFlag() const46     sal_uInt16   GetTypeFlag() const { return mnTypeFlag; }
47 
48     bool                EqualsText( const OUString& rText ) const;
49     bool                EqualsDouble( double fValue ) const;
50     bool                EqualsDateTime( const DateTime& rDateTime ) const;
51     bool                EqualsBool( bool bValue ) const;
52 
53 private:
54     virtual void        WriteBody( XclExpStream& rStrm ) override;
55 
56 private:
57     sal_uInt16          mnTypeFlag;         /// Data type flag.
58 };
59 
60 class XclExpPCField : public XclExpRecord, public XclPCField, protected XclExpRoot
61 {
62 public:
63     /** Creates a standard pivot cache field, filled from sheet source data. */
64     explicit            XclExpPCField( const XclExpRoot& rRoot,
65                             sal_uInt16 nFieldIdx,
66                             const ScDPObject& rDPObj, const ScRange& rRange );
67     /** Creates a child grouping pivot cache field, filled from the passed grouping info. */
68     explicit            XclExpPCField( const XclExpRoot& rRoot,
69                             sal_uInt16 nFieldIdx,
70                             const ScDPObject& rDPObj, const ScDPSaveGroupDimension& rGroupDim,
71                             const XclExpPCField& rBaseField );
72     virtual             ~XclExpPCField() override;
73 
74     /** Sets the passed field as direct grouping child field of this field. */
75     void                SetGroupChildField( const XclExpPCField& rChildField );
76 
77     /** Returns the name of this cache field. */
GetFieldName() const78     const OUString& GetFieldName() const { return maFieldInfo.maName; }
79 
80     /** Returns the number of visible items of this field. */
81     sal_uInt16          GetItemCount() const;
82     /** Returns the specified pivot cache item (returns visible items in groupings). */
83     const XclExpPCItem* GetItem( sal_uInt16 nItemIdx ) const;
84     /** Returns the index of a pivot cache item, or EXC_PC_NOITEM on error. */
85     sal_uInt16          GetItemIndex( const OUString& rItemName ) const;
86 
87     /** Returns the size an item index needs to write out. */
88     std::size_t         GetIndexSize() const;
89     /** Writes the item index at the passed source row position as part of the SXINDEXLIST record. */
90     void                WriteIndex( XclExpStream& rStrm, sal_uInt32 nSrcRow ) const;
91 
92     /** Writes the pivot cache field and all items and other related records. */
93     virtual void        Save( XclExpStream& rStrm ) override;
94 
95 private:
96     typedef XclExpRecordList< XclExpPCItem >    XclExpPCItemList;
97 
98     /** Returns the item list that contains the visible items.
99         @descr  Visible items are equal to source items in standard fields,
100             but are generated items in grouping and calculated fields. */
101     const XclExpPCItemList& GetVisItemList() const;
102 
103     /** Initializes a standard field. Inserts all original source items. */
104     void                InitStandardField( const ScRange& rRange );
105     /** Initializes a standard grouping field. Inserts all visible grouping items. */
106     void                InitStdGroupField( const XclExpPCField& rBaseField, const ScDPSaveGroupDimension& rGroupDim );
107     /** Initializes a numeric grouping field. Inserts all visible grouping items and the limit settings. */
108     void                InitNumGroupField( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rNumInfo );
109     /** Initializes a date grouping field. Inserts all visible grouping items and the limit settings. */
110     void                InitDateGroupField( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nDatePart );
111 
112     /** Inserts the passed index into the item index array of original items. */
113     void                InsertItemArrayIndex( size_t nListPos );
114     /** Inserts an original source item. Updates item index array. */
115     void                InsertOrigItem( XclExpPCItem* pNewItem );
116     /** Inserts an original text item, if it is not contained already. */
117     void                InsertOrigTextItem( const OUString& rText );
118     /** Inserts an original value item, if it is not contained already. */
119     void                InsertOrigDoubleItem( double fValue, const OUString& rText );
120     /** Inserts an original date/time item, if it is not contained already. */
121     void                InsertOrigDateTimeItem( const DateTime& rDateTime, const OUString& rText );
122     /** Inserts an original boolean item, if it is not contained already. */
123     void                InsertOrigBoolItem( bool bValue, const OUString& rText );
124 
125     /** Inserts an item into the grouping item list. Does not change anything else.
126         @return  The list index of the new item. */
127     sal_uInt16          InsertGroupItem( XclExpPCItem* pNewItem );
128     /** Generates and inserts all visible items for numeric or date grouping. */
129     void                InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rNumInfo, sal_Int32 nDatePart = 0 );
130 
131     /** Inserts the SXDOUBLE items that specify the limits for a numeric grouping. */
132     void                SetNumGroupLimit( const ScDPNumGroupInfo& rNumInfo );
133     /** Inserts the SXDATETIME/SXINTEGER items that specify the limits for a date grouping.
134         @param bUseStep  true = Insert the passed step value; false = always insert 1. */
135     void                SetDateGroupLimit( const ScDPNumGroupInfo& rDateInfo, bool bUseStep );
136 
137     /** Initializes flags and item count fields. */
138     void                Finalize();
139 
140     /** Writes an SXNUMGROUP record and the additional items for a numeric grouping field. */
141     void                WriteSxnumgroup( XclExpStream& rStrm );
142     /** Writes an SXGROUPINFO record describing the item order in grouping fields. */
143     void                WriteSxgroupinfo( XclExpStream& rStrm );
144 
145     /** Writes the contents of the SXFIELD record for this field. */
146     virtual void        WriteBody( XclExpStream& rStrm ) override;
147 
148 private:
149     XclExpPCItemList    maOrigItemList;     /// List with original items.
150     XclExpPCItemList    maGroupItemList;    /// List with grouping items.
151     ScfUInt16Vec        maIndexVec;         /// Indexes into maItemList.
152     XclExpPCItemList    maNumGroupLimits;   /// List with limit values for numeric grouping.
153     sal_uInt16          mnTypeFlags;        /// Collected item data type flags.
154 };
155 
156 class XclExpPivotCache : protected XclExpRoot
157 {
158 public:
159     explicit            XclExpPivotCache( const XclExpRoot& rRoot,
160                             const ScDPObject& rDPObj, sal_uInt16 nListIdx );
161 
162     /** Returns true, if the cache has been constructed successfully. */
IsValid() const163     bool         IsValid() const { return mbValid; }
164     /** Returns true, if the item index list will be written. */
165     bool                HasItemIndexList() const;
166 
167     /** Returns the list index of the cache used in pivot table records. */
GetCacheIndex() const168     sal_uInt16   GetCacheIndex() const { return mnListIdx; }
169 
170     /** Returns the number of pivot cache fields. */
171     sal_uInt16          GetFieldCount() const;
172     /** Returns the specified pivot cache field. */
173     const XclExpPCField* GetField( sal_uInt16 nFieldIdx ) const;
174     /** Returns true, if this pivot cache contains non-standard fields (e.g. grouping fields). */
175     bool                HasAddFields() const;
176 
177     /** Returns true, if the passed DP object has the same data source as this cache. */
178     bool                HasEqualDataSource( const ScDPObject& rDPObj ) const;
179 
180     /** Writes related records into Workbook stream and creates the pivot cache storage stream. */
181     void        Save( XclExpStream& rStrm );
182     static void SaveXml( XclExpXmlStream& rStrm );
183 
184 private:
185     /** Adds all pivot cache fields. */
186     void                AddFields( const ScDPObject& rDPObj );
187 
188     /** Adds all standard pivot cache fields based on source data. */
189     void                AddStdFields( const ScDPObject& rDPObj );
190     /** Adds all grouping pivot cache fields. */
191     void                AddGroupFields( const ScDPObject& rDPObj );
192 
193     /** Writes the DCONREF record containing the source range. */
194     void                WriteDconref( XclExpStream& rStrm ) const;
195     /** DCONNAME record contains range name source. */
196     void                WriteDConName( XclExpStream& rStrm ) const;
197 
198     /** Creates the pivot cache storage stream and writes the cache. */
199     void                WriteCacheStream();
200     /** Writes the SXDB record. */
201     void                WriteSxdb( XclExpStream& rStrm ) const;
202     /** Writes the SXDBEX record. */
203     static void         WriteSxdbex( XclExpStream& rStrm );
204     /** Writes the SXINDEXLIST record list containing the item index table. */
205     void                WriteSxindexlistList( XclExpStream& rStrm ) const;
206 
207 private:
208     typedef XclExpRecordList< XclExpPCField >   XclExpPCFieldList;
209     typedef XclExpPCFieldList::RecordRefType    XclExpPCFieldRef;
210 
211     XclPCInfo           maPCInfo;           /// Pivot cache settings (SXDB record).
212     XclExpPCFieldList   maFieldList;        /// List of all pivot cache fields.
213     OUString       maTabName;          /// Name of source data sheet.
214     OUString       maSrcRangeName;     /// Range name for source data.
215     ScRange             maOrigSrcRange;     /// The original sheet source range.
216     ScRange             maExpSrcRange;      /// The exported sheet source range.
217     ScRange             maDocSrcRange;      /// The range used to build the cache fields and items.
218     sal_uInt16 const    mnListIdx;          /// List index in pivot cache buffer.
219     bool                mbValid;            /// true = The cache is valid for export.
220 };
221 
222 // Pivot table
223 
224 class XclExpPivotTable;
225 
226 /** Data field position specifying the pivot table field index (first) and data info index (second). */
227 typedef ::std::pair< sal_uInt16, sal_uInt16 > XclPTDataFieldPos;
228 
229 class XclExpPTItem : public XclExpRecord
230 {
231 public:
232     explicit            XclExpPTItem( const XclExpPCField& rCacheField, sal_uInt16 nCacheIdx );
233     explicit            XclExpPTItem( sal_uInt16 nItemType, sal_uInt16 nCacheIdx );
234 
235     /** Returns the internal name of this item. */
236     OUString       GetItemName() const;
237 
238     /** Fills this item with properties from the passed save member. */
239     void                SetPropertiesFromMember( const ScDPSaveMember& rSaveMem );
240 
241 private:
242     /** Writes the SXVI record body describing the pivot table item. */
243     virtual void        WriteBody( XclExpStream& rStrm ) override;
244 
245 private:
246     const XclExpPCItem* mpCacheItem;        /// The referred pivot cache item.
247     XclPTItemInfo       maItemInfo;         /// General data for this item.
248 };
249 
250 class XclExpPTField : public XclExpRecordBase
251 {
252 public:
253     explicit            XclExpPTField( const XclExpPivotTable& rPTable, sal_uInt16 nCacheIdx );
254 
255     // data access ------------------------------------------------------------
256 
257     /** Returns the name of this field. */
258     OUString       GetFieldName() const;
259     /** Returns the pivot table field list index of this field.
260       * The field index is always equal to cache index.
261       */
GetFieldIndex() const262     sal_uInt16          GetFieldIndex() const { return maFieldInfo.mnCacheIdx; }
263 
264     /** Returns the index of the last inserted data info struct. */
265     sal_uInt16          GetLastDataInfoIndex() const;
266 
267     /** Returns the list index of an item by its name.
268         @param nDefaultIdx  This value will be returned, if the item could not be found. */
269     sal_uInt16          GetItemIndex( const OUString& rName, sal_uInt16 nDefaultIdx ) const;
270 
271     // fill data --------------------------------------------------------------
272 
273     /** Fills this field with row/column/page properties from the passed save dimension. */
274     void                SetPropertiesFromDim( const ScDPSaveDimension& rSaveDim );
275     /** Fills this field with data field properties from the passed save dimension. */
276     void                SetDataPropertiesFromDim( const ScDPSaveDimension& rSaveDim );
277 
278     /** Appends special items describing the field subtotal entries. */
279     void                AppendSubtotalItems();
280 
281     // records ----------------------------------------------------------------
282 
283     /** Writes an entry for an SXPI record containing own page field info. */
284     void                WriteSxpiEntry( XclExpStream& rStrm ) const;
285     /** Writes an SXDI records containing info about a data field. */
286     void                WriteSxdi( XclExpStream& rStrm, sal_uInt16 nDataInfoIdx ) const;
287 
288     /** Writes the entire pivot table field. */
289     virtual void        Save( XclExpStream& rStrm ) override;
290 
291 private:
292     /** Returns an item by its name. */
293     XclExpPTItem*       GetItemAcc( const OUString& rName );
294 
295     /** Appends a special item describing a field subtotal entry. */
296     void                AppendSubtotalItem( sal_uInt16 nItemType );
297 
298     /** Writes the SXVD record introducing the field. */
299     void                WriteSxvd( XclExpStream& rStrm ) const;
300     /** Writes the SXVDEX record containing additional settings. */
301     void                WriteSxvdex( XclExpStream& rStrm ) const;
302 
303 private:
304     typedef ::std::vector< XclPTDataFieldInfo > XclPTDataFieldInfoVec;
305     typedef XclExpRecordList< XclExpPTItem >    XclExpPTItemList;
306 
307     const XclExpPivotTable& mrPTable;       /// Parent pivot table containing this field.
308     const XclExpPCField* mpCacheField;      /// The referred pivot cache field.
309     XclPTFieldInfo      maFieldInfo;        /// General field info (SXVD record).
310     XclPTFieldExtInfo   maFieldExtInfo;     /// Extended field info (SXVDEX record).
311     XclPTPageFieldInfo  maPageInfo;         /// Page field info (entry in SXPI record).
312     XclPTDataFieldInfoVec maDataInfoVec;    /// List of extended data field info (SXDI records).
313     XclExpPTItemList    maItemList;         /// List of all items of this field.
314 };
315 
316 class XclExpPivotTable : public XclExpRecordBase, protected XclExpRoot
317 {
318 public:
319     explicit            XclExpPivotTable( const XclExpRoot& rRoot,
320                             const ScDPObject& rDPObj, const XclExpPivotCache& rPCache );
321 
322     /** Returns a pivot cache field. */
323     const XclExpPCField* GetCacheField( sal_uInt16 nCacheIdx ) const;
324 
325     /** Returns the output range of the pivot table. */
GetScTab() const326     SCTAB         GetScTab() const { return mnOutScTab; }
327 
328     /** Returns a pivot table field by its name. */
329     const XclExpPTField* GetField( sal_uInt16 nFieldIdx ) const;
330     /** Returns a pivot table field by its name. */
331     const XclExpPTField* GetField( const OUString& rName ) const;
332 
333     /** Returns the data-field-only index of the first data field with the passed name.
334         @param nDefaultIdx  This value will be returned, if the field could not be found. */
335     sal_uInt16          GetDataFieldIndex( const OUString& rName, sal_uInt16 nDefaultIdx ) const;
336 
337     /** Writes the entire pivot table. */
338     virtual void        Save( XclExpStream& rStrm ) override;
339 
340 private:
341     /** Returns a pivot table field by its name. */
342     XclExpPTField*      GetFieldAcc( const OUString& rName );
343     /** Returns a pivot table field corresponding to the passed save dimension. */
344     XclExpPTField*      GetFieldAcc( const ScDPSaveDimension& rSaveDim );
345 
346     // fill data --------------------------------------------------------------
347 
348     /** Fills internal members with all properties from the passed save data. */
349     void                SetPropertiesFromDP( const ScDPSaveData& rSaveData );
350     /** Fills a pivot table field with all properties from the passed save dimension. */
351     void                SetFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim );
352     /** Fills a pivot table data field with all properties from the passed save dimension. */
353     void                SetDataFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim );
354 
355     /** Initializes any data after processing the entire source DataPilot. */
356     void                Finalize();
357 
358     // records ----------------------------------------------------------------
359 
360     /** Writes the SXVIEW record starting the pivot table. */
361     void                WriteSxview( XclExpStream& rStrm ) const;
362     /** Writes an SXIVD record for row field or column field order. */
363     static void         WriteSxivd( XclExpStream& rStrm, const ScfUInt16Vec& rFields );
364     /** Writes the SXPI record containing page field info. */
365     void                WriteSxpi( XclExpStream& rStrm ) const;
366     /** Writes all SXDI records containing info about the data fields. */
367     void                WriteSxdiList( XclExpStream& rStrm ) const;
368     /** Writes a dummy SXLI records containing item layout info. */
369     static void         WriteSxli( XclExpStream& rStrm, sal_uInt16 nLineCount, sal_uInt16 nIndexCount );
370     /** Writes the SXEX records containing additional pivot table info. */
371     void                WriteSxex( XclExpStream& rStrm ) const;
372 
373     void                WriteQsiSxTag( XclExpStream& rStrm ) const;
374     /** Writes the SX_AUTOFORMAT records with the autoformat id and header layout */
375     void                WriteSxViewEx9( XclExpStream& rStrm ) const;
376 
377 private:
378     typedef XclExpRecordList< XclExpPTField >   XclExpPTFieldList;
379     typedef XclExpPTFieldList::RecordRefType    XclExpPTFieldRef;
380     typedef ::std::vector< XclPTDataFieldPos >  XclPTDataFieldPosVec;
381 
382     const XclExpPivotCache& mrPCache;       /// The pivot cache this pivot table bases on.
383     XclPTInfo           maPTInfo;           /// Info about the pivot table (SXVIEW record).
384     XclPTExtInfo        maPTExtInfo;        /// Extended info about the pivot table (SXEX record).
385     XclPTViewEx9Info    maPTViewEx9Info;    /// The selected autoformat (SXVIEWEX9)
386     XclExpPTFieldList   maFieldList;        /// All fields in pivot cache order.
387     ScfUInt16Vec        maRowFields;        /// Row field indexes.
388     ScfUInt16Vec        maColFields;        /// Column field indexes.
389     ScfUInt16Vec        maPageFields;       /// Page field indexes.
390     XclPTDataFieldPosVec maDataFields;      /// Data field indexes.
391     XclExpPTField       maDataOrientField;  /// Special data field orientation field.
392     SCTAB               mnOutScTab;         /// Sheet index of the output range.
393     bool                mbValid;            /// true = The pivot table is valid for export.
394     bool                mbFilterBtn;        /// true = DataPilot has filter button.
395 };
396 
397 /** The main class for pivot table export.
398 
399     This class contains all pivot caches and pivot tables in a Calc document.
400     It creates the pivot cache streams and pivot table records in the main
401     workbook stream. It supports sharing of pivot caches between multiple pivot
402     tables to decrease file size.
403  */
404 class XclExpPivotTableManager : protected XclExpRoot
405 {
406 public:
407     explicit            XclExpPivotTableManager( const XclExpRoot& rRoot );
408 
409     /** Creates all pivot tables and caches from the Calc DataPilot objects. */
410     void                CreatePivotTables();
411 
412     /** Creates a record wrapper for exporting all pivot caches. */
413     XclExpRecordRef     CreatePivotCachesRecord();
414     /** Creates a record wrapper for exporting all pivot tables of the specified sheet. */
415     XclExpRecordRef     CreatePivotTablesRecord( SCTAB nScTab );
416 
417     /** Writes all pivot caches (all Workbook records and cache streams). */
418     void                WritePivotCaches( XclExpStream& rStrm );
419     /** Writes all pivot tables of the specified Calc sheet. */
420     void                WritePivotTables( XclExpStream& rStrm, SCTAB nScTab );
421 
422 private:
423     /** Finds an existing (if enabled in mbShareCaches) or creates a new pivot cache.
424         @return  Pointer to the pivot cache or 0, if the passed source range was invalid. */
425     const XclExpPivotCache* CreatePivotCache( const ScDPObject& rDPObj );
426 
427 private:
428     typedef XclExpRecordList< XclExpPivotCache >    XclExpPivotCacheList;
429     typedef XclExpPivotCacheList::RecordRefType     XclExpPivotCacheRef;
430     typedef XclExpRecordList< XclExpPivotTable >    XclExpPivotTableList;
431     typedef XclExpPivotTableList::RecordRefType     XclExpPivotTableRef;
432 
433     XclExpPivotCacheList maPCacheList;      /// List of all pivot caches.
434     XclExpPivotTableList maPTableList;      /// List of all pivot tables.
435 };
436 
437 #endif
438 
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
440