fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / vba / excelvbahelper.cxx
blobda36330cb4045acb56932f88c05e136921b6d458
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "excelvbahelper.hxx"
22 #include <comphelper/processfactory.hxx>
23 #include <com/sun/star/sheet/XSheetCellRange.hpp>
24 #include <com/sun/star/sheet/GlobalSheetSettings.hpp>
26 #include "docuno.hxx"
27 #include "tabvwsh.hxx"
28 #include "transobj.hxx"
29 #include "scmod.hxx"
30 #include "cellsuno.hxx"
31 #include <gridwin.hxx>
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>
40 using namespace ::com::sun::star;
41 using namespace ::ooo::vba;
43 namespace ooo {
44 namespace vba {
45 namespace excel {
47 uno::Reference< sheet::XUnnamedDatabaseRanges >
48 GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException )
50 uno::Reference< frame::XModel > xModel;
51 if ( pShell )
52 xModel.set( pShell->GetModel(), uno::UNO_QUERY_THROW );
53 uno::Reference< beans::XPropertySet > xModelProps( xModel, uno::UNO_QUERY_THROW );
54 uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( xModelProps->getPropertyValue("UnnamedDatabaseRanges"), uno::UNO_QUERY_THROW );
55 return xUnnamedDBRanges;
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 GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( uno::RuntimeException )
63 uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( GetUnnamedDataBaseRanges( pShell ), uno::UNO_QUERY_THROW );
64 uno::Reference< sheet::XDatabaseRange > xDataBaseRange;
65 if (xUnnamedDBRanges->hasByTable( nSheet ) )
67 uno::Reference< sheet::XDatabaseRange > xDBRange( xUnnamedDBRanges->getByTable( nSheet ) , uno::UNO_QUERY_THROW );
68 bool bHasAuto = false;
69 uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW );
70 xProps->getPropertyValue("AutoFilter") >>= bHasAuto;
71 if ( bHasAuto )
73 xDataBaseRange=xDBRange;
76 return xDataBaseRange;
79 ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
81 ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
82 if ( !pScCellRangesBase )
84 throw uno::RuntimeException("Failed to access underlying doc shell uno range object" );
86 return pScCellRangesBase->GetDocShell();
89 uno::Reference< XHelperInterface >
90 getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
92 uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
93 uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
94 return getUnoSheetModuleObj( xSheet );
97 void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
99 ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
100 Fraction aFract( nZoom, 100 );
101 pViewSh->GetViewData().SetZoom( aFract, aFract, nTabs );
102 pViewSh->RefreshZoom();
105 const OUString REPLACE_CELLS_WARNING( "ReplaceCellsWarning");
107 class PasteCellsWarningReseter
109 private:
110 bool bInitialWarningState;
111 static uno::Reference< sheet::XGlobalSheetSettings > getGlobalSheetSettings() throw ( uno::RuntimeException )
113 static uno::Reference< sheet::XGlobalSheetSettings > xProps = sheet::GlobalSheetSettings::create( comphelper::getProcessComponentContext() );
114 return xProps;
117 static bool getReplaceCellsWarning() throw ( uno::RuntimeException )
119 return getGlobalSheetSettings()->getReplaceCellsWarning();
122 static void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
124 getGlobalSheetSettings()->setReplaceCellsWarning( bState );
126 public:
127 PasteCellsWarningReseter() throw ( uno::RuntimeException )
129 bInitialWarningState = getReplaceCellsWarning();
130 if ( bInitialWarningState )
131 setReplaceCellsWarning( false );
133 ~PasteCellsWarningReseter()
135 if ( bInitialWarningState )
137 // don't allow dtor to throw
140 setReplaceCellsWarning( true );
142 catch ( uno::Exception& /*e*/ ){}
147 void
148 implnPaste( const uno::Reference< frame::XModel>& xModel )
150 PasteCellsWarningReseter resetWarningBox;
151 ScTabViewShell* pViewShell = getBestViewShell( xModel );
152 if ( pViewShell )
154 pViewShell->PasteFromSystem();
155 pViewShell->CellContentChanged();
159 void
160 implnCopy( const uno::Reference< frame::XModel>& xModel )
162 ScTabViewShell* pViewShell = getBestViewShell( xModel );
163 if ( pViewShell )
165 pViewShell->CopyToClip(NULL,false,false,true);
167 // mark the copied transfer object so it is used in ScVbaRange::Insert
168 ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
169 if (pClipObj)
170 pClipObj->SetUseInApi( true );
174 void
175 implnCut( const uno::Reference< frame::XModel>& xModel )
177 ScTabViewShell* pViewShell = getBestViewShell( xModel );
178 if ( pViewShell )
180 pViewShell->CutToClip( NULL, true );
182 // mark the copied transfer object so it is used in ScVbaRange::Insert
183 ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
184 if (pClipObj)
185 pClipObj->SetUseInApi( true );
189 void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, InsertDeleteFlags nFlags, sal_uInt16 nFunction, bool bSkipEmpty, bool bTranspose)
191 PasteCellsWarningReseter resetWarningBox;
192 InsCellCmd eMoveMode = INS_NONE;
194 ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
195 if ( pTabViewShell )
197 ScViewData& rView = pTabViewShell->GetViewData();
198 vcl::Window* pWin = rView.GetActiveWin();
199 if (pWin)
201 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
202 ScDocument* pDoc = NULL;
203 if ( pOwnClip )
204 pDoc = pOwnClip->GetDocument();
205 pTabViewShell->PasteFromClip( nFlags, pDoc,
206 nFunction, bSkipEmpty, bTranspose, false,
207 eMoveMode, IDF_NONE, true );
208 pTabViewShell->CellContentChanged();
214 ScDocShell*
215 getDocShell( const css::uno::Reference< css::frame::XModel>& xModel )
217 uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
218 ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
219 ScDocShell* pDocShell = NULL;
220 if ( pModel )
221 pDocShell = static_cast<ScDocShell*>(pModel->GetEmbeddedObject());
222 return pDocShell;
226 ScTabViewShell*
227 getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
229 ScDocShell* pDocShell = getDocShell( xModel );
230 if ( pDocShell )
231 return pDocShell->GetBestViewShell();
232 return NULL;
235 ScTabViewShell*
236 getCurrentBestViewShell( const uno::Reference< uno::XComponentContext >& xContext )
238 uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
239 return getBestViewShell( xModel );
242 SfxViewFrame*
243 getViewFrame( const uno::Reference< frame::XModel >& xModel )
245 ScTabViewShell* pViewShell = getBestViewShell( xModel );
246 if ( pViewShell )
247 return pViewShell->GetViewFrame();
248 return NULL;
251 uno::Reference< XHelperInterface >
252 getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
254 uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
255 OUString sCodeName;
256 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 return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) );
265 uno::Reference< XHelperInterface >
266 getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
268 uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
269 uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
270 uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
271 return getUnoSheetModuleObj( xRange );
274 uno::Reference< XHelperInterface >
275 getUnoSheetModuleObj( const uno::Reference< table::XCell >& xCell ) throw ( uno::RuntimeException )
277 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCell, uno::UNO_QUERY_THROW );
278 uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
279 return getUnoSheetModuleObj( xSheet );
282 uno::Reference< XHelperInterface >
283 getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab ) throw ( uno::RuntimeException )
285 uno::Reference< sheet::XSpreadsheetDocument > xDoc( xModel, uno::UNO_QUERY_THROW );
286 uno::Reference< container::XIndexAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
287 uno::Reference< sheet::XSpreadsheet > xSheet( xSheets->getByIndex( nTab ), uno::UNO_QUERY_THROW );
288 return getUnoSheetModuleObj( xSheet );
291 void setUpDocumentModules( const uno::Reference< sheet::XSpreadsheetDocument >& xDoc )
293 uno::Reference< frame::XModel > xModel( xDoc, uno::UNO_QUERY );
294 ScDocShell* pShell = excel::getDocShell( xModel );
295 if ( pShell )
297 OUString aPrjName( "Standard" );
298 pShell->GetBasicManager()->SetName( aPrjName );
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 uno::Reference<script::XLibraryContainer> xLibContainer = pShell->GetBasicContainer();
304 uno::Reference<script::vba::XVBACompatibility> xVBACompat( xLibContainer, uno::UNO_QUERY_THROW );
305 xVBACompat->setVBACompatibilityMode( sal_True );
307 if( xLibContainer.is() )
309 if( !xLibContainer->hasByName( aPrjName ) )
310 xLibContainer->createLibrary( aPrjName );
311 uno::Any aLibAny = xLibContainer->getByName( aPrjName );
312 uno::Reference< container::XNameContainer > xLib;
313 aLibAny >>= xLib;
314 if( xLib.is() )
316 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY_THROW );
317 uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY_THROW);
318 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 ScDocument& rDoc = pShell->GetDocument();
322 OUString sCodeName = rDoc.GetCodeName();
323 if ( sCodeName.isEmpty() )
325 sCodeName = "ThisWorkbook";
326 rDoc.SetCodeName( sCodeName );
329 std::vector< OUString > sDocModuleNames;
330 sDocModuleNames.push_back( sCodeName );
332 for ( SCTAB index = 0; index < rDoc.GetTableCount(); index++)
334 OUString aName;
335 rDoc.GetCodeName( index, aName );
336 sDocModuleNames.push_back( aName );
339 std::vector<OUString>::iterator it_end = sDocModuleNames.end();
341 for ( std::vector<OUString>::iterator it = sDocModuleNames.begin(); it != it_end; ++it )
343 script::ModuleInfo sModuleInfo;
345 uno::Any aName= xVBACodeNamedObjectAccess->getByName( *it );
346 sModuleInfo.ModuleObject.set( aName, uno::UNO_QUERY );
347 sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
348 xVBAModuleInfo->insertModuleInfo( *it, sModuleInfo );
349 if( xLib->hasByName( *it ) )
350 xLib->replaceByName( *it, uno::makeAny( OUString( "Option VBASupport 1\n") ) );
351 else
352 xLib->insertByName( *it, uno::makeAny( OUString( "Option VBASupport 1\n" ) ) );
357 /* Trigger the Workbook_Open event, event processor will register
358 itself as listener for specific events. */
361 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pShell->GetDocument().GetVbaEventProcessor(), uno::UNO_SET_THROW );
362 uno::Sequence< uno::Any > aArgs;
363 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_OPEN, aArgs );
365 catch( uno::Exception& )
371 SfxItemSet*
372 ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
374 return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
377 } // namespace excel
378 } // namespace vba
379 } // namespace ooo
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */