xref: /aoo4110/main/oox/inc/oox/xls/sheetdatabuffer.hxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef OOX_XLS_SHEETDATABUFFER_HXX
25 #define OOX_XLS_SHEETDATABUFFER_HXX
26 
27 #include <list>
28 #include <map>
29 #include "oox/xls/richstring.hxx"
30 #include "oox/xls/worksheethelper.hxx"
31 
32 namespace com { namespace sun { namespace star {
33     namespace sheet { class XNamedRange; }
34     namespace util { struct DateTime; }
35 } } }
36 
37 namespace oox {
38 namespace xls {
39 
40 // ============================================================================
41 
42 /** Stores basic data about cell values and formatting. */
43 struct CellModel
44 {
45     ::com::sun::star::table::CellAddress
46                         maCellAddr;         /// The address of the current cell.
47     sal_Int32           mnCellType;         /// Data type of the cell value.
48     sal_Int32           mnXfId;             /// XF (cell formatting) identifier.
49     bool                mbShowPhonetic;     /// True = show phonetic text.
50 
51     explicit            CellModel();
52 };
53 
54 // ----------------------------------------------------------------------------
55 
56 /** Stores data about cell formulas. */
57 struct CellFormulaModel
58 {
59     ::com::sun::star::table::CellRangeAddress
60                         maFormulaRef;       /// Formula range for array/shared formulas and data tables.
61     sal_Int32           mnFormulaType;      /// Type of the formula (regular, array, shared, table).
62     sal_Int32           mnSharedId;         /// Identifier of a shared formula (OOXML only).
63 
64     explicit            CellFormulaModel();
65 
66     /** Returns true, if the passed cell address is valid for an array formula. */
67     bool                isValidArrayRef( const ::com::sun::star::table::CellAddress& rCellAddr );
68     /** Returns true, if the passed cell address is valid for a shared formula. */
69     bool                isValidSharedRef( const ::com::sun::star::table::CellAddress& rCellAddr );
70 };
71 
72 // ----------------------------------------------------------------------------
73 
74 /** Stores data about table operations. */
75 struct DataTableModel
76 {
77     ::rtl::OUString     maRef1;             /// First reference cell for table operations.
78     ::rtl::OUString     maRef2;             /// Second reference cell for table operations.
79     bool                mb2dTable;          /// True = 2-dimensional data table.
80     bool                mbRowTable;         /// True = row oriented data table.
81     bool                mbRef1Deleted;      /// True = first reference cell deleted.
82     bool                mbRef2Deleted;      /// True = second reference cell deleted.
83 
84     explicit            DataTableModel();
85 };
86 
87 // ============================================================================
88 
89 /** Stores position and contents of a range of cells for optimized import. */
90 class CellBlock : public WorksheetHelper
91 {
92 public:
93     explicit            CellBlock( const WorksheetHelper& rHelper, const ValueRange& rColSpan, sal_Int32 nRow );
94 
95     /** Returns true, if the end index of the passed colspan is greater than
96         the own column end index, or if the passed range has the same end index
97         but the start indexes do not match. */
98     bool                isBefore( const ValueRange& rColSpan ) const;
99     /** Returns true, if the cell block can be expanded with the passed colspan. */
100     bool                isExpandable( const ValueRange& rColSpan ) const;
101     /** Returns true, if the own colspan contains the passed column. */
102     bool                contains( sal_Int32 nCol ) const;
103 
104     /** Returns the specified cell from the last row in the cell buffer array. */
105     ::com::sun::star::uno::Any& getCellAny( sal_Int32 nCol );
106     /** Inserts a rich-string into the cell block. */
107     void                insertRichString(
108                             const ::com::sun::star::table::CellAddress& rAddress,
109                             const RichStringRef& rxString,
110                             const Font* pFirstPortionFont );
111 
112     /** Appends a new row to the cell buffer array. */
113     void                startNextRow();
114     /** Writes all buffered cells into the Calc sheet. */
115     void                finalizeImport();
116 
117 private:
118     /** Fills unused cells before passed index with empty strings. */
119     void                fillUnusedCells( sal_Int32 nIndex );
120 
121 private:
122     /** Stores position and string data of a rich-string cell. */
123     struct RichStringCell
124     {
125         ::com::sun::star::table::CellAddress
126                             maCellAddr;         /// The address of the rich-string cell.
127         RichStringRef       mxString;           /// The string with rich formatting.
128         const Font*         mpFirstPortionFont; /// Font information from cell for first text portion.
129 
130         explicit            RichStringCell(
131                                 const ::com::sun::star::table::CellAddress& rCellAddr,
132                                 const RichStringRef& rxString,
133                                 const Font* pFirstPortionFont );
134     };
135     typedef ::std::list< RichStringCell > RichStringCellList;
136 
137     ::com::sun::star::table::CellRangeAddress
138                         maRange;            /// Cell range covered by this cell block.
139     RichStringCellList  maRichStrings;      /// Cached rich-string cells.
140     ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > >
141                         maCellArray;        /// The array of cells of this cell block.
142     ::com::sun::star::uno::Any*
143                         mpCurrCellRow;      /// Pointer to first cell of current row (last row in maCellArray).
144     const sal_Int32     mnRowLength;        /// Number of cells covered by row of this cell block.
145     sal_Int32           mnFirstFreeIndex;   /// Relative index of first unused cell in current row.
146 };
147 
148 // ============================================================================
149 
150 /** Manages all cell blocks currently in use. */
151 class CellBlockBuffer : public WorksheetHelper
152 {
153 public:
154     explicit            CellBlockBuffer( const WorksheetHelper& rHelper );
155 
156     /** Sets column span information for a row. */
157     void                setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans );
158 
159     /** Tries to find a cell block. Recalculates the map of cell blocks, if the
160         passed cell address is located in another row than the last cell. */
161     CellBlock*          getCellBlock( const ::com::sun::star::table::CellAddress& rCellAddr );
162 
163     /** Inserts all cells of all open cell blocks into the Calc document. */
164     void                finalizeImport();
165 
166 private:
167     typedef ::std::map< sal_Int32, ValueRangeVector >   ColSpanVectorMap;
168     typedef RefMap< sal_Int32, CellBlock >              CellBlockMap;
169 
170     ColSpanVectorMap    maColSpans;             /// Buffereed column spans, mapped by row index.
171     CellBlockMap        maCellBlocks;           /// All open cell blocks, mapped by last (!) column of the block span.
172     CellBlockMap::iterator maCellBlockIt;       /// Pointer to cell block currently in use.
173     sal_Int32           mnCurrRow;              /// Current row index used for buffered cell import.
174 };
175 
176 // ============================================================================
177 
178 /** Manages the cell contents and cell formatting of a sheet.
179  */
180 class SheetDataBuffer : public WorksheetHelper
181 {
182 public:
183     explicit            SheetDataBuffer( const WorksheetHelper& rHelper );
184 
185     /** Sets column span information for a row. */
186     void                setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans );
187 
188     /** Inserts a blank cell (with formatting) into the sheet. */
189     void                setBlankCell( const CellModel& rModel );
190     /** Inserts a value cell into the sheet. */
191     void                setValueCell( const CellModel& rModel, double fValue );
192     /** Inserts a simple string cell into the sheet. */
193     void                setStringCell( const CellModel& rModel, const ::rtl::OUString& rText );
194     /** Inserts a rich-string cell into the sheet. */
195     void                setStringCell( const CellModel& rModel, const RichStringRef& rxString );
196     /** Inserts a shared string cell into the sheet. */
197     void                setStringCell( const CellModel& rModel, sal_Int32 nStringId );
198     /** Inserts a date/time cell into the sheet and adjusts number format. */
199     void                setDateTimeCell( const CellModel& rModel, const ::com::sun::star::util::DateTime& rDateTime );
200     /** Inserts a boolean cell into the sheet and adjusts number format. */
201     void                setBooleanCell( const CellModel& rModel, bool bValue );
202     /** Inserts an error cell from the passed error code into the sheet. */
203     void                setErrorCell( const CellModel& rModel, const ::rtl::OUString& rErrorCode );
204     /** Inserts an error cell from the passed BIFF error code into the sheet. */
205     void                setErrorCell( const CellModel& rModel, sal_uInt8 nErrorCode );
206     /** Inserts a formula cell into the sheet. */
207     void                setFormulaCell( const CellModel& rModel, const ApiTokenSequence& rTokens );
208     /** Inserts a shared formula cell into the sheet (OOXML only). */
209     void                setFormulaCell( const CellModel& rModel, sal_Int32 nSharedId );
210 
211     /** Inserts the passed token array as array formula. */
212     void                createArrayFormula(
213                             const ::com::sun::star::table::CellRangeAddress& rRange,
214                             const ApiTokenSequence& rTokens );
215     /** Sets a multiple table operation to the passed range. */
216     void                createTableOperation(
217                             const ::com::sun::star::table::CellRangeAddress& rRange,
218                             const DataTableModel& rModel );
219     /** Creates a named range with a special name for a shared formula with the
220         specified identifier and formula definition (OOXML only). */
221     void                createSharedFormula(
222                             sal_Int32 nSharedId,
223                             const ApiTokenSequence& rTokens );
224     /** Creates a named range with a special name for a shared formula with the
225         specified base address and formula definition (BIFF only). */
226     void                createSharedFormula(
227                             const ::com::sun::star::table::CellAddress& rCellAddr,
228                             const ApiTokenSequence& rTokens );
229 
230     /** Sets default cell formatting for the specified range of rows. */
231     void                setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat );
232     /** Merges the cells in the passed cell range. */
233     void                setMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange );
234     /** Sets a standard number format (constant from com.sun.star.util.NumberFormat) to the specified cell. */
235     void                setStandardNumFmt(
236                             const ::com::sun::star::table::CellAddress& rCellAddr,
237                             sal_Int16 nStdNumFmt );
238 
239     /** Final processing after the sheet has been imported. */
240     void                finalizeImport();
241 
242 private:
243     struct XfIdRowRange;
244     struct XfIdRange;
245 
246     /** Sets the passed formula token array into a cell. */
247     void                setCellFormula(
248                             const ::com::sun::star::table::CellAddress& rCellAddr,
249                             const ApiTokenSequence& rTokens );
250 
251     /** Creates a named range with a special name for a shared formula with the
252         specified base address and formula definition. */
253     void                createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens );
254     /** Creates a formula token array representing the shared formula with the
255         passed identifier. */
256     ApiTokenSequence    resolveSharedFormula( const BinAddress& rMapKey ) const;
257 
258     /** Inserts the passed array formula into the sheet. */
259     void                finalizeArrayFormula(
260                             const ::com::sun::star::table::CellRangeAddress& rRange,
261                             const ApiTokenSequence& rTokens ) const;
262     /** Inserts the passed table operation into the sheet. */
263     void                finalizeTableOperation(
264                             const ::com::sun::star::table::CellRangeAddress& rRange,
265                             const DataTableModel& rModel ) const;
266 
267     /** Processes the cell formatting data of the passed cell.
268         @param nNumFmtId  If set, overrides number format of the cell XF. */
269     void                setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId = -1 );
270 
271     /** Writes all cell formatting attributes to the passed row range. */
272     void                writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const;
273     /** Writes all cell formatting attributes to the passed cell range. */
274     void                writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const;
275     /** Tries to merge the ranges last inserted in maXfIdRanges with existing ranges. */
276     void                mergeXfIdRanges();
277 
278     /** Merges the passed merged range and updates right/bottom cell borders. */
279     void                finalizeMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange );
280 
281 private:
282     /** Stores cell range address and formula token array of an array formula. */
283     typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, ApiTokenSequence > ArrayFormula;
284     typedef ::std::list< ArrayFormula > ArrayFormulaList;
285 
286     /** Stores cell range address and settings of a table operation. */
287     typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, DataTableModel > TableOperation;
288     typedef ::std::list< TableOperation > TableOperationList;
289 
290     typedef ::std::map< BinAddress, sal_Int32 > SharedFormulaMap;
291 
292     /** Stores information about a range of rows with equal cell formatting. */
293     struct XfIdRowRange
294     {
295         ValueRange          maRowRange;         /// Indexes of first and last row.
296         sal_Int32           mnXfId;             /// XF identifier for the row range.
297 
298         explicit            XfIdRowRange();
299         bool                intersects( const ::com::sun::star::table::CellRangeAddress& rRange ) const;
300         void                set( sal_Int32 nRow, sal_Int32 nXfId );
301         bool                tryExpand( sal_Int32 nRow, sal_Int32 nXfId );
302     };
303 
304     /** Stores information about a range of cells with equal formatting. */
305     struct XfIdRange
306     {
307         ::com::sun::star::table::CellRangeAddress
308                             maRange;            /// The formatted cell range.
309         sal_Int32           mnXfId;             /// XF identifier for the range.
310         sal_Int32           mnNumFmtId;         /// Number format overriding the XF.
311 
312         void                set( const ::com::sun::star::table::CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId );
313         bool                tryExpand( const ::com::sun::star::table::CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId );
314         bool                tryMerge( const XfIdRange& rXfIdRange );
315     };
316     typedef ::std::map< BinAddress, XfIdRange > XfIdRangeMap;
317 
318     /** Stores information about a merged cell range. */
319     struct MergedRange
320     {
321         ::com::sun::star::table::CellRangeAddress
322                             maRange;            /// The formatted cell range.
323         sal_Int32           mnHorAlign;         /// Horizontal alignment in the range.
324 
325         explicit            MergedRange( const ::com::sun::star::table::CellRangeAddress& rRange );
326         explicit            MergedRange( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nHorAlign );
327         bool                tryExpand( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nHorAlign );
328     };
329     typedef ::std::list< MergedRange > MergedRangeList;
330 
331     CellBlockBuffer     maCellBlocks;           /// Manages all open cell blocks.
332     ArrayFormulaList    maArrayFormulas;        /// All array formulas in the sheet.
333     TableOperationList  maTableOperations;      /// All table operations in the sheet.
334     SharedFormulaMap    maSharedFormulas;       /// Maps shared formula base address to defined name token index.
335     ::com::sun::star::table::CellAddress
336                         maSharedFmlaAddr;       /// Address of a cell containing a pending shared formula.
337     BinAddress          maSharedBaseAddr;       /// Base address of the pending shared formula.
338     XfIdRowRange        maXfIdRowRange;         /// Cached XF identifier for a range of rows.
339     XfIdRangeMap        maXfIdRanges;           /// Collected XF identifiers for cell ranges.
340     MergedRangeList     maMergedRanges;         /// Merged cell ranges.
341     MergedRangeList     maCenterFillRanges;     /// Merged cell ranges from 'center across' or 'fill' alignment.
342     bool                mbPendingSharedFmla;    /// True = maSharedFmlaAddr and maSharedBaseAddr are valid.
343 };
344 
345 // ============================================================================
346 
347 } // namespace xls
348 } // namespace oox
349 
350 #endif
351