Update ooo320-m1
[ooovba.git] / sc / source / core / data / table4.cxx
blobe58af5d4558185875685ce20ed66b316b9abc1a1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: table4.cxx,v $
10 * $Revision: 1.23.126.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // System - Includes -----------------------------------------------------
38 #ifdef _MSC_VER
39 #pragma optimize("",off)
40 // sonst Absturz Win beim Fuellen
41 #endif
43 // INCLUDE ---------------------------------------------------------------
45 #include "scitems.hxx"
46 #include <svx/algitem.hxx>
47 #include <svx/boxitem.hxx>
48 #include <svx/brshitem.hxx>
49 #include <svx/cntritem.hxx>
50 #include <svx/colritem.hxx>
51 #include <svx/crsditem.hxx>
52 #include <svx/fhgtitem.hxx>
53 #include <svx/fontitem.hxx>
54 #include <svx/langitem.hxx>
55 #include <svx/postitem.hxx>
56 #include <svx/shdditem.hxx>
57 #include <svx/udlnitem.hxx>
58 #include <svx/wghtitem.hxx>
59 #include <svx/rotmodit.hxx>
60 #include <svx/editobj.hxx>
61 #include <svx/editeng.hxx>
62 #include <svx/eeitem.hxx>
63 #include <svx/escpitem.hxx>
64 #include <svtools/zforlist.hxx>
65 #include <vcl/keycodes.hxx>
66 #include <rtl/math.hxx>
67 #include <unotools/charclass.hxx>
69 #include "attrib.hxx"
70 #include "patattr.hxx"
71 #include "cell.hxx"
72 #include "table.hxx"
73 #include "globstr.hrc"
74 #include "global.hxx"
75 #include "document.hxx"
76 #include "autoform.hxx"
77 #include "userlist.hxx"
78 #include "zforauto.hxx"
79 #include "subtotal.hxx"
80 #include "formula/errorcodes.hxx"
81 #include "rangenam.hxx"
82 #include "docpool.hxx"
83 #include "progress.hxx"
85 #include <math.h>
87 // STATIC DATA -----------------------------------------------------------
89 #define _D_MAX_LONG_ (double) 0x7fffffff
91 extern USHORT nScFillModeMouseModifier; // global.cxx
93 // -----------------------------------------------------------------------
95 short lcl_DecompValueString( String& aValue, sal_Int32& nVal, USHORT* pMinDigits = NULL )
97 if ( !aValue.Len() )
99 nVal = 0;
100 return 0;
102 const sal_Unicode* p = aValue.GetBuffer();
103 xub_StrLen nNeg = 0;
104 xub_StrLen nNum = 0;
105 if ( p[nNum] == '-' )
106 nNum = nNeg = 1;
107 while ( p[nNum] && CharClass::isAsciiNumeric( p[nNum] ) )
108 nNum++;
110 sal_Unicode cNext = p[nNum]; // 0 if at the end
111 sal_Unicode cLast = p[aValue.Len()-1];
113 // #i5550# If there are numbers at the beginning and the end,
114 // prefer the one at the beginning only if it's followed by a space.
115 // Otherwise, use the number at the end, to enable things like IP addresses.
116 if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(cLast) ) )
117 { // number at the beginning
118 nVal = aValue.Copy( 0, nNum ).ToInt32();
119 // #60893# any number with a leading zero sets the minimum number of digits
120 if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
121 *pMinDigits = nNum - nNeg;
122 aValue.Erase( 0, nNum );
123 return -1;
125 else
127 nNeg = 0;
128 xub_StrLen nEnd = nNum = aValue.Len() - 1;
129 while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) )
130 nNum--;
131 if ( p[nNum] == '-' )
133 nNum--;
134 nNeg = 1;
136 if ( nNum < nEnd - nNeg )
137 { // number at the end
138 nVal = aValue.Copy( nNum + 1 ).ToInt32();
139 // #60893# any number with a leading zero sets the minimum number of digits
140 if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
141 *pMinDigits = nEnd - nNum - nNeg;
142 aValue.Erase( nNum + 1 );
143 return 1;
146 nVal = 0;
147 return 0;
150 String lcl_ValueString( sal_Int32 nValue, USHORT nMinDigits )
152 if ( nMinDigits <= 1 )
153 return String::CreateFromInt32( nValue ); // simple case...
154 else
156 String aStr = String::CreateFromInt32( Abs( nValue ) );
157 if ( aStr.Len() < nMinDigits )
159 String aZero;
160 aZero.Fill( nMinDigits - aStr.Len(), '0' );
161 aStr.Insert( aZero, 0 );
163 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
164 if ( nValue < 0 )
165 aStr.Insert( '-', 0 );
166 return aStr;
170 static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue,
171 USHORT nDigits, const String& rSuffix, CellType eCellType,
172 BOOL bIsOrdinalSuffix )
174 String aValue( lcl_ValueString( nValue, nDigits ));
175 if (!bIsOrdinalSuffix)
176 return new ScStringCell( aValue += rSuffix);
178 String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue));
179 if (eCellType != CELLTYPE_EDIT)
180 return new ScStringCell( aValue += aOrdinalSuffix);
182 EditEngine aEngine( pDocument->GetEnginePool() );
183 SfxItemSet aAttr = aEngine.GetEmptyItemSet();
184 aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
185 aEngine.SetText( aValue );
186 aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0,
187 aValue.Len() + aOrdinalSuffix.Len()));
188 aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() +
189 aOrdinalSuffix.Len()));
190 return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL );
193 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
194 FillCmd& rCmd, FillDateCmd& rDateCmd,
195 double& rInc, USHORT& rMinDigits,
196 ScUserListData*& rListData, USHORT& rListIndex)
198 DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" );
200 rInc = 0.0;
201 rMinDigits = 0;
202 rListData = NULL;
203 rCmd = FILL_SIMPLE;
204 if ( nScFillModeMouseModifier & KEY_MOD1 )
205 return ; // Ctrl-Taste: Copy
207 SCCOL nAddX;
208 SCROW nAddY;
209 SCSIZE nCount;
210 if (nCol1 == nCol2)
212 nAddX = 0;
213 nAddY = 1;
214 nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
216 else
218 nAddX = 1;
219 nAddY = 0;
220 nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
223 SCCOL nCol = nCol1;
224 SCROW nRow = nRow1;
226 ScBaseCell* pFirstCell = GetCell( nCol, nRow );
227 CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE;
229 if (eCellType == CELLTYPE_VALUE)
231 UINT32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
232 BOOL bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
233 if (bDate)
235 if (nCount > 1)
237 long nCmpInc = 0;
238 double nVal;
239 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
240 Date aDate1 = aNullDate;
241 nVal = ((ScValueCell*)pFirstCell)->GetValue();
242 aDate1 += (long)nVal;
243 Date aDate2 = aNullDate;
244 nVal = GetValue(nCol+nAddX, nRow+nAddY);
245 aDate2 += (long)nVal;
246 if ( aDate1 != aDate2 )
248 FillDateCmd eType;
249 long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
250 long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
251 long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
252 if ( nDDiff )
254 eType = FILL_DAY;
255 nCmpInc = aDate2 - aDate1;
257 else
259 eType = FILL_MONTH;
260 nCmpInc = nMDiff + 12 * nYDiff;
263 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
264 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
265 BOOL bVal = TRUE;
266 for (USHORT i=1; i<nCount && bVal; i++)
268 ScBaseCell* pCell = GetCell(nCol,nRow);
269 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
271 nVal = ((ScValueCell*)pCell)->GetValue();
272 aDate2 = aNullDate + (long) nVal;
273 if ( eType == FILL_DAY )
275 if ( aDate2-aDate1 != nCmpInc )
276 bVal = FALSE;
278 else
280 nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
281 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
282 nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
283 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
284 bVal = FALSE;
286 aDate1 = aDate2;
287 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
288 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
290 else
291 bVal = FALSE; // #50965# kein Datum passt auch nicht
293 if (bVal)
295 if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
297 eType = FILL_YEAR;
298 nCmpInc /= 12;
300 rCmd = FILL_DATE;
301 rDateCmd = eType;
302 rInc = nCmpInc;
306 else // einzelnes Datum -> Tage hochzaehlen
308 rCmd = FILL_DATE;
309 rDateCmd = FILL_DAY;
310 rInc = 1.0;
313 else
315 if (nCount > 1)
317 double nVal1 = ((ScValueCell*)pFirstCell)->GetValue();
318 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
319 rInc = nVal2 - nVal1;
320 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
321 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
322 BOOL bVal = TRUE;
323 for (USHORT i=1; i<nCount && bVal; i++)
325 ScBaseCell* pCell = GetCell(nCol,nRow);
326 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
328 nVal2 = ((ScValueCell*)pCell)->GetValue();
329 double nDiff = nVal2 - nVal1;
330 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
331 bVal = FALSE;
332 nVal1 = nVal2;
334 else
335 bVal = FALSE;
336 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
337 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
339 if (bVal)
340 rCmd = FILL_LINEAR;
344 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
346 String aStr;
347 GetString(nCol, nRow, aStr);
348 rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
349 if (rListData)
351 rListData->GetSubIndex(aStr, rListIndex);
352 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
353 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
354 for (USHORT i=1; i<nCount && rListData; i++)
356 GetString(nCol, nRow, aStr);
357 if (!rListData->GetSubIndex(aStr, rListIndex))
358 rListData = NULL;
359 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
360 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
363 else if ( nCount > 1 )
365 // pass rMinDigits to all DecompValueString calls
366 // -> longest number defines rMinDigits
368 sal_Int32 nVal1;
369 short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
370 if ( nFlag1 )
372 sal_Int32 nVal2;
373 GetString( nCol+nAddX, nRow+nAddY, aStr );
374 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
375 if ( nFlag1 == nFlag2 )
377 rInc = (double)nVal2 - (double)nVal1;
378 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
379 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
380 BOOL bVal = TRUE;
381 for (USHORT i=1; i<nCount && bVal; i++)
383 ScBaseCell* pCell = GetCell(nCol,nRow);
384 CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
385 if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
387 if ( eType == CELLTYPE_STRING )
388 ((ScStringCell*)pCell)->GetString( aStr );
389 else
390 ((ScEditCell*)pCell)->GetString( aStr );
391 nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
392 if ( nFlag1 == nFlag2 )
394 double nDiff = (double)nVal2 - (double)nVal1;
395 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
396 bVal = FALSE;
397 nVal1 = nVal2;
399 else
400 bVal = FALSE;
402 else
403 bVal = FALSE;
404 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
405 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
407 if (bVal)
408 rCmd = FILL_LINEAR;
412 else
414 // call DecompValueString to set rMinDigits
415 sal_Int32 nDummy;
416 lcl_DecompValueString( aStr, nDummy, &rMinDigits );
421 void ScTable::FillFormula(ULONG& /* nFormulaCounter */, BOOL /* bFirst */, ScFormulaCell* pSrcCell,
422 SCCOL nDestCol, SCROW nDestRow, BOOL bLast )
424 /* USHORT nTokArrLen = pSrcCell->GetTokenArrayLen();
425 if ( nTokArrLen > 15 ) // mehr als =A1 oder =67
427 ScRangeName* pRangeName = pDocument->GetRangeName();
428 String aName("___SC_"); // Wird dieser String veraendert,
429 // auch in document2 EraseNonUsed...
430 // mitaendern!!
431 aName += pRangeName->GetSharedMaxIndex() + 1;
432 aName += '_';
433 aName += nFormulaCounter;
434 nFormulaCounter++;
435 if (bFirst)
437 ScRangeData *pAktRange = new ScRangeData(
438 pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
439 pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
440 if (!pRangeName->Insert( pAktRange ))
441 delete pAktRange;
442 else
443 bSharedNameInserted = TRUE;
445 USHORT nIndex;
446 pRangeName->SearchName(aName, nIndex);
447 if (!pRangeName)
449 DBG_ERROR("ScTable::FillFormula: Falscher Name");
450 return;
452 nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
453 ScTokenArray aArr;
454 aArr.AddName(nIndex);
455 aArr.AddOpCode(ocStop);
456 ScFormulaCell* pDestCell = new ScFormulaCell
457 (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
458 aCol[nDestCol].Insert(nDestRow, pDestCell);
460 else
461 */ {
462 pDocument->SetNoListening( TRUE ); // noch falsche Referenzen
463 ScAddress aAddr( nDestCol, nDestRow, nTab );
464 ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
465 aCol[nDestCol].Insert(nDestRow, pDestCell);
466 #if 0
467 // mit RelRefs unnoetig
468 pDestCell->UpdateReference(URM_COPY,
469 ScRange( aAddr, aAddr ),
470 nDestCol - pSrcCell->aPos.Col(),
471 nDestRow - pSrcCell->aPos.Row(), 0);
472 #endif
473 if ( bLast && pDestCell->GetMatrixFlag() )
475 ScAddress aOrg;
476 if ( pDestCell->GetMatrixOrigin( aOrg ) )
478 if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
480 ScBaseCell* pOrgCell = pDocument->GetCell( aOrg );
481 if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA
482 && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA )
484 ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
485 nDestCol - aOrg.Col() + 1,
486 nDestRow - aOrg.Row() + 1 );
488 else
490 DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
493 else
495 DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
498 else
500 DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
503 pDocument->SetNoListening( FALSE );
504 pDestCell->StartListeningTo( pDocument );
508 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
509 ULONG nFillCount, FillDir eFillDir, ScProgress& rProgress )
511 if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
512 return;
515 // Richtung auswerten
518 BOOL bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
519 BOOL bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
521 ULONG nCol = 0;
522 ULONG nRow = 0;
523 ULONG& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
524 ULONG& rOuter = bVertical ? nCol : nRow;
525 ULONG nOStart;
526 ULONG nOEnd;
527 ULONG nIStart;
528 ULONG nIEnd;
529 ULONG nISrcStart;
530 ULONG nISrcEnd;
532 if (bVertical)
534 nOStart = nCol1;
535 nOEnd = nCol2;
536 if (bPositive)
538 nISrcStart = nRow1;
539 nISrcEnd = nRow2;
540 nIStart = nRow2 + 1;
541 nIEnd = nRow2 + nFillCount;
543 else
545 nISrcStart = nRow2;
546 nISrcEnd = nRow1;
547 nIStart = nRow1 - 1;
548 nIEnd = nRow1 - nFillCount;
551 else
553 nOStart = nRow1;
554 nOEnd = nRow2;
555 if (bPositive)
557 nISrcStart = nCol1;
558 nISrcEnd = nCol2;
559 nIStart = nCol2 + 1;
560 nIEnd = nCol2 + nFillCount;
562 else
564 nISrcStart = nCol2;
565 nISrcEnd = nCol1;
566 nIStart = nCol1 - 1;
567 nIEnd = nCol1 - nFillCount;
570 ULONG nIMin = nIStart;
571 ULONG nIMax = nIEnd;
572 PutInOrder(nIMin,nIMax);
573 if (bVertical)
574 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
575 else
576 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
578 ULONG nProgress = rProgress.GetState();
581 // ausfuehren
584 ULONG nActFormCnt = 0;
585 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
587 ULONG nMaxFormCnt = 0; // fuer Formeln
589 // Attributierung uebertragen
591 const ScPatternAttr* pSrcPattern = NULL;
592 ULONG nAtSrc = nISrcStart;
593 ScPatternAttr* pNewPattern = NULL;
594 BOOL bGetPattern = TRUE;
595 rInner = nIStart;
596 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
598 const ScStyleSheet* pStyleSheet = NULL;
599 if ( bGetPattern )
601 if ( pNewPattern )
602 delete pNewPattern;
603 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
604 pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
605 else // rInner&:=nCol, rOuter&:=nRow
606 pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
607 bGetPattern = FALSE;
608 pStyleSheet = pSrcPattern->GetStyleSheet();
609 // Merge/Mergeflag nicht uebernehmen,
610 const SfxItemSet& rSet = pSrcPattern->GetItemSet();
611 if ( rSet.GetItemState(ATTR_MERGE, FALSE) == SFX_ITEM_SET
612 || rSet.GetItemState(ATTR_MERGE_FLAG, FALSE) == SFX_ITEM_SET )
614 pNewPattern = new ScPatternAttr( *pSrcPattern );
615 SfxItemSet& rNewSet = pNewPattern->GetItemSet();
616 rNewSet.ClearItem(ATTR_MERGE);
617 rNewSet.ClearItem(ATTR_MERGE_FLAG);
619 else
620 pNewPattern = NULL;
623 if ( bVertical && nISrcStart == nISrcEnd )
625 // Attribute komplett am Stueck setzen
626 if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
628 // Default steht schon da (DeleteArea)
629 SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd ));
630 SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd ));
631 if ( pStyleSheet )
632 aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
633 if ( pNewPattern )
634 aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
635 else
636 aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
638 break; // Schleife abbrechen
641 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
643 // Vorlage auch uebernehmen
644 //! am AttrArray mit ApplyPattern zusammenfassen ??
645 if ( pStyleSheet )
646 aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
648 // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
649 if ( pNewPattern )
650 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
651 else
652 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
655 if (nAtSrc==nISrcEnd)
657 if ( nAtSrc != nISrcStart )
658 { // mehr als eine Source-Zelle
659 nAtSrc = nISrcStart;
660 bGetPattern = TRUE;
663 else if (bPositive)
665 ++nAtSrc;
666 bGetPattern = TRUE;
668 else
670 --nAtSrc;
671 bGetPattern = TRUE;
674 if (rInner == nIEnd) break;
675 if (bPositive) ++rInner; else --rInner;
677 if ( pNewPattern )
678 delete pNewPattern;
680 // Analyse
682 FillCmd eFillCmd;
683 FillDateCmd eDateCmd;
684 double nInc;
685 USHORT nMinDigits;
686 ScUserListData* pListData = NULL;
687 USHORT nListIndex;
688 if (bVertical)
689 FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
690 static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
691 nInc,nMinDigits, pListData,nListIndex);
692 else
693 FillAnalyse(nCol1,static_cast<SCROW>(nRow),
694 nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
695 nInc,nMinDigits, pListData,nListIndex);
697 if (bVertical)
698 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
700 if (pListData)
702 USHORT nListCount = pListData->GetSubCount();
703 if ( !bPositive )
705 // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
706 ULONG nSub = nISrcStart - nISrcEnd;
707 for (ULONG i=0; i<nSub; i++)
709 if (nListIndex == 0) nListIndex = nListCount;
710 --nListIndex;
714 rInner = nIStart;
715 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
717 if (bPositive)
719 ++nListIndex;
720 if (nListIndex >= nListCount) nListIndex = 0;
722 else
724 if (nListIndex == 0) nListIndex = nListCount;
725 --nListIndex;
727 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex)));
729 if (rInner == nIEnd) break;
730 if (bPositive) ++rInner; else --rInner;
732 nProgress += nIMax - nIMin + 1;
733 rProgress.SetStateOnPercent( nProgress );
735 else if (eFillCmd == FILL_SIMPLE) // Auffuellen mit Muster
737 ULONG nSource = nISrcStart;
738 double nDelta;
739 if ( nScFillModeMouseModifier & KEY_MOD1 )
740 nDelta = 0.0;
741 else if ( bPositive )
742 nDelta = 1.0;
743 else
744 nDelta = -1.0;
745 double nVal = 0.0;
746 ULONG nFormulaCounter = nActFormCnt;
747 BOOL bFirst = TRUE;
748 BOOL bGetCell = TRUE;
749 USHORT nCellDigits = 0;
750 short nHeadNoneTail = 0;
751 sal_Int32 nStringValue = 0;
752 String aValue;
753 ScBaseCell* pSrcCell = NULL;
754 CellType eCellType = CELLTYPE_NONE;
755 BOOL bIsOrdinalSuffix = FALSE;
757 rInner = nIStart;
758 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
760 if ( bGetCell )
762 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
763 pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) );
764 else // rInner&:=nCol, rOuter&:=nRow
765 pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) );
766 bGetCell = FALSE;
767 if ( pSrcCell )
769 eCellType = pSrcCell->GetCellType();
770 switch ( eCellType )
772 case CELLTYPE_VALUE:
773 nVal = ((ScValueCell*)pSrcCell)->GetValue();
774 break;
775 case CELLTYPE_STRING:
776 case CELLTYPE_EDIT:
777 if ( eCellType == CELLTYPE_STRING )
778 ((ScStringCell*)pSrcCell)->GetString( aValue );
779 else
780 ((ScEditCell*)pSrcCell)->GetString( aValue );
781 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
783 nCellDigits = 0; // look at each source cell individually
784 nHeadNoneTail = lcl_DecompValueString(
785 aValue, nStringValue, &nCellDigits );
787 bIsOrdinalSuffix = aValue.Equals(
788 ScGlobal::GetOrdinalSuffix( nStringValue));
790 break;
791 default:
793 // added to avoid warnings
797 else
798 eCellType = CELLTYPE_NONE;
800 switch (eCellType)
802 case CELLTYPE_VALUE:
803 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
804 break;
805 case CELLTYPE_STRING:
806 case CELLTYPE_EDIT:
807 if ( nHeadNoneTail )
809 // #i48009# with the "nStringValue+(long)nDelta" expression within the
810 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
811 // so nNextValue is now calculated ahead.
812 sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
814 String aStr;
815 if ( nHeadNoneTail < 0 )
817 aCol[nCol].Insert( static_cast<SCROW>(nRow),
818 lcl_getSuffixCell( pDocument,
819 nNextValue, nCellDigits, aValue,
820 eCellType, bIsOrdinalSuffix));
822 else
824 aStr = aValue;
825 aStr += lcl_ValueString( nNextValue, nCellDigits );
826 aCol[nCol].Insert( static_cast<SCROW>(nRow),
827 new ScStringCell( aStr));
830 else
832 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
833 switch ( eCellType )
835 case CELLTYPE_STRING:
836 case CELLTYPE_EDIT:
837 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
838 break;
839 default:
841 // added to avoid warnings
845 break;
846 case CELLTYPE_FORMULA :
847 FillFormula( nFormulaCounter, bFirst,
848 (ScFormulaCell*) pSrcCell,
849 static_cast<SCCOL>(nCol),
850 static_cast<SCROW>(nRow), (rInner == nIEnd) );
851 if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
852 nMaxFormCnt = nFormulaCounter - nActFormCnt;
853 break;
854 default:
856 // added to avoid warnings
860 if (nSource==nISrcEnd)
862 if ( nSource != nISrcStart )
863 { // mehr als eine Source-Zelle
864 nSource = nISrcStart;
865 bGetCell = TRUE;
867 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
869 if ( bPositive )
870 nDelta += 1.0;
871 else
872 nDelta -= 1.0;
874 nFormulaCounter = nActFormCnt;
875 bFirst = FALSE;
877 else if (bPositive)
879 ++nSource;
880 bGetCell = TRUE;
882 else
884 --nSource;
885 bGetCell = TRUE;
888 // Progress in der inneren Schleife nur bei teuren Zellen,
889 // und auch dann nicht fuer jede einzelne
891 ++nProgress;
892 if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
893 rProgress.SetStateOnPercent( nProgress );
895 if (rInner == nIEnd) break;
896 if (bPositive) ++rInner; else --rInner;
898 rProgress.SetStateOnPercent( nProgress );
900 else
902 if (!bPositive)
903 nInc = -nInc;
904 double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
905 if (bVertical)
906 FillSeries( static_cast<SCCOL>(nCol), nRow1,
907 static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
908 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, FALSE,
909 rProgress );
910 else
911 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
912 static_cast<SCROW>(nRow), nFillCount, eFillDir,
913 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, FALSE,
914 rProgress );
915 nProgress = rProgress.GetState();
918 nActFormCnt += nMaxFormCnt;
922 String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
924 String aValue;
926 SCCOL nCol1 = rSource.aStart.Col();
927 SCROW nRow1 = rSource.aStart.Row();
928 SCCOL nCol2 = rSource.aEnd.Col();
929 SCROW nRow2 = rSource.aEnd.Row();
930 BOOL bOk = TRUE;
931 long nIndex = 0;
932 ULONG nSrcCount = 0;
933 FillDir eFillDir = FILL_TO_BOTTOM;
934 if ( nEndX == nCol2 && nEndY == nRow2 ) // leer
935 bOk = FALSE;
936 else if ( nEndX == nCol2 ) // nach oben/unten
938 nEndX = nCol2 = nCol1; // nur erste Spalte ansehen
939 nSrcCount = nRow2 - nRow1 + 1;
940 nIndex = ((long)nEndY) - nRow1; // kann negativ werden
941 if ( nEndY >= nRow1 )
942 eFillDir = FILL_TO_BOTTOM;
943 else
944 eFillDir = FILL_TO_TOP;
946 else if ( nEndY == nRow2 ) // nach links/rechts
948 nEndY = nRow2 = nRow1; // nur erste Zeile ansehen
949 nSrcCount = nCol2 - nCol1 + 1;
950 nIndex = ((long)nEndX) - nCol1; // kann negativ werden
951 if ( nEndX >= nCol1 )
952 eFillDir = FILL_TO_RIGHT;
953 else
954 eFillDir = FILL_TO_LEFT;
956 else // Richtung nicht eindeutig
957 bOk = FALSE;
959 if ( bOk )
961 FillCmd eFillCmd;
962 FillDateCmd eDateCmd;
963 double nInc;
964 USHORT nMinDigits;
965 ScUserListData* pListData = NULL;
966 USHORT nListIndex;
968 FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
970 if ( pListData ) // benutzerdefinierte Liste
972 USHORT nListCount = pListData->GetSubCount();
973 if ( nListCount )
975 ULONG nSub = nSrcCount - 1; // nListIndex ist vom letzten Source-Eintrag
976 while ( nIndex < sal::static_int_cast<long>(nSub) )
977 nIndex += nListCount;
978 ULONG nPos = ( nListIndex + nIndex - nSub ) % nListCount;
979 aValue = pListData->GetSubStr(sal::static_int_cast<USHORT>(nPos));
982 else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster
984 long nPosIndex = nIndex;
985 while ( nPosIndex < 0 )
986 nPosIndex += nSrcCount;
987 ULONG nPos = nPosIndex % nSrcCount;
988 SCCOL nSrcX = nCol1;
989 SCROW nSrcY = nRow1;
990 if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
991 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
992 else
993 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
995 ScBaseCell* pCell = GetCell( nSrcX, nSrcY );
996 if ( pCell )
998 sal_Int32 nDelta;
999 if (nIndex >= 0)
1000 nDelta = nIndex / nSrcCount;
1001 else
1002 nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1
1004 CellType eType = pCell->GetCellType();
1005 switch ( eType )
1007 case CELLTYPE_STRING:
1008 case CELLTYPE_EDIT:
1010 if ( eType == CELLTYPE_STRING )
1011 ((ScStringCell*)pCell)->GetString( aValue );
1012 else
1013 ((ScEditCell*)pCell)->GetString( aValue );
1014 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1016 sal_Int32 nVal;
1017 USHORT nCellDigits = 0; // look at each source cell individually
1018 short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
1019 if ( nFlag < 0 )
1021 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1022 aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
1024 aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 );
1026 else if ( nFlag > 0 )
1027 aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
1030 break;
1031 case CELLTYPE_VALUE:
1033 // dabei kann's keinen Ueberlauf geben...
1034 double nVal = ((ScValueCell*)pCell)->GetValue();
1035 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1036 nVal += (double) nDelta;
1038 Color* pColor;
1039 ULONG nNumFmt = GetNumberFormat( nSrcX, nSrcY );
1040 pDocument->GetFormatTable()->
1041 GetOutputString( nVal, nNumFmt, aValue, &pColor );
1043 break;
1044 // Formeln nicht
1045 default:
1047 // added to avoid warnings
1052 else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // Werte
1054 BOOL bValueOk;
1055 double nStart;
1056 sal_Int32 nVal = 0;
1057 short nHeadNoneTail = 0;
1058 ScBaseCell* pCell = GetCell( nCol1, nRow1 );
1059 if ( pCell )
1061 CellType eType = pCell->GetCellType();
1062 switch ( eType )
1064 case CELLTYPE_STRING:
1065 case CELLTYPE_EDIT:
1067 if ( eType == CELLTYPE_STRING )
1068 ((ScStringCell*)pCell)->GetString( aValue );
1069 else
1070 ((ScEditCell*)pCell)->GetString( aValue );
1071 nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
1072 if ( nHeadNoneTail )
1073 nStart = (double)nVal;
1074 else
1075 nStart = 0.0;
1077 break;
1078 case CELLTYPE_VALUE:
1079 nStart = ((ScValueCell*)pCell)->GetValue();
1080 break;
1081 case CELLTYPE_FORMULA:
1082 nStart = ((ScFormulaCell*)pCell)->GetValue();
1083 break;
1084 default:
1085 nStart = 0.0;
1088 else
1089 nStart = 0.0;
1090 if ( eFillCmd == FILL_LINEAR )
1092 double nAdd = nInc;
1093 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
1094 SubTotal::SafePlus( nStart, nAdd ) );
1096 else // Datum
1098 bValueOk = TRUE;
1099 USHORT nDayOfMonth = 0;
1100 if ( nIndex < 0 )
1102 nIndex = -nIndex;
1103 nInc = -nInc;
1105 for (long i=0; i<nIndex; i++)
1106 IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
1109 if (bValueOk)
1111 if ( nHeadNoneTail )
1113 if ( nHeadNoneTail < 0 )
1115 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1116 aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
1118 aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 );
1120 else
1121 aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
1123 else
1125 //! Zahlformat je nach Index holen?
1126 Color* pColor;
1127 ULONG nNumFmt = GetNumberFormat( nCol1, nRow1 );
1128 pDocument->GetFormatTable()->
1129 GetOutputString( nStart, nNumFmt, aValue, &pColor );
1133 else
1135 DBG_ERROR("GetAutoFillPreview: falscher Modus");
1139 return aValue;
1142 void ScTable::IncDate(double& rVal, USHORT& nDayOfMonth, double nStep, FillDateCmd eCmd)
1144 if (eCmd == FILL_DAY)
1146 rVal += nStep;
1147 return;
1150 // class Date Grenzen
1151 const USHORT nMinYear = 1583;
1152 const USHORT nMaxYear = 9956;
1154 long nInc = (long) nStep; // nach oben/unten begrenzen ?
1155 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1156 Date aDate = aNullDate;
1157 aDate += (long)rVal;
1158 switch (eCmd)
1160 case FILL_WEEKDAY:
1162 aDate += nInc;
1163 DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1164 if (nInc >= 0)
1166 if (eWeekDay == SATURDAY)
1167 aDate += 2;
1168 else if (eWeekDay == SUNDAY)
1169 aDate += 1;
1171 else
1173 if (eWeekDay == SATURDAY)
1174 aDate -= 1;
1175 else if (eWeekDay == SUNDAY)
1176 aDate -= 2;
1179 break;
1180 case FILL_MONTH:
1182 if ( nDayOfMonth == 0 )
1183 nDayOfMonth = aDate.GetDay(); // init
1184 long nMonth = aDate.GetMonth();
1185 long nYear = aDate.GetYear();
1187 nMonth += nInc;
1189 if (nInc >= 0)
1191 if (nMonth > 12)
1193 long nYAdd = (nMonth-1) / 12;
1194 nMonth -= nYAdd * 12;
1195 nYear += nYAdd;
1198 else
1200 if (nMonth < 1)
1202 long nYAdd = 1 - nMonth / 12; // positiv
1203 nMonth += nYAdd * 12;
1204 nYear -= nYAdd;
1208 if ( nYear < nMinYear )
1209 aDate = Date( 1,1, nMinYear );
1210 else if ( nYear > nMaxYear )
1211 aDate = Date( 31,12, nMaxYear );
1212 else
1214 aDate.SetMonth((USHORT) nMonth);
1215 aDate.SetYear((USHORT) nYear);
1216 if ( nDayOfMonth > 28 )
1217 aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) );
1220 break;
1221 case FILL_YEAR:
1223 long nYear = aDate.GetYear();
1224 nYear += nInc;
1225 if ( nYear < nMinYear )
1226 aDate = Date( 1,1, nMinYear );
1227 else if ( nYear > nMaxYear )
1228 aDate = Date( 31,12, nMaxYear );
1229 else
1230 aDate.SetYear((USHORT) nYear);
1232 break;
1233 default:
1235 // added to avoid warnings
1239 rVal = aDate - aNullDate;
1242 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1243 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1244 double nStepValue, double nMaxValue, USHORT nArgMinDigits,
1245 BOOL bAttribs, ScProgress& rProgress )
1248 // Richtung auswerten
1251 BOOL bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1252 BOOL bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1254 ULONG nCol = 0;
1255 ULONG nRow = 0;
1256 ULONG& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
1257 ULONG& rOuter = bVertical ? nCol : nRow;
1258 ULONG nOStart;
1259 ULONG nOEnd;
1260 ULONG nIStart;
1261 ULONG nIEnd;
1262 ULONG nISource;
1264 if (bVertical)
1266 nFillCount += (nRow2 - nRow1);
1267 if (nFillCount == 0)
1268 return;
1269 nOStart = nCol1;
1270 nOEnd = nCol2;
1271 if (bPositive)
1273 nISource = nRow1;
1274 nIStart = nRow1 + 1;
1275 nIEnd = nRow1 + nFillCount;
1277 else
1279 nISource = nRow2;
1280 nIStart = nRow2 - 1;
1281 nIEnd = nRow2 - nFillCount;
1284 else
1286 nFillCount += (nCol2 - nCol1);
1287 if (nFillCount == 0)
1288 return;
1289 nOStart = nRow1;
1290 nOEnd = nRow2;
1291 if (bPositive)
1293 nISource = nCol1;
1294 nIStart = nCol1 + 1;
1295 nIEnd = nCol1 + nFillCount;
1297 else
1299 nISource = nCol2;
1300 nIStart = nCol2 - 1;
1301 nIEnd = nCol2 - nFillCount;
1305 ULONG nIMin = nIStart;
1306 ULONG nIMax = nIEnd;
1307 PutInOrder(nIMin,nIMax);
1308 USHORT nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1309 if (bVertical)
1310 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1311 else
1312 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1314 ULONG nProgress = rProgress.GetState();
1317 // ausfuehren
1320 ULONG nActFormCnt = 0;
1321 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1323 BOOL bFirst = TRUE;
1324 rInner = nISource;
1325 ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow));
1327 if (bVertical && bAttribs)
1328 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
1330 if (bAttribs)
1332 const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1333 if (bVertical)
1334 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1335 static_cast<SCROW>(nIMax), *pSrcPattern, TRUE );
1336 else
1337 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1338 aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, TRUE);
1341 if (pSrcCell)
1343 CellType eCellType = pSrcCell->GetCellType();
1345 if (eFillCmd == FILL_SIMPLE) // kopieren
1347 if (eCellType == CELLTYPE_FORMULA)
1349 for (rInner = nIMin; rInner <= nIMax; rInner++)
1351 if (pDocument->RowFiltered( rInner, nTab))
1352 continue;
1353 ULONG nInd = nActFormCnt;
1354 FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell,
1355 static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) );
1356 bFirst = FALSE;
1357 rProgress.SetStateOnPercent( ++nProgress );
1360 else if (eCellType != CELLTYPE_NOTE)
1362 for (rInner = nIMin; rInner <= nIMax; rInner++)
1364 if (pDocument->RowFiltered( rInner, nTab))
1365 continue;
1366 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
1367 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
1369 nProgress += nIMax - nIMin + 1;
1370 rProgress.SetStateOnPercent( nProgress );
1373 else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1375 double nStartVal;
1376 if (eCellType == CELLTYPE_VALUE)
1377 nStartVal = ((ScValueCell*)pSrcCell)->GetValue();
1378 else
1379 nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue();
1380 double nVal = nStartVal;
1381 long nIndex = 0;
1383 BOOL bError = FALSE;
1384 BOOL bOverflow = FALSE;
1386 USHORT nDayOfMonth = 0;
1387 rInner = nIStart;
1388 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1390 if (!bError && !bOverflow)
1392 switch (eFillCmd)
1394 case FILL_LINEAR:
1396 // #86365# use multiplication instead of repeated addition
1397 // to avoid accumulating rounding errors
1398 nVal = nStartVal;
1399 double nAdd = nStepValue;
1400 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1401 !SubTotal::SafePlus( nVal, nAdd ) )
1402 bError = TRUE;
1404 break;
1405 case FILL_GROWTH:
1406 if (!SubTotal::SafeMult(nVal, nStepValue))
1407 bError = TRUE;
1408 break;
1409 case FILL_DATE:
1410 if (fabs(nVal) > _D_MAX_LONG_)
1411 bError = TRUE;
1412 else
1413 IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1414 break;
1415 default:
1417 // added to avoid warnings
1421 if (nStepValue >= 0)
1423 if (nVal > nMaxValue) // Zielwert erreicht?
1425 nVal = nMaxValue;
1426 bOverflow = TRUE;
1429 else
1431 if (nVal < nMaxValue)
1433 nVal = nMaxValue;
1434 bOverflow = TRUE;
1439 if (bError)
1440 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1441 else if (!bOverflow)
1442 aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1444 if (rInner == nIEnd) break;
1445 if (bPositive) ++rInner; else --rInner;
1447 nProgress += nIMax - nIMin + 1;
1448 rProgress.SetStateOnPercent( nProgress );
1450 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1452 if ( nStepValue >= 0 )
1454 if ( nMaxValue >= (double)LONG_MAX )
1455 nMaxValue = (double)LONG_MAX - 1;
1457 else
1459 if ( nMaxValue <= (double)LONG_MIN )
1460 nMaxValue = (double)LONG_MIN + 1;
1462 String aValue;
1463 if (eCellType == CELLTYPE_STRING)
1464 ((ScStringCell*)pSrcCell)->GetString( aValue );
1465 else
1466 ((ScEditCell*)pSrcCell)->GetString( aValue );
1467 sal_Int32 nStringValue;
1468 USHORT nMinDigits = nArgMinDigits;
1469 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1470 if ( nHeadNoneTail )
1472 double nStartVal = (double)nStringValue;
1473 double nVal = nStartVal;
1474 long nIndex = 0;
1475 BOOL bError = FALSE;
1476 BOOL bOverflow = FALSE;
1478 BOOL bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix(
1479 (sal_Int32)nStartVal));
1481 rInner = nIStart;
1482 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1484 if (!bError && !bOverflow)
1486 switch (eFillCmd)
1488 case FILL_LINEAR:
1490 // #86365# use multiplication instead of repeated addition
1491 // to avoid accumulating rounding errors
1492 nVal = nStartVal;
1493 double nAdd = nStepValue;
1494 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1495 !SubTotal::SafePlus( nVal, nAdd ) )
1496 bError = TRUE;
1498 break;
1499 case FILL_GROWTH:
1500 if (!SubTotal::SafeMult(nVal, nStepValue))
1501 bError = TRUE;
1502 break;
1503 default:
1505 // added to avoid warnings
1509 if (nStepValue >= 0)
1511 if (nVal > nMaxValue) // Zielwert erreicht?
1513 nVal = nMaxValue;
1514 bOverflow = TRUE;
1517 else
1519 if (nVal < nMaxValue)
1521 nVal = nMaxValue;
1522 bOverflow = TRUE;
1527 if (bError)
1528 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1529 else if (!bOverflow)
1531 nStringValue = (sal_Int32)nVal;
1532 String aStr;
1533 if ( nHeadNoneTail < 0 )
1535 aCol[nCol].Insert( static_cast<SCROW>(nRow),
1536 lcl_getSuffixCell( pDocument,
1537 nStringValue, nMinDigits, aValue,
1538 eCellType, bIsOrdinalSuffix ));
1540 else
1542 aStr = aValue;
1543 aStr += lcl_ValueString( nStringValue, nMinDigits );
1544 ScStringCell* pCell = new ScStringCell( aStr );
1545 aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell );
1549 if (rInner == nIEnd) break;
1550 if (bPositive) ++rInner; else --rInner;
1553 nProgress += nIMax - nIMin + 1;
1554 rProgress.SetStateOnPercent( nProgress );
1557 else
1559 nProgress += nIMax - nIMin + 1;
1560 rProgress.SetStateOnPercent( nProgress );
1562 ++nActFormCnt;
1566 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1567 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1568 double nStepValue, double nMaxValue)
1570 ULONG nProgCount;
1571 if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
1572 nProgCount = nCol2 - nCol1 + 1;
1573 else
1574 nProgCount = nRow2 - nRow1 + 1;
1575 nProgCount *= nFillCount;
1576 ScProgress aProgress( pDocument->GetDocumentShell(),
1577 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
1579 bSharedNameInserted = FALSE;
1581 if (eFillCmd == FILL_AUTO)
1582 FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
1583 else
1584 FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1585 eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, TRUE, aProgress);
1587 if (bSharedNameInserted) // Wurde Shared-Name eingefuegt?
1588 pDocument->GetRangeName()->SetSharedMaxIndex(
1589 pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen
1593 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1594 const ScPatternAttr& rAttr, USHORT nFormatNo)
1596 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1597 if (pAutoFormat)
1599 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1600 if (pData)
1602 // ScPatternAttr aPattern(pDocument->GetPool());
1603 // pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument);
1604 ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1609 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1610 USHORT nFormatNo )
1612 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1614 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1615 if (pAutoFormat)
1617 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1618 if (pData)
1620 ScPatternAttr* pPatternAttrs[16];
1621 for (sal_uInt8 i = 0; i < 16; ++i)
1623 pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1624 pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1627 SCCOL nCol = nStartCol;
1628 SCROW nRow = nStartRow;
1629 USHORT nIndex = 0;
1630 // Linke obere Ecke
1631 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1632 // Linke Spalte
1633 if (pData->IsEqualData(4, 8))
1634 AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1635 else
1637 nIndex = 4;
1638 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1640 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1641 if (nIndex == 4)
1642 nIndex = 8;
1643 else
1644 nIndex = 4;
1647 // Linke untere Ecke
1648 nRow = nEndRow;
1649 nIndex = 12;
1650 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1651 // Rechte obere Ecke
1652 nCol = nEndCol;
1653 nRow = nStartRow;
1654 nIndex = 3;
1655 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1656 // Rechte Spalte
1657 if (pData->IsEqualData(7, 11))
1658 AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1659 else
1661 nIndex = 7;
1662 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1664 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1665 if (nIndex == 7)
1666 nIndex = 11;
1667 else
1668 nIndex = 7;
1671 // Rechte untere Ecke
1672 nRow = nEndRow;
1673 nIndex = 15;
1674 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1675 nRow = nStartRow;
1676 nIndex = 1;
1677 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1679 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1680 if (nIndex == 1)
1681 nIndex = 2;
1682 else
1683 nIndex = 1;
1685 // Untere Zeile
1686 nRow = nEndRow;
1687 nIndex = 13;
1688 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1690 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1691 if (nIndex == 13)
1692 nIndex = 14;
1693 else
1694 nIndex = 13;
1696 // Boddy
1697 if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1698 AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1699 else
1701 if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1703 nIndex = 5;
1704 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1706 AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1707 if (nIndex == 5)
1708 nIndex = 6;
1709 else
1710 nIndex = 5;
1713 else
1715 nIndex = 5;
1716 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1718 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1720 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1721 if ((nIndex == 5) || (nIndex == 9))
1723 if (nIndex == 5)
1724 nIndex = 9;
1725 else
1726 nIndex = 5;
1728 else
1730 if (nIndex == 6)
1731 nIndex = 10;
1732 else
1733 nIndex = 6;
1735 } // for nRow
1736 if ((nIndex == 5) || (nIndex == 9))
1737 nIndex = 6;
1738 else
1739 nIndex = 5;
1740 } // for nCol
1741 } // if not equal Column
1742 } // if not all equal
1744 for (sal_uInt8 j = 0; j < 16; ++j)
1745 delete pPatternAttrs[j];
1746 } // if AutoFormatData != NULL
1747 } // if AutoFormat != NULL
1748 } // if ValidColRow
1751 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, USHORT nIndex, ScAutoFormatData& rData)
1753 UINT32 nFormatIndex = GetNumberFormat( nCol, nRow );
1754 ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1755 rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1758 #define LF_LEFT 1
1759 #define LF_TOP 2
1760 #define LF_RIGHT 4
1761 #define LF_BOTTOM 8
1762 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1764 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, USHORT nFlags, USHORT nIndex, ScAutoFormatData& rData)
1766 const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1767 const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1768 const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1769 const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1770 const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1772 SvxBoxItem aBox( ATTR_BORDER );
1773 if (nFlags & LF_LEFT)
1775 if (pLeftBox)
1777 if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1778 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1779 else
1780 aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1782 else
1783 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1785 if (nFlags & LF_TOP)
1787 if (pTopBox)
1789 if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
1790 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1791 else
1792 aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
1794 else
1795 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1797 if (nFlags & LF_RIGHT)
1799 if (pRightBox)
1801 if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
1802 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1803 else
1804 aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
1806 else
1807 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1809 if (nFlags & LF_BOTTOM)
1811 if (pBottomBox)
1813 if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
1814 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1815 else
1816 aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
1818 else
1819 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1821 rData.PutItem( nIndex, aBox );
1824 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
1826 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1828 if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
1830 // Linke obere Ecke
1831 GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
1832 GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
1833 // Linke Spalte
1834 GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
1835 GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
1836 GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
1837 if (nEndRow - nStartRow >= 4)
1838 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
1839 else
1840 rData.CopyItem( 8, 4, ATTR_BORDER );
1841 // Linke untere Ecke
1842 GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
1843 GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
1844 // Rechte obere Ecke
1845 GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
1846 GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
1847 // Rechte Spalte
1848 GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
1849 GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
1850 GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
1851 if (nEndRow - nStartRow >= 4)
1852 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
1853 else
1854 rData.CopyItem( 11, 7, ATTR_BORDER );
1855 // Rechte untere Ecke
1856 GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
1857 GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
1858 // Ober Zeile
1859 GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
1860 GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
1861 GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
1862 if (nEndCol - nStartCol >= 4)
1863 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
1864 else
1865 rData.CopyItem( 2, 1, ATTR_BORDER );
1866 // Untere Zeile
1867 GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
1868 GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
1869 GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
1870 if (nEndCol - nStartCol >= 4)
1871 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
1872 else
1873 rData.CopyItem( 14, 13, ATTR_BORDER );
1874 // Body
1875 GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
1876 GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
1877 GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
1878 GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
1879 GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
1880 if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
1882 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
1883 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
1884 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
1886 else
1888 rData.CopyItem( 6, 5, ATTR_BORDER );
1889 rData.CopyItem( 9, 5, ATTR_BORDER );
1890 rData.CopyItem( 10, 5, ATTR_BORDER );
1896 void ScTable::SetError( SCCOL nCol, SCROW nRow, USHORT nError)
1898 if (ValidColRow(nCol, nRow))
1899 aCol[nCol].SetError( nRow, nError );
1902 void ScTable::UpdateInsertTabAbs(SCTAB nTable)
1904 for (SCCOL i=0; i <= MAXCOL; i++)
1905 aCol[i].UpdateInsertTabAbs(nTable);
1908 //UNUSED2008-05 USHORT ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const
1909 //UNUSED2008-05 {
1910 //UNUSED2008-05 if (ValidColRow(nCol,nRow))
1911 //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow );
1912 //UNUSED2008-05 else
1913 //UNUSED2008-05 return 0;
1914 //UNUSED2008-05 }
1916 BOOL ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, BOOL bInSel,
1917 const ScMarkData& rMark) const
1919 if (rRow == MAXROW+2) // Tabellenende
1921 rRow = 0;
1922 rCol = 0;
1924 else
1926 rRow++;
1927 if (rRow == MAXROW+1)
1929 rCol++;
1930 rRow = 0;
1933 if (rCol == MAXCOL+1)
1934 return TRUE;
1935 else
1937 BOOL bStop = FALSE;
1938 while (!bStop)
1940 if (ValidCol(rCol))
1942 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
1943 if (bStop)
1944 return TRUE;
1945 else /*if (rRow == MAXROW+1) */
1947 rCol++;
1948 rRow = 0;
1951 else
1952 return TRUE;
1955 return FALSE;
1958 void ScTable::RemoveAutoSpellObj()
1960 for (SCCOL i=0; i <= MAXCOL; i++)
1961 aCol[i].RemoveAutoSpellObj();
1964 BOOL ScTable::TestTabRefAbs(SCTAB nTable)
1966 BOOL bRet = FALSE;
1967 for (SCCOL i=0; i <= MAXCOL; i++)
1968 if (aCol[i].TestTabRefAbs(nTable))
1969 bRet = TRUE;
1970 return bRet;
1973 void ScTable::CompileDBFormula()
1975 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
1978 void ScTable::CompileDBFormula( BOOL bCreateFormulaString )
1980 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
1983 void ScTable::CompileNameFormula( BOOL bCreateFormulaString )
1985 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
1988 void ScTable::CompileColRowNameFormula()
1990 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();