LCOV - code coverage report
Current view: top level - sc/source/filter/oox - sheetdatabuffer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 167 325 51.4 %
Date: 2012-08-25 Functions: 25 45 55.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 185 606 30.5 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "sheetdatabuffer.hxx"
      30                 :            : 
      31                 :            : #include <algorithm>
      32                 :            : #include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
      33                 :            : #include <com/sun/star/sheet/XCellRangeData.hpp>
      34                 :            : #include <com/sun/star/sheet/XFormulaTokens.hpp>
      35                 :            : #include <com/sun/star/sheet/XMultipleOperation.hpp>
      36                 :            : #include <com/sun/star/table/XCell.hpp>
      37                 :            : #include <com/sun/star/text/XText.hpp>
      38                 :            : #include <com/sun/star/util/DateTime.hpp>
      39                 :            : #include <com/sun/star/util/NumberFormat.hpp>
      40                 :            : #include <com/sun/star/util/XMergeable.hpp>
      41                 :            : #include <com/sun/star/util/XNumberFormatTypes.hpp>
      42                 :            : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
      43                 :            : #include <rtl/ustrbuf.hxx>
      44                 :            : #include <editeng/boxitem.hxx>
      45                 :            : #include <editeng/editobj.hxx>
      46                 :            : #include <svl/eitem.hxx>
      47                 :            : #include "oox/helper/containerhelper.hxx"
      48                 :            : #include "oox/helper/propertymap.hxx"
      49                 :            : #include "oox/helper/propertyset.hxx"
      50                 :            : #include "oox/token/tokens.hxx"
      51                 :            : #include "addressconverter.hxx"
      52                 :            : #include "biffinputstream.hxx"
      53                 :            : #include "formulaparser.hxx"
      54                 :            : #include "sharedstringsbuffer.hxx"
      55                 :            : #include "unitconverter.hxx"
      56                 :            : #include "convuno.hxx"
      57                 :            : #include "markdata.hxx"
      58                 :            : #include "rangelst.hxx"
      59                 :            : #include "document.hxx"
      60                 :            : #include "scitems.hxx"
      61                 :            : #include "cell.hxx"
      62                 :            : 
      63                 :            : namespace oox {
      64                 :            : namespace xls {
      65                 :            : 
      66                 :            : // ============================================================================
      67                 :            : 
      68                 :            : using namespace ::com::sun::star::lang;
      69                 :            : using namespace ::com::sun::star::sheet;
      70                 :            : using namespace ::com::sun::star::table;
      71                 :            : using namespace ::com::sun::star::text;
      72                 :            : using namespace ::com::sun::star::uno;
      73                 :            : using namespace ::com::sun::star::util;
      74                 :            : 
      75                 :            : using ::rtl::OUString;
      76                 :            : using ::rtl::OUStringBuffer;
      77                 :            : 
      78                 :            : // ============================================================================
      79                 :            : 
      80                 :         60 : CellModel::CellModel() :
      81                 :            :     mnCellType( XML_TOKEN_INVALID ),
      82                 :            :     mnXfId( -1 ),
      83                 :         60 :     mbShowPhonetic( false )
      84                 :            : {
      85                 :         60 : }
      86                 :            : 
      87                 :            : // ----------------------------------------------------------------------------
      88                 :            : 
      89                 :         60 : CellFormulaModel::CellFormulaModel() :
      90                 :            :     mnFormulaType( XML_TOKEN_INVALID ),
      91                 :         60 :     mnSharedId( -1 )
      92                 :            : {
      93                 :         60 : }
      94                 :            : 
      95                 :          0 : bool CellFormulaModel::isValidArrayRef( const CellAddress& rCellAddr )
      96                 :            : {
      97                 :            :     return
      98                 :            :         (maFormulaRef.Sheet == rCellAddr.Sheet) &&
      99                 :            :         (maFormulaRef.StartColumn == rCellAddr.Column) &&
     100 [ #  # ][ #  # ]:          0 :         (maFormulaRef.StartRow == rCellAddr.Row);
                 [ #  # ]
     101                 :            : }
     102                 :            : 
     103                 :          3 : bool CellFormulaModel::isValidSharedRef( const CellAddress& rCellAddr )
     104                 :            : {
     105                 :            :     return
     106                 :            :         (maFormulaRef.Sheet == rCellAddr.Sheet) &&
     107                 :            :         (maFormulaRef.StartColumn <= rCellAddr.Column) && (rCellAddr.Column <= maFormulaRef.EndColumn) &&
     108 [ +  - ][ +  - ]:          3 :         (maFormulaRef.StartRow <= rCellAddr.Row) && (rCellAddr.Row <= maFormulaRef.EndRow);
         [ +  - ][ +  - ]
                 [ +  - ]
     109                 :            : }
     110                 :            : 
     111                 :            : // ----------------------------------------------------------------------------
     112                 :            : 
     113                 :         60 : DataTableModel::DataTableModel() :
     114                 :            :     mb2dTable( false ),
     115                 :            :     mbRowTable( false ),
     116                 :            :     mbRef1Deleted( false ),
     117                 :         60 :     mbRef2Deleted( false )
     118                 :            : {
     119                 :         60 : }
     120                 :            : 
     121                 :            : // ============================================================================
     122                 :            : 
     123                 :         60 : CellBlockBuffer::CellBlockBuffer( const WorksheetHelper& rHelper ) :
     124                 :            :     WorksheetHelper( rHelper ),
     125         [ +  - ]:         60 :     mnCurrRow( -1 )
     126                 :            : {
     127                 :         60 : }
     128                 :            : 
     129                 :        243 : void CellBlockBuffer::setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans )
     130                 :            : {
     131                 :            :     OSL_ENSURE( maColSpans.count( nRow ) == 0, "CellBlockBuffer::setColSpans - multiple column spans for the same row" );
     132                 :            :     OSL_ENSURE( (mnCurrRow < nRow) && (maColSpans.empty() || (maColSpans.rbegin()->first < nRow)), "CellBlockBuffer::setColSpans - rows are unsorted" );
     133 [ +  - ][ +  - ]:        243 :     if( (mnCurrRow < nRow) && (maColSpans.count( nRow ) == 0) )
                 [ +  - ]
     134                 :        243 :         maColSpans[ nRow ] = rColSpans.getRanges();
     135                 :        243 : }
     136                 :            : 
     137                 :         60 : void CellBlockBuffer::finalizeImport()
     138                 :            : {
     139                 :         60 : }
     140                 :            : 
     141                 :            : // ============================================================================
     142                 :            : 
     143                 :         60 : SheetDataBuffer::SheetDataBuffer( const WorksheetHelper& rHelper ) :
     144                 :            :     WorksheetHelper( rHelper ),
     145                 :            :     maCellBlocks( rHelper ),
     146 [ +  - ][ +  - ]:         60 :     mbPendingSharedFmla( false )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     147                 :            : {
     148                 :         60 : }
     149                 :            : 
     150                 :        243 : void SheetDataBuffer::setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans )
     151                 :            : {
     152                 :        243 :     maCellBlocks.setColSpans( nRow, rColSpans );
     153                 :        243 : }
     154                 :            : 
     155                 :          0 : void SheetDataBuffer::setBlankCell( const CellModel& rModel )
     156                 :            : {
     157                 :          0 :     setCellFormat( rModel );
     158                 :          0 : }
     159                 :            : 
     160                 :        195 : void SheetDataBuffer::setValueCell( const CellModel& rModel, double fValue )
     161                 :            : {
     162                 :        195 :     putValue( rModel.maCellAddr, fValue );
     163                 :        195 :     setCellFormat( rModel );
     164                 :        195 : }
     165                 :            : 
     166                 :        147 : void SheetDataBuffer::setStringCell( const CellModel& rModel, const OUString& rText )
     167                 :            : {
     168                 :        147 :     putString( rModel.maCellAddr, rText );
     169                 :        147 :     setCellFormat( rModel );
     170                 :        147 : }
     171                 :            : 
     172                 :        147 : void SheetDataBuffer::setStringCell( const CellModel& rModel, const RichStringRef& rxString )
     173                 :            : {
     174                 :            :     OSL_ENSURE( rxString.get(), "SheetDataBuffer::setStringCell - missing rich string object" );
     175 [ +  - ][ +  - ]:        147 :     const Font* pFirstPortionFont = getStyles().getFontFromCellXf( rModel.mnXfId ).get();
                 [ +  - ]
     176                 :        147 :     OUString aText;
     177 [ +  - ][ +  - ]:        147 :     if( rxString->extractPlainString( aText, pFirstPortionFont ) )
     178                 :            :     {
     179         [ +  - ]:        147 :         setStringCell( rModel, aText );
     180                 :            :     }
     181                 :            :     else
     182                 :            :     {
     183         [ #  # ]:          0 :         putRichString( rModel.maCellAddr, *rxString, pFirstPortionFont );
     184         [ #  # ]:          0 :         setCellFormat( rModel );
     185                 :        147 :     }
     186                 :        147 : }
     187                 :            : 
     188                 :        147 : void SheetDataBuffer::setStringCell( const CellModel& rModel, sal_Int32 nStringId )
     189                 :            : {
     190 [ +  - ][ +  - ]:        147 :     RichStringRef xString = getSharedStrings().getString( nStringId );
     191         [ +  - ]:        147 :     if( xString.get() )
     192         [ +  - ]:        147 :         setStringCell( rModel, xString );
     193                 :            :     else
     194 [ #  # ][ +  - ]:        147 :         setBlankCell( rModel );
     195                 :        147 : }
     196                 :            : 
     197                 :          0 : void SheetDataBuffer::setDateTimeCell( const CellModel& rModel, const ::com::sun::star::util::DateTime& rDateTime )
     198                 :            : {
     199                 :            :     // write serial date/time value into the cell
     200                 :          0 :     double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime );
     201                 :          0 :     setValueCell( rModel, fSerial );
     202                 :            :     // set appropriate number format
     203                 :            :     using namespace ::com::sun::star::util::NumberFormat;
     204 [ #  # ][ #  # ]:          0 :     sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE);
         [ #  # ][ #  # ]
     205                 :          0 :     setStandardNumFmt( rModel.maCellAddr, nStdFmt );
     206                 :          0 : }
     207                 :            : 
     208                 :          0 : void SheetDataBuffer::setBooleanCell( const CellModel& rModel, bool bValue )
     209                 :            : {
     210         [ #  # ]:          0 :     setCellFormula( rModel.maCellAddr, getFormulaParser().convertBoolToFormula( bValue ) );
     211                 :            :     // #108770# set 'Standard' number format for all Boolean cells
     212                 :          0 :     setCellFormat( rModel, 0 );
     213                 :          0 : }
     214                 :            : 
     215                 :          0 : void SheetDataBuffer::setErrorCell( const CellModel& rModel, const OUString& rErrorCode )
     216                 :            : {
     217                 :          0 :     setErrorCell( rModel, getUnitConverter().calcBiffErrorCode( rErrorCode ) );
     218                 :          0 : }
     219                 :            : 
     220                 :          0 : void SheetDataBuffer::setErrorCell( const CellModel& rModel, sal_uInt8 nErrorCode )
     221                 :            : {
     222         [ #  # ]:          0 :     setCellFormula( rModel.maCellAddr, getFormulaParser().convertErrorToFormula( nErrorCode ) );
     223                 :          0 :     setCellFormat( rModel );
     224                 :          0 : }
     225                 :            : 
     226                 :          0 : void SheetDataBuffer::setFormulaCell( const CellModel& rModel, const ApiTokenSequence& rTokens )
     227                 :            : {
     228                 :          0 :     mbPendingSharedFmla = false;
     229         [ #  # ]:          0 :     ApiTokenSequence aTokens;
     230                 :            : 
     231                 :            :     /*  Detect special token passed as placeholder for array formulas, shared
     232                 :            :         formulas, and table operations. In BIFF, these formulas are represented
     233                 :            :         by a single tExp resp. tTbl token. If the formula parser finds these
     234                 :            :         tokens, it puts a single OPCODE_BAD token with the base address and
     235                 :            :         formula type into the token sequence. This information will be
     236                 :            :         extracted here, and in case of a shared formula, the shared formula
     237                 :            :         buffer will generate the resulting formula token array. */
     238                 :          0 :     ApiSpecialTokenInfo aTokenInfo;
     239 [ #  # ][ #  # ]:          0 :     if( rTokens.hasElements() && getFormulaParser().extractSpecialTokenInfo( aTokenInfo, rTokens ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     240                 :            :     {
     241                 :            :         /*  The second member of the token info is set to true, if the formula
     242                 :            :             represents a table operation, which will be skipped. In BIFF12 it
     243                 :            :             is not possible to distinguish array and shared formulas
     244                 :            :             (BIFF5/BIFF8 provide this information with a special flag in the
     245                 :            :             FORMULA record). */
     246         [ #  # ]:          0 :         if( !aTokenInfo.Second )
     247                 :            :         {
     248                 :            :             /*  Construct the token array representing the shared formula. If
     249                 :            :                 the returned sequence is empty, the definition of the shared
     250                 :            :                 formula has not been loaded yet, or the cell is part of an
     251                 :            :                 array formula. In this case, the cell will be remembered. After
     252                 :            :                 reading the formula definition it will be retried to insert the
     253                 :            :                 formula via retryPendingSharedFormulaCell(). */
     254                 :          0 :             BinAddress aBaseAddr( aTokenInfo.First );
     255 [ #  # ][ #  # ]:          0 :             aTokens = resolveSharedFormula( aBaseAddr );
                 [ #  # ]
     256         [ #  # ]:          0 :             if( !aTokens.hasElements() )
     257                 :            :             {
     258                 :          0 :                 maSharedFmlaAddr = rModel.maCellAddr;
     259                 :          0 :                 maSharedBaseAddr = aBaseAddr;
     260                 :          0 :                 mbPendingSharedFmla = true;
     261                 :            :             }
     262                 :            :         }
     263                 :            :     }
     264                 :            :     else
     265                 :            :     {
     266                 :            :         // simple formula, use the passed token array
     267         [ #  # ]:          0 :         aTokens = rTokens;
     268                 :            :     }
     269                 :            : 
     270         [ #  # ]:          0 :     setCellFormula( rModel.maCellAddr, aTokens );
     271 [ #  # ][ #  # ]:          0 :     setCellFormat( rModel );
     272                 :          0 : }
     273                 :            : 
     274                 :          0 : void SheetDataBuffer::createArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens )
     275                 :            : {
     276                 :            :     /*  Array formulas will be inserted later in finalizeImport(). This is
     277                 :            :         needed to not disturb collecting all the cells, which will be put into
     278                 :            :         the sheet in large blocks to increase performance. */
     279         [ #  # ]:          0 :     maArrayFormulas.push_back( ArrayFormula( rRange, rTokens ) );
     280                 :          0 : }
     281                 :            : 
     282                 :          0 : void SheetDataBuffer::createTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel )
     283                 :            : {
     284                 :            :     /*  Table operations will be inserted later in finalizeImport(). This is
     285                 :            :         needed to not disturb collecting all the cells, which will be put into
     286                 :            :         the sheet in large blocks to increase performance. */
     287         [ #  # ]:          0 :     maTableOperations.push_back( TableOperation( rRange, rModel ) );
     288                 :          0 : }
     289                 :            : 
     290                 :          0 : void SheetDataBuffer::createSharedFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
     291                 :            : {
     292         [ #  # ]:          0 :     createSharedFormula( BinAddress( rCellAddr ), rTokens );
     293                 :          0 : }
     294                 :            : 
     295                 :        243 : void SheetDataBuffer::setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat )
     296                 :            : {
     297                 :            :     // set row formatting
     298         [ -  + ]:        243 :     if( bCustomFormat )
     299                 :            :     {
     300                 :            :         // try to expand cached row range, if formatting is equal
     301 [ #  # ][ #  # ]:          0 :         if( (maXfIdRowRange.maRowRange.mnLast < 0) || !maXfIdRowRange.tryExpand( nRow, nXfId ) )
                 [ #  # ]
     302                 :            :         {
     303                 :            : 
     304                 :          0 :             maXfIdRowRangeList[ maXfIdRowRange.mnXfId ].push_back( maXfIdRowRange.maRowRange );
     305                 :          0 :             maXfIdRowRange.set( nRow, nXfId );
     306                 :            :         }
     307                 :            :     }
     308         [ -  + ]:        243 :     else if( maXfIdRowRange.maRowRange.mnLast >= 0 )
     309                 :            :     {
     310                 :            :         // finish last cached row range
     311                 :          0 :         maXfIdRowRangeList[ maXfIdRowRange.mnXfId ].push_back( maXfIdRowRange.maRowRange );
     312                 :          0 :         maXfIdRowRange.set( -1, -1 );
     313                 :            :     }
     314                 :        243 : }
     315                 :            : 
     316                 :          3 : void SheetDataBuffer::setMergedRange( const CellRangeAddress& rRange )
     317                 :            : {
     318         [ +  - ]:          3 :     maMergedRanges.push_back( MergedRange( rRange ) );
     319                 :          3 : }
     320                 :            : 
     321                 :          0 : void SheetDataBuffer::setStandardNumFmt( const CellAddress& rCellAddr, sal_Int16 nStdNumFmt )
     322                 :            : {
     323                 :            :     try
     324                 :            :     {
     325 [ #  # ][ #  # ]:          0 :         Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY_THROW );
     326 [ #  # ][ #  # ]:          0 :         Reference< XNumberFormatTypes > xNumFmtTypes( xNumFmtsSupp->getNumberFormats(), UNO_QUERY_THROW );
                 [ #  # ]
     327 [ #  # ][ #  # ]:          0 :         sal_Int32 nIndex = xNumFmtTypes->getStandardFormat( nStdNumFmt, Locale() );
     328 [ #  # ][ #  # ]:          0 :         PropertySet aPropSet( getCell( rCellAddr ) );
     329 [ #  # ][ #  # ]:          0 :         aPropSet.setProperty( PROP_NumberFormat, nIndex );
                 [ #  # ]
     330                 :            :     }
     331                 :          0 :     catch( Exception& )
     332                 :            :     {
     333                 :            :     }
     334                 :          0 : }
     335                 :            : 
     336                 :         93 : void addIfNotInMyMap( StylesBuffer& rStyles, std::map< std::pair< sal_Int32, sal_Int32 >, ApiCellRangeList >& rMap, sal_Int32 nXfId, sal_Int32 nFormatId, const ApiCellRangeList& rRangeList )
     337                 :            : {
     338                 :         93 :     Xf* pXf1 = rStyles.getCellXf( nXfId ).get();
     339         [ +  - ]:         93 :     if ( pXf1 )
     340                 :            :     {
     341         [ +  + ]:        405 :         for ( std::map< std::pair< sal_Int32, sal_Int32 >, ApiCellRangeList >::iterator it = rMap.begin(), it_end = rMap.end(); it != it_end; ++it )
     342                 :            :         {
     343         [ +  - ]:        312 :             if ( it->first.second == nFormatId )
     344                 :            :             {
     345 [ +  - ][ +  - ]:        312 :                 Xf* pXf2 = rStyles.getCellXf( it->first.first ).get();
     346 [ +  - ][ -  + ]:        312 :                 if ( *pXf1 == *pXf2 ) // already exists
     347                 :            :                 {
     348                 :            :                     // add ranges from the rangelist to the existing rangelist for the
     349                 :            :                     // matching style ( should we check if they overlap ? )
     350 [ #  # ][ #  # ]:          0 :                     for ( ApiCellRangeList::const_iterator iter = rRangeList.begin(), iter_end =  rRangeList.end(); iter != iter_end; ++iter )
     351         [ #  # ]:          0 :                        it->second.push_back( *iter );
     352                 :         93 :                     return;
     353                 :            :                 }
     354                 :            :             }
     355                 :            :         }
     356 [ +  - ][ +  - ]:         93 :         rMap[ std::pair<sal_Int32, sal_Int32>( nXfId, nFormatId ) ] = rRangeList;
     357                 :            :     }
     358                 :            : }
     359                 :            : 
     360                 :         60 : void SheetDataBuffer::finalizeImport()
     361                 :            : {
     362                 :            :     // insert all cells of all open cell blocks
     363                 :         60 :     maCellBlocks.finalizeImport();
     364                 :            : 
     365                 :            :     // create all array formulas
     366         [ -  + ]:         60 :     for( ArrayFormulaList::iterator aIt = maArrayFormulas.begin(), aEnd = maArrayFormulas.end(); aIt != aEnd; ++aIt )
     367         [ #  # ]:          0 :         finalizeArrayFormula( aIt->first, aIt->second );
     368                 :            : 
     369                 :            :     // create all table operations
     370         [ -  + ]:         60 :     for( TableOperationList::iterator aIt = maTableOperations.begin(), aEnd = maTableOperations.end(); aIt != aEnd; ++aIt )
     371         [ #  # ]:          0 :         finalizeTableOperation( aIt->first, aIt->second );
     372                 :            : 
     373                 :            :     // write default formatting of remaining row range
     374 [ +  - ][ +  - ]:         60 :     maXfIdRowRangeList[ maXfIdRowRange.mnXfId ].push_back( maXfIdRowRange.maRowRange );
     375         [ +  + ]:        120 :     for ( std::map< sal_Int32, std::vector< ValueRange > >::iterator it = maXfIdRowRangeList.begin(), it_end =  maXfIdRowRangeList.end(); it != it_end; ++it )
     376                 :            :     {
     377         [ +  - ]:         60 :         ApiCellRangeList rangeList;
     378         [ +  - ]:         60 :         AddressConverter& rAddrConv = getAddressConverter();
     379                 :            :         // get all row ranges for id
     380 [ +  - ][ +  + ]:        120 :         for ( std::vector< ValueRange >::iterator rangeIter = it->second.begin(), rangeIter_end = it->second.end(); rangeIter != rangeIter_end; ++rangeIter )
     381                 :            :         {
     382         [ +  - ]:         60 :             CellRangeAddress aRange( getSheetIndex(), 0, rangeIter->mnFirst, rAddrConv.getMaxApiAddress().Column, rangeIter->mnLast );
     383         [ +  - ]:         60 :             rangeList.push_back( aRange );
     384                 :            :         }
     385         [ +  - ]:         60 :         ScRangeList aList;
     386 [ +  - ][ +  - ]:        120 :         for ( ApiCellRangeList::const_iterator itRange = rangeList.begin(), itRange_end = rangeList.end(); itRange!=itRange_end; ++itRange )
         [ +  - ][ +  + ]
     387                 :            :         {
     388         [ +  - ]:         60 :             ScRange* pRange = new ScRange();
     389                 :         60 :             ScUnoConversion::FillScRange( *pRange, *itRange );
     390         [ +  - ]:         60 :             aList.push_back( pRange );
     391                 :            :         }
     392         [ +  - ]:         60 :         ScMarkData aMark;
     393         [ +  - ]:         60 :         aMark.MarkFromRangeList( aList, false );
     394                 :            : 
     395 [ +  - ][ +  - ]:         60 :         getStyles().writeCellXfToMarkData( aMark, it->first, -1 );
     396 [ +  - ][ +  - ]:         60 :     }
     397         [ +  - ]:         60 :     std::map< std::pair< sal_Int32, sal_Int32 >, ApiCellRangeList > rangeStyleListMap;
     398                 :            :     // gather all ranges that have the same style and apply them in bulk
     399         [ +  + ]:        153 :     for( XfIdRangeListMap::const_iterator aIt = maXfIdRangeLists.begin(), aEnd = maXfIdRangeLists.end(); aIt != aEnd; ++aIt )
     400 [ +  - ][ +  - ]:         93 :         addIfNotInMyMap( getStyles(), rangeStyleListMap, aIt->first.first, aIt->first.second, aIt->second );
     401         [ +  + ]:        153 :     for (  std::map< std::pair< sal_Int32, sal_Int32 >, ApiCellRangeList >::iterator it = rangeStyleListMap.begin(), it_end = rangeStyleListMap.end(); it != it_end; ++it )
     402         [ +  - ]:         93 :         writeXfIdRangeListProperties( it->first.first, it->first.second, it->second );
     403                 :            :     // merge all cached merged ranges and update right/bottom cell borders
     404         [ +  + ]:         63 :     for( MergedRangeList::iterator aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt )
     405         [ +  - ]:          3 :         applyCellMerging( aIt->maRange );
     406         [ -  + ]:         60 :     for( MergedRangeList::iterator aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt )
     407         [ #  # ]:         60 :         applyCellMerging( aIt->maRange );
     408                 :         60 : }
     409                 :            : 
     410                 :            : // private --------------------------------------------------------------------
     411                 :            : 
     412                 :         60 : SheetDataBuffer::XfIdRowRange::XfIdRowRange() :
     413                 :            :     maRowRange( -1 ),
     414                 :         60 :     mnXfId( -1 )
     415                 :            : {
     416                 :         60 : }
     417                 :            : 
     418                 :          0 : void SheetDataBuffer::XfIdRowRange::set( sal_Int32 nRow, sal_Int32 nXfId )
     419                 :            : {
     420                 :          0 :     maRowRange = ValueRange( nRow );
     421                 :          0 :     mnXfId = nXfId;
     422                 :          0 : }
     423                 :            : 
     424                 :          0 : bool SheetDataBuffer::XfIdRowRange::tryExpand( sal_Int32 nRow, sal_Int32 nXfId )
     425                 :            : {
     426         [ #  # ]:          0 :     if( mnXfId == nXfId )
     427                 :            :     {
     428         [ #  # ]:          0 :         if( maRowRange.mnLast + 1 == nRow )
     429                 :            :         {
     430                 :          0 :             ++maRowRange.mnLast;
     431                 :          0 :             return true;
     432                 :            :         }
     433         [ #  # ]:          0 :         if( maRowRange.mnFirst == nRow + 1 )
     434                 :            :         {
     435                 :          0 :             --maRowRange.mnFirst;
     436                 :          0 :             return true;
     437                 :            :         }
     438                 :            :     }
     439                 :          0 :     return false;
     440                 :            : }
     441                 :            : 
     442                 :            : 
     443                 :          3 : SheetDataBuffer::MergedRange::MergedRange( const CellRangeAddress& rRange ) :
     444                 :            :     maRange( rRange ),
     445                 :          3 :     mnHorAlign( XML_TOKEN_INVALID )
     446                 :            : {
     447                 :          3 : }
     448                 :            : 
     449                 :          0 : SheetDataBuffer::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) :
     450                 :            :     maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ),
     451                 :          0 :     mnHorAlign( nHorAlign )
     452                 :            : {
     453                 :          0 : }
     454                 :            : 
     455                 :          0 : bool SheetDataBuffer::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign )
     456                 :            : {
     457 [ #  # ][ #  # ]:          0 :     if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) &&
         [ #  # ][ #  # ]
     458                 :            :         (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) )
     459                 :            :     {
     460                 :          0 :         ++maRange.EndColumn;
     461                 :          0 :         return true;
     462                 :            :     }
     463                 :          0 :     return false;
     464                 :            : }
     465                 :            : 
     466                 :            : // ----------------------------------------------------------------------------
     467                 :            : 
     468                 :          0 : void SheetDataBuffer::setCellFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens )
     469                 :            : {
     470         [ #  # ]:          0 :     if( rTokens.hasElements() )
     471                 :            :     {
     472                 :          0 :         putFormulaTokens( rCellAddr, rTokens );
     473                 :            :     }
     474                 :          0 : }
     475                 :            : 
     476                 :          0 : void SheetDataBuffer::createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens )
     477                 :            : {
     478                 :            :     // create the defined name that will represent the shared formula
     479         [ #  # ]:          0 :     OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
     480 [ #  # ][ #  # ]:          0 :         append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ).
     481 [ #  # ][ #  # ]:          0 :         append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ).
     482 [ #  # ][ #  # ]:          0 :         append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear();
                 [ #  # ]
     483         [ #  # ]:          0 :     ScRangeData* pScRangeData = createNamedRangeObject( aName, rTokens, 0 );
     484                 :          0 :     pScRangeData->SetType(RT_SHARED);
     485                 :            : 
     486                 :            :     // get and store the token index of the defined name
     487                 :            :     OSL_ENSURE( maSharedFormulas.count( rMapKey ) == 0, "SheetDataBuffer::createSharedFormula - shared formula exists already" );
     488                 :          0 :     sal_Int32 nTokenIndex = static_cast< sal_Int32 >( pScRangeData->GetIndex() );
     489         [ #  # ]:          0 :     if( nTokenIndex >= 0 ) try
     490                 :            :     {
     491                 :            :         // store the token index in the map
     492         [ #  # ]:          0 :         maSharedFormulas[ rMapKey ] = nTokenIndex;
     493                 :            :         // retry to insert a pending shared formula cell
     494         [ #  # ]:          0 :         if( mbPendingSharedFmla )
     495 [ #  # ][ #  # ]:          0 :             setCellFormula( maSharedFmlaAddr, resolveSharedFormula( maSharedBaseAddr ) );
         [ #  # ][ #  # ]
     496                 :            :     }
     497         [ #  # ]:          0 :     catch( Exception& )
     498                 :            :     {
     499                 :            :     }
     500                 :          0 :     mbPendingSharedFmla = false;
     501                 :          0 : }
     502                 :            : 
     503                 :          0 : ApiTokenSequence SheetDataBuffer::resolveSharedFormula( const BinAddress& rMapKey ) const
     504                 :            : {
     505         [ #  # ]:          0 :     sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maSharedFormulas, rMapKey, -1 );
     506         [ #  # ]:          0 :     return (nTokenIndex >= 0) ? getFormulaParser().convertNameToFormula( nTokenIndex ) : ApiTokenSequence();
     507                 :            : }
     508                 :            : 
     509                 :          0 : void SheetDataBuffer::finalizeArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens ) const
     510                 :            : {
     511 [ #  # ][ #  # ]:          0 :     Reference< XArrayFormulaTokens > xTokens( getCellRange( rRange ), UNO_QUERY );
     512                 :            :     OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" );
     513         [ #  # ]:          0 :     if( xTokens.is() )
     514 [ #  # ][ #  # ]:          0 :         xTokens->setArrayTokens( rTokens );
     515                 :          0 : }
     516                 :            : 
     517                 :          0 : void SheetDataBuffer::finalizeTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const
     518                 :            : {
     519         [ #  # ]:          0 :     sal_Int16 nSheet = getSheetIndex();
     520                 :          0 :     bool bOk = false;
     521 [ #  # ][ #  # ]:          0 :     if( !rModel.mbRef1Deleted && !rModel.maRef1.isEmpty() && (rRange.StartColumn > 0) && (rRange.StartRow > 0) )
         [ #  # ][ #  # ]
                 [ #  # ]
     522                 :            :     {
     523                 :          0 :         CellRangeAddress aOpRange = rRange;
     524                 :          0 :         CellAddress aRef1;
     525 [ #  # ][ #  # ]:          0 :         if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, nSheet, true ) ) try
                 [ #  # ]
     526                 :            :         {
     527         [ #  # ]:          0 :             if( rModel.mb2dTable )
     528                 :            :             {
     529                 :          0 :                 CellAddress aRef2;
     530 [ #  # ][ #  # ]:          0 :                 if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, nSheet, true ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     531                 :            :                 {
     532                 :            :                     // API call expects input values inside operation range
     533                 :          0 :                     --aOpRange.StartColumn;
     534                 :          0 :                     --aOpRange.StartRow;
     535                 :            :                     // formula range is top-left cell of operation range
     536                 :          0 :                     CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow );
     537                 :            :                     // set multiple operation
     538 [ #  # ][ #  # ]:          0 :                     Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
     539 [ #  # ][ #  # ]:          0 :                     xMultOp->setTableOperation( aFormulaRange, TableOperationMode_BOTH, aRef2, aRef1 );
     540                 :          0 :                     bOk = true;
     541                 :            :                 }
     542                 :            :             }
     543         [ #  # ]:          0 :             else if( rModel.mbRowTable )
     544                 :            :             {
     545                 :            :                 // formula range is column to the left of operation range
     546                 :          0 :                 CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow );
     547                 :            :                 // API call expects input values (top row) inside operation range
     548                 :          0 :                 --aOpRange.StartRow;
     549                 :            :                 // set multiple operation
     550 [ #  # ][ #  # ]:          0 :                 Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
     551 [ #  # ][ #  # ]:          0 :                 xMultOp->setTableOperation( aFormulaRange, TableOperationMode_ROW, aRef1, aRef1 );
     552                 :          0 :                 bOk = true;
     553                 :            :             }
     554                 :            :             else
     555                 :            :             {
     556                 :            :                 // formula range is row above operation range
     557                 :          0 :                 CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 );
     558                 :            :                 // API call expects input values (left column) inside operation range
     559                 :          0 :                 --aOpRange.StartColumn;
     560                 :            :                 // set multiple operation
     561 [ #  # ][ #  # ]:          0 :                 Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW );
     562 [ #  # ][ #  # ]:          0 :                 xMultOp->setTableOperation( aFormulaRange, TableOperationMode_COLUMN, aRef1, aRef1 );
     563         [ #  # ]:          0 :                 bOk = true;
     564                 :            :             }
     565                 :            :         }
     566         [ #  # ]:          0 :         catch( Exception& )
     567                 :            :         {
     568                 :            :         }
     569                 :            :     }
     570                 :            : 
     571                 :            :     // on error: fill cell range with #REF! error codes
     572         [ #  # ]:          0 :     if( !bOk ) try
     573                 :            :     {
     574 [ #  # ][ #  # ]:          0 :         Reference< XCellRangeData > xCellRangeData( getCellRange( rRange ), UNO_QUERY_THROW );
     575                 :          0 :         size_t nWidth = static_cast< size_t >( rRange.EndColumn - rRange.StartColumn + 1 );
     576                 :          0 :         size_t nHeight = static_cast< size_t >( rRange.EndRow - rRange.StartRow + 1 );
     577 [ #  # ][ #  # ]:          0 :         Matrix< Any > aErrorCells( nWidth, nHeight, Any( getFormulaParser().convertErrorToFormula( BIFF_ERR_REF ) ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     578 [ #  # ][ #  # ]:          0 :         xCellRangeData->setDataArray( ContainerHelper::matrixToSequenceSequence( aErrorCells ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     579                 :            :     }
     580         [ #  # ]:          0 :     catch( Exception& )
     581                 :            :     {
     582                 :            :     }
     583                 :          0 : }
     584                 :            : 
     585                 :        444 : void SheetDataBuffer::setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId )
     586                 :            : {
     587 [ +  + ][ -  + ]:        444 :     if( (rModel.mnXfId >= 0) || (nNumFmtId >= 0) )
     588                 :            :     {
     589 [ +  - ][ +  - ]:        411 :         ApiCellRangeList::reverse_iterator aIt = maXfIdRangeLists[ XfIdNumFmtKey( rModel.mnXfId, nNumFmtId ) ].rbegin();
     590 [ +  - ][ +  - ]:        411 :         ApiCellRangeList::reverse_iterator aItEnd = maXfIdRangeLists[ XfIdNumFmtKey( rModel.mnXfId, nNumFmtId ) ].rend();
     591                 :            :         /* The xlsx sheet data contains row wise information.
     592                 :            :          * It is sufficient to check if the row range size is one
     593                 :            :          */
     594 [ +  + ][ +  - ]:       1527 :         if(     aIt                 != aItEnd &&
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  - ]
     595         [ +  - ]:        318 :                 aIt->Sheet          == rModel.maCellAddr.Sheet &&
     596 [ +  - ][ +  - ]:        318 :                 aIt->StartRow       == aIt->EndRow &&
     597         [ +  - ]:        270 :                 aIt->StartRow       == rModel.maCellAddr.Row &&
     598         [ +  - ]:        210 :                 (aIt->EndColumn+1)  == rModel.maCellAddr.Column )
     599                 :            :         {
     600         [ +  - ]:        195 :             aIt->EndColumn++;       // Expand Column
     601                 :            :         }
     602                 :            :         else
     603                 :            :         {
     604 [ +  - ][ +  - ]:        216 :             maXfIdRangeLists[ XfIdNumFmtKey (rModel.mnXfId, nNumFmtId ) ].push_back(
     605                 :            :                               CellRangeAddress( rModel.maCellAddr.Sheet, rModel.maCellAddr.Column, rModel.maCellAddr.Row,
     606         [ +  - ]:        432 :                               rModel.maCellAddr.Column, rModel.maCellAddr.Row ) );
     607                 :            :         }
     608                 :            : 
     609 [ +  - ][ +  - ]:        411 :         aIt = maXfIdRangeLists[ XfIdNumFmtKey( rModel.mnXfId, nNumFmtId ) ].rbegin();
     610 [ +  - ][ +  - ]:        411 :         aItEnd = maXfIdRangeLists[ XfIdNumFmtKey( rModel.mnXfId, nNumFmtId ) ].rend();
     611         [ +  - ]:        411 :         ApiCellRangeList::reverse_iterator aItM = aIt+1;
     612 [ +  - ][ +  + ]:        594 :         while( aItM != aItEnd )
     613                 :            :         {
     614 [ +  - ][ +  - ]:        327 :             if( aIt->Sheet == aItM->Sheet )
                 [ +  - ]
     615                 :            :             {
     616                 :            :                 /* Try to merge this with the previous range */
     617 [ +  - ][ +  - ]:        750 :                 if( aIt->StartRow == (aItM->EndRow + 1) &&
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     618 [ +  - ][ +  - ]:        228 :                         aIt->StartColumn == aItM->StartColumn &&
     619 [ +  - ][ +  - ]:        195 :                         aIt->EndColumn == aItM->EndColumn)
     620                 :            :                 {
     621 [ +  - ][ +  - ]:         69 :                     aItM->EndRow = aIt->EndRow;
     622 [ +  - ][ +  - ]:         69 :                     maXfIdRangeLists[ XfIdNumFmtKey( rModel.mnXfId, nNumFmtId ) ].pop_back();
                 [ +  - ]
     623                 :         69 :                     break;
     624                 :            :                 }
     625 [ +  - ][ +  - ]:        258 :                 else if( aIt->StartRow > aItM->EndRow + 1 )
                 [ +  + ]
     626                 :         75 :                     break; // Un-necessary to check with any other rows
     627                 :            :             }
     628                 :            :             else
     629                 :          0 :                 break;
     630         [ +  - ]:        183 :             ++aItM;
     631                 :            :         }
     632                 :            : 
     633                 :            :         // update merged ranges for 'center across selection' and 'fill'
     634 [ +  - ][ +  - ]:        411 :         if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() )
         [ +  - ][ +  - ]
     635                 :            :         {
     636                 :        411 :             sal_Int32 nHorAlign = pXf->getAlignment().getModel().mnHorAlign;
     637 [ -  + ][ +  - ]:        411 :             if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) )
     638                 :            :             {
     639                 :            :                 /*  start new merged range, if cell is not empty (#108781#),
     640                 :            :                     or try to expand last range with empty cell */
     641         [ #  # ]:          0 :                 if( rModel.mnCellType != XML_TOKEN_INVALID )
     642         [ #  # ]:          0 :                     maCenterFillRanges.push_back( MergedRange( rModel.maCellAddr, nHorAlign ) );
     643         [ #  # ]:          0 :                 else if( !maCenterFillRanges.empty() )
     644         [ #  # ]:        411 :                     maCenterFillRanges.rbegin()->tryExpand( rModel.maCellAddr, nHorAlign );
     645                 :            :             }
     646                 :            :         }
     647                 :            :     }
     648                 :        444 : }
     649                 :            : 
     650                 :         93 : void SheetDataBuffer::writeXfIdRangeListProperties( sal_Int32 nXfId, sal_Int32 nNumFmtId, const ApiCellRangeList& rRanges ) const
     651                 :            : {
     652         [ +  - ]:         93 :     StylesBuffer& rStyles = getStyles();
     653         [ +  - ]:         93 :     ScRangeList aList;
     654 [ +  - ][ +  + ]:        240 :     for ( ApiCellRangeList::const_iterator it = rRanges.begin(), it_end = rRanges.end(); it!=it_end; ++it )
     655                 :            :     {
     656         [ +  - ]:        147 :         ScRange* pRange = new ScRange();
     657                 :        147 :         ScUnoConversion::FillScRange( *pRange, *it );
     658         [ +  - ]:        147 :         aList.push_back( pRange );
     659                 :            :     }
     660         [ +  - ]:         93 :     ScMarkData aMark;
     661         [ +  - ]:         93 :     aMark.MarkFromRangeList( aList, false );
     662 [ +  - ][ +  - ]:         93 :     rStyles.writeCellXfToMarkData( aMark, nXfId, nNumFmtId );
                 [ +  - ]
     663                 :         93 : }
     664                 :            : 
     665                 :          6 : void lcl_SetBorderLine( ScDocument& rDoc, ScRange& rRange, SCTAB nScTab, sal_uInt16 nLine )
     666                 :            : {
     667         [ +  + ]:          6 :     SCCOL nFromScCol = (nLine == BOX_LINE_RIGHT) ? rRange.aEnd.Col() : rRange.aStart.Col();
     668         [ +  + ]:          6 :     SCROW nFromScRow = (nLine == BOX_LINE_BOTTOM) ? rRange.aEnd.Row() : rRange.aStart.Row();
     669                 :            : 
     670                 :            :     const SvxBoxItem* pFromItem = static_cast< const SvxBoxItem* >(
     671         [ +  - ]:          6 :         rDoc.GetAttr( nFromScCol, nFromScRow, nScTab, ATTR_BORDER ) );
     672                 :            :     const SvxBoxItem* pToItem = static_cast< const SvxBoxItem* >(
     673         [ +  - ]:          6 :         rDoc.GetAttr( rRange.aStart.Col(), rRange.aStart.Row(), nScTab, ATTR_BORDER ) );
     674                 :            : 
     675         [ +  - ]:          6 :     SvxBoxItem aNewItem( *pToItem );
     676 [ +  - ][ +  - ]:          6 :     aNewItem.SetLine( pFromItem->GetLine( nLine ), nLine );
     677 [ +  - ][ +  - ]:          6 :     rDoc.ApplyAttr( rRange.aStart.Col(), rRange.aStart.Row(), nScTab, aNewItem );
     678                 :          6 : }
     679                 :            : 
     680                 :          3 : void SheetDataBuffer::applyCellMerging( const CellRangeAddress& rRange )
     681                 :            : {
     682                 :          3 :     bool bMultiCol = rRange.StartColumn < rRange.EndColumn;
     683                 :          3 :     bool bMultiRow = rRange.StartRow < rRange.EndRow;
     684                 :            : 
     685                 :          3 :     ScRange aRange;
     686                 :          3 :     ScUnoConversion::FillScRange( aRange, rRange );
     687                 :          3 :     const ScAddress& rStart = aRange.aStart;
     688                 :          3 :     const ScAddress& rEnd = aRange.aEnd;
     689         [ +  - ]:          3 :     ScDocument& rDoc = getScDocument();
     690                 :            :     // set correct right border
     691         [ +  - ]:          3 :     if( bMultiCol )
     692 [ +  - ][ +  - ]:          3 :         lcl_SetBorderLine( rDoc, aRange, getSheetIndex(), BOX_LINE_RIGHT );
     693                 :            :         // set correct lower border
     694         [ +  - ]:          3 :     if( bMultiRow )
     695 [ +  - ][ +  - ]:          3 :         lcl_SetBorderLine( rDoc, aRange, getSheetIndex(), BOX_LINE_BOTTOM );
     696                 :            :     // do merge
     697 [ -  + ][ #  # ]:          3 :     if( bMultiCol || bMultiRow )
     698 [ +  - ][ +  - ]:          3 :         rDoc.DoMerge( getSheetIndex(), rStart.Col(), rStart.Row(), rEnd.Col(), rEnd.Row() );
     699                 :            :     // #i93609# merged range in a single row: test if manual row height is needed
     700         [ -  + ]:          3 :     if( !bMultiRow )
     701                 :            :     {
     702         [ #  # ]:          0 :         bool bTextWrap = static_cast< const SfxBoolItem* >( rDoc.GetAttr( rStart.Col(), rStart.Row(), rStart.Tab(), ATTR_LINEBREAK ) )->GetValue();
     703 [ #  # ][ #  # ]:          0 :         if( !bTextWrap && (rDoc.GetCellType( rStart ) == CELLTYPE_EDIT) )
         [ #  # ][ #  # ]
     704                 :            :         {
     705 [ #  # ][ #  # ]:          0 :             if( const EditTextObject* pEditObj = static_cast< const ScEditCell* >( rDoc.GetCell( rStart ) )->GetData() )
     706         [ #  # ]:          0 :                 bTextWrap = pEditObj->GetParagraphCount() > 1;
     707                 :            :         }
     708                 :            :     }
     709                 :          3 : }
     710                 :            : 
     711                 :            : } // namespace xls
     712 [ +  - ][ +  - ]:         24 : } // namespace oox
     713                 :            : 
     714                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10