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