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 "excelvbahelper.hxx"
21 :
22 : #include <comphelper/processfactory.hxx>
23 : #include <com/sun/star/sheet/XSheetCellRange.hpp>
24 : #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
25 :
26 : #include "docuno.hxx"
27 : #include "tabvwsh.hxx"
28 : #include "transobj.hxx"
29 : #include "scmod.hxx"
30 : #include "cellsuno.hxx"
31 : #include <gridwin.hxx>
32 :
33 : #include <com/sun/star/script/vba/VBAEventId.hpp>
34 : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
35 : #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
36 : #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
37 : #include <com/sun/star/script/ModuleInfo.hpp>
38 : #include <com/sun/star/script/ModuleType.hpp>
39 :
40 : using namespace ::com::sun::star;
41 : using namespace ::ooo::vba;
42 :
43 : namespace ooo {
44 : namespace vba {
45 : namespace excel {
46 :
47 : uno::Reference< sheet::XUnnamedDatabaseRanges >
48 13 : GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException )
49 : {
50 13 : uno::Reference< frame::XModel > xModel;
51 13 : if ( pShell )
52 13 : xModel.set( pShell->GetModel(), uno::UNO_QUERY_THROW );
53 26 : uno::Reference< beans::XPropertySet > xModelProps( xModel, uno::UNO_QUERY_THROW );
54 13 : uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( xModelProps->getPropertyValue("UnnamedDatabaseRanges"), uno::UNO_QUERY_THROW );
55 26 : return xUnnamedDBRanges;
56 : }
57 :
58 : // returns the XDatabaseRange for the autofilter on sheet (nSheet)
59 : // also populates sName with the name of range
60 : uno::Reference< sheet::XDatabaseRange >
61 12 : GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( uno::RuntimeException )
62 : {
63 12 : uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( GetUnnamedDataBaseRanges( pShell ), uno::UNO_QUERY_THROW );
64 12 : uno::Reference< sheet::XDatabaseRange > xDataBaseRange;
65 12 : if (xUnnamedDBRanges->hasByTable( nSheet ) )
66 : {
67 11 : uno::Reference< sheet::XDatabaseRange > xDBRange( xUnnamedDBRanges->getByTable( nSheet ) , uno::UNO_QUERY_THROW );
68 11 : bool bHasAuto = false;
69 22 : uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW );
70 11 : xProps->getPropertyValue("AutoFilter") >>= bHasAuto;
71 11 : if ( bHasAuto )
72 : {
73 11 : xDataBaseRange=xDBRange;
74 11 : }
75 : }
76 12 : return xDataBaseRange;
77 : }
78 :
79 2377 : ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
80 : {
81 2377 : ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
82 2377 : if ( !pScCellRangesBase )
83 : {
84 0 : throw uno::RuntimeException("Failed to access underlying doc shell uno range object" );
85 : }
86 2377 : return pScCellRangesBase->GetDocShell();
87 : }
88 :
89 : uno::Reference< XHelperInterface >
90 1747 : getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
91 : {
92 1747 : uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
93 3494 : uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
94 3494 : return getUnoSheetModuleObj( xSheet );
95 : }
96 :
97 2 : void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
98 : {
99 2 : ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
100 2 : Fraction aFract( nZoom, 100 );
101 2 : pViewSh->GetViewData().SetZoom( aFract, aFract, nTabs );
102 2 : pViewSh->RefreshZoom();
103 2 : }
104 :
105 3 : const OUString REPLACE_CELLS_WARNING( "ReplaceCellsWarning");
106 :
107 : class PasteCellsWarningReseter
108 : {
109 : private:
110 : bool bInitialWarningState;
111 45 : static uno::Reference< sheet::XGlobalSheetSettings > getGlobalSheetSettings() throw ( uno::RuntimeException )
112 : {
113 45 : static uno::Reference< sheet::XGlobalSheetSettings > xProps = sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
114 45 : return xProps;
115 : }
116 :
117 15 : static bool getReplaceCellsWarning() throw ( uno::RuntimeException )
118 : {
119 15 : return getGlobalSheetSettings()->getReplaceCellsWarning();
120 : }
121 :
122 30 : static void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
123 : {
124 30 : getGlobalSheetSettings()->setReplaceCellsWarning( bState );
125 30 : }
126 : public:
127 15 : PasteCellsWarningReseter() throw ( uno::RuntimeException )
128 : {
129 15 : bInitialWarningState = getReplaceCellsWarning();
130 15 : if ( bInitialWarningState )
131 15 : setReplaceCellsWarning( false );
132 15 : }
133 15 : ~PasteCellsWarningReseter()
134 : {
135 15 : if ( bInitialWarningState )
136 : {
137 : // don't allow dtor to throw
138 : try
139 : {
140 15 : setReplaceCellsWarning( true );
141 : }
142 0 : catch ( uno::Exception& /*e*/ ){}
143 : }
144 15 : }
145 : };
146 :
147 : void
148 3 : implnPaste( const uno::Reference< frame::XModel>& xModel )
149 : {
150 3 : PasteCellsWarningReseter resetWarningBox;
151 3 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
152 3 : if ( pViewShell )
153 : {
154 3 : pViewShell->PasteFromSystem();
155 3 : pViewShell->CellContentChanged();
156 3 : }
157 3 : }
158 :
159 : void
160 11 : implnCopy( const uno::Reference< frame::XModel>& xModel )
161 : {
162 11 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
163 11 : if ( pViewShell )
164 : {
165 11 : pViewShell->CopyToClip(NULL,false,false,true);
166 :
167 : // mark the copied transfer object so it is used in ScVbaRange::Insert
168 11 : ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
169 11 : if (pClipObj)
170 0 : pClipObj->SetUseInApi( true );
171 : }
172 11 : }
173 :
174 : void
175 0 : implnCut( const uno::Reference< frame::XModel>& xModel )
176 : {
177 0 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
178 0 : if ( pViewShell )
179 : {
180 0 : pViewShell->CutToClip( NULL, true );
181 :
182 : // mark the copied transfer object so it is used in ScVbaRange::Insert
183 0 : ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
184 0 : if (pClipObj)
185 0 : pClipObj->SetUseInApi( true );
186 : }
187 0 : }
188 :
189 12 : void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, InsertDeleteFlags nFlags, sal_uInt16 nFunction, bool bSkipEmpty, bool bTranspose)
190 : {
191 12 : PasteCellsWarningReseter resetWarningBox;
192 12 : InsCellCmd eMoveMode = INS_NONE;
193 :
194 12 : ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
195 12 : if ( pTabViewShell )
196 : {
197 12 : ScViewData& rView = pTabViewShell->GetViewData();
198 12 : vcl::Window* pWin = rView.GetActiveWin();
199 12 : if (pWin)
200 : {
201 12 : ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
202 12 : ScDocument* pDoc = NULL;
203 12 : if ( pOwnClip )
204 0 : pDoc = pOwnClip->GetDocument();
205 : pTabViewShell->PasteFromClip( nFlags, pDoc,
206 : nFunction, bSkipEmpty, bTranspose, false,
207 12 : eMoveMode, IDF_NONE, true );
208 12 : pTabViewShell->CellContentChanged();
209 : }
210 12 : }
211 :
212 12 : }
213 :
214 : ScDocShell*
215 353 : getDocShell( const css::uno::Reference< css::frame::XModel>& xModel )
216 : {
217 353 : uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
218 353 : ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
219 353 : ScDocShell* pDocShell = NULL;
220 353 : if ( pModel )
221 353 : pDocShell = static_cast<ScDocShell*>(pModel->GetEmbeddedObject());
222 353 : return pDocShell;
223 :
224 : }
225 :
226 : ScTabViewShell*
227 329 : getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
228 : {
229 329 : ScDocShell* pDocShell = getDocShell( xModel );
230 329 : if ( pDocShell )
231 329 : return pDocShell->GetBestViewShell();
232 0 : return NULL;
233 : }
234 :
235 : ScTabViewShell*
236 178 : getCurrentBestViewShell( const uno::Reference< uno::XComponentContext >& xContext )
237 : {
238 178 : uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
239 178 : return getBestViewShell( xModel );
240 : }
241 :
242 : SfxViewFrame*
243 83 : getViewFrame( const uno::Reference< frame::XModel >& xModel )
244 : {
245 83 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
246 83 : if ( pViewShell )
247 83 : return pViewShell->GetViewFrame();
248 0 : return NULL;
249 : }
250 :
251 : uno::Reference< XHelperInterface >
252 2377 : getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
253 : {
254 2377 : uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
255 4754 : OUString sCodeName;
256 2377 : xProps->getPropertyValue("CodeName") >>= sCodeName;
257 : // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
258 : // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
259 : // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
260 : // the document in the future could fix this, especially IF the switching of the vba mode takes care to
261 : // create the special document module objects if they don't exist.
262 4754 : return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) );
263 : }
264 :
265 : uno::Reference< XHelperInterface >
266 50 : getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
267 : {
268 50 : uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
269 100 : uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
270 100 : uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
271 100 : return getUnoSheetModuleObj( xRange );
272 : }
273 :
274 : uno::Reference< XHelperInterface >
275 0 : getUnoSheetModuleObj( const uno::Reference< table::XCell >& xCell ) throw ( uno::RuntimeException )
276 : {
277 0 : uno::Reference< sheet::XSheetCellRange > xSheetRange( xCell, uno::UNO_QUERY_THROW );
278 0 : uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
279 0 : return getUnoSheetModuleObj( xSheet );
280 : }
281 :
282 : uno::Reference< XHelperInterface >
283 0 : getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab ) throw ( uno::RuntimeException )
284 : {
285 0 : uno::Reference< sheet::XSpreadsheetDocument > xDoc( xModel, uno::UNO_QUERY_THROW );
286 0 : uno::Reference< container::XIndexAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
287 0 : uno::Reference< sheet::XSpreadsheet > xSheet( xSheets->getByIndex( nTab ), uno::UNO_QUERY_THROW );
288 0 : return getUnoSheetModuleObj( xSheet );
289 : }
290 :
291 1 : void setUpDocumentModules( const uno::Reference< sheet::XSpreadsheetDocument >& xDoc )
292 : {
293 1 : uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
294 1 : ScDocShell* pShell = excel::getDocShell( xModel );
295 1 : if ( pShell )
296 : {
297 1 : OUString aPrjName( "Standard" );
298 1 : pShell->GetBasicManager()->SetName( aPrjName );
299 :
300 : /* Set library container to VBA compatibility mode. This will create
301 : the VBA Globals object and store it in the Basic manager of the
302 : document. */
303 2 : uno::Reference<script::XLibraryContainer> xLibContainer = pShell->GetBasicContainer();
304 2 : uno::Reference<script::vba::XVBACompatibility> xVBACompat( xLibContainer, uno::UNO_QUERY_THROW );
305 1 : xVBACompat->setVBACompatibilityMode( sal_True );
306 :
307 1 : if( xLibContainer.is() )
308 : {
309 1 : if( !xLibContainer->hasByName( aPrjName ) )
310 0 : xLibContainer->createLibrary( aPrjName );
311 1 : uno::Any aLibAny = xLibContainer->getByName( aPrjName );
312 2 : uno::Reference< container::XNameContainer > xLib;
313 1 : aLibAny >>= xLib;
314 1 : if( xLib.is() )
315 : {
316 1 : uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY_THROW );
317 2 : uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY_THROW);
318 2 : uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess( xSF->createInstance("ooo.vba.VBAObjectModuleObjectProvider"), uno::UNO_QUERY_THROW );
319 : // set up the module info for the workbook and sheets in the nealy created
320 : // spreadsheet
321 1 : ScDocument& rDoc = pShell->GetDocument();
322 2 : OUString sCodeName = rDoc.GetCodeName();
323 1 : if ( sCodeName.isEmpty() )
324 : {
325 1 : sCodeName = "ThisWorkbook";
326 1 : rDoc.SetCodeName( sCodeName );
327 : }
328 :
329 2 : std::vector< OUString > sDocModuleNames;
330 1 : sDocModuleNames.push_back( sCodeName );
331 :
332 2 : for ( SCTAB index = 0; index < rDoc.GetTableCount(); index++)
333 : {
334 1 : OUString aName;
335 1 : rDoc.GetCodeName( index, aName );
336 1 : sDocModuleNames.push_back( aName );
337 1 : }
338 :
339 1 : std::vector<OUString>::iterator it_end = sDocModuleNames.end();
340 :
341 3 : for ( std::vector<OUString>::iterator it = sDocModuleNames.begin(); it != it_end; ++it )
342 : {
343 2 : script::ModuleInfo sModuleInfo;
344 :
345 4 : uno::Any aName= xVBACodeNamedObjectAccess->getByName( *it );
346 2 : sModuleInfo.ModuleObject.set( aName, uno::UNO_QUERY );
347 2 : sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
348 2 : xVBAModuleInfo->insertModuleInfo( *it, sModuleInfo );
349 2 : if( xLib->hasByName( *it ) )
350 0 : xLib->replaceByName( *it, uno::makeAny( OUString( "Option VBASupport 1\n") ) );
351 : else
352 2 : xLib->insertByName( *it, uno::makeAny( OUString( "Option VBASupport 1\n" ) ) );
353 3 : }
354 1 : }
355 : }
356 :
357 : /* Trigger the Workbook_Open event, event processor will register
358 : itself as listener for specific events. */
359 : try
360 : {
361 1 : uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pShell->GetDocument().GetVbaEventProcessor(), uno::UNO_SET_THROW );
362 2 : uno::Sequence< uno::Any > aArgs;
363 2 : xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_OPEN, aArgs );
364 : }
365 0 : catch( uno::Exception& )
366 : {
367 1 : }
368 1 : }
369 1 : }
370 :
371 : SfxItemSet*
372 72 : ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
373 : {
374 72 : return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
375 : }
376 :
377 : } // namespace excel
378 : } // namespace vba
379 9 : } // namespace ooo
380 :
381 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|