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