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