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