1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_sc.hxx"
26*b1cdbd2cSJim Jagielski #include "xetable.hxx"
27*b1cdbd2cSJim Jagielski
28*b1cdbd2cSJim Jagielski #include <map>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/i18n/ScriptType.hpp>
30*b1cdbd2cSJim Jagielski #include "scitems.hxx"
31*b1cdbd2cSJim Jagielski #include <svl/intitem.hxx>
32*b1cdbd2cSJim Jagielski #include "document.hxx"
33*b1cdbd2cSJim Jagielski #include "dociter.hxx"
34*b1cdbd2cSJim Jagielski #include "olinetab.hxx"
35*b1cdbd2cSJim Jagielski #include "cell.hxx"
36*b1cdbd2cSJim Jagielski #include "patattr.hxx"
37*b1cdbd2cSJim Jagielski #include "attrib.hxx"
38*b1cdbd2cSJim Jagielski #include "xehelper.hxx"
39*b1cdbd2cSJim Jagielski #include "xecontent.hxx"
40*b1cdbd2cSJim Jagielski #include "xeescher.hxx"
41*b1cdbd2cSJim Jagielski
42*b1cdbd2cSJim Jagielski using namespace ::oox;
43*b1cdbd2cSJim Jagielski
44*b1cdbd2cSJim Jagielski using ::rtl::OString;
45*b1cdbd2cSJim Jagielski using ::rtl::OUString;
46*b1cdbd2cSJim Jagielski using ::rtl::OUStringBuffer;
47*b1cdbd2cSJim Jagielski
48*b1cdbd2cSJim Jagielski namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
49*b1cdbd2cSJim Jagielski
50*b1cdbd2cSJim Jagielski // ============================================================================
51*b1cdbd2cSJim Jagielski // Helper records for cell records
52*b1cdbd2cSJim Jagielski // ============================================================================
53*b1cdbd2cSJim Jagielski
XclExpStringRec(const XclExpRoot & rRoot,const String & rResult)54*b1cdbd2cSJim Jagielski XclExpStringRec::XclExpStringRec( const XclExpRoot& rRoot, const String& rResult ) :
55*b1cdbd2cSJim Jagielski XclExpRecord( EXC_ID3_STRING ),
56*b1cdbd2cSJim Jagielski mxResult( XclExpStringHelper::CreateString( rRoot, rResult ) )
57*b1cdbd2cSJim Jagielski {
58*b1cdbd2cSJim Jagielski DBG_ASSERT( (rRoot.GetBiff() <= EXC_BIFF5) || (mxResult->Len() > 0),
59*b1cdbd2cSJim Jagielski "XclExpStringRec::XclExpStringRec - empty result not allowed in BIFF8+" );
60*b1cdbd2cSJim Jagielski SetRecSize( mxResult->GetSize() );
61*b1cdbd2cSJim Jagielski }
62*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)63*b1cdbd2cSJim Jagielski void XclExpStringRec::WriteBody( XclExpStream& rStrm )
64*b1cdbd2cSJim Jagielski {
65*b1cdbd2cSJim Jagielski rStrm << *mxResult;
66*b1cdbd2cSJim Jagielski }
67*b1cdbd2cSJim Jagielski
68*b1cdbd2cSJim Jagielski // Additional records for special formula ranges ==============================
69*b1cdbd2cSJim Jagielski
XclExpRangeFmlaBase(sal_uInt16 nRecId,sal_uInt32 nRecSize,const ScAddress & rScPos)70*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase::XclExpRangeFmlaBase(
71*b1cdbd2cSJim Jagielski sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScAddress& rScPos ) :
72*b1cdbd2cSJim Jagielski XclExpRecord( nRecId, nRecSize ),
73*b1cdbd2cSJim Jagielski maXclRange( ScAddress::UNINITIALIZED ),
74*b1cdbd2cSJim Jagielski maBaseXclPos( ScAddress::UNINITIALIZED )
75*b1cdbd2cSJim Jagielski {
76*b1cdbd2cSJim Jagielski maBaseXclPos.Set( static_cast< sal_uInt16 >( rScPos.Col() ), static_cast< sal_uInt16 >( rScPos.Row() ) );
77*b1cdbd2cSJim Jagielski maXclRange.maFirst = maXclRange.maLast = maBaseXclPos;
78*b1cdbd2cSJim Jagielski }
79*b1cdbd2cSJim Jagielski
XclExpRangeFmlaBase(sal_uInt16 nRecId,sal_uInt32 nRecSize,const ScRange & rScRange)80*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase::XclExpRangeFmlaBase(
81*b1cdbd2cSJim Jagielski sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScRange& rScRange ) :
82*b1cdbd2cSJim Jagielski XclExpRecord( nRecId, nRecSize ),
83*b1cdbd2cSJim Jagielski maXclRange( ScAddress::UNINITIALIZED ),
84*b1cdbd2cSJim Jagielski maBaseXclPos( ScAddress::UNINITIALIZED )
85*b1cdbd2cSJim Jagielski {
86*b1cdbd2cSJim Jagielski maXclRange.Set(
87*b1cdbd2cSJim Jagielski static_cast< sal_uInt16 >( rScRange.aStart.Col() ),
88*b1cdbd2cSJim Jagielski static_cast< sal_uInt16 >( rScRange.aStart.Row() ),
89*b1cdbd2cSJim Jagielski static_cast< sal_uInt16 >( rScRange.aEnd.Col() ),
90*b1cdbd2cSJim Jagielski static_cast< sal_uInt16 >( rScRange.aEnd.Row() ) );
91*b1cdbd2cSJim Jagielski maBaseXclPos = maXclRange.maFirst;
92*b1cdbd2cSJim Jagielski }
93*b1cdbd2cSJim Jagielski
IsBasePos(sal_uInt16 nXclCol,sal_uInt16 nXclRow) const94*b1cdbd2cSJim Jagielski bool XclExpRangeFmlaBase::IsBasePos( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
95*b1cdbd2cSJim Jagielski {
96*b1cdbd2cSJim Jagielski return (maBaseXclPos.mnCol == nXclCol) && (maBaseXclPos.mnRow == nXclRow);
97*b1cdbd2cSJim Jagielski }
98*b1cdbd2cSJim Jagielski
Extend(const ScAddress & rScPos)99*b1cdbd2cSJim Jagielski void XclExpRangeFmlaBase::Extend( const ScAddress& rScPos )
100*b1cdbd2cSJim Jagielski {
101*b1cdbd2cSJim Jagielski sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
102*b1cdbd2cSJim Jagielski sal_uInt16 nXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
103*b1cdbd2cSJim Jagielski maXclRange.maFirst.mnCol = ::std::min( maXclRange.maFirst.mnCol, nXclCol );
104*b1cdbd2cSJim Jagielski maXclRange.maFirst.mnRow = ::std::min( maXclRange.maFirst.mnRow, nXclRow );
105*b1cdbd2cSJim Jagielski maXclRange.maLast.mnCol = ::std::max( maXclRange.maLast.mnCol, nXclCol );
106*b1cdbd2cSJim Jagielski maXclRange.maLast.mnRow = ::std::max( maXclRange.maLast.mnRow, nXclRow );
107*b1cdbd2cSJim Jagielski }
108*b1cdbd2cSJim Jagielski
WriteRangeAddress(XclExpStream & rStrm) const109*b1cdbd2cSJim Jagielski void XclExpRangeFmlaBase::WriteRangeAddress( XclExpStream& rStrm ) const
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski maXclRange.Write( rStrm, false );
112*b1cdbd2cSJim Jagielski }
113*b1cdbd2cSJim Jagielski
114*b1cdbd2cSJim Jagielski // Array formulas =============================================================
115*b1cdbd2cSJim Jagielski
XclExpArray(XclTokenArrayRef xTokArr,const ScRange & rScRange)116*b1cdbd2cSJim Jagielski XclExpArray::XclExpArray( XclTokenArrayRef xTokArr, const ScRange& rScRange ) :
117*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase( EXC_ID3_ARRAY, 14 + xTokArr->GetSize(), rScRange ),
118*b1cdbd2cSJim Jagielski mxTokArr( xTokArr )
119*b1cdbd2cSJim Jagielski {
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski
CreateCellTokenArray(const XclExpRoot & rRoot) const122*b1cdbd2cSJim Jagielski XclTokenArrayRef XclExpArray::CreateCellTokenArray( const XclExpRoot& rRoot ) const
123*b1cdbd2cSJim Jagielski {
124*b1cdbd2cSJim Jagielski return rRoot.GetFormulaCompiler().CreateSpecialRefFormula( EXC_TOKID_EXP, maBaseXclPos );
125*b1cdbd2cSJim Jagielski }
126*b1cdbd2cSJim Jagielski
IsVolatile() const127*b1cdbd2cSJim Jagielski bool XclExpArray::IsVolatile() const
128*b1cdbd2cSJim Jagielski {
129*b1cdbd2cSJim Jagielski return mxTokArr->IsVolatile();
130*b1cdbd2cSJim Jagielski }
131*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)132*b1cdbd2cSJim Jagielski void XclExpArray::WriteBody( XclExpStream& rStrm )
133*b1cdbd2cSJim Jagielski {
134*b1cdbd2cSJim Jagielski WriteRangeAddress( rStrm );
135*b1cdbd2cSJim Jagielski sal_uInt16 nFlags = EXC_ARRAY_DEFAULTFLAGS;
136*b1cdbd2cSJim Jagielski ::set_flag( nFlags, EXC_ARRAY_RECALC_ALWAYS, IsVolatile() );
137*b1cdbd2cSJim Jagielski rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
138*b1cdbd2cSJim Jagielski }
139*b1cdbd2cSJim Jagielski
140*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
141*b1cdbd2cSJim Jagielski
XclExpArrayBuffer(const XclExpRoot & rRoot)142*b1cdbd2cSJim Jagielski XclExpArrayBuffer::XclExpArrayBuffer( const XclExpRoot& rRoot ) :
143*b1cdbd2cSJim Jagielski XclExpRoot( rRoot )
144*b1cdbd2cSJim Jagielski {
145*b1cdbd2cSJim Jagielski }
146*b1cdbd2cSJim Jagielski
CreateArray(const ScTokenArray & rScTokArr,const ScRange & rScRange)147*b1cdbd2cSJim Jagielski XclExpArrayRef XclExpArrayBuffer::CreateArray( const ScTokenArray& rScTokArr, const ScRange& rScRange )
148*b1cdbd2cSJim Jagielski {
149*b1cdbd2cSJim Jagielski const ScAddress& rScPos = rScRange.aStart;
150*b1cdbd2cSJim Jagielski XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_MATRIX, rScTokArr, &rScPos );
151*b1cdbd2cSJim Jagielski
152*b1cdbd2cSJim Jagielski DBG_ASSERT( maRecMap.find( rScPos ) == maRecMap.end(), "XclExpArrayBuffer::CreateArray - array exists already" );
153*b1cdbd2cSJim Jagielski XclExpArrayRef& rxRec = maRecMap[ rScPos ];
154*b1cdbd2cSJim Jagielski rxRec.reset( new XclExpArray( xTokArr, rScRange ) );
155*b1cdbd2cSJim Jagielski return rxRec;
156*b1cdbd2cSJim Jagielski }
157*b1cdbd2cSJim Jagielski
FindArray(const ScTokenArray & rScTokArr) const158*b1cdbd2cSJim Jagielski XclExpArrayRef XclExpArrayBuffer::FindArray( const ScTokenArray& rScTokArr ) const
159*b1cdbd2cSJim Jagielski {
160*b1cdbd2cSJim Jagielski XclExpArrayRef xRec;
161*b1cdbd2cSJim Jagielski // try to extract a matrix reference token
162*b1cdbd2cSJim Jagielski if( rScTokArr.GetLen() == 1 )
163*b1cdbd2cSJim Jagielski {
164*b1cdbd2cSJim Jagielski const formula::FormulaToken* pToken = rScTokArr.GetArray()[ 0 ];
165*b1cdbd2cSJim Jagielski if( pToken && (pToken->GetOpCode() == ocMatRef) )
166*b1cdbd2cSJim Jagielski {
167*b1cdbd2cSJim Jagielski const ScSingleRefData& rRef = static_cast<const ScToken*>(pToken)->GetSingleRef();
168*b1cdbd2cSJim Jagielski ScAddress aBasePos( rRef.nCol, rRef.nRow, GetCurrScTab() );
169*b1cdbd2cSJim Jagielski XclExpArrayMap::const_iterator aIt = maRecMap.find( aBasePos );
170*b1cdbd2cSJim Jagielski if( aIt != maRecMap.end() )
171*b1cdbd2cSJim Jagielski xRec = aIt->second;
172*b1cdbd2cSJim Jagielski }
173*b1cdbd2cSJim Jagielski }
174*b1cdbd2cSJim Jagielski return xRec;
175*b1cdbd2cSJim Jagielski }
176*b1cdbd2cSJim Jagielski
177*b1cdbd2cSJim Jagielski // Shared formulas ============================================================
178*b1cdbd2cSJim Jagielski
XclExpShrfmla(XclTokenArrayRef xTokArr,const ScAddress & rScPos)179*b1cdbd2cSJim Jagielski XclExpShrfmla::XclExpShrfmla( XclTokenArrayRef xTokArr, const ScAddress& rScPos ) :
180*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase( EXC_ID_SHRFMLA, 10 + xTokArr->GetSize(), rScPos ),
181*b1cdbd2cSJim Jagielski mxTokArr( xTokArr ),
182*b1cdbd2cSJim Jagielski mnUsedCount( 1 )
183*b1cdbd2cSJim Jagielski {
184*b1cdbd2cSJim Jagielski }
185*b1cdbd2cSJim Jagielski
ExtendRange(const ScAddress & rScPos)186*b1cdbd2cSJim Jagielski void XclExpShrfmla::ExtendRange( const ScAddress& rScPos )
187*b1cdbd2cSJim Jagielski {
188*b1cdbd2cSJim Jagielski Extend( rScPos );
189*b1cdbd2cSJim Jagielski ++mnUsedCount;
190*b1cdbd2cSJim Jagielski }
191*b1cdbd2cSJim Jagielski
CreateCellTokenArray(const XclExpRoot & rRoot) const192*b1cdbd2cSJim Jagielski XclTokenArrayRef XclExpShrfmla::CreateCellTokenArray( const XclExpRoot& rRoot ) const
193*b1cdbd2cSJim Jagielski {
194*b1cdbd2cSJim Jagielski return rRoot.GetFormulaCompiler().CreateSpecialRefFormula( EXC_TOKID_EXP, maBaseXclPos );
195*b1cdbd2cSJim Jagielski }
196*b1cdbd2cSJim Jagielski
IsVolatile() const197*b1cdbd2cSJim Jagielski bool XclExpShrfmla::IsVolatile() const
198*b1cdbd2cSJim Jagielski {
199*b1cdbd2cSJim Jagielski return mxTokArr->IsVolatile();
200*b1cdbd2cSJim Jagielski }
201*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)202*b1cdbd2cSJim Jagielski void XclExpShrfmla::WriteBody( XclExpStream& rStrm )
203*b1cdbd2cSJim Jagielski {
204*b1cdbd2cSJim Jagielski WriteRangeAddress( rStrm );
205*b1cdbd2cSJim Jagielski rStrm << sal_uInt8( 0 ) << mnUsedCount << *mxTokArr;
206*b1cdbd2cSJim Jagielski }
207*b1cdbd2cSJim Jagielski
208*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
209*b1cdbd2cSJim Jagielski
XclExpShrfmlaBuffer(const XclExpRoot & rRoot)210*b1cdbd2cSJim Jagielski XclExpShrfmlaBuffer::XclExpShrfmlaBuffer( const XclExpRoot& rRoot ) :
211*b1cdbd2cSJim Jagielski XclExpRoot( rRoot )
212*b1cdbd2cSJim Jagielski {
213*b1cdbd2cSJim Jagielski }
214*b1cdbd2cSJim Jagielski
CreateOrExtendShrfmla(const ScTokenArray & rScTokArr,const ScAddress & rScPos)215*b1cdbd2cSJim Jagielski XclExpShrfmlaRef XclExpShrfmlaBuffer::CreateOrExtendShrfmla(
216*b1cdbd2cSJim Jagielski const ScTokenArray& rScTokArr, const ScAddress& rScPos )
217*b1cdbd2cSJim Jagielski {
218*b1cdbd2cSJim Jagielski XclExpShrfmlaRef xRec;
219*b1cdbd2cSJim Jagielski if( const ScTokenArray* pShrdScTokArr = XclTokenArrayHelper::GetSharedFormula( GetRoot(), rScTokArr ) )
220*b1cdbd2cSJim Jagielski {
221*b1cdbd2cSJim Jagielski XclExpShrfmlaMap::iterator aIt = maRecMap.find( pShrdScTokArr );
222*b1cdbd2cSJim Jagielski if( aIt == maRecMap.end() )
223*b1cdbd2cSJim Jagielski {
224*b1cdbd2cSJim Jagielski // create a new record
225*b1cdbd2cSJim Jagielski XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos );
226*b1cdbd2cSJim Jagielski xRec.reset( new XclExpShrfmla( xTokArr, rScPos ) );
227*b1cdbd2cSJim Jagielski maRecMap[ pShrdScTokArr ] = xRec;
228*b1cdbd2cSJim Jagielski }
229*b1cdbd2cSJim Jagielski else
230*b1cdbd2cSJim Jagielski {
231*b1cdbd2cSJim Jagielski // extend existing record
232*b1cdbd2cSJim Jagielski DBG_ASSERT( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" );
233*b1cdbd2cSJim Jagielski xRec = aIt->second;
234*b1cdbd2cSJim Jagielski xRec->ExtendRange( rScPos );
235*b1cdbd2cSJim Jagielski }
236*b1cdbd2cSJim Jagielski }
237*b1cdbd2cSJim Jagielski return xRec;
238*b1cdbd2cSJim Jagielski }
239*b1cdbd2cSJim Jagielski
240*b1cdbd2cSJim Jagielski // Multiple operations ========================================================
241*b1cdbd2cSJim Jagielski
XclExpTableop(const ScAddress & rScPos,const XclMultipleOpRefs & rRefs,sal_uInt8 nScMode)242*b1cdbd2cSJim Jagielski XclExpTableop::XclExpTableop( const ScAddress& rScPos,
243*b1cdbd2cSJim Jagielski const XclMultipleOpRefs& rRefs, sal_uInt8 nScMode ) :
244*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase( EXC_ID3_TABLEOP, 16, rScPos ),
245*b1cdbd2cSJim Jagielski mnLastAppXclCol( static_cast< sal_uInt16 >( rScPos.Col() ) ),
246*b1cdbd2cSJim Jagielski mnColInpXclCol( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Col() ) ),
247*b1cdbd2cSJim Jagielski mnColInpXclRow( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Row() ) ),
248*b1cdbd2cSJim Jagielski mnRowInpXclCol( static_cast< sal_uInt16 >( rRefs.maRowFirstScPos.Col() ) ),
249*b1cdbd2cSJim Jagielski mnRowInpXclRow( static_cast< sal_uInt16 >( rRefs.maRowFirstScPos.Row() ) ),
250*b1cdbd2cSJim Jagielski mnScMode( nScMode ),
251*b1cdbd2cSJim Jagielski mbValid( false )
252*b1cdbd2cSJim Jagielski {
253*b1cdbd2cSJim Jagielski }
254*b1cdbd2cSJim Jagielski
TryExtend(const ScAddress & rScPos,const XclMultipleOpRefs & rRefs)255*b1cdbd2cSJim Jagielski bool XclExpTableop::TryExtend( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs )
256*b1cdbd2cSJim Jagielski {
257*b1cdbd2cSJim Jagielski sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
258*b1cdbd2cSJim Jagielski sal_uInt16 nXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
259*b1cdbd2cSJim Jagielski
260*b1cdbd2cSJim Jagielski bool bOk = IsAppendable( nXclCol, nXclRow );
261*b1cdbd2cSJim Jagielski if( bOk )
262*b1cdbd2cSJim Jagielski {
263*b1cdbd2cSJim Jagielski SCCOL nFirstScCol = static_cast< SCCOL >( maXclRange.maFirst.mnCol );
264*b1cdbd2cSJim Jagielski SCROW nFirstScRow = static_cast< SCROW >( maXclRange.maFirst.mnRow );
265*b1cdbd2cSJim Jagielski SCCOL nColInpScCol = static_cast< SCCOL >( mnColInpXclCol );
266*b1cdbd2cSJim Jagielski SCROW nColInpScRow = static_cast< SCROW >( mnColInpXclRow );
267*b1cdbd2cSJim Jagielski SCCOL nRowInpScCol = static_cast< SCCOL >( mnRowInpXclCol );
268*b1cdbd2cSJim Jagielski SCROW nRowInpScRow = static_cast< SCROW >( mnRowInpXclRow );
269*b1cdbd2cSJim Jagielski
270*b1cdbd2cSJim Jagielski bOk = ((mnScMode == 2) == rRefs.mbDblRefMode) &&
271*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maFmlaScPos.Tab()) &&
272*b1cdbd2cSJim Jagielski (nColInpScCol == rRefs.maColFirstScPos.Col()) &&
273*b1cdbd2cSJim Jagielski (nColInpScRow == rRefs.maColFirstScPos.Row()) &&
274*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maColFirstScPos.Tab()) &&
275*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maColRelScPos.Tab());
276*b1cdbd2cSJim Jagielski
277*b1cdbd2cSJim Jagielski if( bOk ) switch( mnScMode )
278*b1cdbd2cSJim Jagielski {
279*b1cdbd2cSJim Jagielski case 0:
280*b1cdbd2cSJim Jagielski bOk = (rScPos.Col() == rRefs.maFmlaScPos.Col()) &&
281*b1cdbd2cSJim Jagielski (nFirstScRow == rRefs.maFmlaScPos.Row() + 1) &&
282*b1cdbd2cSJim Jagielski (nFirstScCol == rRefs.maColRelScPos.Col() + 1) &&
283*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maColRelScPos.Row());
284*b1cdbd2cSJim Jagielski break;
285*b1cdbd2cSJim Jagielski case 1:
286*b1cdbd2cSJim Jagielski bOk = (nFirstScCol == rRefs.maFmlaScPos.Col() + 1) &&
287*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maFmlaScPos.Row()) &&
288*b1cdbd2cSJim Jagielski (rScPos.Col() == rRefs.maColRelScPos.Col()) &&
289*b1cdbd2cSJim Jagielski (nFirstScRow == rRefs.maColRelScPos.Row() + 1);
290*b1cdbd2cSJim Jagielski break;
291*b1cdbd2cSJim Jagielski case 2:
292*b1cdbd2cSJim Jagielski bOk = (nFirstScCol == rRefs.maFmlaScPos.Col() + 1) &&
293*b1cdbd2cSJim Jagielski (nFirstScRow == rRefs.maFmlaScPos.Row() + 1) &&
294*b1cdbd2cSJim Jagielski (nFirstScCol == rRefs.maColRelScPos.Col() + 1) &&
295*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maColRelScPos.Row()) &&
296*b1cdbd2cSJim Jagielski (nRowInpScCol == rRefs.maRowFirstScPos.Col()) &&
297*b1cdbd2cSJim Jagielski (nRowInpScRow == rRefs.maRowFirstScPos.Row()) &&
298*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maRowFirstScPos.Tab()) &&
299*b1cdbd2cSJim Jagielski (rScPos.Col() == rRefs.maRowRelScPos.Col()) &&
300*b1cdbd2cSJim Jagielski (nFirstScRow == rRefs.maRowRelScPos.Row() + 1) &&
301*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maRowRelScPos.Tab());
302*b1cdbd2cSJim Jagielski break;
303*b1cdbd2cSJim Jagielski default:
304*b1cdbd2cSJim Jagielski bOk = false;
305*b1cdbd2cSJim Jagielski }
306*b1cdbd2cSJim Jagielski
307*b1cdbd2cSJim Jagielski if( bOk )
308*b1cdbd2cSJim Jagielski {
309*b1cdbd2cSJim Jagielski // extend the cell range
310*b1cdbd2cSJim Jagielski DBG_ASSERT( IsAppendable( nXclCol, nXclRow ), "XclExpTableop::TryExtend - wrong cell address" );
311*b1cdbd2cSJim Jagielski Extend( rScPos );
312*b1cdbd2cSJim Jagielski mnLastAppXclCol = nXclCol;
313*b1cdbd2cSJim Jagielski }
314*b1cdbd2cSJim Jagielski }
315*b1cdbd2cSJim Jagielski
316*b1cdbd2cSJim Jagielski return bOk;
317*b1cdbd2cSJim Jagielski }
318*b1cdbd2cSJim Jagielski
Finalize()319*b1cdbd2cSJim Jagielski void XclExpTableop::Finalize()
320*b1cdbd2cSJim Jagielski {
321*b1cdbd2cSJim Jagielski // is the range complete? (last appended cell is in last column)
322*b1cdbd2cSJim Jagielski mbValid = maXclRange.maLast.mnCol == mnLastAppXclCol;
323*b1cdbd2cSJim Jagielski // if last row is incomplete, try to shorten the used range
324*b1cdbd2cSJim Jagielski if( !mbValid && (maXclRange.maFirst.mnRow < maXclRange.maLast.mnRow) )
325*b1cdbd2cSJim Jagielski {
326*b1cdbd2cSJim Jagielski --maXclRange.maLast.mnRow;
327*b1cdbd2cSJim Jagielski mbValid = true;
328*b1cdbd2cSJim Jagielski }
329*b1cdbd2cSJim Jagielski
330*b1cdbd2cSJim Jagielski // check if referred cells are outside of own range
331*b1cdbd2cSJim Jagielski if( mbValid ) switch( mnScMode )
332*b1cdbd2cSJim Jagielski {
333*b1cdbd2cSJim Jagielski case 0:
334*b1cdbd2cSJim Jagielski mbValid = (mnColInpXclCol + 1 < maXclRange.maFirst.mnCol) || (mnColInpXclCol > maXclRange.maLast.mnCol) ||
335*b1cdbd2cSJim Jagielski (mnColInpXclRow < maXclRange.maFirst.mnRow) || (mnColInpXclRow > maXclRange.maLast.mnRow);
336*b1cdbd2cSJim Jagielski break;
337*b1cdbd2cSJim Jagielski case 1:
338*b1cdbd2cSJim Jagielski mbValid = (mnColInpXclCol < maXclRange.maFirst.mnCol) || (mnColInpXclCol > maXclRange.maLast.mnCol) ||
339*b1cdbd2cSJim Jagielski (mnColInpXclRow + 1 < maXclRange.maFirst.mnRow) || (mnColInpXclRow > maXclRange.maLast.mnRow);
340*b1cdbd2cSJim Jagielski break;
341*b1cdbd2cSJim Jagielski case 2:
342*b1cdbd2cSJim Jagielski mbValid = ((mnColInpXclCol + 1 < maXclRange.maFirst.mnCol) || (mnColInpXclCol > maXclRange.maLast.mnCol) ||
343*b1cdbd2cSJim Jagielski (mnColInpXclRow + 1 < maXclRange.maFirst.mnRow) || (mnColInpXclRow > maXclRange.maLast.mnRow)) &&
344*b1cdbd2cSJim Jagielski ((mnRowInpXclCol + 1 < maXclRange.maFirst.mnCol) || (mnRowInpXclCol > maXclRange.maLast.mnCol) ||
345*b1cdbd2cSJim Jagielski (mnRowInpXclRow + 1 < maXclRange.maFirst.mnRow) || (mnRowInpXclRow > maXclRange.maLast.mnRow));
346*b1cdbd2cSJim Jagielski break;
347*b1cdbd2cSJim Jagielski }
348*b1cdbd2cSJim Jagielski }
349*b1cdbd2cSJim Jagielski
CreateCellTokenArray(const XclExpRoot & rRoot) const350*b1cdbd2cSJim Jagielski XclTokenArrayRef XclExpTableop::CreateCellTokenArray( const XclExpRoot& rRoot ) const
351*b1cdbd2cSJim Jagielski {
352*b1cdbd2cSJim Jagielski XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
353*b1cdbd2cSJim Jagielski return mbValid ?
354*b1cdbd2cSJim Jagielski rFmlaComp.CreateSpecialRefFormula( EXC_TOKID_TBL, maBaseXclPos ) :
355*b1cdbd2cSJim Jagielski rFmlaComp.CreateErrorFormula( EXC_ERR_NA );
356*b1cdbd2cSJim Jagielski }
357*b1cdbd2cSJim Jagielski
IsVolatile() const358*b1cdbd2cSJim Jagielski bool XclExpTableop::IsVolatile() const
359*b1cdbd2cSJim Jagielski {
360*b1cdbd2cSJim Jagielski return true;
361*b1cdbd2cSJim Jagielski }
362*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)363*b1cdbd2cSJim Jagielski void XclExpTableop::Save( XclExpStream& rStrm )
364*b1cdbd2cSJim Jagielski {
365*b1cdbd2cSJim Jagielski if( mbValid )
366*b1cdbd2cSJim Jagielski XclExpRangeFmlaBase::Save( rStrm );
367*b1cdbd2cSJim Jagielski }
368*b1cdbd2cSJim Jagielski
IsAppendable(sal_uInt16 nXclCol,sal_uInt16 nXclRow) const369*b1cdbd2cSJim Jagielski bool XclExpTableop::IsAppendable( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
370*b1cdbd2cSJim Jagielski {
371*b1cdbd2cSJim Jagielski return ((nXclCol == mnLastAppXclCol + 1) && (nXclRow == maXclRange.maFirst.mnRow)) ||
372*b1cdbd2cSJim Jagielski ((nXclCol == mnLastAppXclCol + 1) && (nXclCol <= maXclRange.maLast.mnCol) && (nXclRow == maXclRange.maLast.mnRow)) ||
373*b1cdbd2cSJim Jagielski ((mnLastAppXclCol == maXclRange.maLast.mnCol) && (nXclCol == maXclRange.maFirst.mnCol) && (nXclRow == maXclRange.maLast.mnRow + 1));
374*b1cdbd2cSJim Jagielski }
375*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)376*b1cdbd2cSJim Jagielski void XclExpTableop::WriteBody( XclExpStream& rStrm )
377*b1cdbd2cSJim Jagielski {
378*b1cdbd2cSJim Jagielski sal_uInt16 nFlags = EXC_TABLEOP_DEFAULTFLAGS;
379*b1cdbd2cSJim Jagielski ::set_flag( nFlags, EXC_TABLEOP_RECALC_ALWAYS, IsVolatile() );
380*b1cdbd2cSJim Jagielski switch( mnScMode )
381*b1cdbd2cSJim Jagielski {
382*b1cdbd2cSJim Jagielski case 1: ::set_flag( nFlags, EXC_TABLEOP_ROW ); break;
383*b1cdbd2cSJim Jagielski case 2: ::set_flag( nFlags, EXC_TABLEOP_BOTH ); break;
384*b1cdbd2cSJim Jagielski }
385*b1cdbd2cSJim Jagielski
386*b1cdbd2cSJim Jagielski WriteRangeAddress( rStrm );
387*b1cdbd2cSJim Jagielski rStrm << nFlags;
388*b1cdbd2cSJim Jagielski if( mnScMode == 2 )
389*b1cdbd2cSJim Jagielski rStrm << mnRowInpXclRow << mnRowInpXclCol << mnColInpXclRow << mnColInpXclCol;
390*b1cdbd2cSJim Jagielski else
391*b1cdbd2cSJim Jagielski rStrm << mnColInpXclRow << mnColInpXclCol << sal_uInt32( 0 );
392*b1cdbd2cSJim Jagielski }
393*b1cdbd2cSJim Jagielski
394*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
395*b1cdbd2cSJim Jagielski
XclExpTableopBuffer(const XclExpRoot & rRoot)396*b1cdbd2cSJim Jagielski XclExpTableopBuffer::XclExpTableopBuffer( const XclExpRoot& rRoot ) :
397*b1cdbd2cSJim Jagielski XclExpRoot( rRoot )
398*b1cdbd2cSJim Jagielski {
399*b1cdbd2cSJim Jagielski }
400*b1cdbd2cSJim Jagielski
CreateOrExtendTableop(const ScTokenArray & rScTokArr,const ScAddress & rScPos)401*b1cdbd2cSJim Jagielski XclExpTableopRef XclExpTableopBuffer::CreateOrExtendTableop(
402*b1cdbd2cSJim Jagielski const ScTokenArray& rScTokArr, const ScAddress& rScPos )
403*b1cdbd2cSJim Jagielski {
404*b1cdbd2cSJim Jagielski XclExpTableopRef xRec;
405*b1cdbd2cSJim Jagielski
406*b1cdbd2cSJim Jagielski // try to extract cell references of a multiple operations formula
407*b1cdbd2cSJim Jagielski XclMultipleOpRefs aRefs;
408*b1cdbd2cSJim Jagielski if( XclTokenArrayHelper::GetMultipleOpRefs( aRefs, rScTokArr ) )
409*b1cdbd2cSJim Jagielski {
410*b1cdbd2cSJim Jagielski // try to find an existing TABLEOP record for this cell position
411*b1cdbd2cSJim Jagielski for( size_t nPos = 0, nSize = maTableopList.GetSize(); !xRec && (nPos < nSize); ++nPos )
412*b1cdbd2cSJim Jagielski {
413*b1cdbd2cSJim Jagielski XclExpTableopRef xTempRec = maTableopList.GetRecord( nPos );
414*b1cdbd2cSJim Jagielski if( xTempRec->TryExtend( rScPos, aRefs ) )
415*b1cdbd2cSJim Jagielski xRec = xTempRec;
416*b1cdbd2cSJim Jagielski }
417*b1cdbd2cSJim Jagielski
418*b1cdbd2cSJim Jagielski // no record found, or found record not extensible
419*b1cdbd2cSJim Jagielski if( !xRec )
420*b1cdbd2cSJim Jagielski xRec = TryCreate( rScPos, aRefs );
421*b1cdbd2cSJim Jagielski }
422*b1cdbd2cSJim Jagielski
423*b1cdbd2cSJim Jagielski return xRec;
424*b1cdbd2cSJim Jagielski }
425*b1cdbd2cSJim Jagielski
Finalize()426*b1cdbd2cSJim Jagielski void XclExpTableopBuffer::Finalize()
427*b1cdbd2cSJim Jagielski {
428*b1cdbd2cSJim Jagielski for( size_t nPos = 0, nSize = maTableopList.GetSize(); nPos < nSize; ++nPos )
429*b1cdbd2cSJim Jagielski maTableopList.GetRecord( nPos )->Finalize();
430*b1cdbd2cSJim Jagielski }
431*b1cdbd2cSJim Jagielski
TryCreate(const ScAddress & rScPos,const XclMultipleOpRefs & rRefs)432*b1cdbd2cSJim Jagielski XclExpTableopRef XclExpTableopBuffer::TryCreate( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs )
433*b1cdbd2cSJim Jagielski {
434*b1cdbd2cSJim Jagielski sal_uInt8 nScMode = 0;
435*b1cdbd2cSJim Jagielski bool bOk = (rScPos.Tab() == rRefs.maFmlaScPos.Tab()) &&
436*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maColFirstScPos.Tab()) &&
437*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maColRelScPos.Tab());
438*b1cdbd2cSJim Jagielski
439*b1cdbd2cSJim Jagielski if( bOk )
440*b1cdbd2cSJim Jagielski {
441*b1cdbd2cSJim Jagielski if( rRefs.mbDblRefMode )
442*b1cdbd2cSJim Jagielski {
443*b1cdbd2cSJim Jagielski nScMode = 2;
444*b1cdbd2cSJim Jagielski bOk = (rScPos.Col() == rRefs.maFmlaScPos.Col() + 1) &&
445*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maFmlaScPos.Row() + 1) &&
446*b1cdbd2cSJim Jagielski (rScPos.Col() == rRefs.maColRelScPos.Col() + 1) &&
447*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maColRelScPos.Row()) &&
448*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maRowFirstScPos.Tab()) &&
449*b1cdbd2cSJim Jagielski (rScPos.Col() == rRefs.maRowRelScPos.Col()) &&
450*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maRowRelScPos.Row() + 1) &&
451*b1cdbd2cSJim Jagielski (rScPos.Tab() == rRefs.maRowRelScPos.Tab());
452*b1cdbd2cSJim Jagielski }
453*b1cdbd2cSJim Jagielski else if( (rScPos.Col() == rRefs.maFmlaScPos.Col()) &&
454*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maFmlaScPos.Row() + 1) &&
455*b1cdbd2cSJim Jagielski (rScPos.Col() == rRefs.maColRelScPos.Col() + 1) &&
456*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maColRelScPos.Row()) )
457*b1cdbd2cSJim Jagielski {
458*b1cdbd2cSJim Jagielski nScMode = 0;
459*b1cdbd2cSJim Jagielski }
460*b1cdbd2cSJim Jagielski else if( (rScPos.Col() == rRefs.maFmlaScPos.Col() + 1) &&
461*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maFmlaScPos.Row()) &&
462*b1cdbd2cSJim Jagielski (rScPos.Col() == rRefs.maColRelScPos.Col()) &&
463*b1cdbd2cSJim Jagielski (rScPos.Row() == rRefs.maColRelScPos.Row() + 1) )
464*b1cdbd2cSJim Jagielski {
465*b1cdbd2cSJim Jagielski nScMode = 1;
466*b1cdbd2cSJim Jagielski }
467*b1cdbd2cSJim Jagielski else
468*b1cdbd2cSJim Jagielski {
469*b1cdbd2cSJim Jagielski bOk = false;
470*b1cdbd2cSJim Jagielski }
471*b1cdbd2cSJim Jagielski }
472*b1cdbd2cSJim Jagielski
473*b1cdbd2cSJim Jagielski XclExpTableopRef xRec;
474*b1cdbd2cSJim Jagielski if( bOk )
475*b1cdbd2cSJim Jagielski {
476*b1cdbd2cSJim Jagielski xRec.reset( new XclExpTableop( rScPos, rRefs, nScMode ) );
477*b1cdbd2cSJim Jagielski maTableopList.AppendRecord( xRec );
478*b1cdbd2cSJim Jagielski }
479*b1cdbd2cSJim Jagielski
480*b1cdbd2cSJim Jagielski return xRec;
481*b1cdbd2cSJim Jagielski }
482*b1cdbd2cSJim Jagielski
483*b1cdbd2cSJim Jagielski // ============================================================================
484*b1cdbd2cSJim Jagielski // Cell records
485*b1cdbd2cSJim Jagielski // ============================================================================
486*b1cdbd2cSJim Jagielski
XclExpCellBase(sal_uInt16 nRecId,sal_Size nContSize,const XclAddress & rXclPos)487*b1cdbd2cSJim Jagielski XclExpCellBase::XclExpCellBase(
488*b1cdbd2cSJim Jagielski sal_uInt16 nRecId, sal_Size nContSize, const XclAddress& rXclPos ) :
489*b1cdbd2cSJim Jagielski XclExpRecord( nRecId, nContSize + 4 ),
490*b1cdbd2cSJim Jagielski maXclPos( rXclPos )
491*b1cdbd2cSJim Jagielski {
492*b1cdbd2cSJim Jagielski }
493*b1cdbd2cSJim Jagielski
IsMultiLineText() const494*b1cdbd2cSJim Jagielski bool XclExpCellBase::IsMultiLineText() const
495*b1cdbd2cSJim Jagielski {
496*b1cdbd2cSJim Jagielski return false;
497*b1cdbd2cSJim Jagielski }
498*b1cdbd2cSJim Jagielski
TryMerge(const XclExpCellBase &)499*b1cdbd2cSJim Jagielski bool XclExpCellBase::TryMerge( const XclExpCellBase& /*rCell*/ )
500*b1cdbd2cSJim Jagielski {
501*b1cdbd2cSJim Jagielski return false;
502*b1cdbd2cSJim Jagielski }
503*b1cdbd2cSJim Jagielski
GetBlankXFIndexes(ScfUInt16Vec &) const504*b1cdbd2cSJim Jagielski void XclExpCellBase::GetBlankXFIndexes( ScfUInt16Vec& /*rXFIndexes*/ ) const
505*b1cdbd2cSJim Jagielski {
506*b1cdbd2cSJim Jagielski // default: do nothing
507*b1cdbd2cSJim Jagielski }
508*b1cdbd2cSJim Jagielski
RemoveUnusedBlankCells(const ScfUInt16Vec &)509*b1cdbd2cSJim Jagielski void XclExpCellBase::RemoveUnusedBlankCells( const ScfUInt16Vec& /*rXFIndexes*/ )
510*b1cdbd2cSJim Jagielski {
511*b1cdbd2cSJim Jagielski // default: do nothing
512*b1cdbd2cSJim Jagielski }
513*b1cdbd2cSJim Jagielski
514*b1cdbd2cSJim Jagielski // Single cell records ========================================================
515*b1cdbd2cSJim Jagielski
XclExpSingleCellBase(sal_uInt16 nRecId,sal_Size nContSize,const XclAddress & rXclPos,sal_uInt32 nXFId)516*b1cdbd2cSJim Jagielski XclExpSingleCellBase::XclExpSingleCellBase(
517*b1cdbd2cSJim Jagielski sal_uInt16 nRecId, sal_Size nContSize, const XclAddress& rXclPos, sal_uInt32 nXFId ) :
518*b1cdbd2cSJim Jagielski XclExpCellBase( nRecId, 2, rXclPos ),
519*b1cdbd2cSJim Jagielski maXFId( nXFId ),
520*b1cdbd2cSJim Jagielski mnContSize( nContSize )
521*b1cdbd2cSJim Jagielski {
522*b1cdbd2cSJim Jagielski }
523*b1cdbd2cSJim Jagielski
XclExpSingleCellBase(const XclExpRoot & rRoot,sal_uInt16 nRecId,sal_Size nContSize,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_Int16 nScript,sal_uInt32 nForcedXFId)524*b1cdbd2cSJim Jagielski XclExpSingleCellBase::XclExpSingleCellBase( const XclExpRoot& rRoot,
525*b1cdbd2cSJim Jagielski sal_uInt16 nRecId, sal_Size nContSize, const XclAddress& rXclPos,
526*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uInt32 nForcedXFId ) :
527*b1cdbd2cSJim Jagielski XclExpCellBase( nRecId, 2, rXclPos ),
528*b1cdbd2cSJim Jagielski maXFId( nForcedXFId ),
529*b1cdbd2cSJim Jagielski mnContSize( nContSize )
530*b1cdbd2cSJim Jagielski {
531*b1cdbd2cSJim Jagielski if( GetXFId() == EXC_XFID_NOTFOUND )
532*b1cdbd2cSJim Jagielski SetXFId( rRoot.GetXFBuffer().Insert( pPattern, nScript ) );
533*b1cdbd2cSJim Jagielski }
534*b1cdbd2cSJim Jagielski
GetLastXclCol() const535*b1cdbd2cSJim Jagielski sal_uInt16 XclExpSingleCellBase::GetLastXclCol() const
536*b1cdbd2cSJim Jagielski {
537*b1cdbd2cSJim Jagielski return GetXclCol();
538*b1cdbd2cSJim Jagielski }
539*b1cdbd2cSJim Jagielski
GetFirstXFId() const540*b1cdbd2cSJim Jagielski sal_uInt32 XclExpSingleCellBase::GetFirstXFId() const
541*b1cdbd2cSJim Jagielski {
542*b1cdbd2cSJim Jagielski return GetXFId();
543*b1cdbd2cSJim Jagielski }
544*b1cdbd2cSJim Jagielski
IsEmpty() const545*b1cdbd2cSJim Jagielski bool XclExpSingleCellBase::IsEmpty() const
546*b1cdbd2cSJim Jagielski {
547*b1cdbd2cSJim Jagielski return false;
548*b1cdbd2cSJim Jagielski }
549*b1cdbd2cSJim Jagielski
ConvertXFIndexes(const XclExpRoot & rRoot)550*b1cdbd2cSJim Jagielski void XclExpSingleCellBase::ConvertXFIndexes( const XclExpRoot& rRoot )
551*b1cdbd2cSJim Jagielski {
552*b1cdbd2cSJim Jagielski maXFId.ConvertXFIndex( rRoot );
553*b1cdbd2cSJim Jagielski }
554*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)555*b1cdbd2cSJim Jagielski void XclExpSingleCellBase::Save( XclExpStream& rStrm )
556*b1cdbd2cSJim Jagielski {
557*b1cdbd2cSJim Jagielski DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
558*b1cdbd2cSJim Jagielski AddRecSize( mnContSize );
559*b1cdbd2cSJim Jagielski XclExpCellBase::Save( rStrm );
560*b1cdbd2cSJim Jagielski }
561*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)562*b1cdbd2cSJim Jagielski void XclExpSingleCellBase::WriteBody( XclExpStream& rStrm )
563*b1cdbd2cSJim Jagielski {
564*b1cdbd2cSJim Jagielski rStrm << GetXclRow() << GetXclCol() << maXFId.mnXFIndex;
565*b1cdbd2cSJim Jagielski WriteContents( rStrm );
566*b1cdbd2cSJim Jagielski }
567*b1cdbd2cSJim Jagielski
568*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
569*b1cdbd2cSJim Jagielski
570*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpNumberCell, 256, 256 )
571*b1cdbd2cSJim Jagielski
XclExpNumberCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,double fValue)572*b1cdbd2cSJim Jagielski XclExpNumberCell::XclExpNumberCell(
573*b1cdbd2cSJim Jagielski const XclExpRoot& rRoot, const XclAddress& rXclPos,
574*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, double fValue ) :
575*b1cdbd2cSJim Jagielski // #i41210# always use latin script for number cells - may look wrong for special number formats...
576*b1cdbd2cSJim Jagielski XclExpSingleCellBase( rRoot, EXC_ID3_NUMBER, 8, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
577*b1cdbd2cSJim Jagielski mfValue( fValue )
578*b1cdbd2cSJim Jagielski {
579*b1cdbd2cSJim Jagielski }
580*b1cdbd2cSJim Jagielski
lcl_GetStyleId(XclExpXmlStream & rStrm,sal_uInt32 nXFIndex)581*b1cdbd2cSJim Jagielski static OString lcl_GetStyleId( XclExpXmlStream& rStrm, sal_uInt32 nXFIndex )
582*b1cdbd2cSJim Jagielski {
583*b1cdbd2cSJim Jagielski return OString::valueOf( rStrm.GetRoot().GetXFBuffer()
584*b1cdbd2cSJim Jagielski .GetXmlCellIndex( nXFIndex ) );
585*b1cdbd2cSJim Jagielski }
586*b1cdbd2cSJim Jagielski
lcl_GetStyleId(XclExpXmlStream & rStrm,const XclExpCellBase & rCell)587*b1cdbd2cSJim Jagielski static OString lcl_GetStyleId( XclExpXmlStream& rStrm, const XclExpCellBase& rCell )
588*b1cdbd2cSJim Jagielski {
589*b1cdbd2cSJim Jagielski sal_uInt32 nXFId = rCell.GetFirstXFId();
590*b1cdbd2cSJim Jagielski sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( nXFId );
591*b1cdbd2cSJim Jagielski return lcl_GetStyleId( rStrm, nXFIndex );
592*b1cdbd2cSJim Jagielski }
593*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)594*b1cdbd2cSJim Jagielski void XclExpNumberCell::SaveXml( XclExpXmlStream& rStrm )
595*b1cdbd2cSJim Jagielski {
596*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
597*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_c,
598*b1cdbd2cSJim Jagielski XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(),
599*b1cdbd2cSJim Jagielski XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
600*b1cdbd2cSJim Jagielski XML_t, "n",
601*b1cdbd2cSJim Jagielski // OOXTODO: XML_cm, XML_vm, XML_ph
602*b1cdbd2cSJim Jagielski FSEND );
603*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_v, FSEND );
604*b1cdbd2cSJim Jagielski rWorksheet->write( mfValue );
605*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_v );
606*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_c );
607*b1cdbd2cSJim Jagielski }
608*b1cdbd2cSJim Jagielski
WriteContents(XclExpStream & rStrm)609*b1cdbd2cSJim Jagielski void XclExpNumberCell::WriteContents( XclExpStream& rStrm )
610*b1cdbd2cSJim Jagielski {
611*b1cdbd2cSJim Jagielski rStrm << mfValue;
612*b1cdbd2cSJim Jagielski }
613*b1cdbd2cSJim Jagielski
614*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
615*b1cdbd2cSJim Jagielski
616*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpBooleanCell, 256, 256 )
617*b1cdbd2cSJim Jagielski
XclExpBooleanCell(const XclExpRoot rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,bool bValue)618*b1cdbd2cSJim Jagielski XclExpBooleanCell::XclExpBooleanCell(
619*b1cdbd2cSJim Jagielski const XclExpRoot rRoot, const XclAddress& rXclPos,
620*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, bool bValue ) :
621*b1cdbd2cSJim Jagielski // #i41210# always use latin script for boolean cells
622*b1cdbd2cSJim Jagielski XclExpSingleCellBase( rRoot, EXC_ID3_BOOLERR, 2, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
623*b1cdbd2cSJim Jagielski mbValue( bValue )
624*b1cdbd2cSJim Jagielski {
625*b1cdbd2cSJim Jagielski }
626*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)627*b1cdbd2cSJim Jagielski void XclExpBooleanCell::SaveXml( XclExpXmlStream& rStrm )
628*b1cdbd2cSJim Jagielski {
629*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
630*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_c,
631*b1cdbd2cSJim Jagielski XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(),
632*b1cdbd2cSJim Jagielski XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
633*b1cdbd2cSJim Jagielski XML_t, "b",
634*b1cdbd2cSJim Jagielski // OOXTODO: XML_cm, XML_vm, XML_ph
635*b1cdbd2cSJim Jagielski FSEND );
636*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_v, FSEND );
637*b1cdbd2cSJim Jagielski rWorksheet->write( mbValue ? "1" : "0" );
638*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_v );
639*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_c );
640*b1cdbd2cSJim Jagielski }
641*b1cdbd2cSJim Jagielski
WriteContents(XclExpStream & rStrm)642*b1cdbd2cSJim Jagielski void XclExpBooleanCell::WriteContents( XclExpStream& rStrm )
643*b1cdbd2cSJim Jagielski {
644*b1cdbd2cSJim Jagielski rStrm << sal_uInt16( mbValue ? 1 : 0 ) << EXC_BOOLERR_BOOL;
645*b1cdbd2cSJim Jagielski }
646*b1cdbd2cSJim Jagielski
647*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
648*b1cdbd2cSJim Jagielski
649*b1cdbd2cSJim Jagielski //UNUSED2009-05 IMPL_FIXEDMEMPOOL_NEWDEL( XclExpErrorCell, 256, 256 )
650*b1cdbd2cSJim Jagielski //UNUSED2009-05
651*b1cdbd2cSJim Jagielski //UNUSED2009-05 XclExpErrorCell::XclExpErrorCell(
652*b1cdbd2cSJim Jagielski //UNUSED2009-05 const XclExpRoot rRoot, const XclAddress& rXclPos,
653*b1cdbd2cSJim Jagielski //UNUSED2009-05 const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, sal_uInt8 nErrCode ) :
654*b1cdbd2cSJim Jagielski //UNUSED2009-05 // #i41210# always use latin script for error cells
655*b1cdbd2cSJim Jagielski //UNUSED2009-05 XclExpSingleCellBase( rRoot, EXC_ID3_BOOLERR, 2, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
656*b1cdbd2cSJim Jagielski //UNUSED2009-05 mnErrCode( nErrCode )
657*b1cdbd2cSJim Jagielski //UNUSED2009-05 {
658*b1cdbd2cSJim Jagielski //UNUSED2009-05 }
659*b1cdbd2cSJim Jagielski //UNUSED2009-05
660*b1cdbd2cSJim Jagielski //UNUSED2009-05 void XclExpErrorCell::SaveXml( XclExpXmlStream& rStrm )
661*b1cdbd2cSJim Jagielski //UNUSED2009-05 {
662*b1cdbd2cSJim Jagielski //UNUSED2009-05 sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
663*b1cdbd2cSJim Jagielski //UNUSED2009-05 rWorksheet->startElement( XML_c,
664*b1cdbd2cSJim Jagielski //UNUSED2009-05 XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(),
665*b1cdbd2cSJim Jagielski //UNUSED2009-05 XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
666*b1cdbd2cSJim Jagielski //UNUSED2009-05 XML_t, "e",
667*b1cdbd2cSJim Jagielski //UNUSED2009-05 // OOXTODO: XML_cm, XML_vm, XML_ph
668*b1cdbd2cSJim Jagielski //UNUSED2009-05 FSEND );
669*b1cdbd2cSJim Jagielski //UNUSED2009-05 rWorksheet->startElement( XML_v, FSEND );
670*b1cdbd2cSJim Jagielski //UNUSED2009-05 rWorksheet->write( (sal_Int32) mnErrCode );
671*b1cdbd2cSJim Jagielski //UNUSED2009-05 rWorksheet->endElement( XML_v );
672*b1cdbd2cSJim Jagielski //UNUSED2009-05 rWorksheet->endElement( XML_c );
673*b1cdbd2cSJim Jagielski //UNUSED2009-05 }
674*b1cdbd2cSJim Jagielski //UNUSED2009-05
675*b1cdbd2cSJim Jagielski //UNUSED2009-05 void XclExpErrorCell::WriteContents( XclExpStream& rStrm )
676*b1cdbd2cSJim Jagielski //UNUSED2009-05 {
677*b1cdbd2cSJim Jagielski //UNUSED2009-05 rStrm << mnErrCode << EXC_BOOLERR_ERROR;
678*b1cdbd2cSJim Jagielski //UNUSED2009-05 }
679*b1cdbd2cSJim Jagielski
680*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
681*b1cdbd2cSJim Jagielski
682*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpLabelCell, 256, 256 )
683*b1cdbd2cSJim Jagielski
XclExpLabelCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,const ScStringCell & rCell)684*b1cdbd2cSJim Jagielski XclExpLabelCell::XclExpLabelCell(
685*b1cdbd2cSJim Jagielski const XclExpRoot& rRoot, const XclAddress& rXclPos,
686*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, const ScStringCell& rCell ) :
687*b1cdbd2cSJim Jagielski XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
688*b1cdbd2cSJim Jagielski {
689*b1cdbd2cSJim Jagielski sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
690*b1cdbd2cSJim Jagielski XclExpStringRef xText = XclExpStringHelper::CreateCellString( rRoot, rCell, pPattern, EXC_STR_DEFAULT, nMaxLen );
691*b1cdbd2cSJim Jagielski Init( rRoot, pPattern, xText );
692*b1cdbd2cSJim Jagielski }
693*b1cdbd2cSJim Jagielski
XclExpLabelCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,const ScEditCell & rCell,XclExpHyperlinkHelper & rLinkHelper)694*b1cdbd2cSJim Jagielski XclExpLabelCell::XclExpLabelCell(
695*b1cdbd2cSJim Jagielski const XclExpRoot& rRoot, const XclAddress& rXclPos,
696*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
697*b1cdbd2cSJim Jagielski const ScEditCell& rCell, XclExpHyperlinkHelper& rLinkHelper ) :
698*b1cdbd2cSJim Jagielski XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
699*b1cdbd2cSJim Jagielski {
700*b1cdbd2cSJim Jagielski sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
701*b1cdbd2cSJim Jagielski XclExpStringRef xText = XclExpStringHelper::CreateCellString( rRoot, rCell, pPattern, rLinkHelper, EXC_STR_DEFAULT, nMaxLen );
702*b1cdbd2cSJim Jagielski Init( rRoot, pPattern, xText );
703*b1cdbd2cSJim Jagielski }
704*b1cdbd2cSJim Jagielski
IsMultiLineText() const705*b1cdbd2cSJim Jagielski bool XclExpLabelCell::IsMultiLineText() const
706*b1cdbd2cSJim Jagielski {
707*b1cdbd2cSJim Jagielski return mbLineBreak || mxText->IsWrapped();
708*b1cdbd2cSJim Jagielski }
709*b1cdbd2cSJim Jagielski
Init(const XclExpRoot & rRoot,const ScPatternAttr * pPattern,XclExpStringRef xText)710*b1cdbd2cSJim Jagielski void XclExpLabelCell::Init( const XclExpRoot& rRoot,
711*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, XclExpStringRef xText )
712*b1cdbd2cSJim Jagielski {
713*b1cdbd2cSJim Jagielski DBG_ASSERT( xText.is() && xText->Len(), "XclExpLabelCell::XclExpLabelCell - empty string passed" );
714*b1cdbd2cSJim Jagielski mxText = xText;
715*b1cdbd2cSJim Jagielski mnSstIndex = 0;
716*b1cdbd2cSJim Jagielski
717*b1cdbd2cSJim Jagielski // create the cell format
718*b1cdbd2cSJim Jagielski sal_uInt16 nXclFont = mxText->RemoveLeadingFont();
719*b1cdbd2cSJim Jagielski if( GetXFId() == EXC_XFID_NOTFOUND )
720*b1cdbd2cSJim Jagielski {
721*b1cdbd2cSJim Jagielski DBG_ASSERT( nXclFont != EXC_FONT_NOTFOUND, "XclExpLabelCell::Init - leading font not found" );
722*b1cdbd2cSJim Jagielski bool bForceLineBreak = mxText->IsWrapped();
723*b1cdbd2cSJim Jagielski SetXFId( rRoot.GetXFBuffer().InsertWithFont( pPattern, ApiScriptType::WEAK, nXclFont, bForceLineBreak ) );
724*b1cdbd2cSJim Jagielski }
725*b1cdbd2cSJim Jagielski
726*b1cdbd2cSJim Jagielski // get auto-wrap attribute from cell format
727*b1cdbd2cSJim Jagielski const XclExpXF* pXF = rRoot.GetXFBuffer().GetXFById( GetXFId() );
728*b1cdbd2cSJim Jagielski mbLineBreak = pXF && pXF->GetAlignmentData().mbLineBreak;
729*b1cdbd2cSJim Jagielski
730*b1cdbd2cSJim Jagielski // initialize the record contents
731*b1cdbd2cSJim Jagielski switch( rRoot.GetBiff() )
732*b1cdbd2cSJim Jagielski {
733*b1cdbd2cSJim Jagielski case EXC_BIFF5:
734*b1cdbd2cSJim Jagielski // BIFF5-BIFF7: create a LABEL or RSTRING record
735*b1cdbd2cSJim Jagielski DBG_ASSERT( mxText->Len() <= EXC_LABEL_MAXLEN, "XclExpLabelCell::XclExpLabelCell - string too long" );
736*b1cdbd2cSJim Jagielski SetContSize( mxText->GetSize() );
737*b1cdbd2cSJim Jagielski // formatted string is exported in an RSTRING record
738*b1cdbd2cSJim Jagielski if( mxText->IsRich() )
739*b1cdbd2cSJim Jagielski {
740*b1cdbd2cSJim Jagielski DBG_ASSERT( mxText->GetFormatsCount() <= EXC_LABEL_MAXLEN, "XclExpLabelCell::WriteContents - too many formats" );
741*b1cdbd2cSJim Jagielski mxText->LimitFormatCount( EXC_LABEL_MAXLEN );
742*b1cdbd2cSJim Jagielski SetRecId( EXC_ID_RSTRING );
743*b1cdbd2cSJim Jagielski SetContSize( GetContSize() + 1 + 2 * mxText->GetFormatsCount() );
744*b1cdbd2cSJim Jagielski }
745*b1cdbd2cSJim Jagielski break;
746*b1cdbd2cSJim Jagielski case EXC_BIFF8:
747*b1cdbd2cSJim Jagielski // BIFF8+: create a LABELSST record
748*b1cdbd2cSJim Jagielski mnSstIndex = rRoot.GetSst().Insert( xText );
749*b1cdbd2cSJim Jagielski SetRecId( EXC_ID_LABELSST );
750*b1cdbd2cSJim Jagielski SetContSize( 4 );
751*b1cdbd2cSJim Jagielski break;
752*b1cdbd2cSJim Jagielski default: DBG_ERROR_BIFF();
753*b1cdbd2cSJim Jagielski }
754*b1cdbd2cSJim Jagielski }
755*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)756*b1cdbd2cSJim Jagielski void XclExpLabelCell::SaveXml( XclExpXmlStream& rStrm )
757*b1cdbd2cSJim Jagielski {
758*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
759*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_c,
760*b1cdbd2cSJim Jagielski XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(),
761*b1cdbd2cSJim Jagielski XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
762*b1cdbd2cSJim Jagielski XML_t, "s",
763*b1cdbd2cSJim Jagielski // OOXTODO: XML_cm, XML_vm, XML_ph
764*b1cdbd2cSJim Jagielski FSEND );
765*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_v, FSEND );
766*b1cdbd2cSJim Jagielski rWorksheet->write( (sal_Int32) mnSstIndex );
767*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_v );
768*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_c );
769*b1cdbd2cSJim Jagielski }
770*b1cdbd2cSJim Jagielski
WriteContents(XclExpStream & rStrm)771*b1cdbd2cSJim Jagielski void XclExpLabelCell::WriteContents( XclExpStream& rStrm )
772*b1cdbd2cSJim Jagielski {
773*b1cdbd2cSJim Jagielski switch( rStrm.GetRoot().GetBiff() )
774*b1cdbd2cSJim Jagielski {
775*b1cdbd2cSJim Jagielski case EXC_BIFF5:
776*b1cdbd2cSJim Jagielski rStrm << *mxText;
777*b1cdbd2cSJim Jagielski if( mxText->IsRich() )
778*b1cdbd2cSJim Jagielski {
779*b1cdbd2cSJim Jagielski rStrm << static_cast< sal_uInt8 >( mxText->GetFormatsCount() );
780*b1cdbd2cSJim Jagielski mxText->WriteFormats( rStrm );
781*b1cdbd2cSJim Jagielski }
782*b1cdbd2cSJim Jagielski break;
783*b1cdbd2cSJim Jagielski case EXC_BIFF8:
784*b1cdbd2cSJim Jagielski rStrm << mnSstIndex;
785*b1cdbd2cSJim Jagielski break;
786*b1cdbd2cSJim Jagielski default: DBG_ERROR_BIFF();
787*b1cdbd2cSJim Jagielski }
788*b1cdbd2cSJim Jagielski }
789*b1cdbd2cSJim Jagielski
790*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
791*b1cdbd2cSJim Jagielski
792*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpFormulaCell, 256, 256 )
793*b1cdbd2cSJim Jagielski
XclExpFormulaCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,const ScFormulaCell & rScFmlaCell,XclExpArrayBuffer & rArrayBfr,XclExpShrfmlaBuffer & rShrfmlaBfr,XclExpTableopBuffer & rTableopBfr)794*b1cdbd2cSJim Jagielski XclExpFormulaCell::XclExpFormulaCell(
795*b1cdbd2cSJim Jagielski const XclExpRoot& rRoot, const XclAddress& rXclPos,
796*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
797*b1cdbd2cSJim Jagielski const ScFormulaCell& rScFmlaCell,
798*b1cdbd2cSJim Jagielski XclExpArrayBuffer& rArrayBfr,
799*b1cdbd2cSJim Jagielski XclExpShrfmlaBuffer& rShrfmlaBfr,
800*b1cdbd2cSJim Jagielski XclExpTableopBuffer& rTableopBfr ) :
801*b1cdbd2cSJim Jagielski XclExpSingleCellBase( EXC_ID2_FORMULA, 0, rXclPos, nForcedXFId ),
802*b1cdbd2cSJim Jagielski mrScFmlaCell( const_cast< ScFormulaCell& >( rScFmlaCell ) )
803*b1cdbd2cSJim Jagielski {
804*b1cdbd2cSJim Jagielski // *** Find result number format overwriting cell number format *** -------
805*b1cdbd2cSJim Jagielski
806*b1cdbd2cSJim Jagielski if( GetXFId() == EXC_XFID_NOTFOUND )
807*b1cdbd2cSJim Jagielski {
808*b1cdbd2cSJim Jagielski SvNumberFormatter& rFormatter = rRoot.GetFormatter();
809*b1cdbd2cSJim Jagielski XclExpNumFmtBuffer& rNumFmtBfr = rRoot.GetNumFmtBuffer();
810*b1cdbd2cSJim Jagielski
811*b1cdbd2cSJim Jagielski // current cell number format
812*b1cdbd2cSJim Jagielski sal_uLong nScNumFmt = pPattern ?
813*b1cdbd2cSJim Jagielski GETITEMVALUE( pPattern->GetItemSet(), SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong ) :
814*b1cdbd2cSJim Jagielski rNumFmtBfr.GetStandardFormat();
815*b1cdbd2cSJim Jagielski
816*b1cdbd2cSJim Jagielski // alternative number format passed to XF buffer
817*b1cdbd2cSJim Jagielski sal_uLong nAltScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
818*b1cdbd2cSJim Jagielski /* #73420# Xcl doesn't know Boolean number formats, we write
819*b1cdbd2cSJim Jagielski "TRUE";"FALSE" (language dependent). Don't do it for automatic
820*b1cdbd2cSJim Jagielski formula formats, because Excel gets them right. */
821*b1cdbd2cSJim Jagielski /* #i8640# Don't set text format, if we have string results. */
822*b1cdbd2cSJim Jagielski short nFormatType = mrScFmlaCell.GetFormatType();
823*b1cdbd2cSJim Jagielski if( ((nScNumFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0) &&
824*b1cdbd2cSJim Jagielski (nFormatType != NUMBERFORMAT_LOGICAL) &&
825*b1cdbd2cSJim Jagielski (nFormatType != NUMBERFORMAT_TEXT) )
826*b1cdbd2cSJim Jagielski nAltScNumFmt = mrScFmlaCell.GetStandardFormat( rFormatter, nScNumFmt );
827*b1cdbd2cSJim Jagielski /* #73420# If cell number format is Boolean and automatic formula
828*b1cdbd2cSJim Jagielski format is Boolean don't write that ugly special format. */
829*b1cdbd2cSJim Jagielski else if( (nFormatType == NUMBERFORMAT_LOGICAL) &&
830*b1cdbd2cSJim Jagielski (rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL) )
831*b1cdbd2cSJim Jagielski nAltScNumFmt = rNumFmtBfr.GetStandardFormat();
832*b1cdbd2cSJim Jagielski
833*b1cdbd2cSJim Jagielski // #i41420# find script type according to result type (always latin for numeric results)
834*b1cdbd2cSJim Jagielski sal_Int16 nScript = ApiScriptType::LATIN;
835*b1cdbd2cSJim Jagielski bool bForceLineBreak = false;
836*b1cdbd2cSJim Jagielski if( nFormatType == NUMBERFORMAT_TEXT )
837*b1cdbd2cSJim Jagielski {
838*b1cdbd2cSJim Jagielski String aResult;
839*b1cdbd2cSJim Jagielski mrScFmlaCell.GetString( aResult );
840*b1cdbd2cSJim Jagielski bForceLineBreak = mrScFmlaCell.IsMultilineResult();
841*b1cdbd2cSJim Jagielski nScript = XclExpStringHelper::GetLeadingScriptType( rRoot, aResult );
842*b1cdbd2cSJim Jagielski }
843*b1cdbd2cSJim Jagielski SetXFId( rRoot.GetXFBuffer().InsertWithNumFmt( pPattern, nScript, nAltScNumFmt, bForceLineBreak ) );
844*b1cdbd2cSJim Jagielski }
845*b1cdbd2cSJim Jagielski
846*b1cdbd2cSJim Jagielski // *** Convert the formula token array *** --------------------------------
847*b1cdbd2cSJim Jagielski
848*b1cdbd2cSJim Jagielski ScAddress aScPos( static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), rRoot.GetCurrScTab() );
849*b1cdbd2cSJim Jagielski const ScTokenArray& rScTokArr = *mrScFmlaCell.GetCode();
850*b1cdbd2cSJim Jagielski
851*b1cdbd2cSJim Jagielski // first try to create multiple operations
852*b1cdbd2cSJim Jagielski mxAddRec = rTableopBfr.CreateOrExtendTableop( rScTokArr, aScPos );
853*b1cdbd2cSJim Jagielski
854*b1cdbd2cSJim Jagielski // no multiple operation found - try to create matrix formula
855*b1cdbd2cSJim Jagielski if( !mxAddRec ) switch( static_cast< ScMatrixMode >( mrScFmlaCell.GetMatrixFlag() ) )
856*b1cdbd2cSJim Jagielski {
857*b1cdbd2cSJim Jagielski case MM_FORMULA:
858*b1cdbd2cSJim Jagielski {
859*b1cdbd2cSJim Jagielski // origin of the matrix - find the used matrix range
860*b1cdbd2cSJim Jagielski SCCOL nMatWidth;
861*b1cdbd2cSJim Jagielski SCROW nMatHeight;
862*b1cdbd2cSJim Jagielski mrScFmlaCell.GetMatColsRows( nMatWidth, nMatHeight );
863*b1cdbd2cSJim Jagielski DBG_ASSERT( nMatWidth && nMatHeight, "XclExpFormulaCell::XclExpFormulaCell - empty matrix" );
864*b1cdbd2cSJim Jagielski ScRange aMatScRange( aScPos );
865*b1cdbd2cSJim Jagielski ScAddress& rMatEnd = aMatScRange.aEnd;
866*b1cdbd2cSJim Jagielski rMatEnd.IncCol( static_cast< SCsCOL >( nMatWidth - 1 ) );
867*b1cdbd2cSJim Jagielski rMatEnd.IncRow( static_cast< SCsROW >( nMatHeight - 1 ) );
868*b1cdbd2cSJim Jagielski // reduce to valid range (range keeps valid, because start position IS valid)
869*b1cdbd2cSJim Jagielski rRoot.GetAddressConverter().ValidateRange( aMatScRange, true );
870*b1cdbd2cSJim Jagielski // create the ARRAY record
871*b1cdbd2cSJim Jagielski mxAddRec = rArrayBfr.CreateArray( rScTokArr, aMatScRange );
872*b1cdbd2cSJim Jagielski }
873*b1cdbd2cSJim Jagielski break;
874*b1cdbd2cSJim Jagielski case MM_REFERENCE:
875*b1cdbd2cSJim Jagielski {
876*b1cdbd2cSJim Jagielski // other formula cell covered by a matrix - find the ARRAY record
877*b1cdbd2cSJim Jagielski mxAddRec = rArrayBfr.FindArray( rScTokArr );
878*b1cdbd2cSJim Jagielski // should always be found, if Calc document is not broken
879*b1cdbd2cSJim Jagielski DBG_ASSERT( mxAddRec.is(), "XclExpFormulaCell::XclExpFormulaCell - no matrix found" );
880*b1cdbd2cSJim Jagielski }
881*b1cdbd2cSJim Jagielski break;
882*b1cdbd2cSJim Jagielski default:;
883*b1cdbd2cSJim Jagielski }
884*b1cdbd2cSJim Jagielski
885*b1cdbd2cSJim Jagielski // no matrix found - try to create shared formula
886*b1cdbd2cSJim Jagielski if( !mxAddRec )
887*b1cdbd2cSJim Jagielski mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla( rScTokArr, aScPos );
888*b1cdbd2cSJim Jagielski
889*b1cdbd2cSJim Jagielski // no shared formula found - create a simple cell formula
890*b1cdbd2cSJim Jagielski if( !mxAddRec )
891*b1cdbd2cSJim Jagielski mxTokArr = rRoot.GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CELL, rScTokArr, &aScPos );
892*b1cdbd2cSJim Jagielski }
893*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)894*b1cdbd2cSJim Jagielski void XclExpFormulaCell::Save( XclExpStream& rStrm )
895*b1cdbd2cSJim Jagielski {
896*b1cdbd2cSJim Jagielski // create token array for FORMULA cells with additional record
897*b1cdbd2cSJim Jagielski if( mxAddRec.is() )
898*b1cdbd2cSJim Jagielski mxTokArr = mxAddRec->CreateCellTokenArray( rStrm.GetRoot() );
899*b1cdbd2cSJim Jagielski
900*b1cdbd2cSJim Jagielski // FORMULA record itself
901*b1cdbd2cSJim Jagielski DBG_ASSERT( mxTokArr.is(), "XclExpFormulaCell::Save - missing token array" );
902*b1cdbd2cSJim Jagielski if( !mxTokArr )
903*b1cdbd2cSJim Jagielski mxTokArr = rStrm.GetRoot().GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NA );
904*b1cdbd2cSJim Jagielski SetContSize( 16 + mxTokArr->GetSize() );
905*b1cdbd2cSJim Jagielski XclExpSingleCellBase::Save( rStrm );
906*b1cdbd2cSJim Jagielski
907*b1cdbd2cSJim Jagielski // additional record (ARRAY, SHRFMLA, or TABLEOP), only for first FORMULA record
908*b1cdbd2cSJim Jagielski if( mxAddRec.is() && mxAddRec->IsBasePos( GetXclCol(), GetXclRow() ) )
909*b1cdbd2cSJim Jagielski mxAddRec->Save( rStrm );
910*b1cdbd2cSJim Jagielski
911*b1cdbd2cSJim Jagielski // STRING record for string result
912*b1cdbd2cSJim Jagielski if( mxStringRec.is() )
913*b1cdbd2cSJim Jagielski mxStringRec->Save( rStrm );
914*b1cdbd2cSJim Jagielski }
915*b1cdbd2cSJim Jagielski
lcl_GetErrorString(sal_uInt16 nScErrCode)916*b1cdbd2cSJim Jagielski static const char* lcl_GetErrorString( sal_uInt16 nScErrCode )
917*b1cdbd2cSJim Jagielski {
918*b1cdbd2cSJim Jagielski sal_uInt8 nXclErrCode = XclTools::GetXclErrorCode( nScErrCode );
919*b1cdbd2cSJim Jagielski switch( nXclErrCode )
920*b1cdbd2cSJim Jagielski {
921*b1cdbd2cSJim Jagielski case EXC_ERR_NULL: return "#NULL!";
922*b1cdbd2cSJim Jagielski case EXC_ERR_DIV0: return "#DIV/0!";
923*b1cdbd2cSJim Jagielski case EXC_ERR_VALUE: return "#VALUE!";
924*b1cdbd2cSJim Jagielski case EXC_ERR_REF: return "#REF!";
925*b1cdbd2cSJim Jagielski case EXC_ERR_NAME: return "#NAME?";
926*b1cdbd2cSJim Jagielski case EXC_ERR_NUM: return "#NUM!";
927*b1cdbd2cSJim Jagielski case EXC_ERR_NA:
928*b1cdbd2cSJim Jagielski default: return "#N/A";
929*b1cdbd2cSJim Jagielski }
930*b1cdbd2cSJim Jagielski }
931*b1cdbd2cSJim Jagielski
lcl_GetFormulaInfo(ScFormulaCell & rCell,const char ** pType,OUString & rValue)932*b1cdbd2cSJim Jagielski static void lcl_GetFormulaInfo( ScFormulaCell& rCell, const char** pType, OUString& rValue)
933*b1cdbd2cSJim Jagielski {
934*b1cdbd2cSJim Jagielski switch( rCell.GetFormatType() )
935*b1cdbd2cSJim Jagielski {
936*b1cdbd2cSJim Jagielski case NUMBERFORMAT_NUMBER:
937*b1cdbd2cSJim Jagielski {
938*b1cdbd2cSJim Jagielski // either value or error code
939*b1cdbd2cSJim Jagielski sal_uInt16 nScErrCode = rCell.GetErrCode();
940*b1cdbd2cSJim Jagielski if( nScErrCode )
941*b1cdbd2cSJim Jagielski {
942*b1cdbd2cSJim Jagielski *pType = "e";
943*b1cdbd2cSJim Jagielski rValue = XclXmlUtils::ToOUString( lcl_GetErrorString( nScErrCode ) );
944*b1cdbd2cSJim Jagielski }
945*b1cdbd2cSJim Jagielski else
946*b1cdbd2cSJim Jagielski {
947*b1cdbd2cSJim Jagielski *pType = "n";
948*b1cdbd2cSJim Jagielski rValue = OUString::valueOf( rCell.GetValue() );
949*b1cdbd2cSJim Jagielski }
950*b1cdbd2cSJim Jagielski }
951*b1cdbd2cSJim Jagielski break;
952*b1cdbd2cSJim Jagielski
953*b1cdbd2cSJim Jagielski case NUMBERFORMAT_TEXT:
954*b1cdbd2cSJim Jagielski {
955*b1cdbd2cSJim Jagielski *pType = "str";
956*b1cdbd2cSJim Jagielski String aResult;
957*b1cdbd2cSJim Jagielski rCell.GetString( aResult );
958*b1cdbd2cSJim Jagielski rValue = XclXmlUtils::ToOUString( aResult );
959*b1cdbd2cSJim Jagielski }
960*b1cdbd2cSJim Jagielski break;
961*b1cdbd2cSJim Jagielski
962*b1cdbd2cSJim Jagielski case NUMBERFORMAT_LOGICAL:
963*b1cdbd2cSJim Jagielski {
964*b1cdbd2cSJim Jagielski *pType = "b";
965*b1cdbd2cSJim Jagielski rValue = XclXmlUtils::ToOUString( rCell.GetValue() == 0.0 ? "0" : "1" );
966*b1cdbd2cSJim Jagielski }
967*b1cdbd2cSJim Jagielski break;
968*b1cdbd2cSJim Jagielski
969*b1cdbd2cSJim Jagielski default:
970*b1cdbd2cSJim Jagielski {
971*b1cdbd2cSJim Jagielski *pType = "inlineStr";
972*b1cdbd2cSJim Jagielski String aResult;
973*b1cdbd2cSJim Jagielski rCell.GetString( aResult );
974*b1cdbd2cSJim Jagielski rValue = XclXmlUtils::ToOUString( aResult );
975*b1cdbd2cSJim Jagielski }
976*b1cdbd2cSJim Jagielski break;
977*b1cdbd2cSJim Jagielski }
978*b1cdbd2cSJim Jagielski }
979*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)980*b1cdbd2cSJim Jagielski void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm )
981*b1cdbd2cSJim Jagielski {
982*b1cdbd2cSJim Jagielski const char* sType = NULL;
983*b1cdbd2cSJim Jagielski OUString sValue;
984*b1cdbd2cSJim Jagielski
985*b1cdbd2cSJim Jagielski lcl_GetFormulaInfo( mrScFmlaCell, &sType, sValue );
986*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
987*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_c,
988*b1cdbd2cSJim Jagielski XML_r, XclXmlUtils::ToOString( GetXclPos() ).getStr(),
989*b1cdbd2cSJim Jagielski XML_s, lcl_GetStyleId( rStrm, *this ).getStr(),
990*b1cdbd2cSJim Jagielski XML_t, sType,
991*b1cdbd2cSJim Jagielski // OOXTODO: XML_cm, XML_vm, XML_ph
992*b1cdbd2cSJim Jagielski FSEND );
993*b1cdbd2cSJim Jagielski
994*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_f,
995*b1cdbd2cSJim Jagielski // OOXTODO: XML_t, ST_CellFormulaType
996*b1cdbd2cSJim Jagielski XML_aca, XclXmlUtils::ToPsz( mxTokArr->IsVolatile() || (mxAddRec.is() && mxAddRec->IsVolatile()) ),
997*b1cdbd2cSJim Jagielski // OOXTODO: XML_ref, ST_Ref
998*b1cdbd2cSJim Jagielski // OOXTODO: XML_dt2D, bool
999*b1cdbd2cSJim Jagielski // OOXTODO: XML_dtr, bool
1000*b1cdbd2cSJim Jagielski // OOXTODO: XML_del1, bool
1001*b1cdbd2cSJim Jagielski // OOXTODO: XML_del2, bool
1002*b1cdbd2cSJim Jagielski // OOXTODO: XML_r1, ST_CellRef
1003*b1cdbd2cSJim Jagielski // OOXTODO: XML_r2, ST_CellRef
1004*b1cdbd2cSJim Jagielski // OOXTODO: XML_ca, bool
1005*b1cdbd2cSJim Jagielski // OOXTODO: XML_si, uint
1006*b1cdbd2cSJim Jagielski // OOXTODO: XML_bx bool
1007*b1cdbd2cSJim Jagielski FSEND );
1008*b1cdbd2cSJim Jagielski rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *mrScFmlaCell.GetDocument(), mrScFmlaCell.aPos, mrScFmlaCell.GetCode() ) );
1009*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_f );
1010*b1cdbd2cSJim Jagielski if( strcmp( sType, "inlineStr" ) == 0 )
1011*b1cdbd2cSJim Jagielski {
1012*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_is, FSEND );
1013*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_t, FSEND );
1014*b1cdbd2cSJim Jagielski rWorksheet->writeEscaped( sValue );
1015*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_t );
1016*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_is );
1017*b1cdbd2cSJim Jagielski }
1018*b1cdbd2cSJim Jagielski else
1019*b1cdbd2cSJim Jagielski {
1020*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_v, FSEND );
1021*b1cdbd2cSJim Jagielski rWorksheet->writeEscaped( sValue );
1022*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_v );
1023*b1cdbd2cSJim Jagielski }
1024*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_c );
1025*b1cdbd2cSJim Jagielski }
1026*b1cdbd2cSJim Jagielski
WriteContents(XclExpStream & rStrm)1027*b1cdbd2cSJim Jagielski void XclExpFormulaCell::WriteContents( XclExpStream& rStrm )
1028*b1cdbd2cSJim Jagielski {
1029*b1cdbd2cSJim Jagielski // result of the formula
1030*b1cdbd2cSJim Jagielski switch( mrScFmlaCell.GetFormatType() )
1031*b1cdbd2cSJim Jagielski {
1032*b1cdbd2cSJim Jagielski case NUMBERFORMAT_NUMBER:
1033*b1cdbd2cSJim Jagielski {
1034*b1cdbd2cSJim Jagielski // either value or error code
1035*b1cdbd2cSJim Jagielski sal_uInt16 nScErrCode = mrScFmlaCell.GetErrCode();
1036*b1cdbd2cSJim Jagielski if( nScErrCode )
1037*b1cdbd2cSJim Jagielski rStrm << EXC_FORMULA_RES_ERROR << sal_uInt8( 0 )
1038*b1cdbd2cSJim Jagielski << XclTools::GetXclErrorCode( nScErrCode )
1039*b1cdbd2cSJim Jagielski << sal_uInt8( 0 ) << sal_uInt16( 0 )
1040*b1cdbd2cSJim Jagielski << sal_uInt16( 0xFFFF );
1041*b1cdbd2cSJim Jagielski else
1042*b1cdbd2cSJim Jagielski rStrm << mrScFmlaCell.GetValue();
1043*b1cdbd2cSJim Jagielski }
1044*b1cdbd2cSJim Jagielski break;
1045*b1cdbd2cSJim Jagielski
1046*b1cdbd2cSJim Jagielski case NUMBERFORMAT_TEXT:
1047*b1cdbd2cSJim Jagielski {
1048*b1cdbd2cSJim Jagielski String aResult;
1049*b1cdbd2cSJim Jagielski mrScFmlaCell.GetString( aResult );
1050*b1cdbd2cSJim Jagielski if( aResult.Len() || (rStrm.GetRoot().GetBiff() <= EXC_BIFF5) )
1051*b1cdbd2cSJim Jagielski {
1052*b1cdbd2cSJim Jagielski rStrm << EXC_FORMULA_RES_STRING;
1053*b1cdbd2cSJim Jagielski mxStringRec.reset( new XclExpStringRec( rStrm.GetRoot(), aResult ) );
1054*b1cdbd2cSJim Jagielski }
1055*b1cdbd2cSJim Jagielski else
1056*b1cdbd2cSJim Jagielski rStrm << EXC_FORMULA_RES_EMPTY; // BIFF8 only
1057*b1cdbd2cSJim Jagielski rStrm << sal_uInt8( 0 ) << sal_uInt32( 0 ) << sal_uInt16( 0xFFFF );
1058*b1cdbd2cSJim Jagielski }
1059*b1cdbd2cSJim Jagielski break;
1060*b1cdbd2cSJim Jagielski
1061*b1cdbd2cSJim Jagielski case NUMBERFORMAT_LOGICAL:
1062*b1cdbd2cSJim Jagielski {
1063*b1cdbd2cSJim Jagielski sal_uInt8 nXclValue = (mrScFmlaCell.GetValue() == 0.0) ? 0 : 1;
1064*b1cdbd2cSJim Jagielski rStrm << EXC_FORMULA_RES_BOOL << sal_uInt8( 0 )
1065*b1cdbd2cSJim Jagielski << nXclValue << sal_uInt8( 0 ) << sal_uInt16( 0 )
1066*b1cdbd2cSJim Jagielski << sal_uInt16( 0xFFFF );
1067*b1cdbd2cSJim Jagielski }
1068*b1cdbd2cSJim Jagielski break;
1069*b1cdbd2cSJim Jagielski
1070*b1cdbd2cSJim Jagielski default:
1071*b1cdbd2cSJim Jagielski rStrm << mrScFmlaCell.GetValue();
1072*b1cdbd2cSJim Jagielski }
1073*b1cdbd2cSJim Jagielski
1074*b1cdbd2cSJim Jagielski // flags and formula token array
1075*b1cdbd2cSJim Jagielski sal_uInt16 nFlags = EXC_FORMULA_DEFAULTFLAGS;
1076*b1cdbd2cSJim Jagielski ::set_flag( nFlags, EXC_FORMULA_RECALC_ALWAYS, mxTokArr->IsVolatile() || (mxAddRec.is() && mxAddRec->IsVolatile()) );
1077*b1cdbd2cSJim Jagielski ::set_flag( nFlags, EXC_FORMULA_SHARED, mxAddRec.is() && (mxAddRec->GetRecId() == EXC_ID_SHRFMLA) );
1078*b1cdbd2cSJim Jagielski rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
1079*b1cdbd2cSJim Jagielski }
1080*b1cdbd2cSJim Jagielski
1081*b1cdbd2cSJim Jagielski // Multiple cell records ======================================================
1082*b1cdbd2cSJim Jagielski
XclExpMultiCellBase(sal_uInt16 nRecId,sal_uInt16 nMulRecId,sal_Size nContSize,const XclAddress & rXclPos)1083*b1cdbd2cSJim Jagielski XclExpMultiCellBase::XclExpMultiCellBase(
1084*b1cdbd2cSJim Jagielski sal_uInt16 nRecId, sal_uInt16 nMulRecId, sal_Size nContSize, const XclAddress& rXclPos ) :
1085*b1cdbd2cSJim Jagielski XclExpCellBase( nRecId, 0, rXclPos ),
1086*b1cdbd2cSJim Jagielski mnMulRecId( nMulRecId ),
1087*b1cdbd2cSJim Jagielski mnContSize( nContSize )
1088*b1cdbd2cSJim Jagielski {
1089*b1cdbd2cSJim Jagielski }
1090*b1cdbd2cSJim Jagielski
GetLastXclCol() const1091*b1cdbd2cSJim Jagielski sal_uInt16 XclExpMultiCellBase::GetLastXclCol() const
1092*b1cdbd2cSJim Jagielski {
1093*b1cdbd2cSJim Jagielski return GetXclCol() + GetCellCount() - 1;
1094*b1cdbd2cSJim Jagielski }
1095*b1cdbd2cSJim Jagielski
GetFirstXFId() const1096*b1cdbd2cSJim Jagielski sal_uInt32 XclExpMultiCellBase::GetFirstXFId() const
1097*b1cdbd2cSJim Jagielski {
1098*b1cdbd2cSJim Jagielski return maXFIds.empty() ? XclExpXFBuffer::GetDefCellXFId() : maXFIds.front().mnXFId;
1099*b1cdbd2cSJim Jagielski }
1100*b1cdbd2cSJim Jagielski
IsEmpty() const1101*b1cdbd2cSJim Jagielski bool XclExpMultiCellBase::IsEmpty() const
1102*b1cdbd2cSJim Jagielski {
1103*b1cdbd2cSJim Jagielski return maXFIds.empty();
1104*b1cdbd2cSJim Jagielski }
1105*b1cdbd2cSJim Jagielski
ConvertXFIndexes(const XclExpRoot & rRoot)1106*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::ConvertXFIndexes( const XclExpRoot& rRoot )
1107*b1cdbd2cSJim Jagielski {
1108*b1cdbd2cSJim Jagielski for( XclExpMultiXFIdDeq::iterator aIt = maXFIds.begin(), aEnd = maXFIds.end(); aIt != aEnd; ++aIt )
1109*b1cdbd2cSJim Jagielski aIt->ConvertXFIndex( rRoot );
1110*b1cdbd2cSJim Jagielski }
1111*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)1112*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::Save( XclExpStream& rStrm )
1113*b1cdbd2cSJim Jagielski {
1114*b1cdbd2cSJim Jagielski DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1115*b1cdbd2cSJim Jagielski
1116*b1cdbd2cSJim Jagielski XclExpMultiXFIdDeq::const_iterator aEnd = maXFIds.end();
1117*b1cdbd2cSJim Jagielski XclExpMultiXFIdDeq::const_iterator aRangeBeg = maXFIds.begin();
1118*b1cdbd2cSJim Jagielski XclExpMultiXFIdDeq::const_iterator aRangeEnd = aRangeBeg;
1119*b1cdbd2cSJim Jagielski sal_uInt16 nBegXclCol = GetXclCol();
1120*b1cdbd2cSJim Jagielski sal_uInt16 nEndXclCol = nBegXclCol;
1121*b1cdbd2cSJim Jagielski
1122*b1cdbd2cSJim Jagielski while( aRangeEnd != aEnd )
1123*b1cdbd2cSJim Jagielski {
1124*b1cdbd2cSJim Jagielski // find begin of next used XF range
1125*b1cdbd2cSJim Jagielski aRangeBeg = aRangeEnd;
1126*b1cdbd2cSJim Jagielski nBegXclCol = nEndXclCol;
1127*b1cdbd2cSJim Jagielski while( (aRangeBeg != aEnd) && (aRangeBeg->mnXFIndex == EXC_XF_NOTFOUND) )
1128*b1cdbd2cSJim Jagielski {
1129*b1cdbd2cSJim Jagielski nBegXclCol = nBegXclCol + aRangeBeg->mnCount;
1130*b1cdbd2cSJim Jagielski ++aRangeBeg;
1131*b1cdbd2cSJim Jagielski }
1132*b1cdbd2cSJim Jagielski // find end of next used XF range
1133*b1cdbd2cSJim Jagielski aRangeEnd = aRangeBeg;
1134*b1cdbd2cSJim Jagielski nEndXclCol = nBegXclCol;
1135*b1cdbd2cSJim Jagielski while( (aRangeEnd != aEnd) && (aRangeEnd->mnXFIndex != EXC_XF_NOTFOUND) )
1136*b1cdbd2cSJim Jagielski {
1137*b1cdbd2cSJim Jagielski nEndXclCol = nEndXclCol + aRangeEnd->mnCount;
1138*b1cdbd2cSJim Jagielski ++aRangeEnd;
1139*b1cdbd2cSJim Jagielski }
1140*b1cdbd2cSJim Jagielski
1141*b1cdbd2cSJim Jagielski // export this range as a record
1142*b1cdbd2cSJim Jagielski if( aRangeBeg != aRangeEnd )
1143*b1cdbd2cSJim Jagielski {
1144*b1cdbd2cSJim Jagielski sal_uInt16 nCount = nEndXclCol - nBegXclCol;
1145*b1cdbd2cSJim Jagielski bool bIsMulti = nCount > 1;
1146*b1cdbd2cSJim Jagielski sal_Size nTotalSize = GetRecSize() + (2 + mnContSize) * nCount;
1147*b1cdbd2cSJim Jagielski if( bIsMulti ) nTotalSize += 2;
1148*b1cdbd2cSJim Jagielski
1149*b1cdbd2cSJim Jagielski rStrm.StartRecord( bIsMulti ? mnMulRecId : GetRecId(), nTotalSize );
1150*b1cdbd2cSJim Jagielski rStrm << GetXclRow() << nBegXclCol;
1151*b1cdbd2cSJim Jagielski
1152*b1cdbd2cSJim Jagielski sal_uInt16 nRelCol = nBegXclCol - GetXclCol();
1153*b1cdbd2cSJim Jagielski for( XclExpMultiXFIdDeq::const_iterator aIt = aRangeBeg; aIt != aRangeEnd; ++aIt )
1154*b1cdbd2cSJim Jagielski {
1155*b1cdbd2cSJim Jagielski for( sal_uInt16 nIdx = 0; nIdx < aIt->mnCount; ++nIdx )
1156*b1cdbd2cSJim Jagielski {
1157*b1cdbd2cSJim Jagielski rStrm << aIt->mnXFIndex;
1158*b1cdbd2cSJim Jagielski WriteContents( rStrm, nRelCol );
1159*b1cdbd2cSJim Jagielski ++nRelCol;
1160*b1cdbd2cSJim Jagielski }
1161*b1cdbd2cSJim Jagielski }
1162*b1cdbd2cSJim Jagielski if( bIsMulti )
1163*b1cdbd2cSJim Jagielski rStrm << static_cast< sal_uInt16 >( nEndXclCol - 1 );
1164*b1cdbd2cSJim Jagielski rStrm.EndRecord();
1165*b1cdbd2cSJim Jagielski }
1166*b1cdbd2cSJim Jagielski }
1167*b1cdbd2cSJim Jagielski }
1168*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)1169*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::SaveXml( XclExpXmlStream& rStrm )
1170*b1cdbd2cSJim Jagielski {
1171*b1cdbd2cSJim Jagielski XclExpMultiXFIdDeq::const_iterator aEnd = maXFIds.end();
1172*b1cdbd2cSJim Jagielski XclExpMultiXFIdDeq::const_iterator aRangeBeg = maXFIds.begin();
1173*b1cdbd2cSJim Jagielski XclExpMultiXFIdDeq::const_iterator aRangeEnd = aRangeBeg;
1174*b1cdbd2cSJim Jagielski sal_uInt16 nBegXclCol = GetXclCol();
1175*b1cdbd2cSJim Jagielski sal_uInt16 nEndXclCol = nBegXclCol;
1176*b1cdbd2cSJim Jagielski
1177*b1cdbd2cSJim Jagielski while( aRangeEnd != aEnd )
1178*b1cdbd2cSJim Jagielski {
1179*b1cdbd2cSJim Jagielski // find begin of next used XF range
1180*b1cdbd2cSJim Jagielski aRangeBeg = aRangeEnd;
1181*b1cdbd2cSJim Jagielski nBegXclCol = nEndXclCol;
1182*b1cdbd2cSJim Jagielski while( (aRangeBeg != aEnd) && (aRangeBeg->mnXFIndex == EXC_XF_NOTFOUND) )
1183*b1cdbd2cSJim Jagielski {
1184*b1cdbd2cSJim Jagielski nBegXclCol = nBegXclCol + aRangeBeg->mnCount;
1185*b1cdbd2cSJim Jagielski ++aRangeBeg;
1186*b1cdbd2cSJim Jagielski }
1187*b1cdbd2cSJim Jagielski // find end of next used XF range
1188*b1cdbd2cSJim Jagielski aRangeEnd = aRangeBeg;
1189*b1cdbd2cSJim Jagielski nEndXclCol = nBegXclCol;
1190*b1cdbd2cSJim Jagielski while( (aRangeEnd != aEnd) && (aRangeEnd->mnXFIndex != EXC_XF_NOTFOUND) )
1191*b1cdbd2cSJim Jagielski {
1192*b1cdbd2cSJim Jagielski nEndXclCol = nEndXclCol + aRangeEnd->mnCount;
1193*b1cdbd2cSJim Jagielski ++aRangeEnd;
1194*b1cdbd2cSJim Jagielski }
1195*b1cdbd2cSJim Jagielski
1196*b1cdbd2cSJim Jagielski // export this range as a record
1197*b1cdbd2cSJim Jagielski if( aRangeBeg != aRangeEnd )
1198*b1cdbd2cSJim Jagielski {
1199*b1cdbd2cSJim Jagielski sal_uInt16 nRelColIdx = nBegXclCol - GetXclCol();
1200*b1cdbd2cSJim Jagielski sal_Int32 nRelCol = 0;
1201*b1cdbd2cSJim Jagielski for( XclExpMultiXFIdDeq::const_iterator aIt = aRangeBeg; aIt != aRangeEnd; ++aIt )
1202*b1cdbd2cSJim Jagielski {
1203*b1cdbd2cSJim Jagielski for( sal_uInt16 nIdx = 0; nIdx < aIt->mnCount; ++nIdx )
1204*b1cdbd2cSJim Jagielski {
1205*b1cdbd2cSJim Jagielski WriteXmlContents(
1206*b1cdbd2cSJim Jagielski rStrm,
1207*b1cdbd2cSJim Jagielski XclAddress( static_cast<sal_uInt16>(nBegXclCol + nRelCol), GetXclRow() ),
1208*b1cdbd2cSJim Jagielski aIt->mnXFIndex,
1209*b1cdbd2cSJim Jagielski nRelColIdx );
1210*b1cdbd2cSJim Jagielski ++nRelCol;
1211*b1cdbd2cSJim Jagielski ++nRelColIdx;
1212*b1cdbd2cSJim Jagielski }
1213*b1cdbd2cSJim Jagielski }
1214*b1cdbd2cSJim Jagielski }
1215*b1cdbd2cSJim Jagielski }
1216*b1cdbd2cSJim Jagielski }
1217*b1cdbd2cSJim Jagielski
GetCellCount() const1218*b1cdbd2cSJim Jagielski sal_uInt16 XclExpMultiCellBase::GetCellCount() const
1219*b1cdbd2cSJim Jagielski {
1220*b1cdbd2cSJim Jagielski sal_uInt16 nCount = 0;
1221*b1cdbd2cSJim Jagielski for( XclExpMultiXFIdDeq::const_iterator aIt = maXFIds.begin(), aEnd = maXFIds.end(); aIt != aEnd; ++aIt )
1222*b1cdbd2cSJim Jagielski nCount = nCount + aIt->mnCount;
1223*b1cdbd2cSJim Jagielski return nCount;
1224*b1cdbd2cSJim Jagielski }
1225*b1cdbd2cSJim Jagielski
AppendXFId(const XclExpMultiXFId & rXFId)1226*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::AppendXFId( const XclExpMultiXFId& rXFId )
1227*b1cdbd2cSJim Jagielski {
1228*b1cdbd2cSJim Jagielski if( maXFIds.empty() || (maXFIds.back().mnXFId != rXFId.mnXFId) )
1229*b1cdbd2cSJim Jagielski maXFIds.push_back( rXFId );
1230*b1cdbd2cSJim Jagielski else
1231*b1cdbd2cSJim Jagielski maXFIds.back().mnCount = maXFIds.back().mnCount + rXFId.mnCount;
1232*b1cdbd2cSJim Jagielski }
1233*b1cdbd2cSJim Jagielski
AppendXFId(const XclExpRoot & rRoot,const ScPatternAttr * pPattern,sal_uInt16 nScript,sal_uInt32 nForcedXFId,sal_uInt16 nCount)1234*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::AppendXFId( const XclExpRoot& rRoot,
1235*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt16 nScript, sal_uInt32 nForcedXFId, sal_uInt16 nCount )
1236*b1cdbd2cSJim Jagielski {
1237*b1cdbd2cSJim Jagielski sal_uInt32 nXFId = (nForcedXFId == EXC_XFID_NOTFOUND) ?
1238*b1cdbd2cSJim Jagielski rRoot.GetXFBuffer().Insert( pPattern, nScript ) : nForcedXFId;
1239*b1cdbd2cSJim Jagielski AppendXFId( XclExpMultiXFId( nXFId, nCount ) );
1240*b1cdbd2cSJim Jagielski }
1241*b1cdbd2cSJim Jagielski
TryMergeXFIds(const XclExpMultiCellBase & rCell)1242*b1cdbd2cSJim Jagielski bool XclExpMultiCellBase::TryMergeXFIds( const XclExpMultiCellBase& rCell )
1243*b1cdbd2cSJim Jagielski {
1244*b1cdbd2cSJim Jagielski if( GetLastXclCol() + 1 == rCell.GetXclCol() )
1245*b1cdbd2cSJim Jagielski {
1246*b1cdbd2cSJim Jagielski maXFIds.insert( maXFIds.end(), rCell.maXFIds.begin(), rCell.maXFIds.end() );
1247*b1cdbd2cSJim Jagielski return true;
1248*b1cdbd2cSJim Jagielski }
1249*b1cdbd2cSJim Jagielski return false;
1250*b1cdbd2cSJim Jagielski }
1251*b1cdbd2cSJim Jagielski
GetXFIndexes(ScfUInt16Vec & rXFIndexes) const1252*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::GetXFIndexes( ScfUInt16Vec& rXFIndexes ) const
1253*b1cdbd2cSJim Jagielski {
1254*b1cdbd2cSJim Jagielski DBG_ASSERT( GetLastXclCol() < rXFIndexes.size(), "XclExpMultiCellBase::GetXFIndexes - vector too small" );
1255*b1cdbd2cSJim Jagielski ScfUInt16Vec::iterator aDestIt = rXFIndexes.begin() + GetXclCol();
1256*b1cdbd2cSJim Jagielski for( XclExpMultiXFIdDeq::const_iterator aIt = maXFIds.begin(), aEnd = maXFIds.end(); aIt != aEnd; ++aIt )
1257*b1cdbd2cSJim Jagielski {
1258*b1cdbd2cSJim Jagielski ::std::fill( aDestIt, aDestIt + aIt->mnCount, aIt->mnXFIndex );
1259*b1cdbd2cSJim Jagielski aDestIt += aIt->mnCount;
1260*b1cdbd2cSJim Jagielski }
1261*b1cdbd2cSJim Jagielski }
1262*b1cdbd2cSJim Jagielski
RemoveUnusedXFIndexes(const ScfUInt16Vec & rXFIndexes)1263*b1cdbd2cSJim Jagielski void XclExpMultiCellBase::RemoveUnusedXFIndexes( const ScfUInt16Vec& rXFIndexes )
1264*b1cdbd2cSJim Jagielski {
1265*b1cdbd2cSJim Jagielski // save last column before calling maXFIds.clear()
1266*b1cdbd2cSJim Jagielski sal_uInt16 nLastXclCol = GetLastXclCol();
1267*b1cdbd2cSJim Jagielski DBG_ASSERT( nLastXclCol < rXFIndexes.size(), "XclExpMultiCellBase::RemoveUnusedXFIndexes - XF index vector too small" );
1268*b1cdbd2cSJim Jagielski
1269*b1cdbd2cSJim Jagielski // build new XF index vector, containing passed XF indexes
1270*b1cdbd2cSJim Jagielski maXFIds.clear();
1271*b1cdbd2cSJim Jagielski XclExpMultiXFId aXFId( 0 );
1272*b1cdbd2cSJim Jagielski for( ScfUInt16Vec::const_iterator aIt = rXFIndexes.begin() + GetXclCol(), aEnd = rXFIndexes.begin() + nLastXclCol + 1; aIt != aEnd; ++aIt )
1273*b1cdbd2cSJim Jagielski {
1274*b1cdbd2cSJim Jagielski // AppendXFId() tests XclExpXFIndex::mnXFId, set it too
1275*b1cdbd2cSJim Jagielski aXFId.mnXFId = aXFId.mnXFIndex = *aIt;
1276*b1cdbd2cSJim Jagielski AppendXFId( aXFId );
1277*b1cdbd2cSJim Jagielski }
1278*b1cdbd2cSJim Jagielski
1279*b1cdbd2cSJim Jagielski // remove leading and trailing unused XF indexes
1280*b1cdbd2cSJim Jagielski if( !maXFIds.empty() && (maXFIds.front().mnXFIndex == EXC_XF_NOTFOUND) )
1281*b1cdbd2cSJim Jagielski {
1282*b1cdbd2cSJim Jagielski SetXclCol( GetXclCol() + maXFIds.front().mnCount );
1283*b1cdbd2cSJim Jagielski maXFIds.pop_front();
1284*b1cdbd2cSJim Jagielski }
1285*b1cdbd2cSJim Jagielski if( !maXFIds.empty() && (maXFIds.back().mnXFIndex == EXC_XF_NOTFOUND) )
1286*b1cdbd2cSJim Jagielski maXFIds.pop_back();
1287*b1cdbd2cSJim Jagielski
1288*b1cdbd2cSJim Jagielski // The Save() function will skip all XF indexes equal to EXC_XF_NOTFOUND.
1289*b1cdbd2cSJim Jagielski }
1290*b1cdbd2cSJim Jagielski
1291*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1292*b1cdbd2cSJim Jagielski
1293*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpBlankCell, 256, 256 )
1294*b1cdbd2cSJim Jagielski
XclExpBlankCell(const XclAddress & rXclPos,const XclExpMultiXFId & rXFId)1295*b1cdbd2cSJim Jagielski XclExpBlankCell::XclExpBlankCell( const XclAddress& rXclPos, const XclExpMultiXFId& rXFId ) :
1296*b1cdbd2cSJim Jagielski XclExpMultiCellBase( EXC_ID3_BLANK, EXC_ID_MULBLANK, 0, rXclPos )
1297*b1cdbd2cSJim Jagielski {
1298*b1cdbd2cSJim Jagielski DBG_ASSERT( rXFId.mnCount > 0, "XclExpBlankCell::XclExpBlankCell - invalid count" );
1299*b1cdbd2cSJim Jagielski AppendXFId( rXFId );
1300*b1cdbd2cSJim Jagielski }
1301*b1cdbd2cSJim Jagielski
XclExpBlankCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,sal_uInt16 nLastXclCol,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId)1302*b1cdbd2cSJim Jagielski XclExpBlankCell::XclExpBlankCell(
1303*b1cdbd2cSJim Jagielski const XclExpRoot& rRoot, const XclAddress& rXclPos, sal_uInt16 nLastXclCol,
1304*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId ) :
1305*b1cdbd2cSJim Jagielski XclExpMultiCellBase( EXC_ID3_BLANK, EXC_ID_MULBLANK, 0, rXclPos )
1306*b1cdbd2cSJim Jagielski {
1307*b1cdbd2cSJim Jagielski DBG_ASSERT( rXclPos.mnCol <= nLastXclCol, "XclExpBlankCell::XclExpBlankCell - invalid column range" );
1308*b1cdbd2cSJim Jagielski // #i46627# use default script type instead of ApiScriptType::WEAK
1309*b1cdbd2cSJim Jagielski AppendXFId( rRoot, pPattern, rRoot.GetDefApiScript(), nForcedXFId, nLastXclCol - rXclPos.mnCol + 1 );
1310*b1cdbd2cSJim Jagielski }
1311*b1cdbd2cSJim Jagielski
TryMerge(const XclExpCellBase & rCell)1312*b1cdbd2cSJim Jagielski bool XclExpBlankCell::TryMerge( const XclExpCellBase& rCell )
1313*b1cdbd2cSJim Jagielski {
1314*b1cdbd2cSJim Jagielski const XclExpBlankCell* pBlankCell = dynamic_cast< const XclExpBlankCell* >( &rCell );
1315*b1cdbd2cSJim Jagielski return pBlankCell && TryMergeXFIds( *pBlankCell );
1316*b1cdbd2cSJim Jagielski }
1317*b1cdbd2cSJim Jagielski
GetBlankXFIndexes(ScfUInt16Vec & rXFIndexes) const1318*b1cdbd2cSJim Jagielski void XclExpBlankCell::GetBlankXFIndexes( ScfUInt16Vec& rXFIndexes ) const
1319*b1cdbd2cSJim Jagielski {
1320*b1cdbd2cSJim Jagielski GetXFIndexes( rXFIndexes );
1321*b1cdbd2cSJim Jagielski }
1322*b1cdbd2cSJim Jagielski
RemoveUnusedBlankCells(const ScfUInt16Vec & rXFIndexes)1323*b1cdbd2cSJim Jagielski void XclExpBlankCell::RemoveUnusedBlankCells( const ScfUInt16Vec& rXFIndexes )
1324*b1cdbd2cSJim Jagielski {
1325*b1cdbd2cSJim Jagielski RemoveUnusedXFIndexes( rXFIndexes );
1326*b1cdbd2cSJim Jagielski }
1327*b1cdbd2cSJim Jagielski
WriteContents(XclExpStream &,sal_uInt16)1328*b1cdbd2cSJim Jagielski void XclExpBlankCell::WriteContents( XclExpStream& /*rStrm*/, sal_uInt16 /*nRelCol*/ )
1329*b1cdbd2cSJim Jagielski {
1330*b1cdbd2cSJim Jagielski }
1331*b1cdbd2cSJim Jagielski
WriteXmlContents(XclExpXmlStream & rStrm,const XclAddress & rAddress,sal_uInt32 nXFId,sal_uInt16)1332*b1cdbd2cSJim Jagielski void XclExpBlankCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 /* nRelCol */ )
1333*b1cdbd2cSJim Jagielski {
1334*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1335*b1cdbd2cSJim Jagielski rWorksheet->singleElement( XML_c,
1336*b1cdbd2cSJim Jagielski XML_r, XclXmlUtils::ToOString( rAddress ).getStr(),
1337*b1cdbd2cSJim Jagielski XML_s, lcl_GetStyleId( rStrm, nXFId ).getStr(),
1338*b1cdbd2cSJim Jagielski FSEND );
1339*b1cdbd2cSJim Jagielski }
1340*b1cdbd2cSJim Jagielski
1341*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1342*b1cdbd2cSJim Jagielski
1343*b1cdbd2cSJim Jagielski IMPL_FIXEDMEMPOOL_NEWDEL( XclExpRkCell, 256, 256 )
1344*b1cdbd2cSJim Jagielski
XclExpRkCell(const XclExpRoot & rRoot,const XclAddress & rXclPos,const ScPatternAttr * pPattern,sal_uInt32 nForcedXFId,sal_Int32 nRkValue)1345*b1cdbd2cSJim Jagielski XclExpRkCell::XclExpRkCell(
1346*b1cdbd2cSJim Jagielski const XclExpRoot& rRoot, const XclAddress& rXclPos,
1347*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, sal_Int32 nRkValue ) :
1348*b1cdbd2cSJim Jagielski XclExpMultiCellBase( EXC_ID_RK, EXC_ID_MULRK, 4, rXclPos )
1349*b1cdbd2cSJim Jagielski {
1350*b1cdbd2cSJim Jagielski // #i41210# always use latin script for number cells - may look wrong for special number formats...
1351*b1cdbd2cSJim Jagielski AppendXFId( rRoot, pPattern, ApiScriptType::LATIN, nForcedXFId );
1352*b1cdbd2cSJim Jagielski maRkValues.push_back( nRkValue );
1353*b1cdbd2cSJim Jagielski }
1354*b1cdbd2cSJim Jagielski
TryMerge(const XclExpCellBase & rCell)1355*b1cdbd2cSJim Jagielski bool XclExpRkCell::TryMerge( const XclExpCellBase& rCell )
1356*b1cdbd2cSJim Jagielski {
1357*b1cdbd2cSJim Jagielski const XclExpRkCell* pRkCell = dynamic_cast< const XclExpRkCell* >( &rCell );
1358*b1cdbd2cSJim Jagielski if( pRkCell && TryMergeXFIds( *pRkCell ) )
1359*b1cdbd2cSJim Jagielski {
1360*b1cdbd2cSJim Jagielski maRkValues.insert( maRkValues.end(), pRkCell->maRkValues.begin(), pRkCell->maRkValues.end() );
1361*b1cdbd2cSJim Jagielski return true;
1362*b1cdbd2cSJim Jagielski }
1363*b1cdbd2cSJim Jagielski return false;
1364*b1cdbd2cSJim Jagielski }
1365*b1cdbd2cSJim Jagielski
WriteXmlContents(XclExpXmlStream & rStrm,const XclAddress & rAddress,sal_uInt32 nXFId,sal_uInt16 nRelCol)1366*b1cdbd2cSJim Jagielski void XclExpRkCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol )
1367*b1cdbd2cSJim Jagielski {
1368*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1369*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_c,
1370*b1cdbd2cSJim Jagielski XML_r, XclXmlUtils::ToOString( rAddress ).getStr(),
1371*b1cdbd2cSJim Jagielski XML_s, lcl_GetStyleId( rStrm, nXFId ).getStr(),
1372*b1cdbd2cSJim Jagielski XML_t, "n",
1373*b1cdbd2cSJim Jagielski // OOXTODO: XML_cm, XML_vm, XML_ph
1374*b1cdbd2cSJim Jagielski FSEND );
1375*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_v, FSEND );
1376*b1cdbd2cSJim Jagielski rWorksheet->write( XclTools::GetDoubleFromRK( maRkValues[ nRelCol ] ) );
1377*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_v );
1378*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_c );
1379*b1cdbd2cSJim Jagielski }
1380*b1cdbd2cSJim Jagielski
WriteContents(XclExpStream & rStrm,sal_uInt16 nRelCol)1381*b1cdbd2cSJim Jagielski void XclExpRkCell::WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol )
1382*b1cdbd2cSJim Jagielski {
1383*b1cdbd2cSJim Jagielski DBG_ASSERT( nRelCol < maRkValues.size(), "XclExpRkCell::WriteContents - overflow error" );
1384*b1cdbd2cSJim Jagielski rStrm << maRkValues[ nRelCol ];
1385*b1cdbd2cSJim Jagielski }
1386*b1cdbd2cSJim Jagielski
1387*b1cdbd2cSJim Jagielski // ============================================================================
1388*b1cdbd2cSJim Jagielski // Rows and Columns
1389*b1cdbd2cSJim Jagielski // ============================================================================
1390*b1cdbd2cSJim Jagielski
XclExpOutlineBuffer(const XclExpRoot & rRoot,bool bRows)1391*b1cdbd2cSJim Jagielski XclExpOutlineBuffer::XclExpOutlineBuffer( const XclExpRoot& rRoot, bool bRows ) :
1392*b1cdbd2cSJim Jagielski mpScOLArray( 0 ),
1393*b1cdbd2cSJim Jagielski maLevelInfos( SC_OL_MAXDEPTH ),
1394*b1cdbd2cSJim Jagielski mnCurrLevel( 0 ),
1395*b1cdbd2cSJim Jagielski mbCurrCollapse( false )
1396*b1cdbd2cSJim Jagielski {
1397*b1cdbd2cSJim Jagielski if( const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() ) )
1398*b1cdbd2cSJim Jagielski mpScOLArray = bRows ? pOutlineTable->GetRowArray() : pOutlineTable->GetColArray();
1399*b1cdbd2cSJim Jagielski
1400*b1cdbd2cSJim Jagielski if( mpScOLArray )
1401*b1cdbd2cSJim Jagielski for( sal_uInt16 nLevel = 0; nLevel < SC_OL_MAXDEPTH; ++nLevel )
1402*b1cdbd2cSJim Jagielski if( ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nLevel, 0 ) )
1403*b1cdbd2cSJim Jagielski maLevelInfos[ nLevel ].mnScEndPos = pEntry->GetEnd();
1404*b1cdbd2cSJim Jagielski }
1405*b1cdbd2cSJim Jagielski
UpdateColRow(SCCOLROW nScPos)1406*b1cdbd2cSJim Jagielski void XclExpOutlineBuffer::UpdateColRow( SCCOLROW nScPos )
1407*b1cdbd2cSJim Jagielski {
1408*b1cdbd2cSJim Jagielski if( mpScOLArray )
1409*b1cdbd2cSJim Jagielski {
1410*b1cdbd2cSJim Jagielski // find open level index for passed position
1411*b1cdbd2cSJim Jagielski sal_uInt16 nNewOpenScLevel = 0; // new open level (0-based Calc index)
1412*b1cdbd2cSJim Jagielski sal_uInt8 nNewLevel = 0; // new open level (1-based Excel index)
1413*b1cdbd2cSJim Jagielski
1414*b1cdbd2cSJim Jagielski if( mpScOLArray->FindTouchedLevel( nScPos, nScPos, nNewOpenScLevel ) )
1415*b1cdbd2cSJim Jagielski nNewLevel = static_cast< sal_uInt8 >( nNewOpenScLevel + 1 );
1416*b1cdbd2cSJim Jagielski // else nNewLevel keeps 0 to show that there are no groups
1417*b1cdbd2cSJim Jagielski
1418*b1cdbd2cSJim Jagielski mbCurrCollapse = false;
1419*b1cdbd2cSJim Jagielski if( nNewLevel >= mnCurrLevel )
1420*b1cdbd2cSJim Jagielski {
1421*b1cdbd2cSJim Jagielski // new level(s) opened, or no level closed - update all level infos
1422*b1cdbd2cSJim Jagielski for( sal_uInt16 nScLevel = 0; nScLevel <= nNewOpenScLevel; ++nScLevel )
1423*b1cdbd2cSJim Jagielski {
1424*b1cdbd2cSJim Jagielski /* In each level: check if a new group is started (there may be
1425*b1cdbd2cSJim Jagielski neighbored groups without gap - therefore check ALL levels). */
1426*b1cdbd2cSJim Jagielski if( maLevelInfos[ nScLevel ].mnScEndPos < nScPos )
1427*b1cdbd2cSJim Jagielski {
1428*b1cdbd2cSJim Jagielski if( ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nScLevel, nScPos ) )
1429*b1cdbd2cSJim Jagielski {
1430*b1cdbd2cSJim Jagielski maLevelInfos[ nScLevel ].mnScEndPos = pEntry->GetEnd();
1431*b1cdbd2cSJim Jagielski maLevelInfos[ nScLevel ].mbHidden = pEntry->IsHidden();
1432*b1cdbd2cSJim Jagielski }
1433*b1cdbd2cSJim Jagielski }
1434*b1cdbd2cSJim Jagielski }
1435*b1cdbd2cSJim Jagielski }
1436*b1cdbd2cSJim Jagielski else
1437*b1cdbd2cSJim Jagielski {
1438*b1cdbd2cSJim Jagielski // level(s) closed - check if any of the closed levels are collapsed
1439*b1cdbd2cSJim Jagielski // Calc uses 0-based level indexes
1440*b1cdbd2cSJim Jagielski sal_uInt16 nOldOpenScLevel = mnCurrLevel - 1;
1441*b1cdbd2cSJim Jagielski for( sal_uInt16 nScLevel = nNewOpenScLevel + 1; !mbCurrCollapse && (nScLevel <= nOldOpenScLevel); ++nScLevel )
1442*b1cdbd2cSJim Jagielski mbCurrCollapse = maLevelInfos[ nScLevel ].mbHidden;
1443*b1cdbd2cSJim Jagielski }
1444*b1cdbd2cSJim Jagielski
1445*b1cdbd2cSJim Jagielski // cache new opened level
1446*b1cdbd2cSJim Jagielski mnCurrLevel = nNewLevel;
1447*b1cdbd2cSJim Jagielski }
1448*b1cdbd2cSJim Jagielski }
1449*b1cdbd2cSJim Jagielski
1450*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1451*b1cdbd2cSJim Jagielski
XclExpGuts(const XclExpRoot & rRoot)1452*b1cdbd2cSJim Jagielski XclExpGuts::XclExpGuts( const XclExpRoot& rRoot ) :
1453*b1cdbd2cSJim Jagielski XclExpRecord( EXC_ID_GUTS, 8 ),
1454*b1cdbd2cSJim Jagielski mnColLevels( 0 ),
1455*b1cdbd2cSJim Jagielski mnColWidth( 0 ),
1456*b1cdbd2cSJim Jagielski mnRowLevels( 0 ),
1457*b1cdbd2cSJim Jagielski mnRowWidth( 0 )
1458*b1cdbd2cSJim Jagielski {
1459*b1cdbd2cSJim Jagielski if( const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() ) )
1460*b1cdbd2cSJim Jagielski {
1461*b1cdbd2cSJim Jagielski // column outline groups
1462*b1cdbd2cSJim Jagielski if( const ScOutlineArray* pColArray = pOutlineTable->GetColArray() )
1463*b1cdbd2cSJim Jagielski mnColLevels = ulimit_cast< sal_uInt16 >( pColArray->GetDepth(), EXC_OUTLINE_MAX );
1464*b1cdbd2cSJim Jagielski if( mnColLevels )
1465*b1cdbd2cSJim Jagielski {
1466*b1cdbd2cSJim Jagielski ++mnColLevels;
1467*b1cdbd2cSJim Jagielski mnColWidth = 12 * mnColLevels + 5;
1468*b1cdbd2cSJim Jagielski }
1469*b1cdbd2cSJim Jagielski
1470*b1cdbd2cSJim Jagielski // row outline groups
1471*b1cdbd2cSJim Jagielski if( const ScOutlineArray* pRowArray = pOutlineTable->GetRowArray() )
1472*b1cdbd2cSJim Jagielski mnRowLevels = ulimit_cast< sal_uInt16 >( pRowArray->GetDepth(), EXC_OUTLINE_MAX );
1473*b1cdbd2cSJim Jagielski if( mnRowLevels )
1474*b1cdbd2cSJim Jagielski {
1475*b1cdbd2cSJim Jagielski ++mnRowLevels;
1476*b1cdbd2cSJim Jagielski mnRowWidth = 12 * mnRowLevels + 5;
1477*b1cdbd2cSJim Jagielski }
1478*b1cdbd2cSJim Jagielski }
1479*b1cdbd2cSJim Jagielski }
1480*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)1481*b1cdbd2cSJim Jagielski void XclExpGuts::WriteBody( XclExpStream& rStrm )
1482*b1cdbd2cSJim Jagielski {
1483*b1cdbd2cSJim Jagielski rStrm << mnRowWidth << mnColWidth << mnRowLevels << mnColLevels;
1484*b1cdbd2cSJim Jagielski }
1485*b1cdbd2cSJim Jagielski
1486*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1487*b1cdbd2cSJim Jagielski
XclExpDimensions(const XclExpRoot & rRoot)1488*b1cdbd2cSJim Jagielski XclExpDimensions::XclExpDimensions( const XclExpRoot& rRoot ) :
1489*b1cdbd2cSJim Jagielski mnFirstUsedXclRow( 0 ),
1490*b1cdbd2cSJim Jagielski mnFirstFreeXclRow( 0 ),
1491*b1cdbd2cSJim Jagielski mnFirstUsedXclCol( 0 ),
1492*b1cdbd2cSJim Jagielski mnFirstFreeXclCol( 0 )
1493*b1cdbd2cSJim Jagielski {
1494*b1cdbd2cSJim Jagielski switch( rRoot.GetBiff() )
1495*b1cdbd2cSJim Jagielski {
1496*b1cdbd2cSJim Jagielski case EXC_BIFF2: SetRecHeader( EXC_ID2_DIMENSIONS, 8 ); break;
1497*b1cdbd2cSJim Jagielski case EXC_BIFF3:
1498*b1cdbd2cSJim Jagielski case EXC_BIFF4:
1499*b1cdbd2cSJim Jagielski case EXC_BIFF5: SetRecHeader( EXC_ID3_DIMENSIONS, 10 ); break;
1500*b1cdbd2cSJim Jagielski case EXC_BIFF8: SetRecHeader( EXC_ID3_DIMENSIONS, 14 ); break;
1501*b1cdbd2cSJim Jagielski default: DBG_ERROR_BIFF();
1502*b1cdbd2cSJim Jagielski }
1503*b1cdbd2cSJim Jagielski }
1504*b1cdbd2cSJim Jagielski
SetDimensions(sal_uInt16 nFirstUsedXclCol,sal_uInt32 nFirstUsedXclRow,sal_uInt16 nFirstFreeXclCol,sal_uInt32 nFirstFreeXclRow)1505*b1cdbd2cSJim Jagielski void XclExpDimensions::SetDimensions(
1506*b1cdbd2cSJim Jagielski sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow,
1507*b1cdbd2cSJim Jagielski sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow )
1508*b1cdbd2cSJim Jagielski {
1509*b1cdbd2cSJim Jagielski mnFirstUsedXclRow = nFirstUsedXclRow;
1510*b1cdbd2cSJim Jagielski mnFirstFreeXclRow = nFirstFreeXclRow;
1511*b1cdbd2cSJim Jagielski mnFirstUsedXclCol = nFirstUsedXclCol;
1512*b1cdbd2cSJim Jagielski mnFirstFreeXclCol = nFirstFreeXclCol;
1513*b1cdbd2cSJim Jagielski }
1514*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)1515*b1cdbd2cSJim Jagielski void XclExpDimensions::SaveXml( XclExpXmlStream& rStrm )
1516*b1cdbd2cSJim Jagielski {
1517*b1cdbd2cSJim Jagielski ScRange aRange;
1518*b1cdbd2cSJim Jagielski aRange.aStart.SetRow( (SCROW) mnFirstUsedXclRow );
1519*b1cdbd2cSJim Jagielski aRange.aStart.SetCol( (SCCOL) mnFirstUsedXclCol );
1520*b1cdbd2cSJim Jagielski
1521*b1cdbd2cSJim Jagielski if( mnFirstFreeXclRow != mnFirstUsedXclRow && mnFirstFreeXclCol != mnFirstUsedXclCol )
1522*b1cdbd2cSJim Jagielski {
1523*b1cdbd2cSJim Jagielski aRange.aEnd.SetRow( (SCROW) (mnFirstFreeXclRow-1) );
1524*b1cdbd2cSJim Jagielski aRange.aEnd.SetCol( (SCCOL) (mnFirstFreeXclCol-1) );
1525*b1cdbd2cSJim Jagielski }
1526*b1cdbd2cSJim Jagielski
1527*b1cdbd2cSJim Jagielski rStrm.GetCurrentStream()->singleElement( XML_dimension,
1528*b1cdbd2cSJim Jagielski XML_ref, XclXmlUtils::ToOString( aRange ).getStr(),
1529*b1cdbd2cSJim Jagielski FSEND );
1530*b1cdbd2cSJim Jagielski }
1531*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)1532*b1cdbd2cSJim Jagielski void XclExpDimensions::WriteBody( XclExpStream& rStrm )
1533*b1cdbd2cSJim Jagielski {
1534*b1cdbd2cSJim Jagielski XclBiff eBiff = rStrm.GetRoot().GetBiff();
1535*b1cdbd2cSJim Jagielski if( eBiff == EXC_BIFF8 )
1536*b1cdbd2cSJim Jagielski rStrm << mnFirstUsedXclRow << mnFirstFreeXclRow;
1537*b1cdbd2cSJim Jagielski else
1538*b1cdbd2cSJim Jagielski rStrm << static_cast< sal_uInt16 >( mnFirstUsedXclRow ) << static_cast< sal_uInt16 >( mnFirstFreeXclRow );
1539*b1cdbd2cSJim Jagielski rStrm << mnFirstUsedXclCol << mnFirstFreeXclCol;
1540*b1cdbd2cSJim Jagielski if( eBiff >= EXC_BIFF3 )
1541*b1cdbd2cSJim Jagielski rStrm << sal_uInt16( 0 );
1542*b1cdbd2cSJim Jagielski }
1543*b1cdbd2cSJim Jagielski
1544*b1cdbd2cSJim Jagielski // ============================================================================
1545*b1cdbd2cSJim Jagielski
1546*b1cdbd2cSJim Jagielski namespace {
1547*b1cdbd2cSJim Jagielski
lclGetCorrectedColWidth(const XclExpRoot & rRoot,sal_uInt16 nXclColWidth)1548*b1cdbd2cSJim Jagielski double lclGetCorrectedColWidth( const XclExpRoot& rRoot, sal_uInt16 nXclColWidth )
1549*b1cdbd2cSJim Jagielski {
1550*b1cdbd2cSJim Jagielski long nFontHt = rRoot.GetFontBuffer().GetAppFontData().mnHeight;
1551*b1cdbd2cSJim Jagielski return nXclColWidth - XclTools::GetXclDefColWidthCorrection( nFontHt );
1552*b1cdbd2cSJim Jagielski }
1553*b1cdbd2cSJim Jagielski
1554*b1cdbd2cSJim Jagielski } // namespace
1555*b1cdbd2cSJim Jagielski
1556*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1557*b1cdbd2cSJim Jagielski
XclExpDefcolwidth(const XclExpRoot & rRoot)1558*b1cdbd2cSJim Jagielski XclExpDefcolwidth::XclExpDefcolwidth( const XclExpRoot& rRoot ) :
1559*b1cdbd2cSJim Jagielski XclExpUInt16Record( EXC_ID_DEFCOLWIDTH, EXC_DEFCOLWIDTH_DEF ),
1560*b1cdbd2cSJim Jagielski XclExpRoot( rRoot )
1561*b1cdbd2cSJim Jagielski {
1562*b1cdbd2cSJim Jagielski }
1563*b1cdbd2cSJim Jagielski
IsDefWidth(sal_uInt16 nXclColWidth) const1564*b1cdbd2cSJim Jagielski bool XclExpDefcolwidth::IsDefWidth( sal_uInt16 nXclColWidth ) const
1565*b1cdbd2cSJim Jagielski {
1566*b1cdbd2cSJim Jagielski double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
1567*b1cdbd2cSJim Jagielski // exactly matched, if difference is less than 1/16 of a character to the left or to the right
1568*b1cdbd2cSJim Jagielski return Abs( static_cast< long >( GetValue() * 256.0 - fNewColWidth + 0.5 ) ) < 16;
1569*b1cdbd2cSJim Jagielski }
1570*b1cdbd2cSJim Jagielski
SetDefWidth(sal_uInt16 nXclColWidth)1571*b1cdbd2cSJim Jagielski void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth )
1572*b1cdbd2cSJim Jagielski {
1573*b1cdbd2cSJim Jagielski double fNewColWidth = lclGetCorrectedColWidth( GetRoot(), nXclColWidth );
1574*b1cdbd2cSJim Jagielski SetValue( limit_cast< sal_uInt16 >( fNewColWidth / 256.0 + 0.5 ) );
1575*b1cdbd2cSJim Jagielski }
1576*b1cdbd2cSJim Jagielski
1577*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1578*b1cdbd2cSJim Jagielski
XclExpColinfo(const XclExpRoot & rRoot,SCCOL nScCol,SCROW nLastScRow,XclExpColOutlineBuffer & rOutlineBfr)1579*b1cdbd2cSJim Jagielski XclExpColinfo::XclExpColinfo( const XclExpRoot& rRoot,
1580*b1cdbd2cSJim Jagielski SCCOL nScCol, SCROW nLastScRow, XclExpColOutlineBuffer& rOutlineBfr ) :
1581*b1cdbd2cSJim Jagielski XclExpRecord( EXC_ID_COLINFO, 12 ),
1582*b1cdbd2cSJim Jagielski XclExpRoot( rRoot ),
1583*b1cdbd2cSJim Jagielski mnWidth( 0 ),
1584*b1cdbd2cSJim Jagielski mnFlags( 0 ),
1585*b1cdbd2cSJim Jagielski mnFirstXclCol( static_cast< sal_uInt16 >( nScCol ) ),
1586*b1cdbd2cSJim Jagielski mnLastXclCol( static_cast< sal_uInt16 >( nScCol ) )
1587*b1cdbd2cSJim Jagielski {
1588*b1cdbd2cSJim Jagielski ScDocument& rDoc = GetDoc();
1589*b1cdbd2cSJim Jagielski SCTAB nScTab = GetCurrScTab();
1590*b1cdbd2cSJim Jagielski
1591*b1cdbd2cSJim Jagielski // column default format
1592*b1cdbd2cSJim Jagielski maXFId.mnXFId = GetXFBuffer().Insert(
1593*b1cdbd2cSJim Jagielski rDoc.GetMostUsedPattern( nScCol, 0, nLastScRow, nScTab ), GetDefApiScript() );
1594*b1cdbd2cSJim Jagielski
1595*b1cdbd2cSJim Jagielski // column width
1596*b1cdbd2cSJim Jagielski sal_uInt16 nScWidth = rDoc.GetColWidth( nScCol, nScTab );
1597*b1cdbd2cSJim Jagielski mnWidth = XclTools::GetXclColumnWidth( nScWidth, GetCharWidth() );
1598*b1cdbd2cSJim Jagielski
1599*b1cdbd2cSJim Jagielski // column flags
1600*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) );
1601*b1cdbd2cSJim Jagielski
1602*b1cdbd2cSJim Jagielski // outline data
1603*b1cdbd2cSJim Jagielski rOutlineBfr.Update( nScCol );
1604*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_COLINFO_COLLAPSED, rOutlineBfr.IsCollapsed() );
1605*b1cdbd2cSJim Jagielski ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 8, 3 );
1606*b1cdbd2cSJim Jagielski }
1607*b1cdbd2cSJim Jagielski
ConvertXFIndexes()1608*b1cdbd2cSJim Jagielski sal_uInt16 XclExpColinfo::ConvertXFIndexes()
1609*b1cdbd2cSJim Jagielski {
1610*b1cdbd2cSJim Jagielski maXFId.ConvertXFIndex( GetRoot() );
1611*b1cdbd2cSJim Jagielski return maXFId.mnXFIndex;
1612*b1cdbd2cSJim Jagielski }
1613*b1cdbd2cSJim Jagielski
IsDefault(const XclExpDefcolwidth & rDefColWidth) const1614*b1cdbd2cSJim Jagielski bool XclExpColinfo::IsDefault( const XclExpDefcolwidth& rDefColWidth ) const
1615*b1cdbd2cSJim Jagielski {
1616*b1cdbd2cSJim Jagielski return (maXFId.mnXFIndex == EXC_XF_DEFAULTCELL) && (mnFlags == 0) && rDefColWidth.IsDefWidth( mnWidth );
1617*b1cdbd2cSJim Jagielski }
1618*b1cdbd2cSJim Jagielski
TryMerge(const XclExpColinfo & rColInfo)1619*b1cdbd2cSJim Jagielski bool XclExpColinfo::TryMerge( const XclExpColinfo& rColInfo )
1620*b1cdbd2cSJim Jagielski {
1621*b1cdbd2cSJim Jagielski if( (maXFId.mnXFIndex == rColInfo.maXFId.mnXFIndex) &&
1622*b1cdbd2cSJim Jagielski (mnWidth == rColInfo.mnWidth) &&
1623*b1cdbd2cSJim Jagielski (mnFlags == rColInfo.mnFlags) &&
1624*b1cdbd2cSJim Jagielski (mnLastXclCol + 1 == rColInfo.mnFirstXclCol) )
1625*b1cdbd2cSJim Jagielski {
1626*b1cdbd2cSJim Jagielski mnLastXclCol = rColInfo.mnLastXclCol;
1627*b1cdbd2cSJim Jagielski return true;
1628*b1cdbd2cSJim Jagielski }
1629*b1cdbd2cSJim Jagielski return false;
1630*b1cdbd2cSJim Jagielski }
1631*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)1632*b1cdbd2cSJim Jagielski void XclExpColinfo::WriteBody( XclExpStream& rStrm )
1633*b1cdbd2cSJim Jagielski {
1634*b1cdbd2cSJim Jagielski // if last column is equal to last possible column, Excel adds one more
1635*b1cdbd2cSJim Jagielski sal_uInt16 nLastXclCol = mnLastXclCol;
1636*b1cdbd2cSJim Jagielski if( nLastXclCol == static_cast< sal_uInt16 >( rStrm.GetRoot().GetMaxPos().Col() ) )
1637*b1cdbd2cSJim Jagielski ++nLastXclCol;
1638*b1cdbd2cSJim Jagielski
1639*b1cdbd2cSJim Jagielski rStrm << mnFirstXclCol
1640*b1cdbd2cSJim Jagielski << nLastXclCol
1641*b1cdbd2cSJim Jagielski << mnWidth
1642*b1cdbd2cSJim Jagielski << maXFId.mnXFIndex
1643*b1cdbd2cSJim Jagielski << mnFlags
1644*b1cdbd2cSJim Jagielski << sal_uInt16( 0 );
1645*b1cdbd2cSJim Jagielski }
1646*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)1647*b1cdbd2cSJim Jagielski void XclExpColinfo::SaveXml( XclExpXmlStream& rStrm )
1648*b1cdbd2cSJim Jagielski {
1649*b1cdbd2cSJim Jagielski // if last column is equal to last possible column, Excel adds one more
1650*b1cdbd2cSJim Jagielski sal_uInt16 nLastXclCol = mnLastXclCol;
1651*b1cdbd2cSJim Jagielski if( nLastXclCol == static_cast< sal_uInt16 >( rStrm.GetRoot().GetMaxPos().Col() ) )
1652*b1cdbd2cSJim Jagielski ++nLastXclCol;
1653*b1cdbd2cSJim Jagielski
1654*b1cdbd2cSJim Jagielski rStrm.GetCurrentStream()->singleElement( XML_col,
1655*b1cdbd2cSJim Jagielski // OOXTODO: XML_bestFit,
1656*b1cdbd2cSJim Jagielski XML_collapsed, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_COLLAPSED ) ),
1657*b1cdbd2cSJim Jagielski // OOXTODO: XML_customWidth,
1658*b1cdbd2cSJim Jagielski XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_COLINFO_HIDDEN ) ),
1659*b1cdbd2cSJim Jagielski XML_max, OString::valueOf( (sal_Int32) (nLastXclCol+1) ).getStr(),
1660*b1cdbd2cSJim Jagielski XML_min, OString::valueOf( (sal_Int32) (mnFirstXclCol+1) ).getStr(),
1661*b1cdbd2cSJim Jagielski // OOXTODO: XML_outlineLevel,
1662*b1cdbd2cSJim Jagielski // OOXTODO: XML_phonetic,
1663*b1cdbd2cSJim Jagielski XML_style, lcl_GetStyleId( rStrm, maXFId.mnXFIndex ).getStr(),
1664*b1cdbd2cSJim Jagielski XML_width, OString::valueOf( (double) (mnWidth / 255.0) ).getStr(),
1665*b1cdbd2cSJim Jagielski FSEND );
1666*b1cdbd2cSJim Jagielski }
1667*b1cdbd2cSJim Jagielski
1668*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1669*b1cdbd2cSJim Jagielski
XclExpColinfoBuffer(const XclExpRoot & rRoot)1670*b1cdbd2cSJim Jagielski XclExpColinfoBuffer::XclExpColinfoBuffer( const XclExpRoot& rRoot ) :
1671*b1cdbd2cSJim Jagielski XclExpRoot( rRoot ),
1672*b1cdbd2cSJim Jagielski maDefcolwidth( rRoot ),
1673*b1cdbd2cSJim Jagielski maOutlineBfr( rRoot )
1674*b1cdbd2cSJim Jagielski {
1675*b1cdbd2cSJim Jagielski }
1676*b1cdbd2cSJim Jagielski
Initialize(SCROW nLastScRow)1677*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::Initialize( SCROW nLastScRow )
1678*b1cdbd2cSJim Jagielski {
1679*b1cdbd2cSJim Jagielski
1680*b1cdbd2cSJim Jagielski for( sal_uInt16 nScCol = 0, nLastScCol = GetMaxPos().Col(); nScCol <= nLastScCol; ++nScCol )
1681*b1cdbd2cSJim Jagielski maColInfos.AppendNewRecord( new XclExpColinfo( GetRoot(), nScCol, nLastScRow, maOutlineBfr ) );
1682*b1cdbd2cSJim Jagielski }
1683*b1cdbd2cSJim Jagielski
Finalize(ScfUInt16Vec & rXFIndexes)1684*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes )
1685*b1cdbd2cSJim Jagielski {
1686*b1cdbd2cSJim Jagielski rXFIndexes.clear();
1687*b1cdbd2cSJim Jagielski rXFIndexes.reserve( maColInfos.GetSize() );
1688*b1cdbd2cSJim Jagielski
1689*b1cdbd2cSJim Jagielski size_t nPos, nSize;
1690*b1cdbd2cSJim Jagielski
1691*b1cdbd2cSJim Jagielski // do not cache the record list size, it may change in the loop
1692*b1cdbd2cSJim Jagielski for( nPos = 0; nPos < maColInfos.GetSize(); ++nPos )
1693*b1cdbd2cSJim Jagielski {
1694*b1cdbd2cSJim Jagielski XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1695*b1cdbd2cSJim Jagielski xRec->ConvertXFIndexes();
1696*b1cdbd2cSJim Jagielski
1697*b1cdbd2cSJim Jagielski // try to merge with previous record
1698*b1cdbd2cSJim Jagielski if( nPos > 0 )
1699*b1cdbd2cSJim Jagielski {
1700*b1cdbd2cSJim Jagielski XclExpColinfoRef xPrevRec = maColInfos.GetRecord( nPos - 1 );
1701*b1cdbd2cSJim Jagielski if( xPrevRec->TryMerge( *xRec ) )
1702*b1cdbd2cSJim Jagielski // adjust nPos to get the next COLINFO record at the same position
1703*b1cdbd2cSJim Jagielski maColInfos.RemoveRecord( nPos-- );
1704*b1cdbd2cSJim Jagielski }
1705*b1cdbd2cSJim Jagielski }
1706*b1cdbd2cSJim Jagielski
1707*b1cdbd2cSJim Jagielski // put XF indexes into passed vector, collect use count of all different widths
1708*b1cdbd2cSJim Jagielski typedef ::std::map< sal_uInt16, sal_uInt16 > XclExpWidthMap;
1709*b1cdbd2cSJim Jagielski XclExpWidthMap aWidthMap;
1710*b1cdbd2cSJim Jagielski sal_uInt16 nMaxColCount = 0;
1711*b1cdbd2cSJim Jagielski sal_uInt16 nMaxUsedWidth = 0;
1712*b1cdbd2cSJim Jagielski for( nPos = 0, nSize = maColInfos.GetSize(); nPos < nSize; ++nPos )
1713*b1cdbd2cSJim Jagielski {
1714*b1cdbd2cSJim Jagielski XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1715*b1cdbd2cSJim Jagielski sal_uInt16 nColCount = xRec->GetColCount();
1716*b1cdbd2cSJim Jagielski
1717*b1cdbd2cSJim Jagielski // add XF index to passed vector
1718*b1cdbd2cSJim Jagielski rXFIndexes.resize( rXFIndexes.size() + nColCount, xRec->GetXFIndex() );
1719*b1cdbd2cSJim Jagielski
1720*b1cdbd2cSJim Jagielski // collect use count of column width
1721*b1cdbd2cSJim Jagielski sal_uInt16 nWidth = xRec->GetColWidth();
1722*b1cdbd2cSJim Jagielski sal_uInt16& rnMapCount = aWidthMap[ nWidth ];
1723*b1cdbd2cSJim Jagielski rnMapCount = rnMapCount + nColCount;
1724*b1cdbd2cSJim Jagielski if( rnMapCount > nMaxColCount )
1725*b1cdbd2cSJim Jagielski {
1726*b1cdbd2cSJim Jagielski nMaxColCount = rnMapCount;
1727*b1cdbd2cSJim Jagielski nMaxUsedWidth = nWidth;
1728*b1cdbd2cSJim Jagielski }
1729*b1cdbd2cSJim Jagielski }
1730*b1cdbd2cSJim Jagielski maDefcolwidth.SetDefWidth( nMaxUsedWidth );
1731*b1cdbd2cSJim Jagielski
1732*b1cdbd2cSJim Jagielski // remove all default COLINFO records
1733*b1cdbd2cSJim Jagielski nPos = 0;
1734*b1cdbd2cSJim Jagielski while( nPos < maColInfos.GetSize() )
1735*b1cdbd2cSJim Jagielski {
1736*b1cdbd2cSJim Jagielski XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1737*b1cdbd2cSJim Jagielski if( xRec->IsDefault( maDefcolwidth ) )
1738*b1cdbd2cSJim Jagielski maColInfos.RemoveRecord( nPos );
1739*b1cdbd2cSJim Jagielski else
1740*b1cdbd2cSJim Jagielski ++nPos;
1741*b1cdbd2cSJim Jagielski }
1742*b1cdbd2cSJim Jagielski }
1743*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)1744*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::Save( XclExpStream& rStrm )
1745*b1cdbd2cSJim Jagielski {
1746*b1cdbd2cSJim Jagielski // DEFCOLWIDTH
1747*b1cdbd2cSJim Jagielski maDefcolwidth.Save( rStrm );
1748*b1cdbd2cSJim Jagielski // COLINFO records
1749*b1cdbd2cSJim Jagielski maColInfos.Save( rStrm );
1750*b1cdbd2cSJim Jagielski }
1751*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)1752*b1cdbd2cSJim Jagielski void XclExpColinfoBuffer::SaveXml( XclExpXmlStream& rStrm )
1753*b1cdbd2cSJim Jagielski {
1754*b1cdbd2cSJim Jagielski if( maColInfos.IsEmpty() )
1755*b1cdbd2cSJim Jagielski return;
1756*b1cdbd2cSJim Jagielski
1757*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1758*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_cols,
1759*b1cdbd2cSJim Jagielski FSEND );
1760*b1cdbd2cSJim Jagielski maColInfos.SaveXml( rStrm );
1761*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_cols );
1762*b1cdbd2cSJim Jagielski }
1763*b1cdbd2cSJim Jagielski
1764*b1cdbd2cSJim Jagielski // ============================================================================
1765*b1cdbd2cSJim Jagielski
XclExpDefaultRowData()1766*b1cdbd2cSJim Jagielski XclExpDefaultRowData::XclExpDefaultRowData() :
1767*b1cdbd2cSJim Jagielski mnFlags( EXC_DEFROW_DEFAULTFLAGS ),
1768*b1cdbd2cSJim Jagielski mnHeight( EXC_DEFROW_DEFAULTHEIGHT )
1769*b1cdbd2cSJim Jagielski {
1770*b1cdbd2cSJim Jagielski }
1771*b1cdbd2cSJim Jagielski
XclExpDefaultRowData(const XclExpRow & rRow)1772*b1cdbd2cSJim Jagielski XclExpDefaultRowData::XclExpDefaultRowData( const XclExpRow& rRow ) :
1773*b1cdbd2cSJim Jagielski mnFlags( EXC_DEFROW_DEFAULTFLAGS ),
1774*b1cdbd2cSJim Jagielski mnHeight( rRow.GetHeight() )
1775*b1cdbd2cSJim Jagielski {
1776*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_DEFROW_HIDDEN, rRow.IsHidden() );
1777*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_DEFROW_UNSYNCED, rRow.IsUnsynced() );
1778*b1cdbd2cSJim Jagielski }
1779*b1cdbd2cSJim Jagielski
operator <(const XclExpDefaultRowData & rLeft,const XclExpDefaultRowData & rRight)1780*b1cdbd2cSJim Jagielski bool operator<( const XclExpDefaultRowData& rLeft, const XclExpDefaultRowData& rRight )
1781*b1cdbd2cSJim Jagielski {
1782*b1cdbd2cSJim Jagielski return (rLeft.mnHeight < rRight.mnHeight) ||
1783*b1cdbd2cSJim Jagielski ((rLeft.mnHeight == rRight.mnHeight) && (rLeft.mnFlags < rRight.mnFlags));
1784*b1cdbd2cSJim Jagielski }
1785*b1cdbd2cSJim Jagielski
1786*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1787*b1cdbd2cSJim Jagielski
XclExpDefrowheight()1788*b1cdbd2cSJim Jagielski XclExpDefrowheight::XclExpDefrowheight() :
1789*b1cdbd2cSJim Jagielski XclExpRecord( EXC_ID3_DEFROWHEIGHT, 4 )
1790*b1cdbd2cSJim Jagielski {
1791*b1cdbd2cSJim Jagielski }
1792*b1cdbd2cSJim Jagielski
SetDefaultData(const XclExpDefaultRowData & rDefData)1793*b1cdbd2cSJim Jagielski void XclExpDefrowheight::SetDefaultData( const XclExpDefaultRowData& rDefData )
1794*b1cdbd2cSJim Jagielski {
1795*b1cdbd2cSJim Jagielski maDefData = rDefData;
1796*b1cdbd2cSJim Jagielski }
1797*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)1798*b1cdbd2cSJim Jagielski void XclExpDefrowheight::WriteBody( XclExpStream& rStrm )
1799*b1cdbd2cSJim Jagielski {
1800*b1cdbd2cSJim Jagielski DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1801*b1cdbd2cSJim Jagielski rStrm << maDefData.mnFlags << maDefData.mnHeight;
1802*b1cdbd2cSJim Jagielski }
1803*b1cdbd2cSJim Jagielski
1804*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
1805*b1cdbd2cSJim Jagielski
XclExpRow(const XclExpRoot & rRoot,sal_uInt16 nXclRow,XclExpRowOutlineBuffer & rOutlineBfr,bool bAlwaysEmpty)1806*b1cdbd2cSJim Jagielski XclExpRow::XclExpRow( const XclExpRoot& rRoot, sal_uInt16 nXclRow,
1807*b1cdbd2cSJim Jagielski XclExpRowOutlineBuffer& rOutlineBfr, bool bAlwaysEmpty ) :
1808*b1cdbd2cSJim Jagielski XclExpRecord( EXC_ID3_ROW, 16 ),
1809*b1cdbd2cSJim Jagielski XclExpRoot( rRoot ),
1810*b1cdbd2cSJim Jagielski mnXclRow( nXclRow ),
1811*b1cdbd2cSJim Jagielski mnHeight( 0 ),
1812*b1cdbd2cSJim Jagielski mnFlags( EXC_ROW_DEFAULTFLAGS ),
1813*b1cdbd2cSJim Jagielski mnXFIndex( EXC_XF_DEFAULTCELL ),
1814*b1cdbd2cSJim Jagielski mnOutlineLevel( 0 ),
1815*b1cdbd2cSJim Jagielski mbAlwaysEmpty( bAlwaysEmpty ),
1816*b1cdbd2cSJim Jagielski mbEnabled( true )
1817*b1cdbd2cSJim Jagielski {
1818*b1cdbd2cSJim Jagielski SCTAB nScTab = GetCurrScTab();
1819*b1cdbd2cSJim Jagielski SCROW nScRow = static_cast< SCROW >( mnXclRow );
1820*b1cdbd2cSJim Jagielski
1821*b1cdbd2cSJim Jagielski // *** Row flags *** ------------------------------------------------------
1822*b1cdbd2cSJim Jagielski
1823*b1cdbd2cSJim Jagielski sal_uInt8 nRowFlags = GetDoc().GetRowFlags( nScRow, nScTab );
1824*b1cdbd2cSJim Jagielski bool bUserHeight = ::get_flag< sal_uInt8 >( nRowFlags, CR_MANUALSIZE );
1825*b1cdbd2cSJim Jagielski bool bHidden = GetDoc().RowHidden(nScRow, nScTab);
1826*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_ROW_UNSYNCED, bUserHeight );
1827*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_ROW_HIDDEN, bHidden );
1828*b1cdbd2cSJim Jagielski
1829*b1cdbd2cSJim Jagielski // *** Row height *** -----------------------------------------------------
1830*b1cdbd2cSJim Jagielski
1831*b1cdbd2cSJim Jagielski if (bUserHeight)
1832*b1cdbd2cSJim Jagielski mnHeight = GetDoc().GetRowHeight(nScRow, nScTab, false);
1833*b1cdbd2cSJim Jagielski else
1834*b1cdbd2cSJim Jagielski mnHeight = EXC_ROW_DEFAULTHEIGHT;
1835*b1cdbd2cSJim Jagielski
1836*b1cdbd2cSJim Jagielski // #76250# not usable in Applix
1837*b1cdbd2cSJim Jagielski // ::set_flag( mnHeight, EXC_ROW_FLAGDEFHEIGHT, !bUserHeight );
1838*b1cdbd2cSJim Jagielski
1839*b1cdbd2cSJim Jagielski // *** Outline data *** ---------------------------------------------------
1840*b1cdbd2cSJim Jagielski
1841*b1cdbd2cSJim Jagielski rOutlineBfr.Update( nScRow );
1842*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_ROW_COLLAPSED, rOutlineBfr.IsCollapsed() );
1843*b1cdbd2cSJim Jagielski ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 0, 3 );
1844*b1cdbd2cSJim Jagielski mnOutlineLevel = rOutlineBfr.GetLevel();
1845*b1cdbd2cSJim Jagielski
1846*b1cdbd2cSJim Jagielski // *** Progress bar *** ---------------------------------------------------
1847*b1cdbd2cSJim Jagielski
1848*b1cdbd2cSJim Jagielski XclExpProgressBar& rProgress = GetProgressBar();
1849*b1cdbd2cSJim Jagielski rProgress.IncRowRecordCount();
1850*b1cdbd2cSJim Jagielski rProgress.Progress();
1851*b1cdbd2cSJim Jagielski }
1852*b1cdbd2cSJim Jagielski
AppendCell(XclExpCellRef xCell,bool bIsMergedBase)1853*b1cdbd2cSJim Jagielski void XclExpRow::AppendCell( XclExpCellRef xCell, bool bIsMergedBase )
1854*b1cdbd2cSJim Jagielski {
1855*b1cdbd2cSJim Jagielski DBG_ASSERT( !mbAlwaysEmpty, "XclExpRow::AppendCell - row is marked to be always empty" );
1856*b1cdbd2cSJim Jagielski // try to merge with last existing cell
1857*b1cdbd2cSJim Jagielski InsertCell( xCell, maCellList.GetSize(), bIsMergedBase );
1858*b1cdbd2cSJim Jagielski }
1859*b1cdbd2cSJim Jagielski
Finalize(const ScfUInt16Vec & rColXFIndexes)1860*b1cdbd2cSJim Jagielski void XclExpRow::Finalize( const ScfUInt16Vec& rColXFIndexes )
1861*b1cdbd2cSJim Jagielski {
1862*b1cdbd2cSJim Jagielski size_t nPos, nSize;
1863*b1cdbd2cSJim Jagielski
1864*b1cdbd2cSJim Jagielski // *** Convert XF identifiers *** -----------------------------------------
1865*b1cdbd2cSJim Jagielski
1866*b1cdbd2cSJim Jagielski // additionally collect the blank XF indexes
1867*b1cdbd2cSJim Jagielski size_t nColCount = GetMaxPos().Col() + 1;
1868*b1cdbd2cSJim Jagielski DBG_ASSERT( rColXFIndexes.size() == nColCount, "XclExpRow::Finalize - wrong column XF index count" );
1869*b1cdbd2cSJim Jagielski
1870*b1cdbd2cSJim Jagielski ScfUInt16Vec aXFIndexes( nColCount, EXC_XF_NOTFOUND );
1871*b1cdbd2cSJim Jagielski for( nPos = 0, nSize = maCellList.GetSize(); nPos < nSize; ++nPos )
1872*b1cdbd2cSJim Jagielski {
1873*b1cdbd2cSJim Jagielski XclExpCellRef xCell = maCellList.GetRecord( nPos );
1874*b1cdbd2cSJim Jagielski xCell->ConvertXFIndexes( GetRoot() );
1875*b1cdbd2cSJim Jagielski xCell->GetBlankXFIndexes( aXFIndexes );
1876*b1cdbd2cSJim Jagielski }
1877*b1cdbd2cSJim Jagielski
1878*b1cdbd2cSJim Jagielski // *** Fill gaps with BLANK/MULBLANK cell records *** ---------------------
1879*b1cdbd2cSJim Jagielski
1880*b1cdbd2cSJim Jagielski /* This is needed because nonexistant cells in Calc are not formatted at all,
1881*b1cdbd2cSJim Jagielski but in Excel they would have the column default format. Blank cells that
1882*b1cdbd2cSJim Jagielski are equal to the respective column default are removed later in this function. */
1883*b1cdbd2cSJim Jagielski if( !mbAlwaysEmpty )
1884*b1cdbd2cSJim Jagielski {
1885*b1cdbd2cSJim Jagielski // XF identifier representing default cell XF
1886*b1cdbd2cSJim Jagielski XclExpMultiXFId aXFId( XclExpXFBuffer::GetDefCellXFId() );
1887*b1cdbd2cSJim Jagielski aXFId.ConvertXFIndex( GetRoot() );
1888*b1cdbd2cSJim Jagielski
1889*b1cdbd2cSJim Jagielski nPos = 0;
1890*b1cdbd2cSJim Jagielski while( nPos <= maCellList.GetSize() ) // don't cache list size, may change in the loop
1891*b1cdbd2cSJim Jagielski {
1892*b1cdbd2cSJim Jagielski // get column index that follows previous cell
1893*b1cdbd2cSJim Jagielski sal_uInt16 nFirstFreeXclCol = (nPos > 0) ? (maCellList.GetRecord( nPos - 1 )->GetLastXclCol() + 1) : 0;
1894*b1cdbd2cSJim Jagielski // get own column index
1895*b1cdbd2cSJim Jagielski sal_uInt16 nNextUsedXclCol = (nPos < maCellList.GetSize()) ? maCellList.GetRecord( nPos )->GetXclCol() : (GetMaxPos().Col() + 1);
1896*b1cdbd2cSJim Jagielski
1897*b1cdbd2cSJim Jagielski // is there a gap?
1898*b1cdbd2cSJim Jagielski if( nFirstFreeXclCol < nNextUsedXclCol )
1899*b1cdbd2cSJim Jagielski {
1900*b1cdbd2cSJim Jagielski aXFId.mnCount = nNextUsedXclCol - nFirstFreeXclCol;
1901*b1cdbd2cSJim Jagielski XclExpCellRef xNewCell( new XclExpBlankCell( XclAddress( nFirstFreeXclCol, mnXclRow ), aXFId ) );
1902*b1cdbd2cSJim Jagielski // insert the cell, InsertCell() may merge it with existing BLANK records
1903*b1cdbd2cSJim Jagielski InsertCell( xNewCell, nPos, false );
1904*b1cdbd2cSJim Jagielski // insert default XF indexes into aXFIndexes
1905*b1cdbd2cSJim Jagielski ::std::fill( aXFIndexes.begin() + nFirstFreeXclCol,
1906*b1cdbd2cSJim Jagielski aXFIndexes.begin() + nNextUsedXclCol, aXFId.mnXFIndex );
1907*b1cdbd2cSJim Jagielski // don't step forward with nPos, InsertCell() may remove records
1908*b1cdbd2cSJim Jagielski }
1909*b1cdbd2cSJim Jagielski else
1910*b1cdbd2cSJim Jagielski ++nPos;
1911*b1cdbd2cSJim Jagielski }
1912*b1cdbd2cSJim Jagielski }
1913*b1cdbd2cSJim Jagielski
1914*b1cdbd2cSJim Jagielski // *** Find default row format *** ----------------------------------------
1915*b1cdbd2cSJim Jagielski
1916*b1cdbd2cSJim Jagielski ScfUInt16Vec::iterator aCellBeg = aXFIndexes.begin(), aCellEnd = aXFIndexes.end(), aCellIt;
1917*b1cdbd2cSJim Jagielski ScfUInt16Vec::const_iterator aColBeg = rColXFIndexes.begin(), aColIt;
1918*b1cdbd2cSJim Jagielski
1919*b1cdbd2cSJim Jagielski // find most used XF index in the row
1920*b1cdbd2cSJim Jagielski typedef ::std::map< sal_uInt16, size_t > XclExpXFIndexMap;
1921*b1cdbd2cSJim Jagielski XclExpXFIndexMap aIndexMap;
1922*b1cdbd2cSJim Jagielski sal_uInt16 nRowXFIndex = EXC_XF_DEFAULTCELL;
1923*b1cdbd2cSJim Jagielski size_t nMaxXFCount = 0;
1924*b1cdbd2cSJim Jagielski for( aCellIt = aCellBeg; aCellIt != aCellEnd; ++aCellIt )
1925*b1cdbd2cSJim Jagielski {
1926*b1cdbd2cSJim Jagielski if( *aCellIt != EXC_XF_NOTFOUND )
1927*b1cdbd2cSJim Jagielski {
1928*b1cdbd2cSJim Jagielski size_t& rnCount = aIndexMap[ *aCellIt ];
1929*b1cdbd2cSJim Jagielski ++rnCount;
1930*b1cdbd2cSJim Jagielski if( rnCount > nMaxXFCount )
1931*b1cdbd2cSJim Jagielski {
1932*b1cdbd2cSJim Jagielski nRowXFIndex = *aCellIt;
1933*b1cdbd2cSJim Jagielski nMaxXFCount = rnCount;
1934*b1cdbd2cSJim Jagielski }
1935*b1cdbd2cSJim Jagielski }
1936*b1cdbd2cSJim Jagielski }
1937*b1cdbd2cSJim Jagielski
1938*b1cdbd2cSJim Jagielski // decide whether to use the row default XF index or column default XF indexes
1939*b1cdbd2cSJim Jagielski bool bUseColDefXFs = nRowXFIndex == EXC_XF_DEFAULTCELL;
1940*b1cdbd2cSJim Jagielski if( !bUseColDefXFs )
1941*b1cdbd2cSJim Jagielski {
1942*b1cdbd2cSJim Jagielski // count needed XF indexes for blank cells with and without row default XF index
1943*b1cdbd2cSJim Jagielski size_t nXFCountWithRowDefXF = 0;
1944*b1cdbd2cSJim Jagielski size_t nXFCountWithoutRowDefXF = 0;
1945*b1cdbd2cSJim Jagielski for( aCellIt = aCellBeg, aColIt = aColBeg; aCellIt != aCellEnd; ++aCellIt, ++aColIt )
1946*b1cdbd2cSJim Jagielski {
1947*b1cdbd2cSJim Jagielski sal_uInt16 nXFIndex = *aCellIt;
1948*b1cdbd2cSJim Jagielski if( nXFIndex != EXC_XF_NOTFOUND )
1949*b1cdbd2cSJim Jagielski {
1950*b1cdbd2cSJim Jagielski if( nXFIndex != nRowXFIndex )
1951*b1cdbd2cSJim Jagielski ++nXFCountWithRowDefXF; // with row default XF index
1952*b1cdbd2cSJim Jagielski if( nXFIndex != *aColIt )
1953*b1cdbd2cSJim Jagielski ++nXFCountWithoutRowDefXF; // without row default XF index
1954*b1cdbd2cSJim Jagielski }
1955*b1cdbd2cSJim Jagielski }
1956*b1cdbd2cSJim Jagielski
1957*b1cdbd2cSJim Jagielski // use column XF indexes if this would cause less or equal number of BLANK records
1958*b1cdbd2cSJim Jagielski bUseColDefXFs = nXFCountWithoutRowDefXF <= nXFCountWithRowDefXF;
1959*b1cdbd2cSJim Jagielski }
1960*b1cdbd2cSJim Jagielski
1961*b1cdbd2cSJim Jagielski // *** Remove unused BLANK cell records *** -------------------------------
1962*b1cdbd2cSJim Jagielski
1963*b1cdbd2cSJim Jagielski if( bUseColDefXFs )
1964*b1cdbd2cSJim Jagielski {
1965*b1cdbd2cSJim Jagielski // use column default XF indexes
1966*b1cdbd2cSJim Jagielski // #i194#: remove cell XF indexes equal to column default XF indexes
1967*b1cdbd2cSJim Jagielski for( aCellIt = aCellBeg, aColIt = aColBeg; aCellIt != aCellEnd; ++aCellIt, ++aColIt )
1968*b1cdbd2cSJim Jagielski if( *aCellIt == *aColIt )
1969*b1cdbd2cSJim Jagielski *aCellIt = EXC_XF_NOTFOUND;
1970*b1cdbd2cSJim Jagielski }
1971*b1cdbd2cSJim Jagielski else
1972*b1cdbd2cSJim Jagielski {
1973*b1cdbd2cSJim Jagielski // use row default XF index
1974*b1cdbd2cSJim Jagielski mnXFIndex = nRowXFIndex;
1975*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_ROW_USEDEFXF );
1976*b1cdbd2cSJim Jagielski // #98133#, #i194#, #i27407#: remove cell XF indexes equal to row default XF index
1977*b1cdbd2cSJim Jagielski for( aCellIt = aCellBeg; aCellIt != aCellEnd; ++aCellIt )
1978*b1cdbd2cSJim Jagielski if( *aCellIt == nRowXFIndex )
1979*b1cdbd2cSJim Jagielski *aCellIt = EXC_XF_NOTFOUND;
1980*b1cdbd2cSJim Jagielski }
1981*b1cdbd2cSJim Jagielski
1982*b1cdbd2cSJim Jagielski // remove unused parts of BLANK/MULBLANK cell records
1983*b1cdbd2cSJim Jagielski nPos = 0;
1984*b1cdbd2cSJim Jagielski while( nPos < maCellList.GetSize() ) // do not cache list size, may change in the loop
1985*b1cdbd2cSJim Jagielski {
1986*b1cdbd2cSJim Jagielski XclExpCellRef xCell = maCellList.GetRecord( nPos );
1987*b1cdbd2cSJim Jagielski xCell->RemoveUnusedBlankCells( aXFIndexes );
1988*b1cdbd2cSJim Jagielski if( xCell->IsEmpty() )
1989*b1cdbd2cSJim Jagielski maCellList.RemoveRecord( nPos );
1990*b1cdbd2cSJim Jagielski else
1991*b1cdbd2cSJim Jagielski ++nPos;
1992*b1cdbd2cSJim Jagielski }
1993*b1cdbd2cSJim Jagielski
1994*b1cdbd2cSJim Jagielski // progress bar includes disabled rows
1995*b1cdbd2cSJim Jagielski GetProgressBar().Progress();
1996*b1cdbd2cSJim Jagielski }
1997*b1cdbd2cSJim Jagielski
GetFirstUsedXclCol() const1998*b1cdbd2cSJim Jagielski sal_uInt16 XclExpRow::GetFirstUsedXclCol() const
1999*b1cdbd2cSJim Jagielski {
2000*b1cdbd2cSJim Jagielski return maCellList.IsEmpty() ? 0 : maCellList.GetFirstRecord()->GetXclCol();
2001*b1cdbd2cSJim Jagielski }
2002*b1cdbd2cSJim Jagielski
GetFirstFreeXclCol() const2003*b1cdbd2cSJim Jagielski sal_uInt16 XclExpRow::GetFirstFreeXclCol() const
2004*b1cdbd2cSJim Jagielski {
2005*b1cdbd2cSJim Jagielski return maCellList.IsEmpty() ? 0 : (maCellList.GetLastRecord()->GetLastXclCol() + 1);
2006*b1cdbd2cSJim Jagielski }
2007*b1cdbd2cSJim Jagielski
IsDefaultable() const2008*b1cdbd2cSJim Jagielski bool XclExpRow::IsDefaultable() const
2009*b1cdbd2cSJim Jagielski {
2010*b1cdbd2cSJim Jagielski const sal_uInt16 nAllowedFlags = EXC_ROW_DEFAULTFLAGS | EXC_ROW_HIDDEN | EXC_ROW_UNSYNCED;
2011*b1cdbd2cSJim Jagielski return !::get_flag( mnFlags, static_cast< sal_uInt16 >( ~nAllowedFlags ) ) && IsEmpty();
2012*b1cdbd2cSJim Jagielski }
2013*b1cdbd2cSJim Jagielski
DisableIfDefault(const XclExpDefaultRowData & rDefRowData)2014*b1cdbd2cSJim Jagielski void XclExpRow::DisableIfDefault( const XclExpDefaultRowData& rDefRowData )
2015*b1cdbd2cSJim Jagielski {
2016*b1cdbd2cSJim Jagielski mbEnabled = !IsDefaultable() ||
2017*b1cdbd2cSJim Jagielski (mnHeight != rDefRowData.mnHeight) ||
2018*b1cdbd2cSJim Jagielski (IsHidden() != rDefRowData.IsHidden()) ||
2019*b1cdbd2cSJim Jagielski (IsUnsynced() != rDefRowData.IsUnsynced());
2020*b1cdbd2cSJim Jagielski }
2021*b1cdbd2cSJim Jagielski
WriteCellList(XclExpStream & rStrm)2022*b1cdbd2cSJim Jagielski void XclExpRow::WriteCellList( XclExpStream& rStrm )
2023*b1cdbd2cSJim Jagielski {
2024*b1cdbd2cSJim Jagielski DBG_ASSERT( mbEnabled || maCellList.IsEmpty(), "XclExpRow::WriteCellList - cells in disabled row" );
2025*b1cdbd2cSJim Jagielski maCellList.Save( rStrm );
2026*b1cdbd2cSJim Jagielski }
2027*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)2028*b1cdbd2cSJim Jagielski void XclExpRow::Save( XclExpStream& rStrm )
2029*b1cdbd2cSJim Jagielski {
2030*b1cdbd2cSJim Jagielski if( mbEnabled )
2031*b1cdbd2cSJim Jagielski XclExpRecord::Save( rStrm );
2032*b1cdbd2cSJim Jagielski }
2033*b1cdbd2cSJim Jagielski
InsertCell(XclExpCellRef xCell,size_t nPos,bool bIsMergedBase)2034*b1cdbd2cSJim Jagielski void XclExpRow::InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase )
2035*b1cdbd2cSJim Jagielski {
2036*b1cdbd2cSJim Jagielski DBG_ASSERT( xCell.is(), "XclExpRow::InsertCell - missing cell" );
2037*b1cdbd2cSJim Jagielski
2038*b1cdbd2cSJim Jagielski /* #109751# If we have a multi-line text in a merged cell, and the resulting
2039*b1cdbd2cSJim Jagielski row height has not been confirmed, we need to force the EXC_ROW_UNSYNCED
2040*b1cdbd2cSJim Jagielski flag to be true to ensure Excel works correctly. */
2041*b1cdbd2cSJim Jagielski if( bIsMergedBase && xCell->IsMultiLineText() )
2042*b1cdbd2cSJim Jagielski ::set_flag( mnFlags, EXC_ROW_UNSYNCED );
2043*b1cdbd2cSJim Jagielski
2044*b1cdbd2cSJim Jagielski // try to merge with previous cell, insert the new cell if not successful
2045*b1cdbd2cSJim Jagielski XclExpCellRef xPrevCell = maCellList.GetRecord( nPos - 1 );
2046*b1cdbd2cSJim Jagielski if( xPrevCell.is() && xPrevCell->TryMerge( *xCell ) )
2047*b1cdbd2cSJim Jagielski xCell = xPrevCell;
2048*b1cdbd2cSJim Jagielski else
2049*b1cdbd2cSJim Jagielski maCellList.InsertRecord( xCell, nPos++ );
2050*b1cdbd2cSJim Jagielski // nPos points now to following cell
2051*b1cdbd2cSJim Jagielski
2052*b1cdbd2cSJim Jagielski // try to merge with following cell, remove it if successful
2053*b1cdbd2cSJim Jagielski XclExpCellRef xNextCell = maCellList.GetRecord( nPos );
2054*b1cdbd2cSJim Jagielski if( xNextCell.is() && xCell->TryMerge( *xNextCell ) )
2055*b1cdbd2cSJim Jagielski maCellList.RemoveRecord( nPos );
2056*b1cdbd2cSJim Jagielski }
2057*b1cdbd2cSJim Jagielski
WriteBody(XclExpStream & rStrm)2058*b1cdbd2cSJim Jagielski void XclExpRow::WriteBody( XclExpStream& rStrm )
2059*b1cdbd2cSJim Jagielski {
2060*b1cdbd2cSJim Jagielski rStrm << mnXclRow
2061*b1cdbd2cSJim Jagielski << GetFirstUsedXclCol()
2062*b1cdbd2cSJim Jagielski << GetFirstFreeXclCol()
2063*b1cdbd2cSJim Jagielski << mnHeight
2064*b1cdbd2cSJim Jagielski << sal_uInt32( 0 )
2065*b1cdbd2cSJim Jagielski << mnFlags
2066*b1cdbd2cSJim Jagielski << mnXFIndex;
2067*b1cdbd2cSJim Jagielski }
2068*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)2069*b1cdbd2cSJim Jagielski void XclExpRow::SaveXml( XclExpXmlStream& rStrm )
2070*b1cdbd2cSJim Jagielski {
2071*b1cdbd2cSJim Jagielski if( !mbEnabled )
2072*b1cdbd2cSJim Jagielski return;
2073*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2074*b1cdbd2cSJim Jagielski bool haveFormat = ::get_flag( mnFlags, EXC_ROW_USEDEFXF );
2075*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_row,
2076*b1cdbd2cSJim Jagielski XML_r, OString::valueOf( (sal_Int32) (mnXclRow+1) ).getStr(),
2077*b1cdbd2cSJim Jagielski // OOXTODO: XML_spans, optional
2078*b1cdbd2cSJim Jagielski XML_s, haveFormat ? lcl_GetStyleId( rStrm, mnXFIndex ).getStr() : NULL,
2079*b1cdbd2cSJim Jagielski XML_customFormat, XclXmlUtils::ToPsz( haveFormat ),
2080*b1cdbd2cSJim Jagielski XML_ht, OString::valueOf( (double) mnHeight / 20.0 ).getStr(),
2081*b1cdbd2cSJim Jagielski XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_HIDDEN ) ),
2082*b1cdbd2cSJim Jagielski XML_customHeight, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_UNSYNCED ) ),
2083*b1cdbd2cSJim Jagielski XML_outlineLevel, OString::valueOf( (sal_Int32) mnOutlineLevel ).getStr(),
2084*b1cdbd2cSJim Jagielski XML_collapsed, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_ROW_COLLAPSED ) ),
2085*b1cdbd2cSJim Jagielski // OOXTODO: XML_thickTop, bool
2086*b1cdbd2cSJim Jagielski // OOXTODO: XML_thickBot, bool
2087*b1cdbd2cSJim Jagielski // OOXTODO: XML_ph, bool
2088*b1cdbd2cSJim Jagielski FSEND );
2089*b1cdbd2cSJim Jagielski // OOXTODO: XML_extLst
2090*b1cdbd2cSJim Jagielski maCellList.SaveXml( rStrm );
2091*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_row );
2092*b1cdbd2cSJim Jagielski }
2093*b1cdbd2cSJim Jagielski
2094*b1cdbd2cSJim Jagielski // ----------------------------------------------------------------------------
2095*b1cdbd2cSJim Jagielski
XclExpRowBuffer(const XclExpRoot & rRoot)2096*b1cdbd2cSJim Jagielski XclExpRowBuffer::XclExpRowBuffer( const XclExpRoot& rRoot ) :
2097*b1cdbd2cSJim Jagielski XclExpRoot( rRoot ),
2098*b1cdbd2cSJim Jagielski maOutlineBfr( rRoot ),
2099*b1cdbd2cSJim Jagielski maDimensions( rRoot ),
2100*b1cdbd2cSJim Jagielski mpLastUsedRow( 0 ),
2101*b1cdbd2cSJim Jagielski mnLastUsedXclRow( 0 )
2102*b1cdbd2cSJim Jagielski {
2103*b1cdbd2cSJim Jagielski }
2104*b1cdbd2cSJim Jagielski
AppendCell(XclExpCellRef xCell,bool bIsMergedBase)2105*b1cdbd2cSJim Jagielski void XclExpRowBuffer::AppendCell( XclExpCellRef xCell, bool bIsMergedBase )
2106*b1cdbd2cSJim Jagielski {
2107*b1cdbd2cSJim Jagielski DBG_ASSERT( xCell.is(), "XclExpRowBuffer::AppendCell - missing cell" );
2108*b1cdbd2cSJim Jagielski GetOrCreateRow( xCell->GetXclRow(), false ).AppendCell( xCell, bIsMergedBase );
2109*b1cdbd2cSJim Jagielski }
2110*b1cdbd2cSJim Jagielski
CreateRows(SCROW nFirstFreeScRow)2111*b1cdbd2cSJim Jagielski void XclExpRowBuffer::CreateRows( SCROW nFirstFreeScRow )
2112*b1cdbd2cSJim Jagielski {
2113*b1cdbd2cSJim Jagielski if( nFirstFreeScRow > 0 )
2114*b1cdbd2cSJim Jagielski GetOrCreateRow( static_cast< sal_uInt16 >( nFirstFreeScRow - 1 ), true );
2115*b1cdbd2cSJim Jagielski }
2116*b1cdbd2cSJim Jagielski
Finalize(XclExpDefaultRowData & rDefRowData,const ScfUInt16Vec & rColXFIndexes)2117*b1cdbd2cSJim Jagielski void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt16Vec& rColXFIndexes )
2118*b1cdbd2cSJim Jagielski {
2119*b1cdbd2cSJim Jagielski size_t nPos, nSize;
2120*b1cdbd2cSJim Jagielski
2121*b1cdbd2cSJim Jagielski // *** Finalize all rows *** ----------------------------------------------
2122*b1cdbd2cSJim Jagielski
2123*b1cdbd2cSJim Jagielski GetProgressBar().ActivateFinalRowsSegment();
2124*b1cdbd2cSJim Jagielski
2125*b1cdbd2cSJim Jagielski // unused blank cell records will be removed
2126*b1cdbd2cSJim Jagielski for( nPos = 0, nSize = maRowList.GetSize(); nPos < nSize; ++nPos )
2127*b1cdbd2cSJim Jagielski maRowList.GetRecord( nPos )->Finalize( rColXFIndexes );
2128*b1cdbd2cSJim Jagielski
2129*b1cdbd2cSJim Jagielski // *** Default row format *** ---------------------------------------------
2130*b1cdbd2cSJim Jagielski
2131*b1cdbd2cSJim Jagielski typedef ::std::map< XclExpDefaultRowData, size_t > XclExpDefRowDataMap;
2132*b1cdbd2cSJim Jagielski XclExpDefRowDataMap aDefRowMap;
2133*b1cdbd2cSJim Jagielski
2134*b1cdbd2cSJim Jagielski // find default row format for rows beyond used area
2135*b1cdbd2cSJim Jagielski sal_uInt32 nDefaultXclRow = maRowList.IsEmpty() ? 0 : (maRowList.GetLastRecord()->GetXclRow() + 1);
2136*b1cdbd2cSJim Jagielski XclExpDefaultRowData aMaxDefData;
2137*b1cdbd2cSJim Jagielski size_t nMaxDefCount = 0;
2138*b1cdbd2cSJim Jagielski /* #i30411# Files saved with SO7/OOo1.x with nonstandard default column
2139*b1cdbd2cSJim Jagielski formatting cause big Excel files, because all rows from row 1 to row
2140*b1cdbd2cSJim Jagielski 32000 are exported. Now, if the used area goes exactly to row 32000,
2141*b1cdbd2cSJim Jagielski ignore all rows >32000.
2142*b1cdbd2cSJim Jagielski #i59220# Tolerance of +-128 rows for inserted/removed rows. */
2143*b1cdbd2cSJim Jagielski if( (nDefaultXclRow < 31872) || (nDefaultXclRow > 32128) )
2144*b1cdbd2cSJim Jagielski {
2145*b1cdbd2cSJim Jagielski sal_uInt16 nLastXclRow = static_cast< sal_uInt16 >( GetMaxPos().Row() );
2146*b1cdbd2cSJim Jagielski if( nDefaultXclRow <= nLastXclRow )
2147*b1cdbd2cSJim Jagielski {
2148*b1cdbd2cSJim Jagielski // create a dummy ROW record and fill aMaxDefData
2149*b1cdbd2cSJim Jagielski XclExpRowOutlineBuffer aOutlineBfr( GetRoot() );
2150*b1cdbd2cSJim Jagielski XclExpRow aRow( GetRoot(), nLastXclRow, aOutlineBfr, true );
2151*b1cdbd2cSJim Jagielski aMaxDefData = XclExpDefaultRowData( aRow );
2152*b1cdbd2cSJim Jagielski aDefRowMap[ aMaxDefData ] = nMaxDefCount =
2153*b1cdbd2cSJim Jagielski static_cast< size_t >( nLastXclRow - nDefaultXclRow + 1 );
2154*b1cdbd2cSJim Jagielski }
2155*b1cdbd2cSJim Jagielski }
2156*b1cdbd2cSJim Jagielski
2157*b1cdbd2cSJim Jagielski // only look for default format in existing rows, if there are more than unused
2158*b1cdbd2cSJim Jagielski nSize = maRowList.GetSize();
2159*b1cdbd2cSJim Jagielski if( nMaxDefCount < nSize )
2160*b1cdbd2cSJim Jagielski {
2161*b1cdbd2cSJim Jagielski for( nPos = 0; nPos < nSize; ++nPos )
2162*b1cdbd2cSJim Jagielski {
2163*b1cdbd2cSJim Jagielski XclExpRowRef xRow = maRowList.GetRecord( nPos );
2164*b1cdbd2cSJim Jagielski /* Collect formats of unused rows (rows without cells), which are able
2165*b1cdbd2cSJim Jagielski to be defaulted (i.e. no explicit format or outline level). */
2166*b1cdbd2cSJim Jagielski if( xRow->IsDefaultable() )
2167*b1cdbd2cSJim Jagielski {
2168*b1cdbd2cSJim Jagielski XclExpDefaultRowData aDefData( *xRow );
2169*b1cdbd2cSJim Jagielski size_t& rnDefCount = aDefRowMap[ aDefData ];
2170*b1cdbd2cSJim Jagielski ++rnDefCount;
2171*b1cdbd2cSJim Jagielski if( rnDefCount > nMaxDefCount )
2172*b1cdbd2cSJim Jagielski {
2173*b1cdbd2cSJim Jagielski nMaxDefCount = rnDefCount;
2174*b1cdbd2cSJim Jagielski aMaxDefData = aDefData;
2175*b1cdbd2cSJim Jagielski }
2176*b1cdbd2cSJim Jagielski }
2177*b1cdbd2cSJim Jagielski }
2178*b1cdbd2cSJim Jagielski }
2179*b1cdbd2cSJim Jagielski
2180*b1cdbd2cSJim Jagielski // return the default row format to caller
2181*b1cdbd2cSJim Jagielski rDefRowData = aMaxDefData;
2182*b1cdbd2cSJim Jagielski
2183*b1cdbd2cSJim Jagielski // *** Disable unused ROW records, find used area *** ---------------------
2184*b1cdbd2cSJim Jagielski
2185*b1cdbd2cSJim Jagielski sal_uInt16 nFirstUsedXclCol = SAL_MAX_UINT16;
2186*b1cdbd2cSJim Jagielski sal_uInt16 nFirstFreeXclCol = 0;
2187*b1cdbd2cSJim Jagielski sal_uInt32 nFirstUsedXclRow = SAL_MAX_UINT32;
2188*b1cdbd2cSJim Jagielski sal_uInt32 nFirstFreeXclRow = 0;
2189*b1cdbd2cSJim Jagielski
2190*b1cdbd2cSJim Jagielski for( nPos = 0, nSize = maRowList.GetSize(); nPos < nSize; ++nPos )
2191*b1cdbd2cSJim Jagielski {
2192*b1cdbd2cSJim Jagielski XclExpRowRef xRow = maRowList.GetRecord( nPos );
2193*b1cdbd2cSJim Jagielski
2194*b1cdbd2cSJim Jagielski // disable unused rows
2195*b1cdbd2cSJim Jagielski xRow->DisableIfDefault( aMaxDefData );
2196*b1cdbd2cSJim Jagielski
2197*b1cdbd2cSJim Jagielski // find used column range
2198*b1cdbd2cSJim Jagielski if( !xRow->IsEmpty() ) // empty rows return (0...0) as used range
2199*b1cdbd2cSJim Jagielski {
2200*b1cdbd2cSJim Jagielski nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, xRow->GetFirstUsedXclCol() );
2201*b1cdbd2cSJim Jagielski nFirstFreeXclCol = ::std::max( nFirstFreeXclCol, xRow->GetFirstFreeXclCol() );
2202*b1cdbd2cSJim Jagielski }
2203*b1cdbd2cSJim Jagielski
2204*b1cdbd2cSJim Jagielski // find used row range
2205*b1cdbd2cSJim Jagielski if( xRow->IsEnabled() )
2206*b1cdbd2cSJim Jagielski {
2207*b1cdbd2cSJim Jagielski sal_uInt16 nXclRow = xRow->GetXclRow();
2208*b1cdbd2cSJim Jagielski nFirstUsedXclRow = ::std::min< sal_uInt32 >( nFirstUsedXclRow, nXclRow );
2209*b1cdbd2cSJim Jagielski nFirstFreeXclRow = ::std::max< sal_uInt32 >( nFirstFreeXclRow, nXclRow + 1 );
2210*b1cdbd2cSJim Jagielski }
2211*b1cdbd2cSJim Jagielski }
2212*b1cdbd2cSJim Jagielski
2213*b1cdbd2cSJim Jagielski // adjust start position, if there are no or only empty/disabled ROW records
2214*b1cdbd2cSJim Jagielski nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, nFirstFreeXclCol );
2215*b1cdbd2cSJim Jagielski nFirstUsedXclRow = ::std::min( nFirstUsedXclRow, nFirstFreeXclRow );
2216*b1cdbd2cSJim Jagielski
2217*b1cdbd2cSJim Jagielski // initialize the DIMENSIONS record
2218*b1cdbd2cSJim Jagielski maDimensions.SetDimensions(
2219*b1cdbd2cSJim Jagielski nFirstUsedXclCol, nFirstUsedXclRow, nFirstFreeXclCol, nFirstFreeXclRow );
2220*b1cdbd2cSJim Jagielski }
2221*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)2222*b1cdbd2cSJim Jagielski void XclExpRowBuffer::Save( XclExpStream& rStrm )
2223*b1cdbd2cSJim Jagielski {
2224*b1cdbd2cSJim Jagielski // DIMENSIONS record
2225*b1cdbd2cSJim Jagielski maDimensions.Save( rStrm );
2226*b1cdbd2cSJim Jagielski
2227*b1cdbd2cSJim Jagielski // save in blocks of 32 rows, each block contains first all ROWs, then all cells
2228*b1cdbd2cSJim Jagielski size_t nSize = maRowList.GetSize();
2229*b1cdbd2cSJim Jagielski size_t nBlockStart = 0;
2230*b1cdbd2cSJim Jagielski sal_uInt16 nStartXclRow = (nSize == 0) ? 0 : maRowList.GetRecord( 0 )->GetXclRow();
2231*b1cdbd2cSJim Jagielski
2232*b1cdbd2cSJim Jagielski while( nBlockStart < nSize )
2233*b1cdbd2cSJim Jagielski {
2234*b1cdbd2cSJim Jagielski // find end of row block
2235*b1cdbd2cSJim Jagielski size_t nBlockEnd = nBlockStart + 1;
2236*b1cdbd2cSJim Jagielski while( (nBlockEnd < nSize) && (maRowList.GetRecord( nBlockEnd )->GetXclRow() - nStartXclRow < EXC_ROW_ROWBLOCKSIZE) )
2237*b1cdbd2cSJim Jagielski ++nBlockEnd;
2238*b1cdbd2cSJim Jagielski
2239*b1cdbd2cSJim Jagielski // write the ROW records
2240*b1cdbd2cSJim Jagielski size_t nPos;
2241*b1cdbd2cSJim Jagielski for( nPos = nBlockStart; nPos < nBlockEnd; ++nPos )
2242*b1cdbd2cSJim Jagielski maRowList.GetRecord( nPos )->Save( rStrm );
2243*b1cdbd2cSJim Jagielski
2244*b1cdbd2cSJim Jagielski // write the cell records
2245*b1cdbd2cSJim Jagielski for( nPos = nBlockStart; nPos < nBlockEnd; ++nPos )
2246*b1cdbd2cSJim Jagielski maRowList.GetRecord( nPos )->WriteCellList( rStrm );
2247*b1cdbd2cSJim Jagielski
2248*b1cdbd2cSJim Jagielski nBlockStart = nBlockEnd;
2249*b1cdbd2cSJim Jagielski nStartXclRow += EXC_ROW_ROWBLOCKSIZE;
2250*b1cdbd2cSJim Jagielski }
2251*b1cdbd2cSJim Jagielski }
2252*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)2253*b1cdbd2cSJim Jagielski void XclExpRowBuffer::SaveXml( XclExpXmlStream& rStrm )
2254*b1cdbd2cSJim Jagielski {
2255*b1cdbd2cSJim Jagielski sal_Int32 nNonEmpty = 0;
2256*b1cdbd2cSJim Jagielski
2257*b1cdbd2cSJim Jagielski size_t nRows = maRowList.GetSize();
2258*b1cdbd2cSJim Jagielski for( size_t i = 0; i < nRows; ++i)
2259*b1cdbd2cSJim Jagielski if( maRowList.GetRecord( i )->IsEnabled() )
2260*b1cdbd2cSJim Jagielski ++nNonEmpty;
2261*b1cdbd2cSJim Jagielski
2262*b1cdbd2cSJim Jagielski if( nNonEmpty == 0 )
2263*b1cdbd2cSJim Jagielski {
2264*b1cdbd2cSJim Jagielski rStrm.GetCurrentStream()->singleElement( XML_sheetData, FSEND );
2265*b1cdbd2cSJim Jagielski }
2266*b1cdbd2cSJim Jagielski else
2267*b1cdbd2cSJim Jagielski {
2268*b1cdbd2cSJim Jagielski sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2269*b1cdbd2cSJim Jagielski rWorksheet->startElement( XML_sheetData, FSEND );
2270*b1cdbd2cSJim Jagielski maRowList.SaveXml( rStrm );
2271*b1cdbd2cSJim Jagielski rWorksheet->endElement( XML_sheetData );
2272*b1cdbd2cSJim Jagielski }
2273*b1cdbd2cSJim Jagielski }
2274*b1cdbd2cSJim Jagielski
GetDimensions()2275*b1cdbd2cSJim Jagielski XclExpDimensions* XclExpRowBuffer::GetDimensions()
2276*b1cdbd2cSJim Jagielski {
2277*b1cdbd2cSJim Jagielski return &maDimensions;
2278*b1cdbd2cSJim Jagielski }
2279*b1cdbd2cSJim Jagielski
GetOrCreateRow(sal_uInt16 nXclRow,bool bRowAlwaysEmpty)2280*b1cdbd2cSJim Jagielski XclExpRow& XclExpRowBuffer::GetOrCreateRow( sal_uInt16 nXclRow, bool bRowAlwaysEmpty )
2281*b1cdbd2cSJim Jagielski {
2282*b1cdbd2cSJim Jagielski if( !mpLastUsedRow || (mnLastUsedXclRow != nXclRow) )
2283*b1cdbd2cSJim Jagielski {
2284*b1cdbd2cSJim Jagielski // fill up missing ROW records
2285*b1cdbd2cSJim Jagielski // do not use sal_uInt16 for nFirstFreeXclRow, would cause loop in full sheets
2286*b1cdbd2cSJim Jagielski for( size_t nFirstFreeXclRow = maRowList.GetSize(); nFirstFreeXclRow <= nXclRow; ++nFirstFreeXclRow )
2287*b1cdbd2cSJim Jagielski maRowList.AppendNewRecord( new XclExpRow(
2288*b1cdbd2cSJim Jagielski GetRoot(), static_cast< sal_uInt16 >( nFirstFreeXclRow ), maOutlineBfr, bRowAlwaysEmpty ) );
2289*b1cdbd2cSJim Jagielski
2290*b1cdbd2cSJim Jagielski mpLastUsedRow = maRowList.GetRecord( nXclRow ).get();
2291*b1cdbd2cSJim Jagielski mnLastUsedXclRow = nXclRow;
2292*b1cdbd2cSJim Jagielski }
2293*b1cdbd2cSJim Jagielski return *mpLastUsedRow;
2294*b1cdbd2cSJim Jagielski }
2295*b1cdbd2cSJim Jagielski
2296*b1cdbd2cSJim Jagielski // ============================================================================
2297*b1cdbd2cSJim Jagielski // Cell Table
2298*b1cdbd2cSJim Jagielski // ============================================================================
2299*b1cdbd2cSJim Jagielski
XclExpCellTable(const XclExpRoot & rRoot)2300*b1cdbd2cSJim Jagielski XclExpCellTable::XclExpCellTable( const XclExpRoot& rRoot ) :
2301*b1cdbd2cSJim Jagielski XclExpRoot( rRoot ),
2302*b1cdbd2cSJim Jagielski maColInfoBfr( rRoot ),
2303*b1cdbd2cSJim Jagielski maRowBfr( rRoot ),
2304*b1cdbd2cSJim Jagielski maArrayBfr( rRoot ),
2305*b1cdbd2cSJim Jagielski maShrfmlaBfr( rRoot ),
2306*b1cdbd2cSJim Jagielski maTableopBfr( rRoot ),
2307*b1cdbd2cSJim Jagielski mxDefrowheight( new XclExpDefrowheight ),
2308*b1cdbd2cSJim Jagielski mxGuts( new XclExpGuts( rRoot ) ),
2309*b1cdbd2cSJim Jagielski mxNoteList( new XclExpNoteList ),
2310*b1cdbd2cSJim Jagielski mxMergedcells( new XclExpMergedcells( rRoot ) ),
2311*b1cdbd2cSJim Jagielski mxHyperlinkList( new XclExpHyperlinkList ),
2312*b1cdbd2cSJim Jagielski mxDval( new XclExpDval( rRoot ) )
2313*b1cdbd2cSJim Jagielski {
2314*b1cdbd2cSJim Jagielski ScDocument& rDoc = GetDoc();
2315*b1cdbd2cSJim Jagielski SCTAB nScTab = GetCurrScTab();
2316*b1cdbd2cSJim Jagielski SvNumberFormatter& rFormatter = GetFormatter();
2317*b1cdbd2cSJim Jagielski
2318*b1cdbd2cSJim Jagielski // maximum sheet limits
2319*b1cdbd2cSJim Jagielski SCCOL nMaxScCol = GetMaxPos().Col();
2320*b1cdbd2cSJim Jagielski SCROW nMaxScRow = GetMaxPos().Row();
2321*b1cdbd2cSJim Jagielski
2322*b1cdbd2cSJim Jagielski // find used area (non-empty cells)
2323*b1cdbd2cSJim Jagielski SCCOL nLastUsedScCol;
2324*b1cdbd2cSJim Jagielski SCROW nLastUsedScRow;
2325*b1cdbd2cSJim Jagielski rDoc.GetTableArea( nScTab, nLastUsedScCol, nLastUsedScRow );
2326*b1cdbd2cSJim Jagielski
2327*b1cdbd2cSJim Jagielski ScRange aUsedRange( 0, 0, nScTab, nLastUsedScCol, nLastUsedScRow, nScTab );
2328*b1cdbd2cSJim Jagielski GetAddressConverter().ValidateRange( aUsedRange, true );
2329*b1cdbd2cSJim Jagielski nLastUsedScCol = aUsedRange.aEnd.Col();
2330*b1cdbd2cSJim Jagielski nLastUsedScRow = aUsedRange.aEnd.Row();
2331*b1cdbd2cSJim Jagielski
2332*b1cdbd2cSJim Jagielski // first row without any set attributes (height/hidden/...)
2333*b1cdbd2cSJim Jagielski SCROW nFirstUnflaggedScRow = rDoc.GetLastFlaggedRow( nScTab ) + 1;
2334*b1cdbd2cSJim Jagielski
2335*b1cdbd2cSJim Jagielski // find range of outlines
2336*b1cdbd2cSJim Jagielski SCROW nFirstUngroupedScRow = 0;
2337*b1cdbd2cSJim Jagielski if( const ScOutlineTable* pOutlineTable = rDoc.GetOutlineTable( nScTab ) )
2338*b1cdbd2cSJim Jagielski {
2339*b1cdbd2cSJim Jagielski SCCOLROW nScStartPos, nScEndPos;
2340*b1cdbd2cSJim Jagielski if( const ScOutlineArray* pRowArray = pOutlineTable->GetRowArray() )
2341*b1cdbd2cSJim Jagielski {
2342*b1cdbd2cSJim Jagielski pRowArray->GetRange( nScStartPos, nScEndPos );
2343*b1cdbd2cSJim Jagielski // +1 because open/close button is in next row in Excel, +1 for "end->first unused"
2344*b1cdbd2cSJim Jagielski nFirstUngroupedScRow = static_cast< SCROW >( nScEndPos + 2 );
2345*b1cdbd2cSJim Jagielski }
2346*b1cdbd2cSJim Jagielski }
2347*b1cdbd2cSJim Jagielski
2348*b1cdbd2cSJim Jagielski // column settings
2349*b1cdbd2cSJim Jagielski /* #i30411# Files saved with SO7/OOo1.x with nonstandard default column
2350*b1cdbd2cSJim Jagielski formatting cause big Excel files, because all rows from row 1 to row
2351*b1cdbd2cSJim Jagielski 32000 are exported. Now, if the used area goes exactly to row 32000,
2352*b1cdbd2cSJim Jagielski use this row as default and ignore all rows >32000.
2353*b1cdbd2cSJim Jagielski #i59220# Tolerance of +-128 rows for inserted/removed rows. */
2354*b1cdbd2cSJim Jagielski if( (31871 <= nLastUsedScRow) && (nLastUsedScRow <= 32127) && (nFirstUnflaggedScRow < nLastUsedScRow) && (nFirstUngroupedScRow <= nLastUsedScRow) )
2355*b1cdbd2cSJim Jagielski nMaxScRow = nLastUsedScRow;
2356*b1cdbd2cSJim Jagielski maColInfoBfr.Initialize( nMaxScRow );
2357*b1cdbd2cSJim Jagielski
2358*b1cdbd2cSJim Jagielski // range for cell iterator
2359*b1cdbd2cSJim Jagielski SCCOL nLastIterScCol = nMaxScCol;
2360*b1cdbd2cSJim Jagielski SCROW nLastIterScRow = ulimit_cast< SCROW >( nLastUsedScRow + 128, nMaxScRow );
2361*b1cdbd2cSJim Jagielski // modified for 119707 by zhanglu
2362*b1cdbd2cSJim Jagielski
2363*b1cdbd2cSJim Jagielski SCCOL rEndColAtt = 0;
2364*b1cdbd2cSJim Jagielski SCROW rEndRowAtt = 0;
2365*b1cdbd2cSJim Jagielski rDoc.GetLastAttrCell( nScTab, rEndColAtt,rEndRowAtt ); // To get the real last cell's row number, which has visual data or attribute.
2366*b1cdbd2cSJim Jagielski if( rEndRowAtt > nLastIterScRow )
2367*b1cdbd2cSJim Jagielski nLastIterScRow = rEndRowAtt;
2368*b1cdbd2cSJim Jagielski
2369*b1cdbd2cSJim Jagielski if (nLastIterScRow > nMaxScRow)
2370*b1cdbd2cSJim Jagielski nLastIterScRow = nMaxScRow;
2371*b1cdbd2cSJim Jagielski
2372*b1cdbd2cSJim Jagielski // modified for 119707 end
2373*b1cdbd2cSJim Jagielski ScUsedAreaIterator aIt( &rDoc, nScTab, 0, 0, nLastIterScCol, nLastIterScRow );
2374*b1cdbd2cSJim Jagielski
2375*b1cdbd2cSJim Jagielski // activate the correct segment and sub segment at the progress bar
2376*b1cdbd2cSJim Jagielski GetProgressBar().ActivateCreateRowsSegment();
2377*b1cdbd2cSJim Jagielski
2378*b1cdbd2cSJim Jagielski for( bool bIt = aIt.GetNext(); bIt; bIt = aIt.GetNext() )
2379*b1cdbd2cSJim Jagielski {
2380*b1cdbd2cSJim Jagielski SCCOL nScCol = aIt.GetStartCol();
2381*b1cdbd2cSJim Jagielski SCROW nScRow = aIt.GetRow();
2382*b1cdbd2cSJim Jagielski SCCOL nLastScCol = aIt.GetEndCol();
2383*b1cdbd2cSJim Jagielski ScAddress aScPos( nScCol, nScRow, nScTab );
2384*b1cdbd2cSJim Jagielski
2385*b1cdbd2cSJim Jagielski XclAddress aXclPos( static_cast< sal_uInt16 >( nScCol ), static_cast< sal_uInt16 >( nScRow ) );
2386*b1cdbd2cSJim Jagielski sal_uInt16 nLastXclCol = static_cast< sal_uInt16 >( nLastScCol );
2387*b1cdbd2cSJim Jagielski
2388*b1cdbd2cSJim Jagielski const ScBaseCell* pScCell = aIt.GetCell();
2389*b1cdbd2cSJim Jagielski XclExpCellRef xCell;
2390*b1cdbd2cSJim Jagielski
2391*b1cdbd2cSJim Jagielski const ScPatternAttr* pPattern = aIt.GetPattern();
2392*b1cdbd2cSJim Jagielski
2393*b1cdbd2cSJim Jagielski // handle overlapped merged cells before creating the cell record
2394*b1cdbd2cSJim Jagielski sal_uInt32 nMergeBaseXFId = EXC_XFID_NOTFOUND;
2395*b1cdbd2cSJim Jagielski bool bIsMergedBase = false;
2396*b1cdbd2cSJim Jagielski if( pPattern )
2397*b1cdbd2cSJim Jagielski {
2398*b1cdbd2cSJim Jagielski const SfxItemSet& rItemSet = pPattern->GetItemSet();
2399*b1cdbd2cSJim Jagielski // base cell in a merged range
2400*b1cdbd2cSJim Jagielski const ScMergeAttr& rMergeItem = GETITEM( rItemSet, ScMergeAttr, ATTR_MERGE );
2401*b1cdbd2cSJim Jagielski bIsMergedBase = rMergeItem.IsMerged();
2402*b1cdbd2cSJim Jagielski /* overlapped cell in a merged range; in Excel all merged cells
2403*b1cdbd2cSJim Jagielski must contain same XF index, for correct border */
2404*b1cdbd2cSJim Jagielski const ScMergeFlagAttr& rMergeFlagItem = GETITEM( rItemSet, ScMergeFlagAttr, ATTR_MERGE_FLAG );
2405*b1cdbd2cSJim Jagielski if( rMergeFlagItem.IsOverlapped() )
2406*b1cdbd2cSJim Jagielski nMergeBaseXFId = mxMergedcells->GetBaseXFId( aScPos );
2407*b1cdbd2cSJim Jagielski }
2408*b1cdbd2cSJim Jagielski
2409*b1cdbd2cSJim Jagielski String aAddNoteText; // additional text to be appended to a note
2410*b1cdbd2cSJim Jagielski
2411*b1cdbd2cSJim Jagielski CellType eCellType = pScCell ? pScCell->GetCellType() : CELLTYPE_NONE;
2412*b1cdbd2cSJim Jagielski switch( eCellType )
2413*b1cdbd2cSJim Jagielski {
2414*b1cdbd2cSJim Jagielski case CELLTYPE_VALUE:
2415*b1cdbd2cSJim Jagielski {
2416*b1cdbd2cSJim Jagielski double fValue = static_cast< const ScValueCell* >( pScCell )->GetValue();
2417*b1cdbd2cSJim Jagielski
2418*b1cdbd2cSJim Jagielski // try to create a Boolean cell
2419*b1cdbd2cSJim Jagielski if( pPattern && ((fValue == 0.0) || (fValue == 1.0)) )
2420*b1cdbd2cSJim Jagielski {
2421*b1cdbd2cSJim Jagielski sal_uLong nScNumFmt = GETITEMVALUE( pPattern->GetItemSet(), SfxUInt32Item, ATTR_VALUE_FORMAT, sal_uLong );
2422*b1cdbd2cSJim Jagielski if( rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL )
2423*b1cdbd2cSJim Jagielski xCell.reset( new XclExpBooleanCell(
2424*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue != 0.0 ) );
2425*b1cdbd2cSJim Jagielski }
2426*b1cdbd2cSJim Jagielski
2427*b1cdbd2cSJim Jagielski // try to create an RK value (compressed floating-point number)
2428*b1cdbd2cSJim Jagielski sal_Int32 nRkValue;
2429*b1cdbd2cSJim Jagielski if( !xCell && XclTools::GetRKFromDouble( nRkValue, fValue ) )
2430*b1cdbd2cSJim Jagielski xCell.reset( new XclExpRkCell(
2431*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, pPattern, nMergeBaseXFId, nRkValue ) );
2432*b1cdbd2cSJim Jagielski
2433*b1cdbd2cSJim Jagielski // else: simple floating-point number cell
2434*b1cdbd2cSJim Jagielski if( !xCell )
2435*b1cdbd2cSJim Jagielski xCell.reset( new XclExpNumberCell(
2436*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue ) );
2437*b1cdbd2cSJim Jagielski }
2438*b1cdbd2cSJim Jagielski break;
2439*b1cdbd2cSJim Jagielski
2440*b1cdbd2cSJim Jagielski case CELLTYPE_STRING:
2441*b1cdbd2cSJim Jagielski {
2442*b1cdbd2cSJim Jagielski const ScStringCell& rScStrCell = *static_cast< const ScStringCell* >( pScCell );
2443*b1cdbd2cSJim Jagielski xCell.reset( new XclExpLabelCell(
2444*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScStrCell ) );
2445*b1cdbd2cSJim Jagielski }
2446*b1cdbd2cSJim Jagielski break;
2447*b1cdbd2cSJim Jagielski
2448*b1cdbd2cSJim Jagielski case CELLTYPE_EDIT:
2449*b1cdbd2cSJim Jagielski {
2450*b1cdbd2cSJim Jagielski const ScEditCell& rScEditCell = *static_cast< const ScEditCell* >( pScCell );
2451*b1cdbd2cSJim Jagielski XclExpHyperlinkHelper aLinkHelper( GetRoot(), aScPos );
2452*b1cdbd2cSJim Jagielski xCell.reset( new XclExpLabelCell(
2453*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScEditCell, aLinkHelper ) );
2454*b1cdbd2cSJim Jagielski
2455*b1cdbd2cSJim Jagielski // add a single created HLINK record to the record list
2456*b1cdbd2cSJim Jagielski if( aLinkHelper.HasLinkRecord() )
2457*b1cdbd2cSJim Jagielski mxHyperlinkList->AppendRecord( aLinkHelper.GetLinkRecord() );
2458*b1cdbd2cSJim Jagielski // add list of multiple URLs to the additional cell note text
2459*b1cdbd2cSJim Jagielski if( aLinkHelper.HasMultipleUrls() )
2460*b1cdbd2cSJim Jagielski ScGlobal::AddToken( aAddNoteText, aLinkHelper.GetUrlList(), '\n', 2 );
2461*b1cdbd2cSJim Jagielski }
2462*b1cdbd2cSJim Jagielski break;
2463*b1cdbd2cSJim Jagielski
2464*b1cdbd2cSJim Jagielski case CELLTYPE_FORMULA:
2465*b1cdbd2cSJim Jagielski {
2466*b1cdbd2cSJim Jagielski const ScFormulaCell& rScFmlaCell = *static_cast< const ScFormulaCell* >( pScCell );
2467*b1cdbd2cSJim Jagielski xCell.reset( new XclExpFormulaCell(
2468*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, pPattern, nMergeBaseXFId,
2469*b1cdbd2cSJim Jagielski rScFmlaCell, maArrayBfr, maShrfmlaBfr, maTableopBfr ) );
2470*b1cdbd2cSJim Jagielski }
2471*b1cdbd2cSJim Jagielski break;
2472*b1cdbd2cSJim Jagielski
2473*b1cdbd2cSJim Jagielski default:
2474*b1cdbd2cSJim Jagielski DBG_ERRORFILE( "XclExpCellTable::XclExpCellTable - unknown cell type" );
2475*b1cdbd2cSJim Jagielski // run-through!
2476*b1cdbd2cSJim Jagielski case CELLTYPE_NONE:
2477*b1cdbd2cSJim Jagielski case CELLTYPE_NOTE:
2478*b1cdbd2cSJim Jagielski {
2479*b1cdbd2cSJim Jagielski xCell.reset( new XclExpBlankCell(
2480*b1cdbd2cSJim Jagielski GetRoot(), aXclPos, nLastXclCol, pPattern, nMergeBaseXFId ) );
2481*b1cdbd2cSJim Jagielski }
2482*b1cdbd2cSJim Jagielski break;
2483*b1cdbd2cSJim Jagielski }
2484*b1cdbd2cSJim Jagielski
2485*b1cdbd2cSJim Jagielski // insert the cell into the current row
2486*b1cdbd2cSJim Jagielski if( xCell.is() )
2487*b1cdbd2cSJim Jagielski maRowBfr.AppendCell( xCell, bIsMergedBase );
2488*b1cdbd2cSJim Jagielski
2489*b1cdbd2cSJim Jagielski // notes
2490*b1cdbd2cSJim Jagielski const ScPostIt* pScNote = pScCell ? pScCell->GetNote() : 0;
2491*b1cdbd2cSJim Jagielski if( pScNote || (aAddNoteText.Len() > 0) )
2492*b1cdbd2cSJim Jagielski mxNoteList->AppendNewRecord( new XclExpNote( GetRoot(), aScPos, pScNote, aAddNoteText ) );
2493*b1cdbd2cSJim Jagielski
2494*b1cdbd2cSJim Jagielski // other sheet contents
2495*b1cdbd2cSJim Jagielski if( pPattern )
2496*b1cdbd2cSJim Jagielski {
2497*b1cdbd2cSJim Jagielski const SfxItemSet& rItemSet = pPattern->GetItemSet();
2498*b1cdbd2cSJim Jagielski
2499*b1cdbd2cSJim Jagielski // base cell in a merged range
2500*b1cdbd2cSJim Jagielski if( bIsMergedBase )
2501*b1cdbd2cSJim Jagielski {
2502*b1cdbd2cSJim Jagielski const ScMergeAttr& rMergeItem = GETITEM( rItemSet, ScMergeAttr, ATTR_MERGE );
2503*b1cdbd2cSJim Jagielski ScRange aScRange( aScPos );
2504*b1cdbd2cSJim Jagielski aScRange.aEnd.IncCol( rMergeItem.GetColMerge() - 1 );
2505*b1cdbd2cSJim Jagielski aScRange.aEnd.IncRow( rMergeItem.GetRowMerge() - 1 );
2506*b1cdbd2cSJim Jagielski sal_uInt32 nXFId = xCell.is() ? xCell->GetFirstXFId() : EXC_XFID_NOTFOUND;
2507*b1cdbd2cSJim Jagielski // #120156# blank cells merged vertically may occur repeatedly
2508*b1cdbd2cSJim Jagielski DBG_ASSERT( (aScRange.aStart.Col() == aScRange.aEnd.Col()) || (nScCol == nLastScCol),
2509*b1cdbd2cSJim Jagielski "XclExpCellTable::XclExpCellTable - invalid repeated blank merged cell" );
2510*b1cdbd2cSJim Jagielski for( SCCOL nIndex = nScCol; nIndex <= nLastScCol; ++nIndex )
2511*b1cdbd2cSJim Jagielski {
2512*b1cdbd2cSJim Jagielski mxMergedcells->AppendRange( aScRange, nXFId );
2513*b1cdbd2cSJim Jagielski aScRange.aStart.IncCol();
2514*b1cdbd2cSJim Jagielski aScRange.aEnd.IncCol();
2515*b1cdbd2cSJim Jagielski }
2516*b1cdbd2cSJim Jagielski }
2517*b1cdbd2cSJim Jagielski
2518*b1cdbd2cSJim Jagielski // data validation
2519*b1cdbd2cSJim Jagielski if( ScfTools::CheckItem( rItemSet, ATTR_VALIDDATA, false ) )
2520*b1cdbd2cSJim Jagielski {
2521*b1cdbd2cSJim Jagielski sal_uLong nScHandle = GETITEMVALUE( rItemSet, SfxUInt32Item, ATTR_VALIDDATA, sal_uLong );
2522*b1cdbd2cSJim Jagielski ScRange aScRange( aScPos );
2523*b1cdbd2cSJim Jagielski aScRange.aEnd.SetCol( nLastScCol );
2524*b1cdbd2cSJim Jagielski mxDval->InsertCellRange( aScRange, nScHandle );
2525*b1cdbd2cSJim Jagielski }
2526*b1cdbd2cSJim Jagielski }
2527*b1cdbd2cSJim Jagielski }
2528*b1cdbd2cSJim Jagielski
2529*b1cdbd2cSJim Jagielski // create missing row settings for rows anyhow flagged or with outlines
2530*b1cdbd2cSJim Jagielski maRowBfr.CreateRows( ::std::max( nFirstUnflaggedScRow, nFirstUngroupedScRow ) );
2531*b1cdbd2cSJim Jagielski }
2532*b1cdbd2cSJim Jagielski
Finalize()2533*b1cdbd2cSJim Jagielski void XclExpCellTable::Finalize()
2534*b1cdbd2cSJim Jagielski {
2535*b1cdbd2cSJim Jagielski // Finalize multiple operations.
2536*b1cdbd2cSJim Jagielski maTableopBfr.Finalize();
2537*b1cdbd2cSJim Jagielski
2538*b1cdbd2cSJim Jagielski /* Finalize column buffer. This calculates column default XF indexes from
2539*b1cdbd2cSJim Jagielski the XF identifiers and fills a vector with these XF indexes. */
2540*b1cdbd2cSJim Jagielski ScfUInt16Vec aColXFIndexes;
2541*b1cdbd2cSJim Jagielski maColInfoBfr.Finalize( aColXFIndexes );
2542*b1cdbd2cSJim Jagielski
2543*b1cdbd2cSJim Jagielski /* Finalize row buffer. This calculates all cell XF indexes from the XF
2544*b1cdbd2cSJim Jagielski identifiers. Then the XF index vector aColXFIndexes (filled above) is
2545*b1cdbd2cSJim Jagielski used to calculate the row default formats. With this, all unneeded blank
2546*b1cdbd2cSJim Jagielski cell records (equal to row default or column default) will be removed.
2547*b1cdbd2cSJim Jagielski The function returns the (most used) default row format in aDefRowData. */
2548*b1cdbd2cSJim Jagielski XclExpDefaultRowData aDefRowData;
2549*b1cdbd2cSJim Jagielski maRowBfr.Finalize( aDefRowData, aColXFIndexes );
2550*b1cdbd2cSJim Jagielski
2551*b1cdbd2cSJim Jagielski // Initialize the DEFROWHEIGHT record.
2552*b1cdbd2cSJim Jagielski mxDefrowheight->SetDefaultData( aDefRowData );
2553*b1cdbd2cSJim Jagielski }
2554*b1cdbd2cSJim Jagielski
CreateRecord(sal_uInt16 nRecId) const2555*b1cdbd2cSJim Jagielski XclExpRecordRef XclExpCellTable::CreateRecord( sal_uInt16 nRecId ) const
2556*b1cdbd2cSJim Jagielski {
2557*b1cdbd2cSJim Jagielski XclExpRecordRef xRec;
2558*b1cdbd2cSJim Jagielski switch( nRecId )
2559*b1cdbd2cSJim Jagielski {
2560*b1cdbd2cSJim Jagielski case EXC_ID3_DIMENSIONS: xRec.reset( new XclExpDelegatingRecord( const_cast<XclExpRowBuffer*>(&maRowBfr)->GetDimensions() ) ); break;
2561*b1cdbd2cSJim Jagielski case EXC_ID2_DEFROWHEIGHT: xRec = mxDefrowheight; break;
2562*b1cdbd2cSJim Jagielski case EXC_ID_GUTS: xRec = mxGuts; break;
2563*b1cdbd2cSJim Jagielski case EXC_ID_NOTE: xRec = mxNoteList; break;
2564*b1cdbd2cSJim Jagielski case EXC_ID_MERGEDCELLS: xRec = mxMergedcells; break;
2565*b1cdbd2cSJim Jagielski case EXC_ID_HLINK: xRec = mxHyperlinkList; break;
2566*b1cdbd2cSJim Jagielski case EXC_ID_DVAL: xRec = mxDval; break;
2567*b1cdbd2cSJim Jagielski default: DBG_ERRORFILE( "XclExpCellTable::CreateRecord - unknown record id" );
2568*b1cdbd2cSJim Jagielski }
2569*b1cdbd2cSJim Jagielski return xRec;
2570*b1cdbd2cSJim Jagielski }
2571*b1cdbd2cSJim Jagielski
Save(XclExpStream & rStrm)2572*b1cdbd2cSJim Jagielski void XclExpCellTable::Save( XclExpStream& rStrm )
2573*b1cdbd2cSJim Jagielski {
2574*b1cdbd2cSJim Jagielski // DEFCOLWIDTH and COLINFOs
2575*b1cdbd2cSJim Jagielski maColInfoBfr.Save( rStrm );
2576*b1cdbd2cSJim Jagielski // ROWs and cell records
2577*b1cdbd2cSJim Jagielski maRowBfr.Save( rStrm );
2578*b1cdbd2cSJim Jagielski }
2579*b1cdbd2cSJim Jagielski
SaveXml(XclExpXmlStream & rStrm)2580*b1cdbd2cSJim Jagielski void XclExpCellTable::SaveXml( XclExpXmlStream& rStrm )
2581*b1cdbd2cSJim Jagielski {
2582*b1cdbd2cSJim Jagielski maColInfoBfr.SaveXml( rStrm );
2583*b1cdbd2cSJim Jagielski maRowBfr.SaveXml( rStrm );
2584*b1cdbd2cSJim Jagielski }
2585*b1cdbd2cSJim Jagielski
2586*b1cdbd2cSJim Jagielski // ============================================================================
2587*b1cdbd2cSJim Jagielski
2588