LCOV - code coverage report
Current view: top level - sc/source/ui/vba - vbarange.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1941 2944 65.9 %
Date: 2014-11-03 Functions: 226 297 76.1 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include "vbarange.hxx"
      21             : 
      22             : #include <vbahelper/helperdecl.hxx>
      23             : 
      24             : #include <comphelper/unwrapargs.hxx>
      25             : #include <comphelper/processfactory.hxx>
      26             : #include <sfx2/objsh.hxx>
      27             : 
      28             : #include <com/sun/star/script/ArrayWrapper.hpp>
      29             : #include <com/sun/star/script/vba/VBAEventId.hpp>
      30             : #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
      31             : #include <com/sun/star/sheet/XDatabaseRange.hpp>
      32             : #include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp>
      33             : #include <com/sun/star/sheet/XGoalSeek.hpp>
      34             : #include <com/sun/star/sheet/XSheetOperation.hpp>
      35             : #include <com/sun/star/sheet/CellFlags.hpp>
      36             : #include <com/sun/star/table/XColumnRowRange.hpp>
      37             : #include <com/sun/star/sheet/XCellAddressable.hpp>
      38             : #include <com/sun/star/table/CellContentType.hpp>
      39             : #include <com/sun/star/sheet/XCellSeries.hpp>
      40             : #include <com/sun/star/text/XTextRange.hpp>
      41             : #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
      42             : #include <com/sun/star/table/CellAddress.hpp>
      43             : #include <com/sun/star/table/CellRangeAddress.hpp>
      44             : #include <com/sun/star/sheet/XSpreadsheetView.hpp>
      45             : #include <com/sun/star/sheet/XCellRangeReferrer.hpp>
      46             : #include <com/sun/star/sheet/XSheetCellRange.hpp>
      47             : #include <com/sun/star/sheet/XSpreadsheet.hpp>
      48             : #include <com/sun/star/sheet/XSheetCellCursor.hpp>
      49             : #include <com/sun/star/sheet/XArrayFormulaRange.hpp>
      50             : #include <com/sun/star/sheet/XNamedRange.hpp>
      51             : #include <com/sun/star/sheet/XPrintAreas.hpp>
      52             : #include <com/sun/star/sheet/XCellRangesQuery.hpp>
      53             : #include <com/sun/star/beans/XPropertySet.hpp>
      54             : #include <com/sun/star/sheet/XFunctionAccess.hpp>
      55             : #include <com/sun/star/frame/XModel.hpp>
      56             : #include <com/sun/star/view/XSelectionSupplier.hpp>
      57             : #include <com/sun/star/table/XCellCursor.hpp>
      58             : #include <com/sun/star/table/XTableRows.hpp>
      59             : #include <com/sun/star/table/XTableColumns.hpp>
      60             : #include <com/sun/star/table/TableSortField.hpp>
      61             : #include <com/sun/star/util/XMergeable.hpp>
      62             : #include <com/sun/star/uno/XComponentContext.hpp>
      63             : #include <com/sun/star/lang/XMultiComponentFactory.hpp>
      64             : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
      65             : #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
      66             : #include <com/sun/star/util/XNumberFormats.hpp>
      67             : #include <com/sun/star/util/NumberFormat.hpp>
      68             : #include <com/sun/star/util/XNumberFormatTypes.hpp>
      69             : #include <com/sun/star/util/XReplaceable.hpp>
      70             : #include <com/sun/star/util/XSortable.hpp>
      71             : #include <com/sun/star/sheet/XCellRangeMovement.hpp>
      72             : #include <com/sun/star/sheet/XCellRangeData.hpp>
      73             : #include <com/sun/star/sheet/FormulaResult.hpp>
      74             : #include <com/sun/star/sheet/FilterOperator2.hpp>
      75             : #include <com/sun/star/sheet/TableFilterField.hpp>
      76             : #include <com/sun/star/sheet/TableFilterField2.hpp>
      77             : #include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp>
      78             : #include <com/sun/star/sheet/XSheetFilterable.hpp>
      79             : #include <com/sun/star/sheet/FilterConnection.hpp>
      80             : #include <com/sun/star/util/CellProtection.hpp>
      81             : #include <com/sun/star/util/TriState.hpp>
      82             : 
      83             : #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
      84             : #include <com/sun/star/awt/XDevice.hpp>
      85             : 
      86             : #include <com/sun/star/sheet/XSubTotalCalculatable.hpp>
      87             : #include <com/sun/star/sheet/XSubTotalDescriptor.hpp>
      88             : #include <com/sun/star/sheet/GeneralFunction.hpp>
      89             : 
      90             : #include <com/sun/star/sheet/XSheetAnnotationsSupplier.hpp>
      91             : #include <com/sun/star/sheet/XSheetAnnotations.hpp>
      92             : 
      93             : #include <ooo/vba/excel/XlPasteSpecialOperation.hpp>
      94             : #include <ooo/vba/excel/XlPasteType.hpp>
      95             : #include <ooo/vba/excel/Constants.hpp>
      96             : #include <ooo/vba/excel/XlFindLookIn.hpp>
      97             : #include <ooo/vba/excel/XlLookAt.hpp>
      98             : #include <ooo/vba/excel/XlSearchOrder.hpp>
      99             : #include <ooo/vba/excel/XlSortOrder.hpp>
     100             : #include <ooo/vba/excel/XlYesNoGuess.hpp>
     101             : #include <ooo/vba/excel/XlSortOrientation.hpp>
     102             : #include <ooo/vba/excel/XlSortMethod.hpp>
     103             : #include <ooo/vba/excel/XlDirection.hpp>
     104             : #include <ooo/vba/excel/XlSortDataOption.hpp>
     105             : #include <ooo/vba/excel/XlDeleteShiftDirection.hpp>
     106             : #include <ooo/vba/excel/XlInsertShiftDirection.hpp>
     107             : #include <ooo/vba/excel/XlReferenceStyle.hpp>
     108             : #include <ooo/vba/excel/XlBordersIndex.hpp>
     109             : #include <ooo/vba/excel/XlPageBreak.hpp>
     110             : #include <ooo/vba/excel/XlAutoFilterOperator.hpp>
     111             : #include <ooo/vba/excel/XlAutoFillType.hpp>
     112             : #include <ooo/vba/excel/XlTextParsingType.hpp>
     113             : #include <ooo/vba/excel/XlTextQualifier.hpp>
     114             : #include <ooo/vba/excel/XlCellType.hpp>
     115             : #include <ooo/vba/excel/XlSpecialCellsValue.hpp>
     116             : #include <ooo/vba/excel/XlConsolidationFunction.hpp>
     117             : #include <ooo/vba/excel/XlSearchDirection.hpp>
     118             : 
     119             : #include <scitems.hxx>
     120             : #include <svl/srchitem.hxx>
     121             : #include <cellsuno.hxx>
     122             : #include <dbdata.hxx>
     123             : #include "docfunc.hxx"
     124             : #include <docuno.hxx>
     125             : 
     126             : #include <sfx2/dispatch.hxx>
     127             : #include <sfx2/app.hxx>
     128             : #include <sfx2/bindings.hxx>
     129             : #include <sfx2/request.hxx>
     130             : #include <sfx2/viewfrm.hxx>
     131             : #include <sfx2/itemwrapper.hxx>
     132             : #include <sc.hrc>
     133             : #include <globstr.hrc>
     134             : #include <unonames.hxx>
     135             : 
     136             : #include "vbaapplication.hxx"
     137             : #include "vbafont.hxx"
     138             : #include "vbacomment.hxx"
     139             : #include "vbainterior.hxx"
     140             : #include "vbacharacters.hxx"
     141             : #include "vbaborders.hxx"
     142             : #include "vbaworksheet.hxx"
     143             : #include "vbavalidation.hxx"
     144             : #include "vbahyperlinks.hxx"
     145             : 
     146             : #include "tabvwsh.hxx"
     147             : #include "rangelst.hxx"
     148             : #include "convuno.hxx"
     149             : #include "compiler.hxx"
     150             : #include "attrib.hxx"
     151             : #include "undodat.hxx"
     152             : #include "dbdocfun.hxx"
     153             : #include "patattr.hxx"
     154             : #include "olinetab.hxx"
     155             : #include "transobj.hxx"
     156             : #include "queryentry.hxx"
     157             : #include "markdata.hxx"
     158             : #include <comphelper/anytostring.hxx>
     159             : 
     160             : #include <global.hxx>
     161             : 
     162             : #include "vbaglobals.hxx"
     163             : #include "vbastyle.hxx"
     164             : #include "vbaname.hxx"
     165             : #include <vector>
     166             : #include <vbahelper/vbacollectionimpl.hxx>
     167             : // begin test includes
     168             : #include <com/sun/star/sheet/FunctionArgument.hpp>
     169             : // end test includes
     170             : 
     171             : #include <ooo/vba/excel/Range.hpp>
     172             : #include <com/sun/star/bridge/oleautomation/Date.hpp>
     173             : #include "tokenarray.hxx"
     174             : #include "tokenuno.hxx"
     175             : #include <columnspanset.hxx>
     176             : 
     177             : #include <boost/scoped_ptr.hpp>
     178             : 
     179             : using namespace ::ooo::vba;
     180             : using namespace ::com::sun::star;
     181             : using ::std::vector;
     182             : 
     183             : // difference between VBA and file format width, in character units
     184             : const double fExtraWidth = 182.0 / 256.0;
     185             : 
     186             : //    * 1 point = 1/72 inch = 20 twips
     187             : //    * 1 inch = 72 points = 1440 twips
     188             : //    * 1 cm = 567 twips
     189          32 : static double lcl_hmmToPoints( double nVal ) { return ( (double)((nVal /1000 ) * 567 ) / 20 ); }
     190             : 
     191             : static const sal_Int16 supportedIndexTable[] = {  excel::XlBordersIndex::xlEdgeLeft, excel::XlBordersIndex::xlEdgeTop, excel::XlBordersIndex::xlEdgeBottom, excel::XlBordersIndex::xlEdgeRight, excel::XlBordersIndex::xlDiagonalDown, excel::XlBordersIndex::xlDiagonalUp, excel::XlBordersIndex::xlInsideVertical, excel::XlBordersIndex::xlInsideHorizontal };
     192             : 
     193          16 : static sal_uInt16 lcl_pointsToTwips( double nVal )
     194             : {
     195          16 :     nVal = nVal * static_cast<double>(20);
     196          16 :     short nTwips = static_cast<short>(nVal);
     197          16 :     return nTwips;
     198             : }
     199         154 : static double lcl_TwipsToPoints( sal_uInt16 nVal )
     200             : {
     201         154 :     double nPoints = nVal;
     202         154 :     return nPoints / 20;
     203             : }
     204             : 
     205         170 : static double lcl_Round2DecPlaces( double nVal )
     206             : {
     207         170 :     nVal  = (nVal * (double)100);
     208         170 :     long tmp = static_cast<long>(nVal);
     209         170 :     if ( ( ( nVal - tmp ) >= 0.5 ) )
     210          20 :         ++tmp;
     211         170 :     nVal = tmp;
     212         170 :     nVal = nVal/100;
     213         170 :     return nVal;
     214             : }
     215             : 
     216        1364 : static uno::Any lcl_makeRange( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Any aAny, bool bIsRows, bool bIsColumns )
     217             : {
     218        1364 :     uno::Reference< table::XCellRange > xCellRange( aAny, uno::UNO_QUERY_THROW );
     219        1364 :     return uno::makeAny( uno::Reference< excel::XRange >( new ScVbaRange( xParent, xContext, xCellRange, bIsRows, bIsColumns ) ) );
     220             : }
     221             : 
     222          14 : static uno::Reference< excel::XRange > lcl_makeXRangeFromSheetCellRanges( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< sheet::XSheetCellRanges >& xLocSheetCellRanges, ScDocShell* pDoc )
     223             : {
     224          14 :     uno::Reference< excel::XRange > xRange;
     225          28 :     uno::Sequence< table::CellRangeAddress  > sAddresses = xLocSheetCellRanges->getRangeAddresses();
     226          28 :     ScRangeList aCellRanges;
     227          14 :     sal_Int32 nLen = sAddresses.getLength();
     228          14 :     if ( nLen )
     229             :            {
     230          38 :     for ( sal_Int32 index = 0; index < nLen; ++index )
     231             :     {
     232          24 :         ScRange refRange;
     233          24 :         ScUnoConversion::FillScRange( refRange, sAddresses[ index ] );
     234          24 :         aCellRanges.Append( refRange );
     235             :     }
     236             :     // Single range
     237          14 :     if ( aCellRanges.size() == 1 )
     238             :     {
     239           4 :         uno::Reference< table::XCellRange > xTmpRange( new ScCellRangeObj( pDoc, *aCellRanges.front() ) );
     240           4 :         xRange = new ScVbaRange( xParent, xContext, xTmpRange );
     241             :     }
     242             :     else
     243             :     {
     244          10 :         uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pDoc, aCellRanges ) );
     245          10 :         xRange = new ScVbaRange( xParent, xContext, xRanges );
     246             :     }
     247             :     }
     248          28 :     return xRange;
     249             : }
     250             : 
     251         428 : ScCellRangesBase* ScVbaRange::getCellRangesBase() throw ( uno::RuntimeException )
     252             : {
     253         428 :     if( mxRanges.is() )
     254          72 :         return ScCellRangesBase::getImplementation( mxRanges );
     255         356 :     if( mxRange.is() )
     256         356 :         return ScCellRangesBase::getImplementation( mxRange );
     257           0 :     throw uno::RuntimeException("General Error creating range - Unknown" );
     258             : }
     259             : 
     260          20 : ScCellRangeObj* ScVbaRange::getCellRangeObj() throw ( uno::RuntimeException )
     261             : {
     262          20 :     return dynamic_cast< ScCellRangeObj* >( getCellRangesBase() );
     263             : }
     264             : 
     265          58 : SfxItemSet*  ScVbaRange::getCurrentDataSet( ) throw ( uno::RuntimeException )
     266             : {
     267          58 :     SfxItemSet* pDataSet = excel::ScVbaCellRangeAccess::GetDataSet( getCellRangesBase() );
     268          58 :     if ( !pDataSet )
     269           0 :         throw uno::RuntimeException("Can't access Itemset for range" );
     270          58 :     return pDataSet;
     271             : }
     272             : 
     273        1138 : void ScVbaRange::fireChangeEvent()
     274             : {
     275        1138 :     if( ScVbaApplication::getDocumentEventsEnabled() )
     276             :     {
     277        1094 :         ScDocument& rDoc = getScDocument();
     278        1094 :         uno::Reference< script::vba::XVBAEventProcessor > xVBAEvents = rDoc.GetVbaEventProcessor();
     279        1094 :         if( xVBAEvents.is() ) try
     280             :         {
     281        1094 :             uno::Sequence< uno::Any > aArgs( 1 );
     282        1094 :             aArgs[ 0 ] <<= uno::Reference< excel::XRange >( this );
     283        1094 :             xVBAEvents->processVbaEvent( script::vba::VBAEventId::WORKSHEET_CHANGE, aArgs );
     284             :         }
     285           0 :         catch( uno::Exception& )
     286             :         {
     287        1094 :         }
     288             :     }
     289        1138 : }
     290             : 
     291           0 : class SingleRangeEnumeration : public EnumerationHelper_BASE
     292             : {
     293             :     uno::Reference< XHelperInterface > m_xParent;
     294             :     uno::Reference< table::XCellRange > m_xRange;
     295             :     uno::Reference< uno::XComponentContext > mxContext;
     296             :     bool bHasMore;
     297             : public:
     298             : 
     299           0 :     SingleRangeEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< css::uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException ) : m_xParent( xParent ), m_xRange( xRange ), mxContext( xContext ), bHasMore( true ) { }
     300           0 :     virtual sal_Bool SAL_CALL hasMoreElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return bHasMore; }
     301           0 :     virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     302             :     {
     303           0 :         if ( !bHasMore )
     304           0 :             throw container::NoSuchElementException();
     305           0 :         bHasMore = false;
     306           0 :         return uno::makeAny( m_xRange );
     307             :     }
     308             : };
     309             : 
     310             : // very simple class to pass to ScVbaCollectionBaseImpl containing
     311             : // just one item
     312             : typedef ::cppu::WeakImplHelper2< container::XIndexAccess, container::XEnumerationAccess > SingleRange_BASE;
     313             : 
     314       10908 : class SingleRangeIndexAccess : public SingleRange_BASE
     315             : {
     316             : private:
     317             :     uno::Reference< XHelperInterface > mxParent;
     318             :     uno::Reference< table::XCellRange > m_xRange;
     319             :     uno::Reference< uno::XComponentContext > mxContext;
     320             : 
     321             : public:
     322        5454 :     SingleRangeIndexAccess( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange ):mxParent( xParent ), m_xRange( xRange ), mxContext( xContext ) {}
     323             :     // XIndexAccess
     324        7912 :     virtual ::sal_Int32 SAL_CALL getCount() throw (::uno::RuntimeException, std::exception) SAL_OVERRIDE { return 1; }
     325         630 :     virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     326             :     {
     327         630 :         if ( Index != 0 )
     328           0 :             throw lang::IndexOutOfBoundsException();
     329         630 :         return uno::makeAny( m_xRange );
     330             :     }
     331             :         // XElementAccess
     332           0 :         virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return cppu::UnoType<table::XCellRange>::get(); }
     333             : 
     334           0 :         virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return sal_True; }
     335             :     // XEnumerationAccess
     336           0 :     virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE { return new SingleRangeEnumeration( mxParent, mxContext, m_xRange ); }
     337             : 
     338             : };
     339             : 
     340           0 : class RangesEnumerationImpl : public EnumerationHelperImpl
     341             : {
     342             :     bool mbIsRows;
     343             :     bool mbIsColumns;
     344             : public:
     345             : 
     346           0 :     RangesEnumerationImpl( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XEnumeration >& xEnumeration, bool bIsRows, bool bIsColumns ) throw ( uno::RuntimeException ) : EnumerationHelperImpl( xParent, xContext, xEnumeration ), mbIsRows( bIsRows ), mbIsColumns( bIsColumns ) {}
     347           0 :     virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     348             :     {
     349           0 :         return lcl_makeRange( m_xParent, m_xContext, m_xEnumeration->nextElement(), mbIsRows, mbIsColumns );
     350             :     }
     351             : };
     352             : 
     353       11228 : class ScVbaRangeAreas : public ScVbaCollectionBaseImpl
     354             : {
     355             :     bool mbIsRows;
     356             :     bool mbIsColumns;
     357             : public:
     358        5614 :     ScVbaRangeAreas( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< container::XIndexAccess >& xIndexAccess, bool bIsRows, bool bIsColumns ) : ScVbaCollectionBaseImpl( xParent, xContext, xIndexAccess ), mbIsRows( bIsRows ), mbIsColumns( bIsColumns ) {}
     359             : 
     360             :     // XEnumerationAccess
     361             :     virtual uno::Reference< container::XEnumeration > SAL_CALL createEnumeration() throw (uno::RuntimeException) SAL_OVERRIDE;
     362             : 
     363             :     // XElementAccess
     364           0 :     virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException) SAL_OVERRIDE { return cppu::UnoType<excel::XRange>::get(); }
     365             : 
     366             :     virtual uno::Any createCollectionObject( const uno::Any& aSource ) SAL_OVERRIDE;
     367             : 
     368           0 :     virtual OUString getServiceImplName() SAL_OVERRIDE { return OUString(); }
     369             : 
     370           0 :     virtual uno::Sequence< OUString > getServiceNames() SAL_OVERRIDE { return uno::Sequence< OUString >(); }
     371             : 
     372             : };
     373             : 
     374             : uno::Reference< container::XEnumeration > SAL_CALL
     375           0 : ScVbaRangeAreas::createEnumeration() throw (uno::RuntimeException)
     376             : {
     377           0 :     uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xIndexAccess, uno::UNO_QUERY_THROW );
     378           0 :     return new RangesEnumerationImpl( mxParent, mxContext, xEnumAccess->createEnumeration(), mbIsRows, mbIsColumns );
     379             : }
     380             : 
     381             : uno::Any
     382        1364 : ScVbaRangeAreas::createCollectionObject( const uno::Any& aSource )
     383             : {
     384        1364 :     return lcl_makeRange( mxParent, mxContext, aSource, mbIsRows, mbIsColumns );
     385             : }
     386             : 
     387             : // assume that xIf is infact a ScCellRangesBase
     388             : ScDocShell*
     389       18602 : getDocShellFromIf( const uno::Reference< uno::XInterface >& xIf ) throw ( uno::RuntimeException )
     390             : {
     391       18602 :         ScCellRangesBase* pUno = ScCellRangesBase::getImplementation( xIf );
     392       18602 :         if ( !pUno )
     393           0 :             throw uno::RuntimeException("Failed to access underlying uno range object"  );
     394       18602 :         return pUno->GetDocShell();
     395             : }
     396             : 
     397             : ScDocShell*
     398        3580 : getDocShellFromRange( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
     399             : {
     400             :         // need the ScCellRangesBase to get docshell
     401        3580 :     uno::Reference< uno::XInterface > xIf( xRange );
     402        3580 :         return getDocShellFromIf(xIf );
     403             : }
     404             : 
     405             : ScDocShell*
     406           6 : getDocShellFromRanges( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
     407             : {
     408             :     // need the ScCellRangesBase to get docshell
     409           6 :     uno::Reference< uno::XInterface > xIf( xRanges );
     410           6 :     return getDocShellFromIf(xIf );
     411             : }
     412             : 
     413       15016 : uno::Reference< frame::XModel > getModelFromXIf( const uno::Reference< uno::XInterface >& xIf ) throw ( uno::RuntimeException )
     414             : {
     415       15016 :         ScDocShell* pDocShell = getDocShellFromIf(xIf );
     416       15016 :         return pDocShell->GetModel();
     417             : }
     418             : 
     419       14824 : uno::Reference< frame::XModel > getModelFromRange( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
     420             : {
     421             :     // the XInterface for getImplementation can be any derived interface, no need for queryInterface
     422       14824 :     uno::Reference< uno::XInterface > xIf( xRange );
     423       14824 :         return getModelFromXIf( xIf );
     424             : }
     425             : 
     426             : ScDocument&
     427        1504 : getDocumentFromRange( const uno::Reference< table::XCellRange >& xRange )
     428             : {
     429        1504 :         ScDocShell* pDocShell = getDocShellFromRange( xRange );
     430        1504 :         if ( !pDocShell )
     431           0 :             throw uno::RuntimeException("Failed to access underlying docshell from uno range object" );
     432        1504 :     ScDocument& rDoc = pDocShell->GetDocument();
     433        1504 :     return rDoc;
     434             : }
     435             : 
     436             : ScDocument&
     437        1312 : ScVbaRange::getScDocument() throw (uno::RuntimeException)
     438             : {
     439        1312 :     if ( mxRanges.is() )
     440             :     {
     441          30 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
     442          60 :         uno::Reference< table::XCellRange > xRange( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
     443          60 :         return getDocumentFromRange( xRange );
     444             :     }
     445        1282 :     return getDocumentFromRange( mxRange );
     446             : }
     447             : 
     448             : ScDocShell*
     449        2062 : ScVbaRange::getScDocShell() throw (uno::RuntimeException)
     450             : {
     451        2062 :     if ( mxRanges.is() )
     452             :     {
     453           4 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
     454           8 :         uno::Reference< table::XCellRange > xRange( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
     455           8 :         return getDocShellFromRange( xRange );
     456             :     }
     457        2058 :     return getDocShellFromRange( mxRange );
     458             : }
     459             : 
     460         620 : ScVbaRange* ScVbaRange::getImplementation( const uno::Reference< excel::XRange >& rxRange )
     461             : {
     462             :     // FIXME: always save to use dynamic_cast? Or better to (implement and) use XTunnel?
     463         620 :     return dynamic_cast< ScVbaRange* >( rxRange.get() );
     464             : }
     465             : 
     466           2 : uno::Reference< frame::XModel > ScVbaRange::getUnoModel() throw (uno::RuntimeException)
     467             : {
     468           2 :     if( ScDocShell* pDocShell = getScDocShell() )
     469           4 :         return pDocShell->GetModel();
     470           0 :     throw uno::RuntimeException();
     471             : }
     472             : 
     473           0 : uno::Reference< frame::XModel > ScVbaRange::getUnoModel( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException)
     474             : {
     475           0 :     if( ScVbaRange* pScVbaRange = getImplementation( rxRange ) )
     476           0 :         return pScVbaRange->getUnoModel();
     477           0 :     throw uno::RuntimeException();
     478             : }
     479             : 
     480           2 : const ScRangeList& ScVbaRange::getScRangeList() throw (uno::RuntimeException)
     481             : {
     482           2 :     if( ScCellRangesBase* pScRangesBase = getCellRangesBase() )
     483           4 :         return pScRangesBase->GetRangeList();
     484           0 :     throw uno::RuntimeException("Cannot obtain UNO range implementation object" );
     485             : }
     486             : 
     487           0 : const ScRangeList& ScVbaRange::getScRangeList( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException)
     488             : {
     489           0 :     if( ScVbaRange* pScVbaRange = getImplementation( rxRange ) )
     490           0 :         return pScVbaRange->getScRangeList();
     491           0 :     throw uno::RuntimeException("Cannot obtain VBA range implementation object" );
     492             : }
     493             : 
     494        9358 : class NumFormatHelper
     495             : {
     496             :     uno::Reference< util::XNumberFormatsSupplier > mxSupplier;
     497             :     uno::Reference< beans::XPropertySet > mxRangeProps;
     498             :     uno::Reference< util::XNumberFormats > mxFormats;
     499             : public:
     500        9358 :     NumFormatHelper( const uno::Reference< table::XCellRange >& xRange )
     501        9358 :     {
     502        9358 :         mxSupplier.set( getModelFromRange( xRange ), uno::UNO_QUERY_THROW );
     503        9358 :         mxRangeProps.set( xRange, uno::UNO_QUERY_THROW);
     504        9358 :         mxFormats = mxSupplier->getNumberFormats();
     505        9358 :     }
     506       14106 :     uno::Reference< beans::XPropertySet > getNumberProps()
     507             :     {
     508       14106 :         long nIndexKey = 0;
     509       14106 :         uno::Any aValue = mxRangeProps->getPropertyValue( "NumberFormat" );
     510       14106 :         aValue >>= nIndexKey;
     511             : 
     512       14106 :         if ( mxFormats.is() )
     513       14106 :             return  mxFormats->getByKey( nIndexKey );
     514           0 :         return  uno::Reference< beans::XPropertySet > ();
     515             :     }
     516             : 
     517        9344 :     bool isBooleanType()
     518             :     {
     519             : 
     520        9344 :         if ( getNumberFormat() & util::NumberFormat::LOGICAL )
     521           6 :             return true;
     522        9338 :         return false;
     523             :     }
     524             : 
     525        4752 :     bool isDateType()
     526             :     {
     527        4752 :         sal_Int16 nType = getNumberFormat();
     528        4752 :         if(( nType & util::NumberFormat::DATETIME ))
     529             :         {
     530           0 :             return true;
     531             :         }
     532        4752 :         return false;
     533             :     }
     534             : 
     535           6 :     OUString getNumberFormatString()
     536             :     {
     537           6 :         uno::Reference< uno::XInterface > xIf( mxRangeProps, uno::UNO_QUERY_THROW );
     538           6 :         ScCellRangesBase* pUnoCellRange = ScCellRangesBase::getImplementation( xIf );
     539           6 :         if ( pUnoCellRange )
     540             :         {
     541             : 
     542           6 :             SfxItemSet* pDataSet =  excel::ScVbaCellRangeAccess::GetDataSet( pUnoCellRange );
     543           6 :             SfxItemState eState = pDataSet->GetItemState( ATTR_VALUE_FORMAT, true, NULL);
     544             :             // one of the cells in the range is not like the other ;-)
     545             :             // so return a zero length format to indicate that
     546           6 :             if ( eState == SfxItemState::DONTCARE )
     547           2 :                 return OUString();
     548             :         }
     549             : 
     550           8 :         uno::Reference< beans::XPropertySet > xNumberProps( getNumberProps(), uno::UNO_QUERY_THROW );
     551           8 :         OUString aFormatString;
     552           8 :         uno::Any aString = xNumberProps->getPropertyValue( "FormatString" );
     553           4 :         aString >>= aFormatString;
     554          10 :         return aFormatString;
     555             :     }
     556             : 
     557       14096 :     sal_Int16 getNumberFormat()
     558             :     {
     559       14096 :         uno::Reference< beans::XPropertySet > xNumberProps = getNumberProps();
     560             :         sal_Int16 nType = ::comphelper::getINT16(
     561       14096 :             xNumberProps->getPropertyValue( "Type" ) );
     562       14096 :         return nType;
     563             :     }
     564             : 
     565           6 :     bool setNumberFormat( const OUString& rFormat )
     566             :     {
     567             :         // #163288# treat "General" as "Standard" format
     568           6 :         sal_Int32 nNewIndex = 0;
     569           6 :         if( !rFormat.equalsIgnoreAsciiCase( "General" ) )
     570             :         {
     571           2 :             lang::Locale aLocale;
     572           4 :             uno::Reference< beans::XPropertySet > xNumProps = getNumberProps();
     573           2 :             xNumProps->getPropertyValue( "Locale" ) >>= aLocale;
     574           2 :             nNewIndex = mxFormats->queryKey( rFormat, aLocale, false );
     575           2 :             if ( nNewIndex == -1 ) // format not defined
     576           2 :                 nNewIndex = mxFormats->addNew( rFormat, aLocale );
     577             :         }
     578           6 :         mxRangeProps->setPropertyValue( "NumberFormat", uno::makeAny( nNewIndex ) );
     579           6 :         return true;
     580             :     }
     581             : 
     582           4 :     bool setNumberFormat( sal_Int16 nType )
     583             :     {
     584           4 :         uno::Reference< beans::XPropertySet > xNumberProps = getNumberProps();
     585           8 :         lang::Locale aLocale;
     586           4 :         xNumberProps->getPropertyValue( "Locale" ) >>= aLocale;
     587           8 :         uno::Reference<util::XNumberFormatTypes> xTypes( mxFormats, uno::UNO_QUERY );
     588           4 :         if ( xTypes.is() )
     589             :         {
     590           4 :             sal_Int32 nNewIndex = xTypes->getStandardFormat( nType, aLocale );
     591           4 :                mxRangeProps->setPropertyValue( "NumberFormat", uno::makeAny( nNewIndex ) );
     592           4 :             return true;
     593             :         }
     594           4 :         return false;
     595             :     }
     596             : 
     597             : };
     598             : 
     599             : struct CellPos
     600             : {
     601         538 :     CellPos( sal_Int32 nRow, sal_Int32 nCol, sal_Int32 nArea ):m_nRow(nRow), m_nCol(nCol), m_nArea( nArea ) {};
     602             : sal_Int32 m_nRow;
     603             : sal_Int32 m_nCol;
     604             : sal_Int32 m_nArea;
     605             : };
     606             : 
     607             : typedef ::cppu::WeakImplHelper1< container::XEnumeration > CellsEnumeration_BASE;
     608             : typedef ::std::vector< CellPos > vCellPos;
     609             : 
     610             : // #FIXME - QUICK
     611             : // we could probably could and should modify CellsEnumeration below
     612             : // to handle rows and columns ( but I do this separately for now
     613             : // and.. this class only handles singe areas ( does it have to handle
     614             : // multi area ranges?? )
     615           0 : class ColumnsRowEnumeration: public CellsEnumeration_BASE
     616             : {
     617             :     uno::Reference< uno::XComponentContext > mxContext;
     618             :         uno::Reference< excel::XRange > mxRange;
     619             :     sal_Int32 mMaxElems;
     620             :     sal_Int32 mCurElem;
     621             : 
     622             : public:
     623           0 :     ColumnsRowEnumeration( const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< excel::XRange >& xRange, sal_Int32 nElems ) : mxContext( xContext ), mxRange( xRange ), mMaxElems( nElems ), mCurElem( 0 )
     624             :         {
     625           0 :     }
     626             : 
     627           0 :     virtual sal_Bool SAL_CALL hasMoreElements() throw (::uno::RuntimeException, std::exception) SAL_OVERRIDE { return mCurElem < mMaxElems; }
     628             : 
     629           0 :     virtual uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     630             :     {
     631           0 :         if ( !hasMoreElements() )
     632           0 :             throw container::NoSuchElementException();
     633           0 :         sal_Int32 vbaIndex = 1 + mCurElem++;
     634           0 :         return uno::makeAny( mxRange->Item( uno::makeAny( vbaIndex ), uno::Any() ) );
     635             :     }
     636             : };
     637             : 
     638          72 : class CellsEnumeration : public CellsEnumeration_BASE
     639             : {
     640             :     uno::WeakReference< XHelperInterface > mxParent;
     641             :     uno::Reference< uno::XComponentContext > mxContext;
     642             :     uno::Reference< XCollection > m_xAreas;
     643             :     vCellPos m_CellPositions;
     644             :     vCellPos::const_iterator m_it;
     645             : 
     646         574 :     uno::Reference< table::XCellRange > getArea( sal_Int32 nVBAIndex ) throw ( uno::RuntimeException )
     647             :     {
     648         574 :         if ( nVBAIndex < 1 || nVBAIndex > m_xAreas->getCount() )
     649           0 :             throw uno::RuntimeException();
     650         574 :         uno::Reference< excel::XRange > xRange( m_xAreas->Item( uno::makeAny(nVBAIndex), uno::Any() ), uno::UNO_QUERY_THROW );
     651         574 :         uno::Reference< table::XCellRange > xCellRange( ScVbaRange::getCellRange( xRange ), uno::UNO_QUERY_THROW );
     652         574 :         return xCellRange;
     653             :     }
     654             : 
     655          36 :     void populateArea( sal_Int32 nVBAIndex )
     656             :     {
     657          36 :         uno::Reference< table::XCellRange > xRange = getArea( nVBAIndex );
     658          72 :         uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, uno::UNO_QUERY_THROW );
     659          36 :         sal_Int32 nRowCount =  xColumnRowRange->getRows()->getCount();
     660          36 :         sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount();
     661         226 :         for ( sal_Int32 i=0; i<nRowCount; ++i )
     662             :         {
     663         728 :             for ( sal_Int32 j=0; j<nColCount; ++j )
     664         538 :                 m_CellPositions.push_back( CellPos( i,j,nVBAIndex ) );
     665          36 :         }
     666          36 :     }
     667             : public:
     668          36 :     CellsEnumeration( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< XCollection >& xAreas ): mxParent( xParent ), mxContext( xContext ), m_xAreas( xAreas )
     669             :     {
     670          36 :         sal_Int32 nItems = m_xAreas->getCount();
     671          72 :         for ( sal_Int32 index=1; index <= nItems; ++index )
     672             :         {
     673          36 :                 populateArea( index );
     674             :         }
     675          36 :         m_it = m_CellPositions.begin();
     676          36 :     }
     677        1112 :     virtual sal_Bool SAL_CALL hasMoreElements() throw (::uno::RuntimeException, std::exception) SAL_OVERRIDE { return m_it != m_CellPositions.end(); }
     678             : 
     679         538 :     virtual uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
     680             :     {
     681         538 :         if ( !hasMoreElements() )
     682           0 :             throw container::NoSuchElementException();
     683         538 :         CellPos aPos = *(m_it)++;
     684             : 
     685         538 :         uno::Reference< table::XCellRange > xRangeArea = getArea( aPos.m_nArea );
     686        1076 :         uno::Reference< table::XCellRange > xCellRange( xRangeArea->getCellByPosition(  aPos.m_nCol, aPos.m_nRow ), uno::UNO_QUERY_THROW );
     687        1076 :         return uno::makeAny( uno::Reference< excel::XRange >( new ScVbaRange( mxParent, mxContext, xCellRange ) ) );
     688             : 
     689             :     }
     690             : };
     691             : 
     692           4 : const static OUString ISVISIBLE(   "IsVisible");
     693           4 : const static OUString POSITION(   "Position");
     694           4 : const static OUString EQUALS( "=" );
     695           4 : const static OUString NOTEQUALS( "<>" );
     696           4 : const static OUString GREATERTHAN( ">" );
     697           4 : const static OUString GREATERTHANEQUALS( ">=" );
     698           4 : const static OUString LESSTHAN( "<" );
     699           4 : const static OUString LESSTHANEQUALS( "<=" );
     700           4 : const static OUString CONTS_HEADER( "ContainsHeader" );
     701           4 : const static OUString INSERTPAGEBREAKS( "InsertPageBreaks" );
     702           4 : const static OUString STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY( "The command you chose cannot be performed with multiple selections.\nSelect a single range and click the command again" );
     703           4 : const static OUString STR_ERRORMESSAGE_NOCELLSWEREFOUND( "No cells were found" );
     704           4 : const static OUString CELLSTYLE( "CellStyle" );
     705             : 
     706         456 : class CellValueSetter : public ValueSetter
     707             : {
     708             : protected:
     709             :     uno::Any maValue;
     710             : public:
     711             :     CellValueSetter( const uno::Any& aValue );
     712             :     virtual bool processValue( const uno::Any& aValue,  const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE;
     713             :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE;
     714             : 
     715             : };
     716             : 
     717         456 : CellValueSetter::CellValueSetter( const uno::Any& aValue ): maValue( aValue ) {}
     718             : 
     719             : void
     720        7700 : CellValueSetter::visitNode( sal_Int32 /*i*/, sal_Int32 /*j*/, const uno::Reference< table::XCell >& xCell )
     721             : {
     722        7700 :     processValue( maValue, xCell );
     723        7700 : }
     724             : 
     725             : bool
     726        7656 : CellValueSetter::processValue( const uno::Any& aValue, const uno::Reference< table::XCell >& xCell )
     727             : {
     728             : 
     729        7656 :     bool isExtracted = false;
     730        7656 :     switch ( aValue.getValueTypeClass() )
     731             :     {
     732             :         case  uno::TypeClass_BOOLEAN:
     733             :         {
     734           4 :             bool bState = false;
     735           4 :             if ( aValue >>= bState   )
     736             :             {
     737           4 :                 uno::Reference< table::XCellRange > xRange( xCell, uno::UNO_QUERY_THROW );
     738           4 :                 if ( bState )
     739           4 :                     xCell->setValue( (double) 1 );
     740             :                 else
     741           0 :                     xCell->setValue( (double) 0 );
     742           8 :                 NumFormatHelper cellNumFormat( xRange );
     743           8 :                 cellNumFormat.setNumberFormat( util::NumberFormat::LOGICAL );
     744             :             }
     745           4 :             break;
     746             :         }
     747             :         case uno::TypeClass_STRING:
     748             :         {
     749        3058 :             OUString aString;
     750        3058 :             if ( aValue >>= aString )
     751             :             {
     752             :                 // The required behavior for a string value is:
     753             :                 // 1. If the first character is a single quote, use the rest as a string cell, regardless of the cell's number format.
     754             :                 // 2. Otherwise, if the cell's number format is "text", use the string value as a string cell.
     755             :                 // 3. Otherwise, parse the string value in English locale, and apply a corresponding number format with the cell's locale
     756             :                 //    if the cell's number format was "General".
     757             :                 // Case 1 is handled here, the rest in ScCellObj::InputEnglishString
     758             : 
     759        3058 :                 if ( aString.toChar() == '\'' )     // case 1 - handle with XTextRange
     760             :                 {
     761           0 :                     OUString aRemainder( aString.copy(1) );    // strip the quote
     762           0 :                     uno::Reference< text::XTextRange > xTextRange( xCell, uno::UNO_QUERY_THROW );
     763           0 :                     xTextRange->setString( aRemainder );
     764             :                 }
     765             :                 else
     766             :                 {
     767             :                     // call implementation method InputEnglishString
     768        3058 :                     ScCellObj* pCellObj = dynamic_cast< ScCellObj* >( xCell.get() );
     769        3058 :                     if ( pCellObj )
     770        3058 :                         pCellObj->InputEnglishString( aString );
     771             :                 }
     772             :             }
     773             :             else
     774           0 :                 isExtracted = false;
     775        3058 :             break;
     776             :         }
     777             :         default:
     778             :         {
     779        4594 :             double nDouble = 0.0;
     780        4594 :             if ( aValue >>= nDouble )
     781             :             {
     782        4588 :                 uno::Reference< table::XCellRange > xRange( xCell, uno::UNO_QUERY_THROW );
     783        9176 :                 NumFormatHelper cellFormat( xRange );
     784             :                 // If we are setting a number and the cell types was logical
     785             :                 // then we need to reset the logical format. ( see case uno::TypeClass_BOOLEAN:
     786             :                 // handling above )
     787        4588 :                 if ( cellFormat.isBooleanType() )
     788           2 :                     cellFormat.setNumberFormat("General");
     789        9176 :                 xCell->setValue( nDouble );
     790             :             }
     791             :             else
     792           6 :                 isExtracted = false;
     793        4594 :             break;
     794             :         }
     795             :     }
     796        7656 :     return isExtracted;
     797             : 
     798             : }
     799             : 
     800         956 : class CellValueGetter : public ValueGetter
     801             : {
     802             : protected:
     803             :     uno::Any maValue;
     804             : public:
     805         956 :     CellValueGetter() {}
     806             :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE;
     807             :     virtual void processValue( sal_Int32 x, sal_Int32 y, const uno::Any& aValue ) SAL_OVERRIDE;
     808        7706 :     const uno::Any& getValue() const SAL_OVERRIDE { return maValue; }
     809             : 
     810             : };
     811             : 
     812             : void
     813        7706 : CellValueGetter::processValue(  sal_Int32 /*x*/, sal_Int32 /*y*/, const uno::Any& aValue )
     814             : {
     815        7706 :     maValue = aValue;
     816        7706 : }
     817        7578 : void CellValueGetter::visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell )
     818             : {
     819        7578 :     uno::Any aValue;
     820        7578 :     table::CellContentType eType = xCell->getType();
     821        7578 :     if( eType == table::CellContentType_VALUE || eType == table::CellContentType_FORMULA )
     822             :     {
     823        4814 :         if ( eType == table::CellContentType_FORMULA )
     824             :         {
     825             : 
     826          58 :             OUString sFormula = xCell->getFormula();
     827          58 :             if ( sFormula == "=TRUE()" )
     828           0 :                 aValue <<= sal_True;
     829          58 :             else if ( sFormula == "=FALSE()" )
     830           0 :                 aValue <<= false;
     831             :             else
     832             :             {
     833          58 :                 uno::Reference< beans::XPropertySet > xProp( xCell, uno::UNO_QUERY_THROW );
     834             : 
     835          58 :                 table::CellContentType eFormulaType = table::CellContentType_VALUE;
     836             :                 // some formulas give textual results
     837          58 :                 xProp->getPropertyValue( "FormulaResultType" ) >>= eFormulaType;
     838             : 
     839          58 :                 if ( eFormulaType == table::CellContentType_TEXT )
     840             :                 {
     841           8 :                     uno::Reference< text::XTextRange > xTextRange(xCell, ::uno::UNO_QUERY_THROW);
     842           8 :                     aValue <<= xTextRange->getString();
     843             :                 }
     844             :                 else
     845          50 :                     aValue <<= xCell->getValue();
     846          58 :             }
     847             :         }
     848             :         else
     849             :         {
     850        4756 :             uno::Reference< table::XCellRange > xRange( xCell, uno::UNO_QUERY_THROW );
     851        9512 :             NumFormatHelper cellFormat( xRange );
     852        4756 :             if ( cellFormat.isBooleanType() )
     853           4 :                 aValue = uno::makeAny( ( xCell->getValue() != 0.0 ) );
     854        4752 :             else if ( cellFormat.isDateType() )
     855           0 :                 aValue = uno::makeAny( bridge::oleautomation::Date( xCell->getValue() ) );
     856             :             else
     857        9508 :                 aValue <<= xCell->getValue();
     858             :         }
     859             :     }
     860        7578 :     if( eType == table::CellContentType_TEXT )
     861             :     {
     862         200 :         uno::Reference< text::XTextRange > xTextRange(xCell, ::uno::UNO_QUERY_THROW);
     863         200 :         aValue <<= xTextRange->getString();
     864             :     }
     865        7578 :     processValue( x,y,aValue );
     866        7578 : }
     867             : 
     868          30 : class CellFormulaValueSetter : public CellValueSetter
     869             : {
     870             : private:
     871             :     ScDocument*  m_pDoc;
     872             :     formula::FormulaGrammar::Grammar m_eGrammar;
     873             : public:
     874          30 :     CellFormulaValueSetter( const uno::Any& aValue, ScDocument* pDoc, formula::FormulaGrammar::Grammar eGram ):CellValueSetter( aValue ),  m_pDoc( pDoc ), m_eGrammar( eGram ){}
     875             : protected:
     876         132 :     bool processValue( const uno::Any& aValue, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     877             :     {
     878         132 :         OUString sFormula;
     879         132 :         double aDblValue = 0.0;
     880         132 :         if ( aValue >>= sFormula )
     881             :         {
     882             :             // convert to GRAM_PODF_A1 style grammar because XCell::setFormula
     883             :             // always compile it in that grammar. Perhaps
     884             :             // css.sheet.FormulaParser should be used in future to directly
     885             :             // pass formula tokens when that API stabilizes.
     886         132 :             if ( m_eGrammar != formula::FormulaGrammar::GRAM_PODF_A1 && ( sFormula.trim().startsWith("=") ) )
     887             :             {
     888         126 :                 uno::Reference< uno::XInterface > xIf( xCell, uno::UNO_QUERY_THROW );
     889         126 :                 ScCellRangesBase* pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() );
     890         126 :                 if ( pUnoRangesBase )
     891             :                 {
     892         126 :                     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
     893         252 :                     ScCompiler aCompiler( m_pDoc, aCellRanges.front()->aStart );
     894         126 :                     aCompiler.SetGrammar(m_eGrammar);
     895             :                     // compile the string in the format passed in
     896         252 :                     boost::scoped_ptr<ScTokenArray> pArray(aCompiler.CompileString(sFormula));
     897             :                     // set desired convention to that of the document
     898         126 :                     aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_PODF_A1 );
     899         252 :                     OUString sConverted;
     900         126 :                     aCompiler.CreateStringFromTokenArray(sConverted);
     901         252 :                     sFormula = EQUALS + sConverted;
     902         126 :                 }
     903             :             }
     904             : 
     905         132 :             xCell->setFormula( sFormula );
     906         132 :             return true;
     907             :         }
     908           0 :         else if ( aValue >>= aDblValue )
     909             :         {
     910           0 :             xCell->setValue( aDblValue );
     911           0 :             return true;
     912             :         }
     913           0 :         return false;
     914             :     }
     915             : 
     916             : };
     917             : 
     918          94 : class CellFormulaValueGetter : public CellValueGetter
     919             : {
     920             : private:
     921             :     ScDocument*  m_pDoc;
     922             :     formula::FormulaGrammar::Grammar m_eGrammar;
     923             : public:
     924          94 :     CellFormulaValueGetter(ScDocument* pDoc, formula::FormulaGrammar::Grammar eGram ) : CellValueGetter( ), m_pDoc( pDoc ), m_eGrammar( eGram ) {}
     925         128 :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     926             :     {
     927         128 :         uno::Any aValue;
     928         128 :         aValue <<= xCell->getFormula();
     929         256 :         OUString sVal;
     930         128 :         aValue >>= sVal;
     931         256 :         uno::Reference< uno::XInterface > xIf( xCell, uno::UNO_QUERY_THROW );
     932         128 :         ScCellRangesBase* pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() );
     933         128 :         if ( ( xCell->getType() == table::CellContentType_FORMULA ) &&
     934             :             pUnoRangesBase )
     935             :         {
     936          50 :             ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
     937         100 :             ScCompiler aCompiler( m_pDoc, aCellRanges.front()->aStart );
     938          50 :             aCompiler.SetGrammar(formula::FormulaGrammar::GRAM_DEFAULT);
     939         100 :             boost::scoped_ptr<ScTokenArray> pArray(aCompiler.CompileString(sVal));
     940             :             // set desired convention
     941          50 :             aCompiler.SetGrammar( m_eGrammar );
     942         100 :             OUString sConverted;
     943          50 :             aCompiler.CreateStringFromTokenArray(sConverted);
     944          50 :             sVal = EQUALS + sConverted;
     945         100 :             aValue <<= sVal;
     946             :         }
     947             : 
     948         256 :         processValue( x,y,aValue );
     949         128 :     }
     950             : 
     951             : };
     952             : 
     953          62 : class Dim2ArrayValueGetter : public ArrayVisitor
     954             : {
     955             : protected:
     956             :     uno::Any maValue;
     957             :     ValueGetter& mValueGetter;
     958        6812 :     virtual void processValue( sal_Int32 x, sal_Int32 y, const uno::Any& aValue )
     959             :     {
     960        6812 :         uno::Sequence< uno::Sequence< uno::Any > >& aMatrix = *( uno::Sequence< uno::Sequence< uno::Any > >* )( maValue.getValue() );
     961        6812 :         aMatrix[x][y] = aValue;
     962        6812 :     }
     963             : 
     964             : public:
     965          62 :     Dim2ArrayValueGetter(sal_Int32 nRowCount, sal_Int32 nColCount, ValueGetter& rValueGetter ): mValueGetter(rValueGetter)
     966             :     {
     967          62 :         uno::Sequence< uno::Sequence< uno::Any > > aMatrix;
     968          62 :         aMatrix.realloc( nRowCount );
     969         288 :         for ( sal_Int32 index = 0; index < nRowCount; ++index )
     970         226 :             aMatrix[index].realloc( nColCount );
     971          62 :         maValue <<= aMatrix;
     972          62 :     }
     973        6812 :     void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     974             : 
     975             :     {
     976        6812 :         mValueGetter.visitNode( x, y, xCell );
     977        6812 :         processValue( x, y, mValueGetter.getValue() );
     978        6812 :     }
     979          62 :     const uno::Any& getValue() const { return maValue; }
     980             : 
     981             : };
     982             : 
     983           4 : const static OUString sNA("#N/A");
     984             : 
     985           6 : class Dim1ArrayValueSetter : public ArrayVisitor
     986             : {
     987             :     uno::Sequence< uno::Any > aMatrix;
     988             :     sal_Int32 nColCount;
     989             :     ValueSetter& mCellValueSetter;
     990             : public:
     991           6 :     Dim1ArrayValueSetter( const uno::Any& aValue, ValueSetter& rCellValueSetter ):mCellValueSetter( rCellValueSetter )
     992             :     {
     993           6 :         aValue >>= aMatrix;
     994           6 :         nColCount = aMatrix.getLength();
     995           6 :     }
     996          40 :     virtual void visitNode( sal_Int32 /*x*/, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
     997             :     {
     998          40 :         if ( y < nColCount )
     999          40 :             mCellValueSetter.processValue( aMatrix[ y ], xCell );
    1000             :         else
    1001           0 :             mCellValueSetter.processValue( uno::makeAny( sNA ), xCell );
    1002          40 :     }
    1003             : };
    1004             : 
    1005           4 : class Dim2ArrayValueSetter : public ArrayVisitor
    1006             : {
    1007             :     uno::Sequence< uno::Sequence< uno::Any > > aMatrix;
    1008             :     ValueSetter& mCellValueSetter;
    1009             :     sal_Int32 nRowCount;
    1010             :     sal_Int32 nColCount;
    1011             : public:
    1012           4 :     Dim2ArrayValueSetter( const uno::Any& aValue, ValueSetter& rCellValueSetter ) : mCellValueSetter( rCellValueSetter )
    1013             :     {
    1014           4 :         aValue >>= aMatrix;
    1015           4 :         nRowCount = aMatrix.getLength();
    1016           4 :         nColCount = aMatrix[0].getLength();
    1017           4 :     }
    1018             : 
    1019          48 :     virtual void visitNode( sal_Int32 x, sal_Int32 y, const uno::Reference< table::XCell >& xCell ) SAL_OVERRIDE
    1020             :     {
    1021          48 :         if ( x < nRowCount && y < nColCount )
    1022          48 :             mCellValueSetter.processValue( aMatrix[ x ][ y ], xCell );
    1023             :         else
    1024           0 :             mCellValueSetter.processValue( uno::makeAny( sNA ), xCell );
    1025             : 
    1026          48 :     }
    1027             : };
    1028             : 
    1029          42 : class RangeProcessor
    1030             : {
    1031             : public:
    1032             :     virtual void process( const uno::Reference< excel::XRange >& xRange ) = 0;
    1033             : 
    1034             : protected:
    1035          42 :     ~RangeProcessor() {}
    1036             : };
    1037             : 
    1038             : class RangeValueProcessor : public RangeProcessor
    1039             : {
    1040             :     const uno::Any& m_aVal;
    1041             : public:
    1042          18 :     RangeValueProcessor( const uno::Any& rVal ):m_aVal( rVal ) {}
    1043          18 :     virtual ~RangeValueProcessor() {}
    1044          36 :     virtual void process( const uno::Reference< excel::XRange >& xRange ) SAL_OVERRIDE
    1045             :     {
    1046          36 :         xRange->setValue( m_aVal );
    1047          36 :     }
    1048             : };
    1049             : 
    1050             : class RangeFormulaProcessor : public RangeProcessor
    1051             : {
    1052             :     const uno::Any& m_aVal;
    1053             : public:
    1054           2 :     RangeFormulaProcessor( const uno::Any& rVal ):m_aVal( rVal ) {}
    1055           2 :     virtual ~RangeFormulaProcessor() {}
    1056           4 :     virtual void process( const uno::Reference< excel::XRange >& xRange ) SAL_OVERRIDE
    1057             :     {
    1058           4 :         xRange->setFormula( m_aVal );
    1059           4 :     }
    1060             : };
    1061             : 
    1062             : class RangeCountProcessor : public RangeProcessor
    1063             : {
    1064             :     sal_Int32 nCount;
    1065             : public:
    1066          22 :     RangeCountProcessor():nCount(0){}
    1067          22 :     virtual ~RangeCountProcessor() {}
    1068          50 :     virtual void process( const uno::Reference< excel::XRange >& xRange ) SAL_OVERRIDE
    1069             :     {
    1070          50 :         nCount = nCount + xRange->getCount();
    1071          50 :     }
    1072          22 :     sal_Int32 value() { return nCount; }
    1073             : };
    1074          42 : class AreasVisitor
    1075             : {
    1076             : private:
    1077             :     uno::Reference< XCollection > m_Areas;
    1078             : public:
    1079          42 :     AreasVisitor( const uno::Reference< XCollection >& rAreas ):m_Areas( rAreas ){}
    1080             : 
    1081          42 :     void visit( RangeProcessor& processor )
    1082             :     {
    1083          42 :         if ( m_Areas.is() )
    1084             :         {
    1085          42 :             sal_Int32 nItems = m_Areas->getCount();
    1086         132 :             for ( sal_Int32 index=1; index <= nItems; ++index )
    1087             :             {
    1088          90 :                 uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    1089          90 :                 processor.process( xRange );
    1090          90 :             }
    1091             :         }
    1092          42 :     }
    1093             : };
    1094             : 
    1095        3516 : class RangeHelper
    1096             : {
    1097             :     uno::Reference< table::XCellRange > m_xCellRange;
    1098             : 
    1099             : public:
    1100        3516 :     RangeHelper( const uno::Reference< table::XCellRange >& xCellRange ) throw (uno::RuntimeException) : m_xCellRange( xCellRange )
    1101             :     {
    1102        3516 :         if ( !m_xCellRange.is() )
    1103           0 :             throw uno::RuntimeException();
    1104        3516 :     }
    1105           0 :     RangeHelper( const uno::Any aCellRange ) throw (uno::RuntimeException)
    1106           0 :     {
    1107           0 :         m_xCellRange.set( aCellRange, uno::UNO_QUERY_THROW );
    1108           0 :     }
    1109        1560 :     uno::Reference< sheet::XSheetCellRange > getSheetCellRange() throw (uno::RuntimeException)
    1110             :     {
    1111        1560 :         return uno::Reference< sheet::XSheetCellRange >(m_xCellRange, uno::UNO_QUERY_THROW);
    1112             :     }
    1113        1534 :     uno::Reference< sheet::XSpreadsheet >  getSpreadSheet() throw (uno::RuntimeException)
    1114             :     {
    1115        1534 :         return getSheetCellRange()->getSpreadsheet();
    1116             :     }
    1117             : 
    1118        1470 :     uno::Reference< table::XCellRange > getCellRangeFromSheet() throw (uno::RuntimeException)
    1119             :     {
    1120        1470 :         return uno::Reference< table::XCellRange >(getSpreadSheet(), uno::UNO_QUERY_THROW );
    1121             :     }
    1122             : 
    1123        2094 :     uno::Reference< sheet::XCellRangeAddressable >  getCellRangeAddressable() throw (uno::RuntimeException)
    1124             :     {
    1125        2094 :         return uno::Reference< sheet::XCellRangeAddressable >(m_xCellRange, ::uno::UNO_QUERY_THROW);
    1126             : 
    1127             :     }
    1128             : 
    1129          26 :     uno::Reference< sheet::XSheetCellCursor > getSheetCellCursor() throw ( uno::RuntimeException )
    1130             :     {
    1131          26 :         return  uno::Reference< sheet::XSheetCellCursor >( getSpreadSheet()->createCursorByRange( getSheetCellRange() ), uno::UNO_QUERY_THROW );
    1132             :     }
    1133             : 
    1134          16 :     static uno::Reference< excel::XRange > createRangeFromRange( const uno::Reference< XHelperInterface >& xParent, const uno::Reference<uno::XComponentContext >& xContext,
    1135             :         const uno::Reference< table::XCellRange >& xRange, const uno::Reference< sheet::XCellRangeAddressable >& xCellRangeAddressable,
    1136             :         sal_Int32 nStartColOffset = 0, sal_Int32 nStartRowOffset = 0, sal_Int32 nEndColOffset = 0, sal_Int32 nEndRowOffset = 0 )
    1137             :     {
    1138             :         return uno::Reference< excel::XRange >( new ScVbaRange( xParent, xContext,
    1139          16 :             xRange->getCellRangeByPosition(
    1140          16 :                 xCellRangeAddressable->getRangeAddress().StartColumn + nStartColOffset,
    1141          16 :                 xCellRangeAddressable->getRangeAddress().StartRow + nStartRowOffset,
    1142          16 :                 xCellRangeAddressable->getRangeAddress().EndColumn + nEndColOffset,
    1143          64 :                 xCellRangeAddressable->getRangeAddress().EndRow + nEndRowOffset ) ) );
    1144             :     }
    1145             : 
    1146             : };
    1147             : 
    1148             : bool
    1149        1470 : ScVbaRange::getCellRangesForAddress( sal_uInt16& rResFlags, const OUString& sAddress, ScDocShell* pDocSh, ScRangeList& rCellRanges, formula::FormulaGrammar::AddressConvention& eConv, char cDelimiter )
    1150             : {
    1151             : 
    1152        1470 :     if ( pDocSh )
    1153             :     {
    1154        1470 :         ScDocument& rDoc = pDocSh->GetDocument();
    1155        1470 :         sal_uInt16 nMask = SCA_VALID;
    1156        1470 :         rResFlags = rCellRanges.Parse( sAddress, &rDoc, nMask, eConv, 0, cDelimiter );
    1157        1470 :         if ( rResFlags & SCA_VALID )
    1158             :         {
    1159        1466 :             return true;
    1160             :         }
    1161             :     }
    1162           4 :     return false;
    1163             : }
    1164             : 
    1165        1392 : bool getScRangeListForAddress( const OUString& sName, ScDocShell* pDocSh, ScRange& refRange, ScRangeList& aCellRanges, formula::FormulaGrammar::AddressConvention aConv ) throw ( uno::RuntimeException )
    1166             : {
    1167             :     // see if there is a match with a named range
    1168        1392 :     uno::Reference< beans::XPropertySet > xProps( pDocSh->GetModel(), uno::UNO_QUERY_THROW );
    1169        2784 :     uno::Reference< container::XNameAccess > xNameAccess( xProps->getPropertyValue( "NamedRanges" ), uno::UNO_QUERY_THROW );
    1170             :     // Strangly enough you can have Range( "namedRange1, namedRange2, etc," )
    1171             :     // loop around each ',' separated name
    1172        2784 :     std::vector< OUString > vNames;
    1173        1392 :     sal_Int32 nIndex = 0;
    1174        1470 :     do
    1175             :     {
    1176        1470 :         OUString aToken = sName.getToken( 0, ',', nIndex );
    1177        1470 :         vNames.push_back( aToken );
    1178        1470 :     } while ( nIndex >= 0 );
    1179             : 
    1180        1392 :     if ( vNames.empty() )
    1181           0 :         vNames.push_back( sName );
    1182             : 
    1183        1392 :     std::vector< OUString >::iterator it = vNames.begin();
    1184        1392 :     std::vector< OUString >::iterator it_end = vNames.end();
    1185        1466 :     for ( ; it != it_end; ++it )
    1186             :     {
    1187             : 
    1188        1470 :         formula::FormulaGrammar::AddressConvention eConv = aConv;
    1189             :         // spaces are illegal ( but the user of course can enter them )
    1190        1470 :         OUString sAddress = (*it).trim();
    1191             :         // if a local name ( on the active sheet ) exists this will
    1192             :         // take precedence over a global with the same name
    1193        1470 :         bool bLocalName = false;
    1194        1470 :         if ( !xNameAccess->hasByName( sAddress ) )
    1195             :         {
    1196             :             // try a local name
    1197        1432 :             ScDocument& rDoc = pDocSh->GetDocument();
    1198        1432 :             SCTAB nCurTab = ScDocShell::GetCurTab();
    1199        1432 :             ScRangeName* pRangeName = rDoc.GetRangeName(nCurTab);
    1200        1432 :             if (pRangeName)
    1201             :             {
    1202        1432 :                 bLocalName = pRangeName->findByUpperName(ScGlobal::pCharClass->uppercase(sAddress)) != NULL;
    1203             :                 // TODO: Handle local names correctly.
    1204             :                 (void)bLocalName;
    1205             :             }
    1206             :         }
    1207        1470 :         char aChar = 0;
    1208        1470 :         if ( xNameAccess->hasByName( sAddress ) )
    1209             :         {
    1210          38 :             uno::Reference< sheet::XNamedRange > xNamed( xNameAccess->getByName( sAddress ), uno::UNO_QUERY_THROW );
    1211          38 :             sAddress = xNamed->getContent();
    1212             :             // As the address comes from OOO, the addressing
    1213             :             // style is may not be XL_A1
    1214          38 :             eConv = pDocSh->GetDocument().GetAddressConvention();
    1215          38 :             aChar = ';';
    1216             :         }
    1217             : 
    1218        1470 :         sal_uInt16 nFlags = 0;
    1219        1470 :         if ( !ScVbaRange::getCellRangesForAddress( nFlags, sAddress, pDocSh, aCellRanges, eConv, aChar ) )
    1220           4 :             return false;
    1221             : 
    1222        1466 :         bool bTabFromReferrer = !( nFlags & SCA_TAB_3D );
    1223             : 
    1224        3038 :         for ( size_t i = 0, nRanges = aCellRanges.size(); i < nRanges; ++i )
    1225             :         {
    1226        1572 :             ScRange* pRange = aCellRanges[ i ];
    1227        1572 :             pRange->aStart.SetCol( refRange.aStart.Col() + pRange->aStart.Col() );
    1228        1572 :             pRange->aStart.SetRow( refRange.aStart.Row() + pRange->aStart.Row() );
    1229        1572 :             pRange->aStart.SetTab( bTabFromReferrer ? refRange.aStart.Tab()  : pRange->aStart.Tab() );
    1230        1572 :             pRange->aEnd.SetCol( refRange.aStart.Col() + pRange->aEnd.Col() );
    1231        1572 :             pRange->aEnd.SetRow( refRange.aStart.Row() + pRange->aEnd.Row() );
    1232        1572 :             pRange->aEnd.SetTab( bTabFromReferrer ? refRange.aEnd.Tab()  : pRange->aEnd.Tab() );
    1233             :         }
    1234        1466 :     }
    1235        2780 :     return true;
    1236             : }
    1237             : 
    1238             : ScVbaRange*
    1239        1392 : getRangeForName( const uno::Reference< uno::XComponentContext >& xContext, const OUString& sName, ScDocShell* pDocSh, table::CellRangeAddress& pAddr, formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_XL_A1 ) throw ( uno::RuntimeException )
    1240             : {
    1241        1392 :     ScRangeList aCellRanges;
    1242        1392 :     ScRange refRange;
    1243        1392 :     ScUnoConversion::FillScRange( refRange, pAddr );
    1244        1392 :     if ( !getScRangeListForAddress ( sName, pDocSh, refRange, aCellRanges, eConv ) )
    1245           4 :         throw uno::RuntimeException();
    1246             :     // Single range
    1247        1388 :     if ( aCellRanges.size() == 1 )
    1248             :     {
    1249        1312 :         uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pDocSh, *aCellRanges.front() ) );
    1250        2624 :         uno::Reference< XHelperInterface > xFixThisParent = excel::getUnoSheetModuleObj( xRange );
    1251        2624 :         return new ScVbaRange( xFixThisParent, xContext, xRange );
    1252             :     }
    1253         152 :     uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pDocSh, aCellRanges ) );
    1254             : 
    1255         152 :     uno::Reference< XHelperInterface > xFixThisParent = excel::getUnoSheetModuleObj( xRanges );
    1256        1468 :     return new ScVbaRange( xFixThisParent, xContext, xRanges );
    1257             : }
    1258             : 
    1259             : namespace {
    1260             : 
    1261             : template< typename RangeType >
    1262        2062 : inline table::CellRangeAddress lclGetRangeAddress( const uno::Reference< RangeType >& rxCellRange ) throw (uno::RuntimeException)
    1263             : {
    1264        2062 :     return uno::Reference< sheet::XCellRangeAddressable >( rxCellRange, uno::UNO_QUERY_THROW )->getRangeAddress();
    1265             : }
    1266             : 
    1267           2 : void lclClearRange( const uno::Reference< table::XCellRange >& rxCellRange ) throw (uno::RuntimeException)
    1268             : {
    1269             :     using namespace ::com::sun::star::sheet::CellFlags;
    1270           2 :     sal_Int32 nFlags = VALUE | DATETIME | STRING | ANNOTATION | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED;
    1271           2 :     uno::Reference< sheet::XSheetOperation > xSheetOperation( rxCellRange, uno::UNO_QUERY_THROW );
    1272           2 :     xSheetOperation->clearContents( nFlags );
    1273           2 : }
    1274             : 
    1275         214 : uno::Reference< sheet::XSheetCellRange > lclExpandToMerged( const uno::Reference< table::XCellRange >& rxCellRange, bool bRecursive ) throw (uno::RuntimeException)
    1276             : {
    1277         214 :     uno::Reference< sheet::XSheetCellRange > xNewCellRange( rxCellRange, uno::UNO_QUERY_THROW );
    1278         428 :     uno::Reference< sheet::XSpreadsheet > xSheet( xNewCellRange->getSpreadsheet(), uno::UNO_SET_THROW );
    1279         214 :     table::CellRangeAddress aNewAddress = lclGetRangeAddress( xNewCellRange );
    1280         214 :     table::CellRangeAddress aOldAddress;
    1281             :     // expand as long as there are new merged ranges included
    1282         214 :     do
    1283             :     {
    1284         214 :         aOldAddress = aNewAddress;
    1285         214 :         uno::Reference< sheet::XSheetCellCursor > xCursor( xSheet->createCursorByRange( xNewCellRange ), uno::UNO_SET_THROW );
    1286         214 :         xCursor->collapseToMergedArea();
    1287         214 :         xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW );
    1288         214 :         aNewAddress = lclGetRangeAddress( xNewCellRange );
    1289             :     }
    1290         214 :     while( bRecursive && (aOldAddress != aNewAddress) );
    1291         428 :     return xNewCellRange;
    1292             : }
    1293             : 
    1294           6 : uno::Reference< sheet::XSheetCellRangeContainer > lclExpandToMerged( const uno::Reference< sheet::XSheetCellRangeContainer >& rxCellRanges, bool bRecursive ) throw (uno::RuntimeException)
    1295             : {
    1296           6 :     if( !rxCellRanges.is() )
    1297           0 :         throw uno::RuntimeException("Missing cell ranges object" );
    1298           6 :     sal_Int32 nCount = rxCellRanges->getCount();
    1299           6 :     if( nCount < 1 )
    1300           0 :         throw uno::RuntimeException("Missing cell ranges object" );
    1301             : 
    1302           6 :     ScRangeList aScRanges;
    1303          18 :     for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    1304             :     {
    1305          12 :         uno::Reference< table::XCellRange > xRange( rxCellRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    1306          12 :         table::CellRangeAddress aRangeAddr = lclGetRangeAddress( lclExpandToMerged( xRange, bRecursive ) );
    1307          12 :         ScRange aScRange;
    1308          12 :         ScUnoConversion::FillScRange( aScRange, aRangeAddr );
    1309          12 :         aScRanges.Append( aScRange );
    1310          12 :     }
    1311           6 :     return new ScCellRangesObj( getDocShellFromRanges( rxCellRanges ), aScRanges );
    1312             : }
    1313             : 
    1314           4 : void lclExpandAndMerge( const uno::Reference< table::XCellRange >& rxCellRange, bool bMerge ) throw (uno::RuntimeException)
    1315             : {
    1316           4 :     uno::Reference< util::XMergeable > xMerge( lclExpandToMerged( rxCellRange, true ), uno::UNO_QUERY_THROW );
    1317             :     // Calc cannot merge over merged ranges, always unmerge first
    1318           4 :     xMerge->merge( false );
    1319           4 :     if( bMerge )
    1320             :     {
    1321             :         // clear all contents of the covered cells (not the top-left cell)
    1322           2 :         table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxCellRange );
    1323           2 :         sal_Int32 nLastColIdx = aRangeAddr.EndColumn - aRangeAddr.StartColumn;
    1324           2 :         sal_Int32 nLastRowIdx = aRangeAddr.EndRow - aRangeAddr.StartRow;
    1325             :         // clear cells of top row, right of top-left cell
    1326           2 :         if( nLastColIdx > 0 )
    1327           2 :             lclClearRange( rxCellRange->getCellRangeByPosition( 1, 0, nLastColIdx, 0 ) );
    1328             :         // clear all rows below top row
    1329           2 :         if( nLastRowIdx > 0 )
    1330           0 :             lclClearRange( rxCellRange->getCellRangeByPosition( 0, 1, nLastColIdx, nLastRowIdx ) );
    1331             :         // merge the range
    1332           2 :         xMerge->merge( sal_True );
    1333           4 :     }
    1334           4 : }
    1335             : 
    1336          92 : util::TriState lclGetMergedState( const uno::Reference< table::XCellRange >& rxCellRange ) throw (uno::RuntimeException)
    1337             : {
    1338             :     /*  1) Check if range is completely inside one single merged range. To do
    1339             :         this, try to extend from top-left cell only (not from entire range).
    1340             :         This will exclude cases where this range consists of several merged
    1341             :         ranges (or parts of them). */
    1342          92 :     table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxCellRange );
    1343          92 :     uno::Reference< table::XCellRange > xTopLeft( rxCellRange->getCellRangeByPosition( 0, 0, 0, 0 ), uno::UNO_SET_THROW );
    1344         184 :     uno::Reference< sheet::XSheetCellRange > xExpanded( lclExpandToMerged( xTopLeft, false ), uno::UNO_SET_THROW );
    1345          92 :     table::CellRangeAddress aExpAddr = lclGetRangeAddress( xExpanded );
    1346             :     // check that expanded range has more than one cell (really merged)
    1347          92 :     if( ((aExpAddr.StartColumn < aExpAddr.EndColumn) || (aExpAddr.StartRow < aExpAddr.EndRow)) && ScUnoConversion::Contains( aExpAddr, aRangeAddr ) )
    1348          28 :         return util::TriState_YES;
    1349             : 
    1350             :     /*  2) Check if this range contains any merged cells (completely or
    1351             :         partly). This seems to be hardly possible via API, as
    1352             :         XMergeable::getIsMerged() returns only true, if the top-left cell of a
    1353             :         merged range is part of this range, so cases where just the lower part
    1354             :         of a merged range is part of this range are not covered. */
    1355          64 :     ScRange aScRange;
    1356          64 :     ScUnoConversion::FillScRange( aScRange, aRangeAddr );
    1357          64 :     bool bHasMerged = getDocumentFromRange( rxCellRange ).HasAttrib( aScRange, HASATTR_MERGED | HASATTR_OVERLAPPED );
    1358         156 :     return bHasMerged ? util::TriState_INDETERMINATE : util::TriState_NO;
    1359             : }
    1360             : 
    1361             : } // namespace
    1362             : 
    1363             : css::uno::Reference< excel::XRange >
    1364          10 : ScVbaRange::getRangeObjectForName(
    1365             :         const uno::Reference< uno::XComponentContext >& xContext, const OUString& sRangeName,
    1366             :         ScDocShell* pDocSh, formula::FormulaGrammar::AddressConvention eConv ) throw ( uno::RuntimeException )
    1367             : {
    1368          10 :     table::CellRangeAddress refAddr;
    1369          10 :     return getRangeForName( xContext, sRangeName, pDocSh, refAddr, eConv );
    1370             : }
    1371             : 
    1372          24 : table::CellRangeAddress getCellRangeAddressForVBARange( const uno::Any& aParam, ScDocShell* pDocSh,  formula::FormulaGrammar::AddressConvention aConv = formula::FormulaGrammar::CONV_XL_A1) throw ( uno::RuntimeException )
    1373             : {
    1374          24 :     uno::Reference< table::XCellRange > xRangeParam;
    1375          24 :     switch ( aParam.getValueTypeClass() )
    1376             :     {
    1377             :         case uno::TypeClass_STRING:
    1378             :         {
    1379           0 :             OUString rString;
    1380           0 :             aParam >>= rString;
    1381           0 :             ScRangeList aCellRanges;
    1382           0 :             ScRange refRange;
    1383           0 :             if ( getScRangeListForAddress ( rString, pDocSh, refRange, aCellRanges, aConv ) )
    1384             :             {
    1385           0 :                 if ( aCellRanges.size() == 1 )
    1386             :                 {
    1387           0 :                     table::CellRangeAddress aRangeAddress;
    1388           0 :                     ScUnoConversion::FillApiRange( aRangeAddress, *aCellRanges.front() );
    1389           0 :                     return aRangeAddress;
    1390             :                 }
    1391           0 :             }
    1392             :         }
    1393           0 :         break;
    1394             : 
    1395             :         case uno::TypeClass_INTERFACE:
    1396             :         {
    1397          24 :             uno::Reference< excel::XRange > xRange;
    1398          24 :             aParam >>= xRange;
    1399          24 :             if ( xRange.is() )
    1400          24 :                 xRange->getCellRange() >>= xRangeParam;
    1401             :         }
    1402          24 :         break;
    1403             : 
    1404             :         default:
    1405           0 :             throw uno::RuntimeException("Can't extact CellRangeAddress from type" );
    1406             :     }
    1407          24 :     return lclGetRangeAddress( xRangeParam );
    1408             : }
    1409             : 
    1410             : static uno::Reference< XCollection >
    1411           4 : lcl_setupBorders( const uno::Reference< excel::XRange >& xParentRange, const uno::Reference<uno::XComponentContext>& xContext,  const uno::Reference< table::XCellRange >& xRange  ) throw( uno::RuntimeException )
    1412             : {
    1413           4 :     uno::Reference< XHelperInterface > xParent( xParentRange, uno::UNO_QUERY_THROW );
    1414           4 :     ScDocument& rDoc = getDocumentFromRange(xRange);
    1415           4 :     ScVbaPalette aPalette( rDoc.GetDocumentShell() );
    1416           4 :      uno::Reference< XCollection > borders( new ScVbaBorders( xParent, xContext, xRange, aPalette ) );
    1417           4 :     return borders;
    1418             : }
    1419             : 
    1420          36 : ScVbaRange::ScVbaRange( uno::Sequence< uno::Any> const & args,
    1421          36 :     uno::Reference< uno::XComponentContext> const & xContext )  throw ( lang::IllegalArgumentException, uno::RuntimeException ) : ScVbaRange_BASE( getXSomethingFromArgs< XHelperInterface >( args, 0 ), xContext, getXSomethingFromArgs< beans::XPropertySet >( args, 1, false ), getModelFromXIf( getXSomethingFromArgs< uno::XInterface >( args, 1 ) ), true ), mbIsRows( false ), mbIsColumns( false )
    1422             : {
    1423          36 :     mxRange.set( mxPropertySet, uno::UNO_QUERY );
    1424          36 :     mxRanges.set( mxPropertySet, uno::UNO_QUERY );
    1425          36 :     uno::Reference< container::XIndexAccess >  xIndex;
    1426          36 :     if ( mxRange.is() )
    1427             :     {
    1428          32 :         xIndex = new SingleRangeIndexAccess( mxParent, mxContext, mxRange );
    1429             :     }
    1430           4 :     else if ( mxRanges.is() )
    1431             :     {
    1432           4 :         xIndex.set( mxRanges, uno::UNO_QUERY_THROW );
    1433             :     }
    1434          36 :     m_Areas = new ScVbaRangeAreas( mxParent, mxContext, xIndex, mbIsRows, mbIsColumns );
    1435          36 : }
    1436             : 
    1437        5422 : ScVbaRange::ScVbaRange( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< table::XCellRange >& xRange, bool bIsRows, bool bIsColumns ) throw( lang::IllegalArgumentException )
    1438             : : ScVbaRange_BASE( xParent, xContext, uno::Reference< beans::XPropertySet >( xRange, uno::UNO_QUERY_THROW ), getModelFromRange( xRange), true ), mxRange( xRange ),
    1439             :                 mbIsRows( bIsRows ),
    1440        5422 :                 mbIsColumns( bIsColumns )
    1441             : {
    1442        5422 :     if  ( !xContext.is() )
    1443           0 :         throw lang::IllegalArgumentException("context is not set ", uno::Reference< uno::XInterface >() , 1 );
    1444        5422 :     if  ( !xRange.is() )
    1445           0 :         throw lang::IllegalArgumentException("range is not set ", uno::Reference< uno::XInterface >() , 1 );
    1446             : 
    1447        5422 :     uno::Reference< container::XIndexAccess > xIndex( new SingleRangeIndexAccess( mxParent, mxContext, xRange ) );
    1448        5422 :     m_Areas = new ScVbaRangeAreas( mxParent, mxContext, xIndex, mbIsRows, mbIsColumns );
    1449             : 
    1450        5422 : }
    1451             : 
    1452         156 : ScVbaRange::ScVbaRange(const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges, bool bIsRows, bool bIsColumns)
    1453             :     throw (lang::IllegalArgumentException, uno::RuntimeException)
    1454         156 : : ScVbaRange_BASE( xParent, xContext, uno::Reference< beans::XPropertySet >( xRanges, uno::UNO_QUERY_THROW ), getModelFromXIf( uno::Reference< uno::XInterface >( xRanges, uno::UNO_QUERY_THROW ) ), true ), mxRanges( xRanges ),mbIsRows( bIsRows ), mbIsColumns( bIsColumns )
    1455             : 
    1456             : {
    1457         156 :     uno::Reference< container::XIndexAccess >  xIndex( mxRanges, uno::UNO_QUERY_THROW );
    1458         156 :     m_Areas  = new ScVbaRangeAreas( xParent, mxContext, xIndex, mbIsRows, mbIsColumns );
    1459             : 
    1460         156 : }
    1461             : 
    1462       11192 : ScVbaRange::~ScVbaRange()
    1463             : {
    1464       11192 : }
    1465             : 
    1466           6 : uno::Reference< XCollection >& ScVbaRange::getBorders()
    1467             : {
    1468           6 :     if ( !m_Borders.is() )
    1469             :     {
    1470           4 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    1471           4 :         m_Borders = lcl_setupBorders( this, mxContext, uno::Reference< table::XCellRange >( xRange->getCellRange(), uno::UNO_QUERY_THROW ) );
    1472             :     }
    1473           6 :     return m_Borders;
    1474             : }
    1475             : 
    1476             : void
    1477        1412 : ScVbaRange::visitArray( ArrayVisitor& visitor )
    1478             : {
    1479        1412 :     table::CellRangeAddress aRangeAddr = lclGetRangeAddress( mxRange );
    1480        1412 :     sal_Int32 nRowCount = aRangeAddr.EndRow - aRangeAddr.StartRow + 1;
    1481        1412 :     sal_Int32 nColCount = aRangeAddr.EndColumn - aRangeAddr.StartColumn + 1;
    1482        3258 :     for ( sal_Int32 i=0; i<nRowCount; ++i )
    1483             :     {
    1484       17340 :         for ( sal_Int32 j=0; j<nColCount; ++j )
    1485             :         {
    1486       15494 :             uno::Reference< table::XCell > xCell( mxRange->getCellByPosition( j, i ), uno::UNO_QUERY_THROW );
    1487             : 
    1488       15494 :             visitor.visitNode( i, j, xCell );
    1489       15494 :         }
    1490             :     }
    1491        1412 : }
    1492             : 
    1493             : uno::Any
    1494         956 : ScVbaRange::getValue( ValueGetter& valueGetter) throw (uno::RuntimeException)
    1495             : {
    1496         956 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW );
    1497             :     // single cell range
    1498         956 :     if ( isSingleCellRange() )
    1499             :     {
    1500         894 :         visitArray( valueGetter );
    1501         894 :         return valueGetter.getValue();
    1502             :     }
    1503          62 :     sal_Int32 nRowCount = xColumnRowRange->getRows()->getCount();
    1504          62 :     sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount();
    1505             :     // multi cell range ( return array )
    1506         124 :     Dim2ArrayValueGetter arrayGetter( nRowCount, nColCount, valueGetter );
    1507          62 :     visitArray( arrayGetter );
    1508        1018 :     return uno::makeAny( script::ArrayWrapper( false, arrayGetter.getValue() ) );
    1509             : }
    1510             : 
    1511             : uno::Any SAL_CALL
    1512         876 : ScVbaRange::getValue() throw (uno::RuntimeException, std::exception)
    1513             : {
    1514             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1515             :     // Test is performed only because m_xRange is NOT set to be
    1516             :     // the first range in m_Areas ( to force failure while
    1517             :     // the implementations for each method are being updated )
    1518         876 :     if ( m_Areas->getCount() > 1 )
    1519             :     {
    1520          14 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1521          14 :         return xRange->getValue();
    1522             :     }
    1523             : 
    1524         862 :     CellValueGetter valueGetter;
    1525         862 :     return getValue( valueGetter );
    1526             : 
    1527             : }
    1528             : 
    1529             : void
    1530         456 : ScVbaRange::setValue( const uno::Any& aValue, ValueSetter& valueSetter, bool bFireEvent ) throw (uno::RuntimeException)
    1531             : {
    1532         456 :     uno::TypeClass aClass = aValue.getValueTypeClass();
    1533         456 :     if ( aClass == uno::TypeClass_SEQUENCE )
    1534             :     {
    1535          10 :         uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( mxContext );
    1536          20 :         uno::Any aConverted;
    1537             :         try
    1538             :         {
    1539             :             // test for single dimension, could do
    1540             :             // with a better test than this
    1541          10 :             if ( aValue.getValueTypeName().indexOf('[') ==  aValue.getValueTypeName().lastIndexOf('[') )
    1542             :             {
    1543           6 :                 aConverted = xConverter->convertTo( aValue, getCppuType((uno::Sequence< uno::Any >*)0) );
    1544           6 :                 Dim1ArrayValueSetter setter( aConverted, valueSetter );
    1545           6 :                 visitArray( setter );
    1546             :             }
    1547             :             else
    1548             :             {
    1549           4 :                 aConverted = xConverter->convertTo( aValue, getCppuType((uno::Sequence< uno::Sequence< uno::Any > >*)0) );
    1550           4 :                 Dim2ArrayValueSetter setter( aConverted, valueSetter );
    1551           4 :                 visitArray( setter );
    1552             :             }
    1553             :         }
    1554           0 :         catch ( const uno::Exception& e )
    1555             :         {
    1556             :             OSL_TRACE("Bahhh, caught exception %s",
    1557             :                 OUStringToOString( e.Message,
    1558             :                     RTL_TEXTENCODING_UTF8 ).getStr() );
    1559          10 :         }
    1560             :     }
    1561             :     else
    1562             :     {
    1563         446 :         visitArray( valueSetter );
    1564             :     }
    1565         456 :     if( bFireEvent ) fireChangeEvent();
    1566         456 : }
    1567             : 
    1568             : void SAL_CALL
    1569         444 : ScVbaRange::setValue( const uno::Any  &aValue ) throw (uno::RuntimeException, std::exception)
    1570             : {
    1571             :     // If this is a multiple selection apply setValue over all areas
    1572         444 :     if ( m_Areas->getCount() > 1 )
    1573             :     {
    1574          18 :         AreasVisitor aVisitor( m_Areas );
    1575          36 :         RangeValueProcessor valueProcessor( aValue );
    1576          18 :         aVisitor.visit( valueProcessor );
    1577         480 :         return;
    1578             :     }
    1579         426 :     CellValueSetter valueSetter( aValue );
    1580         426 :     setValue( aValue, valueSetter, true );
    1581             : }
    1582             : 
    1583             : void SAL_CALL
    1584         106 : ScVbaRange::Clear() throw (uno::RuntimeException, std::exception)
    1585             : {
    1586             :     using namespace ::com::sun::star::sheet::CellFlags;
    1587         106 :     sal_Int32 nFlags = VALUE | DATETIME | STRING | FORMULA | HARDATTR | EDITATTR | FORMATTED;
    1588         106 :     ClearContents( nFlags, true );
    1589         106 : }
    1590             : 
    1591             : //helper ClearContent
    1592             : void
    1593         154 : ScVbaRange::ClearContents( sal_Int32 nFlags, bool bFireEvent ) throw (uno::RuntimeException)
    1594             : {
    1595             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1596             :     // Test is performed only because m_xRange is NOT set to be
    1597             :     // the first range in m_Areas ( to force failure while
    1598             :     // the implementations for each method are being updated )
    1599         154 :     if ( m_Areas->getCount() > 1 )
    1600             :     {
    1601          14 :         sal_Int32 nItems = m_Areas->getCount();
    1602          42 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    1603             :         {
    1604          28 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    1605          28 :             ScVbaRange* pRange = getImplementation( xRange );
    1606          28 :             if ( pRange )
    1607          28 :                 pRange->ClearContents( nFlags, false ); // do not fire for single ranges
    1608          28 :         }
    1609             :         // fire change event for the entire range list
    1610          14 :         if( bFireEvent ) fireChangeEvent();
    1611          28 :         return;
    1612             :     }
    1613             : 
    1614         140 :     uno::Reference< sheet::XSheetOperation > xSheetOperation(mxRange, uno::UNO_QUERY_THROW);
    1615         140 :     xSheetOperation->clearContents( nFlags );
    1616         140 :     if( bFireEvent ) fireChangeEvent();
    1617             : }
    1618             : 
    1619             : void SAL_CALL
    1620           0 : ScVbaRange::ClearComments() throw (uno::RuntimeException, std::exception)
    1621             : {
    1622           0 :     ClearContents( sheet::CellFlags::ANNOTATION, false );
    1623           0 : }
    1624             : 
    1625             : void SAL_CALL
    1626          18 : ScVbaRange::ClearContents() throw (uno::RuntimeException, std::exception)
    1627             : {
    1628             :     using namespace ::com::sun::star::sheet::CellFlags;
    1629          18 :     sal_Int32 nFlags = VALUE | DATETIME | STRING | FORMULA;
    1630          18 :     ClearContents( nFlags, true );
    1631          18 : }
    1632             : 
    1633             : void SAL_CALL
    1634           2 : ScVbaRange::ClearFormats() throw (uno::RuntimeException, std::exception)
    1635             : {
    1636             :         // FIXME: need to check if we need to combine FORMATTED
    1637             :     using namespace ::com::sun::star::sheet::CellFlags;
    1638           2 :         sal_Int32 nFlags = HARDATTR | FORMATTED | EDITATTR;
    1639           2 :         ClearContents( nFlags, false );
    1640           2 : }
    1641             : 
    1642             : void
    1643          32 : ScVbaRange::setFormulaValue( const uno::Any& rFormula, formula::FormulaGrammar::Grammar eGram, bool bFireEvent ) throw (uno::RuntimeException)
    1644             : {
    1645             :     // If this is a multiple selection apply setFormula over all areas
    1646          32 :     if ( m_Areas->getCount() > 1 )
    1647             :     {
    1648           2 :         AreasVisitor aVisitor( m_Areas );
    1649           4 :         RangeFormulaProcessor valueProcessor( rFormula );
    1650           2 :         aVisitor.visit( valueProcessor );
    1651          36 :         return;
    1652             :     }
    1653          30 :     CellFormulaValueSetter formulaValueSetter( rFormula, &getScDocument(), eGram );
    1654          30 :     setValue( rFormula, formulaValueSetter, bFireEvent );
    1655             : }
    1656             : 
    1657             : uno::Any
    1658          96 : ScVbaRange::getFormulaValue( formula::FormulaGrammar::Grammar eGram ) throw (uno::RuntimeException)
    1659             : {
    1660             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1661             :     // Test is performed only because m_xRange is NOT set to be
    1662             :     // the first range in m_Areas ( to force failure while
    1663             :     // the implementations for each method are being updated )
    1664          96 :     if ( m_Areas->getCount() > 1 )
    1665             :     {
    1666           2 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1667           2 :         return xRange->getFormula();
    1668             :     }
    1669          94 :     CellFormulaValueGetter valueGetter( &getScDocument(), eGram );
    1670          94 :     return getValue( valueGetter );
    1671             : 
    1672             : }
    1673             : 
    1674             : void
    1675          28 : ScVbaRange::setFormula(const uno::Any &rFormula ) throw (uno::RuntimeException, std::exception)
    1676             : {
    1677             :     // #FIXME converting "=$a$1" e.g. CONV_XL_A1 -> CONV_OOO                            // results in "=$a$1:a1", temporalily disable conversion
    1678          28 :     setFormulaValue( rFormula,formula::FormulaGrammar::GRAM_NATIVE_XL_A1, true );
    1679          28 : }
    1680             : 
    1681             : uno::Any
    1682          10 : ScVbaRange::getFormulaR1C1() throw (::com::sun::star::uno::RuntimeException, std::exception)
    1683             : {
    1684          10 :     return getFormulaValue( formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1 );
    1685             : }
    1686             : 
    1687             : void
    1688           4 : ScVbaRange::setFormulaR1C1(const uno::Any& rFormula ) throw (uno::RuntimeException, std::exception)
    1689             : {
    1690           4 :     setFormulaValue( rFormula,formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1, true );
    1691           4 : }
    1692             : 
    1693             : uno::Any
    1694          86 : ScVbaRange::getFormula() throw (::com::sun::star::uno::RuntimeException, std::exception)
    1695             : {
    1696          86 :     return getFormulaValue( formula::FormulaGrammar::GRAM_NATIVE_XL_A1 );
    1697             : }
    1698             : 
    1699             : sal_Int32
    1700         126 : ScVbaRange::getCount() throw (uno::RuntimeException, std::exception)
    1701             : {
    1702             :     // If this is a multiple selection apply setValue over all areas
    1703         126 :     if ( m_Areas->getCount() > 1 )
    1704             :     {
    1705          22 :         AreasVisitor aVisitor( m_Areas );
    1706          44 :         RangeCountProcessor valueProcessor;
    1707          22 :         aVisitor.visit( valueProcessor );
    1708          44 :         return valueProcessor.value();
    1709             :     }
    1710         104 :     sal_Int32 rowCount = 0;
    1711         104 :     sal_Int32 colCount = 0;
    1712         104 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW );
    1713         104 :     rowCount = xColumnRowRange->getRows()->getCount();
    1714         104 :     colCount = xColumnRowRange->getColumns()->getCount();
    1715             : 
    1716         104 :     if( IsRows() )
    1717          56 :         return rowCount;
    1718          48 :     if( IsColumns() )
    1719          22 :         return colCount;
    1720          26 :     return rowCount * colCount;
    1721             : }
    1722             : 
    1723             : sal_Int32
    1724        1444 : ScVbaRange::getRow() throw (uno::RuntimeException, std::exception)
    1725             : {
    1726             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1727             :     // Test is performed only because m_xRange is NOT set to be
    1728             :     // the first range in m_Areas ( to force failure while
    1729             :     // the implementations for each method are being updated )
    1730        1444 :     if ( m_Areas->getCount() > 1 )
    1731             :     {
    1732          10 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1733          10 :         return xRange->getRow();
    1734             :     }
    1735        1434 :     uno::Reference< sheet::XCellAddressable > xCellAddressable(mxRange->getCellByPosition(0, 0), uno::UNO_QUERY_THROW );
    1736        1434 :     return xCellAddressable->getCellAddress().Row + 1; // Zero value indexing
    1737             : }
    1738             : 
    1739             : sal_Int32
    1740        1444 : ScVbaRange::getColumn() throw (uno::RuntimeException, std::exception)
    1741             : {
    1742             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1743             :     // Test is performed only because m_xRange is NOT set to be
    1744             :     // the first range in m_Areas ( to force failure while
    1745             :     // the implementations for each method are being updated )
    1746        1444 :     if ( m_Areas->getCount() > 1 )
    1747             :     {
    1748          10 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1749          10 :         return xRange->getColumn();
    1750             :     }
    1751        1434 :     uno::Reference< sheet::XCellAddressable > xCellAddressable(mxRange->getCellByPosition(0, 0), uno::UNO_QUERY_THROW );
    1752        1434 :     return xCellAddressable->getCellAddress().Column + 1; // Zero value indexing
    1753             : }
    1754             : 
    1755             : uno::Any
    1756          64 : ScVbaRange::HasFormula() throw (uno::RuntimeException, std::exception)
    1757             : {
    1758          64 :     if ( m_Areas->getCount() > 1 )
    1759             :     {
    1760          16 :         sal_Int32 nItems = m_Areas->getCount();
    1761          16 :         uno::Any aResult = aNULL();
    1762          40 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    1763             :         {
    1764          28 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    1765             :             // if the HasFormula for any area is different to another
    1766             :             // return null
    1767          28 :             if ( index > 1 )
    1768          12 :                 if ( aResult != xRange->HasFormula() )
    1769           0 :                     return aNULL();
    1770          28 :             aResult = xRange->HasFormula();
    1771          28 :             if ( aNULL() == aResult )
    1772           4 :                 return aNULL();
    1773          24 :         }
    1774          12 :         return aResult;
    1775             :     }
    1776          48 :     uno::Reference< uno::XInterface > xIf( mxRange, uno::UNO_QUERY_THROW );
    1777          48 :     ScCellRangesBase* pThisRanges = dynamic_cast< ScCellRangesBase * > ( xIf.get() );
    1778          48 :     if ( pThisRanges )
    1779             :     {
    1780          48 :         uno::Reference<uno::XInterface>  xRanges( pThisRanges->queryFormulaCells( ( sheet::FormulaResult::ERROR | sheet::FormulaResult::VALUE |  sheet::FormulaResult::STRING ) ), uno::UNO_QUERY_THROW );
    1781          48 :         ScCellRangesBase* pFormulaRanges = dynamic_cast< ScCellRangesBase * > ( xRanges.get() );
    1782             :         // check if there are no formula cell, return false
    1783          48 :         if ( pFormulaRanges->GetRangeList().empty() )
    1784          28 :             return uno::makeAny(sal_False);
    1785             : 
    1786             :         // chech if there are holes (where some cells are not formulas)
    1787             :         // or returned range is not equal to this range
    1788          40 :         if (  ( pFormulaRanges->GetRangeList().size() > 1 )
    1789          20 :            || ( pFormulaRanges->GetRangeList().front()->aStart != pThisRanges->GetRangeList().front()->aStart )
    1790          36 :            || ( pFormulaRanges->GetRangeList().front()->aEnd   != pThisRanges->GetRangeList().front()->aEnd   )
    1791             :            )
    1792           4 :             return aNULL(); // should return aNULL;
    1793             :     }
    1794          16 :     return uno::makeAny( sal_True );
    1795             : }
    1796             : void
    1797          26 : ScVbaRange::fillSeries( sheet::FillDirection nFillDirection, sheet::FillMode nFillMode, sheet::FillDateMode nFillDateMode, double fStep, double fEndValue ) throw( uno::RuntimeException )
    1798             : {
    1799          26 :     if ( m_Areas->getCount() > 1 )
    1800             :     {
    1801             :         // Multi-Area Range
    1802           8 :         uno::Reference< XCollection > xCollection( m_Areas, uno::UNO_QUERY_THROW );
    1803          24 :         for ( sal_Int32 index = 1; index <= xCollection->getCount(); ++index )
    1804             :         {
    1805          16 :             uno::Reference< excel::XRange > xRange( xCollection->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW );
    1806          16 :             ScVbaRange* pThisRange = getImplementation( xRange );
    1807          16 :             pThisRange->fillSeries( nFillDirection, nFillMode, nFillDateMode, fStep, fEndValue );
    1808             : 
    1809          16 :         }
    1810          34 :         return;
    1811             :     }
    1812             : 
    1813          18 :     uno::Reference< sheet::XCellSeries > xCellSeries(mxRange, uno::UNO_QUERY_THROW );
    1814          18 :     xCellSeries->fillSeries( nFillDirection, nFillMode, nFillDateMode, fStep, fEndValue );
    1815          18 :     fireChangeEvent();
    1816             : }
    1817             : 
    1818             : void
    1819           2 : ScVbaRange::FillLeft() throw (uno::RuntimeException, std::exception)
    1820             : {
    1821             :     fillSeries(sheet::FillDirection_TO_LEFT,
    1822           2 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1823           2 : }
    1824             : 
    1825             : void
    1826           4 : ScVbaRange::FillRight() throw (uno::RuntimeException, std::exception)
    1827             : {
    1828             :     fillSeries(sheet::FillDirection_TO_RIGHT,
    1829           4 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1830           4 : }
    1831             : 
    1832             : void
    1833           2 : ScVbaRange::FillUp() throw (uno::RuntimeException, std::exception)
    1834             : {
    1835             :     fillSeries(sheet::FillDirection_TO_TOP,
    1836           2 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1837           2 : }
    1838             : 
    1839             : void
    1840           2 : ScVbaRange::FillDown() throw (uno::RuntimeException, std::exception)
    1841             : {
    1842             :     fillSeries(sheet::FillDirection_TO_BOTTOM,
    1843           2 :         sheet::FillMode_SIMPLE, sheet::FillDateMode_FILL_DATE_DAY, 0, 0x7FFFFFFF);
    1844           2 : }
    1845             : 
    1846             : OUString
    1847          72 : ScVbaRange::getText() throw (uno::RuntimeException, std::exception)
    1848             : {
    1849             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1850             :     // Test is performed only because m_xRange is NOT set to be
    1851             :     // the first range in m_Areas ( to force failure while
    1852             :     // the implementations for each method are being updated )
    1853          72 :     if ( m_Areas->getCount() > 1 )
    1854             :     {
    1855          28 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1856          28 :         return xRange->getText();
    1857             :     }
    1858          44 :     uno::Reference< text::XTextRange > xTextRange(mxRange->getCellByPosition(0,0), uno::UNO_QUERY_THROW );
    1859          44 :     return xTextRange->getString();
    1860             : }
    1861             : 
    1862             : uno::Reference< excel::XRange >
    1863           4 : ScVbaRange::Offset( const ::uno::Any &nRowOff, const uno::Any &nColOff ) throw (uno::RuntimeException, std::exception)
    1864             : {
    1865           4 :     SCROW nRowOffset = 0;
    1866           4 :     SCCOL nColOffset = 0;
    1867           4 :     bool bIsRowOffset = ( nRowOff >>= nRowOffset );
    1868           4 :     bool bIsColumnOffset = ( nColOff >>= nColOffset );
    1869           4 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    1870             : 
    1871           4 :     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    1872             : 
    1873          12 :     for ( size_t i = 0, nRanges = aCellRanges.size(); i < nRanges; ++i )
    1874             :     {
    1875           8 :         ScRange* pRange = aCellRanges[ i ];
    1876           8 :         if ( bIsColumnOffset )
    1877             :         {
    1878           8 :             pRange->aStart.SetCol( pRange->aStart.Col() + nColOffset );
    1879           8 :             pRange->aEnd.SetCol( pRange->aEnd.Col() + nColOffset );
    1880             :         }
    1881           8 :         if ( bIsRowOffset )
    1882             :         {
    1883           8 :             pRange->aStart.SetRow( pRange->aStart.Row() + nRowOffset );
    1884           8 :             pRange->aEnd.SetRow( pRange->aEnd.Row() + nRowOffset );
    1885             :         }
    1886             :     }
    1887             : 
    1888           4 :     if ( aCellRanges.size() > 1 ) // Multi-Area
    1889             :     {
    1890           4 :         uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pUnoRangesBase->GetDocShell(), aCellRanges ) );
    1891           4 :         return new ScVbaRange( mxParent, mxContext, xRanges );
    1892             :     }
    1893             :     // normal range
    1894           0 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), *aCellRanges.front() ) );
    1895           4 :     return new ScVbaRange( mxParent, mxContext, xRange  );
    1896             : }
    1897             : 
    1898             : uno::Reference< excel::XRange >
    1899          16 : ScVbaRange::CurrentRegion() throw (uno::RuntimeException, std::exception)
    1900             : {
    1901             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1902             :     // Test is performed only because m_xRange is NOT set to be
    1903             :     // the first range in m_Areas ( to force failure while
    1904             :     // the implementations for each method are being updated )
    1905          16 :     if ( m_Areas->getCount() > 1 )
    1906             :     {
    1907           0 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1908           0 :         return xRange->CurrentRegion();
    1909             :     }
    1910             : 
    1911          16 :     RangeHelper helper( mxRange );
    1912             :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor =
    1913          32 :         helper.getSheetCellCursor();
    1914          16 :     xSheetCellCursor->collapseToCurrentRegion();
    1915          32 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    1916          32 :     return RangeHelper::createRangeFromRange( mxParent, mxContext, helper.getCellRangeFromSheet(), xCellRangeAddressable );
    1917             : }
    1918             : 
    1919             : uno::Reference< excel::XRange >
    1920           0 : ScVbaRange::CurrentArray() throw (uno::RuntimeException, std::exception)
    1921             : {
    1922             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1923             :     // Test is performed only because m_xRange is NOT set to be
    1924             :     // the first range in m_Areas ( to force failure while
    1925             :     // the implementations for each method are being updated )
    1926           0 :     if ( m_Areas->getCount() > 1 )
    1927             :     {
    1928           0 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1929           0 :         return xRange->CurrentArray();
    1930             :     }
    1931           0 :     RangeHelper helper( mxRange );
    1932             :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor =
    1933           0 :         helper.getSheetCellCursor();
    1934           0 :     xSheetCellCursor->collapseToCurrentArray();
    1935           0 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    1936           0 :     return RangeHelper::createRangeFromRange( mxParent, mxContext, helper.getCellRangeFromSheet(), xCellRangeAddressable );
    1937             : }
    1938             : 
    1939             : uno::Any
    1940           4 : ScVbaRange::getFormulaArray() throw (uno::RuntimeException, std::exception)
    1941             : {
    1942             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1943             :     // Test is performed only because m_xRange is NOT set to be
    1944             :     // the first range in m_Areas ( to force failure while
    1945             :     // the implementations for each method are being updated )
    1946           4 :     if ( m_Areas->getCount() > 1 )
    1947             :     {
    1948           2 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1949           2 :         return xRange->getFormulaArray();
    1950             :     }
    1951             : 
    1952             :     // return a formula if there is one or else an array
    1953             :     // still not sure when the return as array code should run
    1954             :     // ( I think it is if there is more than one formula ) at least
    1955             :     // that is what the doc says ( but I am not even sure how to detect that )
    1956             :     // for the moment any tests we have pass
    1957           2 :     uno::Reference< sheet::XArrayFormulaRange> xFormulaArray( mxRange, uno::UNO_QUERY_THROW );
    1958           2 :     if ( xFormulaArray.is() && !xFormulaArray->getArrayFormula().isEmpty() )
    1959           0 :         return uno::makeAny( xFormulaArray->getArrayFormula() );
    1960             : 
    1961           4 :     uno::Reference< sheet::XCellRangeFormula> xCellRangeFormula( mxRange, uno::UNO_QUERY_THROW );
    1962           4 :     uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( mxContext );
    1963           4 :     uno::Any aSingleValueOrMatrix;
    1964             :     // When dealing with a single element ( embedded in the sequence of sequence ) unwrap and return
    1965             :     // that value
    1966           4 :     uno::Sequence< uno::Sequence<rtl::OUString> > aTmpSeq = xCellRangeFormula->getFormulaArray();
    1967           2 :     if ( aTmpSeq.getLength() == 1 )
    1968             :     {
    1969           0 :         if ( aTmpSeq[ 0 ].getLength() == 1  )
    1970           0 :             aSingleValueOrMatrix <<= aTmpSeq[ 0 ][ 0 ];
    1971             :     }
    1972             :     else
    1973           2 :         aSingleValueOrMatrix = xConverter->convertTo( uno::makeAny( aTmpSeq ) , getCppuType((uno::Sequence< uno::Sequence< uno::Any > >*)0)  ) ;
    1974           4 :     return aSingleValueOrMatrix;
    1975             : }
    1976             : 
    1977             : void
    1978           4 : ScVbaRange::setFormulaArray(const uno::Any& rFormula) throw (uno::RuntimeException, std::exception)
    1979             : {
    1980             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    1981             :     // Test is performed only because m_xRange is NOT set to be
    1982             :     // the first range in m_Areas ( to force failure while
    1983             :     // the implementations for each method are being updated )
    1984           4 :     if ( m_Areas->getCount() > 1 )
    1985             :     {
    1986           2 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    1987           6 :         return xRange->setFormulaArray( rFormula );
    1988             :     }
    1989             :     // #TODO need to distinguish between getFormula and getFormulaArray e.g. (R1C1)
    1990             :     // but for the moment its just easier to treat them the same for setting
    1991             :     // seems
    1992           2 :     uno::Reference< lang::XMultiServiceFactory > xModelFactory( getUnoModel(), uno::UNO_QUERY_THROW );
    1993           4 :     uno::Reference< sheet::XFormulaParser > xParser( xModelFactory->createInstance( "com.sun.star.sheet.FormulaParser" ), uno::UNO_QUERY_THROW );
    1994           4 :     uno::Reference< sheet::XCellRangeAddressable > xSource( mxRange, uno::UNO_QUERY_THROW);
    1995             : 
    1996           2 :     table::CellRangeAddress aRangeAddress = xSource->getRangeAddress();
    1997             :     // #TODO check if api orders the address
    1998             :     // e.g. do we need to order the RangeAddress to get the topleft ( or can we assume it
    1999             :     // is in the correct order )
    2000           2 :     table::CellAddress aAddress;
    2001           2 :     aAddress.Sheet = aRangeAddress.Sheet;
    2002           2 :     aAddress.Column = aRangeAddress.StartColumn;
    2003           2 :     aAddress.Row = aRangeAddress.StartRow;
    2004           4 :     OUString sFormula;
    2005           2 :     rFormula >>= sFormula;
    2006           4 :     uno::Sequence<sheet::FormulaToken> aTokens = xParser->parseFormula( sFormula, aAddress );
    2007           4 :     ScTokenArray aTokenArray;
    2008           2 :     (void)ScTokenConversion::ConvertToTokenArray( getScDocument(), aTokenArray, aTokens );
    2009             : 
    2010           4 :     getScDocShell()->GetDocFunc().EnterMatrix( *getScRangeList()[0], NULL, &aTokenArray, OUString(), true, true, EMPTY_OUSTRING, formula::FormulaGrammar::GRAM_PODF_A1 );
    2011             : }
    2012             : 
    2013             : OUString
    2014           0 : ScVbaRange::Characters(const uno::Any& Start, const uno::Any& Length) throw (uno::RuntimeException, std::exception)
    2015             : {
    2016             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    2017             :     // Test is performed only because m_xRange is NOT set to be
    2018             :     // the first range in m_Areas ( to force failure while
    2019             :     // the implementations for each method are being updated )
    2020           0 :     if ( m_Areas->getCount() > 1 )
    2021             :     {
    2022           0 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    2023           0 :         return xRange->Characters( Start, Length );
    2024             :     }
    2025             : 
    2026           0 :     long nIndex = 0, nCount = 0;
    2027           0 :     OUString rString;
    2028           0 :     uno::Reference< text::XTextRange > xTextRange(mxRange, ::uno::UNO_QUERY_THROW );
    2029           0 :     rString = xTextRange->getString();
    2030           0 :     if( !( Start >>= nIndex ) && !( Length >>= nCount ) )
    2031           0 :         return rString;
    2032           0 :     if(!( Start >>= nIndex ) )
    2033           0 :         nIndex = 1;
    2034           0 :     if(!( Length >>= nCount ) )
    2035           0 :         nIndex = rString.getLength();
    2036           0 :     return rString.copy( --nIndex, nCount ); // Zero value indexing
    2037             : }
    2038             : 
    2039             : OUString
    2040         618 : ScVbaRange::Address(  const uno::Any& RowAbsolute, const uno::Any& ColumnAbsolute, const uno::Any& ReferenceStyle, const uno::Any& External, const uno::Any& RelativeTo ) throw (uno::RuntimeException, std::exception)
    2041             : {
    2042         618 :     if ( m_Areas->getCount() > 1 )
    2043             :     {
    2044             :         // Multi-Area Range
    2045          82 :         OUString sAddress;
    2046         164 :         uno::Reference< XCollection > xCollection( m_Areas, uno::UNO_QUERY_THROW );
    2047         164 :                 uno::Any aExternalCopy = External;
    2048         256 :         for ( sal_Int32 index = 1; index <= xCollection->getCount(); ++index )
    2049             :         {
    2050         174 :             uno::Reference< excel::XRange > xRange( xCollection->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW );
    2051         174 :             if ( index > 1 )
    2052             :             {
    2053          92 :                 sAddress += OUString( ',' );
    2054             :                                 // force external to be false
    2055             :                                 // only first address should have the
    2056             :                                 // document and sheet specifications
    2057          92 :                                 aExternalCopy = uno::makeAny(sal_False);
    2058             :             }
    2059         174 :             sAddress += xRange->Address( RowAbsolute, ColumnAbsolute, ReferenceStyle, aExternalCopy, RelativeTo );
    2060         174 :         }
    2061         164 :         return sAddress;
    2062             : 
    2063             :     }
    2064         536 :     ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2065         536 :     if ( ReferenceStyle.hasValue() )
    2066             :     {
    2067          28 :         sal_Int32 refStyle = excel::XlReferenceStyle::xlA1;
    2068          28 :         ReferenceStyle >>= refStyle;
    2069          28 :         if ( refStyle == excel::XlReferenceStyle::xlR1C1 )
    2070          28 :             dDetails = ScAddress::Details( formula::FormulaGrammar::CONV_XL_R1C1, 0, 0 );
    2071             :     }
    2072         536 :     sal_uInt16 nFlags = SCA_VALID;
    2073         536 :     ScDocShell* pDocShell =  getScDocShell();
    2074         536 :     ScDocument& rDoc =  pDocShell->GetDocument();
    2075             : 
    2076         536 :     RangeHelper thisRange( mxRange );
    2077         536 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    2078         536 :     ScRange aRange( static_cast< SCCOL >( thisAddress.StartColumn ), static_cast< SCROW >( thisAddress.StartRow ), static_cast< SCTAB >( thisAddress.Sheet ), static_cast< SCCOL >( thisAddress.EndColumn ), static_cast< SCROW >( thisAddress.EndRow ), static_cast< SCTAB >( thisAddress.Sheet ) );
    2079         536 :     sal_uInt16 ROW_ABSOLUTE = ( SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE );
    2080         536 :     sal_uInt16 COL_ABSOLUTE = ( SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE );
    2081             :     // default
    2082         536 :     nFlags |= ( SCA_TAB_ABSOLUTE | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB2_ABSOLUTE | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE );
    2083         536 :     if ( RowAbsolute.hasValue() )
    2084             :     {
    2085           2 :         bool bVal = true;
    2086           2 :         RowAbsolute >>= bVal;
    2087           2 :         if ( !bVal )
    2088           2 :             nFlags &= ~ROW_ABSOLUTE;
    2089             :     }
    2090         536 :     if ( ColumnAbsolute.hasValue() )
    2091             :     {
    2092           2 :         bool bVal = true;
    2093           2 :         ColumnAbsolute >>= bVal;
    2094           2 :         if ( !bVal )
    2095           2 :             nFlags &= ~COL_ABSOLUTE;
    2096             :     }
    2097         536 :     bool bLocal = false;
    2098         536 :     if ( External.hasValue() )
    2099             :     {
    2100         102 :         External >>= bLocal;
    2101         102 :         if (  bLocal )
    2102          10 :             nFlags |= SCA_TAB_3D | SCA_FORCE_DOC;
    2103             :     }
    2104         536 :     if ( RelativeTo.hasValue() )
    2105             :     {
    2106             :         // #TODO should I throw an error if R1C1 is not set?
    2107             : 
    2108           0 :         table::CellRangeAddress refAddress = getCellRangeAddressForVBARange( RelativeTo, pDocShell );
    2109           0 :         dDetails = ScAddress::Details( formula::FormulaGrammar::CONV_XL_R1C1, static_cast< SCROW >( refAddress.StartRow ), static_cast< SCCOL >( refAddress.StartColumn ) );
    2110             :     }
    2111         536 :     return aRange.Format(nFlags, &rDoc, dDetails);
    2112             : }
    2113             : 
    2114             : uno::Reference < excel::XFont >
    2115          20 : ScVbaRange::Font() throw ( script::BasicErrorException, uno::RuntimeException)
    2116             : {
    2117          20 :     uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY );
    2118          20 :     ScDocument& rDoc = getScDocument();
    2119          20 :     if ( mxRange.is() )
    2120           2 :         xProps.set(mxRange, ::uno::UNO_QUERY );
    2121          18 :     else if ( mxRanges.is() )
    2122          18 :         xProps.set(mxRanges, ::uno::UNO_QUERY );
    2123             : 
    2124          20 :     ScVbaPalette aPalette( rDoc.GetDocumentShell() );
    2125          20 :     ScCellRangeObj* pRangeObj = NULL;
    2126             :     try
    2127             :     {
    2128          20 :         pRangeObj = getCellRangeObj();
    2129             :     }
    2130           0 :     catch( uno::Exception& )
    2131             :     {
    2132             :     }
    2133          20 :     return  new ScVbaFont( this, mxContext, aPalette, xProps, pRangeObj );
    2134             : }
    2135             : 
    2136             : uno::Reference< excel::XRange >
    2137          66 : ScVbaRange::Cells( const uno::Any &nRowIndex, const uno::Any &nColumnIndex ) throw(uno::RuntimeException, std::exception)
    2138             : {
    2139             :     // #TODO code within the test below "if ( m_Areas.... " can be removed
    2140             :     // Test is performed only because m_xRange is NOT set to be
    2141             :     // the first range in m_Areas ( to force failure while
    2142             :     // the implementations for each method are being updated )
    2143          66 :     if ( m_Areas->getCount() > 1 )
    2144             :     {
    2145          16 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    2146          16 :         return xRange->Cells( nRowIndex, nColumnIndex );
    2147             :     }
    2148             : 
    2149             :     // Performance: Use a common helper method for ScVbaRange::Cells and ScVbaWorksheet::Cells,
    2150             :     // instead of creating a new ScVbaRange object in often-called ScVbaWorksheet::Cells
    2151          50 :     return CellsHelper( mxParent, mxContext, mxRange, nRowIndex, nColumnIndex );
    2152             : }
    2153             : 
    2154             : // static
    2155             : uno::Reference< excel::XRange >
    2156          60 : ScVbaRange::CellsHelper( const uno::Reference< ov::XHelperInterface >& xParent,
    2157             :                          const uno::Reference< uno::XComponentContext >& xContext,
    2158             :                          const uno::Reference< css::table::XCellRange >& xRange,
    2159             :                          const uno::Any &nRowIndex, const uno::Any &nColumnIndex ) throw(uno::RuntimeException)
    2160             : {
    2161          60 :     sal_Int32 nRow = 0, nColumn = 0;
    2162             : 
    2163          60 :     bool bIsIndex = nRowIndex.hasValue();
    2164          60 :     bool bIsColumnIndex = nColumnIndex.hasValue();
    2165             : 
    2166             :     // Sometimes we might get a float or a double or whatever
    2167             :     // set in the Any, we should convert as appropriate
    2168             :     // #FIXME - perhaps worth turning this into some sort of
    2169             :     // conversion routine e.g. bSuccess = getValueFromAny( nRow, nRowIndex, cppu::UnoType<sal_Int32>::get() )
    2170          60 :     uno::Any aRowIndexAny = nRowIndex;
    2171          60 :     if ( aRowIndexAny.hasValue() && !( aRowIndexAny >>= nRow ) )
    2172             :     {
    2173           0 :         uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( xContext );
    2174           0 :         uno::Any aConverted;
    2175             :         try
    2176             :         {
    2177           0 :             aConverted = xConverter->convertTo( aRowIndexAny, cppu::UnoType<sal_Int32>::get() );
    2178           0 :             bIsIndex = ( aConverted >>= nRow );
    2179             :         }
    2180           0 :         catch( uno::Exception& ) {} // silence any errors
    2181             :     }
    2182             : 
    2183         120 :     uno::Any aColumnAny = nColumnIndex;
    2184             : 
    2185          60 :     if ( bIsColumnIndex )
    2186             :     {
    2187             :          // Column index can be a col address e.g Cells( 1, "B" ) etc.
    2188          42 :         OUString sCol;
    2189          42 :         if ( nColumnIndex >>= sCol )
    2190             :         {
    2191           0 :             ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2192           0 :             ScRange tmpRange;
    2193           0 :             sal_uInt16 flags = tmpRange.ParseCols( sCol, &getDocumentFromRange( xRange ), dDetails );
    2194           0 :             if ( ( flags & 0x200 ) != 0x200 )
    2195           0 :                throw uno::RuntimeException();
    2196           0 :             nColumn = tmpRange.aStart.Col() + 1;
    2197             :         }
    2198             :         else
    2199             :         {
    2200          42 :             if ( !( aColumnAny >>= nColumn ) )
    2201             :             {
    2202           0 :                 uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( xContext );
    2203           0 :                 uno::Any aConverted;
    2204             :                 try
    2205             :                 {
    2206           0 :                     aConverted = xConverter->convertTo( aColumnAny, cppu::UnoType<sal_Int32>::get() );
    2207           0 :                     bIsColumnIndex = ( aConverted >>= nColumn );
    2208             :                 }
    2209           0 :                 catch( uno::Exception& ) {} // silence any errors
    2210             :             }
    2211          42 :        }
    2212             :     }
    2213         120 :     RangeHelper thisRange( xRange );
    2214          60 :     table::CellRangeAddress thisRangeAddress =  thisRange.getCellRangeAddressable()->getRangeAddress();
    2215         120 :     uno::Reference< table::XCellRange > xSheetRange = thisRange.getCellRangeFromSheet();
    2216          60 :     if( !bIsIndex && !bIsColumnIndex ) // .Cells
    2217             :         // #FIXE needs proper parent ( Worksheet )
    2218           4 :         return uno::Reference< excel::XRange >( new ScVbaRange( xParent, xContext, xRange ) );
    2219             : 
    2220          56 :     sal_Int32 nIndex = --nRow;
    2221          56 :     if( bIsIndex && !bIsColumnIndex ) // .Cells(n)
    2222             :     {
    2223          14 :         uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, ::uno::UNO_QUERY_THROW);
    2224          14 :         sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount();
    2225             : 
    2226          14 :         if ( !nIndex || nIndex < 0 )
    2227           8 :             nRow = 0;
    2228             :         else
    2229           6 :             nRow = nIndex / nColCount;
    2230          14 :         nColumn = nIndex % nColCount;
    2231             :     }
    2232             :     else
    2233          42 :         --nColumn;
    2234          56 :     nRow = nRow + thisRangeAddress.StartRow;
    2235          56 :     nColumn =  nColumn + thisRangeAddress.StartColumn;
    2236         116 :     return new ScVbaRange( xParent, xContext, xSheetRange->getCellRangeByPosition( nColumn, nRow, nColumn, nRow ) );
    2237             : }
    2238             : 
    2239             : void
    2240         112 : ScVbaRange::Select() throw (uno::RuntimeException, std::exception)
    2241             : {
    2242         112 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2243         112 :     if ( !pUnoRangesBase )
    2244           0 :         throw uno::RuntimeException("Failed to access underlying uno range object"  );
    2245         112 :     ScDocShell* pShell = pUnoRangesBase->GetDocShell();
    2246         112 :     if ( pShell )
    2247             :     {
    2248         112 :         uno::Reference< frame::XModel > xModel( pShell->GetModel(), uno::UNO_QUERY_THROW );
    2249         224 :         uno::Reference< view::XSelectionSupplier > xSelection( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
    2250         112 :         if ( mxRanges.is() )
    2251           6 :             xSelection->select( uno::Any( lclExpandToMerged( mxRanges, true ) ) );
    2252             :         else
    2253         106 :             xSelection->select( uno::Any( lclExpandToMerged( mxRange, true ) ) );
    2254             :         // set focus on document e.g.
    2255             :         // ThisComponent.CurrentController.Frame.getContainerWindow.SetFocus
    2256             :         try
    2257             :         {
    2258         112 :             uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
    2259         224 :             uno::Reference< frame::XFrame > xFrame( xController->getFrame(), uno::UNO_QUERY_THROW );
    2260         224 :             uno::Reference< awt::XWindow > xWin( xFrame->getContainerWindow(), uno::UNO_QUERY_THROW );
    2261         224 :             xWin->setFocus();
    2262             :         }
    2263           0 :         catch( uno::Exception& )
    2264             :         {
    2265         112 :         }
    2266             :     }
    2267         112 : }
    2268             : 
    2269           8 : bool cellInRange( const table::CellRangeAddress& rAddr, const sal_Int32& nCol, const sal_Int32& nRow )
    2270             : {
    2271          12 :     if ( nCol >= rAddr.StartColumn && nCol <= rAddr.EndColumn &&
    2272           6 :         nRow >= rAddr.StartRow && nRow <= rAddr.EndRow )
    2273           2 :         return true;
    2274           6 :     return false;
    2275             : }
    2276             : 
    2277           6 : void setCursor(  const SCCOL& nCol, const SCROW& nRow, const uno::Reference< frame::XModel >& xModel,  bool bInSel = true )
    2278             : {
    2279           6 :     ScTabViewShell* pShell = excel::getBestViewShell( xModel );
    2280           6 :     if ( pShell )
    2281             :     {
    2282           6 :         if ( bInSel )
    2283           2 :             pShell->SetCursor( nCol, nRow );
    2284             :         else
    2285           4 :             pShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_NONE, false, false, true, false );
    2286             :     }
    2287           6 : }
    2288             : 
    2289             : void
    2290           8 : ScVbaRange::Activate() throw (uno::RuntimeException, std::exception)
    2291             : {
    2292             :     // get first cell of current range
    2293           8 :     uno::Reference< table::XCellRange > xCellRange;
    2294           8 :     if ( mxRanges.is() )
    2295             :     {
    2296           2 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW  );
    2297           2 :         xCellRange.set( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
    2298             :     }
    2299             :     else
    2300           6 :         xCellRange.set( mxRange, uno::UNO_QUERY_THROW );
    2301             : 
    2302          16 :     RangeHelper thisRange( xCellRange );
    2303          16 :     uno::Reference< sheet::XCellRangeAddressable > xThisRangeAddress = thisRange.getCellRangeAddressable();
    2304           8 :     table::CellRangeAddress thisRangeAddress = xThisRangeAddress->getRangeAddress();
    2305          16 :         uno::Reference< frame::XModel > xModel;
    2306           8 :         ScDocShell* pShell = getScDocShell();
    2307             : 
    2308           8 :         if ( pShell )
    2309           8 :             xModel = pShell->GetModel();
    2310             : 
    2311           8 :         if ( !xModel.is() )
    2312           0 :             throw uno::RuntimeException();
    2313             : 
    2314             :     // get current selection
    2315          16 :     uno::Reference< sheet::XCellRangeAddressable > xRange( xModel->getCurrentSelection(), ::uno::UNO_QUERY);
    2316             : 
    2317          16 :     uno::Reference< sheet::XSheetCellRanges > xRanges( xModel->getCurrentSelection(), ::uno::UNO_QUERY);
    2318             : 
    2319           8 :     if ( xRanges.is() )
    2320             :     {
    2321           0 :         uno::Sequence< table::CellRangeAddress > nAddrs = xRanges->getRangeAddresses();
    2322           0 :         for ( sal_Int32 index = 0; index < nAddrs.getLength(); ++index )
    2323             :         {
    2324           0 :             if ( cellInRange( nAddrs[index], thisRangeAddress.StartColumn, thisRangeAddress.StartRow ) )
    2325             :             {
    2326           0 :                 setCursor( static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), xModel );
    2327           8 :                 return;
    2328             :             }
    2329             : 
    2330           0 :         }
    2331             :     }
    2332             : 
    2333           8 :     if ( xRange.is() && cellInRange( xRange->getRangeAddress(), thisRangeAddress.StartColumn, thisRangeAddress.StartRow ) )
    2334           2 :         setCursor( static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), xModel );
    2335             :     else
    2336             :     {
    2337             :         // if this range is multi cell select the range other
    2338             :         // wise just position the cell at this single range position
    2339           6 :         if ( isSingleCellRange() )
    2340             :             // This top-leftmost cell of this Range is not in the current
    2341             :             // selection so just select this range
    2342           4 :             setCursor( static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), xModel, false  );
    2343             :         else
    2344           2 :             Select();
    2345           8 :     }
    2346             : 
    2347             : }
    2348             : 
    2349             : uno::Reference< excel::XRange >
    2350         166 : ScVbaRange::Rows(const uno::Any& aIndex ) throw (uno::RuntimeException, std::exception)
    2351             : {
    2352         166 :     OUString sAddress;
    2353             : 
    2354         166 :     if ( aIndex.hasValue() )
    2355             :     {
    2356          54 :         sal_Int32 nValue = 0;
    2357          54 :         ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2358          54 :         ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    2359             : 
    2360          54 :         ScRange aRange = *aCellRanges.front();
    2361          54 :         if( aIndex >>= nValue )
    2362             :         {
    2363          46 :             aRange.aStart.SetRow( aRange.aStart.Row() + --nValue );
    2364          46 :             aRange.aEnd.SetRow( aRange.aStart.Row() );
    2365             :         }
    2366           8 :         else if ( aIndex >>= sAddress )
    2367             :         {
    2368           8 :             ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2369           8 :             ScRange tmpRange;
    2370           8 :             tmpRange.ParseRows( sAddress, &getDocumentFromRange( mxRange ), dDetails );
    2371           8 :             SCROW nStartRow = tmpRange.aStart.Row();
    2372           8 :             SCROW nEndRow = tmpRange.aEnd.Row();
    2373             : 
    2374           8 :             aRange.aStart.SetRow( aRange.aStart.Row() + nStartRow );
    2375           8 :             aRange.aEnd.SetRow( aRange.aStart.Row() + ( nEndRow  - nStartRow ));
    2376             :         }
    2377             :         else
    2378           0 :             throw uno::RuntimeException("Illegal param" );
    2379             : 
    2380          54 :         if ( aRange.aStart.Row() < 0 || aRange.aEnd.Row() < 0 )
    2381           0 :             throw uno::RuntimeException("Internal failure, illegal param" );
    2382             :         // return a normal range ( even for multi-selection
    2383         108 :         uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange ) );
    2384         108 :         return new ScVbaRange( mxParent, mxContext, xRange, true  );
    2385             :     }
    2386             :     // Rows() - no params
    2387         112 :     if ( m_Areas->getCount() > 1 )
    2388          28 :         return new ScVbaRange(  mxParent, mxContext, mxRanges, true );
    2389          84 :     return new ScVbaRange(  mxParent, mxContext, mxRange, true );
    2390             : }
    2391             : 
    2392             : uno::Reference< excel::XRange >
    2393         142 : ScVbaRange::Columns(const uno::Any& aIndex ) throw (uno::RuntimeException, std::exception)
    2394             : {
    2395         142 :     OUString sAddress;
    2396             : 
    2397         142 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2398         284 :     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    2399             : 
    2400         142 :     ScRange aRange = *aCellRanges.front();
    2401         142 :     if ( aIndex.hasValue() )
    2402             :     {
    2403          60 :         sal_Int32 nValue = 0;
    2404          60 :         if ( aIndex >>= nValue )
    2405             :         {
    2406          34 :             aRange.aStart.SetCol( aRange.aStart.Col() + static_cast< SCCOL > ( --nValue ) );
    2407          34 :             aRange.aEnd.SetCol( aRange.aStart.Col() );
    2408             :         }
    2409             : 
    2410          26 :         else if ( aIndex >>= sAddress )
    2411             :         {
    2412          26 :             ScAddress::Details dDetails( formula::FormulaGrammar::CONV_XL_A1, 0, 0 );
    2413          26 :             ScRange tmpRange;
    2414          26 :             tmpRange.ParseCols( sAddress, &getDocumentFromRange( mxRange ), dDetails );
    2415          26 :             SCCOL nStartCol = tmpRange.aStart.Col();
    2416          26 :             SCCOL nEndCol = tmpRange.aEnd.Col();
    2417             : 
    2418          26 :             aRange.aStart.SetCol( aRange.aStart.Col() + nStartCol );
    2419          26 :             aRange.aEnd.SetCol( aRange.aStart.Col() + ( nEndCol  - nStartCol ));
    2420             :         }
    2421             :         else
    2422           0 :             throw uno::RuntimeException("Illegal param" );
    2423             : 
    2424          60 :         if ( aRange.aStart.Col() < 0 || aRange.aEnd.Col() < 0 )
    2425           0 :             throw uno::RuntimeException("Internal failure, illegal param" );
    2426             :     }
    2427             :     // Columns() - no params
    2428         284 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange ) );
    2429         284 :     return new ScVbaRange( mxParent, mxContext, xRange, false, true  );
    2430             : }
    2431             : 
    2432             : void
    2433           4 : ScVbaRange::setMergeCells( const uno::Any& aIsMerged ) throw (script::BasicErrorException, uno::RuntimeException)
    2434             : {
    2435           4 :     bool bMerge = extractBoolFromAny( aIsMerged );
    2436             : 
    2437           4 :     if( mxRanges.is() )
    2438             :     {
    2439           0 :         sal_Int32 nCount = mxRanges->getCount();
    2440             : 
    2441             :         // VBA does nothing (no error) if the own ranges overlap somehow
    2442           0 :         ::std::vector< table::CellRangeAddress > aList;
    2443           0 :         for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    2444             :         {
    2445           0 :             uno::Reference< sheet::XCellRangeAddressable > xRangeAddr( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    2446           0 :             table::CellRangeAddress aAddress = xRangeAddr->getRangeAddress();
    2447           0 :             for( ::std::vector< table::CellRangeAddress >::const_iterator aIt = aList.begin(), aEnd = aList.end(); aIt != aEnd; ++aIt )
    2448           0 :                 if( ScUnoConversion::Intersects( *aIt, aAddress ) )
    2449           0 :                     return;
    2450           0 :             aList.push_back( aAddress );
    2451           0 :         }
    2452             : 
    2453             :         // (un)merge every range after it has been extended to intersecting merged ranges from sheet
    2454           0 :         for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    2455             :         {
    2456           0 :             uno::Reference< table::XCellRange > xRange( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    2457           0 :             lclExpandAndMerge( xRange, bMerge );
    2458           0 :         }
    2459           0 :         return;
    2460             :     }
    2461             : 
    2462             :     // otherwise, merge single range
    2463           4 :     lclExpandAndMerge( mxRange, bMerge );
    2464             : }
    2465             : 
    2466             : uno::Any
    2467          84 : ScVbaRange::getMergeCells() throw (script::BasicErrorException, uno::RuntimeException)
    2468             : {
    2469          84 :     if( mxRanges.is() )
    2470             :     {
    2471          12 :         sal_Int32 nCount = mxRanges->getCount();
    2472          28 :         for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
    2473             :         {
    2474          20 :             uno::Reference< table::XCellRange > xRange( mxRanges->getByIndex( nIndex ), uno::UNO_QUERY_THROW );
    2475          20 :             util::TriState eMerged = lclGetMergedState( xRange );
    2476             :             /*  Excel always returns NULL, if one range of the range list is
    2477             :                 partly or completely merged. Even if all ranges are completely
    2478             :                 merged, the return value is still NULL. */
    2479          20 :             if( eMerged != util::TriState_NO )
    2480           4 :                 return aNULL();
    2481          16 :         }
    2482             :         // no range is merged anyhow, return false
    2483           8 :         return uno::Any( false );
    2484             :     }
    2485             : 
    2486             :     // otherwise, check single range
    2487          72 :     switch( lclGetMergedState( mxRange ) )
    2488             :     {
    2489          28 :         case util::TriState_YES:    return uno::Any( true );
    2490          44 :         case util::TriState_NO:     return uno::Any( false );
    2491           0 :         default:                    return aNULL();
    2492             :     }
    2493             : }
    2494             : 
    2495             : void
    2496          24 : ScVbaRange::Copy(const ::uno::Any& Destination) throw (uno::RuntimeException, std::exception)
    2497             : {
    2498          24 :     if ( m_Areas->getCount() > 1 )
    2499           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    2500          24 :     if ( Destination.hasValue() )
    2501             :     {
    2502           2 :         uno::Reference< excel::XRange > xRange( Destination, uno::UNO_QUERY_THROW );
    2503           4 :         uno::Any aRange = xRange->getCellRange();
    2504           4 :         uno::Reference< table::XCellRange > xCellRange;
    2505           2 :         aRange >>= xCellRange;
    2506           4 :         uno::Reference< sheet::XSheetCellRange > xSheetCellRange(xCellRange, ::uno::UNO_QUERY_THROW);
    2507           4 :         uno::Reference< sheet::XSpreadsheet > xSheet = xSheetCellRange->getSpreadsheet();
    2508           4 :         uno::Reference< table::XCellRange > xDest( xSheet, uno::UNO_QUERY_THROW );
    2509           4 :         uno::Reference< sheet::XCellRangeMovement > xMover( xSheet, uno::UNO_QUERY_THROW);
    2510           2 :         uno::Reference< sheet::XCellAddressable > xDestination( xDest->getCellByPosition(
    2511           4 :                                                 xRange->getColumn()-1,xRange->getRow()-1), uno::UNO_QUERY_THROW );
    2512           4 :         uno::Reference< sheet::XCellRangeAddressable > xSource( mxRange, uno::UNO_QUERY);
    2513           2 :         xMover->copyRange( xDestination->getCellAddress(), xSource->getRangeAddress() );
    2514           2 :         if ( ScVbaRange* pRange = getImplementation( xRange ) )
    2515           4 :             pRange->fireChangeEvent();
    2516             :     }
    2517             :     else
    2518             :     {
    2519          22 :         uno::Reference< frame::XModel > xModel = getModelFromRange( mxRange );
    2520          22 :         Select();
    2521          22 :         excel::implnCopy( xModel );
    2522             :     }
    2523          24 : }
    2524             : 
    2525             : void
    2526           2 : ScVbaRange::Cut(const ::uno::Any& Destination) throw (uno::RuntimeException, std::exception)
    2527             : {
    2528           2 :     if ( m_Areas->getCount() > 1 )
    2529           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    2530           2 :     if (Destination.hasValue())
    2531             :     {
    2532           2 :         uno::Reference< excel::XRange > xRange( Destination, uno::UNO_QUERY_THROW );
    2533           4 :         uno::Reference< table::XCellRange > xCellRange( xRange->getCellRange(), uno::UNO_QUERY_THROW );
    2534           4 :         uno::Reference< sheet::XSheetCellRange > xSheetCellRange(xCellRange, ::uno::UNO_QUERY_THROW );
    2535           4 :         uno::Reference< sheet::XSpreadsheet > xSheet = xSheetCellRange->getSpreadsheet();
    2536           4 :         uno::Reference< table::XCellRange > xDest( xSheet, uno::UNO_QUERY_THROW );
    2537           4 :         uno::Reference< sheet::XCellRangeMovement > xMover( xSheet, uno::UNO_QUERY_THROW);
    2538           2 :         uno::Reference< sheet::XCellAddressable > xDestination( xDest->getCellByPosition(
    2539           4 :                                                 xRange->getColumn()-1,xRange->getRow()-1), uno::UNO_QUERY);
    2540           4 :         uno::Reference< sheet::XCellRangeAddressable > xSource( mxRange, uno::UNO_QUERY);
    2541           4 :         xMover->moveRange( xDestination->getCellAddress(), xSource->getRangeAddress() );
    2542             :     }
    2543             :     else
    2544             :     {
    2545           0 :         uno::Reference< frame::XModel > xModel = getModelFromRange( mxRange );
    2546           0 :         Select();
    2547           0 :         excel::implnCut( xModel );
    2548             :     }
    2549           2 : }
    2550             : 
    2551             : void
    2552           4 : ScVbaRange::setNumberFormat( const uno::Any& aFormat ) throw ( script::BasicErrorException, uno::RuntimeException)
    2553             : {
    2554           4 :     OUString sFormat;
    2555           4 :     aFormat >>= sFormat;
    2556           4 :     if ( m_Areas->getCount() > 1 )
    2557             :     {
    2558           0 :         sal_Int32 nItems = m_Areas->getCount();
    2559           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2560             :         {
    2561           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2562           0 :             xRange->setNumberFormat( aFormat );
    2563           0 :         }
    2564           4 :         return;
    2565             :     }
    2566           8 :     NumFormatHelper numFormat( mxRange );
    2567           8 :     numFormat.setNumberFormat( sFormat );
    2568             : }
    2569             : 
    2570             : uno::Any
    2571           6 : ScVbaRange::getNumberFormat() throw ( script::BasicErrorException, uno::RuntimeException)
    2572             : {
    2573             : 
    2574           6 :     if ( m_Areas->getCount() > 1 )
    2575             :     {
    2576           0 :         sal_Int32 nItems = m_Areas->getCount();
    2577           0 :         uno::Any aResult = aNULL();
    2578           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2579             :         {
    2580           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2581             :             // if the numberformat of one area is different to another
    2582             :             // return null
    2583           0 :             if ( index > 1 )
    2584           0 :                 if ( aResult != xRange->getNumberFormat() )
    2585           0 :                     return aNULL();
    2586           0 :             aResult = xRange->getNumberFormat();
    2587           0 :             if ( aNULL() == aResult )
    2588           0 :                 return aNULL();
    2589           0 :         }
    2590           0 :         return aResult;
    2591             :     }
    2592           6 :     NumFormatHelper numFormat( mxRange );
    2593          12 :     OUString sFormat = numFormat.getNumberFormatString();
    2594           6 :     if ( !sFormat.isEmpty() )
    2595           4 :         return uno::makeAny( sFormat );
    2596           8 :     return aNULL();
    2597             : }
    2598             : 
    2599             : uno::Reference< excel::XRange >
    2600           4 : ScVbaRange::Resize( const uno::Any &RowSize, const uno::Any &ColumnSize ) throw (uno::RuntimeException, std::exception)
    2601             : {
    2602           4 :     long nRowSize = 0, nColumnSize = 0;
    2603           4 :     bool bIsRowChanged = ( RowSize >>= nRowSize ), bIsColumnChanged = ( ColumnSize >>= nColumnSize );
    2604           4 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, ::uno::UNO_QUERY_THROW);
    2605           8 :     uno::Reference< sheet::XSheetCellRange > xSheetRange(mxRange, ::uno::UNO_QUERY_THROW);
    2606           8 :     uno::Reference< sheet::XSheetCellCursor > xCursor( xSheetRange->getSpreadsheet()->createCursorByRange(xSheetRange), ::uno::UNO_QUERY_THROW );
    2607             : 
    2608           4 :     if( !bIsRowChanged )
    2609           0 :         nRowSize = xColumnRowRange->getRows()->getCount();
    2610           4 :     if( !bIsColumnChanged )
    2611           0 :         nColumnSize = xColumnRowRange->getColumns()->getCount();
    2612             : 
    2613           4 :     xCursor->collapseToSize( nColumnSize, nRowSize );
    2614           8 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xCursor, ::uno::UNO_QUERY_THROW );
    2615           8 :     uno::Reference< table::XCellRange > xRange( xSheetRange->getSpreadsheet(), ::uno::UNO_QUERY_THROW );
    2616           4 :     return new ScVbaRange( mxParent, mxContext,xRange->getCellRangeByPosition(
    2617           4 :                                         xCellRangeAddressable->getRangeAddress().StartColumn,
    2618           4 :                                         xCellRangeAddressable->getRangeAddress().StartRow,
    2619           4 :                                         xCellRangeAddressable->getRangeAddress().EndColumn,
    2620          24 :                                         xCellRangeAddressable->getRangeAddress().EndRow ) );
    2621             : }
    2622             : 
    2623             : void
    2624          36 : ScVbaRange::setWrapText( const uno::Any& aIsWrapped ) throw (script::BasicErrorException, uno::RuntimeException)
    2625             : {
    2626          36 :     if ( m_Areas->getCount() > 1 )
    2627             :     {
    2628          10 :         sal_Int32 nItems = m_Areas->getCount();
    2629          30 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2630             :         {
    2631          20 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2632          20 :             xRange->setWrapText( aIsWrapped );
    2633          20 :         }
    2634          20 :         return;
    2635             :     }
    2636             : 
    2637          26 :     uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY_THROW );
    2638          26 :     bool bIsWrapped = extractBoolFromAny( aIsWrapped );
    2639          26 :     xProps->setPropertyValue( "IsTextWrapped", uno::Any( bIsWrapped ) );
    2640             : }
    2641             : 
    2642             : uno::Any
    2643          68 : ScVbaRange::getWrapText() throw (script::BasicErrorException, uno::RuntimeException)
    2644             : {
    2645          68 :     if ( m_Areas->getCount() > 1 )
    2646             :     {
    2647          10 :         sal_Int32 nItems = m_Areas->getCount();
    2648          10 :         uno::Any aResult;
    2649          28 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    2650             :         {
    2651          20 :                 uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    2652          20 :                 if ( index > 1 )
    2653          10 :                 if ( aResult != xRange->getWrapText() )
    2654           2 :                     return aNULL();
    2655          18 :             aResult = xRange->getWrapText();
    2656          18 :         }
    2657           8 :         return aResult;
    2658             :     }
    2659             : 
    2660          58 :     SfxItemSet* pDataSet = getCurrentDataSet();
    2661             : 
    2662          58 :     SfxItemState eState = pDataSet->GetItemState( ATTR_LINEBREAK, true, NULL);
    2663          58 :     if ( eState == SfxItemState::DONTCARE )
    2664           2 :         return aNULL();
    2665             : 
    2666          56 :     uno::Reference< beans::XPropertySet > xProps(mxRange, ::uno::UNO_QUERY_THROW );
    2667         112 :     uno::Any aValue = xProps->getPropertyValue( "IsTextWrapped" );
    2668         112 :     return aValue;
    2669             : }
    2670             : 
    2671          18 : uno::Reference< excel::XInterior > ScVbaRange::Interior( ) throw ( script::BasicErrorException, uno::RuntimeException)
    2672             : {
    2673          18 :     uno::Reference< beans::XPropertySet > xProps( mxRange, uno::UNO_QUERY_THROW );
    2674          18 :         return new ScVbaInterior ( this, mxContext, xProps, &getScDocument() );
    2675             : }
    2676             : uno::Reference< excel::XRange >
    2677         264 : ScVbaRange::Range( const uno::Any &Cell1, const uno::Any &Cell2 ) throw (uno::RuntimeException, std::exception)
    2678             : {
    2679         264 :     return Range( Cell1, Cell2, false );
    2680             : }
    2681             : uno::Reference< excel::XRange >
    2682        1394 : ScVbaRange::Range( const uno::Any &Cell1, const uno::Any &Cell2, bool bForceUseInpuRangeTab ) throw (uno::RuntimeException)
    2683             : 
    2684             : {
    2685        1394 :     uno::Reference< table::XCellRange > xCellRange = mxRange;
    2686             : 
    2687        1394 :     if ( m_Areas->getCount() > 1 )
    2688             :     {
    2689           2 :         uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
    2690           2 :         xCellRange.set( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
    2691             :     }
    2692             :     else
    2693        1392 :         xCellRange.set( mxRange );
    2694             : 
    2695        2788 :     RangeHelper thisRange( xCellRange );
    2696        2788 :     uno::Reference< table::XCellRange > xRanges = thisRange.getCellRangeFromSheet();
    2697        2788 :     uno::Reference< sheet::XCellRangeAddressable > xAddressable( xRanges, uno::UNO_QUERY_THROW );
    2698             : 
    2699             :     uno::Reference< table::XCellRange > xReferrer =
    2700        4182 :         xRanges->getCellRangeByPosition( getColumn()-1, getRow()-1,
    2701        1394 :                 xAddressable->getRangeAddress().EndColumn,
    2702        6970 :                 xAddressable->getRangeAddress().EndRow );
    2703             :     // xAddressable now for this range
    2704        1394 :     xAddressable.set( xReferrer, uno::UNO_QUERY_THROW );
    2705             : 
    2706        1394 :     if( !Cell1.hasValue() )
    2707           0 :         throw uno::RuntimeException( "Invalid Argument" );
    2708             : 
    2709        1394 :     table::CellRangeAddress resultAddress;
    2710        1394 :     table::CellRangeAddress parentRangeAddress = xAddressable->getRangeAddress();
    2711             : 
    2712        1394 :     ScRange aRange;
    2713             :     // Cell1 defined only
    2714        1394 :     if ( !Cell2.hasValue() )
    2715             :     {
    2716        1382 :         OUString sName;
    2717        1382 :         Cell1 >>= sName;
    2718        2764 :         RangeHelper referRange( xReferrer );
    2719        1382 :         table::CellRangeAddress referAddress = referRange.getCellRangeAddressable()->getRangeAddress();
    2720        2764 :         return getRangeForName( mxContext, sName, getScDocShell(), referAddress );
    2721             : 
    2722             :     }
    2723             :     else
    2724             :     {
    2725          12 :         table::CellRangeAddress  cell1, cell2;
    2726          12 :         cell1 = getCellRangeAddressForVBARange( Cell1, getScDocShell() );
    2727             :         // Cell1 & Cell2 defined
    2728             :         // Excel seems to combine the range as the range defined by
    2729             :         // the combination of Cell1 & Cell2
    2730             : 
    2731          12 :         cell2 = getCellRangeAddressForVBARange( Cell2, getScDocShell() );
    2732             : 
    2733          12 :         resultAddress.StartColumn = ( cell1.StartColumn <  cell2.StartColumn ) ? cell1.StartColumn : cell2.StartColumn;
    2734          12 :         resultAddress.StartRow = ( cell1.StartRow <  cell2.StartRow ) ? cell1.StartRow : cell2.StartRow;
    2735          12 :         resultAddress.EndColumn = ( cell1.EndColumn >  cell2.EndColumn ) ? cell1.EndColumn : cell2.EndColumn;
    2736          12 :         resultAddress.EndRow = ( cell1.EndRow >  cell2.EndRow ) ? cell1.EndRow : cell2.EndRow;
    2737          12 :         if ( bForceUseInpuRangeTab )
    2738             :         {
    2739             :             // this is a call from Application.Range( x,y )
    2740             :             // its possiblefor x or y to specify a different sheet from
    2741             :             // the current or active on ( but they must be the same )
    2742           4 :             if ( cell1.Sheet != cell2.Sheet )
    2743           0 :                 throw uno::RuntimeException();
    2744           4 :             parentRangeAddress.Sheet = cell1.Sheet;
    2745             :         }
    2746             :         else
    2747             :         {
    2748             :             // this is not a call from Application.Range( x,y )
    2749             :             // if a different sheet from this range is specified it's
    2750             :             // an error
    2751           8 :             if ( parentRangeAddress.Sheet != cell1.Sheet
    2752           6 :             || parentRangeAddress.Sheet != cell2.Sheet
    2753             :             )
    2754           2 :                 throw uno::RuntimeException();
    2755             : 
    2756             :         }
    2757          10 :         ScUnoConversion::FillScRange( aRange, resultAddress );
    2758             :     }
    2759          10 :     ScRange parentAddress;
    2760          10 :     ScUnoConversion::FillScRange( parentAddress, parentRangeAddress);
    2761          10 :     if ( aRange.aStart.Col() >= 0 && aRange.aStart.Row() >= 0 && aRange.aEnd.Col() >= 0 && aRange.aEnd.Row() >= 0 )
    2762             :     {
    2763          10 :         sal_Int32 nStartX = parentAddress.aStart.Col() + aRange.aStart.Col();
    2764          10 :         sal_Int32 nStartY = parentAddress.aStart.Row() + aRange.aStart.Row();
    2765          10 :         sal_Int32 nEndX = parentAddress.aStart.Col() + aRange.aEnd.Col();
    2766          10 :         sal_Int32 nEndY = parentAddress.aStart.Row() + aRange.aEnd.Row();
    2767             : 
    2768          20 :         if ( nStartX <= nEndX && nEndX <= parentAddress.aEnd.Col() &&
    2769          20 :              nStartY <= nEndY && nEndY <= parentAddress.aEnd.Row() )
    2770             :         {
    2771          10 :             ScRange aNew( (SCCOL)nStartX, (SCROW)nStartY, parentAddress.aStart.Tab(),
    2772          20 :                           (SCCOL)nEndX, (SCROW)nEndY, parentAddress.aEnd.Tab() );
    2773          10 :             xCellRange = new ScCellRangeObj( getScDocShell(), aNew );
    2774             :         }
    2775             :     }
    2776             : 
    2777        1404 :     return new ScVbaRange( mxParent, mxContext, xCellRange );
    2778             : 
    2779             : }
    2780             : 
    2781             : // Allow access to underlying openoffice uno api ( useful for debugging
    2782             : // with openoffice basic )
    2783         742 : uno::Any SAL_CALL ScVbaRange::getCellRange(  ) throw (uno::RuntimeException, std::exception)
    2784             : {
    2785         742 :     uno::Any aAny;
    2786         742 :     if ( mxRanges.is() )
    2787           0 :         aAny <<= mxRanges;
    2788         742 :     else if ( mxRange.is() )
    2789         742 :         aAny <<= mxRange;
    2790         742 :     return aAny;
    2791             : }
    2792             : 
    2793         574 : uno::Any ScVbaRange::getCellRange( const uno::Reference< excel::XRange >& rxRange ) throw (uno::RuntimeException)
    2794             : {
    2795         574 :     if( ScVbaRange* pVbaRange = getImplementation( rxRange ) )
    2796        1148 :         return pVbaRange->getCellRange();
    2797           0 :     throw uno::RuntimeException();
    2798             : }
    2799             : 
    2800          24 : static InsertDeleteFlags getPasteFlags (sal_Int32 Paste)
    2801             : {
    2802          24 :     InsertDeleteFlags nFlags = IDF_NONE;
    2803          24 :     switch (Paste) {
    2804             :         case excel::XlPasteType::xlPasteComments:
    2805           0 :         nFlags = IDF_NOTE;break;
    2806             :         case excel::XlPasteType::xlPasteFormats:
    2807           2 :         nFlags = IDF_ATTRIB;break;
    2808             :         case excel::XlPasteType::xlPasteFormulas:
    2809           2 :         nFlags = IDF_FORMULA;break;
    2810             :         case excel::XlPasteType::xlPasteFormulasAndNumberFormats :
    2811             :         case excel::XlPasteType::xlPasteValues:
    2812           2 :         nFlags = ( IDF_VALUE | IDF_DATETIME | IDF_STRING | IDF_SPECIAL_BOOLEAN ); break;
    2813             :         case excel::XlPasteType::xlPasteValuesAndNumberFormats:
    2814           0 :         nFlags = IDF_VALUE | IDF_ATTRIB; break;
    2815             :         case excel::XlPasteType::xlPasteColumnWidths:
    2816             :         case excel::XlPasteType::xlPasteValidation:
    2817           0 :         nFlags = IDF_NONE;break;
    2818             :     case excel::XlPasteType::xlPasteAll:
    2819             :         case excel::XlPasteType::xlPasteAllExceptBorders:
    2820             :     default:
    2821          18 :         nFlags = IDF_ALL;break;
    2822             :     }
    2823          24 :     return nFlags;
    2824             : }
    2825             : 
    2826             : static sal_uInt16
    2827          24 : getPasteFormulaBits( sal_Int32 Operation)
    2828             : {
    2829          24 :     sal_uInt16 nFormulaBits = PASTE_NOFUNC ;
    2830          24 :     switch (Operation)
    2831             :     {
    2832             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationAdd:
    2833           2 :         nFormulaBits = PASTE_ADD;break;
    2834             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationSubtract:
    2835           2 :         nFormulaBits = PASTE_SUB;break;
    2836             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationMultiply:
    2837           2 :         nFormulaBits = PASTE_MUL;break;
    2838             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationDivide:
    2839           2 :         nFormulaBits = PASTE_DIV;break;
    2840             : 
    2841             :     case excel::XlPasteSpecialOperation::xlPasteSpecialOperationNone:
    2842             :     default:
    2843          16 :         nFormulaBits = PASTE_NOFUNC; break;
    2844             :     }
    2845             : 
    2846          24 : return nFormulaBits;
    2847             : }
    2848             : void SAL_CALL
    2849          24 : ScVbaRange::PasteSpecial( const uno::Any& Paste, const uno::Any& Operation, const uno::Any& SkipBlanks, const uno::Any& Transpose ) throw (::com::sun::star::uno::RuntimeException, std::exception)
    2850             : {
    2851          24 :     if ( m_Areas->getCount() > 1 )
    2852           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    2853          24 :     ScDocShell* pShell = getScDocShell();
    2854             : 
    2855          24 :     if (!pShell)
    2856           0 :         throw uno::RuntimeException("That command cannot be used with no ScDocShell" );
    2857             : 
    2858          24 :     uno::Reference< frame::XModel > xModel(pShell->GetModel(), uno::UNO_QUERY_THROW);
    2859          48 :     uno::Reference< view::XSelectionSupplier > xSelection( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
    2860             :     // select this range
    2861          24 :     xSelection->select( uno::makeAny( mxRange ) );
    2862             :     // set up defaults
    2863          24 :     sal_Int32 nPaste = excel::XlPasteType::xlPasteAll;
    2864          24 :     sal_Int32 nOperation = excel::XlPasteSpecialOperation::xlPasteSpecialOperationNone;
    2865          24 :     bool bTranspose = false;
    2866          24 :     bool bSkipBlanks = false;
    2867             : 
    2868          24 :     if ( Paste.hasValue() )
    2869           6 :         Paste >>= nPaste;
    2870          24 :     if ( Operation.hasValue() )
    2871           8 :         Operation >>= nOperation;
    2872          24 :     if ( SkipBlanks.hasValue() )
    2873           2 :         SkipBlanks >>= bSkipBlanks;
    2874          24 :     if ( Transpose.hasValue() )
    2875           2 :         Transpose >>= bTranspose;
    2876             : 
    2877          24 :     InsertDeleteFlags nFlags = getPasteFlags(nPaste);
    2878          24 :     sal_uInt16 nFormulaBits = getPasteFormulaBits(nOperation);
    2879          48 :     excel::implnPasteSpecial(pShell->GetModel(), nFlags,nFormulaBits,bSkipBlanks,bTranspose);
    2880          24 : }
    2881             : 
    2882             : uno::Reference< excel::XRange >
    2883          36 : ScVbaRange::getEntireColumnOrRow( bool bColumn ) throw (uno::RuntimeException)
    2884             : {
    2885          36 :     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
    2886             :     // copy the range list
    2887          36 :     ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
    2888             : 
    2889          90 :     for ( size_t i = 0, nRanges = aCellRanges.size(); i < nRanges; ++i )
    2890             :     {
    2891          54 :         ScRange* pRange = aCellRanges[ i ];
    2892          54 :         if ( bColumn )
    2893             :         {
    2894          28 :             pRange->aStart.SetRow( 0 );
    2895          28 :             pRange->aEnd.SetRow( MAXROW );
    2896             :         }
    2897             :         else
    2898             :         {
    2899          26 :             pRange->aStart.SetCol( 0 );
    2900          26 :             pRange->aEnd.SetCol( MAXCOL );
    2901             :         }
    2902             :     }
    2903          36 :     if ( aCellRanges.size() > 1 ) // Multi-Area
    2904             :     {
    2905          18 :         uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( pUnoRangesBase->GetDocShell(), aCellRanges ) );
    2906             : 
    2907          18 :         return new ScVbaRange( mxParent, mxContext, xRanges, !bColumn, bColumn );
    2908             :     }
    2909          36 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), *aCellRanges.front() ) );
    2910          54 :     return new ScVbaRange( mxParent, mxContext, xRange, !bColumn, bColumn  );
    2911             : }
    2912             : 
    2913             : uno::Reference< excel::XRange > SAL_CALL
    2914          18 : ScVbaRange::getEntireRow() throw (uno::RuntimeException, std::exception)
    2915             : {
    2916          18 :     return getEntireColumnOrRow(false);
    2917             : }
    2918             : 
    2919             : uno::Reference< excel::XRange > SAL_CALL
    2920          18 : ScVbaRange::getEntireColumn() throw (uno::RuntimeException, std::exception)
    2921             : {
    2922          18 :     return getEntireColumnOrRow();
    2923             : }
    2924             : 
    2925             : uno::Reference< excel::XComment > SAL_CALL
    2926           0 : ScVbaRange::AddComment( const uno::Any& Text ) throw (uno::RuntimeException, std::exception)
    2927             : {
    2928             :     // if there is already a comment in the top-left cell then throw
    2929           0 :     if( getComment().is() )
    2930           0 :         throw uno::RuntimeException();
    2931             : 
    2932             :     // workaround: Excel allows to create empty comment, Calc does not
    2933           0 :     OUString aNoteText;
    2934           0 :     if( Text.hasValue() && !(Text >>= aNoteText) )
    2935           0 :         throw uno::RuntimeException();
    2936           0 :     if( aNoteText.isEmpty() )
    2937           0 :         aNoteText = OUString( ' ' );
    2938             : 
    2939             :     // try to create a new annotation
    2940           0 :     table::CellRangeAddress aRangePos = lclGetRangeAddress( mxRange );
    2941           0 :     table::CellAddress aNotePos( aRangePos.Sheet, aRangePos.StartColumn, aRangePos.StartRow );
    2942           0 :     uno::Reference< sheet::XSheetCellRange > xCellRange( mxRange, uno::UNO_QUERY_THROW );
    2943           0 :     uno::Reference< sheet::XSheetAnnotationsSupplier > xAnnosSupp( xCellRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
    2944           0 :     uno::Reference< sheet::XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), uno::UNO_SET_THROW );
    2945           0 :     xAnnos->insertNew( aNotePos, aNoteText );
    2946           0 :     return new ScVbaComment( this, mxContext, getUnoModel(), mxRange );
    2947             : }
    2948             : 
    2949             : uno::Reference< excel::XComment > SAL_CALL
    2950           0 : ScVbaRange::getComment() throw (uno::RuntimeException, std::exception)
    2951             : {
    2952             :     // intentional behavior to return a null object if no
    2953             :     // comment defined
    2954           0 :     uno::Reference< excel::XComment > xComment( new ScVbaComment( this, mxContext, getUnoModel(), mxRange ) );
    2955           0 :     if ( xComment->Text( uno::Any(), uno::Any(), uno::Any() ).isEmpty() )
    2956           0 :         return NULL;
    2957           0 :     return xComment;
    2958             : 
    2959             : }
    2960             : 
    2961             : uno::Reference< beans::XPropertySet >
    2962         174 : getRowOrColumnProps( const uno::Reference< table::XCellRange >& xCellRange, bool bRows ) throw ( uno::RuntimeException )
    2963             : {
    2964         174 :     uno::Reference< table::XColumnRowRange > xColRow( xCellRange, uno::UNO_QUERY_THROW );
    2965         174 :     uno::Reference< beans::XPropertySet > xProps;
    2966         174 :     if ( bRows )
    2967         106 :         xProps.set( xColRow->getRows(), uno::UNO_QUERY_THROW );
    2968             :     else
    2969          68 :         xProps.set( xColRow->getColumns(), uno::UNO_QUERY_THROW );
    2970         174 :     return xProps;
    2971             : }
    2972             : 
    2973             : uno::Any SAL_CALL
    2974         142 : ScVbaRange::getHidden() throw (uno::RuntimeException, std::exception)
    2975             : {
    2976             :     // if multi-area result is the result of the
    2977             :     // first area
    2978         142 :     if ( m_Areas->getCount() > 1 )
    2979             :     {
    2980           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(sal_Int32(1)), uno::Any() ), uno::UNO_QUERY_THROW );
    2981           0 :         return xRange->getHidden();
    2982             :     }
    2983         142 :     bool bIsVisible = false;
    2984             :     try
    2985             :     {
    2986         142 :         uno::Reference< beans::XPropertySet > xProps = getRowOrColumnProps( mxRange, mbIsRows );
    2987         142 :         if ( !( xProps->getPropertyValue( ISVISIBLE ) >>= bIsVisible ) )
    2988           0 :             throw uno::RuntimeException("Failed to get IsVisible property" );
    2989             :     }
    2990           0 :     catch( const uno::Exception& e )
    2991             :     {
    2992           0 :         throw uno::RuntimeException( e.Message );
    2993             :     }
    2994         142 :     return uno::makeAny( !bIsVisible );
    2995             : }
    2996             : 
    2997             : void SAL_CALL
    2998          32 : ScVbaRange::setHidden( const uno::Any& _hidden ) throw (uno::RuntimeException, std::exception)
    2999             : {
    3000          32 :     if ( m_Areas->getCount() > 1 )
    3001             :     {
    3002           0 :         sal_Int32 nItems = m_Areas->getCount();
    3003           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    3004             :         {
    3005           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    3006           0 :             xRange->setHidden( _hidden );
    3007           0 :         }
    3008          32 :         return;
    3009             :     }
    3010             : 
    3011          32 :     bool bHidden = extractBoolFromAny( _hidden );
    3012             :     try
    3013             :     {
    3014          32 :         uno::Reference< beans::XPropertySet > xProps = getRowOrColumnProps( mxRange, mbIsRows );
    3015          32 :         xProps->setPropertyValue( ISVISIBLE, uno::Any( !bHidden ) );
    3016             :     }
    3017           0 :     catch( const uno::Exception& e )
    3018             :     {
    3019           0 :         throw uno::RuntimeException( e.Message );
    3020             :     }
    3021             : }
    3022             : 
    3023             : sal_Bool SAL_CALL
    3024          50 : ScVbaRange::Replace( const OUString& What, const OUString& Replacement, const uno::Any& LookAt, const uno::Any& SearchOrder, const uno::Any& MatchCase, const uno::Any& MatchByte, const uno::Any& SearchFormat, const uno::Any& ReplaceFormat  ) throw (uno::RuntimeException, std::exception)
    3025             : {
    3026          50 :     if ( m_Areas->getCount() > 1 )
    3027             :     {
    3028          42 :         for ( sal_Int32 index = 1; index <= m_Areas->getCount(); ++index )
    3029             :         {
    3030          28 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( index ), uno::Any() ), uno::UNO_QUERY_THROW );
    3031          28 :             xRange->Replace( What, Replacement,  LookAt, SearchOrder, MatchCase, MatchByte, SearchFormat, ReplaceFormat );
    3032          28 :         }
    3033          14 :         return sal_True; // seems to return true always ( or at least I haven't found the trick of
    3034             :     }
    3035             : 
    3036             :     // sanity check required params
    3037          36 :     if ( What.isEmpty()  )
    3038           0 :         throw uno::RuntimeException("Range::Replace, missing params" );
    3039          36 :     OUString sWhat = VBAToRegexp( What);
    3040             :     // #TODO #FIXME SearchFormat & ReplacesFormat are not processed
    3041             :     // What do we do about MatchByte.. we don't seem to support that
    3042          36 :     const SvxSearchItem& globalSearchOptions = ScGlobal::GetSearchItem();
    3043          72 :     SvxSearchItem newOptions( globalSearchOptions );
    3044             : 
    3045          36 :     sal_Int16 nLook =  globalSearchOptions.GetWordOnly() ?  excel::XlLookAt::xlPart : excel::XlLookAt::xlWhole;
    3046          36 :     sal_Int16 nSearchOrder = globalSearchOptions.GetRowDirection() ? excel::XlSearchOrder::xlByRows : excel::XlSearchOrder::xlByColumns;
    3047             : 
    3048          36 :     bool bMatchCase = false;
    3049          72 :     uno::Reference< util::XReplaceable > xReplace( mxRange, uno::UNO_QUERY );
    3050          36 :     if ( xReplace.is() )
    3051             :     {
    3052             :         uno::Reference< util::XReplaceDescriptor > xDescriptor =
    3053          36 :             xReplace->createReplaceDescriptor();
    3054             : 
    3055          36 :         xDescriptor->setSearchString( sWhat);
    3056          36 :         xDescriptor->setPropertyValue( SC_UNO_SRCHREGEXP, uno::makeAny( sal_True ) );
    3057          36 :         xDescriptor->setReplaceString( Replacement);
    3058          36 :         if ( LookAt.hasValue() )
    3059             :         {
    3060             :             // sets SearchWords ( true is Cell match )
    3061          12 :             nLook =  ::comphelper::getINT16( LookAt );
    3062          12 :             bool bSearchWords = false;
    3063          12 :             if ( nLook == excel::XlLookAt::xlPart )
    3064           8 :                 bSearchWords = false;
    3065           4 :             else if ( nLook == excel::XlLookAt::xlWhole )
    3066           4 :                 bSearchWords = true;
    3067             :             else
    3068           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for LookAt" );
    3069             :             // set global search props ( affects the find dialog
    3070             :             // and of course the defaults for this method
    3071          12 :             newOptions.SetWordOnly( bSearchWords );
    3072          12 :             xDescriptor->setPropertyValue( SC_UNO_SRCHWORDS, uno::makeAny( bSearchWords ) );
    3073             :         }
    3074             :         // sets SearchByRow ( true for Rows )
    3075          36 :         if ( SearchOrder.hasValue() )
    3076             :         {
    3077          34 :             nSearchOrder =  ::comphelper::getINT16( SearchOrder );
    3078          34 :             bool bSearchByRow = false;
    3079          34 :             if ( nSearchOrder == excel::XlSearchOrder::xlByColumns )
    3080          34 :                 bSearchByRow = false;
    3081           0 :             else if ( nSearchOrder == excel::XlSearchOrder::xlByRows )
    3082           0 :                 bSearchByRow = true;
    3083             :             else
    3084           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for SearchOrder" );
    3085             : 
    3086          34 :             newOptions.SetRowDirection( bSearchByRow );
    3087          34 :             xDescriptor->setPropertyValue( SC_UNO_SRCHBYROW, uno::makeAny( bSearchByRow ) );
    3088             :         }
    3089          36 :         if ( MatchCase.hasValue() )
    3090             :         {
    3091             :             // SearchCaseSensitive
    3092          34 :             MatchCase >>= bMatchCase;
    3093          34 :             xDescriptor->setPropertyValue( SC_UNO_SRCHCASE, uno::makeAny( bMatchCase ) );
    3094             :         }
    3095             : 
    3096          36 :         ScGlobal::SetSearchItem( newOptions );
    3097             :         // ignore MatchByte for the moment, its not supported in
    3098             :         // OOo.org afaik
    3099             : 
    3100          72 :         uno::Reference< util::XSearchDescriptor > xSearch( xDescriptor, uno::UNO_QUERY );
    3101          72 :         uno::Reference< container::XIndexAccess > xIndexAccess = xReplace->findAll( xSearch );
    3102          36 :         xReplace->replaceAll( xSearch );
    3103          36 :         if ( xIndexAccess.is() && xIndexAccess->getCount() > 0 )
    3104             :         {
    3105          64 :             for ( sal_Int32 i = 0; i < xIndexAccess->getCount(); ++i )
    3106             :             {
    3107          36 :                 uno::Reference< table::XCellRange > xCellRange( xIndexAccess->getByIndex( i ), uno::UNO_QUERY );
    3108          36 :                 if ( xCellRange.is() )
    3109             :                 {
    3110          36 :                     uno::Reference< excel::XRange > xRange( new ScVbaRange( mxParent, mxContext, xCellRange ) );
    3111          72 :                     uno::Reference< container::XEnumerationAccess > xEnumAccess( xRange, uno::UNO_QUERY_THROW );
    3112          72 :                     uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
    3113         610 :                     while ( xEnum->hasMoreElements() )
    3114             :                     {
    3115         538 :                         uno::Reference< excel::XRange > xNextRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
    3116         538 :                         ScVbaRange* pRange = dynamic_cast< ScVbaRange * > ( xNextRange.get() );
    3117         538 :                         if ( pRange )
    3118         538 :                             pRange->fireChangeEvent();
    3119         574 :                     }
    3120             :                 }
    3121          36 :             }
    3122          36 :         }
    3123             :     }
    3124          72 :     return sal_True; // always
    3125             : }
    3126             : 
    3127             : uno::Reference< excel::XRange > SAL_CALL
    3128           0 : ScVbaRange::Find( const uno::Any& What, const uno::Any& After, const uno::Any& LookIn, const uno::Any& LookAt, const uno::Any& SearchOrder, const uno::Any& SearchDirection, const uno::Any& MatchCase, const uno::Any& /*MatchByte*/, const uno::Any& /*SearchFormat*/ ) throw (uno::RuntimeException, std::exception)
    3129             : {
    3130             :     // return a Range object that represents the first cell where that information is found.
    3131           0 :     OUString sWhat;
    3132           0 :     sal_Int32 nWhat = 0;
    3133           0 :     double fWhat = 0.0;
    3134             : 
    3135             :     // string.
    3136           0 :     if( What >>= sWhat )
    3137             :     {
    3138           0 :         if( sWhat.isEmpty() )
    3139           0 :             throw uno::RuntimeException("Range::Find, missing params" );
    3140             :     }
    3141           0 :     else if( What >>= nWhat )
    3142             :     {
    3143           0 :         sWhat = OUString::number( nWhat );
    3144             :     }
    3145           0 :     else if( What >>= fWhat )
    3146             :     {
    3147           0 :         sWhat = OUString::number( fWhat );
    3148             :     }
    3149             :     else
    3150           0 :         throw uno::RuntimeException("Range::Find, missing params" );
    3151             : 
    3152           0 :     OUString sSearch = VBAToRegexp( sWhat );
    3153             : 
    3154           0 :     const SvxSearchItem& globalSearchOptions = ScGlobal::GetSearchItem();
    3155           0 :     SvxSearchItem newOptions( globalSearchOptions );
    3156             : 
    3157           0 :     sal_Int16 nSearchOrder = globalSearchOptions.GetRowDirection() ? excel::XlSearchOrder::xlByRows : excel::XlSearchOrder::xlByColumns;
    3158             : 
    3159           0 :     uno::Reference< util::XSearchable > xSearch( mxRange, uno::UNO_QUERY );
    3160           0 :     if( xSearch.is() )
    3161             :     {
    3162           0 :         uno::Reference< util::XSearchDescriptor > xDescriptor = xSearch->createSearchDescriptor();
    3163           0 :         xDescriptor->setSearchString( sSearch );
    3164           0 :         xDescriptor->setPropertyValue( SC_UNO_SRCHREGEXP, uno::Any( true ) );
    3165             : 
    3166           0 :         uno::Reference< excel::XRange > xAfterRange;
    3167           0 :         uno::Reference< table::XCellRange > xStartCell;
    3168           0 :         if( After >>= xAfterRange )
    3169             :         {
    3170             :             // After must be a single cell in the range
    3171           0 :             if( xAfterRange->getCount() > 1 )
    3172           0 :                 throw uno::RuntimeException("After must be a single cell." );
    3173           0 :             uno::Reference< excel::XRange > xCell( Cells( uno::makeAny( xAfterRange->getRow() ), uno::makeAny( xAfterRange->getColumn() ) ), uno::UNO_QUERY );
    3174           0 :             if( !xCell.is() )
    3175           0 :                 throw uno::RuntimeException("After must be in range." );
    3176           0 :             xStartCell.set( xAfterRange->getCellRange(), uno::UNO_QUERY_THROW );
    3177             :         }
    3178             : 
    3179             :         // LookIn
    3180           0 :         if( LookIn.hasValue() )
    3181             :         {
    3182           0 :             sal_Int32 nLookIn = 0;
    3183           0 :             if( LookIn >>= nLookIn )
    3184             :             {
    3185           0 :                 sal_Int16 nSearchType = 0;
    3186           0 :                 switch( nLookIn )
    3187             :                 {
    3188             :                     case excel::XlFindLookIn::xlComments :
    3189           0 :                         nSearchType = SVX_SEARCHIN_NOTE; // Notes
    3190           0 :                     break;
    3191             :                     case excel::XlFindLookIn::xlFormulas :
    3192           0 :                         nSearchType = SVX_SEARCHIN_FORMULA;
    3193           0 :                     break;
    3194             :                     case excel::XlFindLookIn::xlValues :
    3195           0 :                         nSearchType = SVX_SEARCHIN_VALUE;
    3196           0 :                     break;
    3197             :                     default:
    3198           0 :                         throw uno::RuntimeException("Range::Replace, illegal value for LookIn." );
    3199             :                 }
    3200           0 :                 newOptions.SetCellType( nSearchType );
    3201           0 :                 xDescriptor->setPropertyValue( "SearchType", uno::makeAny( nSearchType ) );
    3202             :             }
    3203             :         }
    3204             : 
    3205             :         // LookAt
    3206           0 :         if ( LookAt.hasValue() )
    3207             :         {
    3208           0 :             sal_Int16 nLookAt = ::comphelper::getINT16( LookAt );
    3209           0 :             bool bSearchWords = false;
    3210           0 :             if ( nLookAt == excel::XlLookAt::xlPart )
    3211           0 :                 bSearchWords = false;
    3212           0 :             else if ( nLookAt == excel::XlLookAt::xlWhole )
    3213           0 :                 bSearchWords = true;
    3214             :             else
    3215           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for LookAt" );
    3216           0 :             newOptions.SetWordOnly( bSearchWords );
    3217           0 :             xDescriptor->setPropertyValue( SC_UNO_SRCHWORDS, uno::makeAny( bSearchWords ) );
    3218             :         }
    3219             : 
    3220             :         // SearchOrder
    3221           0 :         if ( SearchOrder.hasValue() )
    3222             :         {
    3223           0 :             nSearchOrder =  ::comphelper::getINT16( SearchOrder );
    3224           0 :             bool bSearchByRow = false;
    3225           0 :             if ( nSearchOrder == excel::XlSearchOrder::xlByColumns )
    3226           0 :                 bSearchByRow = false;
    3227           0 :             else if ( nSearchOrder == excel::XlSearchOrder::xlByRows )
    3228           0 :                 bSearchByRow = true;
    3229             :             else
    3230           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for SearchOrder" );
    3231             : 
    3232           0 :             newOptions.SetRowDirection( bSearchByRow );
    3233           0 :             xDescriptor->setPropertyValue( SC_UNO_SRCHBYROW, uno::makeAny( bSearchByRow ) );
    3234             :         }
    3235             : 
    3236             :         // SearchDirection
    3237           0 :         if ( SearchDirection.hasValue() )
    3238             :         {
    3239           0 :             sal_Int32 nSearchDirection = 0;
    3240           0 :             if( SearchDirection >>= nSearchDirection )
    3241             :             {
    3242           0 :                 bool bSearchBackwards = false;
    3243           0 :                 if ( nSearchDirection == excel::XlSearchDirection::xlNext )
    3244           0 :                     bSearchBackwards = false;
    3245           0 :                 else if( nSearchDirection == excel::XlSearchDirection::xlPrevious )
    3246           0 :                     bSearchBackwards = true;
    3247             :                 else
    3248           0 :                     throw uno::RuntimeException("Range::Replace, illegal value for SearchDirection" );
    3249           0 :                 newOptions.SetBackward( bSearchBackwards );
    3250           0 :                 xDescriptor->setPropertyValue( "SearchBackwards", uno::makeAny( bSearchBackwards ) );
    3251             :             }
    3252             :         }
    3253             : 
    3254             :         // MatchCase
    3255           0 :         bool bMatchCase = false;
    3256           0 :         if ( MatchCase.hasValue() )
    3257             :         {
    3258             :             // SearchCaseSensitive
    3259           0 :             if( !( MatchCase >>= bMatchCase ) )
    3260           0 :                 throw uno::RuntimeException("Range::Replace, illegal value for MatchCase" );
    3261             :         }
    3262           0 :         xDescriptor->setPropertyValue( SC_UNO_SRCHCASE, uno::makeAny( bMatchCase ) );
    3263             : 
    3264             :         // MatchByte
    3265             :         // SearchFormat
    3266             :         // ignore
    3267             : 
    3268           0 :         ScGlobal::SetSearchItem( newOptions );
    3269             : 
    3270           0 :         uno::Reference< uno::XInterface > xInterface = xStartCell.is() ? xSearch->findNext( xStartCell, xDescriptor) : xSearch->findFirst( xDescriptor );
    3271           0 :         uno::Reference< table::XCellRange > xCellRange( xInterface, uno::UNO_QUERY );
    3272             :         // if we are searching from a starting cell and failed to find a match
    3273             :         // then try from the beginning
    3274           0 :         if ( !xCellRange.is() && xStartCell.is() )
    3275             :         {
    3276           0 :             xInterface = xSearch->findFirst( xDescriptor );
    3277           0 :             xCellRange.set( xInterface, uno::UNO_QUERY );
    3278             :         }
    3279           0 :         if ( xCellRange.is() )
    3280             :         {
    3281           0 :             uno::Reference< excel::XRange > xResultRange = new ScVbaRange( mxParent, mxContext, xCellRange );
    3282           0 :             if( xResultRange.is() )
    3283             :             {
    3284           0 :                 xResultRange->Select();
    3285           0 :                 return xResultRange;
    3286           0 :             }
    3287           0 :         }
    3288             : 
    3289             :     }
    3290             : 
    3291           0 :     return uno::Reference< excel::XRange >();
    3292             : }
    3293             : 
    3294           0 : uno::Reference< table::XCellRange > processKey( const uno::Any& Key, uno::Reference<  uno::XComponentContext >& xContext, ScDocShell* pDocSh )
    3295             : {
    3296           0 :     uno::Reference< excel::XRange > xKeyRange;
    3297           0 :     if ( Key.getValueType() == cppu::UnoType<excel::XRange>::get() )
    3298             :     {
    3299           0 :         xKeyRange.set( Key, uno::UNO_QUERY_THROW );
    3300             :     }
    3301           0 :     else if ( Key.getValueType() == ::cppu::UnoType<OUString>::get()  )
    3302             : 
    3303             :     {
    3304           0 :         OUString sRangeName = ::comphelper::getString( Key );
    3305           0 :         table::CellRangeAddress  aRefAddr;
    3306           0 :         if ( !pDocSh )
    3307           0 :             throw uno::RuntimeException("Range::Sort no docshell to calculate key param" );
    3308           0 :         xKeyRange = getRangeForName( xContext, sRangeName, pDocSh, aRefAddr );
    3309             :     }
    3310             :     else
    3311           0 :         throw uno::RuntimeException("Range::Sort illegal type value for key param" );
    3312           0 :     uno::Reference< table::XCellRange > xKey;
    3313           0 :     xKey.set( xKeyRange->getCellRange(), uno::UNO_QUERY_THROW );
    3314           0 :     return xKey;
    3315             : }
    3316             : 
    3317             : // helper method for Sort
    3318           0 : sal_Int32 findSortPropertyIndex( const uno::Sequence< beans::PropertyValue >& props,
    3319             : const OUString& sPropName ) throw( uno::RuntimeException )
    3320             : {
    3321           0 :     const beans::PropertyValue* pProp = props.getConstArray();
    3322           0 :     sal_Int32 nItems = props.getLength();
    3323             : 
    3324           0 :      sal_Int32 count=0;
    3325           0 :     for ( ; count < nItems; ++count, ++pProp )
    3326           0 :         if ( pProp->Name.equals( sPropName ) )
    3327           0 :             return count;
    3328           0 :     if ( count == nItems )
    3329           0 :         throw uno::RuntimeException("Range::Sort unknown sort property" );
    3330           0 :     return -1; //should never reach here ( satisfy compiler )
    3331             : }
    3332             : 
    3333             : // helper method for Sort
    3334           0 : void updateTableSortField( const uno::Reference< table::XCellRange >& xParentRange,
    3335             :     const uno::Reference< table::XCellRange >& xColRowKey, sal_Int16 nOrder,
    3336             :     table::TableSortField& aTableField, bool bIsSortColumn, bool bMatchCase ) throw ( uno::RuntimeException )
    3337             : {
    3338           0 :         RangeHelper parentRange( xParentRange );
    3339           0 :         RangeHelper colRowRange( xColRowKey );
    3340             : 
    3341           0 :         table::CellRangeAddress parentRangeAddress = parentRange.getCellRangeAddressable()->getRangeAddress();
    3342             : 
    3343           0 :         table::CellRangeAddress colRowKeyAddress = colRowRange.getCellRangeAddressable()->getRangeAddress();
    3344             : 
    3345             :         // make sure that upper left poing of key range is within the
    3346             :         // parent range
    3347           0 :         if (  ( !bIsSortColumn && colRowKeyAddress.StartColumn >= parentRangeAddress.StartColumn &&
    3348           0 :             colRowKeyAddress.StartColumn <= parentRangeAddress.EndColumn ) || ( bIsSortColumn &&
    3349           0 :             colRowKeyAddress.StartRow >= parentRangeAddress.StartRow &&
    3350           0 :             colRowKeyAddress.StartRow <= parentRangeAddress.EndRow  ) )
    3351             :         {
    3352             :             //determine col/row index
    3353           0 :             if ( bIsSortColumn )
    3354           0 :                 aTableField.Field = colRowKeyAddress.StartRow - parentRangeAddress.StartRow;
    3355             :             else
    3356           0 :                 aTableField.Field = colRowKeyAddress.StartColumn - parentRangeAddress.StartColumn;
    3357           0 :             aTableField.IsCaseSensitive = bMatchCase;
    3358             : 
    3359           0 :             if ( nOrder ==  excel::XlSortOrder::xlAscending )
    3360           0 :                 aTableField.IsAscending = sal_True;
    3361             :             else
    3362           0 :                 aTableField.IsAscending = false;
    3363             :         }
    3364             :         else
    3365           0 :             throw uno::RuntimeException("Illegal Key param" );
    3366             : 
    3367           0 : }
    3368             : 
    3369             : void SAL_CALL
    3370           0 : ScVbaRange::Sort( const uno::Any& Key1, const uno::Any& Order1, const uno::Any& Key2, const uno::Any& /*Type*/, const uno::Any& Order2, const uno::Any& Key3, const uno::Any& Order3, const uno::Any& Header, const uno::Any& OrderCustom, const uno::Any& MatchCase, const uno::Any& Orientation, const uno::Any& SortMethod,  const uno::Any& DataOption1, const uno::Any& DataOption2, const uno::Any& DataOption3  ) throw (uno::RuntimeException, std::exception)
    3371             : {
    3372             :     // #TODO# #FIXME# can we do something with Type
    3373           0 :     if ( m_Areas->getCount() > 1 )
    3374           0 :         throw uno::RuntimeException("That command cannot be used on multiple selections" );
    3375             : 
    3376           0 :     sal_Int16 nDataOption1 = excel::XlSortDataOption::xlSortNormal;
    3377           0 :     sal_Int16 nDataOption2 = excel::XlSortDataOption::xlSortNormal;
    3378           0 :     sal_Int16 nDataOption3 = excel::XlSortDataOption::xlSortNormal;
    3379             : 
    3380           0 :     ScDocument& rDoc = getScDocument();
    3381             : 
    3382           0 :     RangeHelper thisRange( mxRange );
    3383           0 :     table::CellRangeAddress thisRangeAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3384           0 :     ScSortParam aSortParam;
    3385           0 :     SCTAB nTab = thisRangeAddress.Sheet;
    3386           0 :     rDoc.GetSortParam( aSortParam, nTab );
    3387             : 
    3388           0 :     if ( DataOption1.hasValue() )
    3389           0 :         DataOption1 >>= nDataOption1;
    3390           0 :     if ( DataOption2.hasValue() )
    3391           0 :         DataOption2 >>= nDataOption2;
    3392           0 :     if ( DataOption3.hasValue() )
    3393           0 :         DataOption3 >>= nDataOption3;
    3394             : 
    3395             :     // 1) #TODO #FIXME need to process DataOption[1..3] not used currently
    3396             :     // 2) #TODO #FIXME need to refactor this ( below ) into a IsSingleCell() method
    3397           0 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW );
    3398             : 
    3399             :     // set up defaults
    3400             : 
    3401           0 :     sal_Int16 nOrder1 = aSortParam.maKeyState[1].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending;
    3402           0 :     sal_Int16 nOrder2 = aSortParam.maKeyState[2].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending;
    3403           0 :     sal_Int16 nOrder3 = aSortParam.maKeyState[3].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending;
    3404             : 
    3405           0 :     sal_Int16 nCustom = aSortParam.nUserIndex;
    3406           0 :     sal_Int16 nSortMethod = excel::XlSortMethod::xlPinYin;
    3407           0 :     bool bMatchCase = aSortParam.bCaseSens;
    3408             : 
    3409             :     // seems to work opposite to expected, see below
    3410           0 :     sal_Int16 nOrientation = aSortParam.bByRow ?  excel::XlSortOrientation::xlSortColumns :  excel::XlSortOrientation::xlSortRows;
    3411             : 
    3412           0 :     if ( Orientation.hasValue() )
    3413             :     {
    3414             :         // Documentation says xlSortRows is default but that doesn't appear to be
    3415             :         // the case. Also it appears that xlSortColumns is the default which
    3416             :         // strangely enough sorts by Row
    3417           0 :         nOrientation = ::comphelper::getINT16( Orientation );
    3418             :         // persist new option to be next calls default
    3419           0 :         if ( nOrientation == excel::XlSortOrientation::xlSortRows )
    3420           0 :             aSortParam.bByRow = false;
    3421             :         else
    3422           0 :             aSortParam.bByRow = true;
    3423             : 
    3424             :     }
    3425             : 
    3426           0 :     bool bIsSortColumns=false; // sort by row
    3427             : 
    3428           0 :     if ( nOrientation == excel::XlSortOrientation::xlSortRows )
    3429           0 :         bIsSortColumns = true;
    3430           0 :     sal_Int16 nHeader = 0;
    3431           0 :     nHeader = aSortParam.nCompatHeader;
    3432           0 :     bool bContainsHeader = false;
    3433             : 
    3434           0 :     if ( Header.hasValue() )
    3435             :     {
    3436           0 :         nHeader = ::comphelper::getINT16( Header );
    3437           0 :         aSortParam.nCompatHeader = nHeader;
    3438             :     }
    3439             : 
    3440           0 :     if ( nHeader == excel::XlYesNoGuess::xlGuess )
    3441             :     {
    3442           0 :         bool bHasColHeader = rDoc.HasColHeader(  static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), static_cast< SCCOL >( thisRangeAddress.EndColumn ), static_cast< SCROW >( thisRangeAddress.EndRow ), static_cast< SCTAB >( thisRangeAddress.Sheet ));
    3443           0 :         bool bHasRowHeader = rDoc.HasRowHeader(  static_cast< SCCOL >( thisRangeAddress.StartColumn ), static_cast< SCROW >( thisRangeAddress.StartRow ), static_cast< SCCOL >( thisRangeAddress.EndColumn ), static_cast< SCROW >( thisRangeAddress.EndRow ), static_cast< SCTAB >( thisRangeAddress.Sheet ) );
    3444           0 :         if ( bHasColHeader || bHasRowHeader )
    3445           0 :             nHeader =  excel::XlYesNoGuess::xlYes;
    3446             :         else
    3447           0 :             nHeader =  excel::XlYesNoGuess::xlNo;
    3448           0 :         aSortParam.nCompatHeader = nHeader;
    3449             :     }
    3450             : 
    3451           0 :     if ( nHeader == excel::XlYesNoGuess::xlYes )
    3452           0 :         bContainsHeader = true;
    3453             : 
    3454           0 :     if ( SortMethod.hasValue() )
    3455             :     {
    3456           0 :         nSortMethod = ::comphelper::getINT16( SortMethod );
    3457             :     }
    3458             : 
    3459           0 :     if ( OrderCustom.hasValue() )
    3460             :     {
    3461           0 :         OrderCustom >>= nCustom;
    3462           0 :         --nCustom; // 0-based in OOo
    3463           0 :         aSortParam.nUserIndex = nCustom;
    3464             :     }
    3465             : 
    3466           0 :     if ( MatchCase.hasValue() )
    3467             :     {
    3468           0 :         MatchCase >>= bMatchCase;
    3469           0 :         aSortParam.bCaseSens = bMatchCase;
    3470             :     }
    3471             : 
    3472           0 :     if ( Order1.hasValue() )
    3473             :     {
    3474           0 :         nOrder1 = ::comphelper::getINT16(Order1);
    3475           0 :         if (  nOrder1 == excel::XlSortOrder::xlAscending )
    3476           0 :             aSortParam.maKeyState[0].bAscending  = true;
    3477             :         else
    3478           0 :             aSortParam.maKeyState[0].bAscending  = false;
    3479             : 
    3480             :     }
    3481           0 :     if ( Order2.hasValue() )
    3482             :     {
    3483           0 :         nOrder2 = ::comphelper::getINT16(Order2);
    3484           0 :         if ( nOrder2 == excel::XlSortOrder::xlAscending )
    3485           0 :             aSortParam.maKeyState[1].bAscending  = true;
    3486             :         else
    3487           0 :             aSortParam.maKeyState[1].bAscending  = false;
    3488             :     }
    3489           0 :     if ( Order3.hasValue() )
    3490             :     {
    3491           0 :         nOrder3 = ::comphelper::getINT16(Order3);
    3492           0 :         if ( nOrder3 == excel::XlSortOrder::xlAscending )
    3493           0 :             aSortParam.maKeyState[2].bAscending  = true;
    3494             :         else
    3495           0 :             aSortParam.maKeyState[2].bAscending  = false;
    3496             :     }
    3497             : 
    3498           0 :     uno::Reference< table::XCellRange > xKey1;
    3499           0 :     uno::Reference< table::XCellRange > xKey2;
    3500           0 :     uno::Reference< table::XCellRange > xKey3;
    3501           0 :     ScDocShell* pDocShell = getScDocShell();
    3502           0 :     xKey1 = processKey( Key1, mxContext, pDocShell );
    3503           0 :     if ( !xKey1.is() )
    3504           0 :         throw uno::RuntimeException("Range::Sort needs a key1 param" );
    3505             : 
    3506           0 :     if ( Key2.hasValue() )
    3507           0 :         xKey2 = processKey( Key2, mxContext, pDocShell );
    3508           0 :     if ( Key3.hasValue() )
    3509           0 :         xKey3 = processKey( Key3, mxContext, pDocShell );
    3510             : 
    3511           0 :     uno::Reference< util::XSortable > xSort( mxRange, uno::UNO_QUERY_THROW );
    3512           0 :     uno::Sequence< beans::PropertyValue > sortDescriptor = xSort->createSortDescriptor();
    3513           0 :     sal_Int32 nTableSortFieldIndex = findSortPropertyIndex( sortDescriptor, OUString( "SortFields" ) );
    3514             : 
    3515           0 :     uno::Sequence< table::TableSortField > sTableFields(1);
    3516           0 :     sal_Int32 nTableIndex = 0;
    3517           0 :     updateTableSortField(  mxRange, xKey1, nOrder1, sTableFields[ nTableIndex++ ], bIsSortColumns, bMatchCase );
    3518             : 
    3519           0 :     if ( xKey2.is() )
    3520             :     {
    3521           0 :         sTableFields.realloc( sTableFields.getLength() + 1 );
    3522           0 :         updateTableSortField(  mxRange, xKey2, nOrder2, sTableFields[ nTableIndex++ ], bIsSortColumns, bMatchCase );
    3523             :     }
    3524           0 :     if ( xKey3.is()  )
    3525             :     {
    3526           0 :         sTableFields.realloc( sTableFields.getLength() + 1 );
    3527           0 :         updateTableSortField(  mxRange, xKey3, nOrder3, sTableFields[ nTableIndex++ ], bIsSortColumns, bMatchCase );
    3528             :     }
    3529           0 :     sortDescriptor[ nTableSortFieldIndex ].Value <<= sTableFields;
    3530             : 
    3531           0 :     sal_Int32 nIndex =  findSortPropertyIndex( sortDescriptor,  OUString("IsSortColumns") );
    3532           0 :     sortDescriptor[ nIndex ].Value <<= bIsSortColumns;
    3533             : 
    3534           0 :     nIndex =    findSortPropertyIndex( sortDescriptor, CONTS_HEADER );
    3535           0 :     sortDescriptor[ nIndex ].Value <<= bContainsHeader;
    3536             : 
    3537           0 :     rDoc.SetSortParam( aSortParam, nTab );
    3538           0 :     xSort->sort( sortDescriptor );
    3539             : 
    3540             :     // #FIXME #TODO
    3541             :     // The SortMethod param is not processed ( not sure what its all about, need to
    3542           0 :     (void)nSortMethod;
    3543           0 : }
    3544             : 
    3545             : uno::Reference< excel::XRange > SAL_CALL
    3546          36 : ScVbaRange::End( ::sal_Int32 Direction )  throw (uno::RuntimeException, std::exception)
    3547             : {
    3548          36 :     if ( m_Areas->getCount() > 1 )
    3549             :     {
    3550          14 :         uno::Reference< excel::XRange > xRange( getArea( 0 ), uno::UNO_QUERY_THROW );
    3551          14 :         return xRange->End( Direction );
    3552             :     }
    3553             : 
    3554             :     // #FIXME #TODO
    3555             :     // euch! found my orig implementation sucked, so
    3556             :     // trying this even suckier one ( really need to use/expose code in
    3557             :     // around  ScTabView::MoveCursorArea(), thats the bit that calcutes
    3558             :     // where the cursor should go )
    3559             :     // Main problem with this method is the ultra hacky attempt to preserve
    3560             :     // the ActiveCell, there should be no need to go to these extreems
    3561             : 
    3562             :     // Save ActiveCell pos ( to restore later )
    3563          22 :     uno::Any aDft;
    3564          44 :     uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
    3565          44 :     OUString sActiveCell = xApplication->getActiveCell()->Address(aDft, aDft, aDft, aDft, aDft );
    3566             : 
    3567             :     // position current cell upper left of this range
    3568          22 :     Cells( uno::makeAny( (sal_Int32) 1 ), uno::makeAny( (sal_Int32) 1 ) )->Select();
    3569             : 
    3570          44 :         uno::Reference< frame::XModel > xModel = getModelFromRange( mxRange );
    3571             : 
    3572          22 :     SfxViewFrame* pViewFrame = excel::getViewFrame( xModel );
    3573          22 :     if ( pViewFrame )
    3574             :     {
    3575          22 :         SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
    3576             :         // Hoping this will make sure this slot is called
    3577             :         // synchronously
    3578          44 :         SfxBoolItem sfxAsync( SID_ASYNCHRON, false );
    3579          22 :         aArgs.Put( sfxAsync, sfxAsync.Which() );
    3580          22 :         SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher();
    3581             : 
    3582          22 :         sal_uInt16 nSID = 0;
    3583             : 
    3584          22 :         switch( Direction )
    3585             :         {
    3586             :             case excel::XlDirection::xlDown:
    3587           4 :                 nSID = SID_CURSORBLKDOWN;
    3588           4 :                 break;
    3589             :             case excel::XlDirection::xlUp:
    3590           6 :                 nSID = SID_CURSORBLKUP;
    3591           6 :                 break;
    3592             :             case excel::XlDirection::xlToLeft:
    3593           6 :                 nSID = SID_CURSORBLKLEFT;
    3594           6 :                 break;
    3595             :             case excel::XlDirection::xlToRight:
    3596           6 :                 nSID = SID_CURSORBLKRIGHT;
    3597           6 :                 break;
    3598             :             default:
    3599           0 :                 throw uno::RuntimeException(": Invalid ColumnIndex" );
    3600             :         }
    3601          22 :         if ( pDispatcher )
    3602             :         {
    3603          22 :             pDispatcher->Execute( nSID, (SfxCallMode)SfxCallMode::SYNCHRON, aArgs );
    3604          22 :         }
    3605             :     }
    3606             : 
    3607             :     // result is the ActiveCell
    3608          22 :     OUString sMoved =    xApplication->getActiveCell()->Address(aDft, aDft, aDft, aDft, aDft );
    3609             : 
    3610             :     // restore old ActiveCell
    3611          44 :     uno::Any aVoid;
    3612             : 
    3613          44 :     uno::Reference< excel::XRange > xOldActiveCell( xApplication->getActiveSheet()->Range( uno::makeAny( sActiveCell ), aVoid ), uno::UNO_QUERY_THROW );
    3614          22 :     xOldActiveCell->Select();
    3615             : 
    3616          44 :     uno::Reference< excel::XRange > resultCell;
    3617          22 :     resultCell.set( xApplication->getActiveSheet()->Range( uno::makeAny( sMoved ), aVoid ), uno::UNO_QUERY_THROW );
    3618             : 
    3619             :     // return result
    3620          66 :     return resultCell;
    3621             : }
    3622             : 
    3623             : bool
    3624         980 : ScVbaRange::isSingleCellRange()
    3625             : {
    3626         980 :     uno::Reference< sheet::XCellRangeAddressable > xAddressable( mxRange, uno::UNO_QUERY );
    3627         980 :     if ( xAddressable.is() )
    3628             :     {
    3629         978 :         table::CellRangeAddress aRangeAddr = xAddressable->getRangeAddress();
    3630         978 :         return ( aRangeAddr.EndColumn == aRangeAddr.StartColumn && aRangeAddr.EndRow == aRangeAddr.StartRow );
    3631             :     }
    3632           2 :     return false;
    3633             : }
    3634             : 
    3635             : uno::Reference< excel::XCharacters > SAL_CALL
    3636           0 : ScVbaRange::characters( const uno::Any& Start, const uno::Any& Length ) throw (uno::RuntimeException, std::exception)
    3637             : {
    3638           0 :     if ( !isSingleCellRange() )
    3639           0 :         throw uno::RuntimeException("Can't create Characters property for multicell range " );
    3640           0 :     uno::Reference< text::XSimpleText > xSimple(mxRange->getCellByPosition(0,0) , uno::UNO_QUERY_THROW );
    3641           0 :     ScDocument& rDoc = getDocumentFromRange(mxRange);
    3642             : 
    3643           0 :     ScVbaPalette aPalette( rDoc.GetDocumentShell() );
    3644           0 :     return new ScVbaCharacters( this, mxContext, aPalette, xSimple, Start, Length );
    3645             : }
    3646             : 
    3647             :  void SAL_CALL
    3648           6 : ScVbaRange::Delete( const uno::Any& Shift ) throw (uno::RuntimeException, std::exception)
    3649             : {
    3650           6 :     if ( m_Areas->getCount() > 1 )
    3651             :     {
    3652           0 :         sal_Int32 nItems = m_Areas->getCount();
    3653           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    3654             :         {
    3655           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    3656           0 :             xRange->Delete( Shift );
    3657           0 :         }
    3658           0 :         return;
    3659             :     }
    3660           6 :     sheet::CellDeleteMode mode = sheet::CellDeleteMode_NONE ;
    3661           6 :     RangeHelper thisRange( mxRange );
    3662           6 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3663           6 :     if ( Shift.hasValue() )
    3664             :     {
    3665           4 :         sal_Int32 nShift = 0;
    3666           4 :         Shift >>= nShift;
    3667           4 :         switch ( nShift )
    3668             :         {
    3669             :             case excel::XlDeleteShiftDirection::xlShiftUp:
    3670           2 :                 mode = sheet::CellDeleteMode_UP;
    3671           2 :                 break;
    3672             :             case excel::XlDeleteShiftDirection::xlShiftToLeft:
    3673           2 :                 mode = sheet::CellDeleteMode_LEFT;
    3674           2 :                 break;
    3675             :             default:
    3676           0 :                 throw uno::RuntimeException("Illegal parameter " );
    3677             :         }
    3678             :     }
    3679             :     else
    3680             :         {
    3681           2 :         bool bFullRow = ( thisAddress.StartColumn == 0 && thisAddress.EndColumn == MAXCOL );
    3682           2 :             sal_Int32 nCols = thisAddress.EndColumn - thisAddress.StartColumn;
    3683           2 :             sal_Int32 nRows = thisAddress.EndRow - thisAddress.StartRow;
    3684           2 :         if ( mbIsRows || bFullRow || ( nCols >=  nRows ) )
    3685           0 :             mode = sheet::CellDeleteMode_UP;
    3686             :         else
    3687           2 :             mode = sheet::CellDeleteMode_LEFT;
    3688             :     }
    3689           6 :     uno::Reference< sheet::XCellRangeMovement > xCellRangeMove( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    3690           6 :     xCellRangeMove->removeRange( thisAddress, mode );
    3691             : 
    3692             : }
    3693             : 
    3694             : //XElementAccess
    3695             : sal_Bool SAL_CALL
    3696           0 : ScVbaRange::hasElements() throw (uno::RuntimeException, std::exception)
    3697             : {
    3698           0 :     uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY );
    3699           0 :     if ( xColumnRowRange.is() )
    3700           0 :         if ( xColumnRowRange->getRows()->getCount() ||
    3701           0 :             xColumnRowRange->getColumns()->getCount() )
    3702           0 :             return sal_True;
    3703           0 :     return false;
    3704             : }
    3705             : 
    3706             : // XEnumerationAccess
    3707             : uno::Reference< container::XEnumeration > SAL_CALL
    3708          36 : ScVbaRange::createEnumeration() throw (uno::RuntimeException, std::exception)
    3709             : {
    3710          36 :     if ( mbIsColumns || mbIsRows )
    3711             :     {
    3712           0 :         uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY );
    3713           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3714           0 :                 sal_Int32 nElems = 0;
    3715           0 :         if ( mbIsColumns )
    3716           0 :             nElems = xColumnRowRange->getColumns()->getCount();
    3717             :         else
    3718           0 :             nElems = xColumnRowRange->getRows()->getCount();
    3719           0 :                 return new ColumnsRowEnumeration( mxContext, xRange, nElems );
    3720             : 
    3721             :     }
    3722          36 :     return new CellsEnumeration( mxParent, mxContext, m_Areas );
    3723             : }
    3724             : 
    3725             : OUString SAL_CALL
    3726           0 : ScVbaRange::getDefaultMethodName(  ) throw (uno::RuntimeException, std::exception)
    3727             : {
    3728           0 :     const static OUString sName( "Item" );
    3729           0 :     return sName;
    3730             : }
    3731             : 
    3732             : // returns calc internal col. width ( in points )
    3733             : double
    3734          54 : ScVbaRange::getCalcColWidth(const table::CellRangeAddress& rAddress)
    3735             :     throw (uno::RuntimeException, std::exception)
    3736             : {
    3737          54 :     ScDocument& rDoc = getScDocument();
    3738          54 :     sal_uInt16 nWidth = rDoc.GetOriginalWidth( static_cast< SCCOL >( rAddress.StartColumn ), static_cast< SCTAB >( rAddress.Sheet ) );
    3739          54 :     double nPoints = lcl_TwipsToPoints( nWidth );
    3740          54 :     nPoints = lcl_Round2DecPlaces( nPoints );
    3741          54 :     return nPoints;
    3742             : }
    3743             : 
    3744             : double
    3745          84 : ScVbaRange::getCalcRowHeight(const table::CellRangeAddress& rAddress)
    3746             :     throw (uno::RuntimeException, std::exception)
    3747             : {
    3748          84 :     ScDocument& rDoc = getDocumentFromRange( mxRange );
    3749          84 :     sal_uInt16 nWidth = rDoc.GetOriginalHeight( rAddress.StartRow, rAddress.Sheet );
    3750          84 :     double nPoints = lcl_TwipsToPoints( nWidth );
    3751          84 :     nPoints = lcl_Round2DecPlaces( nPoints );
    3752          84 :     return nPoints;
    3753             : }
    3754             : 
    3755             : // return Char Width in points
    3756          20 : double getDefaultCharWidth( ScDocShell* pDocShell )
    3757             : {
    3758          20 :     ScDocument& rDoc = pDocShell->GetDocument();
    3759          20 :     OutputDevice* pRefDevice = rDoc.GetRefDevice();
    3760          20 :     ScPatternAttr* pAttr = rDoc.GetDefPattern();
    3761          20 :     vcl::Font aDefFont;
    3762          20 :     pAttr->GetFont( aDefFont, SC_AUTOCOL_BLACK, pRefDevice );
    3763          20 :     pRefDevice->SetFont( aDefFont );
    3764          20 :     long nCharWidth = pRefDevice->GetTextWidth( OUString( '0' ) );        // 1/100th mm
    3765          20 :     return lcl_hmmToPoints( nCharWidth );
    3766             : }
    3767             : 
    3768             : uno::Any SAL_CALL
    3769          22 : ScVbaRange::getColumnWidth() throw (uno::RuntimeException, std::exception)
    3770             : {
    3771          22 :     sal_Int32 nLen = m_Areas->getCount();
    3772          22 :     if ( nLen > 1 )
    3773             :     {
    3774          10 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3775          10 :         return xRange->getColumnWidth();
    3776             :     }
    3777             : 
    3778          12 :     double nColWidth =  0;
    3779          12 :     ScDocShell* pShell = getScDocShell();
    3780          12 :     if ( pShell )
    3781             :     {
    3782          12 :         double defaultCharWidth = getDefaultCharWidth( pShell );
    3783          12 :         RangeHelper thisRange( mxRange );
    3784          12 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3785          12 :         sal_Int32 nStartCol = thisAddress.StartColumn;
    3786          12 :         sal_Int32 nEndCol = thisAddress.EndColumn;
    3787          12 :         sal_uInt16 nColTwips = 0;
    3788          36 :         for( sal_Int32 nCol = nStartCol ; nCol <= nEndCol; ++nCol )
    3789             :         {
    3790          28 :             thisAddress.StartColumn = nCol;
    3791          28 :             sal_uInt16 nCurTwips = pShell->GetDocument().GetOriginalWidth( static_cast< SCCOL >( thisAddress.StartColumn ), static_cast< SCTAB >( thisAddress.Sheet ) );
    3792          28 :             if ( nCol == nStartCol )
    3793          12 :                 nColTwips =  nCurTwips;
    3794          28 :             if ( nColTwips != nCurTwips )
    3795           4 :                 return aNULL();
    3796             :         }
    3797           8 :         nColWidth = lcl_TwipsToPoints( nColTwips );
    3798           8 :         if ( nColWidth != 0.0 )
    3799           8 :             nColWidth = ( nColWidth / defaultCharWidth ) - fExtraWidth;
    3800             :     }
    3801           8 :     nColWidth = lcl_Round2DecPlaces( nColWidth );
    3802           8 :     return uno::makeAny( nColWidth );
    3803             : }
    3804             : 
    3805             : void SAL_CALL
    3806          14 : ScVbaRange::setColumnWidth( const uno::Any& _columnwidth ) throw (uno::RuntimeException, std::exception)
    3807             : {
    3808          14 :     sal_Int32 nLen = m_Areas->getCount();
    3809          14 :     if ( nLen > 1 )
    3810             :     {
    3811          12 :         for ( sal_Int32 index = 1; index != nLen; ++index )
    3812             :         {
    3813           6 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(index) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3814           6 :             xRange->setColumnWidth( _columnwidth );
    3815           6 :         }
    3816          12 :         return;
    3817             :     }
    3818           8 :     double nColWidth = 0;
    3819           8 :     _columnwidth >>= nColWidth;
    3820           8 :     nColWidth = lcl_Round2DecPlaces( nColWidth );
    3821           8 :     ScDocShell* pDocShell = getScDocShell();
    3822           8 :     if ( pDocShell )
    3823             :     {
    3824           8 :         if ( nColWidth != 0.0 )
    3825           8 :             nColWidth = ( nColWidth + fExtraWidth ) * getDefaultCharWidth( pDocShell );
    3826           8 :         RangeHelper thisRange( mxRange );
    3827           8 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3828           8 :         sal_uInt16 nTwips = lcl_pointsToTwips( nColWidth );
    3829             : 
    3830          16 :         std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(thisAddress.StartColumn, thisAddress.EndColumn));
    3831             :         // #163561# use mode SC_SIZE_DIRECT: hide for width 0, show for other values
    3832           8 :         pDocShell->GetDocFunc().SetWidthOrHeight(
    3833          24 :             true, aColArr, thisAddress.Sheet, SC_SIZE_DIRECT, nTwips, true, true);
    3834             :     }
    3835             : }
    3836             : 
    3837             : uno::Any SAL_CALL
    3838          34 : ScVbaRange::getWidth() throw (uno::RuntimeException, std::exception)
    3839             : {
    3840          34 :     if ( m_Areas->getCount() > 1 )
    3841             :     {
    3842          16 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3843          16 :         return xRange->getWidth();
    3844             :     }
    3845          18 :     uno::Reference< table::XColumnRowRange > xColRowRange( mxRange, uno::UNO_QUERY_THROW );
    3846          36 :     uno::Reference< container::XIndexAccess > xIndexAccess( xColRowRange->getColumns(), uno::UNO_QUERY_THROW );
    3847          18 :     sal_Int32 nElems = xIndexAccess->getCount();
    3848          18 :     double nWidth = 0;
    3849          72 :     for ( sal_Int32 index=0; index<nElems; ++index )
    3850             :     {
    3851          54 :         uno::Reference< sheet::XCellRangeAddressable > xAddressable( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW );
    3852          54 :         double nTmpWidth = getCalcColWidth( xAddressable->getRangeAddress() );
    3853          54 :         nWidth += nTmpWidth;
    3854          54 :     }
    3855          36 :     return uno::makeAny( nWidth );
    3856             : }
    3857             : 
    3858             : uno::Any SAL_CALL
    3859         162 : ScVbaRange::Areas( const uno::Any& item) throw (uno::RuntimeException, std::exception)
    3860             : {
    3861         162 :     if ( !item.hasValue() )
    3862         140 :         return uno::makeAny( m_Areas );
    3863          22 :     return m_Areas->Item( item, uno::Any() );
    3864             : }
    3865             : 
    3866             : uno::Reference< excel::XRange >
    3867         110 : ScVbaRange::getArea( sal_Int32 nIndex ) throw( css::uno::RuntimeException )
    3868             : {
    3869         110 :     if ( !m_Areas.is() )
    3870           0 :         throw uno::RuntimeException("No areas available" );
    3871         110 :     uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( ++nIndex ), uno::Any() ), uno::UNO_QUERY_THROW );
    3872         110 :     return xRange;
    3873             : }
    3874             : 
    3875             : uno::Any
    3876           6 : ScVbaRange::Borders( const uno::Any& item ) throw( script::BasicErrorException, uno::RuntimeException )
    3877             : {
    3878           6 :     if ( !item.hasValue() )
    3879           6 :         return uno::makeAny( getBorders() );
    3880           0 :     return getBorders()->Item( item, uno::Any() );
    3881             : }
    3882             : 
    3883             : uno::Any SAL_CALL
    3884           0 : ScVbaRange::BorderAround( const css::uno::Any& LineStyle, const css::uno::Any& Weight,
    3885             :                 const css::uno::Any& ColorIndex, const css::uno::Any& Color ) throw (css::uno::RuntimeException, std::exception)
    3886             : {
    3887           0 :     sal_Int32 nCount = getBorders()->getCount();
    3888             : 
    3889           0 :     for( sal_Int32 i = 0; i < nCount; i++ )
    3890             :     {
    3891           0 :         const sal_Int32 nLineType = supportedIndexTable[i];
    3892           0 :         switch( nLineType )
    3893             :         {
    3894             :             case excel::XlBordersIndex::xlEdgeLeft:
    3895             :             case excel::XlBordersIndex::xlEdgeTop:
    3896             :             case excel::XlBordersIndex::xlEdgeBottom:
    3897             :             case excel::XlBordersIndex::xlEdgeRight:
    3898             :             {
    3899           0 :                 uno::Reference< excel::XBorder > xBorder( m_Borders->Item( uno::makeAny( nLineType ), uno::Any() ), uno::UNO_QUERY_THROW );
    3900           0 :                 if( LineStyle.hasValue() )
    3901             :                 {
    3902           0 :                     xBorder->setLineStyle( LineStyle );
    3903             :                 }
    3904           0 :                 if( Weight.hasValue() )
    3905             :                 {
    3906           0 :                     xBorder->setWeight( Weight );
    3907             :                 }
    3908           0 :                 if( ColorIndex.hasValue() )
    3909             :                 {
    3910           0 :                     xBorder->setColorIndex( ColorIndex );
    3911             :                 }
    3912           0 :                 if( Color.hasValue() )
    3913             :                 {
    3914           0 :                     xBorder->setColor( Color );
    3915             :                 }
    3916           0 :                 break;
    3917             :             }
    3918             :             case excel::XlBordersIndex::xlInsideVertical:
    3919             :             case excel::XlBordersIndex::xlInsideHorizontal:
    3920             :             case excel::XlBordersIndex::xlDiagonalDown:
    3921             :             case excel::XlBordersIndex::xlDiagonalUp:
    3922           0 :                 break;
    3923             :             default:
    3924           0 :                 return uno::makeAny( false );
    3925             :         }
    3926             :     }
    3927           0 :     return uno::makeAny( sal_True );
    3928             : }
    3929             : 
    3930             : uno::Any SAL_CALL
    3931          22 : ScVbaRange::getRowHeight()
    3932             :     throw (uno::RuntimeException, std::exception)
    3933             : {
    3934          22 :     sal_Int32 nLen = m_Areas->getCount();
    3935          22 :     if ( nLen > 1 )
    3936             :     {
    3937          10 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3938          10 :         return xRange->getRowHeight();
    3939             :     }
    3940             : 
    3941             :     // if any row's RowHeight in the
    3942             :     // range is different from any other then return NULL
    3943          12 :     RangeHelper thisRange( mxRange );
    3944          12 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3945             : 
    3946          12 :     sal_Int32 nStartRow = thisAddress.StartRow;
    3947          12 :     sal_Int32 nEndRow = thisAddress.EndRow;
    3948          12 :         sal_uInt16 nRowTwips = 0;
    3949             :     // #TODO probably possible to use the SfxItemSet ( and see if
    3950             :     //  SfxItemState::DONTCARE is set ) to improve performance
    3951             : // #CHECKME looks like this is general behaviour not just row Range specific
    3952             : //  if ( mbIsRows )
    3953          12 :     ScDocShell* pShell = getScDocShell();
    3954          12 :     if ( pShell )
    3955             :     {
    3956          54 :         for ( sal_Int32 nRow = nStartRow ; nRow <= nEndRow; ++nRow )
    3957             :         {
    3958          46 :             thisAddress.StartRow = nRow;
    3959          46 :             sal_uInt16 nCurTwips = pShell->GetDocument().GetOriginalHeight( thisAddress.StartRow, thisAddress.Sheet );
    3960          46 :             if ( nRow == nStartRow )
    3961          12 :                 nRowTwips = nCurTwips;
    3962          46 :             if ( nRowTwips != nCurTwips )
    3963           4 :                 return aNULL();
    3964             :         }
    3965             :     }
    3966           8 :     double nHeight = lcl_Round2DecPlaces( lcl_TwipsToPoints( nRowTwips ) );
    3967           8 :     return uno::makeAny( nHeight );
    3968             : }
    3969             : 
    3970             : void SAL_CALL
    3971          14 : ScVbaRange::setRowHeight( const uno::Any& _rowheight) throw (uno::RuntimeException, std::exception)
    3972             : {
    3973          14 :     sal_Int32 nLen = m_Areas->getCount();
    3974          14 :     if ( nLen > 1 )
    3975             :     {
    3976          12 :         for ( sal_Int32 index = 1; index != nLen; ++index )
    3977             :         {
    3978           6 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(index) ), uno::Any() ), uno::UNO_QUERY_THROW );
    3979           6 :             xRange->setRowHeight( _rowheight );
    3980           6 :         }
    3981          12 :         return;
    3982             :     }
    3983           8 :     double nHeight = 0; // Incoming height is in points
    3984           8 :         _rowheight >>= nHeight;
    3985           8 :     nHeight = lcl_Round2DecPlaces( nHeight );
    3986           8 :     RangeHelper thisRange( mxRange );
    3987           8 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    3988           8 :     sal_uInt16 nTwips = lcl_pointsToTwips( nHeight );
    3989             : 
    3990           8 :     ScDocShell* pDocShell = getDocShellFromRange( mxRange );
    3991          16 :     std::vector<sc::ColRowSpan> aRowArr(1, sc::ColRowSpan(thisAddress.StartRow, thisAddress.EndRow));
    3992           8 :     pDocShell->GetDocFunc().SetWidthOrHeight(
    3993          24 :         false, aRowArr, thisAddress.Sheet, SC_SIZE_ORIGINAL, nTwips, true, true);
    3994             : }
    3995             : 
    3996             : uno::Any SAL_CALL
    3997           0 : ScVbaRange::getPageBreak() throw (uno::RuntimeException, std::exception)
    3998             : {
    3999           0 :     sal_Int32 nPageBreak = excel::XlPageBreak::xlPageBreakNone;
    4000           0 :     ScDocShell* pShell = getDocShellFromRange( mxRange );
    4001           0 :     if ( pShell )
    4002             :     {
    4003           0 :         RangeHelper thisRange( mxRange );
    4004           0 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4005           0 :         bool bColumn = false;
    4006             : 
    4007           0 :         if (thisAddress.StartRow==0)
    4008           0 :             bColumn = true;
    4009             : 
    4010           0 :         uno::Reference< frame::XModel > xModel = pShell->GetModel();
    4011           0 :         if ( xModel.is() )
    4012             :         {
    4013           0 :             ScDocument& rDoc = getDocumentFromRange( mxRange );
    4014             : 
    4015           0 :             ScBreakType nBreak = BREAK_NONE;
    4016           0 :             if ( !bColumn )
    4017           0 :                 nBreak = rDoc.HasRowBreak(thisAddress.StartRow, thisAddress.Sheet);
    4018             :             else
    4019           0 :                 nBreak = rDoc.HasColBreak(thisAddress.StartColumn, thisAddress.Sheet);
    4020             : 
    4021           0 :             if (nBreak & BREAK_PAGE)
    4022           0 :                 nPageBreak = excel::XlPageBreak::xlPageBreakAutomatic;
    4023             : 
    4024           0 :             if (nBreak & BREAK_MANUAL)
    4025           0 :                 nPageBreak = excel::XlPageBreak::xlPageBreakManual;
    4026           0 :         }
    4027             :     }
    4028             : 
    4029           0 :     return uno::makeAny( nPageBreak );
    4030             : }
    4031             : 
    4032             : void SAL_CALL
    4033           0 : ScVbaRange::setPageBreak( const uno::Any& _pagebreak) throw (uno::RuntimeException, std::exception)
    4034             : {
    4035           0 :     sal_Int32 nPageBreak = 0;
    4036           0 :     _pagebreak >>= nPageBreak;
    4037             : 
    4038           0 :     ScDocShell* pShell = getDocShellFromRange( mxRange );
    4039           0 :     if ( pShell )
    4040             :     {
    4041           0 :         RangeHelper thisRange( mxRange );
    4042           0 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4043           0 :         if ((thisAddress.StartColumn==0) && (thisAddress.StartRow==0))
    4044           0 :             return;
    4045           0 :         bool bColumn = false;
    4046             : 
    4047           0 :         if (thisAddress.StartRow==0)
    4048           0 :             bColumn = true;
    4049             : 
    4050           0 :         ScAddress aAddr( static_cast<SCCOL>(thisAddress.StartColumn), thisAddress.StartRow, thisAddress.Sheet );
    4051           0 :         uno::Reference< frame::XModel > xModel = pShell->GetModel();
    4052           0 :         if ( xModel.is() )
    4053             :         {
    4054           0 :             ScTabViewShell* pViewShell = excel::getBestViewShell( xModel );
    4055           0 :             if ( nPageBreak == excel::XlPageBreak::xlPageBreakManual )
    4056           0 :                 pViewShell->InsertPageBreak( bColumn, true, &aAddr);
    4057           0 :             else if ( nPageBreak == excel::XlPageBreak::xlPageBreakNone )
    4058           0 :                 pViewShell->DeletePageBreak( bColumn, true, &aAddr);
    4059           0 :         }
    4060             :     }
    4061             : }
    4062             : 
    4063             : uno::Any SAL_CALL
    4064          28 : ScVbaRange::getHeight() throw (uno::RuntimeException, std::exception)
    4065             : {
    4066          28 :     if ( m_Areas->getCount() > 1 )
    4067             :     {
    4068          14 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(1) ), uno::Any() ), uno::UNO_QUERY_THROW );
    4069          14 :         return xRange->getHeight();
    4070             :     }
    4071             : 
    4072          14 :     uno::Reference< table::XColumnRowRange > xColRowRange( mxRange, uno::UNO_QUERY_THROW );
    4073          28 :     uno::Reference< container::XIndexAccess > xIndexAccess( xColRowRange->getRows(), uno::UNO_QUERY_THROW );
    4074          14 :     sal_Int32 nElems = xIndexAccess->getCount();
    4075          14 :     double nHeight = 0;
    4076          98 :     for ( sal_Int32 index=0; index<nElems; ++index )
    4077             :     {
    4078          84 :             uno::Reference< sheet::XCellRangeAddressable > xAddressable( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW );
    4079          84 :         nHeight += getCalcRowHeight(xAddressable->getRangeAddress() );
    4080          84 :     }
    4081          28 :     return uno::makeAny( nHeight );
    4082             : }
    4083             : 
    4084             : awt::Point
    4085          12 : ScVbaRange::getPosition() throw ( uno::RuntimeException )
    4086             : {
    4087          12 :         awt::Point aPoint;
    4088          12 :     uno::Reference< beans::XPropertySet > xProps;
    4089          12 :     if ( mxRange.is() )
    4090          12 :         xProps.set( mxRange, uno::UNO_QUERY_THROW );
    4091             :     else
    4092           0 :         xProps.set( mxRanges, uno::UNO_QUERY_THROW );
    4093          12 :     xProps->getPropertyValue( POSITION ) >>= aPoint;
    4094          12 :     return aPoint;
    4095             : }
    4096             : uno::Any SAL_CALL
    4097          12 : ScVbaRange::getLeft() throw (uno::RuntimeException, std::exception)
    4098             : {
    4099             :     // helperapi returns the first ranges left ( and top below )
    4100          12 :     if ( m_Areas->getCount() > 1 )
    4101           6 :         return getArea( 0 )->getLeft();
    4102           6 :     awt::Point aPoint = getPosition();
    4103           6 :     return uno::makeAny( lcl_hmmToPoints( aPoint.X ) );
    4104             : }
    4105             : 
    4106             : uno::Any SAL_CALL
    4107          12 : ScVbaRange::getTop() throw (uno::RuntimeException, std::exception)
    4108             : {
    4109             :     // helperapi returns the first ranges top
    4110          12 :     if ( m_Areas->getCount() > 1 )
    4111           6 :         return getArea( 0 )->getTop();
    4112           6 :     awt::Point aPoint= getPosition();
    4113           6 :     return uno::makeAny( lcl_hmmToPoints( aPoint.Y ) );
    4114             : }
    4115             : 
    4116           0 : uno::Reference< sheet::XCellRangeReferrer > getNamedRange( const uno::Reference< uno::XInterface >& xIf, const uno::Reference< table::XCellRange >& thisRange )
    4117             : {
    4118           0 :     uno::Reference< beans::XPropertySet > xProps( xIf, uno::UNO_QUERY_THROW );
    4119           0 :     uno::Reference< container::XNameAccess > xNameAccess( xProps->getPropertyValue( "NamedRanges" ), uno::UNO_QUERY_THROW );
    4120             : 
    4121           0 :     uno::Sequence< OUString > sNames = xNameAccess->getElementNames();
    4122             : //    uno::Reference< table::XCellRange > thisRange( getCellRange(), uno::UNO_QUERY_THROW );
    4123           0 :     uno::Reference< sheet::XCellRangeReferrer > xNamedRange;
    4124           0 :     for ( sal_Int32 i=0; i < sNames.getLength(); ++i )
    4125             :     {
    4126           0 :         uno::Reference< sheet::XCellRangeReferrer > xName( xNameAccess->getByName( sNames[ i ] ), uno::UNO_QUERY );
    4127           0 :         if ( xName.is() )
    4128             :         {
    4129           0 :             if ( thisRange == xName->getReferredCells() )
    4130             :             {
    4131           0 :                 xNamedRange = xName;
    4132           0 :                 break;
    4133             :             }
    4134             :         }
    4135           0 :     }
    4136           0 :     return xNamedRange;
    4137             : }
    4138             : 
    4139             : uno::Reference< excel::XName >
    4140           0 : ScVbaRange::getName() throw (uno::RuntimeException, std::exception)
    4141             : {
    4142           0 :     uno::Reference< beans::XPropertySet > xProps( getUnoModel(), uno::UNO_QUERY );
    4143           0 :     uno::Reference< table::XCellRange > thisRange( getCellRange(), uno::UNO_QUERY_THROW );
    4144             :     // Application range
    4145           0 :     uno::Reference< sheet::XCellRangeReferrer > xNamedRange = getNamedRange( xProps, thisRange );
    4146             : 
    4147           0 :     if ( !xNamedRange.is() )
    4148             :     {
    4149             :         // not in application range then assume it might be in
    4150             :         // sheet namedranges
    4151           0 :         RangeHelper aRange( thisRange );
    4152           0 :         uno::Reference< sheet::XSpreadsheet > xSheet = aRange.getSpreadSheet();
    4153           0 :         xProps.set( xSheet, uno::UNO_QUERY );
    4154             :         // impl here
    4155           0 :         xNamedRange = getNamedRange( xProps, thisRange );
    4156             :     }
    4157           0 :     if ( xProps.is() && xNamedRange.is() )
    4158             :     {
    4159           0 :         uno::Reference< sheet::XNamedRanges > xNamedRanges( xProps, uno::UNO_QUERY_THROW );
    4160           0 :         uno::Reference< sheet::XNamedRange > xName( xNamedRange, uno::UNO_QUERY_THROW );
    4161           0 :         return new ScVbaName( mxParent, mxContext, xName, xNamedRanges, getUnoModel() );
    4162             :     }
    4163           0 :     return uno::Reference< excel::XName >();
    4164             : }
    4165             : 
    4166             : uno::Reference< excel::XWorksheet >
    4167          30 : ScVbaRange::getWorksheet() throw (uno::RuntimeException, std::exception)
    4168             : {
    4169             :     // #TODO #FIXME parent should always be set up ( currently thats not
    4170             :     // the case )
    4171          30 :     uno::Reference< excel::XWorksheet > xSheet( getParent(), uno::UNO_QUERY );
    4172          30 :     if ( !xSheet.is() )
    4173             :     {
    4174           0 :         uno::Reference< table::XCellRange > xRange = mxRange;
    4175             : 
    4176           0 :         if ( mxRanges.is() ) // assign xRange to first range
    4177             :         {
    4178           0 :             uno::Reference< container::XIndexAccess > xIndex( mxRanges, uno::UNO_QUERY_THROW );
    4179           0 :             xRange.set( xIndex->getByIndex( 0 ), uno::UNO_QUERY_THROW );
    4180             :         }
    4181           0 :         ScDocShell* pDocShell = getDocShellFromRange(xRange);
    4182           0 :         RangeHelper rHelper(xRange);
    4183             :         // parent should be Thisworkbook
    4184           0 :            xSheet.set( new ScVbaWorksheet( uno::Reference< XHelperInterface >(), mxContext,rHelper.getSpreadSheet(),pDocShell->GetModel()) );
    4185             :     }
    4186          30 :     return xSheet;
    4187             : }
    4188             : 
    4189             : // #TODO remove this ugly application processing
    4190             : // Process an application Range request e.g. 'Range("a1,b2,a4:b6")
    4191             : uno::Reference< excel::XRange >
    4192        1342 : ScVbaRange::ApplicationRange( const uno::Reference< uno::XComponentContext >& xContext, const css::uno::Any &Cell1, const css::uno::Any &Cell2 ) throw (css::uno::RuntimeException)
    4193             : {
    4194             :     // Althought the documentation seems clear that Range without a
    4195             :     // qualifier then it's a shortcut for ActiveSheet.Range
    4196             :     // however, similarly Application.Range is apparently also a
    4197             :     // shortcut for ActiveSheet.Range
    4198             :     // The is however a subtle behavioural difference I've come across
    4199             :     // wrt to named ranges.
    4200             :     // If a named range "test" exists { Sheet1!$A1 } and the active sheet
    4201             :     // is Sheet2 then the following will fail
    4202             :     // msgbox ActiveSheet.Range("test").Address ' failes
    4203             :     // msgbox WorkSheets("Sheet2").Range("test").Address
    4204             :     // but !!!
    4205             :     // msgbox Range("test").Address ' works
    4206             :     // msgbox Application.Range("test").Address ' works
    4207             : 
    4208             :     // Single param Range
    4209        1342 :     OUString sRangeName;
    4210        1342 :     Cell1 >>= sRangeName;
    4211        1342 :     if ( Cell1.hasValue() && !Cell2.hasValue() && !sRangeName.isEmpty() )
    4212             :     {
    4213        1338 :         const static OUString sNamedRanges( "NamedRanges");
    4214        1338 :         uno::Reference< beans::XPropertySet > xPropSet( getCurrentExcelDoc(xContext), uno::UNO_QUERY_THROW );
    4215             : 
    4216        2464 :         uno::Reference< container::XNameAccess > xNamed( xPropSet->getPropertyValue( sNamedRanges ), uno::UNO_QUERY_THROW );
    4217        2464 :         uno::Reference< sheet::XCellRangeReferrer > xReferrer;
    4218             :         try
    4219             :         {
    4220        1338 :             xReferrer.set ( xNamed->getByName( sRangeName ), uno::UNO_QUERY );
    4221             :         }
    4222        1114 :         catch( uno::Exception& /*e*/ )
    4223             :         {
    4224             :             // do nothing
    4225             :         }
    4226        1338 :         if ( xReferrer.is() )
    4227             :         {
    4228         224 :             uno::Reference< table::XCellRange > xRange = xReferrer->getReferredCells();
    4229         224 :             if ( xRange.is() )
    4230             :             {
    4231         212 :                 uno::Reference< excel::XRange > xVbRange =  new ScVbaRange( excel::getUnoSheetModuleObj( xRange ), xContext, xRange );
    4232         212 :                 return xVbRange;
    4233          12 :             }
    4234        1126 :         }
    4235             :     }
    4236             : 
    4237        2260 :     uno::Reference< sheet::XSpreadsheetView > xView( getCurrentExcelDoc(xContext)->getCurrentController(), uno::UNO_QUERY );
    4238        2260 :     uno::Reference< table::XCellRange > xSheetRange( xView->getActiveSheet(), uno::UNO_QUERY_THROW );
    4239        1130 :     ScVbaRange* pRange = new ScVbaRange( excel::getUnoSheetModuleObj( xSheetRange ), xContext, xSheetRange );
    4240        2260 :     uno::Reference< excel::XRange > xVbSheetRange( pRange );
    4241        2472 :     return pRange->Range( Cell1, Cell2, true );
    4242             : }
    4243             : 
    4244             : // Helper functions for AutoFilter
    4245           8 : static ScDBData* lcl_GetDBData_Impl( ScDocShell* pDocShell, sal_Int16 nSheet )
    4246             : {
    4247           8 :     ScDBData* pRet = NULL;
    4248           8 :     if (pDocShell)
    4249             :     {
    4250           8 :         pRet = pDocShell->GetDocument().GetAnonymousDBData(nSheet);
    4251             :     }
    4252           8 :     return pRet;
    4253             : }
    4254             : 
    4255           6 : static void lcl_SelectAll( ScDocShell* pDocShell, ScQueryParam& aParam )
    4256             : {
    4257           6 :     if ( pDocShell )
    4258             :     {
    4259           6 :         ScViewData* pViewData = ScDocShell::GetViewData();
    4260           6 :         if ( pViewData )
    4261             :         {
    4262             :             OSL_TRACE("Pushing out SelectAll query");
    4263           6 :             pViewData->GetView()->Query( aParam, NULL, true );
    4264             :         }
    4265             :     }
    4266           6 : }
    4267             : 
    4268           8 : static ScQueryParam lcl_GetQueryParam( ScDocShell* pDocShell, sal_Int16 nSheet )
    4269             : {
    4270           8 :     ScDBData* pDBData = lcl_GetDBData_Impl( pDocShell, nSheet );
    4271           8 :     ScQueryParam aParam;
    4272           8 :     if (pDBData)
    4273             :     {
    4274           8 :         pDBData->GetQueryParam( aParam );
    4275             :     }
    4276           8 :     return aParam;
    4277             : }
    4278             : 
    4279           6 : static void lcl_SetAllQueryForField( ScDocShell* pDocShell, SCCOLROW nField, sal_Int16 nSheet )
    4280             : {
    4281           6 :     ScQueryParam aParam = lcl_GetQueryParam( pDocShell, nSheet );
    4282           6 :     aParam.RemoveEntryByField(nField);
    4283           6 :     lcl_SelectAll( pDocShell, aParam );
    4284           6 : }
    4285             : 
    4286             : // Modifies sCriteria, and nOp depending on the value of sCriteria
    4287          20 : static void lcl_setTableFieldsFromCriteria( OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField2& rFilterField )
    4288             : {
    4289             :     // #TODO make this more efficient and cycle through
    4290             :     // sCriteria1 character by character to pick up <,<>,=, * etc.
    4291             :     // right now I am more concerned with just getting it to work right
    4292             : 
    4293          20 :     sCriteria1 = sCriteria1.trim();
    4294             :     // table of translation of criteria text to FilterOperators
    4295             :     // <>searchtext - NOT_EQUAL
    4296             :     //  =searchtext - EQUAL
    4297             :     //  *searchtext - startwith
    4298             :     //  <>*searchtext - doesn't startwith
    4299             :     //  *searchtext* - contains
    4300             :     //  <>*searchtext* - doesn't contain
    4301             :     // [>|>=|<=|...]searchtext for GREATER_value, GREATER_EQUAL_value etc.
    4302          20 :     bool bIsNumeric = false;
    4303          20 :     if ( sCriteria1.startsWith( EQUALS ) )
    4304             :     {
    4305           8 :         if ( sCriteria1.getLength() == EQUALS.getLength() )
    4306           2 :             rFilterField.Operator = sheet::FilterOperator2::EMPTY;
    4307             :         else
    4308             :         {
    4309           6 :             rFilterField.Operator = sheet::FilterOperator2::EQUAL;
    4310           6 :             sCriteria1 = sCriteria1.copy( EQUALS.getLength() );
    4311           6 :             sCriteria1 = VBAToRegexp( sCriteria1 );
    4312             :             // UseRegularExpressions
    4313           6 :             if ( xDescProps.is() )
    4314           4 :                 xDescProps->setPropertyValue( "UseRegularExpressions", uno::Any( sal_True ) );
    4315             :         }
    4316             : 
    4317             :     }
    4318          12 :     else if ( sCriteria1.startsWith( NOTEQUALS ) )
    4319             :     {
    4320           4 :         if ( sCriteria1.getLength() == NOTEQUALS.getLength() )
    4321           2 :             rFilterField.Operator = sheet::FilterOperator2::NOT_EMPTY;
    4322             :         else
    4323             :         {
    4324           2 :             rFilterField.Operator = sheet::FilterOperator2::NOT_EQUAL;
    4325           2 :             sCriteria1 = sCriteria1.copy( NOTEQUALS.getLength() );
    4326           2 :             sCriteria1 = VBAToRegexp( sCriteria1 );
    4327             :             // UseRegularExpressions
    4328           2 :             if ( xDescProps.is() )
    4329           2 :                 xDescProps->setPropertyValue( "UseRegularExpressions", uno::Any( sal_True ) );
    4330             :         }
    4331             :     }
    4332           8 :     else if ( sCriteria1.startsWith( GREATERTHAN ) )
    4333             :     {
    4334           2 :         bIsNumeric = true;
    4335           2 :         if ( sCriteria1.startsWith( GREATERTHANEQUALS ) )
    4336             :         {
    4337           2 :             sCriteria1 = sCriteria1.copy( GREATERTHANEQUALS.getLength() );
    4338           2 :             rFilterField.Operator = sheet::FilterOperator2::GREATER_EQUAL;
    4339             :         }
    4340             :         else
    4341             :         {
    4342           0 :             sCriteria1 = sCriteria1.copy( GREATERTHAN.getLength() );
    4343           0 :             rFilterField.Operator = sheet::FilterOperator2::GREATER;
    4344             :         }
    4345             : 
    4346             :     }
    4347           6 :     else if ( sCriteria1.startsWith( LESSTHAN ) )
    4348             :     {
    4349           4 :         bIsNumeric = true;
    4350           4 :         if ( sCriteria1.startsWith( LESSTHANEQUALS ) )
    4351             :         {
    4352           2 :             sCriteria1 = sCriteria1.copy( LESSTHANEQUALS.getLength() );
    4353           2 :             rFilterField.Operator = sheet::FilterOperator2::LESS_EQUAL;
    4354             :         }
    4355             :         else
    4356             :         {
    4357           2 :             sCriteria1 = sCriteria1.copy( LESSTHAN.getLength() );
    4358           2 :             rFilterField.Operator = sheet::FilterOperator2::LESS;
    4359             :         }
    4360             : 
    4361             :     }
    4362             :     else
    4363           2 :         rFilterField.Operator = sheet::FilterOperator2::EQUAL;
    4364             : 
    4365          20 :     if ( bIsNumeric )
    4366             :     {
    4367           6 :         rFilterField.IsNumeric= sal_True;
    4368           6 :         rFilterField.NumericValue = sCriteria1.toDouble();
    4369             :     }
    4370          20 :     rFilterField.StringValue = sCriteria1;
    4371          20 : }
    4372             : 
    4373             : void SAL_CALL
    4374          24 : ScVbaRange::AutoFilter( const uno::Any& aField, const uno::Any& Criteria1, const uno::Any& Operator, const uno::Any& Criteria2, const uno::Any& VisibleDropDown )
    4375             :     throw (uno::RuntimeException, std::exception)
    4376             : {
    4377             :     // Is there an existing autofilter
    4378          24 :     RangeHelper thisRange( mxRange );
    4379          24 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4380          24 :     sal_Int16 nSheet = thisAddress.Sheet;
    4381          24 :     ScDocShell* pShell = getScDocShell();
    4382          24 :     bool bHasAuto = false;
    4383          48 :     uno::Reference< sheet::XDatabaseRange > xDataBaseRange = excel::GetAutoFiltRange( pShell, nSheet );
    4384          24 :     if ( xDataBaseRange.is() )
    4385          22 :         bHasAuto = true;
    4386             : 
    4387          48 :     uno::Reference< table::XCellRange > xFilterRange;
    4388          24 :     if ( !bHasAuto )
    4389             :     {
    4390           2 :         if (  m_Areas->getCount() > 1 )
    4391           0 :             throw uno::RuntimeException( STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY );
    4392             : 
    4393           2 :         table::CellRangeAddress autoFiltAddress;
    4394             :         //CurrentRegion()
    4395           2 :         if ( isSingleCellRange() )
    4396             :         {
    4397           0 :             uno::Reference< excel::XRange > xCurrent( CurrentRegion() );
    4398           0 :             if ( xCurrent.is() )
    4399             :             {
    4400           0 :                 ScVbaRange* pRange = getImplementation( xCurrent );
    4401           0 :                 if ( pRange )
    4402             :                 {
    4403           0 :                     if ( pRange->isSingleCellRange() )
    4404           0 :                        throw uno::RuntimeException("Can't create AutoFilter" );
    4405           0 :                     RangeHelper currentRegion( pRange->mxRange );
    4406           0 :                     autoFiltAddress = currentRegion.getCellRangeAddressable()->getRangeAddress();
    4407             :                 }
    4408           0 :             }
    4409             :         }
    4410             :         else // multi-cell range
    4411             :         {
    4412           2 :             RangeHelper multiCellRange( mxRange );
    4413           2 :             autoFiltAddress = multiCellRange.getCellRangeAddressable()->getRangeAddress();
    4414             :             // #163530# Filter box shows only entry of first row
    4415           2 :             ScDocument* pDocument = ( pShell ? &pShell->GetDocument() : NULL );
    4416           2 :             if ( pDocument )
    4417             :             {
    4418           2 :                 SCCOL nStartCol = autoFiltAddress.StartColumn;
    4419           2 :                 SCROW nStartRow = autoFiltAddress.StartRow;
    4420           2 :                 SCCOL nEndCol = autoFiltAddress.EndColumn;
    4421           2 :                 SCROW nEndRow = autoFiltAddress.EndRow;
    4422           2 :                 pDocument->GetDataArea( autoFiltAddress.Sheet, nStartCol, nStartRow, nEndCol, nEndRow, true, true );
    4423           2 :                 autoFiltAddress.StartColumn = nStartCol;
    4424           2 :                 autoFiltAddress.StartRow = nStartRow;
    4425           2 :                 autoFiltAddress.EndColumn = nEndCol;
    4426           2 :                 autoFiltAddress.EndRow = nEndRow;
    4427           2 :             }
    4428             :         }
    4429             : 
    4430           2 :         uno::Reference< sheet::XUnnamedDatabaseRanges > xDBRanges = excel::GetUnnamedDataBaseRanges( pShell );
    4431           2 :         if ( xDBRanges.is() )
    4432             :         {
    4433             :             OSL_TRACE("Going to add new autofilter range.. sheet %i", nSheet );
    4434           2 :             if ( !xDBRanges->hasByTable( nSheet ) )
    4435           2 :                 xDBRanges->setByTable( autoFiltAddress );
    4436           2 :             xDataBaseRange.set( xDBRanges->getByTable(nSheet ), uno::UNO_QUERY_THROW );
    4437             :         }
    4438           2 :         if ( !xDataBaseRange.is() )
    4439           0 :             throw uno::RuntimeException("Failed to find the autofilter placeholder range" );
    4440             : 
    4441           4 :         uno::Reference< beans::XPropertySet > xDBRangeProps( xDataBaseRange, uno::UNO_QUERY_THROW );
    4442             :         // set autofilt
    4443           2 :         xDBRangeProps->setPropertyValue( "AutoFilter", uno::Any(sal_True) );
    4444             :                 // set header (autofilter always need column headers)
    4445           4 :         uno::Reference< beans::XPropertySet > xFiltProps( xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY_THROW );
    4446           2 :         bool bHasColHeader = false;
    4447           2 :         ScDocument* pDoc = pShell ? &pShell->GetDocument() : NULL;
    4448           2 :         if (pDoc)
    4449             :         {
    4450           2 :             bHasColHeader = pDoc->HasColHeader(  static_cast< SCCOL >( autoFiltAddress.StartColumn ), static_cast< SCROW >( autoFiltAddress.StartRow ), static_cast< SCCOL >( autoFiltAddress.EndColumn ), static_cast< SCROW >( autoFiltAddress.EndRow ), static_cast< SCTAB >( autoFiltAddress.Sheet ) );
    4451             :         }
    4452           4 :         xFiltProps->setPropertyValue( "ContainsHeader", uno::Any( bHasColHeader ) );
    4453             :     }
    4454             : 
    4455          24 :     sal_Int32 nField = 0; // *IS* 1 based
    4456          48 :     OUString sCriteria1;
    4457          24 :     sal_Int32 nOperator = excel::XlAutoFilterOperator::xlAnd;
    4458             : 
    4459          24 :     bool bVisible = true;
    4460          24 :     VisibleDropDown >>= bVisible;
    4461             : 
    4462          24 :     if ( bVisible == bHasAuto ) // dropdown is displayed/notdisplayed as required
    4463          22 :         bVisible = false;
    4464          24 :     sheet::FilterConnection nConn = sheet::FilterConnection_AND;
    4465          24 :     double nCriteria1 = 0;
    4466             : 
    4467          24 :     bool bHasCritValue = Criteria1.hasValue();
    4468          24 :     bool bCritHasNumericValue = false; // not sure if a numeric criteria is possible
    4469          24 :     if ( bHasCritValue )
    4470          18 :         bCritHasNumericValue = ( Criteria1 >>= nCriteria1 );
    4471             : 
    4472          24 :     if (  !aField.hasValue() && ( Criteria1.hasValue() || Operator.hasValue() || Criteria2.hasValue() ) )
    4473           0 :         throw uno::RuntimeException();
    4474          24 :     bool bAll = false;
    4475          48 :     uno::Any Field( aField );
    4476          24 :     if ( !( Field >>= nField ) )
    4477             :     {
    4478           2 :         uno::Reference< script::XTypeConverter > xConverter = getTypeConverter( mxContext );
    4479             :         try
    4480             :         {
    4481           2 :             Field = xConverter->convertTo( aField, cppu::UnoType<sal_Int32>::get() );
    4482             :         }
    4483           2 :         catch( uno::Exception& )
    4484             :         {
    4485           2 :         }
    4486             :     }
    4487             :     // Use the normal uno api, sometimes e.g. when you want to use ALL as the filter
    4488             :     // we can't use refresh as the uno interface doesn't have a concept of ALL
    4489             :     // in this case we just call the core calc functionality -
    4490          24 :     if ( ( Field >>= nField )  )
    4491             :     {
    4492             :         uno::Reference< sheet::XSheetFilterDescriptor2 > xDesc(
    4493          22 :                 xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
    4494          22 :         if ( xDesc.is() )
    4495             :         {
    4496          22 :             uno::Sequence< sheet::TableFilterField2 > sTabFilts;
    4497          44 :             uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW );
    4498          22 :         if ( Criteria1.hasValue() )
    4499             :         {
    4500          18 :             sTabFilts.realloc( 1 );
    4501          18 :             sTabFilts[0].Operator = sheet::FilterOperator2::EQUAL;// sensible default
    4502          18 :             if ( !bCritHasNumericValue )
    4503             :             {
    4504          18 :                 Criteria1 >>= sCriteria1;
    4505          18 :                 sTabFilts[0].IsNumeric = bCritHasNumericValue;
    4506          18 :                 if ( bHasCritValue && !sCriteria1.isEmpty() )
    4507          18 :                     lcl_setTableFieldsFromCriteria( sCriteria1, xDescProps, sTabFilts[0]  );
    4508             :                 else
    4509           0 :                     bAll = true;
    4510             :             }
    4511             :             else // numeric
    4512             :             {
    4513           0 :                 sTabFilts[0].IsNumeric = sal_True;
    4514           0 :                 sTabFilts[0].NumericValue = nCriteria1;
    4515             :             }
    4516             :         }
    4517             :         else // no value specified
    4518           4 :             bAll = true;
    4519             :         // not sure what the relationship between Criteria1 and Operator is,
    4520             :         // e.g. can you have a Operator without a Criteria ? in openoffice it
    4521          22 :         if ( Operator.hasValue()  && ( Operator >>= nOperator ) )
    4522             :         {
    4523             :             // if it's a bottom/top Ten(Percent/Value) and there
    4524             :             // is no value specified for criteria1 set it to 10
    4525          12 :             if ( !bCritHasNumericValue && sCriteria1.isEmpty() && ( nOperator != excel::XlAutoFilterOperator::xlOr ) && ( nOperator != excel::XlAutoFilterOperator::xlAnd ) )
    4526             :             {
    4527           0 :                 sTabFilts[0].IsNumeric = sal_True;
    4528           0 :                 sTabFilts[0].NumericValue = 10;
    4529           0 :                 bAll = false;
    4530             :             }
    4531          12 :             switch ( nOperator )
    4532             :             {
    4533             :                 case excel::XlAutoFilterOperator::xlBottom10Items:
    4534           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_VALUES;
    4535           0 :                     break;
    4536             :                 case excel::XlAutoFilterOperator::xlBottom10Percent:
    4537           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_PERCENT;
    4538           0 :                     break;
    4539             :                 case excel::XlAutoFilterOperator::xlTop10Items:
    4540           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::TOP_VALUES;
    4541           0 :                     break;
    4542             :                 case excel::XlAutoFilterOperator::xlTop10Percent:
    4543           0 :                     sTabFilts[0].Operator = sheet::FilterOperator2::TOP_PERCENT;
    4544           0 :                     break;
    4545             :                 case excel::XlAutoFilterOperator::xlOr:
    4546           2 :                     nConn = sheet::FilterConnection_OR;
    4547           2 :                     break;
    4548             :                 case excel::XlAutoFilterOperator::xlAnd:
    4549          10 :                     nConn = sheet::FilterConnection_AND;
    4550          10 :                     break;
    4551             :                 default:
    4552           0 :                     throw uno::RuntimeException("UnknownOption" );
    4553             : 
    4554             :             }
    4555             : 
    4556             :         }
    4557          22 :         if ( !bAll )
    4558             :         {
    4559          18 :             sTabFilts[0].Connection = sheet::FilterConnection_AND;
    4560          18 :             sTabFilts[0].Field = (nField - 1);
    4561             : 
    4562          18 :             OUString sCriteria2;
    4563          18 :             if ( Criteria2.hasValue() ) // there is a Criteria2
    4564             :             {
    4565           2 :                 sTabFilts.realloc(2);
    4566           2 :                 sTabFilts[1].Field = sTabFilts[0].Field;
    4567           2 :                 sTabFilts[1].Connection = nConn;
    4568             : 
    4569           2 :                 if ( Criteria2 >>= sCriteria2 )
    4570             :                 {
    4571           2 :                     if ( !sCriteria2.isEmpty() )
    4572             :                     {
    4573           2 :                         uno::Reference< beans::XPropertySet > xProps;
    4574           2 :                         lcl_setTableFieldsFromCriteria( sCriteria2, xProps,  sTabFilts[1] );
    4575           2 :                         sTabFilts[1].IsNumeric = false;
    4576             :                     }
    4577             :                 }
    4578             :                 else // numeric
    4579             :                 {
    4580           0 :                     Criteria2 >>= sTabFilts[1].NumericValue;
    4581           0 :                     sTabFilts[1].IsNumeric = sal_True;
    4582           0 :                     sTabFilts[1].Operator = sheet::FilterOperator2::EQUAL;
    4583             :                 }
    4584          18 :             }
    4585             :         }
    4586             : 
    4587          22 :         xDesc->setFilterFields2( sTabFilts );
    4588          22 :         if ( !bAll )
    4589             :         {
    4590          18 :             xDataBaseRange->refresh();
    4591             :         }
    4592             :         else
    4593             :             // was 0 based now seems to be 1
    4594          26 :             lcl_SetAllQueryForField( pShell, nField, nSheet );
    4595          22 :         }
    4596             :     }
    4597             :     else
    4598             :     {
    4599             :         // this is just to toggle autofilter on and off ( not to be confused with
    4600             :         // a VisibleDropDown option combined with a field, in that case just the
    4601             :         // button should be disabled ) - currently we don't support that
    4602           2 :         uno::Reference< beans::XPropertySet > xDBRangeProps( xDataBaseRange, uno::UNO_QUERY_THROW );
    4603           2 :         if ( bHasAuto )
    4604             :         {
    4605             :             // find the any field with the query and select all
    4606           2 :             ScQueryParam aParam = lcl_GetQueryParam( pShell, nSheet );
    4607          18 :             for (SCSIZE i = 0; i< aParam.GetEntryCount(); ++i)
    4608             :             {
    4609          16 :                 ScQueryEntry& rEntry = aParam.GetEntry(i);
    4610          16 :                 if ( rEntry.bDoQuery )
    4611           2 :                     lcl_SetAllQueryForField( pShell, rEntry.nField, nSheet );
    4612             :             }
    4613             :             // remove exising filters
    4614             :             uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor(
    4615           4 :                     xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY );
    4616           2 :             if( xSheetFilterDescriptor.is() )
    4617           4 :                 xSheetFilterDescriptor->setFilterFields2( uno::Sequence< sheet::TableFilterField2 >() );
    4618             :         }
    4619           2 :         xDBRangeProps->setPropertyValue( "AutoFilter", uno::Any(!bHasAuto) );
    4620             : 
    4621          24 :     }
    4622          24 : }
    4623             : 
    4624             : void SAL_CALL
    4625           2 : ScVbaRange::Insert( const uno::Any& Shift, const uno::Any& /*CopyOrigin*/ ) throw (uno::RuntimeException, std::exception)
    4626             : {
    4627             :     // It appears ( from the web ) that the undocumented CopyOrigin
    4628             :     // param should contain member of enum XlInsertFormatOrigin
    4629             :     // which can have values xlFormatFromLeftOrAbove or xlFormatFromRightOrBelow
    4630             :     // #TODO investigate resultant behaviour using these constants
    4631             :     // currently just processing Shift
    4632             : 
    4633           2 :     sheet::CellInsertMode mode = sheet::CellInsertMode_NONE;
    4634           2 :     if ( Shift.hasValue() )
    4635             :     {
    4636           2 :         sal_Int32 nShift = 0;
    4637           2 :         Shift >>= nShift;
    4638           2 :         switch ( nShift )
    4639             :         {
    4640             :             case excel::XlInsertShiftDirection::xlShiftToRight:
    4641           2 :                 mode = sheet::CellInsertMode_RIGHT;
    4642           2 :                 break;
    4643             :             case excel::XlInsertShiftDirection::xlShiftDown:
    4644           0 :                 mode = sheet::CellInsertMode_DOWN;
    4645           0 :                 break;
    4646             :             default:
    4647           0 :                 throw uno::RuntimeException("Illegal parameter " );
    4648             :         }
    4649             :     }
    4650             :     else
    4651             :     {
    4652           0 :         if ( getRow() >=  getColumn() )
    4653           0 :             mode = sheet::CellInsertMode_DOWN;
    4654             :         else
    4655           0 :             mode = sheet::CellInsertMode_RIGHT;
    4656             :     }
    4657           2 :     RangeHelper thisRange( mxRange );
    4658           2 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4659           4 :     uno::Reference< sheet::XCellRangeMovement > xCellRangeMove( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    4660           2 :     xCellRangeMove->insertCells( thisAddress, mode );
    4661             : 
    4662             :     // Paste from clipboard only if the clipboard content was copied via VBA, and not already pasted via VBA again.
    4663             :     // "Insert" behavior should not depend on random clipboard content previously copied by the user.
    4664           2 :     ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
    4665           2 :     if ( pClipObj && pClipObj->GetUseInApi() )
    4666             :     {
    4667             :         // After the insert ( this range ) actually has moved
    4668           0 :         ScRange aRange( static_cast< SCCOL >( thisAddress.StartColumn ), static_cast< SCROW >( thisAddress.StartRow ), static_cast< SCTAB >( thisAddress.Sheet ), static_cast< SCCOL >( thisAddress.EndColumn ), static_cast< SCROW >( thisAddress.EndRow ), static_cast< SCTAB >( thisAddress.Sheet ) );
    4669           0 :         uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getDocShellFromRange( mxRange ) , aRange ) );
    4670           0 :         uno::Reference< excel::XRange > xVbaRange( new ScVbaRange( mxParent, mxContext, xRange, mbIsRows, mbIsColumns ) );
    4671           0 :         xVbaRange->PasteSpecial( uno::Any(), uno::Any(), uno::Any(), uno::Any() );
    4672           2 :     }
    4673           2 : }
    4674             : 
    4675             : void SAL_CALL
    4676           8 : ScVbaRange::Autofit() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    4677             : {
    4678           8 :     sal_Int32 nLen = m_Areas->getCount();
    4679           8 :     if ( nLen > 1 )
    4680             :     {
    4681           4 :         for ( sal_Int32 index = 1; index != nLen; ++index )
    4682             :         {
    4683           2 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32(index) ), uno::Any() ), uno::UNO_QUERY_THROW );
    4684           2 :             xRange->Autofit();
    4685           2 :         }
    4686          10 :         return;
    4687             :     }
    4688             :         // if the range is a not a row or column range autofit will
    4689             :         // throw an error
    4690             : 
    4691           6 :         if ( !( mbIsColumns || mbIsRows ) )
    4692           0 :             DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString());
    4693           6 :         ScDocShell* pDocShell = getDocShellFromRange( mxRange );
    4694           6 :         if ( pDocShell )
    4695             :         {
    4696           6 :             RangeHelper thisRange( mxRange );
    4697           6 :             table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4698             : 
    4699          12 :             std::vector<sc::ColRowSpan> aColArr(1, sc::ColRowSpan(thisAddress.StartColumn,thisAddress.EndColumn));
    4700           6 :             bool bDirection = true;
    4701           6 :             if ( mbIsRows )
    4702             :             {
    4703           2 :                 bDirection = false;
    4704           2 :                 aColArr[0].mnStart = thisAddress.StartRow;
    4705           2 :                 aColArr[0].mnEnd = thisAddress.EndRow;
    4706             :             }
    4707           6 :             pDocShell->GetDocFunc().SetWidthOrHeight(
    4708          18 :                 bDirection, aColArr, thisAddress.Sheet, SC_SIZE_OPTIMAL, 0, true, true);
    4709             :     }
    4710             : }
    4711             : 
    4712             : uno::Any SAL_CALL
    4713           0 : ScVbaRange::Hyperlinks( const uno::Any& aIndex ) throw (uno::RuntimeException, std::exception)
    4714             : {
    4715             :     /*  The range object always returns a new Hyperlinks object containing a
    4716             :         fixed list of existing hyperlinks in the range.
    4717             :         See vbahyperlinks.hxx for more details. */
    4718             : 
    4719             :     // get the global hyperlink object of the sheet (sheet should always be the parent of a Range object)
    4720           0 :     uno::Reference< excel::XWorksheet > xWorksheet( getParent(), uno::UNO_QUERY_THROW );
    4721           0 :     uno::Reference< excel::XHyperlinks > xSheetHlinks( xWorksheet->Hyperlinks( uno::Any() ), uno::UNO_QUERY_THROW );
    4722           0 :     ScVbaHyperlinksRef xScSheetHlinks( dynamic_cast< ScVbaHyperlinks* >( xSheetHlinks.get() ) );
    4723           0 :     if( !xScSheetHlinks.is() )
    4724           0 :         throw uno::RuntimeException("Cannot obtain hyperlinks implementation object" );
    4725             : 
    4726             :     // create a new local hyperlinks object based on the sheet hyperlinks
    4727           0 :     ScVbaHyperlinksRef xHlinks( new ScVbaHyperlinks( getParent(), mxContext, xScSheetHlinks, getScRangeList() ) );
    4728           0 :     if( aIndex.hasValue() )
    4729           0 :         return xHlinks->Item( aIndex, uno::Any() );
    4730           0 :     return uno::Any( uno::Reference< excel::XHyperlinks >( xHlinks.get() ) );
    4731             : }
    4732             : 
    4733             : css::uno::Reference< excel::XValidation > SAL_CALL
    4734          40 : ScVbaRange::getValidation() throw (css::uno::RuntimeException, std::exception)
    4735             : {
    4736          40 :     if ( !m_xValidation.is() )
    4737           2 :         m_xValidation = new ScVbaValidation( this, mxContext, mxRange );
    4738          40 :     return m_xValidation;
    4739             : }
    4740             : 
    4741             : namespace {
    4742             : 
    4743           0 : sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCell >& rxCell ) throw (uno::RuntimeException)
    4744             : {
    4745             :     /*  TODO/FIXME: We need an apostroph-prefix property at the cell to
    4746             :         implement this correctly. For now, return an apostroph for every text
    4747             :         cell.
    4748             : 
    4749             :         TODO/FIXME: When Application.TransitionNavigKeys is supported and true,
    4750             :         this function needs to inspect the cell formatting and return different
    4751             :         prefixes according to the horizontal cell alignment.
    4752             :      */
    4753           0 :     return (rxCell->getType() == table::CellContentType_TEXT) ? '\'' : 0;
    4754             : }
    4755             : 
    4756           0 : sal_Unicode lclGetPrefixChar( const uno::Reference< table::XCellRange >& rxRange ) throw (uno::RuntimeException)
    4757             : {
    4758             :     /*  This implementation is able to handle different prefixes (needed if
    4759             :         Application.TransitionNavigKeys is true). The function lclGetPrefixChar
    4760             :         for single cells called from here may return any prefix. If that
    4761             :         function returns an empty prefix (NUL character) or different non-empty
    4762             :         prefixes for two cells, this function returns 0.
    4763             :      */
    4764           0 :     sal_Unicode cCurrPrefix = 0;
    4765           0 :     table::CellRangeAddress aRangeAddr = lclGetRangeAddress( rxRange );
    4766           0 :     sal_Int32 nEndCol = aRangeAddr.EndColumn - aRangeAddr.StartColumn;
    4767           0 :     sal_Int32 nEndRow = aRangeAddr.EndRow - aRangeAddr.StartRow;
    4768           0 :     for( sal_Int32 nRow = 0; nRow <= nEndRow; ++nRow )
    4769             :     {
    4770           0 :         for( sal_Int32 nCol = 0; nCol <= nEndCol; ++nCol )
    4771             :         {
    4772           0 :             uno::Reference< table::XCell > xCell( rxRange->getCellByPosition( nCol, nRow ), uno::UNO_SET_THROW );
    4773           0 :             sal_Unicode cNewPrefix = lclGetPrefixChar( xCell );
    4774           0 :             if( (cNewPrefix == 0) || ((cCurrPrefix != 0) && (cNewPrefix != cCurrPrefix)) )
    4775           0 :                 return 0;
    4776           0 :             cCurrPrefix = cNewPrefix;
    4777           0 :         }
    4778             :     }
    4779             :     // all cells contain the same prefix - return it
    4780           0 :     return cCurrPrefix;
    4781             : }
    4782             : 
    4783           0 : sal_Unicode lclGetPrefixChar( const uno::Reference< sheet::XSheetCellRangeContainer >& rxRanges ) throw (uno::RuntimeException)
    4784             : {
    4785           0 :     sal_Unicode cCurrPrefix = 0;
    4786           0 :     uno::Reference< container::XEnumerationAccess > xRangesEA( rxRanges, uno::UNO_QUERY_THROW );
    4787           0 :     uno::Reference< container::XEnumeration > xRangesEnum( xRangesEA->createEnumeration(), uno::UNO_SET_THROW );
    4788           0 :     while( xRangesEnum->hasMoreElements() )
    4789             :     {
    4790           0 :         uno::Reference< table::XCellRange > xRange( xRangesEnum->nextElement(), uno::UNO_QUERY_THROW );
    4791           0 :         sal_Unicode cNewPrefix = lclGetPrefixChar( xRange );
    4792           0 :         if( (cNewPrefix == 0) || ((cCurrPrefix != 0) && (cNewPrefix != cCurrPrefix)) )
    4793           0 :             return 0;
    4794           0 :         cCurrPrefix = cNewPrefix;
    4795           0 :     }
    4796             :     // all ranges contain the same prefix - return it
    4797           0 :     return cCurrPrefix;
    4798             : }
    4799             : 
    4800           0 : inline uno::Any lclGetPrefixVariant( sal_Unicode cPrefixChar )
    4801             : {
    4802           0 :     return uno::Any( (cPrefixChar == 0) ? OUString() : OUString( cPrefixChar ) );
    4803             : }
    4804             : 
    4805             : } // namespace
    4806             : 
    4807           0 : uno::Any SAL_CALL ScVbaRange::getPrefixCharacter() throw (uno::RuntimeException, std::exception)
    4808             : {
    4809             :     /*  (1) If Application.TransitionNavigKeys is false, this function returns
    4810             :         an apostroph character if the text cell begins with an apostroph
    4811             :         character (formula return values are not taken into account); otherwise
    4812             :         an empty string.
    4813             : 
    4814             :         (2) If Application.TransitionNavigKeys is true, this function returns
    4815             :         an apostroph character, if the cell is left-aligned; a double-quote
    4816             :         character, if the cell is right-aligned; a circumflex character, if the
    4817             :         cell is centered; a backslash character, if the cell is set to filled;
    4818             :         or an empty string, if nothing of the above.
    4819             : 
    4820             :         If a range or a list of ranges contains texts with leading apostroph
    4821             :         character as well as other cells, this function returns an empty
    4822             :         string.
    4823             :      */
    4824             : 
    4825           0 :     if( mxRange.is() )
    4826           0 :         return lclGetPrefixVariant( lclGetPrefixChar( mxRange ) );
    4827           0 :     if( mxRanges.is() )
    4828           0 :         return lclGetPrefixVariant( lclGetPrefixChar( mxRanges ) );
    4829           0 :     throw uno::RuntimeException("Unexpected empty Range object" );
    4830             : }
    4831             : 
    4832           6 : uno::Any ScVbaRange::getShowDetail() throw ( css::uno::RuntimeException, std::exception)
    4833             : {
    4834             :     // #FIXME, If the specified range is in a PivotTable report
    4835             : 
    4836             :     // In MSO VBA, the specified range must be a single summary column or row in an outline. otherwise throw exception
    4837           6 :     if( m_Areas->getCount() > 1 )
    4838           0 :         throw uno::RuntimeException("Can not get Range.ShowDetail attribute " );
    4839             : 
    4840           6 :     bool bShowDetail = false;
    4841             : 
    4842           6 :     RangeHelper helper( mxRange );
    4843          12 :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = helper.getSheetCellCursor();
    4844           6 :     xSheetCellCursor->collapseToCurrentRegion();
    4845          12 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    4846           6 :     table::CellRangeAddress aOutlineAddress = xCellRangeAddressable->getRangeAddress();
    4847             : 
    4848             :     // check if the specified range is a single summary column or row.
    4849           6 :     table::CellRangeAddress thisAddress = helper.getCellRangeAddressable()->getRangeAddress();
    4850           6 :     if( (thisAddress.StartRow == thisAddress.EndRow &&  thisAddress.EndRow == aOutlineAddress.EndRow ) ||
    4851           0 :         (thisAddress.StartColumn == thisAddress.EndColumn && thisAddress.EndColumn == aOutlineAddress.EndColumn ))
    4852             :     {
    4853           6 :         bool bColumn =thisAddress.StartRow == thisAddress.EndRow ? false:sal_True;
    4854           6 :         ScDocument& rDoc = getDocumentFromRange( mxRange );
    4855           6 :         ScOutlineTable* pOutlineTable = rDoc.GetOutlineTable(static_cast<SCTAB>(thisAddress.Sheet), true);
    4856           6 :         const ScOutlineArray& rOutlineArray =  bColumn ? pOutlineTable->GetColArray(): pOutlineTable->GetRowArray();
    4857           6 :         SCCOLROW nPos = bColumn ? (SCCOLROW)(thisAddress.EndColumn-1):(SCCOLROW)(thisAddress.EndRow-1);
    4858           6 :         const ScOutlineEntry* pEntry = rOutlineArray.GetEntryByPos( 0, nPos );
    4859           6 :         if( pEntry )
    4860             :         {
    4861           6 :             bShowDetail = !pEntry->IsHidden();
    4862           6 :             return uno::makeAny( bShowDetail );
    4863           0 :         }
    4864             :     }
    4865             :     else
    4866             :     {
    4867           0 :         throw uno::RuntimeException("Can not set Range.ShowDetail attribute" );
    4868             :     }
    4869           6 :     return aNULL();
    4870             : }
    4871             : 
    4872           4 : void ScVbaRange::setShowDetail(const uno::Any& aShowDetail) throw ( css::uno::RuntimeException, std::exception)
    4873             : {
    4874             :     // #FIXME, If the specified range is in a PivotTable report
    4875             : 
    4876             :     // In MSO VBA, the specified range must be a single summary column or row in an outline. otherwise throw exception
    4877           4 :     if( m_Areas->getCount() > 1 )
    4878           0 :         throw uno::RuntimeException("Can not set Range.ShowDetail attribute" );
    4879             : 
    4880           4 :     bool bShowDetail = extractBoolFromAny( aShowDetail );
    4881             : 
    4882           4 :     RangeHelper helper( mxRange );
    4883           8 :     uno::Reference< sheet::XSheetCellCursor > xSheetCellCursor = helper.getSheetCellCursor();
    4884           4 :     xSheetCellCursor->collapseToCurrentRegion();
    4885           8 :     uno::Reference< sheet::XCellRangeAddressable > xCellRangeAddressable(xSheetCellCursor, uno::UNO_QUERY_THROW);
    4886           4 :     table::CellRangeAddress aOutlineAddress = xCellRangeAddressable->getRangeAddress();
    4887             : 
    4888             :     // check if the specified range is a single summary column or row.
    4889           4 :     table::CellRangeAddress thisAddress = helper.getCellRangeAddressable()->getRangeAddress();
    4890           4 :     if( (thisAddress.StartRow == thisAddress.EndRow &&  thisAddress.EndRow == aOutlineAddress.EndRow ) ||
    4891           0 :         (thisAddress.StartColumn == thisAddress.EndColumn && thisAddress.EndColumn == aOutlineAddress.EndColumn ))
    4892             :     {
    4893             :         // #FIXME, seems there is a different behavior between MSO and OOo.
    4894             :         //  In OOo, the showDetail will show all the level entrys, while only show the first level entry in MSO
    4895           4 :         uno::Reference< sheet::XSheetOutline > xSheetOutline( helper.getSpreadSheet(), uno::UNO_QUERY_THROW );
    4896           4 :         if( bShowDetail )
    4897           2 :             xSheetOutline->showDetail( aOutlineAddress );
    4898             :         else
    4899           2 :             xSheetOutline->hideDetail( aOutlineAddress );
    4900             :     }
    4901             :     else
    4902             :     {
    4903           0 :         throw uno::RuntimeException("Can not set Range.ShowDetail attribute" );
    4904           4 :     }
    4905           4 : }
    4906             : 
    4907             : uno::Reference< excel::XRange > SAL_CALL
    4908           2 : ScVbaRange::MergeArea() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    4909             : {
    4910           2 :     uno::Reference< sheet::XSheetCellRange > xMergeShellCellRange(mxRange->getCellRangeByPosition(0,0,0,0), uno::UNO_QUERY_THROW);
    4911           4 :     uno::Reference< sheet::XSheetCellCursor > xMergeSheetCursor(xMergeShellCellRange->getSpreadsheet()->createCursorByRange( xMergeShellCellRange ), uno::UNO_QUERY_THROW);
    4912           2 :     if( xMergeSheetCursor.is() )
    4913             :     {
    4914           2 :         xMergeSheetCursor->collapseToMergedArea();
    4915           2 :         uno::Reference<sheet::XCellRangeAddressable> xMergeCellAddress(xMergeSheetCursor, uno::UNO_QUERY_THROW);
    4916           2 :         if( xMergeCellAddress.is() )
    4917             :         {
    4918           2 :             table::CellRangeAddress aCellAddress = xMergeCellAddress->getRangeAddress();
    4919           2 :             if( aCellAddress.StartColumn ==0 && aCellAddress.EndColumn==0 &&
    4920           0 :                 aCellAddress.StartRow==0 && aCellAddress.EndRow==0)
    4921             :             {
    4922           0 :                 return new ScVbaRange( mxParent,mxContext,mxRange );
    4923             :             }
    4924             :             else
    4925             :             {
    4926             :                 ScRange refRange( static_cast< SCCOL >( aCellAddress.StartColumn ), static_cast< SCROW >( aCellAddress.StartRow ), static_cast< SCTAB >( aCellAddress.Sheet ),
    4927           2 :                                   static_cast< SCCOL >( aCellAddress.EndColumn ), static_cast< SCROW >( aCellAddress.EndRow ), static_cast< SCTAB >( aCellAddress.Sheet ) );
    4928           2 :                 uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getScDocShell() , refRange ) );
    4929           2 :                 return new ScVbaRange( mxParent, mxContext,xRange );
    4930             :             }
    4931           0 :         }
    4932             :     }
    4933           2 :     return new ScVbaRange( mxParent, mxContext, mxRange );
    4934             : }
    4935             : 
    4936             : void SAL_CALL
    4937           0 : ScVbaRange::PrintOut( const uno::Any& From, const uno::Any& To, const uno::Any& Copies, const uno::Any& Preview, const uno::Any& ActivePrinter, const uno::Any& PrintToFile, const uno::Any& Collate, const uno::Any& PrToFileName ) throw (uno::RuntimeException, std::exception)
    4938             : {
    4939           0 :     ScDocShell* pShell = NULL;
    4940             : 
    4941           0 :     sal_Int32 nItems = m_Areas->getCount();
    4942           0 :     uno::Sequence<  table::CellRangeAddress > printAreas( nItems );
    4943           0 :     uno::Reference< sheet::XPrintAreas > xPrintAreas;
    4944           0 :     for ( sal_Int32 index=1; index <= nItems; ++index )
    4945             :     {
    4946           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    4947             : 
    4948           0 :         RangeHelper thisRange( xRange->getCellRange() );
    4949           0 :         table::CellRangeAddress rangeAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4950           0 :         if ( index == 1 )
    4951             :         {
    4952           0 :             ScVbaRange* pRange = getImplementation( xRange );
    4953             :             // initialise the doc shell and the printareas
    4954           0 :             pShell = getDocShellFromRange( pRange->mxRange );
    4955           0 :             xPrintAreas.set( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    4956             :         }
    4957           0 :         printAreas[ index - 1 ] = rangeAddress;
    4958           0 :     }
    4959           0 :     if ( pShell )
    4960             :     {
    4961           0 :         if ( xPrintAreas.is() )
    4962             :         {
    4963           0 :             xPrintAreas->setPrintAreas( printAreas );
    4964           0 :             uno::Reference< frame::XModel > xModel = pShell->GetModel();
    4965           0 :             PrintOutHelper( excel::getBestViewShell( xModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, true );
    4966             :         }
    4967           0 :     }
    4968           0 : }
    4969             : 
    4970             : void SAL_CALL
    4971           0 : ScVbaRange::AutoFill(  const uno::Reference< excel::XRange >& Destination, const uno::Any& Type ) throw (uno::RuntimeException, std::exception)
    4972             : {
    4973           0 :     uno::Reference< excel::XRange > xDest( Destination, uno::UNO_QUERY_THROW );
    4974           0 :     ScVbaRange* pRange = getImplementation( xDest );
    4975           0 :     RangeHelper destRangeHelper( pRange->mxRange );
    4976           0 :     table::CellRangeAddress destAddress = destRangeHelper.getCellRangeAddressable()->getRangeAddress();
    4977             : 
    4978           0 :     RangeHelper thisRange( mxRange );
    4979           0 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    4980           0 :     ScRange sourceRange;
    4981           0 :     ScRange destRange;
    4982             : 
    4983           0 :     ScUnoConversion::FillScRange( destRange, destAddress );
    4984           0 :     ScUnoConversion::FillScRange( sourceRange, thisAddress );
    4985             : 
    4986           0 :     FillDir eDir = FILL_TO_BOTTOM;
    4987           0 :     double fStep = 1.0;
    4988             : 
    4989           0 :     ScRange aRange( destRange );
    4990           0 :     ScRange aSourceRange( destRange );
    4991             : 
    4992             :     // default to include the number of Rows in the source range;
    4993           0 :     SCCOLROW nSourceCount = ( sourceRange.aEnd.Row() - sourceRange.aStart.Row() ) + 1;
    4994           0 :     SCCOLROW nCount = 0;
    4995             : 
    4996           0 :     if ( sourceRange != destRange )
    4997             :     {
    4998             :         // Find direction of fill, vertical or horizontal
    4999           0 :         if ( sourceRange.aStart == destRange.aStart )
    5000             :         {
    5001           0 :             if ( sourceRange.aEnd.Row() == destRange.aEnd.Row() )
    5002             :             {
    5003           0 :                 nSourceCount = ( sourceRange.aEnd.Col() - sourceRange.aStart.Col() + 1 );
    5004           0 :                 aSourceRange.aEnd.SetCol( static_cast<SCCOL>( aSourceRange.aStart.Col() + nSourceCount - 1 ) );
    5005           0 :                 eDir = FILL_TO_RIGHT;
    5006           0 :                 nCount = aRange.aEnd.Col() - aSourceRange.aEnd.Col();
    5007             :             }
    5008           0 :             else if ( sourceRange.aEnd.Col() == destRange.aEnd.Col() )
    5009             :             {
    5010           0 :                 aSourceRange.aEnd.SetRow( static_cast<SCROW>( aSourceRange.aStart.Row() + nSourceCount ) - 1 );
    5011           0 :                 nCount = aRange.aEnd.Row() - aSourceRange.aEnd.Row();
    5012           0 :                 eDir = FILL_TO_BOTTOM;
    5013             :             }
    5014             :         }
    5015             : 
    5016           0 :         else if ( aSourceRange.aEnd == destRange.aEnd )
    5017             :         {
    5018           0 :             if ( sourceRange.aStart.Col() == destRange.aStart.Col() )
    5019             :             {
    5020           0 :                 aSourceRange.aStart.SetRow( static_cast<SCROW>( aSourceRange.aEnd.Row() - nSourceCount + 1 ) );
    5021           0 :                 nCount = aSourceRange.aStart.Row() - aRange.aStart.Row();
    5022           0 :                 eDir = FILL_TO_TOP;
    5023           0 :                 fStep = -fStep;
    5024             :             }
    5025           0 :             else if ( sourceRange.aStart.Row() == destRange.aStart.Row() )
    5026             :             {
    5027           0 :                 nSourceCount = ( sourceRange.aEnd.Col() - sourceRange.aStart.Col() ) + 1;
    5028           0 :                 aSourceRange.aStart.SetCol( static_cast<SCCOL>( aSourceRange.aEnd.Col() - nSourceCount + 1 ) );
    5029           0 :                 nCount = aSourceRange.aStart.Col() - aRange.aStart.Col();
    5030           0 :                 eDir = FILL_TO_LEFT;
    5031           0 :                 fStep = -fStep;
    5032             :             }
    5033             :         }
    5034             :     }
    5035             : 
    5036           0 :     FillCmd eCmd = FILL_AUTO;
    5037           0 :     FillDateCmd eDateCmd = FILL_DAY;
    5038             : 
    5039           0 :     if ( Type.hasValue() )
    5040             :     {
    5041           0 :         sal_Int16 nFillType = excel::XlAutoFillType::xlFillDefault;
    5042           0 :         Type >>= nFillType;
    5043           0 :         switch ( nFillType )
    5044             :         {
    5045             :             case excel::XlAutoFillType::xlFillCopy:
    5046           0 :                 eCmd =  FILL_SIMPLE;
    5047           0 :                 fStep = 0.0;
    5048           0 :                 break;
    5049             :             case excel::XlAutoFillType::xlFillDays:
    5050           0 :                 eCmd = FILL_DATE;
    5051           0 :                 break;
    5052             :             case excel::XlAutoFillType::xlFillMonths:
    5053           0 :                 eCmd = FILL_DATE;
    5054           0 :                 eDateCmd = FILL_MONTH;
    5055           0 :                 break;
    5056             :             case excel::XlAutoFillType::xlFillWeekdays:
    5057           0 :                 eCmd = FILL_DATE;
    5058           0 :                 eDateCmd = FILL_WEEKDAY;
    5059           0 :                 break;
    5060             :             case excel::XlAutoFillType::xlFillYears:
    5061           0 :                 eCmd = FILL_DATE;
    5062           0 :                 eDateCmd = FILL_YEAR;
    5063           0 :                 break;
    5064             :             case excel::XlAutoFillType::xlGrowthTrend:
    5065           0 :                 eCmd = FILL_GROWTH;
    5066           0 :                 break;
    5067             :             case excel::XlAutoFillType::xlFillFormats:
    5068           0 :                 throw uno::RuntimeException("xlFillFormat not supported for AutoFill" );
    5069             :             case excel::XlAutoFillType::xlFillValues:
    5070             :             case excel::XlAutoFillType::xlFillSeries:
    5071             :             case excel::XlAutoFillType::xlLinearTrend:
    5072           0 :                 eCmd = FILL_LINEAR;
    5073           0 :                 break;
    5074             :             case excel::XlAutoFillType::xlFillDefault:
    5075             :             default:
    5076           0 :                 eCmd =  FILL_AUTO;
    5077           0 :                 break;
    5078             :         }
    5079             :     }
    5080           0 :     double fEndValue =  MAXDOUBLE;
    5081           0 :     ScDocShell* pDocSh = getDocShellFromRange( mxRange );
    5082           0 :     pDocSh->GetDocFunc().FillAuto( aSourceRange, NULL, eDir, eCmd, eDateCmd,
    5083           0 :                                    nCount, fStep, fEndValue, true, true );
    5084           0 : }
    5085             : sal_Bool SAL_CALL
    5086           2 : ScVbaRange::GoalSeek( const uno::Any& Goal, const uno::Reference< excel::XRange >& ChangingCell ) throw (uno::RuntimeException, std::exception)
    5087             : {
    5088           2 :     ScDocShell* pDocShell = getScDocShell();
    5089           2 :     bool bRes = true;
    5090           2 :     ScVbaRange* pRange = static_cast< ScVbaRange* >( ChangingCell.get() );
    5091           2 :     if ( pDocShell && pRange )
    5092             :     {
    5093           2 :         uno::Reference< sheet::XGoalSeek > xGoalSeek(  pDocShell->GetModel(), uno::UNO_QUERY_THROW );
    5094           4 :         RangeHelper thisRange( mxRange );
    5095           2 :         table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    5096           4 :         RangeHelper changingCellRange( pRange->mxRange );
    5097           2 :         table::CellRangeAddress changingCellAddr = changingCellRange.getCellRangeAddressable()->getRangeAddress();
    5098           4 :         OUString sGoal = getAnyAsString( Goal );
    5099           2 :         table::CellAddress thisCell( thisAddress.Sheet, thisAddress.StartColumn, thisAddress.StartRow );
    5100           2 :         table::CellAddress changingCell( changingCellAddr.Sheet, changingCellAddr.StartColumn, changingCellAddr.StartRow );
    5101           2 :         sheet::GoalResult res = xGoalSeek->seekGoal( thisCell, changingCell, sGoal );
    5102           2 :         ChangingCell->setValue( uno::makeAny( res.Result ) );
    5103             : 
    5104             :         // openoffice behaves differently, result is 0 if the divergence is too great
    5105             :                 // but... if it detects 0 is the value it requires then it will use that
    5106             :         // e.g. divergence & result both = 0.0 does NOT mean there is an error
    5107           2 :         if ( ( res.Divergence != 0.0 ) && ( res.Result == 0.0 ) )
    5108           2 :             bRes = false;
    5109             :     }
    5110             :     else
    5111           0 :         bRes = false;
    5112           2 :     return bRes;
    5113             : }
    5114             : 
    5115             : void
    5116           4 : ScVbaRange::Calculate(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5117             : {
    5118           4 :     getWorksheet()->Calculate();
    5119           4 : }
    5120             : 
    5121             : uno::Reference< excel::XRange > SAL_CALL
    5122          40 : ScVbaRange::Item( const uno::Any& row, const uno::Any& column ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5123             : {
    5124          40 :     if ( mbIsRows || mbIsColumns )
    5125             :     {
    5126          24 :         if ( column.hasValue() )
    5127           0 :             DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5128          24 :         uno::Reference< excel::XRange > xRange;
    5129          24 :         if ( mbIsColumns )
    5130          14 :             xRange = Columns( row );
    5131             :         else
    5132          10 :             xRange = Rows( row );
    5133          24 :         return xRange;
    5134             :     }
    5135          16 :     return Cells( row, column );
    5136             : }
    5137             : 
    5138             : void
    5139           2 : ScVbaRange::AutoOutline(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5140             : {
    5141             :     // #TODO #FIXME needs to check for summary row/col ( whatever they are )
    5142             :     // not valid for multi Area Addresses
    5143           2 :     if ( m_Areas->getCount() > 1 )
    5144           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY);
    5145             :     // So needs to either span an entire Row or a just be a single cell
    5146             :     // ( that contains a summary RowColumn )
    5147             :     // also the Single cell cause doesn't seem to be handled specially in
    5148             :     // this code ( ported from the helperapi RangeImpl.java,
    5149             :     // RangeRowsImpl.java, RangesImpl.java, RangeSingleCellImpl.java
    5150           2 :     RangeHelper thisRange( mxRange );
    5151           2 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    5152             : 
    5153           2 :     if ( isSingleCellRange() || mbIsRows )
    5154             :     {
    5155           2 :         uno::Reference< sheet::XSheetOutline > xSheetOutline( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    5156           2 :         xSheetOutline->autoOutline( thisAddress );
    5157             :     }
    5158             :     else
    5159           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString());
    5160           2 : }
    5161             : 
    5162             : void SAL_CALL
    5163          16 : ScVbaRange:: ClearOutline(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5164             : {
    5165          16 :     if ( m_Areas->getCount() > 1 )
    5166             :     {
    5167           4 :         sal_Int32 nItems = m_Areas->getCount();
    5168          12 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    5169             :         {
    5170           8 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5171           8 :             xRange->ClearOutline();
    5172           8 :         }
    5173           8 :         return;
    5174             :     }
    5175          12 :     RangeHelper thisRange( mxRange );
    5176          24 :     uno::Reference< sheet::XSheetOutline > xSheetOutline( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    5177          24 :     xSheetOutline->clearOutline();
    5178             : }
    5179             : 
    5180             : void
    5181          12 : ScVbaRange::groupUnGroup( bool bUnGroup ) throw ( script::BasicErrorException, uno::RuntimeException )
    5182             : {
    5183          12 :     if ( m_Areas->getCount() > 1 )
    5184           0 :          DebugHelper::basicexception(SbERR_METHOD_FAILED, STR_ERRORMESSAGE_APPLIESTOSINGLERANGEONLY);
    5185          12 :     table::TableOrientation nOrient = table::TableOrientation_ROWS;
    5186          12 :     if ( mbIsColumns )
    5187           0 :         nOrient = table::TableOrientation_COLUMNS;
    5188          12 :     RangeHelper thisRange( mxRange );
    5189          12 :     table::CellRangeAddress thisAddress = thisRange.getCellRangeAddressable()->getRangeAddress();
    5190          24 :     uno::Reference< sheet::XSheetOutline > xSheetOutline( thisRange.getSpreadSheet(), uno::UNO_QUERY_THROW );
    5191          12 :     if ( bUnGroup )
    5192           4 :             xSheetOutline->ungroup( thisAddress, nOrient );
    5193             :     else
    5194          20 :             xSheetOutline->group( thisAddress, nOrient );
    5195          12 : }
    5196             : 
    5197             : void SAL_CALL
    5198           8 : ScVbaRange::Group(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5199             : {
    5200           8 :     groupUnGroup();
    5201           8 : }
    5202             : void SAL_CALL
    5203           4 : ScVbaRange::Ungroup(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5204             : {
    5205           4 :     groupUnGroup(true);
    5206           4 : }
    5207             : 
    5208          10 : static void lcl_mergeCellsOfRange( const uno::Reference< table::XCellRange >& xCellRange, bool _bMerge = true ) throw ( uno::RuntimeException )
    5209             : {
    5210          10 :         uno::Reference< util::XMergeable > xMergeable( xCellRange, uno::UNO_QUERY_THROW );
    5211          10 :         xMergeable->merge(_bMerge);
    5212          10 : }
    5213             : void SAL_CALL
    5214           8 : ScVbaRange::Merge( const uno::Any& Across ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5215             : {
    5216           8 :     if ( m_Areas->getCount() > 1 )
    5217             :     {
    5218           0 :         sal_Int32 nItems = m_Areas->getCount();
    5219           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    5220             :         {
    5221           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5222           0 :             xRange->Merge(Across);
    5223           0 :         }
    5224           0 :         return;
    5225             :     }
    5226           8 :     uno::Reference< table::XCellRange > oCellRange;
    5227           8 :     bool bAcross = false;
    5228           8 :     Across >>= bAcross;
    5229           8 :     if ( !bAcross )
    5230           6 :         lcl_mergeCellsOfRange( mxRange );
    5231             :     else
    5232             :     {
    5233           2 :         uno::Reference< excel::XRange > oRangeRowsImpl = Rows( uno::Any() );
    5234             :         // #TODO #FIXME this seems incredibly lame, this can't be right
    5235           6 :         for (sal_Int32 i=1; i <= oRangeRowsImpl->getCount();i++)
    5236             :         {
    5237           4 :             oRangeRowsImpl->Cells( uno::makeAny( i ), uno::Any() )->Merge( uno::makeAny( false ) );
    5238           2 :         }
    5239           8 :     }
    5240             : }
    5241             : 
    5242             : void SAL_CALL
    5243           4 : ScVbaRange::UnMerge(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5244             : {
    5245           4 :     if ( m_Areas->getCount() > 1 )
    5246             :     {
    5247           0 :         sal_Int32 nItems = m_Areas->getCount();
    5248           0 :         for ( sal_Int32 index=1; index <= nItems; ++index )
    5249             :         {
    5250           0 :             uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5251           0 :             xRange->UnMerge();
    5252           0 :         }
    5253           4 :         return;
    5254             :     }
    5255           4 :     lcl_mergeCellsOfRange( mxRange, false);
    5256             : }
    5257             : 
    5258             : uno::Any SAL_CALL
    5259           0 : ScVbaRange::getStyle() throw (css::script::BasicErrorException, uno::RuntimeException, std::exception)
    5260             : {
    5261           0 :     if ( m_Areas->getCount() > 1 )
    5262             :     {
    5263           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ), uno::UNO_QUERY_THROW  );
    5264           0 :         return xRange->getStyle();
    5265             :     }
    5266           0 :     uno::Reference< beans::XPropertySet > xProps( mxRange, uno::UNO_QUERY_THROW );
    5267           0 :     OUString sStyleName;
    5268           0 :     xProps->getPropertyValue( CELLSTYLE ) >>= sStyleName;
    5269           0 :     ScDocShell* pShell = getScDocShell();
    5270           0 :     uno::Reference< frame::XModel > xModel( pShell->GetModel() );
    5271           0 :     uno::Reference< excel::XStyle > xStyle = new ScVbaStyle( this, mxContext,  sStyleName, xModel );
    5272           0 :     return uno::makeAny( xStyle );
    5273             : }
    5274             : void SAL_CALL
    5275           0 : ScVbaRange::setStyle( const uno::Any& _style ) throw (uno::RuntimeException, std::exception)
    5276             : {
    5277           0 :     if ( m_Areas->getCount() > 1 )
    5278             :     {
    5279           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ), uno::UNO_QUERY_THROW );
    5280           0 :         xRange->setStyle( _style );
    5281           0 :         return;
    5282             :     }
    5283           0 :     uno::Reference< beans::XPropertySet > xProps( mxRange, uno::UNO_QUERY_THROW );
    5284           0 :     uno::Reference< excel::XStyle > xStyle;
    5285           0 :     _style >>= xStyle;
    5286           0 :     xProps->setPropertyValue( CELLSTYLE, uno::makeAny( xStyle->getName() ) );
    5287             : }
    5288             : 
    5289             : uno::Reference< excel::XRange >
    5290           0 : ScVbaRange::PreviousNext( bool bIsPrevious )
    5291             : {
    5292           0 :     ScMarkData markedRange;
    5293           0 :     ScRange refRange;
    5294           0 :     RangeHelper thisRange( mxRange );
    5295             : 
    5296           0 :     ScUnoConversion::FillScRange( refRange, thisRange.getCellRangeAddressable()->getRangeAddress());
    5297           0 :     markedRange. SetMarkArea( refRange );
    5298           0 :     short nMove = bIsPrevious ? -1 : 1;
    5299             : 
    5300           0 :     SCCOL nNewX = refRange.aStart.Col();
    5301           0 :     SCROW nNewY = refRange.aStart.Row();
    5302           0 :     SCTAB nTab = refRange.aStart.Tab();
    5303             : 
    5304           0 :     ScDocument& rDoc = getScDocument();
    5305           0 :     rDoc.GetNextPos( nNewX,nNewY, nTab, nMove,0, true,true, markedRange );
    5306           0 :     refRange.aStart.SetCol( nNewX );
    5307           0 :     refRange.aStart.SetRow( nNewY );
    5308           0 :     refRange.aStart.SetTab( nTab );
    5309           0 :     refRange.aEnd.SetCol( nNewX );
    5310           0 :     refRange.aEnd.SetRow( nNewY );
    5311           0 :     refRange.aEnd.SetTab( nTab );
    5312             : 
    5313           0 :     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getScDocShell() , refRange ) );
    5314             : 
    5315           0 :     return new ScVbaRange( mxParent, mxContext, xRange );
    5316             : }
    5317             : 
    5318             : uno::Reference< excel::XRange > SAL_CALL
    5319           0 : ScVbaRange::Next() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5320             : {
    5321           0 :     if ( m_Areas->getCount() > 1 )
    5322             :     {
    5323           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ) , uno::UNO_QUERY_THROW  );
    5324           0 :         return xRange->Next();
    5325             :     }
    5326           0 :     return PreviousNext( false );
    5327             : }
    5328             : 
    5329             : uno::Reference< excel::XRange > SAL_CALL
    5330           0 : ScVbaRange::Previous() throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5331             : {
    5332           0 :     if ( m_Areas->getCount() > 1 )
    5333             :     {
    5334           0 :         uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny( sal_Int32( 1 ) ), uno::Any() ), uno::UNO_QUERY_THROW  );
    5335           0 :         return xRange->Previous();
    5336             :     }
    5337           0 :     return PreviousNext( true );
    5338             : }
    5339             : 
    5340             : uno::Reference< excel::XRange > SAL_CALL
    5341          14 : ScVbaRange::SpecialCells( const uno::Any& _oType, const uno::Any& _oValue)
    5342             :     throw (script::BasicErrorException, uno::RuntimeException,
    5343             :            std::exception)
    5344             : {
    5345          14 :     bool bIsSingleCell = isSingleCellRange();
    5346          14 :     bool bIsMultiArea = ( m_Areas->getCount() > 1 );
    5347          14 :     ScVbaRange* pRangeToUse = this;
    5348          14 :     uno::Reference< excel::XRange > xUsedRange( getWorksheet()->getUsedRange() );
    5349          14 :     sal_Int32 nType = 0;
    5350          14 :     if ( !( _oType >>= nType ) )
    5351           0 :         DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5352          14 :     switch(nType)
    5353             :     {
    5354             :         case excel::XlCellType::xlCellTypeSameFormatConditions:
    5355             :         case excel::XlCellType::xlCellTypeAllValidation:
    5356             :         case excel::XlCellType::xlCellTypeSameValidation:
    5357           0 :             DebugHelper::basicexception(SbERR_NOT_IMPLEMENTED, OUString());
    5358           0 :             break;
    5359             :         case excel::XlCellType::xlCellTypeBlanks:
    5360             :         case excel::XlCellType::xlCellTypeComments:
    5361             :         case excel::XlCellType::xlCellTypeConstants:
    5362             :         case excel::XlCellType::xlCellTypeFormulas:
    5363             :         case excel::XlCellType::xlCellTypeVisible:
    5364             :         case excel::XlCellType::xlCellTypeLastCell:
    5365             :         {
    5366          14 :             if ( bIsMultiArea )
    5367             :             {
    5368             :                 // need to process each area, gather the results and
    5369             :                 // create a new range from those
    5370           0 :                 std::vector< table::CellRangeAddress > rangeResults;
    5371           0 :                 sal_Int32 nItems = ( m_Areas->getCount() + 1 );
    5372           0 :                 for ( sal_Int32 index=1; index <= nItems; ++index )
    5373             :                 {
    5374           0 :                     uno::Reference< excel::XRange > xRange( m_Areas->Item( uno::makeAny(index), uno::Any() ), uno::UNO_QUERY_THROW );
    5375           0 :                     xRange = xRange->SpecialCells( _oType,  _oValue);
    5376           0 :                     ScVbaRange* pRange = getImplementation( xRange );
    5377           0 :                     if ( xRange.is() && pRange )
    5378             :                     {
    5379           0 :                         sal_Int32 nElems = ( pRange->m_Areas->getCount() + 1 );
    5380           0 :                         for ( sal_Int32 nArea = 1; nArea < nElems; ++nArea )
    5381             :                         {
    5382           0 :                             uno::Reference< excel::XRange > xTmpRange( m_Areas->Item( uno::makeAny( nArea ), uno::Any() ), uno::UNO_QUERY_THROW );
    5383           0 :                             RangeHelper rHelper( xTmpRange->getCellRange() );
    5384           0 :                             rangeResults.push_back( rHelper.getCellRangeAddressable()->getRangeAddress() );
    5385           0 :                         }
    5386             :                     }
    5387           0 :                 }
    5388           0 :                 ScRangeList aCellRanges;
    5389           0 :                 std::vector< table::CellRangeAddress >::iterator it = rangeResults.begin();
    5390           0 :                 std::vector< table::CellRangeAddress >::iterator it_end = rangeResults.end();
    5391           0 :                 for ( ; it != it_end; ++ it )
    5392             :                 {
    5393           0 :                     ScRange refRange;
    5394           0 :                     ScUnoConversion::FillScRange( refRange, *it );
    5395           0 :                     aCellRanges.Append( refRange );
    5396             :                 }
    5397             :                 // Single range
    5398           0 :                 if ( aCellRanges.size() == 1 )
    5399             :                 {
    5400           0 :                     uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( getScDocShell(), *aCellRanges.front() ) );
    5401           0 :                     return new ScVbaRange( mxParent, mxContext, xRange );
    5402             :                 }
    5403           0 :                 uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( getScDocShell(), aCellRanges ) );
    5404             : 
    5405           0 :                 return new ScVbaRange( mxParent, mxContext, xRanges );
    5406             :             }
    5407          14 :             else if ( bIsSingleCell )
    5408             :             {
    5409           0 :                 pRangeToUse = static_cast< ScVbaRange* >( xUsedRange.get() );
    5410             :             }
    5411             : 
    5412          14 :             break;
    5413             :         }
    5414             :         default:
    5415           0 :         DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5416           0 :             break;
    5417             :     }
    5418          14 :     if ( !pRangeToUse )
    5419           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString() );
    5420          14 :     return pRangeToUse->SpecialCellsImpl( nType, _oValue );
    5421             : }
    5422             : 
    5423           0 : static sal_Int32 lcl_getFormulaResultFlags(const uno::Any& aType) throw ( script::BasicErrorException )
    5424             : {
    5425           0 :     sal_Int32 nType = excel::XlSpecialCellsValue::xlNumbers;
    5426           0 :     aType >>= nType;
    5427           0 :     sal_Int32 nRes = sheet::FormulaResult::VALUE;
    5428             : 
    5429           0 :     switch(nType)
    5430             :     {
    5431             :         case excel::XlSpecialCellsValue::xlErrors:
    5432           0 :             nRes= sheet::FormulaResult::ERROR;
    5433           0 :             break;
    5434             :         case excel::XlSpecialCellsValue::xlLogical:
    5435             :             //TODO bc93774: ask NN if this is really an appropriate substitute
    5436           0 :             nRes = sheet::FormulaResult::VALUE;
    5437           0 :             break;
    5438             :         case excel::XlSpecialCellsValue::xlNumbers:
    5439           0 :             nRes = sheet::FormulaResult::VALUE;
    5440           0 :             break;
    5441             :         case excel::XlSpecialCellsValue::xlTextValues:
    5442           0 :             nRes = sheet::FormulaResult::STRING;
    5443           0 :             break;
    5444             :         default:
    5445           0 :             DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5446             :     }
    5447           0 :     return nRes;
    5448             : }
    5449             : 
    5450             : uno::Reference< excel::XRange >
    5451          14 : ScVbaRange::SpecialCellsImpl( sal_Int32 nType, const uno::Any& _oValue) throw ( script::BasicErrorException )
    5452             : {
    5453          14 :     uno::Reference< excel::XRange > xRange;
    5454             :     try
    5455             :     {
    5456          14 :         uno::Reference< sheet::XCellRangesQuery > xQuery( mxRange, uno::UNO_QUERY_THROW );
    5457          28 :         uno::Reference< excel::XRange > oLocRangeImpl;
    5458          28 :         uno::Reference< sheet::XSheetCellRanges > xLocSheetCellRanges;
    5459          14 :         switch(nType)
    5460             :         {
    5461             :             case excel::XlCellType::xlCellTypeAllFormatConditions:
    5462             :             case excel::XlCellType::xlCellTypeSameFormatConditions:
    5463             :             case excel::XlCellType::xlCellTypeAllValidation:
    5464             :             case excel::XlCellType::xlCellTypeSameValidation:
    5465             :                 // Shouldn't get here ( should be filtered out by
    5466             :                 // ScVbaRange::SpecialCells()
    5467           0 :                 DebugHelper::basicexception(SbERR_NOT_IMPLEMENTED, OUString());
    5468           0 :                 break;
    5469             :             case excel::XlCellType::xlCellTypeBlanks:
    5470           0 :                 xLocSheetCellRanges = xQuery->queryEmptyCells();
    5471           0 :                 break;
    5472             :             case excel::XlCellType::xlCellTypeComments:
    5473           0 :                 xLocSheetCellRanges = xQuery->queryContentCells(sheet::CellFlags::ANNOTATION);
    5474           0 :                 break;
    5475             :             case excel::XlCellType::xlCellTypeConstants:
    5476           0 :                 xLocSheetCellRanges = xQuery->queryContentCells(23);
    5477           0 :                 break;
    5478             :             case excel::XlCellType::xlCellTypeFormulas:
    5479             :             {
    5480           0 :                 sal_Int32 nFormulaResult = lcl_getFormulaResultFlags(_oValue);
    5481           0 :                 xLocSheetCellRanges = xQuery->queryFormulaCells(nFormulaResult);
    5482           0 :                 break;
    5483             :             }
    5484             :             case excel::XlCellType::xlCellTypeLastCell:
    5485           0 :                 xRange = Cells( uno::makeAny( getCount() ), uno::Any() );
    5486             :             case excel::XlCellType::xlCellTypeVisible:
    5487          14 :                 xLocSheetCellRanges = xQuery->queryVisibleCells();
    5488          14 :                 break;
    5489             :             default:
    5490           0 :                 DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString() );
    5491           0 :                 break;
    5492             :         }
    5493          14 :         if (xLocSheetCellRanges.is())
    5494             :         {
    5495          14 :             xRange = lcl_makeXRangeFromSheetCellRanges( getParent(), mxContext, xLocSheetCellRanges, getScDocShell() );
    5496          14 :         }
    5497             :     }
    5498           0 :     catch (uno::Exception& )
    5499             :     {
    5500           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, STR_ERRORMESSAGE_NOCELLSWEREFOUND);
    5501             :     }
    5502          14 :     return xRange;
    5503             : }
    5504             : 
    5505             : void SAL_CALL
    5506           0 : ScVbaRange::RemoveSubtotal(  ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5507             : {
    5508           0 :     uno::Reference< sheet::XSubTotalCalculatable > xSub( mxRange, uno::UNO_QUERY_THROW );
    5509           0 :     xSub->removeSubTotals();
    5510           0 : }
    5511             : 
    5512             : void SAL_CALL
    5513           0 : ScVbaRange::Subtotal( ::sal_Int32 _nGroupBy, ::sal_Int32 _nFunction, const uno::Sequence< ::sal_Int32 >& _nTotalList, const uno::Any& aReplace, const uno::Any& PageBreaks, const uno::Any& /*SummaryBelowData*/ ) throw (script::BasicErrorException, uno::RuntimeException, std::exception)
    5514             : {
    5515             :     try
    5516             :     {
    5517           0 :         bool bDoReplace = false;
    5518           0 :         aReplace >>= bDoReplace;
    5519           0 :         bool bAddPageBreaks = false;
    5520           0 :         PageBreaks >>= bAddPageBreaks;
    5521             : 
    5522           0 :         uno::Reference< sheet::XSubTotalCalculatable> xSub(mxRange, uno::UNO_QUERY_THROW );
    5523           0 :         uno::Reference< sheet::XSubTotalDescriptor > xSubDesc = xSub->createSubTotalDescriptor(sal_True);
    5524           0 :         uno::Reference< beans::XPropertySet > xSubDescPropertySet( xSubDesc, uno::UNO_QUERY_THROW );
    5525           0 :         xSubDescPropertySet->setPropertyValue(INSERTPAGEBREAKS, uno::makeAny( bAddPageBreaks));
    5526           0 :         sal_Int32 nLen = _nTotalList.getLength();
    5527           0 :         uno::Sequence< sheet::SubTotalColumn > aColumns( nLen );
    5528           0 :         for (int i = 0; i < nLen; i++)
    5529             :         {
    5530           0 :             aColumns[i].Column = _nTotalList[i] - 1;
    5531           0 :             switch (_nFunction)
    5532             :             {
    5533             :                 case excel::XlConsolidationFunction::xlAverage:
    5534           0 :                     aColumns[i].Function = sheet::GeneralFunction_AVERAGE;
    5535           0 :                     break;
    5536             :                 case excel::XlConsolidationFunction::xlCount:
    5537           0 :                     aColumns[i].Function = sheet::GeneralFunction_COUNT;
    5538           0 :                     break;
    5539             :                 case excel::XlConsolidationFunction::xlCountNums:
    5540           0 :                     aColumns[i].Function = sheet::GeneralFunction_COUNTNUMS;
    5541           0 :                     break;
    5542             :                 case excel::XlConsolidationFunction::xlMax:
    5543           0 :                     aColumns[i].Function = sheet::GeneralFunction_MAX;
    5544           0 :                     break;
    5545             :                 case excel::XlConsolidationFunction::xlMin:
    5546           0 :                     aColumns[i].Function = sheet::GeneralFunction_MIN;
    5547           0 :                     break;
    5548             :                 case excel::XlConsolidationFunction::xlProduct:
    5549           0 :                     aColumns[i].Function = sheet::GeneralFunction_PRODUCT;
    5550           0 :                     break;
    5551             :                 case excel::XlConsolidationFunction::xlStDev:
    5552           0 :                     aColumns[i].Function = sheet::GeneralFunction_STDEV;
    5553           0 :                     break;
    5554             :                 case excel::XlConsolidationFunction::xlStDevP:
    5555           0 :                     aColumns[i].Function = sheet::GeneralFunction_STDEVP;
    5556           0 :                     break;
    5557             :                 case excel::XlConsolidationFunction::xlSum:
    5558           0 :                     aColumns[i].Function = sheet::GeneralFunction_SUM;
    5559           0 :                     break;
    5560             :                 case excel::XlConsolidationFunction::xlUnknown:
    5561           0 :                     aColumns[i].Function = sheet::GeneralFunction_NONE;
    5562           0 :                     break;
    5563             :                 case excel::XlConsolidationFunction::xlVar:
    5564           0 :                     aColumns[i].Function = sheet::GeneralFunction_VAR;
    5565           0 :                     break;
    5566             :                 case excel::XlConsolidationFunction::xlVarP:
    5567           0 :                     aColumns[i].Function = sheet::GeneralFunction_VARP;
    5568           0 :                     break;
    5569             :                 default:
    5570           0 :                     DebugHelper::basicexception(SbERR_BAD_PARAMETER, OUString()) ;
    5571           0 :                     return;
    5572             :             }
    5573             :         }
    5574           0 :         xSubDesc->addNew(aColumns, _nGroupBy - 1);
    5575           0 :         xSub->applySubTotals(xSubDesc, bDoReplace);
    5576             :     }
    5577           0 :     catch (const uno::Exception&)
    5578             :     {
    5579           0 :         DebugHelper::basicexception(SbERR_METHOD_FAILED, OUString());
    5580             :     }
    5581             : }
    5582             : 
    5583             : OUString
    5584           0 : ScVbaRange::getServiceImplName()
    5585             : {
    5586           0 :     return OUString("ScVbaRange");
    5587             : }
    5588             : 
    5589             : uno::Sequence< OUString >
    5590           0 : ScVbaRange::getServiceNames()
    5591             : {
    5592           0 :     static uno::Sequence< OUString > aServiceNames;
    5593           0 :     if ( aServiceNames.getLength() == 0 )
    5594             :     {
    5595           0 :         aServiceNames.realloc( 1 );
    5596           0 :         aServiceNames[ 0 ] = "ooo.vba.excel.Range";
    5597             :     }
    5598           0 :     return aServiceNames;
    5599             : }
    5600             : 
    5601             : sal_Bool SAL_CALL
    5602           0 : ScVbaRange::hasError() throw (uno::RuntimeException, std::exception)
    5603             : {
    5604           0 :     double dResult = 0.0;
    5605           0 :     uno::Reference< excel::XApplication > xApplication( Application(), uno::UNO_QUERY_THROW );
    5606           0 :     uno::Reference< script::XInvocation > xInvoc( xApplication->WorksheetFunction(), uno::UNO_QUERY_THROW );
    5607             : 
    5608           0 :     static OUString FunctionName( "IsError" );
    5609           0 :     uno::Sequence< uno::Any > Params(1);
    5610           0 :     uno::Reference< excel::XRange > aRange( this );
    5611           0 :     Params[0] = uno::makeAny( aRange );
    5612           0 :     uno::Sequence< sal_Int16 > OutParamIndex;
    5613           0 :     uno::Sequence< uno::Any > OutParam;
    5614           0 :     xInvoc->invoke( FunctionName, Params, OutParamIndex, OutParam ) >>= dResult;
    5615           0 :     return dResult > 0.0;
    5616             : }
    5617             : 
    5618             : namespace range
    5619             : {
    5620             : namespace sdecl = comphelper::service_decl;
    5621           4 : sdecl::vba_service_class_<ScVbaRange, sdecl::with_args<true> > serviceImpl;
    5622           4 : extern sdecl::ServiceDecl const serviceDecl(
    5623             :     serviceImpl,
    5624             :     "SvVbaRange",
    5625             :     "ooo.vba.excel.Range" );
    5626          12 : }
    5627             : 
    5628             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10