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