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