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