1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2011 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 // System - Includes ----------------------------------------------------- 32 33 34 35 #ifdef _MSC_VER 36 #pragma optimize("",off) 37 // sonst Absturz Win beim Fuellen 38 #endif 39 40 // INCLUDE --------------------------------------------------------------- 41 42 #include "scitems.hxx" 43 #include <svx/algitem.hxx> 44 #include <editeng/boxitem.hxx> 45 #include <editeng/brshitem.hxx> 46 #include <editeng/cntritem.hxx> 47 #include <editeng/colritem.hxx> 48 #include <editeng/crsditem.hxx> 49 #include <editeng/fhgtitem.hxx> 50 #include <editeng/fontitem.hxx> 51 #include <editeng/langitem.hxx> 52 #include <editeng/postitem.hxx> 53 #include <editeng/shdditem.hxx> 54 #include <editeng/udlnitem.hxx> 55 #include <editeng/wghtitem.hxx> 56 #include <svx/rotmodit.hxx> 57 #include <editeng/editobj.hxx> 58 #include <editeng/editeng.hxx> 59 #include <editeng/eeitem.hxx> 60 #include <editeng/escpitem.hxx> 61 #include <svl/zforlist.hxx> 62 #include <vcl/keycodes.hxx> 63 #include <rtl/math.hxx> 64 #include <unotools/charclass.hxx> 65 66 #include "attrib.hxx" 67 #include "patattr.hxx" 68 #include "cell.hxx" 69 #include "table.hxx" 70 #include "globstr.hrc" 71 #include "global.hxx" 72 #include "document.hxx" 73 #include "autoform.hxx" 74 #include "userlist.hxx" 75 #include "zforauto.hxx" 76 #include "subtotal.hxx" 77 #include "formula/errorcodes.hxx" 78 #include "rangenam.hxx" 79 #include "docpool.hxx" 80 #include "progress.hxx" 81 #include "segmenttree.hxx" 82 83 #include <math.h> 84 85 // STATIC DATA ----------------------------------------------------------- 86 87 #define _D_MAX_LONG_ (double) 0x7fffffff 88 89 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx 90 91 // ----------------------------------------------------------------------- 92 93 short lcl_DecompValueString( String& aValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL ) 94 { 95 if ( !aValue.Len() ) 96 { 97 nVal = 0; 98 return 0; 99 } 100 const sal_Unicode* p = aValue.GetBuffer(); 101 xub_StrLen nNeg = 0; 102 xub_StrLen nNum = 0; 103 if ( p[nNum] == '-' ) 104 nNum = nNeg = 1; 105 while ( p[nNum] && CharClass::isAsciiNumeric( p[nNum] ) ) 106 nNum++; 107 108 sal_Unicode cNext = p[nNum]; // 0 if at the end 109 sal_Unicode cLast = p[aValue.Len()-1]; 110 111 // #i5550# If there are numbers at the beginning and the end, 112 // prefer the one at the beginning only if it's followed by a space. 113 // Otherwise, use the number at the end, to enable things like IP addresses. 114 if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(cLast) ) ) 115 { // number at the beginning 116 nVal = aValue.Copy( 0, nNum ).ToInt32(); 117 // #60893# any number with a leading zero sets the minimum number of digits 118 if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) ) 119 *pMinDigits = nNum - nNeg; 120 aValue.Erase( 0, nNum ); 121 return -1; 122 } 123 else 124 { 125 nNeg = 0; 126 xub_StrLen nEnd = nNum = aValue.Len() - 1; 127 while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) ) 128 nNum--; 129 if ( p[nNum] == '-' ) 130 { 131 nNum--; 132 nNeg = 1; 133 } 134 if ( nNum < nEnd - nNeg ) 135 { // number at the end 136 nVal = aValue.Copy( nNum + 1 ).ToInt32(); 137 // #60893# any number with a leading zero sets the minimum number of digits 138 if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) ) 139 *pMinDigits = nEnd - nNum - nNeg; 140 aValue.Erase( nNum + 1 ); 141 return 1; 142 } 143 } 144 nVal = 0; 145 return 0; 146 } 147 148 String lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits ) 149 { 150 if ( nMinDigits <= 1 ) 151 return String::CreateFromInt32( nValue ); // simple case... 152 else 153 { 154 String aStr = String::CreateFromInt32( Abs( nValue ) ); 155 if ( aStr.Len() < nMinDigits ) 156 { 157 String aZero; 158 aZero.Fill( nMinDigits - aStr.Len(), '0' ); 159 aStr.Insert( aZero, 0 ); 160 } 161 // nMinDigits doesn't include the '-' sign -> add after inserting zeros 162 if ( nValue < 0 ) 163 aStr.Insert( '-', 0 ); 164 return aStr; 165 } 166 } 167 168 static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue, 169 sal_uInt16 nDigits, const String& rSuffix, CellType eCellType, 170 sal_Bool bIsOrdinalSuffix ) 171 { 172 String aValue( lcl_ValueString( nValue, nDigits )); 173 if (!bIsOrdinalSuffix) 174 return new ScStringCell( aValue += rSuffix); 175 176 String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue)); 177 if (eCellType != CELLTYPE_EDIT) 178 return new ScStringCell( aValue += aOrdinalSuffix); 179 180 EditEngine aEngine( pDocument->GetEnginePool() ); 181 SfxItemSet aAttr = aEngine.GetEmptyItemSet(); 182 aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT)); 183 aEngine.SetText( aValue ); 184 aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0, 185 aValue.Len() + aOrdinalSuffix.Len())); 186 aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() + 187 aOrdinalSuffix.Len())); 188 return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL ); 189 } 190 191 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 192 FillCmd& rCmd, FillDateCmd& rDateCmd, 193 double& rInc, sal_uInt16& rMinDigits, 194 ScUserListData*& rListData, sal_uInt16& rListIndex) 195 { 196 DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" ); 197 198 rInc = 0.0; 199 rMinDigits = 0; 200 rListData = NULL; 201 rCmd = FILL_SIMPLE; 202 if (( nScFillModeMouseModifier & KEY_MOD1 )||IsDataFiltered()) //i89232 203 return ; // Ctrl-Taste: Copy 204 205 SCCOL nAddX; 206 SCROW nAddY; 207 SCSIZE nCount; 208 if (nCol1 == nCol2) 209 { 210 nAddX = 0; 211 nAddY = 1; 212 nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1); 213 } 214 else 215 { 216 nAddX = 1; 217 nAddY = 0; 218 nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1); 219 } 220 221 SCCOL nCol = nCol1; 222 SCROW nRow = nRow1; 223 224 ScBaseCell* pFirstCell = GetCell( nCol, nRow ); 225 CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE; 226 227 if (eCellType == CELLTYPE_VALUE) 228 { 229 sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue(); 230 sal_Bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE ); 231 if (bDate) 232 { 233 if (nCount > 1) 234 { 235 long nCmpInc = 0; 236 double nVal; 237 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate(); 238 Date aDate1 = aNullDate; 239 nVal = ((ScValueCell*)pFirstCell)->GetValue(); 240 aDate1 += (long)nVal; 241 Date aDate2 = aNullDate; 242 nVal = GetValue(nCol+nAddX, nRow+nAddY); 243 aDate2 += (long)nVal; 244 if ( aDate1 != aDate2 ) 245 { 246 FillDateCmd eType; 247 long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay(); 248 long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth(); 249 long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear(); 250 if ( nDDiff ) 251 { 252 eType = FILL_DAY; 253 nCmpInc = aDate2 - aDate1; 254 } 255 else 256 { 257 eType = FILL_MONTH; 258 nCmpInc = nMDiff + 12 * nYDiff; 259 } 260 261 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 262 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 263 sal_Bool bVal = sal_True; 264 for (sal_uInt16 i=1; i<nCount && bVal; i++) 265 { 266 ScBaseCell* pCell = GetCell(nCol,nRow); 267 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE) 268 { 269 nVal = ((ScValueCell*)pCell)->GetValue(); 270 aDate2 = aNullDate + (long) nVal; 271 if ( eType == FILL_DAY ) 272 { 273 if ( aDate2-aDate1 != nCmpInc ) 274 bVal = sal_False; 275 } 276 else 277 { 278 nDDiff = aDate2.GetDay() - (long) aDate1.GetDay(); 279 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth(); 280 nYDiff = aDate2.GetYear() - (long) aDate1.GetYear(); 281 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc )) 282 bVal = sal_False; 283 } 284 aDate1 = aDate2; 285 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 286 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 287 } 288 else 289 bVal = sal_False; // #50965# kein Datum passt auch nicht 290 } 291 if (bVal) 292 { 293 if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) ) 294 { 295 eType = FILL_YEAR; 296 nCmpInc /= 12; 297 } 298 rCmd = FILL_DATE; 299 rDateCmd = eType; 300 rInc = nCmpInc; 301 } 302 } 303 } 304 else // einzelnes Datum -> Tage hochzaehlen 305 { 306 rCmd = FILL_DATE; 307 rDateCmd = FILL_DAY; 308 rInc = 1.0; 309 } 310 } 311 else 312 { 313 if (nCount > 1) 314 { 315 double nVal1 = ((ScValueCell*)pFirstCell)->GetValue(); 316 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY); 317 rInc = nVal2 - nVal1; 318 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 319 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 320 sal_Bool bVal = sal_True; 321 for (sal_uInt16 i=1; i<nCount && bVal; i++) 322 { 323 ScBaseCell* pCell = GetCell(nCol,nRow); 324 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE) 325 { 326 nVal2 = ((ScValueCell*)pCell)->GetValue(); 327 double nDiff = nVal2 - nVal1; 328 if ( !::rtl::math::approxEqual( nDiff, rInc ) ) 329 bVal = sal_False; 330 nVal1 = nVal2; 331 } 332 else 333 bVal = sal_False; 334 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 335 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 336 } 337 if (bVal) 338 rCmd = FILL_LINEAR; 339 } 340 } 341 } 342 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) 343 { 344 String aStr; 345 GetString(nCol, nRow, aStr); 346 rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr)); 347 if (rListData) 348 { 349 rListData->GetSubIndex(aStr, rListIndex); 350 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 351 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 352 for (sal_uInt16 i=1; i<nCount && rListData; i++) 353 { 354 GetString(nCol, nRow, aStr); 355 if (!rListData->GetSubIndex(aStr, rListIndex)) 356 rListData = NULL; 357 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 358 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 359 } 360 } 361 else if ( nCount > 1 ) 362 { 363 // pass rMinDigits to all DecompValueString calls 364 // -> longest number defines rMinDigits 365 366 sal_Int32 nVal1; 367 short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits ); 368 if ( nFlag1 ) 369 { 370 sal_Int32 nVal2; 371 GetString( nCol+nAddX, nRow+nAddY, aStr ); 372 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits ); 373 if ( nFlag1 == nFlag2 ) 374 { 375 rInc = (double)nVal2 - (double)nVal1; 376 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 377 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 378 sal_Bool bVal = sal_True; 379 for (sal_uInt16 i=1; i<nCount && bVal; i++) 380 { 381 ScBaseCell* pCell = GetCell(nCol,nRow); 382 CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE; 383 if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT ) 384 { 385 if ( eType == CELLTYPE_STRING ) 386 ((ScStringCell*)pCell)->GetString( aStr ); 387 else 388 ((ScEditCell*)pCell)->GetString( aStr ); 389 nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits ); 390 if ( nFlag1 == nFlag2 ) 391 { 392 double nDiff = (double)nVal2 - (double)nVal1; 393 if ( !::rtl::math::approxEqual( nDiff, rInc ) ) 394 bVal = sal_False; 395 nVal1 = nVal2; 396 } 397 else 398 bVal = sal_False; 399 } 400 else 401 bVal = sal_False; 402 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); 403 nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); 404 } 405 if (bVal) 406 rCmd = FILL_LINEAR; 407 } 408 } 409 } 410 else 411 { 412 // call DecompValueString to set rMinDigits 413 sal_Int32 nDummy; 414 lcl_DecompValueString( aStr, nDummy, &rMinDigits ); 415 } 416 } 417 } 418 419 void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, sal_Bool /* bFirst */, ScFormulaCell* pSrcCell, 420 SCCOL nDestCol, SCROW nDestRow, sal_Bool bLast ) 421 { 422 /* sal_uInt16 nTokArrLen = pSrcCell->GetTokenArrayLen(); 423 if ( nTokArrLen > 15 ) // mehr als =A1 oder =67 424 { 425 ScRangeName* pRangeName = pDocument->GetRangeName(); 426 String aName("___SC_"); // Wird dieser String veraendert, 427 // auch in document2 EraseNonUsed... 428 // mitaendern!! 429 aName += pRangeName->GetSharedMaxIndex() + 1; 430 aName += '_'; 431 aName += nFormulaCounter; 432 nFormulaCounter++; 433 if (bFirst) 434 { 435 ScRangeData *pAktRange = new ScRangeData( 436 pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen, 437 pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED); 438 if (!pRangeName->Insert( pAktRange )) 439 delete pAktRange; 440 else 441 bSharedNameInserted = sal_True; 442 } 443 sal_uInt16 nIndex; 444 pRangeName->SearchName(aName, nIndex); 445 if (!pRangeName) 446 { 447 DBG_ERROR("ScTable::FillFormula: Falscher Name"); 448 return; 449 } 450 nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex(); 451 ScTokenArray aArr; 452 aArr.AddName(nIndex); 453 aArr.AddOpCode(ocStop); 454 ScFormulaCell* pDestCell = new ScFormulaCell 455 (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr ); 456 aCol[nDestCol].Insert(nDestRow, pDestCell); 457 } 458 else 459 */ { 460 pDocument->SetNoListening( sal_True ); // noch falsche Referenzen 461 ScAddress aAddr( nDestCol, nDestRow, nTab ); 462 ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr ); 463 aCol[nDestCol].Insert(nDestRow, pDestCell); 464 #if 0 465 // mit RelRefs unnoetig 466 pDestCell->UpdateReference(URM_COPY, 467 ScRange( aAddr, aAddr ), 468 nDestCol - pSrcCell->aPos.Col(), 469 nDestRow - pSrcCell->aPos.Row(), 0); 470 #endif 471 if ( bLast && pDestCell->GetMatrixFlag() ) 472 { 473 ScAddress aOrg; 474 if ( pDestCell->GetMatrixOrigin( aOrg ) ) 475 { 476 if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() ) 477 { 478 ScBaseCell* pOrgCell = pDocument->GetCell( aOrg ); 479 if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA 480 && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA ) 481 { 482 ((ScFormulaCell*)pOrgCell)->SetMatColsRows( 483 nDestCol - aOrg.Col() + 1, 484 nDestRow - aOrg.Row() + 1 ); 485 } 486 else 487 { 488 DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" ); 489 } 490 } 491 else 492 { 493 DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" ); 494 } 495 } 496 else 497 { 498 DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" ); 499 } 500 } 501 pDocument->SetNoListening( sal_False ); 502 pDestCell->StartListeningTo( pDocument ); 503 } 504 } 505 506 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 507 sal_uLong nFillCount, FillDir eFillDir, ScProgress& rProgress ) 508 { 509 if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) ) 510 return; 511 512 // 513 // Richtung auswerten 514 // 515 516 sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP); 517 sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT); 518 519 sal_uLong nCol = 0; 520 sal_uLong nRow = 0; 521 sal_uLong& rInner = bVertical ? nRow : nCol; // Schleifenvariablen 522 sal_uLong& rOuter = bVertical ? nCol : nRow; 523 sal_uLong nOStart; 524 sal_uLong nOEnd; 525 sal_uLong nIStart; 526 sal_uLong nIEnd; 527 sal_uLong nISrcStart; 528 sal_uLong nISrcEnd; 529 530 if (bVertical) 531 { 532 nOStart = nCol1; 533 nOEnd = nCol2; 534 if (bPositive) 535 { 536 nISrcStart = nRow1; 537 nISrcEnd = nRow2; 538 nIStart = nRow2 + 1; 539 nIEnd = nRow2 + nFillCount; 540 } 541 else 542 { 543 nISrcStart = nRow2; 544 nISrcEnd = nRow1; 545 nIStart = nRow1 - 1; 546 nIEnd = nRow1 - nFillCount; 547 } 548 } 549 else 550 { 551 nOStart = nRow1; 552 nOEnd = nRow2; 553 if (bPositive) 554 { 555 nISrcStart = nCol1; 556 nISrcEnd = nCol2; 557 nIStart = nCol2 + 1; 558 nIEnd = nCol2 + nFillCount; 559 } 560 else 561 { 562 nISrcStart = nCol2; 563 nISrcEnd = nCol1; 564 nIStart = nCol1 - 1; 565 nIEnd = nCol1 - nFillCount; 566 } 567 } 568 sal_uLong nIMin = nIStart; 569 sal_uLong nIMax = nIEnd; 570 PutInOrder(nIMin,nIMax); 571 sal_Bool bHasFiltered = IsDataFiltered(); 572 if (!bHasFiltered) //modify for i89232 573 { 574 if (bVertical) 575 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL); 576 else 577 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL); 578 } 579 sal_uLong nProgress = rProgress.GetState(); 580 581 // 582 // ausfuehren 583 // 584 585 sal_uLong nActFormCnt = 0; 586 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++) 587 { 588 sal_uLong nMaxFormCnt = 0; // fuer Formeln 589 590 // Attributierung uebertragen 591 592 const ScPatternAttr* pSrcPattern = NULL; 593 const ScStyleSheet* pStyleSheet = NULL; 594 sal_uLong nAtSrc = nISrcStart; 595 ScPatternAttr* pNewPattern = NULL; 596 sal_Bool bGetPattern = sal_True; 597 rInner = nIStart; 598 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes 599 { 600 if ( bGetPattern ) 601 { 602 if ( pNewPattern ) 603 delete pNewPattern; 604 if (bVertical) // rInner&:=nRow, rOuter&:=nCol 605 pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc)); 606 else // rInner&:=nCol, rOuter&:=nRow 607 pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow)); 608 bGetPattern = sal_False; 609 pStyleSheet = pSrcPattern->GetStyleSheet(); 610 // Merge/Mergeflag nicht uebernehmen, 611 const SfxItemSet& rSet = pSrcPattern->GetItemSet(); 612 if ( rSet.GetItemState(ATTR_MERGE, sal_False) == SFX_ITEM_SET 613 || rSet.GetItemState(ATTR_MERGE_FLAG, sal_False) == SFX_ITEM_SET ) 614 { 615 pNewPattern = new ScPatternAttr( *pSrcPattern ); 616 SfxItemSet& rNewSet = pNewPattern->GetItemSet(); 617 rNewSet.ClearItem(ATTR_MERGE); 618 rNewSet.ClearItem(ATTR_MERGE_FLAG); 619 } 620 else 621 pNewPattern = NULL; 622 } 623 624 if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered ) 625 { 626 // Attribute komplett am Stueck setzen 627 if (pNewPattern || pSrcPattern != pDocument->GetDefPattern()) 628 { 629 // Default steht schon da (DeleteArea) 630 SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd )); 631 SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd )); 632 if ( pStyleSheet ) 633 aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet ); 634 if ( pNewPattern ) 635 aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern ); 636 else 637 aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern ); 638 } 639 break; // Schleife abbrechen 640 } 641 642 if ( !RowFiltered(nRow) ) 643 { 644 if ( bHasFiltered ) 645 DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), 646 static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL); 647 648 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) ) 649 { 650 // Vorlage auch uebernehmen 651 //! am AttrArray mit ApplyPattern zusammenfassen ?? 652 if ( pStyleSheet ) 653 aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet ); 654 655 // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen 656 if ( pNewPattern ) 657 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern ); 658 else 659 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern ); 660 } 661 662 if (nAtSrc==nISrcEnd) 663 { 664 if ( nAtSrc != nISrcStart ) 665 { // mehr als eine Source-Zelle 666 nAtSrc = nISrcStart; 667 bGetPattern = sal_True; 668 } 669 } 670 else if (bPositive) 671 { 672 ++nAtSrc; 673 bGetPattern = sal_True; 674 } 675 else 676 { 677 --nAtSrc; 678 bGetPattern = sal_True; 679 } 680 } 681 682 if (rInner == nIEnd) break; 683 if (bPositive) ++rInner; else --rInner; 684 } 685 if ( pNewPattern ) 686 delete pNewPattern; 687 688 // Analyse 689 690 FillCmd eFillCmd; 691 FillDateCmd eDateCmd; 692 double nInc; 693 sal_uInt16 nMinDigits; 694 ScUserListData* pListData = NULL; 695 sal_uInt16 nListIndex; 696 if (bVertical) 697 FillAnalyse(static_cast<SCCOL>(nCol),nRow1, 698 static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd, 699 nInc,nMinDigits, pListData,nListIndex); 700 else 701 FillAnalyse(nCol1,static_cast<SCROW>(nRow), 702 nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd, 703 nInc,nMinDigits, pListData,nListIndex); 704 705 if (bVertical) 706 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount ); 707 708 if (pListData) 709 { 710 sal_uInt16 nListCount = pListData->GetSubCount(); 711 if ( !bPositive ) 712 { 713 // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen 714 sal_uLong nSub = nISrcStart - nISrcEnd; 715 for (sal_uLong i=0; i<nSub; i++) 716 { 717 if (nListIndex == 0) nListIndex = nListCount; 718 --nListIndex; 719 } 720 } 721 722 rInner = nIStart; 723 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes 724 { 725 if (bPositive) 726 { 727 ++nListIndex; 728 if (nListIndex >= nListCount) nListIndex = 0; 729 } 730 else 731 { 732 if (nListIndex == 0) nListIndex = nListCount; 733 --nListIndex; 734 } 735 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex))); 736 737 if (rInner == nIEnd) break; 738 if (bPositive) ++rInner; else --rInner; 739 } 740 nProgress += nIMax - nIMin + 1; 741 rProgress.SetStateOnPercent( nProgress ); 742 } 743 else if (eFillCmd == FILL_SIMPLE) // Auffuellen mit Muster 744 { 745 sal_uLong nSource = nISrcStart; 746 double nDelta; 747 if (( nScFillModeMouseModifier & KEY_MOD1 )||bHasFiltered) //i89232 748 nDelta = 0.0; 749 else if ( bPositive ) 750 nDelta = 1.0; 751 else 752 nDelta = -1.0; 753 double nVal = 0.0; 754 sal_uLong nFormulaCounter = nActFormCnt; 755 sal_Bool bFirst = sal_True; 756 sal_Bool bGetCell = sal_True; 757 sal_uInt16 nCellDigits = 0; 758 short nHeadNoneTail = 0; 759 sal_Int32 nStringValue = 0; 760 String aValue; 761 ScBaseCell* pSrcCell = NULL; 762 CellType eCellType = CELLTYPE_NONE; 763 sal_Bool bIsOrdinalSuffix = sal_False; 764 sal_Bool bRowFiltered = sal_False; //i89232 765 766 rInner = nIStart; 767 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes 768 { 769 if ( bGetCell ) 770 { 771 if (bVertical) // rInner&:=nRow, rOuter&:=nCol 772 pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) ); 773 else // rInner&:=nCol, rOuter&:=nRow 774 pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) ); 775 bGetCell = sal_False; 776 if ( pSrcCell ) 777 { 778 eCellType = pSrcCell->GetCellType(); 779 switch ( eCellType ) 780 { 781 case CELLTYPE_VALUE: 782 nVal = ((ScValueCell*)pSrcCell)->GetValue(); 783 break; 784 case CELLTYPE_STRING: 785 case CELLTYPE_EDIT: 786 if ( eCellType == CELLTYPE_STRING ) 787 ((ScStringCell*)pSrcCell)->GetString( aValue ); 788 else 789 ((ScEditCell*)pSrcCell)->GetString( aValue ); 790 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered) //i89232 791 { 792 nCellDigits = 0; // look at each source cell individually 793 nHeadNoneTail = lcl_DecompValueString( 794 aValue, nStringValue, &nCellDigits ); 795 796 bIsOrdinalSuffix = aValue.Equals( 797 ScGlobal::GetOrdinalSuffix( nStringValue)); 798 } 799 break; 800 default: 801 { 802 // added to avoid warnings 803 } 804 } 805 } 806 else 807 eCellType = CELLTYPE_NONE; 808 } 809 810 //Modify for i89232 811 bRowFiltered = mpFilteredRows->getValue(nRow); 812 813 if (!bRowFiltered) 814 { 815 //End of i89232 816 817 switch (eCellType) 818 { 819 case CELLTYPE_VALUE: 820 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta)); 821 break; 822 case CELLTYPE_STRING: 823 case CELLTYPE_EDIT: 824 if ( nHeadNoneTail ) 825 { 826 // #i48009# with the "nStringValue+(long)nDelta" expression within the 827 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3), 828 // so nNextValue is now calculated ahead. 829 sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta; 830 831 String aStr; 832 if ( nHeadNoneTail < 0 ) 833 { 834 aCol[nCol].Insert( static_cast<SCROW>(nRow), 835 lcl_getSuffixCell( pDocument, 836 nNextValue, nCellDigits, aValue, 837 eCellType, bIsOrdinalSuffix)); 838 } 839 else 840 { 841 aStr = aValue; 842 aStr += lcl_ValueString( nNextValue, nCellDigits ); 843 aCol[nCol].Insert( static_cast<SCROW>(nRow), 844 new ScStringCell( aStr)); 845 } 846 } 847 else 848 { 849 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); 850 switch ( eCellType ) 851 { 852 case CELLTYPE_STRING: 853 case CELLTYPE_EDIT: 854 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) ); 855 break; 856 default: 857 { 858 // added to avoid warnings 859 } 860 } 861 } 862 break; 863 case CELLTYPE_FORMULA : 864 FillFormula( nFormulaCounter, bFirst, 865 (ScFormulaCell*) pSrcCell, 866 static_cast<SCCOL>(nCol), 867 static_cast<SCROW>(nRow), (rInner == nIEnd) ); 868 if (nFormulaCounter - nActFormCnt > nMaxFormCnt) 869 nMaxFormCnt = nFormulaCounter - nActFormCnt; 870 break; 871 default: 872 { 873 // added to avoid warnings 874 } 875 } 876 877 if (nSource==nISrcEnd) 878 { 879 if ( nSource != nISrcStart ) 880 { // mehr als eine Source-Zelle 881 nSource = nISrcStart; 882 bGetCell = sal_True; 883 } 884 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered ) //i89232 885 { 886 if ( bPositive ) 887 nDelta += 1.0; 888 else 889 nDelta -= 1.0; 890 } 891 nFormulaCounter = nActFormCnt; 892 bFirst = sal_False; 893 } 894 else if (bPositive) 895 { 896 ++nSource; 897 bGetCell = sal_True; 898 } 899 else 900 { 901 --nSource; 902 bGetCell = sal_True; 903 } 904 } 905 906 // Progress in der inneren Schleife nur bei teuren Zellen, 907 // und auch dann nicht fuer jede einzelne 908 909 ++nProgress; 910 if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT ) 911 rProgress.SetStateOnPercent( nProgress ); 912 913 if (rInner == nIEnd) break; 914 if (bPositive) ++rInner; else --rInner; 915 } 916 rProgress.SetStateOnPercent( nProgress ); 917 } 918 else 919 { 920 if (!bPositive) 921 nInc = -nInc; 922 double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE; 923 if (bVertical) 924 FillSeries( static_cast<SCCOL>(nCol), nRow1, 925 static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir, 926 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False, 927 rProgress ); 928 else 929 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2, 930 static_cast<SCROW>(nRow), nFillCount, eFillDir, 931 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False, 932 rProgress ); 933 nProgress = rProgress.GetState(); 934 } 935 936 nActFormCnt += nMaxFormCnt; 937 } 938 } 939 940 String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY ) 941 { 942 String aValue; 943 944 SCCOL nCol1 = rSource.aStart.Col(); 945 SCROW nRow1 = rSource.aStart.Row(); 946 SCCOL nCol2 = rSource.aEnd.Col(); 947 SCROW nRow2 = rSource.aEnd.Row(); 948 sal_Bool bOk = sal_True; 949 long nIndex = 0; 950 sal_uLong nSrcCount = 0; 951 FillDir eFillDir = FILL_TO_BOTTOM; 952 if ( nEndX == nCol2 && nEndY == nRow2 ) // leer 953 bOk = sal_False; 954 else if ( nEndX == nCol2 ) // nach oben/unten 955 { 956 nEndX = nCol2 = nCol1; // nur erste Spalte ansehen 957 nSrcCount = nRow2 - nRow1 + 1; 958 nIndex = ((long)nEndY) - nRow1; // kann negativ werden 959 if ( nEndY >= nRow1 ) 960 eFillDir = FILL_TO_BOTTOM; 961 else 962 eFillDir = FILL_TO_TOP; 963 } 964 else if ( nEndY == nRow2 ) // nach links/rechts 965 { 966 nEndY = nRow2 = nRow1; // nur erste Zeile ansehen 967 nSrcCount = nCol2 - nCol1 + 1; 968 nIndex = ((long)nEndX) - nCol1; // kann negativ werden 969 if ( nEndX >= nCol1 ) 970 eFillDir = FILL_TO_RIGHT; 971 else 972 eFillDir = FILL_TO_LEFT; 973 } 974 else // Richtung nicht eindeutig 975 bOk = sal_False; 976 977 if ( bOk ) 978 { 979 FillCmd eFillCmd; 980 FillDateCmd eDateCmd; 981 double nInc; 982 sal_uInt16 nMinDigits; 983 ScUserListData* pListData = NULL; 984 sal_uInt16 nListIndex; 985 986 FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex); 987 988 if ( pListData ) // benutzerdefinierte Liste 989 { 990 sal_uInt16 nListCount = pListData->GetSubCount(); 991 if ( nListCount ) 992 { 993 sal_uLong nSub = nSrcCount - 1; // nListIndex ist vom letzten Source-Eintrag 994 while ( nIndex < sal::static_int_cast<long>(nSub) ) 995 nIndex += nListCount; 996 sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount; 997 aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos)); 998 } 999 } 1000 else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster 1001 { 1002 //Add for i89232 1003 if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP)) 1004 { 1005 long nBegin = 0; 1006 long nEnd = 0; 1007 if (nEndY > nRow1) 1008 { 1009 nBegin = nRow2+1; 1010 nEnd = nEndY; 1011 } 1012 else 1013 { 1014 nBegin = nEndY; 1015 nEnd = nRow1 -1; 1016 } 1017 long nNonFiltered = CountNonFilteredRows(nBegin, nEnd); 1018 long nFiltered = nEnd + 1 - nBegin - nNonFiltered; 1019 if (nIndex >0) 1020 nIndex = nIndex - nFiltered; 1021 else 1022 nIndex = nIndex + nFiltered; 1023 } 1024 //End of i89232 1025 1026 long nPosIndex = nIndex; 1027 while ( nPosIndex < 0 ) 1028 nPosIndex += nSrcCount; 1029 sal_uLong nPos = nPosIndex % nSrcCount; 1030 SCCOL nSrcX = nCol1; 1031 SCROW nSrcY = nRow1; 1032 if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM ) 1033 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) ); 1034 else 1035 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) ); 1036 1037 ScBaseCell* pCell = GetCell( nSrcX, nSrcY ); 1038 if ( pCell ) 1039 { 1040 sal_Int32 nDelta; 1041 if (nIndex >= 0) 1042 nDelta = nIndex / nSrcCount; 1043 else 1044 nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1 1045 1046 CellType eType = pCell->GetCellType(); 1047 switch ( eType ) 1048 { 1049 case CELLTYPE_STRING: 1050 case CELLTYPE_EDIT: 1051 { 1052 if ( eType == CELLTYPE_STRING ) 1053 ((ScStringCell*)pCell)->GetString( aValue ); 1054 else 1055 ((ScEditCell*)pCell)->GetString( aValue ); 1056 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232 1057 { 1058 sal_Int32 nVal; 1059 sal_uInt16 nCellDigits = 0; // look at each source cell individually 1060 short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits ); 1061 if ( nFlag < 0 ) 1062 { 1063 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal))) 1064 aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta); 1065 1066 aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 ); 1067 } 1068 else if ( nFlag > 0 ) 1069 aValue += lcl_ValueString( nVal + nDelta, nCellDigits ); 1070 } 1071 } 1072 break; 1073 case CELLTYPE_VALUE: 1074 { 1075 // dabei kann's keinen Ueberlauf geben... 1076 double nVal = ((ScValueCell*)pCell)->GetValue(); 1077 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232 1078 nVal += (double) nDelta; 1079 1080 Color* pColor; 1081 sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY ); 1082 pDocument->GetFormatTable()-> 1083 GetOutputString( nVal, nNumFmt, aValue, &pColor ); 1084 } 1085 break; 1086 // Formeln nicht 1087 default: 1088 { 1089 // added to avoid warnings 1090 } 1091 } 1092 } 1093 } 1094 else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // Werte 1095 { 1096 sal_Bool bValueOk; 1097 double nStart; 1098 sal_Int32 nVal = 0; 1099 short nHeadNoneTail = 0; 1100 ScBaseCell* pCell = GetCell( nCol1, nRow1 ); 1101 if ( pCell ) 1102 { 1103 CellType eType = pCell->GetCellType(); 1104 switch ( eType ) 1105 { 1106 case CELLTYPE_STRING: 1107 case CELLTYPE_EDIT: 1108 { 1109 if ( eType == CELLTYPE_STRING ) 1110 ((ScStringCell*)pCell)->GetString( aValue ); 1111 else 1112 ((ScEditCell*)pCell)->GetString( aValue ); 1113 nHeadNoneTail = lcl_DecompValueString( aValue, nVal ); 1114 if ( nHeadNoneTail ) 1115 nStart = (double)nVal; 1116 else 1117 nStart = 0.0; 1118 } 1119 break; 1120 case CELLTYPE_VALUE: 1121 nStart = ((ScValueCell*)pCell)->GetValue(); 1122 break; 1123 case CELLTYPE_FORMULA: 1124 nStart = ((ScFormulaCell*)pCell)->GetValue(); 1125 break; 1126 default: 1127 nStart = 0.0; 1128 } 1129 } 1130 else 1131 nStart = 0.0; 1132 if ( eFillCmd == FILL_LINEAR ) 1133 { 1134 double nAdd = nInc; 1135 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) && 1136 SubTotal::SafePlus( nStart, nAdd ) ); 1137 } 1138 else // Datum 1139 { 1140 bValueOk = sal_True; 1141 sal_uInt16 nDayOfMonth = 0; 1142 if ( nIndex < 0 ) 1143 { 1144 nIndex = -nIndex; 1145 nInc = -nInc; 1146 } 1147 for (long i=0; i<nIndex; i++) 1148 IncDate( nStart, nDayOfMonth, nInc, eDateCmd ); 1149 } 1150 1151 if (bValueOk) 1152 { 1153 if ( nHeadNoneTail ) 1154 { 1155 if ( nHeadNoneTail < 0 ) 1156 { 1157 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal))) 1158 aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart ); 1159 1160 aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 ); 1161 } 1162 else 1163 aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits ); 1164 } 1165 else 1166 { 1167 //! Zahlformat je nach Index holen? 1168 Color* pColor; 1169 sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 ); 1170 pDocument->GetFormatTable()-> 1171 GetOutputString( nStart, nNumFmt, aValue, &pColor ); 1172 } 1173 } 1174 } 1175 else 1176 { 1177 DBG_ERROR("GetAutoFillPreview: falscher Modus"); 1178 } 1179 } 1180 1181 return aValue; 1182 } 1183 1184 void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd) 1185 { 1186 if (eCmd == FILL_DAY) 1187 { 1188 rVal += nStep; 1189 return; 1190 } 1191 1192 // class Date Grenzen 1193 const sal_uInt16 nMinYear = 1583; 1194 const sal_uInt16 nMaxYear = 9956; 1195 1196 long nInc = (long) nStep; // nach oben/unten begrenzen ? 1197 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate(); 1198 Date aDate = aNullDate; 1199 aDate += (long)rVal; 1200 switch (eCmd) 1201 { 1202 case FILL_WEEKDAY: 1203 { 1204 aDate += nInc; 1205 DayOfWeek eWeekDay = aDate.GetDayOfWeek(); 1206 if (nInc >= 0) 1207 { 1208 if (eWeekDay == SATURDAY) 1209 aDate += 2; 1210 else if (eWeekDay == SUNDAY) 1211 aDate += 1; 1212 } 1213 else 1214 { 1215 if (eWeekDay == SATURDAY) 1216 aDate -= 1; 1217 else if (eWeekDay == SUNDAY) 1218 aDate -= 2; 1219 } 1220 } 1221 break; 1222 case FILL_MONTH: 1223 { 1224 if ( nDayOfMonth == 0 ) 1225 nDayOfMonth = aDate.GetDay(); // init 1226 long nMonth = aDate.GetMonth(); 1227 long nYear = aDate.GetYear(); 1228 1229 nMonth += nInc; 1230 1231 if (nInc >= 0) 1232 { 1233 if (nMonth > 12) 1234 { 1235 long nYAdd = (nMonth-1) / 12; 1236 nMonth -= nYAdd * 12; 1237 nYear += nYAdd; 1238 } 1239 } 1240 else 1241 { 1242 if (nMonth < 1) 1243 { 1244 long nYAdd = 1 - nMonth / 12; // positiv 1245 nMonth += nYAdd * 12; 1246 nYear -= nYAdd; 1247 } 1248 } 1249 1250 if ( nYear < nMinYear ) 1251 aDate = Date( 1,1, nMinYear ); 1252 else if ( nYear > nMaxYear ) 1253 aDate = Date( 31,12, nMaxYear ); 1254 else 1255 { 1256 aDate.SetMonth((sal_uInt16) nMonth); 1257 aDate.SetYear((sal_uInt16) nYear); 1258 if ( nDayOfMonth > 28 ) 1259 aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) ); 1260 } 1261 } 1262 break; 1263 case FILL_YEAR: 1264 { 1265 long nYear = aDate.GetYear(); 1266 nYear += nInc; 1267 if ( nYear < nMinYear ) 1268 aDate = Date( 1,1, nMinYear ); 1269 else if ( nYear > nMaxYear ) 1270 aDate = Date( 31,12, nMaxYear ); 1271 else 1272 aDate.SetYear((sal_uInt16) nYear); 1273 } 1274 break; 1275 default: 1276 { 1277 // added to avoid warnings 1278 } 1279 } 1280 1281 rVal = aDate - aNullDate; 1282 } 1283 1284 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 1285 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, 1286 double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits, 1287 sal_Bool bAttribs, ScProgress& rProgress ) 1288 { 1289 // 1290 // Richtung auswerten 1291 // 1292 1293 sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP); 1294 sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT); 1295 1296 sal_uLong nCol = 0; 1297 sal_uLong nRow = 0; 1298 sal_uLong& rInner = bVertical ? nRow : nCol; // Schleifenvariablen 1299 sal_uLong& rOuter = bVertical ? nCol : nRow; 1300 sal_uLong nOStart; 1301 sal_uLong nOEnd; 1302 sal_uLong nIStart; 1303 sal_uLong nIEnd; 1304 sal_uLong nISource; 1305 1306 if (bVertical) 1307 { 1308 nFillCount += (nRow2 - nRow1); 1309 if (nFillCount == 0) 1310 return; 1311 nOStart = nCol1; 1312 nOEnd = nCol2; 1313 if (bPositive) 1314 { 1315 nISource = nRow1; 1316 nIStart = nRow1 + 1; 1317 nIEnd = nRow1 + nFillCount; 1318 } 1319 else 1320 { 1321 nISource = nRow2; 1322 nIStart = nRow2 - 1; 1323 nIEnd = nRow2 - nFillCount; 1324 } 1325 } 1326 else 1327 { 1328 nFillCount += (nCol2 - nCol1); 1329 if (nFillCount == 0) 1330 return; 1331 nOStart = nRow1; 1332 nOEnd = nRow2; 1333 if (bPositive) 1334 { 1335 nISource = nCol1; 1336 nIStart = nCol1 + 1; 1337 nIEnd = nCol1 + nFillCount; 1338 } 1339 else 1340 { 1341 nISource = nCol2; 1342 nIStart = nCol2 - 1; 1343 nIEnd = nCol2 - nFillCount; 1344 } 1345 } 1346 1347 sal_uLong nIMin = nIStart; 1348 sal_uLong nIMax = nIEnd; 1349 PutInOrder(nIMin,nIMax); 1350 sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS); 1351 if (bVertical) 1352 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel); 1353 else 1354 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel); 1355 1356 sal_uLong nProgress = rProgress.GetState(); 1357 1358 // 1359 // ausfuehren 1360 // 1361 1362 sal_uLong nActFormCnt = 0; 1363 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++) 1364 { 1365 sal_Bool bFirst = sal_True; 1366 rInner = nISource; 1367 ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow)); 1368 1369 if (bVertical && bAttribs) 1370 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount ); 1371 1372 if (bAttribs) 1373 { 1374 const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow)); 1375 if (bVertical) 1376 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin), 1377 static_cast<SCROW>(nIMax), *pSrcPattern, sal_True ); 1378 else 1379 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++) 1380 aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, sal_True); 1381 } 1382 1383 if (pSrcCell) 1384 { 1385 CellType eCellType = pSrcCell->GetCellType(); 1386 1387 if (eFillCmd == FILL_SIMPLE) // kopieren 1388 { 1389 if (eCellType == CELLTYPE_FORMULA) 1390 { 1391 for (rInner = nIMin; rInner <= nIMax; rInner++) 1392 { 1393 sal_uLong nInd = nActFormCnt; 1394 FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell, 1395 static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) ); 1396 bFirst = sal_False; 1397 rProgress.SetStateOnPercent( ++nProgress ); 1398 } 1399 } 1400 else if (eCellType != CELLTYPE_NOTE) 1401 { 1402 for (rInner = nIMin; rInner <= nIMax; rInner++) 1403 { 1404 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); 1405 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) ); 1406 } 1407 nProgress += nIMax - nIMin + 1; 1408 rProgress.SetStateOnPercent( nProgress ); 1409 } 1410 } 1411 else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA) 1412 { 1413 double nStartVal; 1414 if (eCellType == CELLTYPE_VALUE) 1415 nStartVal = ((ScValueCell*)pSrcCell)->GetValue(); 1416 else 1417 nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue(); 1418 double nVal = nStartVal; 1419 long nIndex = 0; 1420 1421 sal_Bool bError = sal_False; 1422 sal_Bool bOverflow = sal_False; 1423 1424 sal_uInt16 nDayOfMonth = 0; 1425 rInner = nIStart; 1426 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes 1427 { 1428 if (!bError && !bOverflow) 1429 { 1430 switch (eFillCmd) 1431 { 1432 case FILL_LINEAR: 1433 { 1434 // #86365# use multiplication instead of repeated addition 1435 // to avoid accumulating rounding errors 1436 nVal = nStartVal; 1437 double nAdd = nStepValue; 1438 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) || 1439 !SubTotal::SafePlus( nVal, nAdd ) ) 1440 bError = sal_True; 1441 } 1442 break; 1443 case FILL_GROWTH: 1444 if (!SubTotal::SafeMult(nVal, nStepValue)) 1445 bError = sal_True; 1446 break; 1447 case FILL_DATE: 1448 if (fabs(nVal) > _D_MAX_LONG_) 1449 bError = sal_True; 1450 else 1451 IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd); 1452 break; 1453 default: 1454 { 1455 // added to avoid warnings 1456 } 1457 } 1458 1459 if (nStepValue >= 0) 1460 { 1461 if (nVal > nMaxValue) // Zielwert erreicht? 1462 { 1463 nVal = nMaxValue; 1464 bOverflow = sal_True; 1465 } 1466 } 1467 else 1468 { 1469 if (nVal < nMaxValue) 1470 { 1471 nVal = nMaxValue; 1472 bOverflow = sal_True; 1473 } 1474 } 1475 } 1476 1477 if (bError) 1478 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue); 1479 else if (!bOverflow) 1480 aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal); 1481 1482 if (rInner == nIEnd) break; 1483 if (bPositive) ++rInner; else --rInner; 1484 } 1485 nProgress += nIMax - nIMin + 1; 1486 rProgress.SetStateOnPercent( nProgress ); 1487 } 1488 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) 1489 { 1490 if ( nStepValue >= 0 ) 1491 { 1492 if ( nMaxValue >= (double)LONG_MAX ) 1493 nMaxValue = (double)LONG_MAX - 1; 1494 } 1495 else 1496 { 1497 if ( nMaxValue <= (double)LONG_MIN ) 1498 nMaxValue = (double)LONG_MIN + 1; 1499 } 1500 String aValue; 1501 if (eCellType == CELLTYPE_STRING) 1502 ((ScStringCell*)pSrcCell)->GetString( aValue ); 1503 else 1504 ((ScEditCell*)pSrcCell)->GetString( aValue ); 1505 sal_Int32 nStringValue; 1506 sal_uInt16 nMinDigits = nArgMinDigits; 1507 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits ); 1508 if ( nHeadNoneTail ) 1509 { 1510 double nStartVal = (double)nStringValue; 1511 double nVal = nStartVal; 1512 long nIndex = 0; 1513 sal_Bool bError = sal_False; 1514 sal_Bool bOverflow = sal_False; 1515 1516 sal_Bool bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix( 1517 (sal_Int32)nStartVal)); 1518 1519 rInner = nIStart; 1520 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes 1521 { 1522 if (!bError && !bOverflow) 1523 { 1524 switch (eFillCmd) 1525 { 1526 case FILL_LINEAR: 1527 { 1528 // #86365# use multiplication instead of repeated addition 1529 // to avoid accumulating rounding errors 1530 nVal = nStartVal; 1531 double nAdd = nStepValue; 1532 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) || 1533 !SubTotal::SafePlus( nVal, nAdd ) ) 1534 bError = sal_True; 1535 } 1536 break; 1537 case FILL_GROWTH: 1538 if (!SubTotal::SafeMult(nVal, nStepValue)) 1539 bError = sal_True; 1540 break; 1541 default: 1542 { 1543 // added to avoid warnings 1544 } 1545 } 1546 1547 if (nStepValue >= 0) 1548 { 1549 if (nVal > nMaxValue) // Zielwert erreicht? 1550 { 1551 nVal = nMaxValue; 1552 bOverflow = sal_True; 1553 } 1554 } 1555 else 1556 { 1557 if (nVal < nMaxValue) 1558 { 1559 nVal = nMaxValue; 1560 bOverflow = sal_True; 1561 } 1562 } 1563 } 1564 1565 if (bError) 1566 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue); 1567 else if (!bOverflow) 1568 { 1569 nStringValue = (sal_Int32)nVal; 1570 String aStr; 1571 if ( nHeadNoneTail < 0 ) 1572 { 1573 aCol[nCol].Insert( static_cast<SCROW>(nRow), 1574 lcl_getSuffixCell( pDocument, 1575 nStringValue, nMinDigits, aValue, 1576 eCellType, bIsOrdinalSuffix )); 1577 } 1578 else 1579 { 1580 aStr = aValue; 1581 aStr += lcl_ValueString( nStringValue, nMinDigits ); 1582 ScStringCell* pCell = new ScStringCell( aStr ); 1583 aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell ); 1584 } 1585 } 1586 1587 if (rInner == nIEnd) break; 1588 if (bPositive) ++rInner; else --rInner; 1589 } 1590 } 1591 nProgress += nIMax - nIMin + 1; 1592 rProgress.SetStateOnPercent( nProgress ); 1593 } 1594 } 1595 else 1596 { 1597 nProgress += nIMax - nIMin + 1; 1598 rProgress.SetStateOnPercent( nProgress ); 1599 } 1600 ++nActFormCnt; 1601 } 1602 } 1603 1604 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, 1605 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, 1606 double nStepValue, double nMaxValue) 1607 { 1608 sal_uLong nProgCount; 1609 if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP) 1610 nProgCount = nCol2 - nCol1 + 1; 1611 else 1612 nProgCount = nRow2 - nRow1 + 1; 1613 nProgCount *= nFillCount; 1614 ScProgress aProgress( pDocument->GetDocumentShell(), 1615 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount ); 1616 1617 bSharedNameInserted = sal_False; 1618 1619 if (eFillCmd == FILL_AUTO) 1620 FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress); 1621 else 1622 FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, 1623 eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress); 1624 1625 if (bSharedNameInserted) // Wurde Shared-Name eingefuegt? 1626 pDocument->GetRangeName()->SetSharedMaxIndex( 1627 pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen 1628 } 1629 1630 1631 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1632 const ScPatternAttr& rAttr, sal_uInt16 nFormatNo) 1633 { 1634 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); 1635 if (pAutoFormat) 1636 { 1637 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo]; 1638 if (pData) 1639 { 1640 // ScPatternAttr aPattern(pDocument->GetPool()); 1641 // pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument); 1642 ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr); 1643 } 1644 } 1645 } 1646 1647 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, 1648 sal_uInt16 nFormatNo ) 1649 { 1650 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 1651 { 1652 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); 1653 if (pAutoFormat) 1654 { 1655 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo]; 1656 if (pData) 1657 { 1658 ScPatternAttr* pPatternAttrs[16]; 1659 for (sal_uInt8 i = 0; i < 16; ++i) 1660 { 1661 pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool()); 1662 pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument); 1663 } 1664 1665 SCCOL nCol = nStartCol; 1666 SCROW nRow = nStartRow; 1667 sal_uInt16 nIndex = 0; 1668 // Linke obere Ecke 1669 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1670 // Linke Spalte 1671 if (pData->IsEqualData(4, 8)) 1672 AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo); 1673 else 1674 { 1675 nIndex = 4; 1676 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++) 1677 { 1678 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1679 if (nIndex == 4) 1680 nIndex = 8; 1681 else 1682 nIndex = 4; 1683 } 1684 } 1685 // Linke untere Ecke 1686 nRow = nEndRow; 1687 nIndex = 12; 1688 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1689 // Rechte obere Ecke 1690 nCol = nEndCol; 1691 nRow = nStartRow; 1692 nIndex = 3; 1693 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1694 // Rechte Spalte 1695 if (pData->IsEqualData(7, 11)) 1696 AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo); 1697 else 1698 { 1699 nIndex = 7; 1700 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++) 1701 { 1702 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1703 if (nIndex == 7) 1704 nIndex = 11; 1705 else 1706 nIndex = 7; 1707 } 1708 } 1709 // Rechte untere Ecke 1710 nRow = nEndRow; 1711 nIndex = 15; 1712 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1713 nRow = nStartRow; 1714 nIndex = 1; 1715 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) 1716 { 1717 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1718 if (nIndex == 1) 1719 nIndex = 2; 1720 else 1721 nIndex = 1; 1722 } 1723 // Untere Zeile 1724 nRow = nEndRow; 1725 nIndex = 13; 1726 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) 1727 { 1728 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1729 if (nIndex == 13) 1730 nIndex = 14; 1731 else 1732 nIndex = 13; 1733 } 1734 // Boddy 1735 if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9))) 1736 AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo); 1737 else 1738 { 1739 if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10))) 1740 { 1741 nIndex = 5; 1742 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) 1743 { 1744 AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo); 1745 if (nIndex == 5) 1746 nIndex = 6; 1747 else 1748 nIndex = 5; 1749 } 1750 } 1751 else 1752 { 1753 nIndex = 5; 1754 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) 1755 { 1756 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++) 1757 { 1758 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); 1759 if ((nIndex == 5) || (nIndex == 9)) 1760 { 1761 if (nIndex == 5) 1762 nIndex = 9; 1763 else 1764 nIndex = 5; 1765 } 1766 else 1767 { 1768 if (nIndex == 6) 1769 nIndex = 10; 1770 else 1771 nIndex = 6; 1772 } 1773 } // for nRow 1774 if ((nIndex == 5) || (nIndex == 9)) 1775 nIndex = 6; 1776 else 1777 nIndex = 5; 1778 } // for nCol 1779 } // if not equal Column 1780 } // if not all equal 1781 1782 for (sal_uInt8 j = 0; j < 16; ++j) 1783 delete pPatternAttrs[j]; 1784 } // if AutoFormatData != NULL 1785 } // if AutoFormat != NULL 1786 } // if ValidColRow 1787 } 1788 1789 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData) 1790 { 1791 sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow ); 1792 ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() ); 1793 rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat ); 1794 } 1795 1796 #define LF_LEFT 1 1797 #define LF_TOP 2 1798 #define LF_RIGHT 4 1799 #define LF_BOTTOM 8 1800 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM) 1801 1802 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData) 1803 { 1804 const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER); 1805 const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER); 1806 const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER); 1807 const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER); 1808 const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER); 1809 1810 SvxBoxItem aBox( ATTR_BORDER ); 1811 if (nFlags & LF_LEFT) 1812 { 1813 if (pLeftBox) 1814 { 1815 if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight())) 1816 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT); 1817 else 1818 aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT); 1819 } 1820 else 1821 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT); 1822 } 1823 if (nFlags & LF_TOP) 1824 { 1825 if (pTopBox) 1826 { 1827 if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom())) 1828 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP); 1829 else 1830 aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP); 1831 } 1832 else 1833 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP); 1834 } 1835 if (nFlags & LF_RIGHT) 1836 { 1837 if (pRightBox) 1838 { 1839 if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft())) 1840 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT); 1841 else 1842 aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT); 1843 } 1844 else 1845 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT); 1846 } 1847 if (nFlags & LF_BOTTOM) 1848 { 1849 if (pBottomBox) 1850 { 1851 if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop())) 1852 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM); 1853 else 1854 aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM); 1855 } 1856 else 1857 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM); 1858 } 1859 rData.PutItem( nIndex, aBox ); 1860 } 1861 1862 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData) 1863 { 1864 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) 1865 { 1866 if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3)) 1867 { 1868 // Linke obere Ecke 1869 GetAutoFormatAttr(nStartCol, nStartRow, 0, rData); 1870 GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData); 1871 // Linke Spalte 1872 GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData); 1873 GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData); 1874 GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData); 1875 if (nEndRow - nStartRow >= 4) 1876 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData); 1877 else 1878 rData.CopyItem( 8, 4, ATTR_BORDER ); 1879 // Linke untere Ecke 1880 GetAutoFormatAttr(nStartCol, nEndRow, 12, rData); 1881 GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData); 1882 // Rechte obere Ecke 1883 GetAutoFormatAttr(nEndCol, nStartRow, 3, rData); 1884 GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData); 1885 // Rechte Spalte 1886 GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData); 1887 GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData); 1888 GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData); 1889 if (nEndRow - nStartRow >= 4) 1890 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData); 1891 else 1892 rData.CopyItem( 11, 7, ATTR_BORDER ); 1893 // Rechte untere Ecke 1894 GetAutoFormatAttr(nEndCol, nEndRow, 15, rData); 1895 GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData); 1896 // Ober Zeile 1897 GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData); 1898 GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData); 1899 GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData); 1900 if (nEndCol - nStartCol >= 4) 1901 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData); 1902 else 1903 rData.CopyItem( 2, 1, ATTR_BORDER ); 1904 // Untere Zeile 1905 GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData); 1906 GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData); 1907 GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData); 1908 if (nEndCol - nStartCol >= 4) 1909 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData); 1910 else 1911 rData.CopyItem( 14, 13, ATTR_BORDER ); 1912 // Body 1913 GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData); 1914 GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData); 1915 GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData); 1916 GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData); 1917 GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData); 1918 if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4)) 1919 { 1920 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData); 1921 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData); 1922 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData); 1923 } 1924 else 1925 { 1926 rData.CopyItem( 6, 5, ATTR_BORDER ); 1927 rData.CopyItem( 9, 5, ATTR_BORDER ); 1928 rData.CopyItem( 10, 5, ATTR_BORDER ); 1929 } 1930 } 1931 } 1932 } 1933 1934 void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError) 1935 { 1936 if (ValidColRow(nCol, nRow)) 1937 aCol[nCol].SetError( nRow, nError ); 1938 } 1939 1940 void ScTable::UpdateInsertTabAbs(SCTAB nTable) 1941 { 1942 for (SCCOL i=0; i <= MAXCOL; i++) 1943 aCol[i].UpdateInsertTabAbs(nTable); 1944 } 1945 1946 //UNUSED2008-05 sal_uInt16 ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const 1947 //UNUSED2008-05 { 1948 //UNUSED2008-05 if (ValidColRow(nCol,nRow)) 1949 //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow ); 1950 //UNUSED2008-05 else 1951 //UNUSED2008-05 return 0; 1952 //UNUSED2008-05 } 1953 1954 sal_Bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, sal_Bool bInSel, 1955 const ScMarkData& rMark) const 1956 { 1957 if (rRow == MAXROW+2) // Tabellenende 1958 { 1959 rRow = 0; 1960 rCol = 0; 1961 } 1962 else 1963 { 1964 rRow++; 1965 if (rRow == MAXROW+1) 1966 { 1967 rCol++; 1968 rRow = 0; 1969 } 1970 } 1971 if (rCol == MAXCOL+1) 1972 return sal_True; 1973 else 1974 { 1975 sal_Bool bStop = sal_False; 1976 while (!bStop) 1977 { 1978 if (ValidCol(rCol)) 1979 { 1980 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark); 1981 if (bStop) 1982 return sal_True; 1983 else /*if (rRow == MAXROW+1) */ 1984 { 1985 rCol++; 1986 rRow = 0; 1987 } 1988 } 1989 else 1990 return sal_True; 1991 } 1992 } 1993 return sal_False; 1994 } 1995 1996 void ScTable::RemoveAutoSpellObj() 1997 { 1998 for (SCCOL i=0; i <= MAXCOL; i++) 1999 aCol[i].RemoveAutoSpellObj(); 2000 } 2001 2002 sal_Bool ScTable::TestTabRefAbs(SCTAB nTable) 2003 { 2004 sal_Bool bRet = sal_False; 2005 for (SCCOL i=0; i <= MAXCOL; i++) 2006 if (aCol[i].TestTabRefAbs(nTable)) 2007 bRet = sal_True; 2008 return bRet; 2009 } 2010 2011 void ScTable::CompileDBFormula() 2012 { 2013 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula(); 2014 } 2015 2016 void ScTable::CompileDBFormula( sal_Bool bCreateFormulaString ) 2017 { 2018 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString ); 2019 } 2020 2021 void ScTable::CompileNameFormula( sal_Bool bCreateFormulaString ) 2022 { 2023 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString ); 2024 } 2025 2026 void ScTable::CompileColRowNameFormula() 2027 { 2028 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula(); 2029 } 2030 2031 2032 2033 2034 2035 2036