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