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