xref: /AOO41X/main/sc/source/filter/excel/excimp8.cxx (revision 237246f4e9274dc3348d040b1214b9170d5f8c05)
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_sc.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