Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "excrecds.hxx"
21 :
22 : #include <map>
23 : #include <filter/msfilter/countryid.hxx>
24 :
25 : #include "scitems.hxx"
26 : #include <editeng/eeitem.hxx>
27 :
28 : #include <sfx2/objsh.hxx>
29 :
30 : #include <editeng/editdata.hxx>
31 : #include <editeng/editeng.hxx>
32 : #include <editeng/editobj.hxx>
33 : #include <editeng/editstat.hxx>
34 :
35 : #include <editeng/flditem.hxx>
36 : #include <editeng/flstitem.hxx>
37 :
38 : #include <svx/algitem.hxx>
39 : #include <editeng/boxitem.hxx>
40 : #include <editeng/brushitem.hxx>
41 : #include <svx/pageitem.hxx>
42 : #include <editeng/paperinf.hxx>
43 : #include <editeng/sizeitem.hxx>
44 : #include <editeng/ulspitem.hxx>
45 : #include <editeng/fhgtitem.hxx>
46 : #include <editeng/escapementitem.hxx>
47 : #include <svl/intitem.hxx>
48 : #include <svl/zforlist.hxx>
49 : #include <svl/zformat.hxx>
50 : #include <svtools/ctrltool.hxx>
51 :
52 :
53 : #include <string.h>
54 :
55 : #include "global.hxx"
56 : #include "globstr.hrc"
57 : #include "docpool.hxx"
58 : #include "patattr.hxx"
59 : #include "formulacell.hxx"
60 : #include "document.hxx"
61 : #include "scextopt.hxx"
62 : #include "attrib.hxx"
63 : #include "progress.hxx"
64 : #include "dociter.hxx"
65 : #include "rangenam.hxx"
66 : #include "dbdata.hxx"
67 : #include "stlsheet.hxx"
68 : #include "stlpool.hxx"
69 : #include "editutil.hxx"
70 : #include "formula/errorcodes.hxx"
71 : #include "queryentry.hxx"
72 : #include "queryparam.hxx"
73 :
74 : #include "excdoc.hxx"
75 : #include "xeescher.hxx"
76 : #include "xeformula.hxx"
77 : #include "xelink.hxx"
78 : #include "xename.hxx"
79 : #include "xecontent.hxx"
80 :
81 : #include "xcl97rec.hxx"
82 :
83 : using namespace ::oox;
84 :
85 : using ::com::sun::star::uno::Sequence;
86 :
87 : //--------------------------------------------------------- class ExcDummy_00 -
88 : const sal_uInt8 ExcDummy_00::pMyData[] = {
89 : 0x5c, 0x00, 0x20, 0x00, 0x04, 'C', 'a', 'l', 'c', // WRITEACCESS
90 : 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
91 : 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
92 : 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
93 : };
94 : const sal_Size ExcDummy_00::nMyLen = sizeof( ExcDummy_00::pMyData );
95 :
96 : //-------------------------------------------------------- class ExcDummy_04x -
97 : const sal_uInt8 ExcDummy_040::pMyData[] = {
98 : 0x40, 0x00, 0x02, 0x00, 0x00, 0x00, // BACKUP
99 : 0x8d, 0x00, 0x02, 0x00, 0x00, 0x00, // HIDEOBJ
100 : };
101 : const sal_Size ExcDummy_040::nMyLen = sizeof( ExcDummy_040::pMyData );
102 :
103 : const sal_uInt8 ExcDummy_041::pMyData[] = {
104 : 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, // PRECISION
105 : 0xda, 0x00, 0x02, 0x00, 0x00, 0x00 // BOOKBOOL
106 : };
107 : const sal_Size ExcDummy_041::nMyLen = sizeof( ExcDummy_041::pMyData );
108 :
109 : //-------------------------------------------------------- class ExcDummy_02a -
110 : const sal_uInt8 ExcDummy_02a::pMyData[] = {
111 : 0x0d, 0x00, 0x02, 0x00, 0x01, 0x00, // CALCMODE
112 : 0x0c, 0x00, 0x02, 0x00, 0x64, 0x00, // CALCCOUNT
113 : 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00, // REFMODE
114 : 0x11, 0x00, 0x02, 0x00, 0x00, 0x00, // ITERATION
115 : 0x10, 0x00, 0x08, 0x00, 0xfc, 0xa9, 0xf1, 0xd2, 0x4d, // DELTA
116 : 0x62, 0x50, 0x3f,
117 : 0x5f, 0x00, 0x02, 0x00, 0x01, 0x00 // SAVERECALC
118 : };
119 : const sal_Size ExcDummy_02a::nMyLen = sizeof( ExcDummy_02a::pMyData );
120 :
121 : //----------------------------------------------------------- class ExcRecord -
122 :
123 42 : void ExcRecord::Save( XclExpStream& rStrm )
124 : {
125 42 : SetRecHeader( GetNum(), GetLen() );
126 42 : XclExpRecord::Save( rStrm );
127 42 : }
128 :
129 8 : void ExcRecord::SaveCont( XclExpStream& /*rStrm*/ )
130 : {
131 8 : }
132 :
133 42 : void ExcRecord::WriteBody( XclExpStream& rStrm )
134 : {
135 42 : SaveCont( rStrm );
136 42 : }
137 :
138 30 : void ExcRecord::SaveXml( XclExpXmlStream& /*rStrm*/ )
139 : {
140 30 : }
141 :
142 :
143 : //--------------------------------------------------------- class ExcEmptyRec -
144 :
145 0 : void ExcEmptyRec::Save( XclExpStream& /*rStrm*/ )
146 : {
147 0 : }
148 :
149 :
150 0 : sal_uInt16 ExcEmptyRec::GetNum() const
151 : {
152 0 : return 0;
153 : }
154 :
155 :
156 0 : sal_Size ExcEmptyRec::GetLen() const
157 : {
158 0 : return 0;
159 : }
160 :
161 : //--------------------------------------------------------- class ExcDummyRec -
162 :
163 0 : void ExcDummyRec::Save( XclExpStream& rStrm )
164 : {
165 0 : rStrm.Write( GetData(), GetLen() ); // raw write mode
166 0 : }
167 :
168 :
169 0 : sal_uInt16 ExcDummyRec::GetNum( void ) const
170 : {
171 0 : return 0x0000;
172 : }
173 :
174 : //------------------------------------------------------- class ExcBoolRecord -
175 :
176 3 : void ExcBoolRecord::SaveCont( XclExpStream& rStrm )
177 : {
178 3 : rStrm << (sal_uInt16)(bVal ? 0x0001 : 0x0000);
179 3 : }
180 :
181 :
182 3 : sal_Size ExcBoolRecord::GetLen( void ) const
183 : {
184 3 : return 2;
185 : }
186 :
187 :
188 :
189 :
190 : //--------------------------------------------------------- class ExcBof_Base -
191 :
192 23 : ExcBof_Base::ExcBof_Base() :
193 : nRupBuild( 0x096C ), // copied from Excel
194 23 : nRupYear( 0x07C9 ) // copied from Excel
195 : {
196 23 : }
197 :
198 :
199 :
200 : //-------------------------------------------------------------- class ExcBof -
201 :
202 0 : ExcBof::ExcBof( void )
203 : {
204 0 : nDocType = 0x0010;
205 0 : nVers = 0x0500;
206 0 : }
207 :
208 :
209 0 : void ExcBof::SaveCont( XclExpStream& rStrm )
210 : {
211 0 : rStrm << nVers << nDocType << nRupBuild << nRupYear;
212 0 : }
213 :
214 :
215 0 : sal_uInt16 ExcBof::GetNum( void ) const
216 : {
217 0 : return 0x0809;
218 : }
219 :
220 :
221 0 : sal_Size ExcBof::GetLen( void ) const
222 : {
223 0 : return 8;
224 : }
225 :
226 :
227 :
228 : //------------------------------------------------------------- class ExcBofW -
229 :
230 0 : ExcBofW::ExcBofW( void )
231 : {
232 0 : nDocType = 0x0005;
233 0 : nVers = 0x0500;
234 0 : }
235 :
236 :
237 0 : void ExcBofW::SaveCont( XclExpStream& rStrm )
238 : {
239 0 : rStrm << nVers << nDocType << nRupBuild << nRupYear;
240 0 : }
241 :
242 :
243 :
244 0 : sal_uInt16 ExcBofW::GetNum( void ) const
245 : {
246 0 : return 0x0809;
247 : }
248 :
249 :
250 :
251 0 : sal_Size ExcBofW::GetLen( void ) const
252 : {
253 0 : return 8;
254 : }
255 :
256 :
257 :
258 : //-------------------------------------------------------------- class ExcEof -
259 :
260 8 : sal_uInt16 ExcEof::GetNum( void ) const
261 : {
262 8 : return 0x000A;
263 : }
264 :
265 :
266 8 : sal_Size ExcEof::GetLen( void ) const
267 : {
268 8 : return 0;
269 : }
270 :
271 :
272 :
273 : //--------------------------------------------------------- class ExcDummy_00 -
274 :
275 0 : sal_Size ExcDummy_00::GetLen( void ) const
276 : {
277 0 : return nMyLen;
278 : }
279 :
280 :
281 0 : const sal_uInt8* ExcDummy_00::GetData( void ) const
282 : {
283 0 : return pMyData;
284 : }
285 :
286 :
287 :
288 : //-------------------------------------------------------- class ExcDummy_04x -
289 :
290 0 : sal_Size ExcDummy_040::GetLen( void ) const
291 : {
292 0 : return nMyLen;
293 : }
294 :
295 :
296 0 : const sal_uInt8* ExcDummy_040::GetData( void ) const
297 : {
298 0 : return pMyData;
299 : }
300 :
301 :
302 :
303 :
304 0 : sal_Size ExcDummy_041::GetLen( void ) const
305 : {
306 0 : return nMyLen;
307 : }
308 :
309 :
310 0 : const sal_uInt8* ExcDummy_041::GetData( void ) const
311 : {
312 0 : return pMyData;
313 : }
314 :
315 :
316 :
317 : //------------------------------------------------------------- class Exc1904 -
318 :
319 9 : Exc1904::Exc1904( ScDocument& rDoc )
320 : {
321 9 : Date* pDate = rDoc.GetFormatTable()->GetNullDate();
322 9 : bVal = pDate ? (*pDate == Date( 1, 1, 1904 )) : false;
323 9 : bDateCompatibility = pDate ? !( *pDate == Date( 30, 12, 1899 )) : false;
324 9 : }
325 :
326 :
327 3 : sal_uInt16 Exc1904::GetNum( void ) const
328 : {
329 3 : return 0x0022;
330 : }
331 :
332 :
333 6 : void Exc1904::SaveXml( XclExpXmlStream& rStrm )
334 : {
335 6 : bool bISOIEC = ( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 );
336 :
337 6 : if( bISOIEC )
338 : {
339 : rStrm.WriteAttributes(
340 : XML_dateCompatibility, XclXmlUtils::ToPsz( bDateCompatibility ),
341 2 : FSEND );
342 : }
343 :
344 6 : if( !bISOIEC || bDateCompatibility )
345 : {
346 : rStrm.WriteAttributes(
347 : XML_date1904, XclXmlUtils::ToPsz( bVal ),
348 4 : FSEND );
349 : }
350 6 : }
351 :
352 :
353 :
354 : //------------------------------------------------------ class ExcBundlesheet -
355 :
356 14 : ExcBundlesheetBase::ExcBundlesheetBase( RootData& rRootData, SCTAB nTabNum ) :
357 : nStrPos( STREAM_SEEK_TO_END ),
358 : nOwnPos( STREAM_SEEK_TO_END ),
359 14 : nGrbit( rRootData.pER->GetTabInfo().IsVisibleTab( nTabNum ) ? 0x0000 : 0x0001 ),
360 28 : nTab( nTabNum )
361 : {
362 14 : }
363 :
364 :
365 0 : ExcBundlesheetBase::ExcBundlesheetBase() :
366 : nStrPos( STREAM_SEEK_TO_END ),
367 : nOwnPos( STREAM_SEEK_TO_END ),
368 : nGrbit( 0x0000 ),
369 0 : nTab( SCTAB_GLOBAL )
370 : {
371 0 : }
372 :
373 :
374 5 : void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
375 : {
376 5 : rStrm.SetSvStreamPos( nOwnPos );
377 5 : rStrm.DisableEncryption();
378 5 : rStrm << static_cast<sal_uInt32>(nStrPos);
379 5 : rStrm.EnableEncryption();
380 5 : }
381 :
382 :
383 5 : sal_uInt16 ExcBundlesheetBase::GetNum( void ) const
384 : {
385 5 : return 0x0085;
386 : }
387 :
388 :
389 :
390 :
391 0 : ExcBundlesheet::ExcBundlesheet( RootData& rRootData, SCTAB _nTab ) :
392 0 : ExcBundlesheetBase( rRootData, _nTab )
393 : {
394 0 : OUString sTabName = rRootData.pER->GetTabInfo().GetScTabName( _nTab );
395 : OSL_ENSURE( sTabName.getLength() < 256, "ExcBundlesheet::ExcBundlesheet - table name too long" );
396 0 : aName = OUStringToOString(sTabName, rRootData.pER->GetTextEncoding());
397 0 : }
398 :
399 :
400 0 : void ExcBundlesheet::SaveCont( XclExpStream& rStrm )
401 : {
402 0 : nOwnPos = rStrm.GetSvStreamPos();
403 0 : rStrm << (sal_uInt32) 0x00000000 // dummy (stream position of the sheet)
404 0 : << nGrbit;
405 0 : rStrm.WriteByteString(aName); // 8 bit length, max 255 chars
406 0 : }
407 :
408 :
409 0 : sal_Size ExcBundlesheet::GetLen() const
410 : {
411 0 : return 7 + std::min( aName.getLength(), (sal_Int32) 255 );
412 : }
413 :
414 :
415 : //--------------------------------------------------------- class ExcDummy_02 -
416 :
417 0 : sal_Size ExcDummy_02a::GetLen( void ) const
418 : {
419 0 : return nMyLen;
420 : }
421 :
422 0 : const sal_uInt8* ExcDummy_02a::GetData( void ) const
423 : {
424 0 : return pMyData;
425 : }
426 : //--------------------------------------------------------- class ExcDummy_02 -
427 :
428 9 : XclExpCountry::XclExpCountry( const XclExpRoot& rRoot ) :
429 9 : XclExpRecord( EXC_ID_COUNTRY, 4 )
430 : {
431 : /* #i31530# set document country as UI country too -
432 : needed for correct behaviour of number formats. */
433 : mnUICountry = mnDocCountry = static_cast< sal_uInt16 >(
434 9 : ::msfilter::ConvertLanguageToCountry( rRoot.GetDocLanguage() ) );
435 9 : }
436 :
437 3 : void XclExpCountry::WriteBody( XclExpStream& rStrm )
438 : {
439 3 : rStrm << mnUICountry << mnDocCountry;
440 3 : }
441 :
442 : // XclExpWsbool ===============================================================
443 :
444 14 : XclExpWsbool::XclExpWsbool( bool bFitToPages, SCTAB nScTab, XclExpFilterManager* pManager )
445 : : XclExpUInt16Record( EXC_ID_WSBOOL, EXC_WSBOOL_DEFAULTFLAGS )
446 : , mnScTab( nScTab )
447 14 : , mpManager( pManager )
448 : {
449 14 : if( bFitToPages )
450 0 : SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE );
451 14 : }
452 :
453 9 : void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm )
454 : {
455 9 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
456 : rWorksheet->startElement( XML_sheetPr,
457 : // OOXTODO: XML_syncHorizontal,
458 : // OOXTODO: XML_syncVertical,
459 : // OOXTODO: XML_syncRef,
460 : // OOXTODO: XML_transitionEvaluation,
461 : // OOXTODO: XML_transitionEntry,
462 : // OOXTODO: XML_published,
463 : // OOXTODO: XML_codeName,
464 9 : XML_filterMode, mpManager ? XclXmlUtils::ToPsz( mpManager->HasFilterMode( mnScTab ) ) : NULL,
465 : // OOXTODO: XML_enableFormatConditionsCalculation,
466 18 : FSEND );
467 : // OOXTODO: elements XML_tabColor, XML_outlinePr
468 : rWorksheet->singleElement( XML_pageSetUpPr,
469 : // OOXTODO: XML_autoPageBreaks,
470 9 : XML_fitToPage, XclXmlUtils::ToPsz( GetValue() & EXC_WSBOOL_FITTOPAGE ),
471 9 : FSEND );
472 9 : rWorksheet->endElement( XML_sheetPr );
473 9 : }
474 :
475 :
476 : // XclExpWindowProtection ===============================================================
477 :
478 0 : XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
479 0 : XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
480 : {
481 0 : }
482 :
483 0 : void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm )
484 : {
485 : rStrm.WriteAttributes(
486 0 : XML_lockWindows, XclXmlUtils::ToPsz( GetBool() ),
487 0 : FSEND );
488 0 : }
489 :
490 : // XclExpDocProtection ===============================================================
491 :
492 0 : XclExpProtection::XclExpProtection(bool bValue) :
493 0 : XclExpBoolRecord(EXC_ID_PROTECT, bValue)
494 : {
495 0 : }
496 :
497 : // ============================================================================
498 :
499 0 : XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
500 : XclExpRecord(EXC_ID_PASSWORD, 2),
501 0 : mnHash(0x0000)
502 : {
503 0 : if (aHash.getLength() >= 2)
504 : {
505 0 : mnHash = ((aHash[0] << 8) & 0xFFFF);
506 0 : mnHash |= (aHash[1] & 0xFF);
507 : }
508 0 : }
509 :
510 0 : XclExpPassHash::~XclExpPassHash()
511 : {
512 0 : }
513 :
514 0 : void XclExpPassHash::WriteBody(XclExpStream& rStrm)
515 : {
516 0 : rStrm << mnHash;
517 0 : }
518 :
519 : // ============================================================================
520 :
521 0 : XclExpFiltermode::XclExpFiltermode() :
522 0 : XclExpEmptyRecord( EXC_ID_FILTERMODE )
523 : {
524 0 : }
525 :
526 : // ----------------------------------------------------------------------------
527 :
528 0 : XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress& rStartPos, SCCOL nScCol ) :
529 : XclExpUInt16Record( EXC_ID_AUTOFILTERINFO, static_cast< sal_uInt16 >( nScCol ) ),
530 0 : maStartPos( rStartPos )
531 : {
532 0 : }
533 :
534 : // ----------------------------------------------------------------------------
535 :
536 0 : ExcFilterCondition::ExcFilterCondition() :
537 : nType( EXC_AFTYPE_NOTUSED ),
538 : nOper( EXC_AFOPER_EQUAL ),
539 : fVal( 0.0 ),
540 0 : pText( NULL )
541 : {
542 0 : }
543 :
544 0 : ExcFilterCondition::~ExcFilterCondition()
545 : {
546 0 : if( pText )
547 0 : delete pText;
548 0 : }
549 :
550 0 : sal_Size ExcFilterCondition::GetTextBytes() const
551 : {
552 0 : return pText ? (1 + pText->GetBufferSize()) : 0;
553 : }
554 :
555 0 : void ExcFilterCondition::SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, double fV, OUString* pT )
556 : {
557 0 : nType = nTp;
558 0 : nOper = nOp;
559 0 : fVal = fV;
560 :
561 0 : delete pText;
562 0 : (pT) ? pText = new XclExpString( *pT, EXC_STR_8BITLENGTH ) : pText = NULL;
563 0 : }
564 :
565 0 : void ExcFilterCondition::Save( XclExpStream& rStrm )
566 : {
567 0 : rStrm << nType << nOper;
568 0 : switch( nType )
569 : {
570 : case EXC_AFTYPE_DOUBLE:
571 0 : rStrm << fVal;
572 0 : break;
573 : case EXC_AFTYPE_STRING:
574 : OSL_ENSURE( pText, "ExcFilterCondition::Save() -- pText is NULL!" );
575 0 : rStrm << (sal_uInt32)0 << (sal_uInt8) pText->Len() << (sal_uInt16)0 << (sal_uInt8)0;
576 0 : break;
577 : case EXC_AFTYPE_BOOLERR:
578 0 : rStrm << (sal_uInt8)0 << (sal_uInt8)((fVal != 0) ? 1 : 0) << (sal_uInt32)0 << (sal_uInt16)0;
579 0 : break;
580 : default:
581 0 : rStrm << (sal_uInt32)0 << (sal_uInt32)0;
582 : }
583 0 : }
584 :
585 0 : static const char* lcl_GetOperator( sal_uInt8 nOper )
586 : {
587 0 : switch( nOper )
588 : {
589 0 : case EXC_AFOPER_EQUAL: return "equal";
590 0 : case EXC_AFOPER_GREATER: return "greaterThan";
591 0 : case EXC_AFOPER_GREATEREQUAL: return "greaterThanOrEqual";
592 0 : case EXC_AFOPER_LESS: return "lessThan";
593 0 : case EXC_AFOPER_LESSEQUAL: return "lessThanOrEqual";
594 0 : case EXC_AFOPER_NOTEQUAL: return "notEqual";
595 : case EXC_AFOPER_NONE:
596 0 : default: return "**none**";
597 : }
598 : }
599 :
600 0 : static OString lcl_GetValue( sal_uInt8 nType, double fVal, XclExpString* pStr )
601 : {
602 0 : switch( nType )
603 : {
604 0 : case EXC_AFTYPE_STRING: return XclXmlUtils::ToOString( *pStr );
605 0 : case EXC_AFTYPE_DOUBLE: return OString::valueOf( fVal );
606 0 : case EXC_AFTYPE_BOOLERR: return OString::valueOf( (sal_Int32) ( fVal != 0 ? 1 : 0 ) );
607 0 : default: return OString();
608 : }
609 : }
610 :
611 0 : void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm )
612 : {
613 0 : if( IsEmpty() )
614 0 : return;
615 :
616 0 : rStrm.GetCurrentStream()->singleElement( XML_customFilter,
617 : XML_operator, lcl_GetOperator( nOper ),
618 : XML_val, lcl_GetValue( nType, fVal, pText ).getStr(),
619 0 : FSEND );
620 : }
621 :
622 0 : void ExcFilterCondition::SaveText( XclExpStream& rStrm )
623 : {
624 0 : if( nType == EXC_AFTYPE_STRING )
625 : {
626 : OSL_ENSURE( pText, "ExcFilterCondition::SaveText() -- pText is NULL!" );
627 0 : pText->WriteFlagField( rStrm );
628 0 : pText->WriteBuffer( rStrm );
629 : }
630 0 : }
631 :
632 : // ----------------------------------------------------------------------------
633 :
634 0 : XclExpAutofilter::XclExpAutofilter( const XclExpRoot& rRoot, sal_uInt16 nC ) :
635 : XclExpRecord( EXC_ID_AUTOFILTER, 24 ),
636 : XclExpRoot( rRoot ),
637 : meType(FilterCondition),
638 : nCol( nC ),
639 0 : nFlags( 0 )
640 : {
641 0 : }
642 :
643 0 : bool XclExpAutofilter::AddCondition( ScQueryConnect eConn, sal_uInt8 nType, sal_uInt8 nOp,
644 : double fVal, OUString* pText, bool bSimple )
645 : {
646 0 : if( !aCond[ 1 ].IsEmpty() )
647 0 : return false;
648 :
649 0 : sal_uInt16 nInd = aCond[ 0 ].IsEmpty() ? 0 : 1;
650 :
651 0 : if( nInd == 1 )
652 0 : nFlags |= (eConn == SC_OR) ? EXC_AFFLAG_OR : EXC_AFFLAG_AND;
653 0 : if( bSimple )
654 0 : nFlags |= (nInd == 0) ? EXC_AFFLAG_SIMPLE1 : EXC_AFFLAG_SIMPLE2;
655 :
656 0 : aCond[ nInd ].SetCondition( nType, nOp, fVal, pText );
657 :
658 0 : AddRecSize( aCond[ nInd ].GetTextBytes() );
659 :
660 0 : return true;
661 : }
662 :
663 0 : bool XclExpAutofilter::HasCondition() const
664 : {
665 0 : return !aCond[0].IsEmpty();
666 : }
667 :
668 0 : bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
669 : {
670 0 : const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
671 0 : if (rItems.empty())
672 0 : return true;
673 :
674 0 : if (GetOutput() != EXC_OUTPUT_BINARY && rItems.size() > 1)
675 0 : return AddMultiValueEntry(rEntry);
676 :
677 0 : bool bConflict = false;
678 0 : OUString sText;
679 0 : const ScQueryEntry::Item& rItem = rItems[0];
680 0 : const OUString& rQueryStr = rItem.maString;
681 0 : if (!rQueryStr.isEmpty())
682 : {
683 0 : sText = rQueryStr;
684 0 : switch( rEntry.eOp )
685 : {
686 : case SC_CONTAINS:
687 : case SC_DOES_NOT_CONTAIN:
688 : {
689 0 : sText = "*" + sText + "*";
690 : }
691 0 : break;
692 : case SC_BEGINS_WITH:
693 : case SC_DOES_NOT_BEGIN_WITH:
694 0 : sText += "*";
695 0 : break;
696 : case SC_ENDS_WITH:
697 : case SC_DOES_NOT_END_WITH:
698 0 : sText = "*" + sText;
699 0 : break;
700 : default:
701 : {
702 : //nothing
703 : }
704 : }
705 : }
706 :
707 0 : bool bLen = sText.getLength() > 0;
708 :
709 : // empty/nonempty fields
710 0 : if (rEntry.IsQueryByEmpty())
711 0 : bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, 0.0, NULL, true );
712 0 : else if(rEntry.IsQueryByNonEmpty())
713 0 : bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, 0.0, NULL, true );
714 : // other conditions
715 : else
716 : {
717 0 : double fVal = 0.0;
718 0 : sal_uInt32 nIndex = 0;
719 0 : bool bIsNum = bLen ? GetFormatter().IsNumberFormat( sText, nIndex, fVal ) : true;
720 : OUString* pText;
721 0 : (bIsNum) ? pText = NULL : pText = &sText;
722 :
723 : // top10 flags
724 0 : sal_uInt16 nNewFlags = 0x0000;
725 0 : switch( rEntry.eOp )
726 : {
727 : case SC_TOPVAL:
728 0 : nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
729 0 : break;
730 : case SC_BOTVAL:
731 0 : nNewFlags = EXC_AFFLAG_TOP10;
732 0 : break;
733 : case SC_TOPPERC:
734 0 : nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP | EXC_AFFLAG_TOP10PERC);
735 0 : break;
736 : case SC_BOTPERC:
737 0 : nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10PERC);
738 0 : break;
739 : default:;
740 : }
741 0 : bool bNewTop10 = ::get_flag( nNewFlags, EXC_AFFLAG_TOP10 );
742 :
743 0 : bConflict = HasTop10() && bNewTop10;
744 0 : if( !bConflict )
745 : {
746 0 : if( bNewTop10 )
747 : {
748 0 : if( fVal < 0 ) fVal = 0;
749 0 : if( fVal >= 501 ) fVal = 500;
750 0 : nFlags |= (nNewFlags | (sal_uInt16)(fVal) << 7);
751 : }
752 : // normal condition
753 : else
754 : {
755 0 : sal_uInt8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
756 0 : sal_uInt8 nOper = EXC_AFOPER_NONE;
757 :
758 0 : switch( rEntry.eOp )
759 : {
760 0 : case SC_EQUAL: nOper = EXC_AFOPER_EQUAL; break;
761 0 : case SC_LESS: nOper = EXC_AFOPER_LESS; break;
762 0 : case SC_GREATER: nOper = EXC_AFOPER_GREATER; break;
763 0 : case SC_LESS_EQUAL: nOper = EXC_AFOPER_LESSEQUAL; break;
764 0 : case SC_GREATER_EQUAL: nOper = EXC_AFOPER_GREATEREQUAL; break;
765 0 : case SC_NOT_EQUAL: nOper = EXC_AFOPER_NOTEQUAL; break;
766 : case SC_CONTAINS:
767 : case SC_BEGINS_WITH:
768 : case SC_ENDS_WITH:
769 0 : nOper = EXC_AFOPER_EQUAL; break;
770 : case SC_DOES_NOT_CONTAIN:
771 : case SC_DOES_NOT_BEGIN_WITH:
772 : case SC_DOES_NOT_END_WITH:
773 0 : nOper = EXC_AFOPER_NOTEQUAL; break;
774 : default:;
775 : }
776 0 : bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
777 : }
778 : }
779 : }
780 0 : return bConflict;
781 : }
782 :
783 0 : bool XclExpAutofilter::AddMultiValueEntry( const ScQueryEntry& rEntry )
784 : {
785 0 : meType = MultiValue;
786 0 : const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
787 0 : ScQueryEntry::QueryItemsType::const_iterator itr = rItems.begin(), itrEnd = rItems.end();
788 0 : for (; itr != itrEnd; ++itr)
789 0 : maMultiValues.push_back(itr->maString);
790 :
791 0 : return false;
792 : }
793 :
794 0 : void XclExpAutofilter::WriteBody( XclExpStream& rStrm )
795 : {
796 0 : rStrm << nCol << nFlags;
797 0 : aCond[ 0 ].Save( rStrm );
798 0 : aCond[ 1 ].Save( rStrm );
799 0 : aCond[ 0 ].SaveText( rStrm );
800 0 : aCond[ 1 ].SaveText( rStrm );
801 0 : }
802 :
803 0 : void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm )
804 : {
805 0 : if (meType == FilterCondition && !HasCondition())
806 0 : return;
807 :
808 0 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
809 :
810 : rWorksheet->startElement( XML_filterColumn,
811 : XML_colId, OString::valueOf( (sal_Int32) nCol ).getStr(),
812 : // OOXTODO: XML_hiddenButton, AutoFilter12 fHideArrow?
813 : // OOXTODO: XML_showButton,
814 0 : FSEND );
815 :
816 0 : switch (meType)
817 : {
818 : case FilterCondition:
819 : {
820 0 : if( HasTop10() )
821 : {
822 : rWorksheet->singleElement( XML_top10,
823 0 : XML_top, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10TOP ) ),
824 0 : XML_percent, XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10PERC ) ),
825 0 : XML_val, OString::valueOf( (sal_Int32) (nFlags >> 7 ) ).getStr(),
826 : // OOXTODO: XML_filterVal,
827 0 : FSEND );
828 : }
829 :
830 : rWorksheet->startElement( XML_customFilters,
831 0 : XML_and, XclXmlUtils::ToPsz( (nFlags & EXC_AFFLAG_ANDORMASK) == EXC_AFFLAG_AND ),
832 0 : FSEND );
833 0 : aCond[ 0 ].SaveXml( rStrm );
834 0 : aCond[ 1 ].SaveXml( rStrm );
835 0 : rWorksheet->endElement( XML_customFilters );
836 : // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
837 : // XML_extLst, XML_filters, XML_iconFilter, XML_top10
838 : }
839 0 : break;
840 : case MultiValue:
841 : {
842 0 : rWorksheet->startElement(XML_filters, FSEND);
843 0 : std::vector<OUString>::const_iterator itr = maMultiValues.begin(), itrEnd = maMultiValues.end();
844 0 : for (; itr != itrEnd; ++itr)
845 : {
846 0 : const char* pz = OUStringToOString(*itr, RTL_TEXTENCODING_UTF8).getStr();
847 0 : rWorksheet->singleElement(XML_filter, XML_val, pz, FSEND);
848 : }
849 0 : rWorksheet->endElement(XML_filters);
850 : }
851 0 : break;
852 : }
853 0 : rWorksheet->endElement( XML_filterColumn );
854 : }
855 :
856 : // ----------------------------------------------------------------------------
857 :
858 14 : ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab ) :
859 : XclExpRoot( rRoot ),
860 : pFilterMode( NULL ),
861 : pFilterInfo( NULL )
862 14 : , mbAutoFilter (false)
863 : {
864 14 : XclExpNameManager& rNameMgr = GetNameManager();
865 :
866 14 : sal_Bool bFound = false;
867 14 : sal_Bool bAdvanced = false;
868 14 : ScDBData* pData = rRoot.GetDoc().GetAnonymousDBData(nTab);
869 14 : ScRange aAdvRange;
870 14 : if (pData)
871 : {
872 0 : bAdvanced = pData->GetAdvancedQuerySource( aAdvRange );
873 0 : bFound = (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced);
874 : }
875 14 : if( bFound )
876 : {
877 0 : ScQueryParam aParam;
878 0 : pData->GetQueryParam( aParam );
879 :
880 : ScRange aRange( aParam.nCol1, aParam.nRow1, aParam.nTab,
881 0 : aParam.nCol2, aParam.nRow2, aParam.nTab );
882 0 : SCCOL nColCnt = aParam.nCol2 - aParam.nCol1 + 1;
883 :
884 0 : maRef = aRange;
885 :
886 : // #i2394# built-in defined names must be sorted by containing sheet name
887 0 : rNameMgr.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE, aRange );
888 :
889 : // advanced filter
890 0 : if( bAdvanced )
891 : {
892 : // filter criteria, excel allows only same table
893 0 : if( aAdvRange.aStart.Tab() == nTab )
894 0 : rNameMgr.InsertBuiltInName( EXC_BUILTIN_CRITERIA, aAdvRange );
895 :
896 : // filter destination range, excel allows only same table
897 0 : if( !aParam.bInplace )
898 : {
899 0 : ScRange aDestRange( aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
900 0 : aDestRange.aEnd.IncCol( nColCnt - 1 );
901 0 : if( aDestRange.aStart.Tab() == nTab )
902 0 : rNameMgr.InsertBuiltInName( EXC_BUILTIN_EXTRACT, aDestRange );
903 : }
904 :
905 0 : pFilterMode = new XclExpFiltermode;
906 : }
907 : // AutoFilter
908 : else
909 : {
910 0 : sal_Bool bConflict = false;
911 0 : sal_Bool bContLoop = sal_True;
912 0 : sal_Bool bHasOr = false;
913 0 : SCCOLROW nFirstField = aParam.GetEntry( 0 ).nField;
914 :
915 : // create AUTOFILTER records for filtered columns
916 0 : for( SCSIZE nEntry = 0; !bConflict && bContLoop && (nEntry < aParam.GetEntryCount()); nEntry++ )
917 : {
918 0 : const ScQueryEntry& rEntry = aParam.GetEntry( nEntry );
919 :
920 0 : bContLoop = rEntry.bDoQuery;
921 0 : if( bContLoop )
922 : {
923 0 : XclExpAutofilter* pFilter = GetByCol( static_cast<SCCOL>(rEntry.nField) - aRange.aStart.Col() );
924 :
925 0 : if( nEntry > 0 )
926 0 : bHasOr |= (rEntry.eConnect == SC_OR);
927 :
928 0 : bConflict = (nEntry > 1) && bHasOr;
929 0 : if( !bConflict )
930 0 : bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
931 0 : (nFirstField != rEntry.nField);
932 0 : if( !bConflict )
933 0 : bConflict = pFilter->AddEntry( rEntry );
934 : }
935 : }
936 :
937 : // additional tests for conflicts
938 0 : for( size_t nPos = 0, nSize = maFilterList.GetSize(); !bConflict && (nPos < nSize); ++nPos )
939 : {
940 0 : XclExpAutofilterRef xFilter = maFilterList.GetRecord( nPos );
941 0 : bConflict = xFilter->HasCondition() && xFilter->HasTop10();
942 0 : }
943 :
944 0 : if( bConflict )
945 0 : maFilterList.RemoveAllRecords();
946 :
947 0 : if( !maFilterList.IsEmpty() )
948 0 : pFilterMode = new XclExpFiltermode;
949 0 : pFilterInfo = new XclExpAutofilterinfo( aRange.aStart, nColCnt );
950 :
951 0 : if (maFilterList.IsEmpty () && !bConflict)
952 0 : mbAutoFilter = true;
953 0 : }
954 : }
955 14 : }
956 :
957 42 : ExcAutoFilterRecs::~ExcAutoFilterRecs()
958 : {
959 14 : delete pFilterMode;
960 14 : delete pFilterInfo;
961 28 : }
962 :
963 0 : XclExpAutofilter* ExcAutoFilterRecs::GetByCol( SCCOL nCol )
964 : {
965 0 : XclExpAutofilterRef xFilter;
966 0 : for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
967 : {
968 0 : xFilter = maFilterList.GetRecord( nPos );
969 0 : if( xFilter->GetCol() == static_cast<sal_uInt16>(nCol) )
970 0 : return xFilter.get();
971 : }
972 0 : xFilter.reset( new XclExpAutofilter( GetRoot(), static_cast<sal_uInt16>(nCol) ) );
973 0 : maFilterList.AppendRecord( xFilter );
974 0 : return xFilter.get();
975 : }
976 :
977 0 : bool ExcAutoFilterRecs::IsFiltered( SCCOL nCol )
978 : {
979 0 : for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
980 0 : if( maFilterList.GetRecord( nPos )->GetCol() == static_cast<sal_uInt16>(nCol) )
981 0 : return true;
982 0 : return false;
983 : }
984 :
985 14 : void ExcAutoFilterRecs::AddObjRecs()
986 : {
987 14 : if( pFilterInfo )
988 : {
989 0 : ScAddress aAddr( pFilterInfo->GetStartPos() );
990 0 : for( SCCOL nObj = 0, nCount = pFilterInfo->GetColCount(); nObj < nCount; nObj++ )
991 : {
992 0 : XclObj* pObjRec = new XclObjDropDown( GetObjectManager(), aAddr, IsFiltered( nObj ) );
993 0 : GetObjectManager().AddObj( pObjRec );
994 0 : aAddr.IncCol( 1 );
995 : }
996 : }
997 14 : }
998 :
999 5 : void ExcAutoFilterRecs::Save( XclExpStream& rStrm )
1000 : {
1001 5 : if( pFilterMode )
1002 0 : pFilterMode->Save( rStrm );
1003 5 : if( pFilterInfo )
1004 0 : pFilterInfo->Save( rStrm );
1005 5 : maFilterList.Save( rStrm );
1006 5 : }
1007 :
1008 9 : void ExcAutoFilterRecs::SaveXml( XclExpXmlStream& rStrm )
1009 : {
1010 9 : if( maFilterList.IsEmpty() && !mbAutoFilter )
1011 18 : return;
1012 :
1013 0 : sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1014 : rWorksheet->startElement( XML_autoFilter,
1015 : XML_ref, XclXmlUtils::ToOString( maRef ).getStr(),
1016 0 : FSEND );
1017 : // OOXTODO: XML_extLst, XML_sortState
1018 0 : if( !maFilterList.IsEmpty() )
1019 0 : maFilterList.SaveXml( rStrm );
1020 0 : rWorksheet->endElement( XML_autoFilter );
1021 : }
1022 :
1023 9 : bool ExcAutoFilterRecs::HasFilterMode() const
1024 : {
1025 9 : return pFilterMode != NULL;
1026 : }
1027 :
1028 : // ----------------------------------------------------------------------------
1029 :
1030 9 : XclExpFilterManager::XclExpFilterManager( const XclExpRoot& rRoot ) :
1031 9 : XclExpRoot( rRoot )
1032 : {
1033 9 : }
1034 :
1035 14 : void XclExpFilterManager::InitTabFilter( SCTAB nScTab )
1036 : {
1037 14 : maFilterMap[ nScTab ].reset( new ExcAutoFilterRecs( GetRoot(), nScTab ) );
1038 14 : }
1039 :
1040 14 : XclExpRecordRef XclExpFilterManager::CreateRecord( SCTAB nScTab )
1041 : {
1042 14 : XclExpTabFilterRef xRec;
1043 14 : XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1044 14 : if( aIt != maFilterMap.end() )
1045 : {
1046 14 : xRec = aIt->second;
1047 14 : xRec->AddObjRecs();
1048 : }
1049 14 : return xRec;
1050 : }
1051 :
1052 9 : bool XclExpFilterManager::HasFilterMode( SCTAB nScTab )
1053 : {
1054 9 : XclExpTabFilterRef xRec;
1055 9 : XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
1056 9 : if( aIt != maFilterMap.end() )
1057 : {
1058 9 : return aIt->second->HasFilterMode();
1059 : }
1060 0 : return false;
1061 15 : }
1062 :
1063 : // ============================================================================
1064 :
1065 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|