xref: /aoo41x/main/sc/source/ui/vba/excelvbahelper.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "excelvbahelper.hxx"
29 
30 #include <comphelper/processfactory.hxx>
31 #include <com/sun/star/sheet/XSheetCellRange.hpp>
32 #include "docuno.hxx"
33 #include "tabvwsh.hxx"
34 #include "transobj.hxx"
35 #include "scmod.hxx"
36 #include "cellsuno.hxx"
37 
38 namespace ooo {
39 namespace vba {
40 namespace excel {
41 
42 using namespace ::com::sun::star;
43 using namespace ::ooo::vba;
44 
45 // ============================================================================
46 
47 ScDocShell* GetDocShellFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
48 {
49     ScCellRangesBase* pScCellRangesBase = ScCellRangesBase::getImplementation( xRange );
50     if ( !pScCellRangesBase )
51     {
52         throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying doc shell uno range object" ) ), uno::Reference< uno::XInterface >() );
53     }
54     return pScCellRangesBase->GetDocShell();
55 }
56 
57 ScDocument* GetDocumentFromRange( const uno::Reference< uno::XInterface >& xRange ) throw ( uno::RuntimeException )
58 {
59         ScDocShell* pDocShell = GetDocShellFromRange( xRange );
60         if ( !pDocShell )
61         {
62                 throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Failed to access underlying document from uno range object" ) ), uno::Reference< uno::XInterface >() );
63         }
64         return pDocShell->GetDocument();
65 }
66 
67 void implSetZoom( const uno::Reference< frame::XModel >& xModel, sal_Int16 nZoom, std::vector< SCTAB >& nTabs )
68 {
69     ScTabViewShell* pViewSh = excel::getBestViewShell( xModel );
70     Fraction aFract( nZoom, 100 );
71     pViewSh->GetViewData()->SetZoom( aFract, aFract, nTabs );
72     pViewSh->RefreshZoom();
73 }
74 bool isInPrintPreview( SfxViewFrame* pView )
75 {
76 	sal_uInt16 nViewNo = SID_VIEWSHELL1 - SID_VIEWSHELL0;
77 	if ( pView->GetObjectShell()->GetFactory().GetViewFactoryCount() >
78 nViewNo && !pView->GetObjectShell()->IsInPlaceActive() )
79 	{
80 		SfxViewFactory &rViewFactory =
81 			pView->GetObjectShell()->GetFactory().GetViewFactory(nViewNo);
82 		if (  pView->GetCurViewId() == rViewFactory.GetOrdinal() )
83 			return true;
84 	}
85 	return false;
86 }
87 
88 const ::rtl::OUString REPLACE_CELLS_WARNING(  RTL_CONSTASCII_USTRINGPARAM( "ReplaceCellsWarning"));
89 
90 class PasteCellsWarningReseter
91 {
92 private:
93 	bool bInitialWarningState;
94 	static uno::Reference< beans::XPropertySet > getGlobalSheetSettings() throw ( uno::RuntimeException )
95 	{
96 		static uno::Reference< beans::XPropertySet > xTmpProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
97 		static uno::Reference<uno::XComponentContext > xContext( xTmpProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW );
98 		static uno::Reference<lang::XMultiComponentFactory > xServiceManager(
99 				xContext->getServiceManager(), uno::UNO_QUERY_THROW );
100 		static uno::Reference< beans::XPropertySet > xProps( xServiceManager->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.GlobalSheetSettings" ) ) ,xContext ), uno::UNO_QUERY_THROW );
101 		return xProps;
102 	}
103 
104 	bool getReplaceCellsWarning() throw ( uno::RuntimeException )
105 	{
106 		sal_Bool res = sal_False;
107 		getGlobalSheetSettings()->getPropertyValue( REPLACE_CELLS_WARNING ) >>= res;
108 		return ( res == sal_True );
109 	}
110 
111 	void setReplaceCellsWarning( bool bState ) throw ( uno::RuntimeException )
112 	{
113 		getGlobalSheetSettings()->setPropertyValue( REPLACE_CELLS_WARNING, uno::makeAny( bState ) );
114 	}
115 public:
116 	PasteCellsWarningReseter() throw ( uno::RuntimeException )
117 	{
118 		bInitialWarningState = getReplaceCellsWarning();
119 		if ( bInitialWarningState )
120 			setReplaceCellsWarning( false );
121 	}
122 	~PasteCellsWarningReseter()
123 	{
124 		if ( bInitialWarningState )
125 		{
126 			// don't allow dtor to throw
127 			try
128 			{
129 				setReplaceCellsWarning( true );
130 			}
131 			catch ( uno::Exception& /*e*/ ){}
132 		}
133 	}
134 };
135 
136 void
137 implnPaste( const uno::Reference< frame::XModel>& xModel )
138 {
139 	PasteCellsWarningReseter resetWarningBox;
140 	ScTabViewShell* pViewShell = getBestViewShell( xModel );
141 	if ( pViewShell )
142 	{
143 		pViewShell->PasteFromSystem();
144 		pViewShell->CellContentChanged();
145 	}
146 }
147 
148 
149 void
150 implnCopy( const uno::Reference< frame::XModel>& xModel )
151 {
152 	ScTabViewShell* pViewShell = getBestViewShell( xModel );
153 	if ( pViewShell )
154     {
155 		pViewShell->CopyToClip(NULL,false,false,true);
156 
157         // mark the copied transfer object so it is used in ScVbaRange::Insert
158         ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
159         if (pClipObj)
160             pClipObj->SetUseInApi( true );
161     }
162 }
163 
164 void
165 implnCut( const uno::Reference< frame::XModel>& xModel )
166 {
167 	ScTabViewShell* pViewShell =  getBestViewShell( xModel );
168 	if ( pViewShell )
169     {
170 		pViewShell->CutToClip( NULL, sal_True );
171 
172         // mark the copied transfer object so it is used in ScVbaRange::Insert
173         ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( NULL );
174         if (pClipObj)
175             pClipObj->SetUseInApi( true );
176     }
177 }
178 
179 void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, sal_uInt16 nFlags,sal_uInt16 nFunction,sal_Bool bSkipEmpty, sal_Bool bTranspose)
180 {
181 	PasteCellsWarningReseter resetWarningBox;
182 	sal_Bool bAsLink(sal_False), bOtherDoc(sal_False);
183 	InsCellCmd eMoveMode = INS_NONE;
184 
185 	ScTabViewShell* pTabViewShell = getBestViewShell( xModel );
186 	if ( pTabViewShell )
187 	{
188 		ScViewData* pView = pTabViewShell->GetViewData();
189 		Window* pWin = ( pView != NULL ) ? pView->GetActiveWin() : NULL;
190 		if ( pView && pWin )
191 		{
192 			if ( bAsLink && bOtherDoc )
193 				pTabViewShell->PasteFromSystem(0);//SOT_FORMATSTR_ID_LINK
194 			else
195 			{
196 				ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
197 				ScDocument* pDoc = NULL;
198 				if ( pOwnClip )
199                 {
200 					pDoc = pOwnClip->GetDocument();
201                     pOwnClip->SetUseInApi( false );     // don't use in Insert after it was pasted once
202                 }
203 				pTabViewShell->PasteFromClip( nFlags, pDoc,
204 					nFunction, bSkipEmpty, bTranspose, bAsLink,
205 					eMoveMode, IDF_NONE, sal_True );
206 				pTabViewShell->CellContentChanged();
207 			}
208 		}
209 	}
210 
211 }
212 
213 ScDocShell*
214 getDocShell( const css::uno::Reference< css::frame::XModel>& xModel )
215 {
216 	uno::Reference< uno::XInterface > xIf( xModel, uno::UNO_QUERY_THROW );
217 	ScModelObj* pModel = dynamic_cast< ScModelObj* >( xIf.get() );
218 	ScDocShell* pDocShell = NULL;
219 	if ( pModel )
220 		pDocShell = (ScDocShell*)pModel->GetEmbeddedObject();
221 	return pDocShell;
222 
223 }
224 
225 ScTabViewShell*
226 getBestViewShell( const css::uno::Reference< css::frame::XModel>& xModel )
227 {
228 	ScDocShell* pDocShell = getDocShell( xModel );
229 	if ( pDocShell )
230 		return pDocShell->GetBestViewShell();
231 	return NULL;
232 }
233 
234 ScTabViewShell*
235 getCurrentBestViewShell(  const uno::Reference< uno::XComponentContext >& xContext )
236 {
237 	uno::Reference< frame::XModel > xModel = getCurrentExcelDoc( xContext );
238 	return getBestViewShell( xModel );
239 }
240 
241 SfxViewFrame*
242 getViewFrame( const uno::Reference< frame::XModel >& xModel )
243 {
244 	ScTabViewShell* pViewShell = getBestViewShell( xModel );
245 	if ( pViewShell )
246 		return pViewShell->GetViewFrame();
247 	return NULL;
248 }
249 
250 uno::Reference< XHelperInterface >
251 getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException )
252 {
253     uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW );
254     rtl::OUString sCodeName;
255     xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) ) >>= sCodeName;
256     // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
257     // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
258     // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
259     // the document in the future could fix this, especially IF the switching of the vba mode takes care to
260     // create the special document module objects if they don't exist.
261     return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) );
262 }
263 
264 uno::Reference< XHelperInterface >
265 getUnoSheetModuleObj( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException )
266 {
267     uno::Reference< sheet::XSheetCellRange > xSheetRange( xRange, uno::UNO_QUERY_THROW );
268     uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
269     return getUnoSheetModuleObj( xSheet );
270 }
271 
272 uno::Reference< XHelperInterface >
273 getUnoSheetModuleObj( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException )
274 {
275     uno::Reference< container::XEnumerationAccess > xEnumAccess( xRanges, uno::UNO_QUERY_THROW );
276     uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
277     uno::Reference< table::XCellRange > xRange( xEnum->nextElement(), uno::UNO_QUERY_THROW );
278     return getUnoSheetModuleObj( xRange );
279 }
280 
281 uno::Reference< XHelperInterface >
282 getUnoSheetModuleObj( const uno::Reference< table::XCell >& xCell ) throw ( uno::RuntimeException )
283 {
284     uno::Reference< sheet::XSheetCellRange > xSheetRange( xCell, uno::UNO_QUERY_THROW );
285     uno::Reference< sheet::XSpreadsheet > xSheet( xSheetRange->getSpreadsheet(), uno::UNO_SET_THROW );
286     return getUnoSheetModuleObj( xSheet );
287 }
288 
289 uno::Reference< XHelperInterface >
290 getUnoSheetModuleObj( const uno::Reference< frame::XModel >& xModel, SCTAB nTab ) throw ( uno::RuntimeException )
291 {
292     uno::Reference< sheet::XSpreadsheetDocument > xDoc( xModel, uno::UNO_QUERY_THROW );
293     uno::Reference< container::XIndexAccess > xSheets( xDoc->getSheets(), uno::UNO_QUERY_THROW );
294     uno::Reference< sheet::XSpreadsheet > xSheet( xSheets->getByIndex( nTab ), uno::UNO_QUERY_THROW );
295     return getUnoSheetModuleObj( xSheet );
296 }
297 
298 SfxItemSet*
299 ScVbaCellRangeAccess::GetDataSet( ScCellRangesBase* pRangeObj )
300 {
301 	return pRangeObj ? pRangeObj->GetCurrentDataSet( true ) : 0;
302 }
303 
304 // ============================================================================
305 
306 } // namespace excel
307 } // namespace vba
308 } // namespace ooo
309