Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "scitems.hxx"
21 : #include <editeng/eeitem.hxx>
22 :
23 : #include <svx/algitem.hxx>
24 : #include <editeng/editobj.hxx>
25 : #include <editeng/editstat.hxx>
26 : #include <editeng/emphitem.hxx>
27 : #include <editeng/fhgtitem.hxx>
28 : #include <editeng/forbiddencharacterstable.hxx>
29 : #include <svx/rotmodit.hxx>
30 : #include <editeng/scripttypeitem.hxx>
31 : #include <editeng/unolingu.hxx>
32 : #include <editeng/justifyitem.hxx>
33 : #include <svl/zforlist.hxx>
34 : #include <svl/broadcast.hxx>
35 : #include <svl/listeneriter.hxx>
36 : #include <vcl/outdev.hxx>
37 :
38 : #include "column.hxx"
39 : #include "cell.hxx"
40 : #include "document.hxx"
41 : #include "docpool.hxx"
42 : #include "attarray.hxx"
43 : #include "patattr.hxx"
44 : #include "cellform.hxx"
45 : #include "stlsheet.hxx"
46 : #include "rechead.hxx"
47 : #include "brdcst.hxx"
48 : #include "editutil.hxx"
49 : #include "subtotal.hxx"
50 : #include "markdata.hxx"
51 : #include "compiler.hxx" // ScTokenArray GetCodeLen
52 : #include "dbdata.hxx"
53 : #include "fillinfo.hxx"
54 : #include "segmenttree.hxx"
55 : #include "docparam.hxx"
56 :
57 : #include <math.h>
58 :
59 : // -----------------------------------------------------------------------
60 :
61 : // factor from font size to optimal cell height (text width)
62 : #define SC_ROT_BREAK_FACTOR 6
63 :
64 : // -----------------------------------------------------------------------
65 :
66 84 : inline bool IsAmbiguousScript( sal_uInt8 nScript )
67 : {
68 : //! move to a header file
69 : return ( nScript != SCRIPTTYPE_LATIN &&
70 : nScript != SCRIPTTYPE_ASIAN &&
71 84 : nScript != SCRIPTTYPE_COMPLEX );
72 : }
73 :
74 : // -----------------------------------------------------------------------------------------
75 :
76 : //
77 : // Datei-Operationen
78 : //
79 :
80 : // -----------------------------------------------------------------------------------------
81 :
82 :
83 102 : long ScColumn::GetNeededSize(
84 : SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
85 : const Fraction& rZoomX, const Fraction& rZoomY,
86 : bool bWidth, const ScNeededSizeOptions& rOptions ) const
87 : {
88 102 : long nValue=0;
89 : SCSIZE nIndex;
90 102 : double nPPT = bWidth ? nPPTX : nPPTY;
91 102 : if (Search(nRow,nIndex))
92 : {
93 102 : ScBaseCell* pCell = maItems[nIndex].pCell;
94 102 : const ScPatternAttr* pPattern = rOptions.pPattern;
95 102 : if (!pPattern)
96 78 : pPattern = pAttrArray->GetPattern( nRow );
97 :
98 : // zusammengefasst?
99 : // Merge nicht in bedingter Formatierung
100 :
101 102 : const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
102 102 : const ScMergeFlagAttr* pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
103 :
104 102 : if ( bWidth )
105 : {
106 86 : if ( pFlag->IsHorOverlapped() )
107 0 : return 0;
108 86 : if ( rOptions.bSkipMerged && pMerge->GetColMerge() > 1 )
109 0 : return 0;
110 : }
111 : else
112 : {
113 16 : if ( pFlag->IsVerOverlapped() )
114 0 : return 0;
115 16 : if ( rOptions.bSkipMerged && pMerge->GetRowMerge() > 1 )
116 0 : return 0;
117 : }
118 :
119 : // bedingte Formatierung
120 102 : const SfxItemSet* pCondSet = pDocument->GetCondResult( nCol, nRow, nTab );
121 :
122 : // Zeilenumbruch?
123 :
124 : const SfxPoolItem* pCondItem;
125 : SvxCellHorJustify eHorJust;
126 102 : if (pCondSet &&
127 0 : pCondSet->GetItemState(ATTR_HOR_JUSTIFY, true, &pCondItem) == SFX_ITEM_SET)
128 0 : eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem*)pCondItem)->GetValue();
129 : else
130 : eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
131 102 : pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
132 : bool bBreak;
133 102 : if ( eHorJust == SVX_HOR_JUSTIFY_BLOCK )
134 1 : bBreak = true;
135 101 : else if ( pCondSet &&
136 0 : pCondSet->GetItemState(ATTR_LINEBREAK, true, &pCondItem) == SFX_ITEM_SET)
137 0 : bBreak = ((const SfxBoolItem*)pCondItem)->GetValue();
138 : else
139 101 : bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue();
140 :
141 102 : SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
142 102 : sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
143 : // #i111387# disable automatic line breaks only for "General" number format
144 102 : if ( bBreak && pCell->HasValueData() && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
145 : {
146 : // also take formula result type into account for number format
147 0 : if ( pCell->GetCellType() != CELLTYPE_FORMULA ||
148 0 : ( static_cast<ScFormulaCell*>(pCell)->GetStandardFormat(*pFormatter, nFormat) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
149 0 : bBreak = false;
150 : }
151 :
152 : // get other attributes from pattern and conditional formatting
153 :
154 102 : SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
155 : bool bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED &&
156 102 : ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() );
157 102 : if ( bAsianVertical )
158 0 : bBreak = false;
159 :
160 102 : if ( bWidth && bBreak ) // after determining bAsianVertical (bBreak may be reset)
161 2 : return 0;
162 :
163 100 : long nRotate = 0;
164 100 : SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
165 100 : if ( eOrient == SVX_ORIENTATION_STANDARD )
166 : {
167 100 : if (pCondSet &&
168 0 : pCondSet->GetItemState(ATTR_ROTATE_VALUE, true, &pCondItem) == SFX_ITEM_SET)
169 0 : nRotate = ((const SfxInt32Item*)pCondItem)->GetValue();
170 : else
171 100 : nRotate = ((const SfxInt32Item&)pPattern->GetItem(ATTR_ROTATE_VALUE)).GetValue();
172 100 : if ( nRotate )
173 : {
174 0 : if (pCondSet &&
175 0 : pCondSet->GetItemState(ATTR_ROTATE_MODE, true, &pCondItem) == SFX_ITEM_SET)
176 0 : eRotMode = (SvxRotateMode)((const SvxRotateModeItem*)pCondItem)->GetValue();
177 : else
178 : eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
179 0 : pPattern->GetItem(ATTR_ROTATE_MODE)).GetValue();
180 :
181 0 : if ( nRotate == 18000 )
182 0 : eRotMode = SVX_ROTATE_MODE_STANDARD; // keinen Ueberlauf
183 : }
184 : }
185 :
186 100 : if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT )
187 : {
188 : // ignore orientation/rotation if "repeat" is active
189 0 : eOrient = SVX_ORIENTATION_STANDARD;
190 0 : nRotate = 0;
191 0 : bAsianVertical = false;
192 : }
193 :
194 : const SvxMarginItem* pMargin;
195 100 : if (pCondSet &&
196 0 : pCondSet->GetItemState(ATTR_MARGIN, true, &pCondItem) == SFX_ITEM_SET)
197 0 : pMargin = (const SvxMarginItem*) pCondItem;
198 : else
199 100 : pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
200 100 : sal_uInt16 nIndent = 0;
201 100 : if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
202 : {
203 2 : if (pCondSet &&
204 0 : pCondSet->GetItemState(ATTR_INDENT, true, &pCondItem) == SFX_ITEM_SET)
205 0 : nIndent = ((const SfxUInt16Item*)pCondItem)->GetValue();
206 : else
207 2 : nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue();
208 : }
209 :
210 100 : sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pCell );
211 100 : if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
212 :
213 : // also call SetFont for edit cells, because bGetFont may be set only once
214 : // bGetFont is set also if script type changes
215 100 : if (rOptions.bGetFont)
216 : {
217 100 : Fraction aFontZoom = ( eOrient == SVX_ORIENTATION_STANDARD ) ? rZoomX : rZoomY;
218 100 : Font aFont;
219 : // font color doesn't matter here
220 100 : pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &aFontZoom, pCondSet, nScript );
221 100 : pDev->SetFont(aFont);
222 : }
223 :
224 100 : bool bAddMargin = true;
225 100 : CellType eCellType = pCell->GetCellType();
226 :
227 : bool bEditEngine = ( eCellType == CELLTYPE_EDIT ||
228 : eOrient == SVX_ORIENTATION_STACKED ||
229 83 : IsAmbiguousScript( nScript ) ||
230 183 : ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) );
231 :
232 100 : if (!bEditEngine) // direkte Ausgabe
233 : {
234 : Color* pColor;
235 83 : rtl::OUString aValStr;
236 : ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor,
237 : *pFormatter,
238 83 : true, rOptions.bFormula, ftCheck );
239 83 : if (!aValStr.isEmpty())
240 : {
241 : // SetFont ist nach oben verschoben
242 :
243 83 : Size aSize( pDev->GetTextWidth( aValStr ), pDev->GetTextHeight() );
244 83 : if ( eOrient != SVX_ORIENTATION_STANDARD )
245 : {
246 0 : long nTemp = aSize.Width();
247 0 : aSize.Width() = aSize.Height();
248 0 : aSize.Height() = nTemp;
249 : }
250 83 : else if ( nRotate )
251 : {
252 : //! unterschiedliche Skalierung X/Y beruecksichtigen
253 :
254 0 : double nRealOrient = nRotate * F_PI18000; // nRotate sind 1/100 Grad
255 0 : double nCosAbs = fabs( cos( nRealOrient ) );
256 0 : double nSinAbs = fabs( sin( nRealOrient ) );
257 0 : long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
258 : long nWidth;
259 0 : if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
260 0 : nWidth = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
261 0 : else if ( rOptions.bTotalSize )
262 : {
263 0 : nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
264 0 : bAddMargin = false;
265 : // nur nach rechts:
266 : //! unterscheiden nach Ausrichtung oben/unten (nur Text/ganze Hoehe)
267 0 : if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
268 0 : nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
269 0 : nPPT * nCosAbs / nSinAbs );
270 : }
271 : else
272 0 : nWidth = (long)( aSize.Height() / nSinAbs ); //! begrenzen?
273 :
274 0 : if ( bBreak && !rOptions.bTotalSize )
275 : {
276 : // limit size for line break
277 0 : long nCmp = pDev->GetFont().GetSize().Height() * SC_ROT_BREAK_FACTOR;
278 0 : if ( nHeight > nCmp )
279 0 : nHeight = nCmp;
280 : }
281 :
282 0 : aSize = Size( nWidth, nHeight );
283 : }
284 83 : nValue = bWidth ? aSize.Width() : aSize.Height();
285 :
286 83 : if ( bAddMargin )
287 : {
288 83 : if (bWidth)
289 : {
290 83 : nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
291 83 : (long) ( pMargin->GetRightMargin() * nPPT );
292 83 : if ( nIndent )
293 0 : nValue += (long) ( nIndent * nPPT );
294 : }
295 : else
296 0 : nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
297 0 : (long) ( pMargin->GetBottomMargin() * nPPT );
298 : }
299 :
300 : // Zeilenumbruch ausgefuehrt ?
301 :
302 83 : if ( bBreak && !bWidth )
303 : {
304 : // Test mit EditEngine zur Sicherheit schon bei 90%
305 : // (wegen Rundungsfehlern und weil EditEngine teilweise anders formatiert)
306 :
307 0 : long nDocPixel = (long) ( ( pDocument->GetColWidth( nCol,nTab ) -
308 0 : pMargin->GetLeftMargin() - pMargin->GetRightMargin() -
309 : nIndent )
310 0 : * nPPT );
311 0 : nDocPixel = (nDocPixel * 9) / 10; // zur Sicherheit
312 0 : if ( aSize.Width() > nDocPixel )
313 0 : bEditEngine = true;
314 : }
315 83 : }
316 : }
317 :
318 100 : if (bEditEngine)
319 : {
320 : // der Font wird bei !bEditEngine nicht jedesmal neu gesetzt
321 17 : Font aOldFont = pDev->GetFont();
322 :
323 17 : MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY );
324 :
325 : // am Dokument speichern ?
326 17 : ScFieldEditEngine* pEngine = pDocument->CreateFieldEditEngine();
327 :
328 17 : pEngine->SetUpdateMode( false );
329 17 : bool bTextWysiwyg = ( pDev->GetOutDevType() == OUTDEV_PRINTER );
330 17 : sal_uLong nCtrl = pEngine->GetControlWord();
331 17 : if ( bTextWysiwyg )
332 1 : nCtrl |= EE_CNTRL_FORMAT100;
333 : else
334 16 : nCtrl &= ~EE_CNTRL_FORMAT100;
335 17 : pEngine->SetControlWord( nCtrl );
336 17 : MapMode aOld = pDev->GetMapMode();
337 17 : pDev->SetMapMode( aHMMMode );
338 17 : pEngine->SetRefDevice( pDev );
339 17 : pDocument->ApplyAsianEditSettings( *pEngine );
340 17 : SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
341 17 : pPattern->FillEditItemSet( pSet, pCondSet );
342 :
343 : // no longer needed, are setted with the text (is faster)
344 : // pEngine->SetDefaults( pSet );
345 :
346 17 : if ( ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() ) {
347 :
348 0 : com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
349 0 : pEngine->SetHyphenator( xXHyphenator );
350 : }
351 :
352 17 : Size aPaper = Size( 1000000, 1000000 );
353 17 : if ( eOrient==SVX_ORIENTATION_STACKED && !bAsianVertical )
354 0 : aPaper.Width() = 1;
355 17 : else if (bBreak)
356 : {
357 0 : double fWidthFactor = nPPTX;
358 0 : if ( bTextWysiwyg )
359 : {
360 : // if text is formatted for printer, don't use PixelToLogic,
361 : // to ensure the exact same paper width (and same line breaks) as in
362 : // ScEditUtil::GetEditArea, used for output.
363 :
364 0 : fWidthFactor = HMM_PER_TWIPS;
365 : }
366 :
367 : // use original width for hidden columns:
368 0 : long nDocWidth = (long) ( pDocument->GetOriginalWidth(nCol,nTab) * fWidthFactor );
369 0 : SCCOL nColMerge = pMerge->GetColMerge();
370 0 : if (nColMerge > 1)
371 0 : for (SCCOL nColAdd=1; nColAdd<nColMerge; nColAdd++)
372 0 : nDocWidth += (long) ( pDocument->GetColWidth(nCol+nColAdd,nTab) * fWidthFactor );
373 0 : nDocWidth -= (long) ( pMargin->GetLeftMargin() * fWidthFactor )
374 0 : + (long) ( pMargin->GetRightMargin() * fWidthFactor )
375 0 : + 1; // Ausgabebereich ist Breite-1 Pixel (wegen Gitterlinien)
376 0 : if ( nIndent )
377 0 : nDocWidth -= (long) ( nIndent * fWidthFactor );
378 :
379 : // space for AutoFilter button: 20 * nZoom/100
380 0 : if ( pFlag->HasAutoFilter() && !bTextWysiwyg )
381 0 : nDocWidth -= (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
382 :
383 0 : aPaper.Width() = nDocWidth;
384 :
385 0 : if ( !bTextWysiwyg )
386 0 : aPaper = pDev->PixelToLogic( aPaper, aHMMMode );
387 : }
388 17 : pEngine->SetPaperSize(aPaper);
389 :
390 17 : if ( pCell->GetCellType() == CELLTYPE_EDIT )
391 : {
392 : const EditTextObject* pData;
393 17 : ((ScEditCell*)pCell)->GetData(pData);
394 17 : pEngine->SetTextNewDefaults(*pData, pSet);
395 : }
396 : else
397 : {
398 : Color* pColor;
399 0 : rtl::OUString aString;
400 : ScCellFormat::GetString( pCell, nFormat, aString, &pColor,
401 : *pFormatter,
402 0 : true, rOptions.bFormula, ftCheck );
403 0 : if (!aString.isEmpty())
404 0 : pEngine->SetTextNewDefaults(aString, pSet);
405 : else
406 0 : pEngine->SetDefaults(pSet);
407 : }
408 :
409 17 : bool bEngineVertical = pEngine->IsVertical();
410 17 : pEngine->SetVertical( bAsianVertical );
411 17 : pEngine->SetUpdateMode( true );
412 :
413 17 : bool bEdWidth = bWidth;
414 17 : if ( eOrient != SVX_ORIENTATION_STANDARD && eOrient != SVX_ORIENTATION_STACKED )
415 0 : bEdWidth = !bEdWidth;
416 17 : if ( nRotate )
417 : {
418 : //! unterschiedliche Skalierung X/Y beruecksichtigen
419 :
420 0 : Size aSize( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
421 0 : double nRealOrient = nRotate * F_PI18000; // nRotate sind 1/100 Grad
422 0 : double nCosAbs = fabs( cos( nRealOrient ) );
423 0 : double nSinAbs = fabs( sin( nRealOrient ) );
424 0 : long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
425 : long nWidth;
426 0 : if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
427 0 : nWidth = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
428 0 : else if ( rOptions.bTotalSize )
429 : {
430 0 : nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
431 0 : bAddMargin = false;
432 0 : if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
433 0 : nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
434 0 : nPPT * nCosAbs / nSinAbs );
435 : }
436 : else
437 0 : nWidth = (long)( aSize.Height() / nSinAbs ); //! begrenzen?
438 0 : aSize = Size( nWidth, nHeight );
439 :
440 0 : Size aPixSize = pDev->LogicToPixel( aSize, aHMMMode );
441 0 : if ( bEdWidth )
442 0 : nValue = aPixSize.Width();
443 : else
444 : {
445 0 : nValue = aPixSize.Height();
446 :
447 0 : if ( bBreak && !rOptions.bTotalSize )
448 : {
449 : // limit size for line break
450 0 : long nCmp = aOldFont.GetSize().Height() * SC_ROT_BREAK_FACTOR;
451 0 : if ( nValue > nCmp )
452 0 : nValue = nCmp;
453 : }
454 : }
455 : }
456 17 : else if ( bEdWidth )
457 : {
458 1 : if (bBreak)
459 0 : nValue = 0;
460 : else
461 1 : nValue = pDev->LogicToPixel(Size( pEngine->CalcTextWidth(), 0 ),
462 1 : aHMMMode).Width();
463 : }
464 : else // Hoehe
465 : {
466 16 : nValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ),
467 16 : aHMMMode).Height();
468 :
469 : // With non-100% zoom and several lines or paragraphs, don't shrink below the result with FORMAT100 set
470 16 : if ( !bTextWysiwyg && ( rZoomY.GetNumerator() != 1 || rZoomY.GetDenominator() != 1 ) &&
471 0 : ( pEngine->GetParagraphCount() > 1 || ( bBreak && pEngine->GetLineCount(0) > 1 ) ) )
472 : {
473 0 : pEngine->SetControlWord( nCtrl | EE_CNTRL_FORMAT100 );
474 0 : pEngine->QuickFormatDoc( sal_True );
475 0 : long nSecondValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ), aHMMMode).Height();
476 0 : if ( nSecondValue > nValue )
477 0 : nValue = nSecondValue;
478 : }
479 : }
480 :
481 17 : if ( nValue && bAddMargin )
482 : {
483 17 : if (bWidth)
484 : {
485 1 : nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
486 1 : (long) ( pMargin->GetRightMargin() * nPPT );
487 1 : if (nIndent)
488 0 : nValue += (long) ( nIndent * nPPT );
489 : }
490 : else
491 : {
492 16 : nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
493 16 : (long) ( pMargin->GetBottomMargin() * nPPT );
494 :
495 16 : if ( bAsianVertical && pDev->GetOutDevType() != OUTDEV_PRINTER )
496 : {
497 : // add 1pt extra (default margin value) for line breaks with SetVertical
498 0 : nValue += (long) ( 20 * nPPT );
499 : }
500 : }
501 : }
502 :
503 : // EditEngine is cached and re-used, so the old vertical flag must be restored
504 17 : pEngine->SetVertical( bEngineVertical );
505 :
506 17 : pDocument->DisposeFieldEditEngine(pEngine);
507 :
508 17 : pDev->SetMapMode( aOld );
509 17 : pDev->SetFont( aOldFont );
510 : }
511 :
512 100 : if (bWidth)
513 : {
514 : // Platz fuer Autofilter-Button
515 : // 20 * nZoom/100
516 : // bedingte Formatierung hier nicht interessant
517 :
518 84 : sal_Int16 nFlags = ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).GetValue();
519 84 : if (nFlags & SC_MF_AUTO)
520 4 : nValue += (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
521 : }
522 : }
523 100 : return nValue;
524 : }
525 :
526 :
527 78 : sal_uInt16 ScColumn::GetOptimalColWidth(
528 : OutputDevice* pDev, double nPPTX, double nPPTY, const Fraction& rZoomX, const Fraction& rZoomY,
529 : bool bFormula, sal_uInt16 nOldWidth, const ScMarkData* pMarkData, const ScColWidthParam* pParam) const
530 : {
531 78 : if ( maItems.empty() )
532 11 : return nOldWidth;
533 :
534 67 : sal_uInt16 nWidth = (sal_uInt16) (nOldWidth * nPPTX);
535 67 : bool bFound = false;
536 :
537 : SCSIZE nIndex;
538 67 : ScMarkedDataIter aDataIter(this, pMarkData, true);
539 67 : if ( pParam && pParam->mbSimpleText )
540 : { // alles eins bis auf NumberFormate
541 64 : const ScPatternAttr* pPattern = GetPattern( 0 );
542 64 : Font aFont;
543 : // font color doesn't matter here
544 64 : pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &rZoomX, NULL );
545 64 : pDev->SetFont( aFont );
546 64 : const SvxMarginItem* pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
547 64 : long nMargin = (long) ( pMargin->GetLeftMargin() * nPPTX ) +
548 64 : (long) ( pMargin->GetRightMargin() * nPPTX );
549 :
550 : // Try to find the row that has the longest string, and measure the width of that string.
551 64 : SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
552 64 : sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
553 64 : rtl::OUString aLongStr;
554 : Color* pColor;
555 64 : if (pParam->mnMaxTextRow >= 0)
556 : {
557 0 : ScBaseCell* pCell = GetCell(pParam->mnMaxTextRow);
558 : ScCellFormat::GetString(
559 0 : pCell, nFormat, aLongStr, &pColor, *pFormatter, true, false, ftCheck );
560 : }
561 : else
562 : {
563 64 : xub_StrLen nLongLen = 0;
564 2725 : while (aDataIter.Next(nIndex))
565 : {
566 2597 : if (nIndex >= maItems.size())
567 : // Out-of-bound reached. No need to keep going.
568 : break;
569 :
570 2597 : ScBaseCell* pCell = maItems[nIndex].pCell;
571 2597 : rtl::OUString aValStr;
572 : ScCellFormat::GetString(
573 2597 : pCell, nFormat, aValStr, &pColor, *pFormatter, true, false, ftCheck );
574 :
575 2597 : if (aValStr.getLength() > nLongLen)
576 : {
577 119 : nLongLen = aValStr.getLength();
578 119 : aLongStr = aValStr;
579 : }
580 2597 : }
581 : }
582 :
583 64 : if (!aLongStr.isEmpty())
584 : {
585 64 : nWidth = pDev->GetTextWidth(aLongStr) + static_cast<sal_uInt16>(nMargin);
586 64 : bFound = true;
587 64 : }
588 : }
589 : else
590 : {
591 3 : ScNeededSizeOptions aOptions;
592 3 : aOptions.bFormula = bFormula;
593 3 : const ScPatternAttr* pOldPattern = NULL;
594 3 : sal_uInt8 nOldScript = 0;
595 :
596 14 : while (aDataIter.Next( nIndex ))
597 : {
598 8 : SCROW nRow = maItems[nIndex].nRow;
599 :
600 8 : sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, maItems[nIndex].pCell );
601 8 : if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
602 :
603 8 : const ScPatternAttr* pPattern = GetPattern( nRow );
604 8 : aOptions.pPattern = pPattern;
605 8 : aOptions.bGetFont = (pPattern != pOldPattern || nScript != nOldScript);
606 : sal_uInt16 nThis = (sal_uInt16) GetNeededSize( nRow, pDev, nPPTX, nPPTY,
607 8 : rZoomX, rZoomY, true, aOptions );
608 8 : pOldPattern = pPattern;
609 8 : if (nThis)
610 : {
611 8 : if (nThis>nWidth || !bFound)
612 : {
613 5 : nWidth = nThis;
614 5 : bFound = true;
615 : }
616 : }
617 : }
618 : }
619 :
620 67 : if (bFound)
621 : {
622 67 : nWidth += 2;
623 67 : sal_uInt16 nTwips = (sal_uInt16) (nWidth / nPPTX);
624 67 : return nTwips;
625 : }
626 : else
627 0 : return nOldWidth;
628 : }
629 :
630 263366 : static sal_uInt16 lcl_GetAttribHeight( const ScPatternAttr& rPattern, sal_uInt16 nFontHeightId )
631 : {
632 263366 : sal_uInt16 nHeight = (sal_uInt16) ((const SvxFontHeightItem&) rPattern.GetItem(nFontHeightId)).GetHeight();
633 263366 : const SvxMarginItem* pMargin = (const SvxMarginItem*) &rPattern.GetItem(ATTR_MARGIN);
634 263366 : nHeight += nHeight / 5;
635 : // gibt bei 10pt 240
636 :
637 263366 : if ( ((const SvxEmphasisMarkItem&)rPattern.
638 263366 : GetItem(ATTR_FONT_EMPHASISMARK)).GetEmphasisMark() != EMPHASISMARK_NONE )
639 : {
640 : // add height for emphasis marks
641 : //! font metrics should be used instead
642 0 : nHeight += nHeight / 4;
643 : }
644 :
645 263366 : if ( nHeight + 240 > ScGlobal::nDefFontHeight )
646 : {
647 263366 : nHeight = sal::static_int_cast<sal_uInt16>( nHeight + ScGlobal::nDefFontHeight );
648 263366 : nHeight -= 240;
649 : }
650 :
651 : // Standard-Hoehe: TextHeight + Raender - 23
652 : // -> 257 unter Windows
653 :
654 263366 : if (nHeight > STD_ROWHEIGHT_DIFF)
655 263366 : nHeight -= STD_ROWHEIGHT_DIFF;
656 :
657 263366 : nHeight += pMargin->GetTopMargin() + pMargin->GetBottomMargin();
658 :
659 263366 : return nHeight;
660 : }
661 :
662 : // pHeight in Twips
663 : // nMinHeight, nMinStart zur Optimierung: ab nRow >= nMinStart ist mindestens nMinHeight
664 : // (wird nur bei bStdAllowed ausgewertet)
665 :
666 263168 : void ScColumn::GetOptimalHeight(
667 : SCROW nStartRow, SCROW nEndRow, sal_uInt16* pHeight, OutputDevice* pDev,
668 : double nPPTX, double nPPTY, const Fraction& rZoomX, const Fraction& rZoomY,
669 : bool bShrink, sal_uInt16 nMinHeight, SCROW nMinStart) const
670 : {
671 263168 : ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow );
672 :
673 263168 : SCROW nStart = -1;
674 263168 : SCROW nEnd = -1;
675 263168 : SCROW nEditPos = 0;
676 263168 : SCROW nNextEnd = 0;
677 :
678 : // bei bedingter Formatierung werden immer die einzelnen Zellen angesehen
679 :
680 263168 : const ScPatternAttr* pPattern = aIter.Next(nStart,nEnd);
681 789727 : while ( pPattern )
682 : {
683 263391 : const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
684 263391 : const ScMergeFlagAttr* pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
685 263391 : if ( pMerge->GetRowMerge() > 1 || pFlag->IsOverlapped() )
686 : {
687 : // nix - vertikal bei der zusammengefassten und den ueberdeckten,
688 : // horizontal nur bei den ueberdeckten (unsichtbaren) -
689 : // eine nur horizontal zusammengefasste wird aber beruecksichtigt
690 : }
691 : else
692 : {
693 263382 : SCROW nRow = 0;
694 263382 : bool bStdAllowed = (pPattern->GetCellOrientation() == SVX_ORIENTATION_STANDARD);
695 263382 : bool bStdOnly = false;
696 263382 : if (bStdAllowed)
697 : {
698 263382 : bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
699 : ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
700 263382 : GetItem( ATTR_HOR_JUSTIFY )).GetValue() ==
701 526764 : SVX_HOR_JUSTIFY_BLOCK);
702 263382 : bStdOnly = !bBreak;
703 :
704 : // bedingte Formatierung: Zellen durchgehen
705 526764 : if (bStdOnly &&
706 : !static_cast<const ScCondFormatItem&>(pPattern->GetItem(
707 263382 : ATTR_CONDITIONAL)).GetCondFormatData().empty())
708 : {
709 0 : bStdOnly = false;
710 : }
711 :
712 : // gedrehter Text: Zellen durchgehen
713 526764 : if ( bStdOnly && ((const SfxInt32Item&)pPattern->
714 263382 : GetItem(ATTR_ROTATE_VALUE)).GetValue() )
715 0 : bStdOnly = false;
716 : }
717 :
718 263382 : if (bStdOnly)
719 263382 : if (HasEditCells(nStart,nEnd,nEditPos)) // includes mixed script types
720 : {
721 31 : if (nEditPos == nStart)
722 : {
723 16 : bStdOnly = false;
724 16 : if (nEnd > nEditPos)
725 15 : nNextEnd = nEnd;
726 16 : nEnd = nEditPos; // einzeln ausrechnen
727 16 : bStdAllowed = false; // wird auf jeden Fall per Zelle berechnet
728 : }
729 : else
730 : {
731 15 : nNextEnd = nEnd;
732 15 : nEnd = nEditPos - 1; // Standard - Teil
733 : }
734 : }
735 :
736 263382 : if (bStdAllowed)
737 : {
738 263366 : sal_uInt16 nLatHeight = 0;
739 263366 : sal_uInt16 nCjkHeight = 0;
740 263366 : sal_uInt16 nCtlHeight = 0;
741 : sal_uInt16 nDefHeight;
742 263366 : sal_uInt8 nDefScript = ScGlobal::GetDefaultScriptType();
743 263366 : if ( nDefScript == SCRIPTTYPE_ASIAN )
744 0 : nDefHeight = nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT );
745 263366 : else if ( nDefScript == SCRIPTTYPE_COMPLEX )
746 0 : nDefHeight = nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT );
747 : else
748 263366 : nDefHeight = nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT );
749 :
750 : // if everything below is already larger, the loop doesn't have to
751 : // be run again
752 263366 : SCROW nStdEnd = nEnd;
753 263366 : if ( nDefHeight <= nMinHeight && nStdEnd >= nMinStart )
754 263109 : nStdEnd = (nMinStart>0) ? nMinStart-1 : 0;
755 :
756 258472201 : for (nRow=nStart; nRow<=nStdEnd; nRow++)
757 258208835 : if (nDefHeight > pHeight[nRow-nStartRow])
758 257950016 : pHeight[nRow-nStartRow] = nDefHeight;
759 :
760 263366 : if ( bStdOnly )
761 : {
762 : // if cells are not handled individually below,
763 : // check for cells with different script type
764 :
765 : SCSIZE nIndex;
766 263366 : Search(nStart,nIndex);
767 531640 : while ( nIndex < maItems.size() && (nRow=maItems[nIndex].nRow) <= nEnd )
768 : {
769 4908 : sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, maItems[nIndex].pCell );
770 4908 : if ( nScript != nDefScript )
771 : {
772 57 : if ( nScript == SCRIPTTYPE_ASIAN )
773 : {
774 0 : if ( nCjkHeight == 0 )
775 0 : nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT );
776 0 : if (nCjkHeight > pHeight[nRow-nStartRow])
777 0 : pHeight[nRow-nStartRow] = nCjkHeight;
778 : }
779 57 : else if ( nScript == SCRIPTTYPE_COMPLEX )
780 : {
781 0 : if ( nCtlHeight == 0 )
782 0 : nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT );
783 0 : if (nCtlHeight > pHeight[nRow-nStartRow])
784 0 : pHeight[nRow-nStartRow] = nCtlHeight;
785 : }
786 : else
787 : {
788 57 : if ( nLatHeight == 0 )
789 0 : nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT );
790 57 : if (nLatHeight > pHeight[nRow-nStartRow])
791 0 : pHeight[nRow-nStartRow] = nLatHeight;
792 : }
793 : }
794 4908 : ++nIndex;
795 : }
796 : }
797 : }
798 :
799 263382 : if (!bStdOnly) // belegte Zellen suchen
800 : {
801 16 : ScNeededSizeOptions aOptions;
802 :
803 : SCSIZE nIndex;
804 16 : Search(nStart,nIndex);
805 48 : while ( (nIndex < maItems.size()) ? ((nRow=maItems[nIndex].nRow) <= nEnd) : false )
806 : {
807 : // Zellhoehe nur berechnen, wenn sie spaeter auch gebraucht wird (#37928#)
808 :
809 16 : if ( bShrink || !(pDocument->GetRowFlags(nRow, nTab) & CR_MANUALSIZE) )
810 : {
811 16 : aOptions.pPattern = pPattern;
812 : sal_uInt16 nHeight = (sal_uInt16)
813 : ( GetNeededSize( nRow, pDev, nPPTX, nPPTY,
814 16 : rZoomX, rZoomY, false, aOptions ) / nPPTY );
815 16 : if (nHeight > pHeight[nRow-nStartRow])
816 16 : pHeight[nRow-nStartRow] = nHeight;
817 : }
818 16 : ++nIndex;
819 : }
820 : }
821 : }
822 :
823 263391 : if (nNextEnd > 0)
824 : {
825 30 : nStart = nEnd + 1;
826 30 : nEnd = nNextEnd;
827 30 : nNextEnd = 0;
828 : }
829 : else
830 263361 : pPattern = aIter.Next(nStart,nEnd);
831 : }
832 263168 : }
833 :
834 0 : bool ScColumn::GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& rData) const
835 : {
836 0 : bool bStop = false;
837 : CellType eCellType;
838 : SCSIZE nIndex;
839 0 : if (!bInSel && Search(nRow, nIndex))
840 : {
841 0 : eCellType = GetCellType(nRow);
842 0 : if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
843 0 : !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
844 0 : pDocument->IsTabProtected(nTab)) )
845 0 : return true;
846 : }
847 0 : while (!bStop)
848 : {
849 0 : if (bInSel)
850 : {
851 0 : nRow = rData.GetNextMarked(nCol, nRow, false);
852 0 : if (!ValidRow(nRow))
853 : {
854 0 : nRow = MAXROW+1;
855 0 : bStop = true;
856 : }
857 : else
858 : {
859 0 : eCellType = GetCellType(nRow);
860 0 : if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
861 0 : !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
862 0 : pDocument->IsTabProtected(nTab)) )
863 0 : return true;
864 : else
865 0 : nRow++;
866 : }
867 : }
868 0 : else if (GetNextDataPos(nRow))
869 : {
870 0 : eCellType = GetCellType(nRow);
871 0 : if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
872 0 : !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
873 0 : pDocument->IsTabProtected(nTab)) )
874 0 : return true;
875 : else
876 0 : nRow++;
877 : }
878 : else
879 : {
880 0 : nRow = MAXROW+1;
881 0 : bStop = true;
882 : }
883 : }
884 0 : return false;
885 : }
886 :
887 : // =========================================================================================
888 :
889 0 : void ScColumn::RemoveAutoSpellObj()
890 : {
891 0 : ScTabEditEngine* pEngine = NULL;
892 :
893 0 : for (SCSIZE i=0; i<maItems.size(); i++)
894 0 : if ( maItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
895 : {
896 0 : ScEditCell* pOldCell = (ScEditCell*) maItems[i].pCell;
897 0 : const EditTextObject* pData = pOldCell->GetData();
898 : // keine Abfrage auf HasOnlineSpellErrors, damit es auch
899 : // nach dem Laden funktioniert
900 :
901 : // Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
902 : // in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
903 : // Attribute in Default und harter Formatierung erkennen und weglassen sollte,
904 : // muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
905 : // werden!
906 :
907 : // auf Attribute testen
908 0 : if ( !pEngine )
909 0 : pEngine = new ScTabEditEngine(pDocument);
910 0 : pEngine->SetText( *pData );
911 0 : ScEditAttrTester aTester( pEngine );
912 0 : if ( aTester.NeedsObject() ) // nur Spell-Errors entfernen
913 : {
914 0 : EditTextObject* pNewData = pEngine->CreateTextObject(); // ohne BIGOBJ
915 0 : pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
916 0 : delete pNewData;
917 : }
918 : else // String erzeugen
919 : {
920 0 : String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
921 0 : ScBaseCell* pNewCell = new ScStringCell( aText );
922 0 : pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
923 0 : maItems[i].pCell = pNewCell;
924 0 : delete pOldCell;
925 0 : }
926 : }
927 :
928 0 : delete pEngine;
929 0 : }
930 :
931 0 : void ScColumn::RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow )
932 : {
933 0 : ScFieldEditEngine* pEngine = NULL;
934 :
935 : SCSIZE i;
936 0 : Search( nStartRow, i );
937 0 : for (; i<maItems.size() && maItems[i].nRow <= nEndRow; i++)
938 0 : if ( maItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
939 : {
940 0 : ScEditCell* pOldCell = (ScEditCell*) maItems[i].pCell;
941 0 : const EditTextObject* pData = pOldCell->GetData();
942 :
943 : // Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
944 : // in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
945 : // Attribute in Default und harter Formatierung erkennen und weglassen sollte,
946 : // muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
947 : // werden!
948 :
949 : // auf Attribute testen
950 0 : if ( !pEngine )
951 : {
952 0 : pEngine = new ScFieldEditEngine(pDocument, pDocument->GetEditPool());
953 : // EE_CNTRL_ONLINESPELLING falls schon Fehler drin sind
954 0 : pEngine->SetControlWord( pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING );
955 0 : pDocument->ApplyAsianEditSettings( *pEngine );
956 : }
957 0 : pEngine->SetText( *pData );
958 0 : sal_uInt16 nParCount = pEngine->GetParagraphCount();
959 0 : for (sal_uInt16 nPar=0; nPar<nParCount; nPar++)
960 : {
961 0 : pEngine->QuickRemoveCharAttribs( nPar );
962 0 : const SfxItemSet& rOld = pEngine->GetParaAttribs( nPar );
963 0 : if ( rOld.Count() )
964 : {
965 0 : SfxItemSet aNew( *rOld.GetPool(), rOld.GetRanges() ); // leer
966 0 : pEngine->SetParaAttribs( nPar, aNew );
967 : }
968 : }
969 : // URL-Felder in Text wandeln (andere gibt's nicht, darum pType=0)
970 0 : pEngine->RemoveFields( true );
971 :
972 0 : bool bSpellErrors = pEngine->HasOnlineSpellErrors();
973 0 : bool bNeedObject = bSpellErrors || nParCount>1; // Errors/Absaetze behalten
974 : // ScEditAttrTester nicht mehr noetig, Felder sind raus
975 :
976 0 : if ( bNeedObject ) // bleibt Edit-Zelle
977 : {
978 0 : sal_uInt32 nCtrl = pEngine->GetControlWord();
979 0 : sal_uInt32 nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0;
980 0 : if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig )
981 0 : pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig );
982 0 : EditTextObject* pNewData = pEngine->CreateTextObject();
983 0 : pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
984 0 : delete pNewData;
985 : }
986 : else // String erzeugen
987 : {
988 0 : String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
989 0 : ScBaseCell* pNewCell = new ScStringCell( aText );
990 0 : pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
991 0 : maItems[i].pCell = pNewCell;
992 0 : delete pOldCell;
993 : }
994 : }
995 :
996 0 : delete pEngine;
997 0 : }
998 :
999 : // =========================================================================================
1000 :
1001 0 : bool ScColumn::TestTabRefAbs(SCTAB nTable) const
1002 : {
1003 0 : bool bRet = false;
1004 0 : if ( !maItems.empty() )
1005 0 : for (SCSIZE i = 0; i < maItems.size(); i++)
1006 0 : if ( maItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
1007 0 : if (((ScFormulaCell*)maItems[i].pCell)->TestTabRefAbs(nTable))
1008 0 : bRet = true;
1009 0 : return bRet;
1010 : }
1011 :
1012 : // =========================================================================================
1013 :
1014 23955 : ScColumnIterator::ScColumnIterator( const ScColumn* pCol, SCROW nStart, SCROW nEnd ) :
1015 : pColumn( pCol ),
1016 : nTop( nStart ),
1017 23955 : nBottom( nEnd )
1018 : {
1019 23955 : pColumn->Search( nTop, nPos );
1020 23955 : }
1021 :
1022 23955 : ScColumnIterator::~ScColumnIterator()
1023 : {
1024 23955 : }
1025 :
1026 24255 : bool ScColumnIterator::Next( SCROW& rRow, ScBaseCell*& rpCell )
1027 : {
1028 24255 : if ( nPos < pColumn->maItems.size() )
1029 : {
1030 388 : rRow = pColumn->maItems[nPos].nRow;
1031 388 : if ( rRow <= nBottom )
1032 : {
1033 300 : rpCell = pColumn->maItems[nPos].pCell;
1034 300 : ++nPos;
1035 300 : return true;
1036 : }
1037 : }
1038 :
1039 23955 : rRow = 0;
1040 23955 : rpCell = NULL;
1041 23955 : return false;
1042 : }
1043 :
1044 0 : SCSIZE ScColumnIterator::GetIndex() const // Index zur letzen abgefragten Zelle
1045 : {
1046 0 : return nPos - 1; // bei Next ist Pos hochgezaehlt worden
1047 : }
1048 :
1049 : // -----------------------------------------------------------------------------------------
1050 :
1051 67 : ScMarkedDataIter::ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData,
1052 : bool bAllIfNone ) :
1053 : pColumn( pCol ),
1054 : pMarkIter( NULL ),
1055 : bNext( true ),
1056 67 : bAll( bAllIfNone )
1057 : {
1058 67 : if (pMarkData && pMarkData->IsMultiMarked())
1059 67 : pMarkIter = new ScMarkArrayIter( pMarkData->GetArray() + pCol->GetCol() );
1060 67 : }
1061 :
1062 67 : ScMarkedDataIter::~ScMarkedDataIter()
1063 : {
1064 67 : delete pMarkIter;
1065 67 : }
1066 :
1067 2672 : bool ScMarkedDataIter::Next( SCSIZE& rIndex )
1068 : {
1069 2672 : bool bFound = false;
1070 2605 : do
1071 : {
1072 2672 : if (bNext)
1073 : {
1074 67 : if (!pMarkIter || !pMarkIter->Next( nTop, nBottom ))
1075 : {
1076 0 : if (bAll) // ganze Spalte
1077 : {
1078 0 : nTop = 0;
1079 0 : nBottom = MAXROW;
1080 : }
1081 : else
1082 0 : return false;
1083 : }
1084 67 : pColumn->Search( nTop, nPos );
1085 67 : bNext = false;
1086 67 : bAll = false; // nur beim ersten Versuch
1087 : }
1088 :
1089 2672 : if ( nPos >= pColumn->maItems.size() )
1090 67 : return false;
1091 :
1092 2605 : if ( pColumn->maItems[nPos].nRow <= nBottom )
1093 2605 : bFound = true;
1094 : else
1095 0 : bNext = true;
1096 : }
1097 2605 : while (!bFound);
1098 :
1099 2605 : rIndex = nPos++;
1100 2605 : return true;
1101 : }
1102 :
1103 :
1104 : //------------
1105 :
1106 78214 : bool ScColumn::IsEmptyData() const
1107 : {
1108 78214 : return (maItems.empty());
1109 : }
1110 :
1111 95494 : bool ScColumn::IsEmptyVisData() const
1112 : {
1113 95494 : if ( maItems.empty() )
1114 95287 : return true;
1115 : else
1116 : {
1117 207 : bool bVisData = false;
1118 : SCSIZE i;
1119 414 : for (i=0; i<maItems.size() && !bVisData; i++)
1120 : {
1121 207 : if(!maItems[i].pCell->IsBlank())
1122 207 : bVisData = true;
1123 : }
1124 207 : return !bVisData;
1125 : }
1126 : }
1127 :
1128 0 : SCSIZE ScColumn::VisibleCount( SCROW nStartRow, SCROW nEndRow ) const
1129 : {
1130 : // Notizen werden nicht mitgezaehlt
1131 :
1132 0 : SCSIZE nVisCount = 0;
1133 : SCSIZE nIndex;
1134 0 : Search( nStartRow, nIndex );
1135 0 : while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nEndRow )
1136 : {
1137 0 : if ( maItems[nIndex].nRow >= nStartRow )
1138 : {
1139 0 : ++nVisCount;
1140 : }
1141 0 : ++nIndex;
1142 : }
1143 0 : return nVisCount;
1144 : }
1145 :
1146 80337 : SCROW ScColumn::GetLastVisDataPos() const
1147 : {
1148 80337 : SCROW nRet = 0;
1149 80337 : if ( !maItems.empty() )
1150 : {
1151 : SCSIZE i;
1152 339 : bool bFound = false;
1153 1017 : for (i=maItems.size(); i>0 && !bFound; )
1154 : {
1155 339 : --i;
1156 339 : if(!maItems[i].pCell->IsBlank())
1157 : {
1158 339 : bFound = true;
1159 339 : nRet = maItems[i].nRow;
1160 : }
1161 : }
1162 : }
1163 80337 : return nRet;
1164 : }
1165 :
1166 4 : SCROW ScColumn::GetFirstVisDataPos() const
1167 : {
1168 4 : SCROW nRet = 0;
1169 4 : if ( !maItems.empty() )
1170 : {
1171 : SCSIZE i;
1172 4 : bool bFound = false;
1173 8 : for (i=0; i<maItems.size() && !bFound; i++)
1174 : {
1175 4 : bFound = true;
1176 4 : nRet = maItems[i].nRow;
1177 : }
1178 : }
1179 4 : return nRet;
1180 : }
1181 :
1182 1038 : bool ScColumn::HasVisibleDataAt(SCROW nRow) const
1183 : {
1184 : SCSIZE nIndex;
1185 1038 : if (Search(nRow, nIndex))
1186 12 : if (!maItems[nIndex].pCell->IsBlank())
1187 12 : return true;
1188 :
1189 1026 : return false;
1190 : }
1191 :
1192 2 : bool ScColumn::IsEmptyAttr() const
1193 : {
1194 2 : if (pAttrArray)
1195 2 : return pAttrArray->IsEmpty();
1196 : else
1197 0 : return true;
1198 : }
1199 :
1200 2 : bool ScColumn::IsEmpty() const
1201 : {
1202 2 : return (IsEmptyData() && IsEmptyAttr());
1203 : }
1204 :
1205 2479 : bool ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const
1206 : {
1207 2479 : if ( maItems.empty() )
1208 2464 : return true;
1209 :
1210 : SCSIZE nIndex;
1211 15 : Search( nStartRow, nIndex );
1212 30 : while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nEndRow )
1213 : {
1214 13 : if ( !maItems[nIndex].pCell->IsBlank() ) // found a cell
1215 13 : return false; // not empty
1216 0 : ++nIndex;
1217 : }
1218 2 : return true; // no cell found
1219 : }
1220 :
1221 0 : SCSIZE ScColumn::GetEmptyLinesInBlock( SCROW nStartRow, SCROW nEndRow, ScDirection eDir ) const
1222 : {
1223 0 : SCSIZE nLines = 0;
1224 0 : bool bFound = false;
1225 : SCSIZE i;
1226 0 : if ( !maItems.empty() )
1227 : {
1228 0 : if (eDir == DIR_BOTTOM)
1229 : {
1230 0 : i = maItems.size();
1231 0 : while (!bFound && (i > 0))
1232 : {
1233 0 : i--;
1234 0 : if ( maItems[i].nRow < nStartRow )
1235 0 : break;
1236 0 : bFound = maItems[i].nRow <= nEndRow && !maItems[i].pCell->IsBlank();
1237 : }
1238 0 : if (bFound)
1239 0 : nLines = static_cast<SCSIZE>(nEndRow - maItems[i].nRow);
1240 : else
1241 0 : nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
1242 : }
1243 0 : else if (eDir == DIR_TOP)
1244 : {
1245 0 : i = 0;
1246 0 : while (!bFound && (i < maItems.size()))
1247 : {
1248 0 : if ( maItems[i].nRow > nEndRow )
1249 0 : break;
1250 0 : bFound = maItems[i].nRow >= nStartRow && !maItems[i].pCell->IsBlank();
1251 0 : i++;
1252 : }
1253 0 : if (bFound)
1254 0 : nLines = static_cast<SCSIZE>(maItems[i-1].nRow - nStartRow);
1255 : else
1256 0 : nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
1257 : }
1258 : }
1259 : else
1260 0 : nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
1261 0 : return nLines;
1262 : }
1263 :
1264 112 : SCROW ScColumn::GetFirstDataPos() const
1265 : {
1266 112 : if ( !maItems.empty() )
1267 112 : return maItems[0].nRow;
1268 : else
1269 0 : return 0;
1270 : }
1271 :
1272 809 : SCROW ScColumn::GetLastDataPos() const
1273 : {
1274 809 : if ( !maItems.empty() )
1275 729 : return maItems.back().nRow;
1276 : else
1277 80 : return 0;
1278 : }
1279 :
1280 0 : bool ScColumn::GetPrevDataPos(SCROW& rRow) const
1281 : {
1282 0 : bool bFound = false;
1283 0 : SCSIZE i = maItems.size();
1284 0 : while (!bFound && (i > 0))
1285 : {
1286 0 : --i;
1287 0 : bFound = (maItems[i].nRow < rRow);
1288 0 : if (bFound)
1289 0 : rRow = maItems[i].nRow;
1290 : }
1291 0 : return bFound;
1292 : }
1293 :
1294 664 : bool ScColumn::GetNextDataPos(SCROW& rRow) const // greater than rRow
1295 : {
1296 : SCSIZE nIndex;
1297 664 : if (Search( rRow, nIndex ))
1298 657 : ++nIndex; // next cell
1299 :
1300 664 : bool bMore = ( nIndex < maItems.size() );
1301 664 : if ( bMore )
1302 603 : rRow = maItems[nIndex].nRow;
1303 664 : return bMore;
1304 : }
1305 :
1306 9 : SCROW ScColumn::FindNextVisibleRow(SCROW nRow, bool bForward) const
1307 : {
1308 9 : if(bForward)
1309 : {
1310 9 : nRow++;
1311 9 : SCROW nEndRow = 0;
1312 9 : bool bHidden = pDocument->RowHidden(nRow, nTab, NULL, &nEndRow);
1313 9 : if(bHidden)
1314 2 : return std::min<SCROW>(MAXROW, nEndRow + 1);
1315 : else
1316 7 : return nRow;
1317 : }
1318 : else
1319 : {
1320 0 : nRow--;
1321 0 : SCROW nStartRow = MAXROW;
1322 0 : bool bHidden = pDocument->RowHidden(nRow, nTab, &nStartRow, NULL);
1323 0 : if(bHidden)
1324 0 : return std::max<SCROW>(0, nStartRow - 1);
1325 : else
1326 0 : return nRow;
1327 : }
1328 : }
1329 :
1330 4 : SCROW ScColumn::FindNextVisibleRowWithContent(SCROW nRow, bool bForward) const
1331 : {
1332 4 : if(bForward)
1333 : {
1334 0 : do
1335 : {
1336 4 : nRow++;
1337 4 : SCROW nEndRow = 0;
1338 4 : bool bHidden = pDocument->RowHidden(nRow, nTab, NULL, &nEndRow);
1339 4 : if(bHidden)
1340 : {
1341 1 : nRow = nEndRow + 1;
1342 1 : if(nRow >= MAXROW)
1343 0 : return MAXROW;
1344 : }
1345 :
1346 : SCSIZE nIndex;
1347 4 : bool bThere = Search( nRow, nIndex );
1348 4 : if( bThere && !maItems[nIndex].pCell->IsBlank())
1349 3 : return nRow;
1350 1 : else if(nIndex >= maItems.size())
1351 1 : return MAXROW;
1352 : else
1353 : {
1354 0 : if(bThere)
1355 0 : nRow = maItems[nIndex+1].nRow - 1;
1356 : else
1357 0 : nRow = maItems[nIndex].nRow - 1;
1358 : }
1359 : }
1360 : while(nRow < MAXROW);
1361 :
1362 0 : return MAXROW;
1363 : }
1364 : else
1365 : {
1366 0 : do
1367 : {
1368 0 : nRow--;
1369 0 : SCROW nStartRow = MAXROW;
1370 0 : bool bHidden = pDocument->RowHidden(nRow, nTab, &nStartRow, NULL);
1371 0 : if(bHidden)
1372 : {
1373 0 : nRow = nStartRow - 1;
1374 0 : if(nRow <= 0)
1375 0 : return 0;
1376 : }
1377 :
1378 : SCSIZE nIndex;
1379 0 : bool bThere = Search( nRow, nIndex );
1380 0 : if(bThere && !maItems[nIndex].pCell->IsBlank())
1381 0 : return nRow;
1382 0 : else if(nIndex == 0)
1383 0 : return 0;
1384 : else
1385 0 : nRow = maItems[nIndex-1].nRow + 1;
1386 : }
1387 : while(nRow > 0);
1388 :
1389 0 : return 0;
1390 : }
1391 : }
1392 :
1393 7 : void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const
1394 : {
1395 : // check if we are in a data area
1396 : SCSIZE nIndex;
1397 7 : bool bThere = Search(rRow, nIndex);
1398 7 : if (bThere && maItems[nIndex].pCell->IsBlank())
1399 0 : bThere = false;
1400 :
1401 7 : size_t nLastIndex = maItems.size() - 1;
1402 7 : if (bThere)
1403 : {
1404 6 : SCROW nNextRow = FindNextVisibleRow(rRow, bDown);
1405 : SCSIZE nNewIndex;
1406 6 : bool bNextThere = Search(nNextRow, nNewIndex);
1407 6 : if(bNextThere && maItems[nNewIndex].pCell->IsBlank())
1408 0 : bNextThere = false;
1409 :
1410 6 : if(bNextThere)
1411 : {
1412 : SCROW nLastRow;
1413 3 : nLastRow = nNextRow;
1414 3 : do
1415 : {
1416 3 : nNextRow = FindNextVisibleRow(nLastRow, bDown);
1417 3 : bNextThere = Search(nNextRow, nNewIndex);
1418 3 : if(!bNextThere || maItems[nNewIndex].pCell->IsBlank())
1419 3 : bNextThere = false;
1420 : else
1421 0 : nLastRow = nNextRow;
1422 : }
1423 : while(bNextThere && nNewIndex < nLastIndex && nNewIndex > 0);
1424 :
1425 3 : rRow = nLastRow;
1426 : }
1427 : else
1428 : {
1429 3 : rRow = FindNextVisibleRowWithContent(nNextRow, bDown);
1430 : }
1431 : }
1432 : else
1433 : {
1434 1 : rRow = FindNextVisibleRowWithContent(rRow, bDown);
1435 : }
1436 7 : }
1437 :
1438 231 : bool ScColumn::HasDataAt(SCROW nRow) const
1439 : {
1440 : // immer nur sichtbare interessant ?
1441 : //! dann HasVisibleDataAt raus
1442 :
1443 : SCSIZE nIndex;
1444 231 : if (Search(nRow, nIndex))
1445 209 : if (!maItems[nIndex].pCell->IsBlank())
1446 209 : return true;
1447 :
1448 22 : return false;
1449 :
1450 : }
1451 :
1452 2046 : bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
1453 : {
1454 2046 : if (pAttrArray && rCol.pAttrArray)
1455 2046 : return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow );
1456 : else
1457 0 : return !pAttrArray && !rCol.pAttrArray;
1458 : }
1459 :
1460 0 : bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
1461 : {
1462 0 : if (pAttrArray && rCol.pAttrArray)
1463 0 : return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow );
1464 : else
1465 0 : return !pAttrArray && !rCol.pAttrArray;
1466 : }
1467 :
1468 6144 : bool ScColumn::GetFirstVisibleAttr( SCROW& rFirstRow ) const
1469 : {
1470 6144 : if (pAttrArray)
1471 6144 : return pAttrArray->GetFirstVisibleAttr( rFirstRow );
1472 : else
1473 0 : return false;
1474 : }
1475 :
1476 80134 : bool ScColumn::GetLastVisibleAttr( SCROW& rLastRow, bool bFullFormattedArea ) const
1477 : {
1478 80134 : if (pAttrArray)
1479 : {
1480 : // row of last cell is needed
1481 80134 : SCROW nLastData = GetLastVisDataPos(); // always including notes, 0 if none
1482 :
1483 80134 : return pAttrArray->GetLastVisibleAttr( rLastRow, nLastData, bFullFormattedArea );
1484 : }
1485 : else
1486 0 : return false;
1487 : }
1488 :
1489 0 : bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
1490 : {
1491 0 : if (pAttrArray)
1492 0 : return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow );
1493 : else
1494 0 : return false;
1495 : }
1496 :
1497 0 : void ScColumn::FindUsed( SCROW nStartRow, SCROW nEndRow, bool* pUsed ) const
1498 : {
1499 0 : SCROW nRow = 0;
1500 : SCSIZE nIndex;
1501 0 : Search( nStartRow, nIndex );
1502 0 : while ( (nIndex < maItems.size()) ? ((nRow=maItems[nIndex].nRow) <= nEndRow) : false )
1503 : {
1504 0 : pUsed[nRow-nStartRow] = true;
1505 0 : ++nIndex;
1506 : }
1507 0 : }
1508 :
1509 5028 : void ScColumn::StartListening( SvtListener& rLst, SCROW nRow )
1510 : {
1511 5028 : SvtBroadcaster* pBC = NULL;
1512 : ScBaseCell* pCell;
1513 :
1514 : SCSIZE nIndex;
1515 5028 : if (Search(nRow,nIndex))
1516 : {
1517 5005 : pCell = maItems[nIndex].pCell;
1518 5005 : pBC = pCell->GetBroadcaster();
1519 : }
1520 : else
1521 : {
1522 23 : pCell = new ScNoteCell;
1523 23 : Insert(nRow, pCell);
1524 : }
1525 :
1526 5028 : if (!pBC)
1527 : {
1528 3637 : pBC = new SvtBroadcaster;
1529 3637 : pCell->TakeBroadcaster(pBC);
1530 : }
1531 5028 : rLst.StartListening(*pBC);
1532 5028 : }
1533 :
1534 0 : void ScColumn::MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow )
1535 : {
1536 0 : SvtBroadcaster* pBC = NULL;
1537 : ScBaseCell* pCell;
1538 :
1539 : SCSIZE nIndex;
1540 0 : if (Search(nDestRow,nIndex))
1541 : {
1542 0 : pCell = maItems[nIndex].pCell;
1543 0 : pBC = pCell->GetBroadcaster();
1544 : }
1545 : else
1546 : {
1547 0 : pCell = new ScNoteCell;
1548 0 : Insert(nDestRow, pCell);
1549 : }
1550 :
1551 0 : if (!pBC)
1552 : {
1553 0 : pBC = new SvtBroadcaster;
1554 0 : pCell->TakeBroadcaster(pBC);
1555 : }
1556 :
1557 0 : if (rSource.HasListeners())
1558 : {
1559 0 : SvtListenerIter aIter( rSource);
1560 0 : for (SvtListener* pLst = aIter.GoStart(); pLst; pLst = aIter.GoNext())
1561 : {
1562 0 : pLst->StartListening( *pBC);
1563 0 : pLst->EndListening( rSource);
1564 0 : }
1565 : }
1566 0 : }
1567 :
1568 176 : void ScColumn::EndListening( SvtListener& rLst, SCROW nRow )
1569 : {
1570 : SCSIZE nIndex;
1571 176 : if (Search(nRow,nIndex))
1572 : {
1573 174 : ScBaseCell* pCell = maItems[nIndex].pCell;
1574 174 : SvtBroadcaster* pBC = pCell->GetBroadcaster();
1575 174 : if (pBC)
1576 : {
1577 168 : rLst.EndListening(*pBC);
1578 :
1579 168 : if (!pBC->HasListeners())
1580 : {
1581 145 : if (pCell->IsBlank())
1582 43 : DeleteAtIndex(nIndex);
1583 : else
1584 102 : pCell->DeleteBroadcaster();
1585 : }
1586 : }
1587 : }
1588 176 : }
1589 :
1590 0 : void ScColumn::CompileDBFormula()
1591 : {
1592 0 : if ( !maItems.empty() )
1593 0 : for (SCSIZE i = 0; i < maItems.size(); i++)
1594 : {
1595 0 : ScBaseCell* pCell = maItems[i].pCell;
1596 0 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1597 0 : ((ScFormulaCell*) pCell)->CompileDBFormula();
1598 : }
1599 0 : }
1600 :
1601 0 : void ScColumn::CompileDBFormula( bool bCreateFormulaString )
1602 : {
1603 0 : if ( !maItems.empty() )
1604 0 : for (SCSIZE i = 0; i < maItems.size(); i++)
1605 : {
1606 0 : ScBaseCell* pCell = maItems[i].pCell;
1607 0 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1608 0 : ((ScFormulaCell*) pCell)->CompileDBFormula( bCreateFormulaString );
1609 : }
1610 0 : }
1611 :
1612 36864 : void ScColumn::CompileNameFormula( bool bCreateFormulaString )
1613 : {
1614 36864 : if ( !maItems.empty() )
1615 759 : for (SCSIZE i = 0; i < maItems.size(); i++)
1616 : {
1617 691 : ScBaseCell* pCell = maItems[i].pCell;
1618 691 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1619 34 : ((ScFormulaCell*) pCell)->CompileNameFormula( bCreateFormulaString );
1620 : }
1621 36864 : }
1622 :
1623 0 : void ScColumn::CompileColRowNameFormula()
1624 : {
1625 0 : if ( !maItems.empty() )
1626 0 : for (SCSIZE i = 0; i < maItems.size(); i++)
1627 : {
1628 0 : ScBaseCell* pCell = maItems[i].pCell;
1629 0 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1630 0 : ((ScFormulaCell*) pCell)->CompileColRowNameFormula();
1631 : }
1632 0 : }
1633 :
1634 0 : static void lcl_UpdateSubTotal( ScFunctionData& rData, const ScBaseCell* pCell )
1635 : {
1636 0 : double nValue = 0.0;
1637 0 : bool bVal = false;
1638 0 : bool bCell = true;
1639 0 : switch (pCell->GetCellType())
1640 : {
1641 : case CELLTYPE_VALUE:
1642 0 : nValue = ((ScValueCell*)pCell)->GetValue();
1643 0 : bVal = true;
1644 0 : break;
1645 : case CELLTYPE_FORMULA:
1646 : {
1647 0 : if ( rData.eFunc != SUBTOTAL_FUNC_CNT2 ) // da interessiert's nicht
1648 : {
1649 0 : ScFormulaCell* pFC = (ScFormulaCell*)pCell;
1650 0 : if ( pFC->GetErrCode() )
1651 : {
1652 0 : if ( rData.eFunc != SUBTOTAL_FUNC_CNT ) // fuer Anzahl einfach weglassen
1653 0 : rData.bError = true;
1654 : }
1655 0 : else if (pFC->IsValue())
1656 : {
1657 0 : nValue = pFC->GetValue();
1658 0 : bVal = true;
1659 : }
1660 : // sonst Text
1661 : }
1662 : }
1663 0 : break;
1664 : case CELLTYPE_NOTE:
1665 0 : bCell = false;
1666 0 : break;
1667 : // bei Strings nichts
1668 : default:
1669 : {
1670 : // added to avoid warnings
1671 : }
1672 : }
1673 :
1674 0 : if (!rData.bError)
1675 : {
1676 0 : switch (rData.eFunc)
1677 : {
1678 : case SUBTOTAL_FUNC_SUM:
1679 : case SUBTOTAL_FUNC_AVE:
1680 0 : if (bVal)
1681 : {
1682 0 : ++rData.nCount;
1683 0 : if (!SubTotal::SafePlus( rData.nVal, nValue ))
1684 0 : rData.bError = true;
1685 : }
1686 0 : break;
1687 : case SUBTOTAL_FUNC_CNT: // nur Werte
1688 0 : if (bVal)
1689 0 : ++rData.nCount;
1690 0 : break;
1691 : case SUBTOTAL_FUNC_CNT2: // alle
1692 0 : if (bCell)
1693 0 : ++rData.nCount;
1694 0 : break;
1695 : case SUBTOTAL_FUNC_MAX:
1696 0 : if (bVal)
1697 0 : if (++rData.nCount == 1 || nValue > rData.nVal )
1698 0 : rData.nVal = nValue;
1699 0 : break;
1700 : case SUBTOTAL_FUNC_MIN:
1701 0 : if (bVal)
1702 0 : if (++rData.nCount == 1 || nValue < rData.nVal )
1703 0 : rData.nVal = nValue;
1704 0 : break;
1705 : default:
1706 : {
1707 : // added to avoid warnings
1708 : }
1709 : }
1710 : }
1711 0 : }
1712 :
1713 : // Mehrfachselektion:
1714 0 : void ScColumn::UpdateSelectionFunction(
1715 : const ScMarkData& rMark, ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows,
1716 : bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow) const
1717 : {
1718 : SCSIZE nIndex;
1719 0 : ScMarkedDataIter aDataIter(this, &rMark, false);
1720 0 : while (aDataIter.Next( nIndex ))
1721 : {
1722 0 : SCROW nRow = maItems[nIndex].nRow;
1723 0 : bool bRowHidden = rHiddenRows.getValue(nRow);
1724 0 : if ( !bRowHidden )
1725 0 : if ( !bDoExclude || nRow < nExStartRow || nRow > nExEndRow )
1726 0 : lcl_UpdateSubTotal( rData, maItems[nIndex].pCell );
1727 0 : }
1728 0 : }
1729 :
1730 : // bei bNoMarked die Mehrfachselektion weglassen
1731 0 : void ScColumn::UpdateAreaFunction(
1732 : ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows, SCROW nStartRow, SCROW nEndRow) const
1733 : {
1734 : SCSIZE nIndex;
1735 0 : Search( nStartRow, nIndex );
1736 0 : while ( nIndex<maItems.size() && maItems[nIndex].nRow<=nEndRow )
1737 : {
1738 0 : SCROW nRow = maItems[nIndex].nRow;
1739 0 : bool bRowHidden = rHiddenRows.getValue(nRow);
1740 0 : if ( !bRowHidden )
1741 0 : lcl_UpdateSubTotal( rData, maItems[nIndex].pCell );
1742 0 : ++nIndex;
1743 : }
1744 0 : }
1745 :
1746 5285 : sal_uInt32 ScColumn::GetWeightedCount() const
1747 : {
1748 5285 : sal_uInt32 nTotal = 0;
1749 :
1750 : // Notizen werden nicht gezaehlt
1751 :
1752 19595 : for (SCSIZE i=0; i<maItems.size(); i++)
1753 : {
1754 14310 : ScBaseCell* pCell = maItems[i].pCell;
1755 14310 : switch ( pCell->GetCellType() )
1756 : {
1757 : case CELLTYPE_VALUE:
1758 : case CELLTYPE_STRING:
1759 14254 : ++nTotal;
1760 14254 : break;
1761 : case CELLTYPE_FORMULA:
1762 22 : nTotal += 5 + ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
1763 22 : break;
1764 : case CELLTYPE_EDIT:
1765 32 : nTotal += 50;
1766 32 : break;
1767 : default:
1768 : {
1769 : // added to avoid warnings
1770 : }
1771 : }
1772 : }
1773 :
1774 5285 : return nTotal;
1775 : }
1776 :
1777 0 : sal_uInt32 ScColumn::GetCodeCount() const
1778 : {
1779 0 : sal_uInt32 nCodeCount = 0;
1780 :
1781 0 : for (SCSIZE i=0; i<maItems.size(); i++)
1782 : {
1783 0 : ScBaseCell* pCell = maItems[i].pCell;
1784 0 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
1785 0 : nCodeCount += ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
1786 : }
1787 :
1788 0 : return nCodeCount;
1789 : }
1790 :
1791 :
1792 :
1793 :
1794 :
1795 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|