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