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

Generated by: LCOV version 1.10