Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "excimp8.hxx"
31 : :
32 : : #include <boost/bind.hpp>
33 : :
34 : : #include <scitems.hxx>
35 : : #include <comphelper/processfactory.hxx>
36 : : #include <comphelper/mediadescriptor.hxx>
37 : : #include <unotools/fltrcfg.hxx>
38 : :
39 : : #include <svtools/wmf.hxx>
40 : :
41 : : #include <editeng/eeitem.hxx>
42 : :
43 : : #include <sfx2/docfile.hxx>
44 : : #include <sfx2/objsh.hxx>
45 : : #include <sfx2/request.hxx>
46 : : #include <sfx2/app.hxx>
47 : : #include <sfx2/docinf.hxx>
48 : : #include <sfx2/frame.hxx>
49 : :
50 : : #include <editeng/brshitem.hxx>
51 : : #include <editeng/editdata.hxx>
52 : : #include <editeng/editeng.hxx>
53 : : #include <editeng/editobj.hxx>
54 : : #include <editeng/editstat.hxx>
55 : : #include <editeng/colritem.hxx>
56 : : #include <editeng/udlnitem.hxx>
57 : : #include <editeng/wghtitem.hxx>
58 : : #include <editeng/postitem.hxx>
59 : : #include <editeng/crsditem.hxx>
60 : : #include <editeng/flditem.hxx>
61 : : #include <svx/xflclit.hxx>
62 : :
63 : : #include <vcl/graph.hxx>
64 : : #include <vcl/bmpacc.hxx>
65 : : #include <sot/exchange.hxx>
66 : :
67 : : #include <svl/stritem.hxx>
68 : :
69 : : #include <tools/string.hxx>
70 : : #include <rtl/math.hxx>
71 : : #include <unotools/localedatawrapper.hxx>
72 : : #include <unotools/charclass.hxx>
73 : : #include <drwlayer.hxx>
74 : :
75 : : #include <boost/scoped_array.hpp>
76 : :
77 : : #include "cell.hxx"
78 : : #include "document.hxx"
79 : : #include "patattr.hxx"
80 : : #include "docpool.hxx"
81 : : #include "attrib.hxx"
82 : : #include "conditio.hxx"
83 : : #include "dbdata.hxx"
84 : : #include "globalnames.hxx"
85 : : #include "editutil.hxx"
86 : : #include "markdata.hxx"
87 : : #include "rangenam.hxx"
88 : : #include "docoptio.hxx"
89 : : #include "globstr.hrc"
90 : : #include "fprogressbar.hxx"
91 : : #include "xltracer.hxx"
92 : : #include "xihelper.hxx"
93 : : #include "xipage.hxx"
94 : : #include "xicontent.hxx"
95 : : #include "xilink.hxx"
96 : : #include "xiescher.hxx"
97 : : #include "xipivot.hxx"
98 : :
99 : : #include "excform.hxx"
100 : : #include "scextopt.hxx"
101 : : #include "stlpool.hxx"
102 : : #include "stlsheet.hxx"
103 : : #include "detfunc.hxx"
104 : : #include "macromgr.hxx"
105 : : #include "queryentry.hxx"
106 : :
107 : : #include <com/sun/star/document/XDocumentProperties.hpp>
108 : : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
109 : : #include <com/sun/star/script/ModuleInfo.hpp>
110 : : #include <com/sun/star/container/XIndexContainer.hpp>
111 : : #include <cppuhelper/component_context.hxx>
112 : : #include "xltoolbar.hxx"
113 : : #include <oox/ole/vbaproject.hxx>
114 : : #include <oox/ole/olestorage.hxx>
115 : : #include <unotools/streamwrap.hxx>
116 : : #include <comphelper/componentcontext.hxx>
117 : :
118 : : using namespace com::sun::star;
119 : : using namespace ::comphelper;
120 : : using ::rtl::OUString;
121 : :
122 : : //OleNameOverrideContainer
123 : :
124 : : typedef ::cppu::WeakImplHelper1< container::XNameContainer > OleNameOverrideContainer_BASE;
125 : :
126 [ + - ][ + - ]: 39 : class OleNameOverrideContainer : public OleNameOverrideContainer_BASE
[ - + ][ + - ]
[ + - ]
127 : : {
128 : : private:
129 : : typedef boost::unordered_map< rtl::OUString, uno::Reference< container::XIndexContainer >, ::rtl::OUStringHash,
130 : : ::std::equal_to< ::rtl::OUString > > NamedIndexToOleName;
131 : : NamedIndexToOleName IdToOleNameHash;
132 : : ::osl::Mutex m_aMutex;
133 : : public:
134 : : // XElementAccess
135 : 0 : virtual uno::Type SAL_CALL getElementType( ) throw (uno::RuntimeException) { return container::XIndexContainer::static_type(0); }
136 : 0 : virtual ::sal_Bool SAL_CALL hasElements( ) throw (uno::RuntimeException)
137 : : {
138 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
139 [ # # ]: 0 : return ( IdToOleNameHash.size() > 0 );
140 : : }
141 : : // XNameAcess
142 : 44 : virtual uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
143 : : {
144 [ + - ]: 44 : ::osl::MutexGuard aGuard( m_aMutex );
145 [ + - ][ - + ]: 44 : if ( !hasByName(aName) )
146 [ # # ]: 0 : throw container::NoSuchElementException();
147 [ + - ][ + - ]: 44 : return uno::makeAny( IdToOleNameHash[ aName ] );
[ + - ]
148 : : }
149 : 0 : virtual uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (uno::RuntimeException)
150 : : {
151 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
152 [ # # ]: 0 : uno::Sequence< ::rtl::OUString > aResult( IdToOleNameHash.size() );
153 [ # # ]: 0 : NamedIndexToOleName::iterator it = IdToOleNameHash.begin();
154 [ # # ]: 0 : NamedIndexToOleName::iterator it_end = IdToOleNameHash.end();
155 [ # # ]: 0 : rtl::OUString* pName = aResult.getArray();
156 [ # # ]: 0 : for (; it != it_end; ++it, ++pName )
157 [ # # ]: 0 : *pName = it->first;
158 [ # # ]: 0 : return aResult;
159 : : }
160 : 93 : virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (uno::RuntimeException)
161 : : {
162 [ + - ]: 93 : ::osl::MutexGuard aGuard( m_aMutex );
163 [ + - ][ + - ]: 93 : return ( IdToOleNameHash.find( aName ) != IdToOleNameHash.end() );
[ + - ]
164 : : }
165 : :
166 : : // XElementAccess
167 : 0 : virtual ::sal_Int32 SAL_CALL getCount( ) throw (uno::RuntimeException)
168 : : {
169 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
170 [ # # ]: 0 : return IdToOleNameHash.size();
171 : : }
172 : : // XNameContainer
173 : 5 : virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException)
174 : : {
175 [ + - ]: 5 : ::osl::MutexGuard aGuard( m_aMutex );
176 [ + - ][ - + ]: 5 : if ( hasByName( aName ) )
177 [ # # ]: 0 : throw container::ElementExistException();
178 : 5 : uno::Reference< container::XIndexContainer > xElement;
179 [ - + ][ + - ]: 5 : if ( ! ( aElement >>= xElement ) )
180 [ # # ]: 0 : throw lang::IllegalArgumentException();
181 [ + - ][ + - ]: 5 : IdToOleNameHash[ aName ] = xElement;
[ + - ]
182 : 5 : }
183 : 0 : virtual void SAL_CALL removeByName( const ::rtl::OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
184 : : {
185 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
186 [ # # ][ # # ]: 0 : if ( !hasByName( aName ) )
187 [ # # ]: 0 : throw container::NoSuchElementException();
188 [ # # ][ # # ]: 0 : IdToOleNameHash.erase( IdToOleNameHash.find( aName ) );
[ # # ]
189 : 0 : }
190 : 0 : virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
191 : : {
192 [ # # ]: 0 : ::osl::MutexGuard aGuard( m_aMutex );
193 [ # # ][ # # ]: 0 : if ( !hasByName( aName ) )
194 [ # # ]: 0 : throw container::NoSuchElementException();
195 : 0 : uno::Reference< container::XIndexContainer > xElement;
196 [ # # ][ # # ]: 0 : if ( ! ( aElement >>= xElement ) )
197 [ # # ]: 0 : throw lang::IllegalArgumentException();
198 [ # # ][ # # ]: 0 : IdToOleNameHash[ aName ] = xElement;
[ # # ]
199 : 0 : }
200 : : };
201 : :
202 : : // defined in docfunc.cxx ( really this needs a new name )
203 : : script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule );
204 : :
205 : 55 : ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) :
206 [ + - ][ + - ]: 55 : ImportExcel( rImpData, rStrm )
207 : : {
208 : : // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
209 [ + - ][ + - ]: 55 : delete pFormConv;
210 [ + - ][ + - ]: 55 : pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() );
211 : 55 : }
212 : :
213 : :
214 [ + - ]: 55 : ImportExcel8::~ImportExcel8()
215 : : {
216 [ - + ]: 110 : }
217 : :
218 : :
219 : 162 : void ImportExcel8::Calccount( void )
220 : : {
221 [ + - ][ + - ]: 162 : ScDocOptions aOpt = pD->GetDocOptions();
222 [ + - ]: 162 : aOpt.SetIterCount( aIn.ReaduInt16() );
223 [ + - ][ + - ]: 162 : pD->SetDocOptions( aOpt );
224 : 162 : }
225 : :
226 : :
227 : 46 : void ImportExcel8::Precision( void )
228 : : {
229 [ + - ][ + - ]: 46 : ScDocOptions aOpt = pD->GetDocOptions();
230 [ + - ]: 46 : aOpt.SetCalcAsShown( aIn.ReaduInt16() == 0 );
231 [ + - ][ + - ]: 46 : pD->SetDocOptions( aOpt );
232 : 46 : }
233 : :
234 : :
235 : 162 : void ImportExcel8::Delta( void )
236 : : {
237 [ + - ][ + - ]: 162 : ScDocOptions aOpt = pD->GetDocOptions();
238 [ + - ]: 162 : aOpt.SetIterEps( aIn.ReadDouble() );
239 [ + - ][ + - ]: 162 : pD->SetDocOptions( aOpt );
240 : 162 : }
241 : :
242 : :
243 : 162 : void ImportExcel8::Iteration( void )
244 : : {
245 [ + - ][ + - ]: 162 : ScDocOptions aOpt = pD->GetDocOptions();
246 [ + - ]: 162 : aOpt.SetIter( aIn.ReaduInt16() == 1 );
247 [ + - ][ + - ]: 162 : pD->SetDocOptions( aOpt );
248 : 162 : }
249 : :
250 : :
251 : 165 : void ImportExcel8::Boundsheet( void )
252 : : {
253 : : sal_uInt8 nLen;
254 : : sal_uInt16 nGrbit;
255 : :
256 [ + - ]: 165 : aIn.DisableDecryption();
257 [ + - ][ + - ]: 165 : maSheetOffsets.push_back( aIn.ReaduInt32() );
258 [ + - ]: 165 : aIn.EnableDecryption();
259 [ + - ][ + - ]: 165 : aIn >> nGrbit >> nLen;
260 : :
261 [ + - ][ + - ]: 165 : rtl::OUString aName( aIn.ReadUniString( nLen ) );
[ + - ]
262 [ + - ][ + - ]: 165 : GetTabInfo().AppendXclTabName( aName, nBdshtTab );
[ + - ][ + - ]
263 : :
264 : 165 : SCTAB nScTab = static_cast< SCTAB >( nBdshtTab );
265 [ + + ]: 165 : if( nScTab > 0 )
266 : : {
267 : : OSL_ENSURE( !pD->HasTable( nScTab ), "ImportExcel8::Boundsheet - sheet exists already" );
268 [ + - ]: 116 : pD->MakeTable( nScTab );
269 : : }
270 : :
271 [ + + ][ - + ]: 165 : if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
272 [ + - ]: 24 : pD->SetVisible( nScTab, false );
273 : :
274 [ + - ][ - + ]: 165 : if( !pD->RenameTab( nScTab, aName ) )
275 : : {
276 [ # # ]: 0 : pD->CreateValidTabName( aName );
277 [ # # ]: 0 : pD->RenameTab( nScTab, aName );
278 : : }
279 : :
280 : 165 : nBdshtTab++;
281 : 165 : }
282 : :
283 : :
284 : 0 : void ImportExcel8::Scenman( void )
285 : : {
286 : : sal_uInt16 nLastDispl;
287 : :
288 [ # # ]: 0 : aIn.Ignore( 4 );
289 [ # # ]: 0 : aIn >> nLastDispl;
290 : :
291 : 0 : maScenList.nLastScenario = nLastDispl;
292 : 0 : }
293 : :
294 : :
295 : 0 : void ImportExcel8::Scenario( void )
296 : : {
297 [ # # ]: 0 : maScenList.aEntries.push_back( new ExcScenario( aIn, *pExcRoot ) );
298 : 0 : }
299 : :
300 : :
301 : 2100 : void ImportExcel8::Labelsst( void )
302 : : {
303 : 2100 : XclAddress aXclPos;
304 : : sal_uInt16 nXF;
305 : : sal_uInt32 nSst;
306 : :
307 [ + - ][ + - ]: 2100 : aIn >> aXclPos >> nXF >> nSst;
[ + - ]
308 : :
309 : 2100 : ScAddress aScPos( ScAddress::UNINITIALIZED );
310 [ + - ][ + - ]: 2100 : if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
[ + - ]
311 : : {
312 [ + - ][ + - ]: 2100 : GetXFRangeBuffer().SetXF( aScPos, nXF );
313 [ + - ][ + - ]: 2100 : if( ScBaseCell* pCell = GetSst().CreateCell( nSst, nXF ) )
[ + - ]
314 [ + - ]: 2100 : GetDoc().PutCell( aScPos.Col(), aScPos.Row(), aScPos.Tab(), pCell );
315 : : }
316 : 2100 : }
317 : :
318 : :
319 : 90 : void ImportExcel8::SheetProtection( void )
320 : : {
321 : 90 : GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
322 : 90 : }
323 : :
324 : 13 : void ImportExcel8::ReadBasic( void )
325 : : {
326 [ + - ]: 13 : SfxObjectShell* pShell = GetDocShell();
327 [ + - ]: 13 : SotStorageRef xRootStrg = GetRootStorage();
328 [ + - ]: 13 : const SvtFilterOptions& rFilterOpt = SvtFilterOptions::Get();
329 [ + - ][ + - ]: 13 : if( pShell && xRootStrg.Is() ) try
[ + - ]
330 : : {
331 [ + - ]: 13 : bool bLoadCode = rFilterOpt.IsLoadExcelBasicCode();
332 [ + - ]: 13 : bool bLoadExecutable = rFilterOpt.IsLoadExcelBasicExecutable();
333 [ + - ]: 13 : bool bLoadStrg = rFilterOpt.IsLoadExcelBasicStorage();
334 : : // #FIXME need to get rid of this, we can also do this from within oox
335 : : // via the "ooo.vba.VBAGlobals" service
336 [ - + ][ # # ]: 13 : if( bLoadCode || bLoadStrg )
337 : : {
338 : 13 : bool bAsComment = !bLoadExecutable;
339 : :
340 [ + - ]: 13 : if ( !bAsComment )
341 : : {
342 : : // see if we have the XCB stream
343 [ + - ][ + - ]: 13 : SvStorageStreamRef xXCB = xRootStrg->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM( "XCB" ) ), STREAM_STD_READ | STREAM_NOCREATE );
[ + - ]
344 [ - + ][ # # ]: 13 : if ( xXCB.Is()|| SVSTREAM_OK == xXCB->GetError() )
[ + - ]
345 : : {
346 [ + - ]: 13 : CTBWrapper wrapper;
347 [ + - ][ + - ]: 13 : if ( wrapper.Read( *xXCB ) )
348 : : {
349 : : #if OSL_DEBUG_LEVEL > 1
350 : : wrapper.Print( stderr );
351 : : #endif
352 [ + - ]: 13 : wrapper.ImportCustomToolBar( *pShell );
353 [ + - ]: 13 : }
354 [ + - ]: 13 : }
355 : : }
356 : : }
357 : : try
358 : : {
359 [ + - ][ + - ]: 13 : ::comphelper::ComponentContext aCtx( ::comphelper::getProcessServiceFactory() );
360 : 13 : SfxMedium& rMedium = GetMedium();
361 [ + - ]: 13 : uno::Reference< io::XInputStream > xIn = rMedium.GetInputStream();
362 [ + - ][ + - ]: 13 : oox::ole::OleStorage root( aCtx.getUNOContext(), xIn, false );
363 [ + - ][ + - ]: 13 : oox::StorageRef vbaStg = root.openSubStorage( CREATE_OUSTRING( "_VBA_PROJECT_CUR" ), false );
364 [ + - ]: 13 : if ( vbaStg.get() )
365 : : {
366 [ + - ][ + - ]: 13 : oox::ole::VbaProject aVbaPrj( aCtx.getUNOContext(), pShell->GetModel(), CREATE_OUSTRING( "Calc") );
[ + - ][ + - ]
367 : : // collect names of embedded form controls, as specified in the VBA project
368 [ + - ][ + - ]: 13 : uno::Reference< container::XNameContainer > xOleNameOverrideSink( new OleNameOverrideContainer );
[ + - ]
369 [ + - ]: 13 : aVbaPrj.setOleOverridesSink( xOleNameOverrideSink );
370 [ + - ]: 13 : aVbaPrj.importVbaProject( *vbaStg );
371 [ + - ][ + - ]: 13 : GetObjectManager().SetOleNameOverrideInfo( xOleNameOverrideSink );
[ + - ]
372 [ + - ][ + - ]: 13 : }
[ + - ][ # # ]
373 : : }
374 [ # # # # ]: 0 : catch( uno::Exception& )
375 : : {
376 : : }
377 : : }
378 [ # # ]: 0 : catch( uno::Exception& )
379 : : {
380 [ + - ]: 13 : }
381 : 13 : }
382 : :
383 : :
384 : 165 : void ImportExcel8::EndSheet( void )
385 : : {
386 : 165 : ImportExcel::EndSheet();
387 : 165 : GetCondFormatManager().Apply();
388 : 165 : GetValidationManager().Apply();
389 : 165 : }
390 : :
391 : :
392 : 55 : void ImportExcel8::PostDocLoad( void )
393 : : {
394 : : #ifndef DISABLE_SCRIPTING
395 : : // reading basic has been delayed until sheet objects (codenames etc.) are read
396 [ + + ]: 55 : if( HasBasic() )
397 : 13 : ReadBasic();
398 : : #endif
399 : : // #i11776# filtered ranges before outlines and hidden rows
400 [ + - ]: 55 : if( pExcRoot->pAutoFilterBuffer )
401 : 55 : pExcRoot->pAutoFilterBuffer->Apply();
402 : :
403 : 55 : GetWebQueryBuffer().Apply(); //! test if extant
404 : 55 : GetSheetProtectBuffer().Apply();
405 : 55 : GetDocProtectBuffer().Apply();
406 : :
407 : 55 : ImportExcel::PostDocLoad();
408 : :
409 : : // Scenarien bemachen! ACHTUNG: Hier wird Tabellen-Anzahl im Dokument erhoeht!!
410 [ - + ][ - + ]: 55 : if( !pD->IsClipboard() && maScenList.aEntries.size() )
[ + - ]
411 : : {
412 : 0 : pD->UpdateChartListenerCollection(); // references in charts must be updated
413 : :
414 : 0 : maScenList.Apply( GetRoot() );
415 : : }
416 : :
417 : : // read doc info (no docshell while pasting from clipboard)
418 : 55 : LoadDocumentProperties();
419 : :
420 : : // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
421 : : // when formula cells are calculated, for the GETPIVOTDATA function.
422 : 55 : }
423 : :
424 : 55 : void ImportExcel8::LoadDocumentProperties()
425 : : {
426 : : // no docshell while pasting from clipboard
427 [ + - ]: 55 : if( SfxObjectShell* pShell = GetDocShell() )
428 : : {
429 : : // BIFF5+ without storage is possible
430 [ + - ]: 55 : SotStorageRef xRootStrg = GetRootStorage();
431 [ + - ]: 55 : if( xRootStrg.Is() ) try
432 : : {
433 [ + - ][ + - ]: 55 : uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
434 [ + - ][ + - ]: 55 : uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW );
[ + - ]
435 [ # # ][ + - ]: 55 : sfx2::LoadOlePropertySet( xDocProps, xRootStrg );
436 : : }
437 [ # # ]: 0 : catch( uno::Exception& )
438 : : {
439 [ + - ]: 55 : }
440 : : }
441 : 55 : }
442 : :
443 : : //___________________________________________________________________
444 : : // autofilter
445 : :
446 : 15 : void ImportExcel8::FilterMode( void )
447 : : {
448 : : // The FilterMode record exists: if either the AutoFilter
449 : : // record exists or an Advanced Filter is saved and stored
450 : : // in the sheet. Thus if the FilterMode records only exists
451 : : // then the latter is true..
452 [ - + ]: 30 : if( !pExcRoot->pAutoFilterBuffer ) return;
453 : :
454 : 15 : XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
455 [ + - ]: 15 : if( pData )
456 : 15 : pData->SetAutoOrAdvanced();
457 : : }
458 : :
459 : 18 : void ImportExcel8::AutoFilterInfo( void )
460 : : {
461 [ - + ]: 36 : if( !pExcRoot->pAutoFilterBuffer ) return;
462 : :
463 : 18 : XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
464 [ + - ]: 18 : if( pData )
465 : : {
466 : 18 : pData->SetAdvancedRange( NULL );
467 : 18 : pData->Activate();
468 : : }
469 : : }
470 : :
471 : 15 : void ImportExcel8::AutoFilter( void )
472 : : {
473 [ - + ]: 30 : if( !pExcRoot->pAutoFilterBuffer ) return;
474 : :
475 : 15 : XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
476 [ + - ]: 15 : if( pData )
477 : 15 : pData->ReadAutoFilter( aIn );
478 : : }
479 : :
480 : :
481 : :
482 : 18 : XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange ) :
483 : : ExcRoot( pRoot ),
484 : : pCurrDBData(NULL),
485 : : bActive( false ),
486 : : bCriteria( false ),
487 : 18 : bAutoOrAdvanced(false)
488 : : {
489 : 18 : aParam.nCol1 = rRange.aStart.Col();
490 : 18 : aParam.nRow1 = rRange.aStart.Row();
491 : 18 : aParam.nTab = rRange.aStart.Tab();
492 : 18 : aParam.nCol2 = rRange.aEnd.Col();
493 : 18 : aParam.nRow2 = rRange.aEnd.Row();
494 : :
495 : 18 : aParam.bInplace = sal_True;
496 : :
497 : 18 : }
498 : :
499 : 3 : void XclImpAutoFilterData::CreateFromDouble( rtl::OUString& rStr, double fVal )
500 : : {
501 : : rStr += ::rtl::math::doubleToUString(fVal,
502 : : rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
503 : 3 : ScGlobal::pLocaleData->getNumDecimalSep()[0], true);
504 : 3 : }
505 : :
506 : 18 : void XclImpAutoFilterData::SetCellAttribs()
507 : : {
508 : 18 : ScDocument& rDoc = pExcRoot->pIR->GetDoc();
509 [ + + ]: 45 : for ( SCCOL nCol = StartCol(); nCol <= EndCol(); nCol++ )
510 : : {
511 : 27 : sal_Int16 nFlag = ((ScMergeFlagAttr*) rDoc.GetAttr( nCol, StartRow(), Tab(), ATTR_MERGE_FLAG ))->GetValue();
512 [ + - ]: 27 : rDoc.ApplyAttr( nCol, StartRow(), Tab(), ScMergeFlagAttr( nFlag | SC_MF_AUTO) );
513 : : }
514 : 18 : }
515 : :
516 : 18 : void XclImpAutoFilterData::InsertQueryParam()
517 : : {
518 [ + - ]: 18 : if (pCurrDBData)
519 : : {
520 : 18 : ScRange aAdvRange;
521 [ + - ]: 18 : sal_Bool bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
522 [ - + ]: 18 : if( bHasAdv )
523 : 0 : pExcRoot->pIR->GetDoc().CreateQueryParam( aAdvRange.aStart.Col(),
524 : 0 : aAdvRange.aStart.Row(), aAdvRange.aEnd.Col(), aAdvRange.aEnd.Row(),
525 [ # # ]: 0 : aAdvRange.aStart.Tab(), aParam );
526 : :
527 [ + - ]: 18 : pCurrDBData->SetQueryParam( aParam );
528 [ - + ]: 18 : if( bHasAdv )
529 [ # # ]: 0 : pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
530 : : else
531 : : {
532 : 18 : pCurrDBData->SetAutoFilter( sal_True );
533 [ + - ]: 18 : SetCellAttribs();
534 : : }
535 : : }
536 : 18 : }
537 : :
538 : 12 : static void ExcelQueryToOooQuery( ScQueryEntry& rEntry )
539 : : {
540 [ - + ][ # # ]: 12 : if (rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL)
541 : 12 : return;
542 : :
543 [ + - ][ + - ]: 12 : String aStr = rEntry.GetQueryItem().maString;
544 : 12 : xub_StrLen nLen = aStr.Len();
545 : 12 : sal_Unicode nStart = aStr.GetChar( 0 );
546 : 12 : sal_Unicode nEnd = aStr.GetChar( nLen-1 );
547 [ - + ][ # # ]: 12 : if( nLen >2 && nStart == '*' && nEnd == '*' )
[ + - ]
548 : : {
549 [ # # ]: 0 : aStr.Erase( nLen-1, 1 );
550 [ # # ]: 0 : aStr.Erase( 0, 1 );
551 [ # # ]: 0 : rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
552 : : }
553 [ + - ][ - + ]: 12 : else if( nLen > 1 && nStart == '*' && nEnd != '*' )
[ # # ]
554 : : {
555 [ # # ]: 0 : aStr.Erase( 0, 1 );
556 [ # # ]: 0 : rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
557 : : }
558 [ + - ][ + - ]: 12 : else if( nLen > 1 && nStart != '*' && nEnd == '*' )
[ - + ]
559 : : {
560 [ # # ]: 0 : aStr.Erase( nLen-1, 1 );
561 [ # # ]: 0 : rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
562 : : }
563 [ - + ][ # # ]: 12 : else if( nLen == 2 && nStart == '*' && nEnd == '*' )
[ # # ]
564 : : {
565 [ # # ]: 0 : aStr.Erase( 0, 1 );
566 : : }
567 [ + - ][ + - ]: 12 : rEntry.GetQueryItem().maString = aStr;
[ + - ]
568 : : }
569 : :
570 : 15 : void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
571 : : {
572 : : sal_uInt16 nCol, nFlags;
573 [ + - ][ + - ]: 15 : rStrm >> nCol >> nFlags;
574 : :
575 [ + - ]: 15 : ScQueryConnect eConn = ::get_flagvalue( nFlags, EXC_AFFLAG_ANDORMASK, SC_OR, SC_AND );
576 : 15 : bool bSimple1 = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE1);
577 : 15 : bool bSimple2 = ::get_flag(nFlags, EXC_AFFLAG_SIMPLE2);
578 : 15 : bool bTop10 = ::get_flag(nFlags, EXC_AFFLAG_TOP10);
579 : 15 : bool bTopOfTop10 = ::get_flag(nFlags, EXC_AFFLAG_TOP10TOP);
580 : 15 : bool bPercent = ::get_flag(nFlags, EXC_AFFLAG_TOP10PERC);
581 : 15 : sal_uInt16 nCntOfTop10 = nFlags >> 7;
582 : :
583 [ - + ]: 15 : if( bTop10 )
584 : : {
585 [ # # ]: 0 : ScQueryEntry& aEntry = aParam.AppendEntry();
586 [ # # ]: 0 : ScQueryEntry::Item& rItem = aEntry.GetQueryItem();
587 : 0 : aEntry.bDoQuery = true;
588 : 0 : aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
589 : : aEntry.eOp = bTopOfTop10 ?
590 [ # # ][ # # ]: 0 : (bPercent ? SC_TOPPERC : SC_TOPVAL) : (bPercent ? SC_BOTPERC : SC_BOTVAL);
[ # # ]
591 : 0 : aEntry.eConnect = SC_AND;
592 : :
593 : 0 : rItem.meType = ScQueryEntry::ByString;
594 : 0 : rItem.maString = rtl::OUString::valueOf(static_cast<sal_Int32>(nCntOfTop10));
595 : :
596 [ # # ]: 0 : rStrm.Ignore(20);
597 : 15 : return;
598 : : }
599 : :
600 : : sal_uInt8 nType, nOper, nBoolErr, nVal;
601 : : sal_Int32 nRK;
602 : : double fVal;
603 : : bool bIgnore;
604 : :
605 : 15 : sal_uInt8 nStrLen[2] = { 0, 0 };
606 [ + - ][ + + ]: 75 : ScQueryEntry aEntries[2];
[ + - # #
# # ]
607 : :
608 [ + + ]: 45 : for (size_t nE = 0; nE < 2; ++nE)
609 : : {
610 : 30 : ScQueryEntry& rEntry = aEntries[nE];
611 [ + - ]: 30 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
612 : 30 : bIgnore = false;
613 : :
614 [ + - ][ + - ]: 30 : rStrm >> nType >> nOper;
615 [ - + - - : 30 : switch( nOper )
- - + ]
616 : : {
617 : : case EXC_AFOPER_LESS:
618 : 0 : rEntry.eOp = SC_LESS;
619 : 0 : break;
620 : : case EXC_AFOPER_EQUAL:
621 : 18 : rEntry.eOp = SC_EQUAL;
622 : 18 : break;
623 : : case EXC_AFOPER_LESSEQUAL:
624 : 0 : rEntry.eOp = SC_LESS_EQUAL;
625 : 0 : break;
626 : : case EXC_AFOPER_GREATER:
627 : 0 : rEntry.eOp = SC_GREATER;
628 : 0 : break;
629 : : case EXC_AFOPER_NOTEQUAL:
630 : 0 : rEntry.eOp = SC_NOT_EQUAL;
631 : 0 : break;
632 : : case EXC_AFOPER_GREATEREQUAL:
633 : 0 : rEntry.eOp = SC_GREATER_EQUAL;
634 : 0 : break;
635 : : default:
636 : 12 : rEntry.eOp = SC_EQUAL;
637 : : }
638 : :
639 : 30 : rtl::OUString aStr;
640 : :
641 [ - + + - : 30 : switch( nType )
- - + ]
642 : : {
643 : : case EXC_AFTYPE_RK:
644 [ # # ]: 0 : rStrm >> nRK;
645 [ # # ]: 0 : rStrm.Ignore( 4 );
646 : : CreateFromDouble(
647 [ # # ][ # # ]: 0 : rItem.maString, XclTools::GetDoubleFromRK(nRK));
648 : 0 : break;
649 : : case EXC_AFTYPE_DOUBLE:
650 [ + - ]: 3 : rStrm >> fVal;
651 [ + - ]: 3 : CreateFromDouble(rItem.maString, fVal);
652 : 3 : break;
653 : : case EXC_AFTYPE_STRING:
654 [ + - ]: 12 : rStrm.Ignore( 4 );
655 [ + - ]: 12 : rStrm >> nStrLen[ nE ];
656 [ + - ]: 12 : rStrm.Ignore( 3 );
657 : 12 : rItem.maString = rtl::OUString();
658 : 12 : break;
659 : : case EXC_AFTYPE_BOOLERR:
660 [ # # ][ # # ]: 0 : rStrm >> nBoolErr >> nVal;
661 [ # # ]: 0 : rStrm.Ignore( 6 );
662 : 0 : rItem.maString = rtl::OUString::valueOf(static_cast<sal_Int32>(nVal));
663 : 0 : bIgnore = (nBoolErr != 0);
664 : 0 : break;
665 : : case EXC_AFTYPE_EMPTY:
666 [ # # ]: 0 : rEntry.SetQueryByEmpty();
667 : 0 : break;
668 : : case EXC_AFTYPE_NOTEMPTY:
669 [ # # ]: 0 : rEntry.SetQueryByNonEmpty();
670 : 0 : break;
671 : : default:
672 [ + - ]: 15 : rStrm.Ignore( 8 );
673 : 15 : bIgnore = true;
674 : : }
675 : :
676 [ + + ]: 30 : if (!bIgnore)
677 : : {
678 : 15 : rEntry.bDoQuery = true;
679 : 15 : rItem.meType = ScQueryEntry::ByString;
680 : 15 : rEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
681 [ - + ]: 15 : rEntry.eConnect = nE ? eConn : SC_AND;
682 : : }
683 : 30 : }
684 : :
685 [ + - ]: 15 : if (eConn == SC_AND)
686 : : {
687 [ + + ]: 45 : for (size_t nE = 0; nE < 2; ++nE)
688 : : {
689 [ + + ][ + - ]: 30 : if (nStrLen[nE] && aEntries[nE].bDoQuery)
690 : : {
691 [ + - ][ + - ]: 12 : aEntries[nE].GetQueryItem().maString = rStrm.ReadUniString(nStrLen[nE]);
[ + - ][ + - ]
692 [ + - ]: 12 : ExcelQueryToOooQuery(aEntries[nE]);
693 [ + - ][ + - ]: 12 : aParam.AppendEntry() = aEntries[nE];
694 : : }
695 : : }
696 : : }
697 : : else
698 : : {
699 : : OSL_ASSERT(eConn == SC_OR);
700 : : // Import only when both conditions are for simple equality, else
701 : : // import only the 1st condition due to conflict with the ordering of
702 : : // conditions. #i39464#.
703 : : //
704 : : // Example: Let A1 be a condition of column A, and B1 and B2
705 : : // conditions of column B, connected with OR. Excel performs 'A1 AND
706 : : // (B1 OR B2)' in this case, but Calc would do '(A1 AND B1) OR B2'
707 : : // instead.
708 : :
709 [ # # ][ # # ]: 0 : if (bSimple1 && bSimple2 && nStrLen[0] && nStrLen[1])
[ # # ][ # # ]
710 : : {
711 : : // Two simple OR'ed equal conditions. We can import this correctly.
712 [ # # ]: 0 : ScQueryEntry& rEntry = aParam.AppendEntry();
713 : 0 : rEntry.bDoQuery = true;
714 : 0 : rEntry.eOp = SC_EQUAL;
715 : 0 : rEntry.eConnect = SC_AND;
716 [ # # ]: 0 : ScQueryEntry::QueryItemsType aItems;
717 [ # # ]: 0 : aItems.reserve(2);
718 : 0 : ScQueryEntry::Item aItem1, aItem2;
719 [ # # ][ # # ]: 0 : aItem1.maString = rStrm.ReadUniString(nStrLen[0]);
[ # # ]
720 : 0 : aItem1.meType = ScQueryEntry::ByString;
721 [ # # ][ # # ]: 0 : aItem2.maString = rStrm.ReadUniString(nStrLen[1]);
[ # # ]
722 : 0 : aItem2.meType = ScQueryEntry::ByString;
723 [ # # ]: 0 : aItems.push_back(aItem1);
724 [ # # ]: 0 : aItems.push_back(aItem2);
725 [ # # ][ # # ]: 0 : rEntry.GetQueryItems().swap(aItems);
[ # # ]
726 : : }
727 [ # # ][ # # ]: 0 : else if (nStrLen[0] && aEntries[0].bDoQuery)
728 : : {
729 : : // Due to conflict, we can import only the first condition.
730 [ # # ][ # # ]: 0 : aEntries[0].GetQueryItem().maString = rStrm.ReadUniString(nStrLen[0]);
[ # # ][ # # ]
731 [ # # ]: 0 : ExcelQueryToOooQuery(aEntries[0]);
732 [ # # ][ # # ]: 0 : aParam.AppendEntry() = aEntries[0];
733 : : }
734 [ + + ][ # # ]: 45 : }
735 : : }
736 : :
737 : 18 : void XclImpAutoFilterData::SetAdvancedRange( const ScRange* pRange )
738 : : {
739 [ - + ]: 18 : if (pRange)
740 : : {
741 : 0 : aCriteriaRange = *pRange;
742 : 0 : bCriteria = true;
743 : : }
744 : : else
745 : 18 : bCriteria = false;
746 : 18 : }
747 : :
748 : 0 : void XclImpAutoFilterData::SetExtractPos( const ScAddress& rAddr )
749 : : {
750 : 0 : aParam.nDestCol = rAddr.Col();
751 : 0 : aParam.nDestRow = rAddr.Row();
752 : 0 : aParam.nDestTab = rAddr.Tab();
753 : 0 : aParam.bInplace = false;
754 : 0 : aParam.bDestPers = sal_True;
755 : 0 : }
756 : :
757 : 18 : void XclImpAutoFilterData::Apply()
758 : : {
759 : 18 : CreateScDBData();
760 : :
761 [ + - ]: 18 : if( bActive )
762 : : {
763 : 18 : InsertQueryParam();
764 : :
765 : : // #i38093# rows hidden by filter need extra flag, but CR_FILTERED is not set here yet
766 : : // SCROW nRow1 = StartRow();
767 : : // SCROW nRow2 = EndRow();
768 : : // size_t nRows = nRow2 - nRow1 + 1;
769 : : // boost::scoped_array<sal_uInt8> pFlags( new sal_uInt8[nRows]);
770 : : // pExcRoot->pDoc->GetRowFlagsArray( Tab()).FillDataArray( nRow1, nRow2,
771 : : // pFlags.get());
772 : : // for (size_t j=0; j<nRows; ++j)
773 : : // {
774 : : // if ((pFlags[j] & CR_HIDDEN) && !(pFlags[j] & CR_FILTERED))
775 : : // pExcRoot->pDoc->SetRowFlags( nRow1 + j, Tab(),
776 : : // pFlags[j] | CR_FILTERED );
777 : : // }
778 : : }
779 : 18 : }
780 : :
781 : 18 : void XclImpAutoFilterData::CreateScDBData()
782 : : {
783 : :
784 : : // Create the ScDBData() object if the AutoFilter is activated
785 : : // or if we need to create the Advanced Filter.
786 [ - + ][ # # ]: 18 : if( bActive || bCriteria)
787 : : {
788 : 18 : ScDocument* pDoc = pExcRoot->pIR->GetDocPtr();
789 [ + - ][ + - ]: 18 : String aNewName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME));
790 : 18 : pCurrDBData = new ScDBData(aNewName , Tab(),
791 [ + - ]: 36 : StartCol(),StartRow(), EndCol(),EndRow() );
[ + - + - ]
792 [ - + ]: 18 : if(bCriteria)
793 : : {
794 [ # # ]: 0 : EnableRemoveFilter();
795 : :
796 [ # # ]: 0 : pCurrDBData->SetQueryParam( aParam );
797 [ # # ]: 0 : pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
798 : : }
799 : : else
800 [ + - ]: 18 : pCurrDBData->SetAdvancedQuerySource(NULL);
801 [ + - ][ + - ]: 18 : pDoc->SetAnonymousDBData(Tab(), pCurrDBData);
802 : : }
803 : :
804 : 18 : }
805 : :
806 : 0 : void XclImpAutoFilterData::EnableRemoveFilter()
807 : : {
808 : : // only if this is a saved Advanced filter
809 [ # # ][ # # ]: 0 : if( !bActive && bAutoOrAdvanced )
810 : : {
811 : 0 : ScQueryEntry& aEntry = aParam.AppendEntry();
812 : 0 : aEntry.bDoQuery = true;
813 : : }
814 : :
815 : : // TBD: force the automatic activation of the
816 : : // "Remove Filter" by setting a virtual mouse click
817 : : // inside the advanced range
818 : 0 : }
819 : :
820 : 18 : void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange)
821 : : {
822 [ + - ]: 18 : if( !GetByTab( rRange.aStart.Tab() ) )
823 [ + - ]: 18 : maFilters.push_back( new XclImpAutoFilterData( pRoot, rRange) );
824 : 18 : }
825 : :
826 : 0 : void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange& rRange )
827 : : {
828 : 0 : XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
829 [ # # ]: 0 : if( pData )
830 : 0 : pData->SetAdvancedRange( &rRange );
831 : 0 : }
832 : :
833 : 0 : void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange )
834 : : {
835 : 0 : XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
836 [ # # ]: 0 : if( pData )
837 : 0 : pData->SetExtractPos( rRange.aStart );
838 : 0 : }
839 : :
840 : 55 : void XclImpAutoFilterBuffer::Apply()
841 : : {
842 : : std::for_each(maFilters.begin(),maFilters.end(),
843 : 55 : boost::bind(&XclImpAutoFilterData::Apply,_1));
844 : 55 : }
845 : :
846 : 231 : XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab )
847 : : {
848 [ + - ]: 231 : boost::ptr_vector<XclImpAutoFilterData>::iterator it;
849 [ + - ][ + - ]: 432 : for( it = maFilters.begin(); it != maFilters.end(); ++it )
[ + - ][ + - ]
[ + + ]
850 : : {
851 [ + - ][ + + ]: 267 : if( it->Tab() == nTab )
852 [ + - ]: 66 : return const_cast<XclImpAutoFilterData*>(&(*it));
853 : : }
854 : 231 : return NULL;
855 [ + - ][ + - ]: 24 : }
856 : :
857 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|