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