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 "xltable.hxx" 23 24 #include <vector> 25 #include "xladdress.hxx" 26 #include "xecontent.hxx" 27 #include "xerecord.hxx" 28 #include "xestyle.hxx" 29 #include "xlformula.hxx" 30 31 #include <map> 32 #include <memory> 33 #include <unordered_map> 34 #include <o3tl/sorted_vector.hxx> 35 36 class XclExtLst; 37 38 /* ============================================================================ 39 Export of cell tables including row and column description. 40 - Managing all used and formatted cells in a sheet. 41 - Row and column properties, i.e. width/height, visibility. 42 - Find default row formatting and default column formatting. 43 - Merged cell ranges. 44 ============================================================================ */ 45 46 // Helper records for cell records 47 48 /** Represents a STRING record that contains the result of a string formula. */ 49 class XclExpStringRec : public XclExpRecord 50 { 51 public: 52 explicit XclExpStringRec( const XclExpRoot& rRoot, const OUString& rResult ); 53 54 private: 55 virtual void WriteBody( XclExpStream& rStrm ) override; 56 57 private: 58 XclExpStringRef mxResult; 59 }; 60 61 // Additional records for special formula ranges 62 63 /** Base record for additional range formula records (i.e. ARRAY, SHRFMLA). */ 64 class XclExpRangeFmlaBase : public XclExpRecord 65 { 66 public: 67 /** Returns true, if the passed cell position is equal to own base position. */ 68 bool IsBasePos( sal_uInt16 nXclCol, sal_uInt32 nXclRow ) const; 69 70 /** Derived classes create the token array for a corresponding FORMULA cell record. */ 71 virtual XclTokenArrayRef CreateCellTokenArray( const XclExpRoot& rRoot ) const = 0; 72 /** Derived classes return true, if the own formula contains volatile functions. */ 73 virtual bool IsVolatile() const = 0; 74 75 protected: 76 /** Constructs the record with a single cell. */ 77 explicit XclExpRangeFmlaBase( 78 sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScAddress& rScPos ); 79 /** Constructs the record with a cell range. */ 80 explicit XclExpRangeFmlaBase( 81 sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScRange& rScRange ); 82 83 /** Extends the cell range to include the passed cell address. */ 84 void Extend( const ScAddress& rScPos ); 85 86 /** Writes the range address covered by this record. */ 87 void WriteRangeAddress( XclExpStream& rStrm ) const; 88 89 protected: 90 XclRange maXclRange; /// Range described by this record. 91 XclAddress maBaseXclPos; /// Address of base cell (first FORMULA record). 92 }; 93 94 typedef rtl::Reference< XclExpRangeFmlaBase > XclExpRangeFmlaRef; 95 96 // Array formulas ============================================================= 97 98 class ScTokenArray; 99 100 /** Represents an ARRAY record that contains the token array of a matrix formula. 101 102 An ARRAY record is stored following the first FORMULA record that is part 103 of a matrix formula. All FORMULA records of a matrix formula contain a 104 reference to the ARRAY record, while the ARRAY record contains the formula 105 token array used by all formulas. 106 */ 107 class XclExpArray : public XclExpRangeFmlaBase 108 { 109 public: 110 explicit XclExpArray( const XclTokenArrayRef& xTokArr, const ScRange& rScRange ); 111 112 /** Creates and returns the token array for a corresponding FORMULA cell record. */ 113 virtual XclTokenArrayRef CreateCellTokenArray( const XclExpRoot& rRoot ) const override; 114 /** Returns true, if the array formula contains volatile functions. */ 115 virtual bool IsVolatile() const override; 116 117 private: 118 virtual void WriteBody( XclExpStream& rStrm ) override; 119 120 private: 121 XclTokenArrayRef mxTokArr; /// The token array of a matrix formula. 122 }; 123 124 typedef rtl::Reference< XclExpArray > XclExpArrayRef; 125 126 /** Caches all ARRAY records. */ 127 class XclExpArrayBuffer : protected XclExpRoot 128 { 129 public: 130 explicit XclExpArrayBuffer( const XclExpRoot& rRoot ); 131 132 /** Inserts a new ARRAY record into the buffer and returns it. */ 133 XclExpArrayRef CreateArray( const ScTokenArray& rScTokArr, const ScRange& rScRange ); 134 /** Tries to find an ARRAY record that corresponds to an ocMatRef token. */ 135 XclExpArrayRef FindArray( const ScTokenArray& rScTokArr, const ScAddress& rBasePos ) const; 136 137 private: 138 typedef ::std::map< ScAddress, XclExpArrayRef > XclExpArrayMap; 139 XclExpArrayMap maRecMap; /// Map containing the ARRAY records. 140 }; 141 142 // Shared formulas ============================================================ 143 144 /** Represents a SHRFMLA record that contains the token array of a shared formula. 145 146 A SHRFMLA record is stored following the first FORMULA record that is part 147 of a shared formula. All FORMULA records of a shared formula contain a 148 reference to the SHRFMLA record, while the SHRFMLA record contains the 149 formula token array used by all formulas. 150 */ 151 class XclExpShrfmla : public XclExpRangeFmlaBase 152 { 153 public: 154 /** Creates a SHRFMLA record that consists of the passed cell address only. */ 155 explicit XclExpShrfmla( const XclTokenArrayRef& xTokArr, const ScAddress& rScPos ); 156 157 /** Extends the cell range to include the passed cell address. */ 158 void ExtendRange( const ScAddress& rScPos ); 159 160 /** Creates and returns the token array for a corresponding FORMULA cell record. */ 161 virtual XclTokenArrayRef CreateCellTokenArray( const XclExpRoot& rRoot ) const override; 162 /** Returns true, if the shared formula contains volatile functions. */ 163 virtual bool IsVolatile() const override; 164 165 private: 166 virtual void WriteBody( XclExpStream& rStrm ) override; 167 168 private: 169 XclTokenArrayRef mxTokArr; /// The token array of a shared formula. 170 sal_uInt8 mnUsedCount; /// Number of FORMULA records referring to this record. 171 }; 172 173 typedef rtl::Reference< XclExpShrfmla > XclExpShrfmlaRef; 174 175 /** Caches all SHRFMLA records and provides functions to update their ranges. */ 176 class XclExpShrfmlaBuffer : protected XclExpRoot 177 { 178 public: 179 explicit XclExpShrfmlaBuffer( const XclExpRoot& rRoot ); 180 181 /** Tries to create a new or to update an existing SHRFMLA record. 182 @return An empty reference, if the passed token array does not contain 183 a shared formula. If the token array is a shared formula, this 184 function updates its cell range to include the passed cell position, 185 if there is a SHRFMLA record for the passed token array; otherwise 186 this function creates and returns a new SHRFMLA record. */ 187 XclExpShrfmlaRef CreateOrExtendShrfmla( const ScFormulaCell& rScCell, const ScAddress& rScPos ); 188 189 private: 190 /** 191 * Check for presence of token that's not allowed in Excel's shared 192 * formula. Refer to the "SharedParsedFormula" section of [MS-XLS] spec 193 * for more info. 194 */ 195 bool IsValidTokenArray( const ScTokenArray& rArray ) const; 196 197 typedef std::unordered_map<const ScTokenArray*, XclExpShrfmlaRef> TokensType; 198 typedef o3tl::sorted_vector<const ScTokenArray*> BadTokenArraysType; 199 200 TokensType maRecMap; /// Map containing the SHRFMLA records. 201 BadTokenArraysType maBadTokens; /// shared tokens we should *not* export as SHRFMLA 202 }; 203 204 // Multiple operations ======================================================== 205 206 /** Represents a TABLEOP record for a multiple operations range. */ 207 class XclExpTableop : public XclExpRangeFmlaBase 208 { 209 public: 210 explicit XclExpTableop( const ScAddress& rScPos, 211 const XclMultipleOpRefs& rRefs, sal_uInt8 nScMode ); 212 213 /** Returns true, if the cell range has been extended to the passed position. 214 @descr All references passed in rRefs must fit the ranges passed in the constructor. */ 215 bool TryExtend( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs ); 216 217 /** Finalizes the record. Tests on valid cell range and reference addresses. */ 218 void Finalize(); 219 220 /** Creates and returns the token array for a corresponding FORMULA cell record. */ 221 virtual XclTokenArrayRef CreateCellTokenArray( const XclExpRoot& rRoot ) const override; 222 /** Returns true, if the multiple operations range is volatile. */ 223 virtual bool IsVolatile() const override; 224 /** Writes the record if it is valid. */ 225 virtual void Save( XclExpStream& rStrm ) override; 226 227 private: 228 /** Returns true, if the passed cell position can be appended to this record. */ 229 bool IsAppendable( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const; 230 231 /** Writes the contents of the TABLEOP record. */ 232 virtual void WriteBody( XclExpStream& rStrm ) override; 233 234 private: 235 sal_uInt16 mnLastAppXclCol;/// Column index of last appended cell. 236 sal_uInt16 mnColInpXclCol; /// Column index of column input cell. 237 sal_uInt32 mnColInpXclRow; /// Row index of column input cell. 238 sal_uInt16 mnRowInpXclCol; /// Column index of row input cell. 239 sal_uInt32 mnRowInpXclRow; /// Row index of row input cell. 240 sal_uInt8 mnScMode; /// Type of the multiple operation (Calc constant). 241 bool mbValid; /// true = Contains valid references. 242 }; 243 244 typedef rtl::Reference< XclExpTableop > XclExpTableopRef; 245 246 /** Contains all created TABLEOP records and supports creating or updating them. */ 247 class XclExpTableopBuffer : protected XclExpRoot 248 { 249 public: 250 explicit XclExpTableopBuffer( const XclExpRoot& rRoot ); 251 252 /** Tries to update an existing or to create a new TABLEOP record. 253 @return Reference to the TABLEOP record for this cell (existing or new), 254 or an empty reference, if rScTokArr does not contain a multiple 255 operations formula. */ 256 XclExpTableopRef CreateOrExtendTableop( 257 const ScTokenArray& rScTokArr, const ScAddress& rScPos ); 258 259 /** Finalizes all contained TABLEOP records. */ 260 void Finalize(); 261 262 private: 263 /** Tries to create a new TABLEOP record, if rRefs contains valid references. */ 264 XclExpTableopRef TryCreate( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs ); 265 266 private: 267 XclExpRecordList< XclExpTableop > maTableopList; /// List of all TABLEOP records. 268 }; 269 270 // Cell records 271 272 /** The base class of all cell records. */ 273 class XclExpCellBase : public XclExpRecord 274 { 275 public: 276 /** Returns the (first) address of the cell(s). */ GetXclPos() const277 const XclAddress& GetXclPos() const { return maXclPos; } 278 /** Returns the (first) Excel column index of the cell(s). */ GetXclCol() const279 sal_uInt16 GetXclCol() const { return maXclPos.mnCol; } 280 /** Returns the Excel row index of the cell. */ GetXclRow() const281 sal_uInt32 GetXclRow() const { return maXclPos.mnRow; } 282 283 /** Derived classes return the column index of the last contained cell. */ 284 virtual sal_uInt16 GetLastXclCol() const = 0; 285 /** Derived classes return the XF identifier of the first contained cell. */ 286 virtual sal_uInt32 GetFirstXFId() const = 0; 287 /** Derived classes return true, if this record does not contain at least one valid cell. */ 288 virtual bool IsEmpty() const = 0; 289 /** Derived classes return whether the cell contains multi-line text. */ 290 virtual bool IsMultiLineText() const; 291 292 /** Derived classes try to merge the contents of the passed cell to own data. */ 293 virtual bool TryMerge( const XclExpCellBase& rCell ); 294 /** Derived classes convert the XF identifier(s) into the Excel XF index(es). 295 @param rXFIndexes The converted XF index(es) are inserted here. */ 296 virtual void ConvertXFIndexes( const XclExpRoot& rRoot ) = 0; 297 /** Derived classes for blank cells insert the Excel XF index(es) into the passed vector. */ 298 virtual void GetBlankXFIndexes( ScfUInt16Vec& rXFIndexes ) const; 299 /** Derived classes for blank cells remove unused Excel XF index(es). */ 300 virtual void RemoveUnusedBlankCells( const ScfUInt16Vec& rXFIndexes ); 301 302 protected: 303 explicit XclExpCellBase( 304 sal_uInt16 nRecId, std::size_t nContSize, const XclAddress& rXclPos ); 305 306 /** Sets this record to a new column position. */ SetXclCol(sal_uInt16 nXclCol)307 void SetXclCol( sal_uInt16 nXclCol ) { maXclPos.mnCol = nXclCol; } 308 309 private: 310 XclAddress maXclPos; /// Address of the cell. 311 }; 312 313 typedef rtl::Reference< XclExpCellBase > XclExpCellRef; 314 315 // Single cell records ======================================================== 316 317 /** Base class for all cell records not supporting multiple contents. */ 318 class XclExpSingleCellBase : public XclExpCellBase 319 { 320 public: 321 /** Returns the last column, which is equal to the first column for single cells. */ 322 virtual sal_uInt16 GetLastXclCol() const override; 323 /** Return the XF identifier of the cell. */ 324 virtual sal_uInt32 GetFirstXFId() const override; 325 /** Returns true, if this record does not contain at least one valid cell. */ 326 virtual bool IsEmpty() const override; 327 /** Converts the XF identifier into the Excel XF index. */ 328 virtual void ConvertXFIndexes( const XclExpRoot& rRoot ) override; 329 /** Writes cell address, XF index, and calls WriteContents() for each cell. */ 330 virtual void Save( XclExpStream& rStrm ) override; 331 332 protected: 333 explicit XclExpSingleCellBase( sal_uInt16 nRecId, std::size_t nContSize, 334 const XclAddress& rXclPos, sal_uInt32 nXFId ); 335 336 explicit XclExpSingleCellBase( const XclExpRoot& rRoot, 337 sal_uInt16 nRecId, std::size_t nContSize, const XclAddress& rXclPos, 338 const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uInt32 nForcedXFId ); 339 SetContSize(std::size_t nContSize)340 void SetContSize( std::size_t nContSize ) { mnContSize = nContSize; } GetContSize() const341 std::size_t GetContSize() const { return mnContSize; } 342 SetXFId(sal_uInt32 nXFId)343 void SetXFId( sal_uInt32 nXFId ) { maXFId.mnXFId = nXFId; } GetXFId() const344 sal_uInt32 GetXFId() const { return maXFId.mnXFId; } 345 346 private: 347 /** Writes cell address, XF index, and calls WriteContents() for each cell. */ 348 virtual void WriteBody( XclExpStream& rStrm ) override; 349 /** Derived classes write the contents of the specified cell (without XF index). */ 350 virtual void WriteContents( XclExpStream& rStrm ) = 0; 351 352 private: 353 XclExpXFId maXFId; /// The XF identifier of the cell formatting. 354 std::size_t mnContSize; /// The size of the cell contents. 355 }; 356 357 /** Represents a NUMBER record that describes a cell with a double value. */ 358 class XclExpNumberCell : public XclExpSingleCellBase 359 { 360 public: 361 explicit XclExpNumberCell( const XclExpRoot& rRoot, const XclAddress& rXclPos, 362 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, 363 double fValue ); 364 365 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 366 private: 367 virtual void WriteContents( XclExpStream& rStrm ) override; 368 369 private: 370 double mfValue; /// The cell value. 371 }; 372 373 /** Represents a BOOLERR record that describes a cell with a Boolean value. */ 374 class XclExpBooleanCell : public XclExpSingleCellBase 375 { 376 public: 377 explicit XclExpBooleanCell( const XclExpRoot& rRoot, const XclAddress& rXclPos, 378 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, 379 bool bValue ); 380 381 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 382 private: 383 virtual void WriteContents( XclExpStream& rStrm ) override; 384 385 private: 386 bool mbValue; /// The cell value. 387 }; 388 389 class XclExpHyperlinkHelper; 390 class EditTextObject; 391 392 /** Represents a text cell record. 393 394 May contain a BIFF2-BIFF7 LABEL record for a simple string, or a BIFF2-BIFF7 395 RSTRING record for a formatted string, or a BIFF8 LABELSST string for any 396 string (simply stores a reference to the Shared String Table). 397 */ 398 class XclExpLabelCell : public XclExpSingleCellBase 399 { 400 public: 401 /** Constructs the record from an unformatted Calc string cell. */ 402 explicit XclExpLabelCell( const XclExpRoot& rRoot, const XclAddress& rXclPos, 403 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, 404 const OUString& rStr ); 405 406 /** Constructs the record from a formatted Calc edit cell. */ 407 explicit XclExpLabelCell( const XclExpRoot& rRoot, const XclAddress& rXclPos, 408 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, 409 const EditTextObject* pEditText, XclExpHyperlinkHelper& rHlinkHelper ); 410 411 /** Returns true if the cell contains multi-line text. */ 412 virtual bool IsMultiLineText() const override; 413 414 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 415 private: 416 /** Initializes the record contents. Called from constructors. */ 417 void Init( const XclExpRoot& rRoot, 418 const ScPatternAttr* pPattern, XclExpStringRef const & xText ); 419 420 virtual void WriteContents( XclExpStream& rStrm ) override; 421 422 private: 423 XclExpStringRef mxText; /// The cell text. 424 sal_uInt32 mnSstIndex; /// Index into Shared String Table (only used for BIFF8). 425 bool mbLineBreak; /// True = cell has automatic linebreaks enabled. 426 }; 427 428 class ScFormulaCell; 429 430 /** Represents a FORMULA record that describes a cell with a formula. */ 431 class XclExpFormulaCell : public XclExpSingleCellBase 432 { 433 public: 434 explicit XclExpFormulaCell( const XclExpRoot& rRoot, const XclAddress& rXclPos, 435 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, 436 const ScFormulaCell& rScFmlaCell, 437 XclExpArrayBuffer& rArrayBfr, 438 XclExpShrfmlaBuffer& rShrfmlaBfr, 439 XclExpTableopBuffer& rTableopBfr ); 440 441 /** Writes the FORMULA record and additional records related to the formula. */ 442 virtual void Save( XclExpStream& rStrm ) override; 443 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 444 445 private: 446 virtual void WriteContents( XclExpStream& rStrm ) override; 447 448 private: 449 ScFormulaCell& mrScFmlaCell; /// The Calc formula cell. 450 XclTokenArrayRef mxTokArr; /// The token array of the formula. 451 XclExpRangeFmlaRef mxAddRec; /// Additional record for matrix/shared formulas. 452 XclExpRecordRef mxStringRec; /// STRING record for string result. 453 }; 454 455 // Multiple cell records ====================================================== 456 457 struct XclExpMultiXFId : public XclExpXFId 458 { 459 sal_uInt16 mnCount; /// Number of XF identifiers. 460 XclExpMultiXFIdXclExpMultiXFId461 explicit XclExpMultiXFId( sal_uInt32 nXFId, sal_uInt16 nCount = 1 ) : 462 XclExpXFId( nXFId ), mnCount( nCount ) {} 463 }; 464 465 /** Base class for all cell records supporting multiple contents. */ 466 class XclExpMultiCellBase : public XclExpCellBase 467 { 468 public: 469 /** Returns the column index of the last cell this record describes. */ 470 virtual sal_uInt16 GetLastXclCol() const override; 471 /** Return the XF identifier of the first contained cell. */ 472 virtual sal_uInt32 GetFirstXFId() const override; 473 /** Returns true, if this record does not contain at least one valid cell. */ 474 virtual bool IsEmpty() const override; 475 476 /** Convert all XF identifiers into the Excel XF indexes. */ 477 virtual void ConvertXFIndexes( const XclExpRoot& rRoot ) override; 478 /** Writes the record, calls WriteContents() for each contained cell. 479 @descr May write several records, if unused XF indexes are contained. */ 480 virtual void Save( XclExpStream& rStrm ) override; 481 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 482 483 protected: 484 explicit XclExpMultiCellBase( sal_uInt16 nRecId, sal_uInt16 nMulRecId, 485 std::size_t nContSize, const XclAddress& rXclPos ); 486 487 /** Returns the number of cells this record represents. */ 488 sal_uInt16 GetCellCount() const; 489 490 /** Appends the passed XF identifier nCount times to the list of XF identifiers. */ 491 void AppendXFId( const XclExpMultiXFId& rXFId ); 492 /** Appends the passed cell format nCount times to the list of XF identifiers. */ 493 void AppendXFId( const XclExpRoot& rRoot, 494 const ScPatternAttr* pPattern, sal_uInt16 nScript, 495 sal_uInt32 nForcedXFId, sal_uInt16 nCount = 1 ); 496 497 /** Tries to merge the XF ID list of the passed cell with the own list. */ 498 bool TryMergeXFIds( const XclExpMultiCellBase& rCell ); 499 /** Inserts the Excel XF index(es) into the passed vector. */ 500 void GetXFIndexes( ScfUInt16Vec& rXFIndexes ) const; 501 502 /** Removes unused Excel XF index(es). 503 @param rXFIndexes Specifies which XF indexes are used. */ 504 void RemoveUnusedXFIndexes( const ScfUInt16Vec& rXFIndexes ); 505 506 private: 507 /** Derived classes write the remaining contents of the specified cell (without XF index). 508 @param nRelCol Relative column index (starts with 0 for first cell of this record). */ 509 virtual void WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol ) = 0; 510 virtual void WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol ) = 0; 511 512 private: 513 typedef ::std::vector< XclExpMultiXFId > XclExpMultiXFIdDeq; 514 515 sal_uInt16 mnMulRecId; /// Record ID for multiple record variant. 516 std::size_t mnContSize; /// Data size of contents for one cell 517 XclExpMultiXFIdDeq maXFIds; /// The XF identifiers of the cell formatting. 518 }; 519 520 /** Represents a BLANK or MULBLANK record that describes empty but formatted cells. */ 521 class XclExpBlankCell : public XclExpMultiCellBase 522 { 523 public: 524 explicit XclExpBlankCell( const XclAddress& rXclPos, const XclExpMultiXFId& rXFId ); 525 526 explicit XclExpBlankCell( const XclExpRoot& rRoot, 527 const XclAddress& rXclPos, sal_uInt16 nLastXclCol, 528 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId ); 529 530 /** Tries to merge the contents of the passed cell to own data. */ 531 virtual bool TryMerge( const XclExpCellBase& rCell ) override; 532 /** Inserts the Excel XF index(es) into the passed vector. */ 533 virtual void GetBlankXFIndexes( ScfUInt16Vec& rXFIndexes ) const override; 534 /** Tries to remove unused Excel XF index(es). */ 535 virtual void RemoveUnusedBlankCells( const ScfUInt16Vec& rXFIndexes ) override; 536 537 private: 538 /** Writes the remaining contents of the specified cell (without XF index). */ 539 virtual void WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol ) override; 540 virtual void WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol ) override; 541 }; 542 543 /** Represents an RK or MULRK record that describes cells with a compressed double values. */ 544 class XclExpRkCell : public XclExpMultiCellBase 545 { 546 public: 547 explicit XclExpRkCell( const XclExpRoot& rRoot, const XclAddress& rXclPos, 548 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, 549 sal_Int32 nRkValue ); 550 551 /** Tries to merge the contents of the passed cell to own data. */ 552 virtual bool TryMerge( const XclExpCellBase& rCell ) override; 553 554 private: 555 /** Writes the remaining contents of the specified cell (without XF index). */ 556 virtual void WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol ) override; 557 virtual void WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol ) override; 558 559 private: 560 ScfInt32Vec maRkValues; /// The cell values. 561 }; 562 563 // Rows and Columns 564 565 class ScOutlineArray; 566 567 /** Base class for buffers containing row or column outline data. */ 568 class XclExpOutlineBuffer 569 { 570 public: 571 /** Returns true, if a collapsed group ends at the last processed position. */ IsCollapsed() const572 bool IsCollapsed() const { return mbCurrCollapse; } 573 /** Returns the highest level of an open group at the last processed position. */ GetLevel() const574 sal_uInt8 GetLevel() const { return ::std::min( mnCurrLevel, EXC_OUTLINE_MAX ); } 575 576 protected: 577 /** Constructs the outline buffer. 578 @param bRows true = Process row outline array; false = Process column outline array. */ 579 explicit XclExpOutlineBuffer( const XclExpRoot& rRoot, bool bRows ); 580 581 /** Updates the current state by processing the settings at the passed Calc position. */ 582 void UpdateColRow( SCCOLROW nScPos ); 583 584 private: 585 /** Data about an outline level. */ 586 struct XclExpLevelInfo 587 { 588 SCCOLROW mnScEndPos; /// The end position of a group in a level. 589 bool mbHidden; /// true = Group in this level is hidden. XclExpLevelInfoXclExpOutlineBuffer::XclExpLevelInfo590 explicit XclExpLevelInfo() : mnScEndPos( 0 ), mbHidden( false ) {} 591 }; 592 593 const ScOutlineArray* mpScOLArray; /// Pointer to Calc outline array. 594 std::vector< XclExpLevelInfo > 595 maLevelInfos; /// Info for current row and all levels. 596 sal_uInt8 mnCurrLevel; /// Highest level of an open group for current position. 597 bool mbCurrCollapse; /// true = Collapsed group ends at current position. 598 }; 599 600 /** The outline buffer for column outlines. */ 601 class XclExpColOutlineBuffer : public XclExpOutlineBuffer 602 { 603 public: XclExpColOutlineBuffer(const XclExpRoot & rRoot)604 explicit XclExpColOutlineBuffer( const XclExpRoot& rRoot ) : 605 XclExpOutlineBuffer( rRoot, false ) {} 606 607 /** Updates the current state by processing the settings of the passed Calc column. */ Update(SCCOL nScCol)608 void Update( SCCOL nScCol ) 609 { UpdateColRow( static_cast< SCCOLROW >( nScCol ) ); } 610 }; 611 612 /** The outline buffer for row outlines. */ 613 class XclExpRowOutlineBuffer : public XclExpOutlineBuffer 614 { 615 public: XclExpRowOutlineBuffer(const XclExpRoot & rRoot)616 explicit XclExpRowOutlineBuffer( const XclExpRoot& rRoot ) : 617 XclExpOutlineBuffer( rRoot, true ) {} 618 619 /** Updates the current state by processing the settings of the passed Calc row. */ Update(SCROW nScRow)620 void Update( SCROW nScRow ) 621 { UpdateColRow( static_cast< SCCOLROW >( nScRow ) ); } 622 }; 623 624 /** Represents a GUTS record containing the level count of row and column outlines. */ 625 class XclExpGuts : public XclExpRecord 626 { 627 public: 628 explicit XclExpGuts( const XclExpRoot& rRoot ); 629 630 private: 631 virtual void WriteBody( XclExpStream& rStrm ) override; 632 633 private: 634 sal_uInt16 mnColLevels; /// Number of visible column outline levels. 635 sal_uInt16 mnColWidth; /// Width of column outline area (pixels). 636 sal_uInt16 mnRowLevels; /// Number of visible row outline levels. 637 sal_uInt16 mnRowWidth; /// Width of row outline area (pixels). 638 }; 639 640 /** Represents a DIMENSIONS record containing the used area of a sheet. */ 641 class XclExpDimensions : public XclExpRecord 642 { 643 public: 644 explicit XclExpDimensions( const XclExpRoot& rRoot ); 645 646 /** Sets the used area to the record. */ 647 void SetDimensions( 648 sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow, 649 sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow ); 650 651 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 652 private: 653 /** Writes the contents of the DIMENSIONS record. */ 654 virtual void WriteBody( XclExpStream& rStrm ) override; 655 656 private: 657 const XclExpRoot& mrRoot; 658 sal_uInt32 mnFirstUsedXclRow; /// First used row. 659 sal_uInt32 mnFirstFreeXclRow; /// First unused row after used area. 660 sal_uInt16 mnFirstUsedXclCol; /// First used column. 661 sal_uInt16 mnFirstFreeXclCol; /// First free column after used area. 662 }; 663 664 /** Represents the DEFCOLWIDTH record containing the default column width of a sheet. 665 666 Excel stores the default column width in entire character widths of the '0' 667 character using the application default font (i.e. the default width is 10, 668 if the '0' character fits 10 times into a cell in a column with default 669 width. 670 671 Half of character width is reserved for non character display. 672 It is margin padding (two on each side) and padding for the gridlines. 673 674 The IsDefWidth() function returns true, if the passed width (measured in 675 1/256 of the width of the '0' character) could be converted exactly to the 676 default width. If the passed width is rounded up or down to get the default 677 width, the function returns false. 678 */ 679 class XclExpDefcolwidth : public XclExpDoubleRecord, protected XclExpRoot 680 { 681 public: 682 explicit XclExpDefcolwidth( const XclExpRoot& rRoot ); 683 684 /** Returns true, if the own default width exactly matches the passed width. */ 685 bool IsDefWidth( sal_uInt16 nXclColWidth ) const; 686 687 /** Sets the passed column width (in 1/256 character width) as default width. */ 688 void SetDefWidth( sal_uInt16 nXclColWidth, bool bXLS ); 689 690 virtual void Save(XclExpStream& rStrm) override; 691 }; 692 693 /** Contains the column settings for a range of columns. 694 695 After construction the record contains a temporary XF identifier returned 696 from the XF buffer. After creating the entire Excel document in memory, the 697 ConvertXFIndexes() function converts it into the real Excel XF index. 698 */ 699 class XclExpColinfo : public XclExpRecord, protected XclExpRoot 700 { 701 public: 702 /** Constructs the record with the settings in the Calc document. */ 703 explicit XclExpColinfo( const XclExpRoot& rRoot, 704 SCCOL nScCol, SCROW nLastScRow, 705 XclExpColOutlineBuffer& rOutlineBfr ); 706 707 /** Converts the XF identifier into the Excel XF index. */ 708 void ConvertXFIndexes(); 709 710 /** Tries to merge this record with the passed record. 711 @descr Possible, if passed record directly follows this record and has equal contents. 712 @return true = This record is equal to passed record and has been updated. */ 713 bool TryMerge( const XclExpColinfo& rColInfo ); 714 715 /** Returns the Excel width of the column(s). */ GetColWidth() const716 sal_uInt16 GetColWidth() const { return mnWidth; } 717 /** Returns the final Excel XF index of the column(s). */ GetXFIndex() const718 sal_uInt16 GetXFIndex() const { return maXFId.mnXFIndex; } 719 /** Returns the number of columns represented by this record. */ GetColCount() const720 sal_uInt16 GetColCount() const { return mnLastXclCol - mnFirstXclCol + 1; } 721 722 /** Returns true, if the column has default format and width. Also sets mbCustomWidth */ 723 bool IsDefault( const XclExpDefcolwidth& rDefColWidth ); 724 725 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 726 727 private: 728 /** Writes the contents of this COLINFO record. */ 729 virtual void WriteBody( XclExpStream& rStrm ) override; 730 731 private: 732 XclExpXFId maXFId; /// The XF identifier for column default format. 733 bool mbCustomWidth; /// True = Column width is different from default width 734 sal_uInt16 mnWidth; /// Excel width of the column. 735 sal_uInt16 mnScWidth; /// Calc width of the column. 736 sal_uInt16 mnFlags; /// Additional column flags. 737 sal_uInt8 mnOutlineLevel; /// Outline Level of column (for OOXML) 738 sal_uInt16 mnFirstXclCol; /// Index to first column. 739 sal_uInt16 mnLastXclCol; /// Index to last column. 740 }; 741 742 /** Contains COLINFO records for all columns of a Calc sheet. 743 744 On construction one COLINFO record per column is created. After creating 745 the entire Excel document in memory, the ConvertXFIndexes() function converts 746 all temporary XF identifiers into real Excel XF indexes and merges all equal 747 COLINFO records together. 748 */ 749 class XclExpColinfoBuffer : public XclExpRecordBase, protected XclExpRoot 750 { 751 public: 752 explicit XclExpColinfoBuffer( const XclExpRoot& rRoot ); 753 754 /** Initializes the buffer: finds settings and formatting of all columns. 755 @param nLastScRow Last row used to find default formatting. */ 756 void Initialize( SCROW nLastScRow ); 757 /** Converts the XF identifiers into the Excel XF indexes and merges equal columns. 758 @param rXFIndexes Returns the final XF indexes of all columns. */ 759 void Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS ); 760 761 /** Writes all COLINFO records of this buffer. */ 762 virtual void Save( XclExpStream& rStrm ) override; 763 virtual void SaveXml( XclExpXmlStream& rStrm ) override; GetHighestOutlineLevel() const764 sal_uInt8 GetHighestOutlineLevel() const { return mnHighestOutlineLevel; } GetDefColWidth() const765 double GetDefColWidth() const { return maDefcolwidth.GetValue(); } 766 767 private: 768 typedef XclExpRecordList< XclExpColinfo > XclExpColinfoList; 769 typedef XclExpColinfoList::RecordRefType XclExpColinfoRef; 770 771 XclExpColinfoList maColInfos; /// List of COLINFO records. 772 XclExpDefcolwidth maDefcolwidth; /// The DEFCOLWIDTH record. 773 XclExpColOutlineBuffer maOutlineBfr; /// Buffer for column outline groups. 774 sal_uInt8 mnHighestOutlineLevel; /// Highest number of outline levels for columns in sheet. 775 }; 776 777 class XclExpRow; 778 779 /** Contains all possible default row settings. */ 780 struct XclExpDefaultRowData 781 { 782 sal_uInt16 mnFlags; /// Default flags for unspecified rows. 783 sal_uInt16 mnHeight; /// Default height for unspecified rows. 784 785 explicit XclExpDefaultRowData(); 786 explicit XclExpDefaultRowData( const XclExpRow& rRow ); 787 788 /** Returns true, if rows are hidden by default. */ IsHiddenXclExpDefaultRowData789 bool IsHidden() const { return ::get_flag( mnFlags, EXC_DEFROW_HIDDEN ); } 790 /** Returns true, if the rows have a manually set height by default. */ IsUnsyncedXclExpDefaultRowData791 bool IsUnsynced() const { return ::get_flag( mnFlags, EXC_DEFROW_UNSYNCED ); } 792 }; 793 794 /** Represents a DEFROWHEIGHT record containing default format for unused rows. */ 795 class XclExpDefrowheight : public XclExpRecord 796 { 797 public: 798 explicit XclExpDefrowheight(); 799 800 /** Sets the passed default data as current record contents. */ 801 void SetDefaultData( const XclExpDefaultRowData& rDefData ); GetDefaultData()802 XclExpDefaultRowData& GetDefaultData() { return maDefData; } 803 private: 804 /** Writes the contents of the record. */ 805 virtual void WriteBody( XclExpStream& rStrm ) override; 806 807 private: 808 XclExpDefaultRowData maDefData; /// Record data. 809 }; 810 811 /** Represents a ROW record and additionally contains all cells records of a row. 812 813 This class contains all cell records of a row in a spreadsheet. There are 2 814 cell records in Excel that support storing a range of cells in one record 815 (MULBLANK for multiple blank cells, and MULRK for multiple RK values). The 816 insertion functions try to merge a new inserted cell with existing 817 neighbors, if this is supported by the current type of cell record. 818 819 The Finalize() function converts the XF identifiers of all cell records to 820 the final Excel XF indexes. Then a default 821 */ 822 class XclExpRow : public XclExpRecord, protected XclExpRoot 823 { 824 public: 825 /** Constructs the ROW record and converts the Calc row settings. 826 @param bAlwaysEmpty true = This row will not be filled with blank cells 827 in the Finalize() function. */ 828 explicit XclExpRow( const XclExpRoot& rRoot, sal_uInt32 nXclRow, 829 XclExpRowOutlineBuffer& rOutlineBfr, bool bAlwaysEmpty, bool bHidden, sal_uInt16 nHeight ); 830 831 /** Returns the excel row index of this ROW record. */ GetXclRow() const832 sal_uInt32 GetXclRow() const { return mnXclRow; } 833 /** Returns the height of the row in twips. */ GetHeight() const834 sal_uInt16 GetHeight() const { return mnHeight; } 835 /** Returns true, if this row does not contain at least one valid cell. */ IsEmpty() const836 bool IsEmpty() const { return maCellList.IsEmpty(); } 837 /** Returns true, if this row is hidden. */ IsHidden() const838 bool IsHidden() const { return ::get_flag( mnFlags, EXC_ROW_HIDDEN ); } 839 /** Returns true, if this row contains a manually set height. */ IsUnsynced() const840 bool IsUnsynced() const { return ::get_flag( mnFlags, EXC_ROW_UNSYNCED ); } 841 /** Returns true, if this row is enabled (will be exported). */ IsEnabled() const842 bool IsEnabled() const { return mbEnabled; } 843 844 /** Appends the passed cell object to this row. */ 845 void AppendCell( XclExpCellRef const & xCell, bool bIsMergedBase ); 846 847 /** Converts all XF identifiers into the Excel XF indexes. */ 848 void Finalize( const ScfUInt16Vec& rColXFIndexes, 849 bool bUpdateProgress ); 850 851 /** Returns the column index of the first used cell in this row. 852 @descr This function can only be called after Finalize(). */ 853 sal_uInt16 GetFirstUsedXclCol() const; 854 /** Returns the column index of the first unused cell following all used cells in this row. 855 @descr This function can only be called after Finalize(). */ 856 sal_uInt16 GetFirstFreeXclCol() const; 857 858 /** Returns true, if this row may be omitted by using the DEFROWHEIGHT record. 859 @descr A row may be omitted, if it does not contain any cell or 860 explicit default cell formatting, and is not part of an outline. 861 This function can only be called after Finalize(). */ 862 bool IsDefaultable() const; 863 /** Disables this row, if it is defaultable and has the passed default format. 864 @descr Disabled rows will not be saved. 865 This function can only be called after Finalize(). */ 866 void DisableIfDefault( const XclExpDefaultRowData& rDefRowData ); 867 868 /** Writes all cell records of this row. */ 869 void WriteCellList( XclExpStream& rStrm ); 870 871 /** Writes the ROW record if the row is not disabled (see DisableIfDefault() function). */ 872 virtual void Save( XclExpStream& rStrm ) override; 873 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 874 GetXclRowRpt() const875 sal_uInt32 GetXclRowRpt() const { return mnXclRowRpt; } SetXclRowRpt(sal_uInt32 nRpt)876 void SetXclRowRpt( sal_uInt32 nRpt ){ mnXclRowRpt = nRpt; } 877 private: 878 /** Inserts a cell at the specified list position, tries to merge with neighbors. */ 879 void InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase ); 880 881 /** Writes the contents of the ROW record. */ 882 virtual void WriteBody( XclExpStream& rStrm ) override; 883 884 private: 885 XclExpRecordList< XclExpCellBase > 886 maCellList; /// List of cell records for this row. 887 sal_uInt32 mnXclRow; /// Excel row index of this row. 888 sal_uInt16 mnHeight; /// Row height in twips. 889 sal_uInt16 mnFlags; /// Flags for the ROW record. 890 sal_uInt16 mnXFIndex; /// Default row formatting. 891 sal_uInt8 mnOutlineLevel; /// Outline Level of row (for OOXML) 892 sal_uInt32 mnXclRowRpt; 893 sal_uInt32 mnCurrentRow; 894 bool mbAlwaysEmpty; /// true = Do not add blank cells in Finalize(). 895 bool mbEnabled; /// true = Write this ROW record. 896 }; 897 898 /** Collects all rows which contain all cells of a sheet. 899 900 This row buffer automatically creates ROW records when cells are inserted 901 with the AppendCell() function. It is possible to force creation of more 902 ROW records with the CreateRows() function. In both cases, all preceding 903 missing ROW records are inserted too. 904 */ 905 class XclExpRowBuffer : public XclExpRecordBase, protected XclExpRoot 906 { 907 public: 908 explicit XclExpRowBuffer( const XclExpRoot& rRoot ); 909 910 /** Appends the passed cell object to the row that the cell specifies. */ 911 void AppendCell( XclExpCellRef const & xCell, bool bIsMergedBase ); 912 /** Forces insertion of all ROW records before the passed row. */ 913 void CreateRows( SCROW nFirstFreeScRow ); 914 915 /** Converts all XF identifiers into the Excel XF indexes and calculates default formats. 916 @param rDefRowData (out-param) The default row format is returned here. 917 @param rColXFIndexes The column default XF indexes. */ 918 void Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt16Vec& rColXFIndexes ); 919 920 /** Writes the DIMENSIONS record, all ROW records and all cell records. */ 921 virtual void Save( XclExpStream& rStrm ) override; 922 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 923 GetDimensions()924 XclExpDimensions& GetDimensions() { return maDimensions; } GetHighestOutlineLevel() const925 sal_uInt8 GetHighestOutlineLevel() const { return mnHighestOutlineLevel; } 926 927 private: 928 /** Returns access to the specified ROW record. Inserts preceding missing ROW records. 929 @param bRowAlwaysEmpty true = Created rows will not be filled with blank cells 930 in the XclExpRow::Finalize() function. */ 931 XclExpRow& GetOrCreateRow( sal_uInt32 nXclRow, bool bRowAlwaysEmpty ); 932 933 private: 934 typedef std::shared_ptr<XclExpRow> RowRef; 935 typedef ::std::map<sal_uInt32, RowRef> RowMap; 936 937 RowMap maRowMap; 938 XclExpRowOutlineBuffer maOutlineBfr; /// Buffer for row outline groups. 939 XclExpDimensions maDimensions; /// DIMENSIONS record for used area. 940 sal_uInt8 mnHighestOutlineLevel; /// Highest number of outline levels for rows in sheet. 941 }; 942 943 // Cell Table 944 945 class XclExpNote; 946 class XclExpMergedcells; 947 class XclExpHyperlink; 948 class XclExpDval; 949 950 /** This class contains the cell contents and more of an entire sheet. 951 952 The cell table includes the settings and default formatting of all columns, 953 the settings and default formatting of all used rows, and the contents of 954 all cells of one sheet in a spreadsheet document. 955 956 The constructor does all the work creating the cell table. It reads the 957 Calc sheet and converts all columns, rows, and cells to Excel record data. 958 Additionally, hyperlink records, note records, additional records for 959 formula cells, data validation records, and outline records are created. 960 961 The Finalize() function does even more work. It calculates default column 962 settings and removes column records that are equal to this default. The 963 same happens with rows: A default format is calculated for each row, and 964 all blank cells in this row that have the same format are removed. Then, 965 the most used row settings are calculated, and all empty rows that have the 966 same settings are removed too. 967 968 Records that are not stored inside the cell table area in an Excel file 969 (i.e. DEFROWHEIGHT record, NOTE records, MERGEDCELLS record, HLINK records, 970 DVAL and DV records for data validation) can be accessed with the function 971 CreateRecord(). It returns the reference to the respective record (or 972 record list) which can be inserted into a record list. 973 */ 974 class XclExpCellTable : public XclExpRecordBase, protected XclExpRoot 975 { 976 public: 977 explicit XclExpCellTable( const XclExpRoot& rRoot ); 978 979 /** Converts all XF identifiers into the Excel XF indexes and calculates default formats. */ 980 void Finalize(bool bXLS); 981 982 /** Returns the reference to an internal record specified by the passed record id. 983 @param nRecId The record identifier that specifies which record is 984 returned. Possible values are: EXC_ID_DEFROWHEIGHT, EXC_ID_NOTE, 985 EXC_ID_MERGEDCELLS, EXC_ID_HLINK, EXC_ID_DVAL. */ 986 XclExpRecordRef CreateRecord( sal_uInt16 nRecId ) const; 987 /** Saves the entire cell table. */ 988 virtual void Save( XclExpStream& rStrm ) override; 989 virtual void SaveXml( XclExpXmlStream& rStrm ) override; 990 991 private: 992 typedef XclExpRecordList< XclExpNote > XclExpNoteList; 993 typedef XclExpRecordList< XclExpHyperlink > XclExpHyperlinkList; 994 995 typedef rtl::Reference< XclExpDefrowheight > XclExpDefrowhRef; 996 typedef rtl::Reference< XclExpNoteList > XclExpNoteListRef; 997 typedef rtl::Reference< XclExpMergedcells > XclExpMergedcellsRef; 998 typedef rtl::Reference< XclExpHyperlinkList > XclExpHyperlinkRef; 999 typedef rtl::Reference< XclExpDval > XclExpDvalRef; 1000 typedef rtl::Reference< XclExtLst > XclExtLstRef; 1001 1002 XclExpColinfoBuffer maColInfoBfr; /// Buffer for column formatting. 1003 XclExpRowBuffer maRowBfr; /// Rows and cell records. 1004 XclExpArrayBuffer maArrayBfr; /// Buffer for ARRAY records. 1005 XclExpShrfmlaBuffer maShrfmlaBfr; /// Buffer for SHRFMLA records. 1006 XclExpTableopBuffer maTableopBfr; /// Buffer for TABLEOP records. 1007 XclExpDefrowhRef mxDefrowheight; /// DEFROWHEIGHT record for default row format. 1008 XclExpRecordRef mxGuts; /// GUTS record for outline areas. 1009 XclExpNoteListRef mxNoteList; /// List of NOTE records. 1010 XclExpMergedcellsRef mxMergedcells; /// MERGEDCELLS record for merged cell ranges. 1011 XclExpHyperlinkRef mxHyperlinkList; /// List of HLINK records. 1012 XclExpDvalRef mxDval; /// Data validation with DVAL and DV records. 1013 XclExtLstRef mxExtLst; 1014 }; 1015 1016 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1017