1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "excrecds.hxx"
23 #include <filter/msfilter/countryid.hxx>
25 #include "scitems.hxx"
26 #include <editeng/eeitem.hxx>
28 #include <sfx2/objsh.hxx>
30 #include <editeng/editdata.hxx>
31 #include <editeng/editeng.hxx>
32 #include <editeng/editobj.hxx>
33 #include <editeng/editstat.hxx>
35 #include <editeng/flditem.hxx>
36 #include <editeng/flstitem.hxx>
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>
55 #include "globstr.hrc"
56 #include "docpool.hxx"
57 #include "patattr.hxx"
58 #include "formulacell.hxx"
59 #include "document.hxx"
60 #include "scextopt.hxx"
62 #include "progress.hxx"
63 #include "dociter.hxx"
64 #include "rangenam.hxx"
66 #include "stlsheet.hxx"
67 #include "stlpool.hxx"
68 #include "editutil.hxx"
69 #include <formula/errorcodes.hxx>
70 #include "queryentry.hxx"
71 #include "queryparam.hxx"
74 #include "xeescher.hxx"
75 #include "xeformula.hxx"
78 #include "xecontent.hxx"
80 #include "xcl97rec.hxx"
81 #include "tabprotection.hxx"
83 using namespace ::oox
;
85 using ::com::sun::star::uno::Sequence
;
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
94 const sal_Size
ExcDummy_00::nMyLen
= sizeof( ExcDummy_00::pMyData
);
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
101 const sal_Size
ExcDummy_040::nMyLen
= sizeof( ExcDummy_040::pMyData
);
103 const sal_uInt8
ExcDummy_041::pMyData
[] = {
104 0x0e, 0x00, 0x02, 0x00, 0x01, 0x00, // PRECISION
105 0xda, 0x00, 0x02, 0x00, 0x00, 0x00 // BOOKBOOL
107 const sal_Size
ExcDummy_041::nMyLen
= sizeof( ExcDummy_041::pMyData
);
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
117 0x5f, 0x00, 0x02, 0x00, 0x01, 0x00 // SAVERECALC
119 const sal_Size
ExcDummy_02a::nMyLen
= sizeof( ExcDummy_02a::pMyData
);
121 //----------------------------------------------------------- class ExcRecord -
123 void ExcRecord::Save( XclExpStream
& rStrm
)
125 SetRecHeader( GetNum(), GetLen() );
126 XclExpRecord::Save( rStrm
);
129 void ExcRecord::SaveCont( XclExpStream
& /*rStrm*/ )
133 void ExcRecord::WriteBody( XclExpStream
& rStrm
)
138 void ExcRecord::SaveXml( XclExpXmlStream
& /*rStrm*/ )
142 //--------------------------------------------------------- class ExcEmptyRec -
144 void ExcEmptyRec::Save( XclExpStream
& /*rStrm*/ )
148 sal_uInt16
ExcEmptyRec::GetNum() const
153 sal_Size
ExcEmptyRec::GetLen() const
158 //--------------------------------------------------------- class ExcDummyRec -
160 void ExcDummyRec::Save( XclExpStream
& rStrm
)
162 rStrm
.Write( GetData(), GetLen() ); // raw write mode
165 sal_uInt16
ExcDummyRec::GetNum() const
170 //------------------------------------------------------- class ExcBoolRecord -
172 void ExcBoolRecord::SaveCont( XclExpStream
& rStrm
)
174 rStrm
<< (sal_uInt16
)(bVal
? 0x0001 : 0x0000);
177 sal_Size
ExcBoolRecord::GetLen() const
182 //--------------------------------------------------------- class ExcBof_Base -
184 ExcBof_Base::ExcBof_Base()
187 , nRupBuild(0x096C) // copied from Excel
188 , nRupYear(0x07C9) // copied from Excel
192 //-------------------------------------------------------------- class ExcBof -
200 void ExcBof::SaveCont( XclExpStream
& rStrm
)
202 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
;
205 sal_uInt16
ExcBof::GetNum() const
210 sal_Size
ExcBof::GetLen() const
215 //------------------------------------------------------------- class ExcBofW -
223 void ExcBofW::SaveCont( XclExpStream
& rStrm
)
225 rStrm
<< nVers
<< nDocType
<< nRupBuild
<< nRupYear
;
228 sal_uInt16
ExcBofW::GetNum() const
233 sal_Size
ExcBofW::GetLen() const
238 //-------------------------------------------------------------- class ExcEof -
240 sal_uInt16
ExcEof::GetNum() const
245 sal_Size
ExcEof::GetLen() const
250 //--------------------------------------------------------- class ExcDummy_00 -
252 sal_Size
ExcDummy_00::GetLen() const
257 const sal_uInt8
* ExcDummy_00::GetData() const
262 //-------------------------------------------------------- class ExcDummy_04x -
264 sal_Size
ExcDummy_040::GetLen() const
269 const sal_uInt8
* ExcDummy_040::GetData() const
274 sal_Size
ExcDummy_041::GetLen() const
279 const sal_uInt8
* ExcDummy_041::GetData() const
284 //------------------------------------------------------------- class Exc1904 -
286 Exc1904::Exc1904( ScDocument
& rDoc
)
288 Date
* pDate
= rDoc
.GetFormatTable()->GetNullDate();
289 bVal
= pDate
&& (*pDate
== Date( 1, 1, 1904 ));
290 bDateCompatibility
= pDate
&& !( *pDate
== Date( 30, 12, 1899 ));
293 sal_uInt16
Exc1904::GetNum() const
298 void Exc1904::SaveXml( XclExpXmlStream
& rStrm
)
300 bool bISOIEC
= ( rStrm
.getVersion() == oox::core::ISOIEC_29500_2008
);
304 rStrm
.WriteAttributes(
305 XML_dateCompatibility
, XclXmlUtils::ToPsz( bDateCompatibility
),
309 if( !bISOIEC
|| bDateCompatibility
)
311 rStrm
.WriteAttributes(
312 XML_date1904
, XclXmlUtils::ToPsz( bVal
),
317 //------------------------------------------------------ class ExcBundlesheet -
319 ExcBundlesheetBase::ExcBundlesheetBase( RootData
& rRootData
, SCTAB nTabNum
) :
320 m_nStrPos( STREAM_SEEK_TO_END
),
321 m_nOwnPos( STREAM_SEEK_TO_END
),
322 nGrbit( rRootData
.pER
->GetTabInfo().IsVisibleTab( nTabNum
) ? 0x0000 : 0x0001 ),
327 ExcBundlesheetBase::ExcBundlesheetBase() :
328 m_nStrPos( STREAM_SEEK_TO_END
),
329 m_nOwnPos( STREAM_SEEK_TO_END
),
335 void ExcBundlesheetBase::UpdateStreamPos( XclExpStream
& rStrm
)
337 rStrm
.SetSvStreamPos( m_nOwnPos
);
338 rStrm
.DisableEncryption();
339 rStrm
<< static_cast<sal_uInt32
>(m_nStrPos
);
340 rStrm
.EnableEncryption();
343 sal_uInt16
ExcBundlesheetBase::GetNum() const
348 ExcBundlesheet::ExcBundlesheet( RootData
& rRootData
, SCTAB _nTab
) :
349 ExcBundlesheetBase( rRootData
, _nTab
)
351 OUString sTabName
= rRootData
.pER
->GetTabInfo().GetScTabName( _nTab
);
352 OSL_ENSURE( sTabName
.getLength() < 256, "ExcBundlesheet::ExcBundlesheet - table name too long" );
353 aName
= OUStringToOString(sTabName
, rRootData
.pER
->GetTextEncoding());
356 void ExcBundlesheet::SaveCont( XclExpStream
& rStrm
)
358 m_nOwnPos
= rStrm
.GetSvStreamPos();
359 rStrm
<< (sal_uInt32
) 0x00000000 // dummy (stream position of the sheet)
361 rStrm
.WriteByteString(aName
); // 8 bit length, max 255 chars
364 sal_Size
ExcBundlesheet::GetLen() const
366 return 7 + std::min( aName
.getLength(), (sal_Int32
) 255 );
369 //--------------------------------------------------------- class ExcDummy_02 -
371 sal_Size
ExcDummy_02a::GetLen() const
376 const sal_uInt8
* ExcDummy_02a::GetData() const
380 //--------------------------------------------------------- class ExcDummy_02 -
382 XclExpCountry::XclExpCountry( const XclExpRoot
& rRoot
) :
383 XclExpRecord( EXC_ID_COUNTRY
, 4 )
385 /* #i31530# set document country as UI country too -
386 needed for correct behaviour of number formats. */
387 mnUICountry
= mnDocCountry
= static_cast< sal_uInt16
>(
388 ::msfilter::ConvertLanguageToCountry( rRoot
.GetDocLanguage() ) );
391 void XclExpCountry::WriteBody( XclExpStream
& rStrm
)
393 rStrm
<< mnUICountry
<< mnDocCountry
;
396 // XclExpWsbool ===============================================================
398 XclExpWsbool::XclExpWsbool( bool bFitToPages
)
399 : XclExpUInt16Record( EXC_ID_WSBOOL
, EXC_WSBOOL_DEFAULTFLAGS
)
402 SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE
);
405 XclExpXmlSheetPr::XclExpXmlSheetPr( bool bFitToPages
, SCTAB nScTab
, const Color
& rTabColor
, XclExpFilterManager
* pManager
) :
406 mnScTab(nScTab
), mpManager(pManager
), mbFitToPage(bFitToPages
), maTabColor(rTabColor
) {}
408 void XclExpXmlSheetPr::SaveXml( XclExpXmlStream
& rStrm
)
410 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
411 rWorksheet
->startElement( XML_sheetPr
,
412 // OOXTODO: XML_syncHorizontal,
413 // OOXTODO: XML_syncVertical,
414 // OOXTODO: XML_syncRef,
415 // OOXTODO: XML_transitionEvaluation,
416 // OOXTODO: XML_transitionEntry,
417 // OOXTODO: XML_published,
418 // OOXTODO: XML_codeName,
419 XML_filterMode
, mpManager
? XclXmlUtils::ToPsz( mpManager
->HasFilterMode( mnScTab
) ) : NULL
,
420 // OOXTODO: XML_enableFormatConditionsCalculation,
423 // Note : the order of child elements is significant. Don't change the order.
425 // OOXTODO: XML_outlinePr
427 if (maTabColor
!= Color(COL_AUTO
))
428 rWorksheet
->singleElement(
429 XML_tabColor
, XML_rgb
, XclXmlUtils::ToOString(maTabColor
).getStr(), FSEND
);
431 rWorksheet
->singleElement(XML_pageSetUpPr
,
432 // OOXTODO: XML_autoPageBreaks,
433 XML_fitToPage
, XclXmlUtils::ToPsz(mbFitToPage
), FSEND
);
435 rWorksheet
->endElement( XML_sheetPr
);
438 // XclExpWindowProtection ===============================================================
440 XclExpWindowProtection::XclExpWindowProtection(bool bValue
) :
441 XclExpBoolRecord(EXC_ID_WINDOWPROTECT
, bValue
)
445 void XclExpWindowProtection::SaveXml( XclExpXmlStream
& rStrm
)
447 rStrm
.WriteAttributes(
448 XML_lockWindows
, XclXmlUtils::ToPsz( GetBool() ),
452 // XclExpDocProtection ===============================================================
454 XclExpProtection::XclExpProtection(bool bValue
) :
455 XclExpBoolRecord(EXC_ID_PROTECT
, bValue
)
459 XclExpSheetProtection::XclExpSheetProtection(bool bValue
, SCTAB nTab
) :
460 XclExpProtection( bValue
),
465 void XclExpSheetProtection::SaveXml( XclExpXmlStream
& rStrm
)
467 ScDocument
& rDoc
= rStrm
.GetRoot().GetDoc();
468 const ScTableProtection
* pTabProtect
= rDoc
.GetTabProtection(mnTab
);
471 Sequence
<sal_Int8
> aHash
= pTabProtect
->getPasswordHash(PASSHASH_XL
);
473 if (aHash
.getLength() >= 2)
475 sHash
= OString::number(
476 ( static_cast<sal_uInt8
>(aHash
[0]) << 8
477 | static_cast<sal_uInt8
>(aHash
[1]) ),
480 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
481 rWorksheet
->singleElement( XML_sheetProtection
,
482 XML_sheet
, XclXmlUtils::ToPsz( true ),
483 XML_password
, sHash
.isEmpty()? NULL
: sHash
.getStr(),
484 XML_objects
, pTabProtect
->isOptionEnabled( ScTableProtection::OBJECTS
) ? NULL
: XclXmlUtils::ToPsz( true ),
485 XML_scenarios
, pTabProtect
->isOptionEnabled( ScTableProtection::SCENARIOS
) ? NULL
: XclXmlUtils::ToPsz( true ),
486 XML_formatCells
, pTabProtect
->isOptionEnabled( ScTableProtection::FORMAT_CELLS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
487 XML_formatColumns
, pTabProtect
->isOptionEnabled( ScTableProtection::FORMAT_COLUMNS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
488 XML_formatRows
, pTabProtect
->isOptionEnabled( ScTableProtection::FORMAT_ROWS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
489 XML_insertColumns
, pTabProtect
->isOptionEnabled( ScTableProtection::INSERT_COLUMNS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
490 XML_insertRows
, pTabProtect
->isOptionEnabled( ScTableProtection::INSERT_ROWS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
491 XML_insertHyperlinks
, pTabProtect
->isOptionEnabled( ScTableProtection::INSERT_HYPERLINKS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
492 XML_deleteColumns
, pTabProtect
->isOptionEnabled( ScTableProtection::DELETE_COLUMNS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
493 XML_deleteRows
, pTabProtect
->isOptionEnabled( ScTableProtection::DELETE_ROWS
) ? XclXmlUtils::ToPsz( false ) : NULL
,
494 XML_selectLockedCells
, pTabProtect
->isOptionEnabled( ScTableProtection::SELECT_LOCKED_CELLS
) ? NULL
: XclXmlUtils::ToPsz( true ),
495 XML_sort
, pTabProtect
->isOptionEnabled( ScTableProtection::SORT
) ? XclXmlUtils::ToPsz( false ) : NULL
,
496 XML_autoFilter
, pTabProtect
->isOptionEnabled( ScTableProtection::AUTOFILTER
) ? XclXmlUtils::ToPsz( false ) : NULL
,
497 XML_pivotTables
, pTabProtect
->isOptionEnabled( ScTableProtection::PIVOT_TABLES
) ? XclXmlUtils::ToPsz( false ) : NULL
,
498 XML_selectUnlockedCells
, pTabProtect
->isOptionEnabled( ScTableProtection::SELECT_UNLOCKED_CELLS
) ? NULL
: XclXmlUtils::ToPsz( true ),
501 const ::std::vector
<ScEnhancedProtection
>& rProts( pTabProtect
->getEnhancedProtection());
504 rWorksheet
->startElement( XML_protectedRanges
, FSEND
);
505 for (::std::vector
<ScEnhancedProtection
>::const_iterator
it( rProts
.begin()), end( rProts
.end());
508 SAL_WARN_IF( (*it
).maSecurityDescriptorXML
.isEmpty() && !(*it
).maSecurityDescriptor
.empty(),
509 "sc.filter", "XclExpSheetProtection::SaveXml: losing BIFF security descriptor");
510 rWorksheet
->singleElement( XML_protectedRange
,
511 XML_name
, (*it
).maTitle
.isEmpty() ? NULL
: XclXmlUtils::ToOString( (*it
).maTitle
).getStr(),
512 XML_securityDescriptor
, (*it
).maSecurityDescriptorXML
.isEmpty() ? NULL
: XclXmlUtils::ToOString( (*it
).maSecurityDescriptorXML
).getStr(),
513 /* XXX 'password' is not part of OOXML, but Excel2013
514 * writes it if loaded from BIFF, in which case
515 * 'algorithmName', 'hashValue', 'saltValue' and
516 * 'spinCount' are absent; so do we if it was present. */
517 XML_password
, (*it
).mnPasswordVerifier
? OString::number( (*it
).mnPasswordVerifier
, 16).getStr() : NULL
,
518 XML_algorithmName
, (*it
).maAlgorithmName
.isEmpty() ? NULL
: XclXmlUtils::ToOString( (*it
).maAlgorithmName
).getStr(),
519 XML_hashValue
, (*it
).maHashValue
.isEmpty() ? NULL
: XclXmlUtils::ToOString( (*it
).maHashValue
).getStr(),
520 XML_saltValue
, (*it
).maSaltValue
.isEmpty() ? NULL
: XclXmlUtils::ToOString( (*it
).maSaltValue
).getStr(),
521 XML_spinCount
, (*it
).mnSpinCount
? OString::number( (*it
).mnSpinCount
).getStr() : NULL
,
522 XML_sqref
, (*it
).maRangeList
.Is() ? XclXmlUtils::ToOString( *(*it
).maRangeList
).getStr() : NULL
,
525 rWorksheet
->endElement( XML_protectedRanges
);
530 XclExpPassHash::XclExpPassHash(const Sequence
<sal_Int8
>& aHash
) :
531 XclExpRecord(EXC_ID_PASSWORD
, 2),
534 if (aHash
.getLength() >= 2)
536 mnHash
= ((aHash
[0] << 8) & 0xFFFF);
537 mnHash
|= (aHash
[1] & 0xFF);
541 XclExpPassHash::~XclExpPassHash()
545 void XclExpPassHash::WriteBody(XclExpStream
& rStrm
)
550 XclExpFiltermode::XclExpFiltermode() :
551 XclExpEmptyRecord( EXC_ID_FILTERMODE
)
555 XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress
& rStartPos
, SCCOL nScCol
) :
556 XclExpUInt16Record( EXC_ID_AUTOFILTERINFO
, static_cast< sal_uInt16
>( nScCol
) ),
557 maStartPos( rStartPos
)
561 ExcFilterCondition::ExcFilterCondition() :
562 nType( EXC_AFTYPE_NOTUSED
),
563 nOper( EXC_AFOPER_EQUAL
),
569 ExcFilterCondition::~ExcFilterCondition()
575 sal_Size
ExcFilterCondition::GetTextBytes() const
577 return pText
? (1 + pText
->GetBufferSize()) : 0;
580 void ExcFilterCondition::SetCondition( sal_uInt8 nTp
, sal_uInt8 nOp
, double fV
, OUString
* pT
)
587 (pT
) ? pText
= new XclExpString( *pT
, EXC_STR_8BITLENGTH
) : pText
= NULL
;
590 void ExcFilterCondition::Save( XclExpStream
& rStrm
)
592 rStrm
<< nType
<< nOper
;
595 case EXC_AFTYPE_DOUBLE
:
598 case EXC_AFTYPE_STRING
:
599 OSL_ENSURE( pText
, "ExcFilterCondition::Save() -- pText is NULL!" );
600 rStrm
<< (sal_uInt32
)0 << (sal_uInt8
) pText
->Len() << (sal_uInt16
)0 << (sal_uInt8
)0;
602 case EXC_AFTYPE_BOOLERR
:
603 rStrm
<< (sal_uInt8
)0 << (sal_uInt8
)((fVal
!= 0) ? 1 : 0) << (sal_uInt32
)0 << (sal_uInt16
)0;
606 rStrm
<< (sal_uInt32
)0 << (sal_uInt32
)0;
610 static const char* lcl_GetOperator( sal_uInt8 nOper
)
614 case EXC_AFOPER_EQUAL
: return "equal";
615 case EXC_AFOPER_GREATER
: return "greaterThan";
616 case EXC_AFOPER_GREATEREQUAL
: return "greaterThanOrEqual";
617 case EXC_AFOPER_LESS
: return "lessThan";
618 case EXC_AFOPER_LESSEQUAL
: return "lessThanOrEqual";
619 case EXC_AFOPER_NOTEQUAL
: return "notEqual";
620 case EXC_AFOPER_NONE
:
621 default: return "**none**";
625 static OString
lcl_GetValue( sal_uInt8 nType
, double fVal
, XclExpString
* pStr
)
629 case EXC_AFTYPE_STRING
: return XclXmlUtils::ToOString( *pStr
);
630 case EXC_AFTYPE_DOUBLE
: return OString::number( fVal
);
631 case EXC_AFTYPE_BOOLERR
: return OString::number( ( fVal
!= 0 ? 1 : 0 ) );
632 default: return OString();
636 void ExcFilterCondition::SaveXml( XclExpXmlStream
& rStrm
)
641 rStrm
.GetCurrentStream()->singleElement( XML_customFilter
,
642 XML_operator
, lcl_GetOperator( nOper
),
643 XML_val
, lcl_GetValue( nType
, fVal
, pText
).getStr(),
647 void ExcFilterCondition::SaveText( XclExpStream
& rStrm
)
649 if( nType
== EXC_AFTYPE_STRING
)
651 OSL_ENSURE( pText
, "ExcFilterCondition::SaveText() -- pText is NULL!" );
652 pText
->WriteFlagField( rStrm
);
653 pText
->WriteBuffer( rStrm
);
657 XclExpAutofilter::XclExpAutofilter( const XclExpRoot
& rRoot
, sal_uInt16 nC
) :
658 XclExpRecord( EXC_ID_AUTOFILTER
, 24 ),
660 meType(FilterCondition
),
666 bool XclExpAutofilter::AddCondition( ScQueryConnect eConn
, sal_uInt8 nType
, sal_uInt8 nOp
,
667 double fVal
, OUString
* pText
, bool bSimple
)
669 if( !aCond
[ 1 ].IsEmpty() )
672 sal_uInt16 nInd
= aCond
[ 0 ].IsEmpty() ? 0 : 1;
675 nFlags
|= (eConn
== SC_OR
) ? EXC_AFFLAG_OR
: EXC_AFFLAG_AND
;
677 nFlags
|= (nInd
== 0) ? EXC_AFFLAG_SIMPLE1
: EXC_AFFLAG_SIMPLE2
;
679 aCond
[ nInd
].SetCondition( nType
, nOp
, fVal
, pText
);
681 AddRecSize( aCond
[ nInd
].GetTextBytes() );
686 bool XclExpAutofilter::HasCondition() const
688 return !aCond
[0].IsEmpty();
691 bool XclExpAutofilter::AddEntry( const ScQueryEntry
& rEntry
)
693 const ScQueryEntry::QueryItemsType
& rItems
= rEntry
.GetQueryItems();
697 if (GetOutput() != EXC_OUTPUT_BINARY
&& rItems
.size() > 1)
698 return AddMultiValueEntry(rEntry
);
700 bool bConflict
= false;
702 const ScQueryEntry::Item
& rItem
= rItems
[0];
703 if (!rItem
.maString
.isEmpty())
705 sText
= rItem
.maString
.getString();
709 case SC_DOES_NOT_CONTAIN
:
711 sText
= "*" + sText
+ "*";
715 case SC_DOES_NOT_BEGIN_WITH
:
719 case SC_DOES_NOT_END_WITH
:
729 bool bLen
= sText
.getLength() > 0;
731 // empty/nonempty fields
732 if (rEntry
.IsQueryByEmpty())
733 bConflict
= !AddCondition( rEntry
.eConnect
, EXC_AFTYPE_EMPTY
, EXC_AFOPER_NONE
, 0.0, NULL
, true );
734 else if(rEntry
.IsQueryByNonEmpty())
735 bConflict
= !AddCondition( rEntry
.eConnect
, EXC_AFTYPE_NOTEMPTY
, EXC_AFOPER_NONE
, 0.0, NULL
, true );
740 sal_uInt32 nIndex
= 0;
741 bool bIsNum
= !bLen
|| GetFormatter().IsNumberFormat( sText
, nIndex
, fVal
);
743 (bIsNum
) ? pText
= NULL
: pText
= &sText
;
746 sal_uInt16 nNewFlags
= 0x0000;
750 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10TOP
);
753 nNewFlags
= EXC_AFFLAG_TOP10
;
756 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10TOP
| EXC_AFFLAG_TOP10PERC
);
759 nNewFlags
= (EXC_AFFLAG_TOP10
| EXC_AFFLAG_TOP10PERC
);
763 bool bNewTop10
= ::get_flag( nNewFlags
, EXC_AFFLAG_TOP10
);
765 bConflict
= HasTop10() && bNewTop10
;
770 if( fVal
< 0 ) fVal
= 0;
771 if( fVal
>= 501 ) fVal
= 500;
772 nFlags
|= (nNewFlags
| (sal_uInt16
)(fVal
) << 7);
777 sal_uInt8 nType
= bIsNum
? EXC_AFTYPE_DOUBLE
: EXC_AFTYPE_STRING
;
778 sal_uInt8 nOper
= EXC_AFOPER_NONE
;
782 case SC_EQUAL
: nOper
= EXC_AFOPER_EQUAL
; break;
783 case SC_LESS
: nOper
= EXC_AFOPER_LESS
; break;
784 case SC_GREATER
: nOper
= EXC_AFOPER_GREATER
; break;
785 case SC_LESS_EQUAL
: nOper
= EXC_AFOPER_LESSEQUAL
; break;
786 case SC_GREATER_EQUAL
: nOper
= EXC_AFOPER_GREATEREQUAL
; break;
787 case SC_NOT_EQUAL
: nOper
= EXC_AFOPER_NOTEQUAL
; break;
791 nOper
= EXC_AFOPER_EQUAL
; break;
792 case SC_DOES_NOT_CONTAIN
:
793 case SC_DOES_NOT_BEGIN_WITH
:
794 case SC_DOES_NOT_END_WITH
:
795 nOper
= EXC_AFOPER_NOTEQUAL
; break;
798 bConflict
= !AddCondition( rEntry
.eConnect
, nType
, nOper
, fVal
, pText
);
805 bool XclExpAutofilter::AddMultiValueEntry( const ScQueryEntry
& rEntry
)
808 const ScQueryEntry::QueryItemsType
& rItems
= rEntry
.GetQueryItems();
809 ScQueryEntry::QueryItemsType::const_iterator itr
= rItems
.begin(), itrEnd
= rItems
.end();
810 for (; itr
!= itrEnd
; ++itr
)
811 maMultiValues
.push_back(itr
->maString
.getString());
816 void XclExpAutofilter::WriteBody( XclExpStream
& rStrm
)
818 rStrm
<< nCol
<< nFlags
;
819 aCond
[ 0 ].Save( rStrm
);
820 aCond
[ 1 ].Save( rStrm
);
821 aCond
[ 0 ].SaveText( rStrm
);
822 aCond
[ 1 ].SaveText( rStrm
);
825 void XclExpAutofilter::SaveXml( XclExpXmlStream
& rStrm
)
827 if (meType
== FilterCondition
&& !HasCondition())
830 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
832 rWorksheet
->startElement( XML_filterColumn
,
833 XML_colId
, OString::number( nCol
).getStr(),
834 // OOXTODO: XML_hiddenButton, AutoFilter12 fHideArrow?
835 // OOXTODO: XML_showButton,
840 case FilterCondition
:
844 rWorksheet
->singleElement( XML_top10
,
845 XML_top
, XclXmlUtils::ToPsz( get_flag( nFlags
, EXC_AFFLAG_TOP10TOP
) ),
846 XML_percent
, XclXmlUtils::ToPsz( get_flag( nFlags
, EXC_AFFLAG_TOP10PERC
) ),
847 XML_val
, OString::number( (nFlags
>> 7 ) ).getStr(),
848 // OOXTODO: XML_filterVal,
852 rWorksheet
->startElement( XML_customFilters
,
853 XML_and
, XclXmlUtils::ToPsz( (nFlags
& EXC_AFFLAG_ANDORMASK
) == EXC_AFFLAG_AND
),
855 aCond
[ 0 ].SaveXml( rStrm
);
856 aCond
[ 1 ].SaveXml( rStrm
);
857 rWorksheet
->endElement( XML_customFilters
);
858 // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
859 // XML_extLst, XML_filters, XML_iconFilter, XML_top10
864 rWorksheet
->startElement(XML_filters
, FSEND
);
865 std::vector
<OUString
>::const_iterator itr
= maMultiValues
.begin(), itrEnd
= maMultiValues
.end();
866 for (; itr
!= itrEnd
; ++itr
)
868 OString aStr
= OUStringToOString(*itr
, RTL_TEXTENCODING_UTF8
);
869 const char* pz
= aStr
.getStr();
870 rWorksheet
->singleElement(XML_filter
, XML_val
, pz
, FSEND
);
872 rWorksheet
->endElement(XML_filters
);
876 rWorksheet
->endElement( XML_filterColumn
);
879 ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot
& rRoot
, SCTAB nTab
) :
883 , mbAutoFilter (false)
885 XclExpNameManager
& rNameMgr
= GetNameManager();
888 bool bAdvanced
= false;
889 ScDBData
* pData
= rRoot
.GetDoc().GetAnonymousDBData(nTab
);
893 bAdvanced
= pData
->GetAdvancedQuerySource( aAdvRange
);
894 bFound
= (pData
->HasQueryParam() || pData
->HasAutoFilter() || bAdvanced
);
899 pData
->GetQueryParam( aParam
);
901 ScRange
aRange( aParam
.nCol1
, aParam
.nRow1
, aParam
.nTab
,
902 aParam
.nCol2
, aParam
.nRow2
, aParam
.nTab
);
903 SCCOL nColCnt
= aParam
.nCol2
- aParam
.nCol1
+ 1;
907 // #i2394# built-in defined names must be sorted by containing sheet name
908 rNameMgr
.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE
, aRange
);
913 // filter criteria, excel allows only same table
914 if( aAdvRange
.aStart
.Tab() == nTab
)
915 rNameMgr
.InsertBuiltInName( EXC_BUILTIN_CRITERIA
, aAdvRange
);
917 // filter destination range, excel allows only same table
918 if( !aParam
.bInplace
)
920 ScRange
aDestRange( aParam
.nDestCol
, aParam
.nDestRow
, aParam
.nDestTab
);
921 aDestRange
.aEnd
.IncCol( nColCnt
- 1 );
922 if( aDestRange
.aStart
.Tab() == nTab
)
923 rNameMgr
.InsertBuiltInName( EXC_BUILTIN_EXTRACT
, aDestRange
);
926 pFilterMode
= new XclExpFiltermode
;
931 bool bConflict
= false;
932 bool bContLoop
= true;
934 SCCOLROW nFirstField
= aParam
.GetEntry( 0 ).nField
;
936 // create AUTOFILTER records for filtered columns
937 for( SCSIZE nEntry
= 0; !bConflict
&& bContLoop
&& (nEntry
< aParam
.GetEntryCount()); nEntry
++ )
939 const ScQueryEntry
& rEntry
= aParam
.GetEntry( nEntry
);
941 bContLoop
= rEntry
.bDoQuery
;
944 XclExpAutofilter
* pFilter
= GetByCol( static_cast<SCCOL
>(rEntry
.nField
) - aRange
.aStart
.Col() );
947 bHasOr
|= (rEntry
.eConnect
== SC_OR
);
949 bConflict
= (nEntry
> 1) && bHasOr
;
951 bConflict
= (nEntry
== 1) && (rEntry
.eConnect
== SC_OR
) &&
952 (nFirstField
!= rEntry
.nField
);
954 bConflict
= pFilter
->AddEntry( rEntry
);
958 // additional tests for conflicts
959 for( size_t nPos
= 0, nSize
= maFilterList
.GetSize(); !bConflict
&& (nPos
< nSize
); ++nPos
)
961 XclExpAutofilterRef xFilter
= maFilterList
.GetRecord( nPos
);
962 bConflict
= xFilter
->HasCondition() && xFilter
->HasTop10();
966 maFilterList
.RemoveAllRecords();
968 if( !maFilterList
.IsEmpty() )
969 pFilterMode
= new XclExpFiltermode
;
970 pFilterInfo
= new XclExpAutofilterinfo( aRange
.aStart
, nColCnt
);
972 if (maFilterList
.IsEmpty () && !bConflict
)
978 ExcAutoFilterRecs::~ExcAutoFilterRecs()
984 XclExpAutofilter
* ExcAutoFilterRecs::GetByCol( SCCOL nCol
)
986 XclExpAutofilterRef xFilter
;
987 for( size_t nPos
= 0, nSize
= maFilterList
.GetSize(); nPos
< nSize
; ++nPos
)
989 xFilter
= maFilterList
.GetRecord( nPos
);
990 if( xFilter
->GetCol() == static_cast<sal_uInt16
>(nCol
) )
991 return xFilter
.get();
993 xFilter
.reset( new XclExpAutofilter( GetRoot(), static_cast<sal_uInt16
>(nCol
) ) );
994 maFilterList
.AppendRecord( xFilter
);
995 return xFilter
.get();
998 bool ExcAutoFilterRecs::IsFiltered( SCCOL nCol
)
1000 for( size_t nPos
= 0, nSize
= maFilterList
.GetSize(); nPos
< nSize
; ++nPos
)
1001 if( maFilterList
.GetRecord( nPos
)->GetCol() == static_cast<sal_uInt16
>(nCol
) )
1006 void ExcAutoFilterRecs::AddObjRecs()
1010 ScAddress
aAddr( pFilterInfo
->GetStartPos() );
1011 for( SCCOL nObj
= 0, nCount
= pFilterInfo
->GetColCount(); nObj
< nCount
; nObj
++ )
1013 XclObj
* pObjRec
= new XclObjDropDown( GetObjectManager(), aAddr
, IsFiltered( nObj
) );
1014 GetObjectManager().AddObj( pObjRec
);
1020 void ExcAutoFilterRecs::Save( XclExpStream
& rStrm
)
1023 pFilterMode
->Save( rStrm
);
1025 pFilterInfo
->Save( rStrm
);
1026 maFilterList
.Save( rStrm
);
1029 void ExcAutoFilterRecs::SaveXml( XclExpXmlStream
& rStrm
)
1031 if( maFilterList
.IsEmpty() && !mbAutoFilter
)
1034 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
1035 rWorksheet
->startElement( XML_autoFilter
,
1036 XML_ref
, XclXmlUtils::ToOString( maRef
).getStr(),
1038 // OOXTODO: XML_extLst, XML_sortState
1039 if( !maFilterList
.IsEmpty() )
1040 maFilterList
.SaveXml( rStrm
);
1041 rWorksheet
->endElement( XML_autoFilter
);
1044 bool ExcAutoFilterRecs::HasFilterMode() const
1046 return pFilterMode
!= NULL
;
1049 XclExpFilterManager::XclExpFilterManager( const XclExpRoot
& rRoot
) :
1054 void XclExpFilterManager::InitTabFilter( SCTAB nScTab
)
1056 maFilterMap
[ nScTab
].reset( new ExcAutoFilterRecs( GetRoot(), nScTab
) );
1059 XclExpRecordRef
XclExpFilterManager::CreateRecord( SCTAB nScTab
)
1061 XclExpTabFilterRef xRec
;
1062 XclExpTabFilterMap::iterator aIt
= maFilterMap
.find( nScTab
);
1063 if( aIt
!= maFilterMap
.end() )
1071 bool XclExpFilterManager::HasFilterMode( SCTAB nScTab
)
1073 XclExpTabFilterRef xRec
;
1074 XclExpTabFilterMap::iterator aIt
= maFilterMap
.find( nScTab
);
1075 if( aIt
!= maFilterMap
.end() )
1077 return aIt
->second
->HasFilterMode();
1082 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */