xref: /trunk/main/sc/source/filter/excel/excimp8.cxx (revision b77af630)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26 
27 #include "excimp8.hxx"
28 
29 #include <scitems.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/mediadescriptor.hxx>
32 #include <unotools/fltrcfg.hxx>
33 
34 #include <svtools/wmf.hxx>
35 
36 #include <editeng/eeitem.hxx>
37 
38 #include <sfx2/docfile.hxx>
39 #include <sfx2/objsh.hxx>
40 #include <sfx2/request.hxx>
41 #include <sfx2/app.hxx>
42 #include <sfx2/docinf.hxx>
43 #include <sfx2/frame.hxx>
44 
45 #include <editeng/brshitem.hxx>
46 #include <editeng/editdata.hxx>
47 #include <editeng/editeng.hxx>
48 #include <editeng/editobj.hxx>
49 #include <editeng/editstat.hxx>
50 #include <editeng/colritem.hxx>
51 #include <editeng/udlnitem.hxx>
52 #include <editeng/wghtitem.hxx>
53 #include <editeng/postitem.hxx>
54 #include <editeng/crsditem.hxx>
55 #include <editeng/flditem.hxx>
56 #include <svx/xflclit.hxx>
57 
58 #include <vcl/graph.hxx>
59 #include <vcl/bmpacc.hxx>
60 #include <sot/exchange.hxx>
61 
62 #include <svl/stritem.hxx>
63 
64 #include <tools/string.hxx>
65 #include <tools/urlobj.hxx>
66 #include <rtl/math.hxx>
67 #include <unotools/localedatawrapper.hxx>
68 #include <unotools/charclass.hxx>
69 #include <drwlayer.hxx>
70 
71 #include <boost/scoped_array.hpp>
72 
73 #include "cell.hxx"
74 #include "document.hxx"
75 #include "patattr.hxx"
76 #include "docpool.hxx"
77 #include "attrib.hxx"
78 #include "conditio.hxx"
79 #include "dbcolect.hxx"
80 #include "editutil.hxx"
81 #include "markdata.hxx"
82 #include "rangenam.hxx"
83 #include "docoptio.hxx"
84 #include "globstr.hrc"
85 #include "fprogressbar.hxx"
86 #include "xltracer.hxx"
87 #include "xihelper.hxx"
88 #include "xipage.hxx"
89 #include "xicontent.hxx"
90 #include "xilink.hxx"
91 #include "xiescher.hxx"
92 #include "xipivot.hxx"
93 
94 #include "excform.hxx"
95 #include "scextopt.hxx"
96 #include "stlpool.hxx"
97 #include "stlsheet.hxx"
98 #include "detfunc.hxx"
99 
100 #include <com/sun/star/document/XDocumentProperties.hpp>
101 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
102 #include <com/sun/star/document/XFilter.hpp>
103 #include <com/sun/star/document/XImporter.hpp>
104 
105 using namespace com::sun::star;
106 using namespace ::comphelper;
107 using ::rtl::OUString;
108 
109 
ImportExcel8(XclImpRootData & rImpData,SvStream & rStrm)110 ImportExcel8::ImportExcel8( XclImpRootData& rImpData, SvStream& rStrm ) :
111     ImportExcel( rImpData, rStrm )
112 {
113     // replace BIFF2-BIFF5 formula importer with BIFF8 formula importer
114 	delete pFormConv;
115     pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc8( GetRoot() );
116 }
117 
118 
~ImportExcel8()119 ImportExcel8::~ImportExcel8()
120 {
121 }
122 
123 
Calccount(void)124 void ImportExcel8::Calccount( void )
125 {
126 	ScDocOptions	aOpt = pD->GetDocOptions();
127 	aOpt.SetIterCount( aIn.ReaduInt16() );
128 	pD->SetDocOptions( aOpt );
129 }
130 
131 
Precision(void)132 void ImportExcel8::Precision( void )
133 {
134     ScDocOptions aOpt = pD->GetDocOptions();
135     aOpt.SetCalcAsShown( aIn.ReaduInt16() == 0 );
136     pD->SetDocOptions( aOpt );
137 }
138 
139 
Delta(void)140 void ImportExcel8::Delta( void )
141 {
142 	ScDocOptions	aOpt = pD->GetDocOptions();
143 	aOpt.SetIterEps( aIn.ReadDouble() );
144 	pD->SetDocOptions( aOpt );
145 }
146 
147 
Iteration(void)148 void ImportExcel8::Iteration( void )
149 {
150 	ScDocOptions	aOpt = pD->GetDocOptions();
151 	aOpt.SetIter( aIn.ReaduInt16() == 1 );
152 	pD->SetDocOptions( aOpt );
153 }
154 
155 
Boundsheet(void)156 void ImportExcel8::Boundsheet( void )
157 {
158 	sal_uInt8			nLen;
159 	sal_uInt16			nGrbit;
160 
161     aIn.DisableDecryption();
162     maSheetOffsets.push_back( aIn.ReaduInt32() );
163     aIn.EnableDecryption();
164 	aIn >> nGrbit >> nLen;
165 
166     String aName( aIn.ReadUniString( nLen ) );
167     GetTabInfo().AppendXclTabName( aName, nBdshtTab );
168 
169     SCTAB nScTab = static_cast< SCTAB >( nBdshtTab );
170     if( nScTab > 0 )
171 	{
172         DBG_ASSERT( !pD->HasTable( nScTab ), "ImportExcel8::Boundsheet - sheet exists already" );
173         pD->MakeTable( nScTab );
174 	}
175 
176 	//assume pending row heights true here. Only optimize the excel8 type for now. i120586
177 	//if the sheet contain sdrobject, will set false then.
178 	pD->SetPendingRowHeights( nScTab, true );
179 	//end i120586
180 	if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
181         pD->SetVisible( nScTab, sal_False );
182 
183     if( !pD->RenameTab( nScTab, aName ) )
184     {
185         pD->CreateValidTabName( aName );
186         pD->RenameTab( nScTab, aName );
187     }
188 
189 	nBdshtTab++;
190 }
191 
192 
Scenman(void)193 void ImportExcel8::Scenman( void )
194 {
195 	sal_uInt16				nLastDispl;
196 
197     aIn.Ignore( 4 );
198 	aIn >> nLastDispl;
199 
200 	aScenList.SetLast( nLastDispl );
201 }
202 
203 
Scenario(void)204 void ImportExcel8::Scenario( void )
205 {
206 	aScenList.Append( new ExcScenario( aIn, *pExcRoot ) );
207 }
208 
209 
Labelsst(void)210 void ImportExcel8::Labelsst( void )
211 {
212     XclAddress aXclPos;
213     sal_uInt16 nXF;
214     sal_uInt32  nSst;
215 
216     aIn >> aXclPos >> nXF >> nSst;
217 
218     ScAddress aScPos( ScAddress::UNINITIALIZED );
219     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
220 	{
221         GetXFRangeBuffer().SetXF( aScPos, nXF );
222         if( ScBaseCell* pCell = GetSst().CreateCell( nSst, nXF ) )
223             GetDoc().PutCell( aScPos.Col(), aScPos.Row(), aScPos.Tab(), pCell );
224 	}
225 }
226 
227 
SheetProtection(void)228 void ImportExcel8::SheetProtection( void )
229 {
230     GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() );
231 }
232 
ReadBasic(void)233 void ImportExcel8::ReadBasic( void )
234 {
235     SfxObjectShell* pShell = GetDocShell();
236     SotStorageRef xRootStrg = GetRootStorage();
237     if( pShell && xRootStrg.Is() ) try
238     {
239         uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext(), uno::UNO_SET_THROW );
240         uno::Reference< lang::XMultiComponentFactory > xFactory( xContext->getServiceManager(), uno::UNO_SET_THROW );
241         uno::Sequence< beans::NamedValue > aArgSeq( 1 );
242         aArgSeq[ 0 ].Name = CREATE_OUSTRING( "ColorPalette" );
243         aArgSeq[ 0 ].Value <<= GetPalette().CreateColorSequence();
244 
245         uno::Sequence< uno::Any > aArgs( 2 );
246         // framework calls filter objects with factory as first argument
247         aArgs[ 0 ] <<= xFactory;
248         aArgs[ 1 ] <<= aArgSeq;
249 
250         uno::Reference< document::XImporter > xImporter( xFactory->createInstanceWithArgumentsAndContext(
251             CREATE_OUSTRING( "com.sun.star.comp.oox.xls.ExcelVbaProjectFilter" ), aArgs, xContext ), uno::UNO_QUERY_THROW );
252 
253         uno::Reference< lang::XComponent > xComponent( pShell->GetModel(), uno::UNO_QUERY_THROW );
254         xImporter->setTargetDocument( xComponent );
255 
256         MediaDescriptor aMediaDesc;
257         SfxMedium& rMedium = GetMedium();
258         SfxItemSet* pItemSet = rMedium.GetItemSet();
259         if( pItemSet )
260         {
261             SFX_ITEMSET_ARG( pItemSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
262             if( pFileNameItem )
263                 aMediaDesc[ MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( pFileNameItem->GetValue() );
264             SFX_ITEMSET_ARG( pItemSet, pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False );
265             if( pPasswordItem )
266                 aMediaDesc[ MediaDescriptor::PROP_PASSWORD() ] <<= ::rtl::OUString( pPasswordItem->GetValue() );
267             SFX_ITEMSET_ARG( pItemSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
268             if( pEncryptionDataItem )
269                 aMediaDesc[ MediaDescriptor::PROP_ENCRYPTIONDATA() ] = pEncryptionDataItem->GetValue();
270         }
271         aMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ] <<= rMedium.GetInputStream();
272         aMediaDesc[ MediaDescriptor::PROP_INTERACTIONHANDLER() ] <<= rMedium.GetInteractionHandler();
273 
274         // call the filter
275         uno::Reference< document::XFilter > xFilter( xImporter, uno::UNO_QUERY_THROW );
276         xFilter->filter( aMediaDesc.getAsConstPropertyValueList() );
277     }
278     catch( uno::Exception& )
279     {
280     }
281 }
282 
283 
EndSheet(void)284 void ImportExcel8::EndSheet( void )
285 {
286     GetCondFormatManager().Apply();
287 	ImportExcel::EndSheet();
288 }
289 
290 
PostDocLoad(void)291 void ImportExcel8::PostDocLoad( void )
292 {
293     // reading basic has been delayed until sheet objects (codenames etc.) are read
294     if( HasBasic() )
295         ReadBasic();
296     // #i11776# filtered ranges before outlines and hidden rows
297     if( pExcRoot->pAutoFilterBuffer )
298         pExcRoot->pAutoFilterBuffer->Apply();
299 
300     GetWebQueryBuffer().Apply();    //! test if extant
301     GetSheetProtectBuffer().Apply();
302     GetDocProtectBuffer().Apply();
303 
304 	ImportExcel::PostDocLoad();
305 
306 	// Scenarien bemachen! ACHTUNG: Hier wird Tabellen-Anzahl im Dokument erhoeht!!
307     if( !pD->IsClipboard() && aScenList.Count() )
308 	{
309 		pD->UpdateChartListenerCollection();	// references in charts must be updated
310 
311         aScenList.Apply( GetRoot() );
312 	}
313 
314     // read doc info (no docshell while pasting from clipboard)
315     LoadDocumentProperties();
316 
317     // #i45843# Pivot tables are now handled outside of PostDocLoad, so they are available
318     // when formula cells are calculated, for the GETPIVOTDATA function.
319 }
320 
LoadDocumentProperties()321 void ImportExcel8::LoadDocumentProperties()
322 {
323     // no docshell while pasting from clipboard
324     if( SfxObjectShell* pShell = GetDocShell() )
325     {
326         // BIFF5+ without storage is possible
327         SotStorageRef xRootStrg = GetRootStorage();
328         if( xRootStrg.Is() ) try
329         {
330             uno::Reference< document::XDocumentPropertiesSupplier > xDPS( pShell->GetModel(), uno::UNO_QUERY_THROW );
331             uno::Reference< document::XDocumentProperties > xDocProps( xDPS->getDocumentProperties(), uno::UNO_SET_THROW );
332             sfx2::LoadOlePropertySet( xDocProps, xRootStrg );
333         }
334         catch( uno::Exception& )
335         {
336         }
337     }
338 }
339 
340 //___________________________________________________________________
341 // autofilter
342 
FilterMode(void)343 void ImportExcel8::FilterMode( void )
344 {
345     // The FilterMode record exists: if either the AutoFilter
346     // record exists or an Advanced Filter is saved and stored
347     // in the sheet. Thus if the FilterMode records only exists
348     // then the latter is true..
349     if( !pExcRoot->pAutoFilterBuffer ) return;
350 
351     pExcRoot->pAutoFilterBuffer->IncrementActiveAF();
352 
353     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
354     if( pData )
355         pData->SetAutoOrAdvanced();
356 }
357 
AutoFilterInfo(void)358 void ImportExcel8::AutoFilterInfo( void )
359 {
360     if( !pExcRoot->pAutoFilterBuffer ) return;
361 
362     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
363 	if( pData )
364 	{
365 		pData->SetAdvancedRange( NULL );
366         pData->Activate();
367     }
368 }
369 
AutoFilter(void)370 void ImportExcel8::AutoFilter( void )
371 {
372     if( !pExcRoot->pAutoFilterBuffer ) return;
373 
374     XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() );
375 	if( pData )
376 		pData->ReadAutoFilter( aIn );
377 }
378 
379 
380 
XclImpAutoFilterData(RootData * pRoot,const ScRange & rRange,const String & rName)381 XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange, const String& rName ) :
382 		ExcRoot( pRoot ),
383         pCurrDBData(NULL),
384 		nFirstEmpty( 0 ),
385 		bActive( sal_False ),
386 		bHasConflict( sal_False ),
387         bCriteria( sal_False ),
388         bAutoOrAdvanced(sal_False),
389         aFilterName(rName)
390 {
391 	aParam.nCol1 = rRange.aStart.Col();
392 	aParam.nRow1 = rRange.aStart.Row();
393     aParam.nTab = rRange.aStart.Tab();
394     aParam.nCol2 = rRange.aEnd.Col();
395 	aParam.nRow2 = rRange.aEnd.Row();
396 
397     aParam.bInplace = sal_True;
398 
399 }
400 
CreateFromDouble(String & rStr,double fVal)401 void XclImpAutoFilterData::CreateFromDouble( String& rStr, double fVal )
402 {
403     rStr += String( ::rtl::math::doubleToUString( fVal,
404                 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
405                 ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0), sal_True));
406 }
407 
SetCellAttribs()408 void XclImpAutoFilterData::SetCellAttribs()
409 {
410     ScDocument& rDoc = pExcRoot->pIR->GetDoc();
411 	for ( SCCOL nCol = StartCol(); nCol <= EndCol(); nCol++ )
412 	{
413         sal_Int16 nFlag = ((ScMergeFlagAttr*) rDoc.GetAttr( nCol, StartRow(), Tab(), ATTR_MERGE_FLAG ))->GetValue();
414         rDoc.ApplyAttr( nCol, StartRow(), Tab(), ScMergeFlagAttr( nFlag | SC_MF_AUTO) );
415 	}
416 }
417 
InsertQueryParam()418 void XclImpAutoFilterData::InsertQueryParam()
419 {
420 	if( pCurrDBData && !bHasConflict )
421 	{
422 		ScRange	aAdvRange;
423 		sal_Bool	bHasAdv = pCurrDBData->GetAdvancedQuerySource( aAdvRange );
424 		if( bHasAdv )
425             pExcRoot->pIR->GetDoc().CreateQueryParam( aAdvRange.aStart.Col(),
426 				aAdvRange.aStart.Row(), aAdvRange.aEnd.Col(), aAdvRange.aEnd.Row(),
427 				aAdvRange.aStart.Tab(), aParam );
428 
429 		pCurrDBData->SetQueryParam( aParam );
430 		if( bHasAdv )
431 			pCurrDBData->SetAdvancedQuerySource( &aAdvRange );
432 		else
433 		{
434 			pCurrDBData->SetAutoFilter( sal_True );
435 			SetCellAttribs();
436 		}
437 	}
438 }
439 
ExcelQueryToOooQuery(ScQueryEntry & rEntry)440 static void ExcelQueryToOooQuery( ScQueryEntry& rEntry )
441 {
442     if( ( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL ) || rEntry.pStr == NULL )
443         return;
444     else
445     {
446         xub_StrLen nLen = rEntry.pStr->Len();
447         sal_Unicode nStart = rEntry.pStr->GetChar( 0 );
448         sal_Unicode nEnd   = rEntry.pStr->GetChar( nLen-1 );
449         if( nLen >2 && nStart == '*' && nEnd == '*' )
450         {
451             rEntry.pStr->Erase( nLen-1, 1 );
452             rEntry.pStr->Erase( 0, 1 );
453             rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN;
454         }
455         else if( nLen > 1 && nStart == '*' && nEnd != '*' )
456         {
457             rEntry.pStr->Erase( 0, 1 );
458             rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH;
459         }
460         else if( nLen > 1 && nStart != '*' && nEnd == '*' )
461         {
462             rEntry.pStr->Erase( nLen-1, 1 );
463             rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH;
464         }
465         else if( nLen == 2 && nStart == '*' && nEnd == '*' )
466         {
467             rEntry.pStr->Erase( 0, 1 );
468         }
469     }
470 }
471 
ReadAutoFilter(XclImpStream & rStrm)472 void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm )
473 {
474 	sal_uInt16 nCol, nFlags;
475 	rStrm >> nCol >> nFlags;
476 
477     ScQueryConnect  eConn       = ::get_flagvalue( nFlags, EXC_AFFLAG_ANDORMASK, SC_OR, SC_AND );
478     sal_Bool            bTop10      = ::get_flag( nFlags, EXC_AFFLAG_TOP10 );
479     sal_Bool            bTopOfTop10 = ::get_flag( nFlags, EXC_AFFLAG_TOP10TOP );
480     sal_Bool            bPercent    = ::get_flag( nFlags, EXC_AFFLAG_TOP10PERC );
481 	sal_uInt16			nCntOfTop10	= nFlags >> 7;
482 	SCSIZE			nCount		= aParam.GetEntryCount();
483 
484 	if( bTop10 )
485 	{
486 		if( nFirstEmpty < nCount )
487 		{
488 			ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
489 			aEntry.bDoQuery = sal_True;
490 			aEntry.bQueryByString = sal_True;
491 			aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
492 			aEntry.eOp = bTopOfTop10 ?
493 				(bPercent ? SC_TOPPERC : SC_TOPVAL) : (bPercent ? SC_BOTPERC : SC_BOTVAL);
494 			aEntry.eConnect = SC_AND;
495 			aEntry.pStr->Assign( String::CreateFromInt32( (sal_Int32) nCntOfTop10 ) );
496 
497             rStrm.Ignore( 20 );
498 			nFirstEmpty++;
499 		}
500 	}
501 	else
502 	{
503 		sal_uInt8	nE, nType, nOper, nBoolErr, nVal;
504         sal_Int32   nRK;
505 		double	fVal;
506 		sal_Bool	bIgnore;
507 
508 		sal_uInt8	nStrLen[ 2 ]	= { 0, 0 };
509         ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL };
510 
511 		for( nE = 0; nE < 2; nE++ )
512 		{
513 			if( nFirstEmpty < nCount )
514 			{
515 				ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
516                 pQueryEntries[ nE ] = &aEntry;
517 				bIgnore = sal_False;
518 
519 				rStrm >> nType >> nOper;
520 				switch( nOper )
521 				{
522 					case EXC_AFOPER_LESS:
523 						aEntry.eOp = SC_LESS;
524 					break;
525 					case EXC_AFOPER_EQUAL:
526 						aEntry.eOp = SC_EQUAL;
527 					break;
528 					case EXC_AFOPER_LESSEQUAL:
529 						aEntry.eOp = SC_LESS_EQUAL;
530 					break;
531 					case EXC_AFOPER_GREATER:
532 						aEntry.eOp = SC_GREATER;
533 					break;
534 					case EXC_AFOPER_NOTEQUAL:
535 						aEntry.eOp = SC_NOT_EQUAL;
536 					break;
537 					case EXC_AFOPER_GREATEREQUAL:
538 						aEntry.eOp = SC_GREATER_EQUAL;
539 					break;
540 					default:
541 						aEntry.eOp = SC_EQUAL;
542 				}
543 
544 				switch( nType )
545 				{
546 					case EXC_AFTYPE_RK:
547 						rStrm >> nRK;
548                         rStrm.Ignore( 4 );
549                         CreateFromDouble( *aEntry.pStr, XclTools::GetDoubleFromRK( nRK ) );
550 					break;
551 					case EXC_AFTYPE_DOUBLE:
552 						rStrm >> fVal;
553 						CreateFromDouble( *aEntry.pStr, fVal );
554 					break;
555 					case EXC_AFTYPE_STRING:
556                         rStrm.Ignore( 4 );
557 						rStrm >> nStrLen[ nE ];
558                         rStrm.Ignore( 3 );
559 						aEntry.pStr->Erase();
560 					break;
561 					case EXC_AFTYPE_BOOLERR:
562 						rStrm >> nBoolErr >> nVal;
563                         rStrm.Ignore( 6 );
564 						aEntry.pStr->Assign( String::CreateFromInt32( (sal_Int32) nVal ) );
565 						bIgnore = (sal_Bool) nBoolErr;
566 					break;
567 					case EXC_AFTYPE_EMPTY:
568 						aEntry.bQueryByString = sal_False;
569 						aEntry.nVal = SC_EMPTYFIELDS;
570 						aEntry.eOp = SC_EQUAL;
571 					break;
572 					case EXC_AFTYPE_NOTEMPTY:
573 						aEntry.bQueryByString = sal_False;
574 						aEntry.nVal = SC_NONEMPTYFIELDS;
575 						aEntry.eOp = SC_EQUAL;
576 					break;
577 					default:
578                         rStrm.Ignore( 8 );
579 						bIgnore = sal_True;
580 				}
581 
582                 /*  #i39464# conflict, if two conditions of one column are 'OR'ed,
583                     and they follow conditions of other columns.
584                     Example: Let A1 be a condition of column A, and B1 and B2
585                     conditions of column B, connected with OR. Excel performs
586                     'A1 AND (B1 OR B2)' in this case, but Calc would do
587                     '(A1 AND B1) OR B2' instead. */
588                 if( (nFirstEmpty > 1) && nE && (eConn == SC_OR) && !bIgnore )
589 					bHasConflict = sal_True;
590 				if( !bHasConflict && !bIgnore )
591 				{
592 					aEntry.bDoQuery = sal_True;
593 					aEntry.bQueryByString = sal_True;
594 					aEntry.nField = static_cast<SCCOLROW>(StartCol() + static_cast<SCCOL>(nCol));
595 					aEntry.eConnect = nE ? eConn : SC_AND;
596 					nFirstEmpty++;
597 				}
598 			}
599 			else
600                 rStrm.Ignore( 10 );
601 		}
602 
603 		for( nE = 0; nE < 2; nE++ )
604             if( nStrLen[ nE ] && pQueryEntries[ nE ] )
605             {
606                 pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) );
607                 ExcelQueryToOooQuery( *pQueryEntries[ nE ] );
608             }
609 
610 	}
611 }
612 
SetAdvancedRange(const ScRange * pRange)613 void XclImpAutoFilterData::SetAdvancedRange( const ScRange* pRange )
614 {
615     if (pRange)
616     {
617         aCriteriaRange = *pRange;
618         bCriteria = sal_True;
619     }
620     else
621         bCriteria = sal_False;
622 }
623 
SetExtractPos(const ScAddress & rAddr)624 void XclImpAutoFilterData::SetExtractPos( const ScAddress& rAddr )
625 {
626 	aParam.nDestCol = rAddr.Col();
627 	aParam.nDestRow = rAddr.Row();
628 	aParam.nDestTab = rAddr.Tab();
629     aParam.bInplace = sal_False;
630     aParam.bDestPers = sal_True;
631 }
632 
Apply(const sal_Bool bUseUnNamed)633 void XclImpAutoFilterData::Apply( const sal_Bool bUseUnNamed )
634 {
635     CreateScDBData(bUseUnNamed);
636 
637     if( bActive )
638 	{
639         InsertQueryParam();
640 
641         // #i38093# rows hidden by filter need extra flag, but CR_FILTERED is not set here yet
642 //        SCROW nRow1 = StartRow();
643 //        SCROW nRow2 = EndRow();
644 //        size_t nRows = nRow2 - nRow1 + 1;
645 //        boost::scoped_array<sal_uInt8> pFlags( new sal_uInt8[nRows]);
646 //        pExcRoot->pDoc->GetRowFlagsArray( Tab()).FillDataArray( nRow1, nRow2,
647 //                pFlags.get());
648 //        for (size_t j=0; j<nRows; ++j)
649 //        {
650 //            if ((pFlags[j] & CR_HIDDEN) && !(pFlags[j] & CR_FILTERED))
651 //                pExcRoot->pDoc->SetRowFlags( nRow1 + j, Tab(),
652 //                        pFlags[j] | CR_FILTERED );
653 //        }
654 	}
655 }
656 
CreateScDBData(const sal_Bool bUseUnNamed)657 void XclImpAutoFilterData::CreateScDBData( const sal_Bool bUseUnNamed )
658 {
659 
660     // Create the ScDBData() object if the AutoFilter is activated
661     // or if we need to create the Advanced Filter.
662     if( bActive || bCriteria)
663     {
664         ScDBCollection& rColl = pExcRoot->pIR->GetDatabaseRanges();
665         pCurrDBData	= rColl.GetDBAtArea( Tab(), StartCol(), StartRow(), EndCol(), EndRow() );
666         if( !pCurrDBData )
667         {
668             AmendAFName(bUseUnNamed);
669 
670             pCurrDBData = new ScDBData( aFilterName, Tab(), StartCol(), StartRow(), EndCol(), EndRow() );
671 
672             if( pCurrDBData )
673             {
674                 if(bCriteria)
675                 {
676                     EnableRemoveFilter();
677 
678                     pCurrDBData->SetQueryParam( aParam );
679                     pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange);
680                 }
681                 else
682                     pCurrDBData->SetAdvancedQuerySource(NULL);
683                 rColl.Insert( pCurrDBData );
684             }
685         }
686     }
687 
688 }
689 
EnableRemoveFilter()690 void XclImpAutoFilterData::EnableRemoveFilter()
691 {
692     // only if this is a saved Advanced filter
693     if( !bActive && bAutoOrAdvanced )
694     {
695         ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty );
696         aEntry.bDoQuery = sal_True;
697         ++nFirstEmpty;
698     }
699 
700     // TBD: force the automatic activation of the
701     // "Remove Filter" by setting a virtual mouse click
702     // inside the advanced range
703 }
704 
AmendAFName(const sal_Bool bUseUnNamed)705 void XclImpAutoFilterData::AmendAFName(const sal_Bool bUseUnNamed)
706 {
707     // If-and-only-if we have one AF filter then
708     // use the Calc "unnamed" range name. Calc
709     // only supports one in total while Excel
710     // supports one per sheet.
711     if( bUseUnNamed && bAutoOrAdvanced )
712         aFilterName = ScGlobal::GetRscString(STR_DB_NONAME);
713 }
714 
XclImpAutoFilterBuffer()715 XclImpAutoFilterBuffer::XclImpAutoFilterBuffer() :
716     nAFActiveCount( 0 )
717 {
718 }
719 
~XclImpAutoFilterBuffer()720 XclImpAutoFilterBuffer::~XclImpAutoFilterBuffer()
721 {
722 	for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() )
723 		delete pData;
724 }
725 
Insert(RootData * pRoot,const ScRange & rRange,const String & rName)726 void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange,
727 									const String& rName )
728 {
729 	if( !GetByTab( rRange.aStart.Tab() ) )
730 		Append( new XclImpAutoFilterData( pRoot, rRange, rName ) );
731 }
732 
AddAdvancedRange(const ScRange & rRange)733 void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange& rRange )
734 {
735 	XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
736 	if( pData )
737 		pData->SetAdvancedRange( &rRange );
738 }
739 
AddExtractPos(const ScRange & rRange)740 void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange )
741 {
742 	XclImpAutoFilterData* pData = GetByTab( rRange.aStart.Tab() );
743 	if( pData )
744 		pData->SetExtractPos( rRange.aStart );
745 }
746 
Apply()747 void XclImpAutoFilterBuffer::Apply()
748 {
749 	for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() )
750 		pData->Apply(UseUnNamed());
751 }
752 
GetByTab(SCTAB nTab)753 XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab )
754 {
755 	for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() )
756 		if( pData->Tab() == nTab )
757 			return pData;
758 	return NULL;
759 }
760 
761