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 26 : GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException )
49 : {
50 26 : uno::Reference< frame::XModel > xModel;
51 26 : if ( pShell )
52 26 : xModel.set( pShell->GetModel(), uno::UNO_QUERY_THROW );
53 52 : uno::Reference< beans::XPropertySet > xModelProps( xModel, uno::UNO_QUERY_THROW );
54 26 : uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( xModelProps->getPropertyValue("UnnamedDatabaseRanges"), uno::UNO_QUERY_THROW );
55 52 : 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 24 : GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( uno::RuntimeException )
62 : {
63 24 : uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( GetUnnamedDataBaseRanges( pShell ), uno::UNO_QUERY_THROW );
64 24 : uno::Reference< sheet::XDatabaseRange > xDataBaseRange;
65 24 : if (xUnnamedDBRanges->hasByTable( nSheet ) )
66 : {
67 22 : uno::Reference< sheet::XDatabaseRange > xDBRange( xUnnamedDBRanges->getByTable( nSheet ) , uno::UNO_QUERY_THROW );
68 22 : bool bHasAuto = false;
69 44 : uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW );
70 22 : xProps->getPropertyValue("AutoFilter") >>= bHasAuto;
71 22 : if ( bHasAuto )
72 : {
73 22 : xDataBaseRange=xDBRange;
74 22 : }
75 : }
76 24 : return xDataBaseRange;
77 : }
78 :
79 3354 : ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
80 : {
81 3354 : ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
82 3354 : if ( !pScCellRangesBase )
83 : {
84 0 : throw uno::RuntimeException("Failed to access underlying doc shell uno range object" );
85 : }
86 3354 : return pScCellRangesBase->GetDocShell();
87 : }
88 :
89 : uno::Reference< XHelperInterface >
90 2908 : getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
91 : {
92 2908 : uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
93 5816 : uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
94 5816 : return getUnoSheetModuleObj( xSheet );
95 : }
96 :
97 4 : void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
98 : {
99 4 : ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
100 4 : Fraction aFract( nZoom, 100 );
101 4 : pViewSh->GetViewData().SetZoom( aFract, aFract, nTabs );
102 4 : pViewSh->RefreshZoom();
103 4 : }
104 :
105 4 : const OUString REPLACE_CELLS_WARNING( "ReplaceCellsWarning");
106 :
107 : class PasteCellsWarningReseter
108 : {
109 : private:
110 : bool bInitialWarningState;
111 90 : static uno::Reference< sheet::XGlobalSheetSettings > getGlobalSheetSettings() throw ( uno::RuntimeException )
112 : {
113 90 : static uno::Reference< sheet::XGlobalSheetSettings > xProps = sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
114 90 : return xProps;
115 : }
116 :
117 30 : bool getReplaceCellsWarning() throw ( uno::RuntimeException )
118 : {
119 30 : return getGlobalSheetSettings()->getReplaceCellsWarning();
120 : }
121 :
122 60 : void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
123 : {
124 60 : getGlobalSheetSettings()->setReplaceCellsWarning( bState );
125 60 : }
126 : public:
127 30 : PasteCellsWarningReseter() throw ( uno::RuntimeException )
128 : {
129 30 : bInitialWarningState = getReplaceCellsWarning();
130 30 : if ( bInitialWarningState )
131 30 : setReplaceCellsWarning( false );
132 30 : }
133 30 : ~PasteCellsWarningReseter()
134 : {
135 30 : if ( bInitialWarningState )
136 : {
137 : // don't allow dtor to throw
138 : try
139 : {
140 30 : setReplaceCellsWarning( true );
141 : }
142 0 : catch ( uno::Exception& /*e*/ ){}
143 : }
144 30 : }
145 : };
146 :
147 : void
148 6 : implnPaste( const uno::Reference< frame::XModel>& xModel )
149 : {
150 6 : PasteCellsWarningReseter resetWarningBox;
151 6 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
152 6 : if ( pViewShell )
153 : {
154 6 : pViewShell->PasteFromSystem();
155 6 : pViewShell->CellContentChanged();
156 6 : }
157 6 : }
158 :
159 : void
160 22 : implnCopy( const uno::Reference< frame::XModel>& xModel )
161 : {
162 22 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
163 22 : if ( pViewShell )
164 : {
165 22 : pViewShell->CopyToClip(NULL,false,false,true);
166 :
167 : // mark the copied transfer object so it is used in ScVbaRange::Insert
168 22 : ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
169 22 : if (pClipObj)
170 0 : pClipObj->SetUseInApi( true );
171 : }
172 22 : }
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 24 : void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, InsertDeleteFlags nFlags, sal_uInt16 nFunction, bool bSkipEmpty, bool bTranspose)
190 : {
191 24 : PasteCellsWarningReseter resetWarningBox;
192 24 : InsCellCmd eMoveMode = INS_NONE;
193 :
194 24 : ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
195 24 : if ( pTabViewShell )
196 : {
197 24 : ScViewData& rView = pTabViewShell->GetViewData();
198 24 : vcl::Window* pWin = rView.GetActiveWin();
199 24 : if (pWin)
200 : {
201 24 : ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
202 24 : ScDocument* pDoc = NULL;
203 24 : if ( pOwnClip )
204 0 : pDoc = pOwnClip->GetDocument();
205 : pTabViewShell->PasteFromClip( nFlags, pDoc,
206 : nFunction, bSkipEmpty, bTranspose, false,
207 24 : eMoveMode, IDF_NONE, true );
208 24 : pTabViewShell->CellContentChanged();
209 : }
210 24 : }
211 :
212 24 : }
213 :
214 : ScDocShell*
215 272 : getDocShell( const css::uno::Reference< css::frame::XModel>& xModel )
216 : {
217 272 : uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
218 272 : ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
219 272 : ScDocShell* pDocShell = NULL;
220 272 : if ( pModel )
221 272 : pDocShell = static_cast<ScDocShell*>(pModel->GetEmbeddedObject());
222 272 : return pDocShell;
223 :
224 : }
225 :
226 : ScTabViewShell*
227 224 : getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
228 : {
229 224 : ScDocShell* pDocShell = getDocShell( xModel );
230 224 : if ( pDocShell )
231 224 : return pDocShell->GetBestViewShell();
232 0 : return NULL;
233 : }
234 :
235 : ScTabViewShell*
236 66 : getCurrentBestViewShell( const uno::Reference< uno::XComponentContext >& xContext )
237 : {
238 66 : uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
239 66 : return getBestViewShell( xModel );
240 : }
241 :
242 : SfxViewFrame*
243 22 : getViewFrame( const uno::Reference< frame::XModel >& xModel )
244 : {
245 22 : ScTabViewShell* pViewShell = getBestViewShell( xModel );
246 22 : if ( pViewShell )
247 22 : return pViewShell->GetViewFrame();
248 0 : return NULL;
249 : }
250 :
251 : uno::Reference< XHelperInterface >
252 3354 : getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
253 : {
254 3354 : uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
255 6708 : OUString sCodeName;
256 3354 : 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 6708 : return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) );
263 : }
264 :
265 : uno::Reference< XHelperInterface >
266 100 : getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
267 : {
268 100 : uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
269 200 : uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
270 200 : uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
271 200 : 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 2 : void setUpDocumentModules( const uno::Reference< sheet::XSpreadsheetDocument >& xDoc )
292 : {
293 2 : uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
294 2 : ScDocShell* pShell = excel::getDocShell( xModel );
295 2 : if ( pShell )
296 : {
297 2 : OUString aPrjName( "Standard" );
298 2 : 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 4 : uno::Reference<script::XLibraryContainer> xLibContainer = pShell->GetBasicContainer();
304 4 : uno::Reference<script::vba::XVBACompatibility> xVBACompat( xLibContainer, uno::UNO_QUERY_THROW );
305 2 : xVBACompat->setVBACompatibilityMode( sal_True );
306 :
307 2 : if( xLibContainer.is() )
308 : {
309 2 : if( !xLibContainer->hasByName( aPrjName ) )
310 0 : xLibContainer->createLibrary( aPrjName );
311 2 : uno::Any aLibAny = xLibContainer->getByName( aPrjName );
312 4 : uno::Reference< container::XNameContainer > xLib;
313 2 : aLibAny >>= xLib;
314 2 : if( xLib.is() )
315 : {
316 2 : uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY_THROW );
317 4 : uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY_THROW);
318 4 : 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 2 : ScDocument& rDoc = pShell->GetDocument();
322 4 : OUString sCodeName = rDoc.GetCodeName();
323 2 : if ( sCodeName.isEmpty() )
324 : {
325 2 : sCodeName = "ThisWorkbook";
326 2 : rDoc.SetCodeName( sCodeName );
327 : }
328 :
329 4 : std::vector< OUString > sDocModuleNames;
330 2 : sDocModuleNames.push_back( sCodeName );
331 :
332 4 : for ( SCTAB index = 0; index < rDoc.GetTableCount(); index++)
333 : {
334 2 : OUString aName;
335 2 : rDoc.GetCodeName( index, aName );
336 2 : sDocModuleNames.push_back( aName );
337 2 : }
338 :
339 2 : std::vector<OUString>::iterator it_end = sDocModuleNames.end();
340 :
341 6 : for ( std::vector<OUString>::iterator it = sDocModuleNames.begin(); it != it_end; ++it )
342 : {
343 4 : script::ModuleInfo sModuleInfo;
344 :
345 8 : uno::Any aName= xVBACodeNamedObjectAccess->getByName( *it );
346 4 : sModuleInfo.ModuleObject.set( aName, uno::UNO_QUERY );
347 4 : sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
348 4 : xVBAModuleInfo->insertModuleInfo( *it, sModuleInfo );
349 4 : if( xLib->hasByName( *it ) )
350 0 : xLib->replaceByName( *it, uno::makeAny( OUString( "Option VBASupport 1\n") ) );
351 : else
352 4 : xLib->insertByName( *it, uno::makeAny( OUString( "Option VBASupport 1\n" ) ) );
353 6 : }
354 2 : }
355 : }
356 :
357 : /* Trigger the Workbook_Open event, event processor will register
358 : itself as listener for specific events. */
359 : try
360 : {
361 2 : uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pShell->GetDocument().GetVbaEventProcessor(), uno::UNO_SET_THROW );
362 4 : uno::Sequence< uno::Any > aArgs;
363 4 : xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_OPEN, aArgs );
364 : }
365 0 : catch( uno::Exception& )
366 : {
367 2 : }
368 2 : }
369 2 : }
370 :
371 : SfxItemSet*
372 144 : ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
373 : {
374 144 : return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
375 : }
376 :
377 : } // namespace excel
378 : } // namespace vba
379 12 : } // namespace ooo
380 :
381 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|