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