update ooo310-m15
[ooovba.git] / sc / source / core / data / table4.cxx
blob4beb788d2759b7d83c3fcc974080b4568e12ab62
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 xub_StrLen nLen = aValue.Len();
98 if (!nLen)
100 nVal = 0;
101 return 0;
103 const sal_Unicode* p = aValue.GetBuffer();
104 xub_StrLen nSign = (p[0] == '+' || p[0] == '-') ? 1 : 0;
105 xub_StrLen nDot = nLen, nFirst = nLen;
106 String aBuf;
107 bool bLeadingNum = true;
108 for (xub_StrLen i = nSign; i < nLen; ++i)
110 sal_Unicode c = p[i];
111 if (CharClass::isAsciiNumeric(c) && c != '+' && c != '-')
113 aBuf.Append(c);
114 continue;
116 else
118 if (bLeadingNum)
119 bLeadingNum = false;
120 else
121 aBuf.Erase();
124 if (nFirst == nLen)
125 nFirst = i;
127 if (c == '.')
129 // if it's a dot, erase the buffer and keep going.
130 aBuf.Erase();
131 nDot = i;
132 continue;
134 else if (aBuf.Len())
136 // leading number
137 if (nDot < nLen)
139 // If a dot has been previously encountered, then use the
140 // first numerical segment.
141 i = nFirst;
142 aBuf = aValue.Copy(0, nFirst);
145 nVal = aBuf.ToInt32();
146 if (nSign && p[0] == '-')
147 nVal *= -1;
148 aValue.Erase(0, i);
149 if (pMinDigits)
150 *pMinDigits = i - nSign;
151 return -1;
154 if (aBuf.Len())
156 // trailing number.
157 xub_StrLen nBufLen = aBuf.Len();
158 nVal = aBuf.ToInt32();
159 aValue.Erase(nLen - nBufLen);
160 if (pMinDigits)
161 *pMinDigits = nBufLen;
162 return 1;
165 nVal = 0;
166 return 0;
169 String lcl_ValueString( sal_Int32 nValue, USHORT nMinDigits )
171 if ( nMinDigits <= 1 )
172 return String::CreateFromInt32( nValue ); // simple case...
173 else
175 String aStr = String::CreateFromInt32( Abs( nValue ) );
176 if ( aStr.Len() < nMinDigits )
178 String aZero;
179 aZero.Fill( nMinDigits - aStr.Len(), '0' );
180 aStr.Insert( aZero, 0 );
182 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
183 if ( nValue < 0 )
184 aStr.Insert( '-', 0 );
185 return aStr;
189 static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue,
190 USHORT nDigits, const String& rSuffix, CellType eCellType,
191 BOOL bIsOrdinalSuffix )
193 String aValue( lcl_ValueString( nValue, nDigits ));
194 if (!bIsOrdinalSuffix)
195 return new ScStringCell( aValue += rSuffix);
197 String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue));
198 if (eCellType != CELLTYPE_EDIT)
199 return new ScStringCell( aValue += aOrdinalSuffix);
201 EditEngine aEngine( pDocument->GetEnginePool() );
202 SfxItemSet aAttr = aEngine.GetEmptyItemSet();
203 aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
204 aEngine.SetText( aValue );
205 aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0,
206 aValue.Len() + aOrdinalSuffix.Len()));
207 aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() +
208 aOrdinalSuffix.Len()));
209 return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL );
212 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
213 FillCmd& rCmd, FillDateCmd& rDateCmd,
214 double& rInc, USHORT& rMinDigits,
215 ScUserListData*& rListData, USHORT& rListIndex)
217 DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" );
219 rInc = 0.0;
220 rMinDigits = 0;
221 rListData = NULL;
222 rCmd = FILL_SIMPLE;
223 if ( nScFillModeMouseModifier & KEY_MOD1 )
224 return ; // Ctrl-Taste: Copy
226 SCCOL nAddX;
227 SCROW nAddY;
228 SCSIZE nCount;
229 if (nCol1 == nCol2)
231 nAddX = 0;
232 nAddY = 1;
233 nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
235 else
237 nAddX = 1;
238 nAddY = 0;
239 nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
242 SCCOL nCol = nCol1;
243 SCROW nRow = nRow1;
245 ScBaseCell* pFirstCell = GetCell( nCol, nRow );
246 CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE;
248 if (eCellType == CELLTYPE_VALUE)
250 UINT32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
251 BOOL bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
252 if (bDate)
254 if (nCount > 1)
256 long nCmpInc = 0;
257 double nVal;
258 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
259 Date aDate1 = aNullDate;
260 nVal = ((ScValueCell*)pFirstCell)->GetValue();
261 aDate1 += (long)nVal;
262 Date aDate2 = aNullDate;
263 nVal = GetValue(nCol+nAddX, nRow+nAddY);
264 aDate2 += (long)nVal;
265 if ( aDate1 != aDate2 )
267 FillDateCmd eType;
268 long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
269 long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
270 long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
271 if ( nDDiff )
273 eType = FILL_DAY;
274 nCmpInc = aDate2 - aDate1;
276 else
278 eType = FILL_MONTH;
279 nCmpInc = nMDiff + 12 * nYDiff;
282 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
283 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
284 BOOL bVal = TRUE;
285 for (USHORT i=1; i<nCount && bVal; i++)
287 ScBaseCell* pCell = GetCell(nCol,nRow);
288 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
290 nVal = ((ScValueCell*)pCell)->GetValue();
291 aDate2 = aNullDate + (long) nVal;
292 if ( eType == FILL_DAY )
294 if ( aDate2-aDate1 != nCmpInc )
295 bVal = FALSE;
297 else
299 nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
300 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
301 nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
302 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
303 bVal = FALSE;
305 aDate1 = aDate2;
306 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
307 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
309 else
310 bVal = FALSE; // #50965# kein Datum passt auch nicht
312 if (bVal)
314 if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
316 eType = FILL_YEAR;
317 nCmpInc /= 12;
319 rCmd = FILL_DATE;
320 rDateCmd = eType;
321 rInc = nCmpInc;
325 else // einzelnes Datum -> Tage hochzaehlen
327 rCmd = FILL_DATE;
328 rDateCmd = FILL_DAY;
329 rInc = 1.0;
332 else
334 if (nCount > 1)
336 double nVal1 = ((ScValueCell*)pFirstCell)->GetValue();
337 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
338 rInc = nVal2 - nVal1;
339 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
340 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
341 BOOL bVal = TRUE;
342 for (USHORT i=1; i<nCount && bVal; i++)
344 ScBaseCell* pCell = GetCell(nCol,nRow);
345 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
347 nVal2 = ((ScValueCell*)pCell)->GetValue();
348 double nDiff = nVal2 - nVal1;
349 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
350 bVal = FALSE;
351 nVal1 = nVal2;
353 else
354 bVal = FALSE;
355 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
356 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
358 if (bVal)
359 rCmd = FILL_LINEAR;
363 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
365 String aStr;
366 GetString(nCol, nRow, aStr);
367 rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
368 if (rListData)
370 rListData->GetSubIndex(aStr, rListIndex);
371 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
372 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
373 for (USHORT i=1; i<nCount && rListData; i++)
375 GetString(nCol, nRow, aStr);
376 if (!rListData->GetSubIndex(aStr, rListIndex))
377 rListData = NULL;
378 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
379 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
382 else if ( nCount > 1 )
384 // pass rMinDigits to all DecompValueString calls
385 // -> longest number defines rMinDigits
387 sal_Int32 nVal1;
388 short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
389 if ( nFlag1 )
391 sal_Int32 nVal2;
392 GetString( nCol+nAddX, nRow+nAddY, aStr );
393 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
394 if ( nFlag1 == nFlag2 )
396 rInc = (double)nVal2 - (double)nVal1;
397 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
398 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
399 BOOL bVal = TRUE;
400 for (USHORT i=1; i<nCount && bVal; i++)
402 ScBaseCell* pCell = GetCell(nCol,nRow);
403 CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
404 if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
406 if ( eType == CELLTYPE_STRING )
407 ((ScStringCell*)pCell)->GetString( aStr );
408 else
409 ((ScEditCell*)pCell)->GetString( aStr );
410 nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
411 if ( nFlag1 == nFlag2 )
413 double nDiff = (double)nVal2 - (double)nVal1;
414 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
415 bVal = FALSE;
416 nVal1 = nVal2;
418 else
419 bVal = FALSE;
421 else
422 bVal = FALSE;
423 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
424 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
426 if (bVal)
427 rCmd = FILL_LINEAR;
431 else
433 // call DecompValueString to set rMinDigits
434 sal_Int32 nDummy;
435 lcl_DecompValueString( aStr, nDummy, &rMinDigits );
440 void ScTable::FillFormula(ULONG& /* nFormulaCounter */, BOOL /* bFirst */, ScFormulaCell* pSrcCell,
441 SCCOL nDestCol, SCROW nDestRow, BOOL bLast )
443 /* USHORT nTokArrLen = pSrcCell->GetTokenArrayLen();
444 if ( nTokArrLen > 15 ) // mehr als =A1 oder =67
446 ScRangeName* pRangeName = pDocument->GetRangeName();
447 String aName("___SC_"); // Wird dieser String veraendert,
448 // auch in document2 EraseNonUsed...
449 // mitaendern!!
450 aName += pRangeName->GetSharedMaxIndex() + 1;
451 aName += '_';
452 aName += nFormulaCounter;
453 nFormulaCounter++;
454 if (bFirst)
456 ScRangeData *pAktRange = new ScRangeData(
457 pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
458 pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
459 if (!pRangeName->Insert( pAktRange ))
460 delete pAktRange;
461 else
462 bSharedNameInserted = TRUE;
464 USHORT nIndex;
465 pRangeName->SearchName(aName, nIndex);
466 if (!pRangeName)
468 DBG_ERROR("ScTable::FillFormula: Falscher Name");
469 return;
471 nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
472 ScTokenArray aArr;
473 aArr.AddName(nIndex);
474 aArr.AddOpCode(ocStop);
475 ScFormulaCell* pDestCell = new ScFormulaCell
476 (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
477 aCol[nDestCol].Insert(nDestRow, pDestCell);
479 else
480 */ {
481 pDocument->SetNoListening( TRUE ); // noch falsche Referenzen
482 ScAddress aAddr( nDestCol, nDestRow, nTab );
483 ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
484 aCol[nDestCol].Insert(nDestRow, pDestCell);
485 #if 0
486 // mit RelRefs unnoetig
487 pDestCell->UpdateReference(URM_COPY,
488 ScRange( aAddr, aAddr ),
489 nDestCol - pSrcCell->aPos.Col(),
490 nDestRow - pSrcCell->aPos.Row(), 0);
491 #endif
492 if ( bLast && pDestCell->GetMatrixFlag() )
494 ScAddress aOrg;
495 if ( pDestCell->GetMatrixOrigin( aOrg ) )
497 if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
499 ScBaseCell* pOrgCell = pDocument->GetCell( aOrg );
500 if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA
501 && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA )
503 ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
504 nDestCol - aOrg.Col() + 1,
505 nDestRow - aOrg.Row() + 1 );
507 else
509 DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
512 else
514 DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
517 else
519 DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
522 pDocument->SetNoListening( FALSE );
523 pDestCell->StartListeningTo( pDocument );
527 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
528 ULONG nFillCount, FillDir eFillDir, ScProgress& rProgress )
530 if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
531 return;
534 // Richtung auswerten
537 BOOL bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
538 BOOL bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
540 ULONG nCol = 0;
541 ULONG nRow = 0;
542 ULONG& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
543 ULONG& rOuter = bVertical ? nCol : nRow;
544 ULONG nOStart;
545 ULONG nOEnd;
546 ULONG nIStart;
547 ULONG nIEnd;
548 ULONG nISrcStart;
549 ULONG nISrcEnd;
551 if (bVertical)
553 nOStart = nCol1;
554 nOEnd = nCol2;
555 if (bPositive)
557 nISrcStart = nRow1;
558 nISrcEnd = nRow2;
559 nIStart = nRow2 + 1;
560 nIEnd = nRow2 + nFillCount;
562 else
564 nISrcStart = nRow2;
565 nISrcEnd = nRow1;
566 nIStart = nRow1 - 1;
567 nIEnd = nRow1 - nFillCount;
570 else
572 nOStart = nRow1;
573 nOEnd = nRow2;
574 if (bPositive)
576 nISrcStart = nCol1;
577 nISrcEnd = nCol2;
578 nIStart = nCol2 + 1;
579 nIEnd = nCol2 + nFillCount;
581 else
583 nISrcStart = nCol2;
584 nISrcEnd = nCol1;
585 nIStart = nCol1 - 1;
586 nIEnd = nCol1 - nFillCount;
589 ULONG nIMin = nIStart;
590 ULONG nIMax = nIEnd;
591 PutInOrder(nIMin,nIMax);
592 if (bVertical)
593 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
594 else
595 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
597 ULONG nProgress = rProgress.GetState();
600 // ausfuehren
603 ULONG nActFormCnt = 0;
604 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
606 ULONG nMaxFormCnt = 0; // fuer Formeln
608 // Attributierung uebertragen
610 const ScPatternAttr* pSrcPattern = NULL;
611 ULONG nAtSrc = nISrcStart;
612 ScPatternAttr* pNewPattern = NULL;
613 BOOL bGetPattern = TRUE;
614 rInner = nIStart;
615 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
617 const ScStyleSheet* pStyleSheet = NULL;
618 if ( bGetPattern )
620 if ( pNewPattern )
621 delete pNewPattern;
622 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
623 pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
624 else // rInner&:=nCol, rOuter&:=nRow
625 pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
626 bGetPattern = FALSE;
627 pStyleSheet = pSrcPattern->GetStyleSheet();
628 // Merge/Mergeflag nicht uebernehmen,
629 const SfxItemSet& rSet = pSrcPattern->GetItemSet();
630 if ( rSet.GetItemState(ATTR_MERGE, FALSE) == SFX_ITEM_SET
631 || rSet.GetItemState(ATTR_MERGE_FLAG, FALSE) == SFX_ITEM_SET )
633 pNewPattern = new ScPatternAttr( *pSrcPattern );
634 SfxItemSet& rNewSet = pNewPattern->GetItemSet();
635 rNewSet.ClearItem(ATTR_MERGE);
636 rNewSet.ClearItem(ATTR_MERGE_FLAG);
638 else
639 pNewPattern = NULL;
642 if ( bVertical && nISrcStart == nISrcEnd )
644 // Attribute komplett am Stueck setzen
645 if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
647 // Default steht schon da (DeleteArea)
648 SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd ));
649 SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd ));
650 if ( pStyleSheet )
651 aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
652 if ( pNewPattern )
653 aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
654 else
655 aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
657 break; // Schleife abbrechen
660 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
662 // Vorlage auch uebernehmen
663 //! am AttrArray mit ApplyPattern zusammenfassen ??
664 if ( pStyleSheet )
665 aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
667 // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
668 if ( pNewPattern )
669 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
670 else
671 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
674 if (nAtSrc==nISrcEnd)
676 if ( nAtSrc != nISrcStart )
677 { // mehr als eine Source-Zelle
678 nAtSrc = nISrcStart;
679 bGetPattern = TRUE;
682 else if (bPositive)
684 ++nAtSrc;
685 bGetPattern = TRUE;
687 else
689 --nAtSrc;
690 bGetPattern = TRUE;
693 if (rInner == nIEnd) break;
694 if (bPositive) ++rInner; else --rInner;
696 if ( pNewPattern )
697 delete pNewPattern;
699 // Analyse
701 FillCmd eFillCmd;
702 FillDateCmd eDateCmd;
703 double nInc;
704 USHORT nMinDigits;
705 ScUserListData* pListData = NULL;
706 USHORT nListIndex;
707 if (bVertical)
708 FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
709 static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
710 nInc,nMinDigits, pListData,nListIndex);
711 else
712 FillAnalyse(nCol1,static_cast<SCROW>(nRow),
713 nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
714 nInc,nMinDigits, pListData,nListIndex);
716 if (bVertical)
717 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
719 if (pListData)
721 USHORT nListCount = pListData->GetSubCount();
722 if ( !bPositive )
724 // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
725 ULONG nSub = nISrcStart - nISrcEnd;
726 for (ULONG i=0; i<nSub; i++)
728 if (nListIndex == 0) nListIndex = nListCount;
729 --nListIndex;
733 rInner = nIStart;
734 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
736 if (bPositive)
738 ++nListIndex;
739 if (nListIndex >= nListCount) nListIndex = 0;
741 else
743 if (nListIndex == 0) nListIndex = nListCount;
744 --nListIndex;
746 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex)));
748 if (rInner == nIEnd) break;
749 if (bPositive) ++rInner; else --rInner;
751 nProgress += nIMax - nIMin + 1;
752 rProgress.SetStateOnPercent( nProgress );
754 else if (eFillCmd == FILL_SIMPLE) // Auffuellen mit Muster
756 ULONG nSource = nISrcStart;
757 double nDelta;
758 if ( nScFillModeMouseModifier & KEY_MOD1 )
759 nDelta = 0.0;
760 else if ( bPositive )
761 nDelta = 1.0;
762 else
763 nDelta = -1.0;
764 double nVal = 0.0;
765 ULONG nFormulaCounter = nActFormCnt;
766 BOOL bFirst = TRUE;
767 BOOL bGetCell = TRUE;
768 USHORT nCellDigits = 0;
769 short nHeadNoneTail = 0;
770 sal_Int32 nStringValue = 0;
771 String aValue;
772 ScBaseCell* pSrcCell = NULL;
773 CellType eCellType = CELLTYPE_NONE;
774 BOOL bIsOrdinalSuffix = FALSE;
776 rInner = nIStart;
777 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
779 if ( bGetCell )
781 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
782 pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) );
783 else // rInner&:=nCol, rOuter&:=nRow
784 pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) );
785 bGetCell = FALSE;
786 if ( pSrcCell )
788 eCellType = pSrcCell->GetCellType();
789 switch ( eCellType )
791 case CELLTYPE_VALUE:
792 nVal = ((ScValueCell*)pSrcCell)->GetValue();
793 break;
794 case CELLTYPE_STRING:
795 case CELLTYPE_EDIT:
796 if ( eCellType == CELLTYPE_STRING )
797 ((ScStringCell*)pSrcCell)->GetString( aValue );
798 else
799 ((ScEditCell*)pSrcCell)->GetString( aValue );
800 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
802 nCellDigits = 0; // look at each source cell individually
803 nHeadNoneTail = lcl_DecompValueString(
804 aValue, nStringValue, &nCellDigits );
806 bIsOrdinalSuffix = aValue.Equals(
807 ScGlobal::GetOrdinalSuffix( nStringValue));
809 break;
810 default:
812 // added to avoid warnings
816 else
817 eCellType = CELLTYPE_NONE;
819 switch (eCellType)
821 case CELLTYPE_VALUE:
822 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
823 break;
824 case CELLTYPE_STRING:
825 case CELLTYPE_EDIT:
826 if ( nHeadNoneTail )
828 // #i48009# with the "nStringValue+(long)nDelta" expression within the
829 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
830 // so nNextValue is now calculated ahead.
831 sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta;
833 String aStr;
834 if ( nHeadNoneTail < 0 )
836 aCol[nCol].Insert( static_cast<SCROW>(nRow),
837 lcl_getSuffixCell( pDocument,
838 nNextValue, nCellDigits, aValue,
839 eCellType, bIsOrdinalSuffix));
841 else
843 aStr = aValue;
844 aStr += lcl_ValueString( nNextValue, nCellDigits );
845 aCol[nCol].Insert( static_cast<SCROW>(nRow),
846 new ScStringCell( aStr));
849 else
851 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
852 switch ( eCellType )
854 case CELLTYPE_STRING:
855 case CELLTYPE_EDIT:
856 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
857 break;
858 default:
860 // added to avoid warnings
864 break;
865 case CELLTYPE_FORMULA :
866 FillFormula( nFormulaCounter, bFirst,
867 (ScFormulaCell*) pSrcCell,
868 static_cast<SCCOL>(nCol),
869 static_cast<SCROW>(nRow), (rInner == nIEnd) );
870 if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
871 nMaxFormCnt = nFormulaCounter - nActFormCnt;
872 break;
873 default:
875 // added to avoid warnings
879 if (nSource==nISrcEnd)
881 if ( nSource != nISrcStart )
882 { // mehr als eine Source-Zelle
883 nSource = nISrcStart;
884 bGetCell = TRUE;
886 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
888 if ( bPositive )
889 nDelta += 1.0;
890 else
891 nDelta -= 1.0;
893 nFormulaCounter = nActFormCnt;
894 bFirst = FALSE;
896 else if (bPositive)
898 ++nSource;
899 bGetCell = TRUE;
901 else
903 --nSource;
904 bGetCell = TRUE;
907 // Progress in der inneren Schleife nur bei teuren Zellen,
908 // und auch dann nicht fuer jede einzelne
910 ++nProgress;
911 if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
912 rProgress.SetStateOnPercent( nProgress );
914 if (rInner == nIEnd) break;
915 if (bPositive) ++rInner; else --rInner;
917 rProgress.SetStateOnPercent( nProgress );
919 else
921 if (!bPositive)
922 nInc = -nInc;
923 double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
924 if (bVertical)
925 FillSeries( static_cast<SCCOL>(nCol), nRow1,
926 static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
927 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, FALSE,
928 rProgress );
929 else
930 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
931 static_cast<SCROW>(nRow), nFillCount, eFillDir,
932 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, FALSE,
933 rProgress );
934 nProgress = rProgress.GetState();
937 nActFormCnt += nMaxFormCnt;
941 String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
943 String aValue;
945 SCCOL nCol1 = rSource.aStart.Col();
946 SCROW nRow1 = rSource.aStart.Row();
947 SCCOL nCol2 = rSource.aEnd.Col();
948 SCROW nRow2 = rSource.aEnd.Row();
949 BOOL bOk = TRUE;
950 long nIndex = 0;
951 ULONG nSrcCount = 0;
952 FillDir eFillDir = FILL_TO_BOTTOM;
953 if ( nEndX == nCol2 && nEndY == nRow2 ) // leer
954 bOk = FALSE;
955 else if ( nEndX == nCol2 ) // nach oben/unten
957 nEndX = nCol2 = nCol1; // nur erste Spalte ansehen
958 nSrcCount = nRow2 - nRow1 + 1;
959 nIndex = ((long)nEndY) - nRow1; // kann negativ werden
960 if ( nEndY >= nRow1 )
961 eFillDir = FILL_TO_BOTTOM;
962 else
963 eFillDir = FILL_TO_TOP;
965 else if ( nEndY == nRow2 ) // nach links/rechts
967 nEndY = nRow2 = nRow1; // nur erste Zeile ansehen
968 nSrcCount = nCol2 - nCol1 + 1;
969 nIndex = ((long)nEndX) - nCol1; // kann negativ werden
970 if ( nEndX >= nCol1 )
971 eFillDir = FILL_TO_RIGHT;
972 else
973 eFillDir = FILL_TO_LEFT;
975 else // Richtung nicht eindeutig
976 bOk = FALSE;
978 if ( bOk )
980 FillCmd eFillCmd;
981 FillDateCmd eDateCmd;
982 double nInc;
983 USHORT nMinDigits;
984 ScUserListData* pListData = NULL;
985 USHORT nListIndex;
987 FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
989 if ( pListData ) // benutzerdefinierte Liste
991 USHORT nListCount = pListData->GetSubCount();
992 if ( nListCount )
994 ULONG nSub = nSrcCount - 1; // nListIndex ist vom letzten Source-Eintrag
995 while ( nIndex < sal::static_int_cast<long>(nSub) )
996 nIndex += nListCount;
997 ULONG nPos = ( nListIndex + nIndex - nSub ) % nListCount;
998 aValue = pListData->GetSubStr(sal::static_int_cast<USHORT>(nPos));
1001 else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster
1003 long nPosIndex = nIndex;
1004 while ( nPosIndex < 0 )
1005 nPosIndex += nSrcCount;
1006 ULONG nPos = nPosIndex % nSrcCount;
1007 SCCOL nSrcX = nCol1;
1008 SCROW nSrcY = nRow1;
1009 if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
1010 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
1011 else
1012 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
1014 ScBaseCell* pCell = GetCell( nSrcX, nSrcY );
1015 if ( pCell )
1017 sal_Int32 nDelta;
1018 if (nIndex >= 0)
1019 nDelta = nIndex / nSrcCount;
1020 else
1021 nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1
1023 CellType eType = pCell->GetCellType();
1024 switch ( eType )
1026 case CELLTYPE_STRING:
1027 case CELLTYPE_EDIT:
1029 if ( eType == CELLTYPE_STRING )
1030 ((ScStringCell*)pCell)->GetString( aValue );
1031 else
1032 ((ScEditCell*)pCell)->GetString( aValue );
1033 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1035 sal_Int32 nVal;
1036 USHORT nCellDigits = 0; // look at each source cell individually
1037 short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
1038 if ( nFlag < 0 )
1040 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1041 aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
1043 aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 );
1045 else if ( nFlag > 0 )
1046 aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
1049 break;
1050 case CELLTYPE_VALUE:
1052 // dabei kann's keinen Ueberlauf geben...
1053 double nVal = ((ScValueCell*)pCell)->GetValue();
1054 if ( !(nScFillModeMouseModifier & KEY_MOD1) )
1055 nVal += (double) nDelta;
1057 Color* pColor;
1058 ULONG nNumFmt = GetNumberFormat( nSrcX, nSrcY );
1059 pDocument->GetFormatTable()->
1060 GetOutputString( nVal, nNumFmt, aValue, &pColor );
1062 break;
1063 // Formeln nicht
1064 default:
1066 // added to avoid warnings
1071 else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // Werte
1073 BOOL bValueOk;
1074 double nStart;
1075 sal_Int32 nVal = 0;
1076 short nHeadNoneTail = 0;
1077 ScBaseCell* pCell = GetCell( nCol1, nRow1 );
1078 if ( pCell )
1080 CellType eType = pCell->GetCellType();
1081 switch ( eType )
1083 case CELLTYPE_STRING:
1084 case CELLTYPE_EDIT:
1086 if ( eType == CELLTYPE_STRING )
1087 ((ScStringCell*)pCell)->GetString( aValue );
1088 else
1089 ((ScEditCell*)pCell)->GetString( aValue );
1090 nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
1091 if ( nHeadNoneTail )
1092 nStart = (double)nVal;
1093 else
1094 nStart = 0.0;
1096 break;
1097 case CELLTYPE_VALUE:
1098 nStart = ((ScValueCell*)pCell)->GetValue();
1099 break;
1100 case CELLTYPE_FORMULA:
1101 nStart = ((ScFormulaCell*)pCell)->GetValue();
1102 break;
1103 default:
1104 nStart = 0.0;
1107 else
1108 nStart = 0.0;
1109 if ( eFillCmd == FILL_LINEAR )
1111 double nAdd = nInc;
1112 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
1113 SubTotal::SafePlus( nStart, nAdd ) );
1115 else // Datum
1117 bValueOk = TRUE;
1118 USHORT nDayOfMonth = 0;
1119 if ( nIndex < 0 )
1121 nIndex = -nIndex;
1122 nInc = -nInc;
1124 for (long i=0; i<nIndex; i++)
1125 IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
1128 if (bValueOk)
1130 if ( nHeadNoneTail )
1132 if ( nHeadNoneTail < 0 )
1134 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1135 aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
1137 aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 );
1139 else
1140 aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
1142 else
1144 //! Zahlformat je nach Index holen?
1145 Color* pColor;
1146 ULONG nNumFmt = GetNumberFormat( nCol1, nRow1 );
1147 pDocument->GetFormatTable()->
1148 GetOutputString( nStart, nNumFmt, aValue, &pColor );
1152 else
1154 DBG_ERROR("GetAutoFillPreview: falscher Modus");
1158 return aValue;
1161 void ScTable::IncDate(double& rVal, USHORT& nDayOfMonth, double nStep, FillDateCmd eCmd)
1163 if (eCmd == FILL_DAY)
1165 rVal += nStep;
1166 return;
1169 // class Date Grenzen
1170 const USHORT nMinYear = 1583;
1171 const USHORT nMaxYear = 9956;
1173 long nInc = (long) nStep; // nach oben/unten begrenzen ?
1174 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1175 Date aDate = aNullDate;
1176 aDate += (long)rVal;
1177 switch (eCmd)
1179 case FILL_WEEKDAY:
1181 aDate += nInc;
1182 DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1183 if (nInc >= 0)
1185 if (eWeekDay == SATURDAY)
1186 aDate += 2;
1187 else if (eWeekDay == SUNDAY)
1188 aDate += 1;
1190 else
1192 if (eWeekDay == SATURDAY)
1193 aDate -= 1;
1194 else if (eWeekDay == SUNDAY)
1195 aDate -= 2;
1198 break;
1199 case FILL_MONTH:
1201 if ( nDayOfMonth == 0 )
1202 nDayOfMonth = aDate.GetDay(); // init
1203 long nMonth = aDate.GetMonth();
1204 long nYear = aDate.GetYear();
1206 nMonth += nInc;
1208 if (nInc >= 0)
1210 if (nMonth > 12)
1212 long nYAdd = (nMonth-1) / 12;
1213 nMonth -= nYAdd * 12;
1214 nYear += nYAdd;
1217 else
1219 if (nMonth < 1)
1221 long nYAdd = 1 - nMonth / 12; // positiv
1222 nMonth += nYAdd * 12;
1223 nYear -= nYAdd;
1227 if ( nYear < nMinYear )
1228 aDate = Date( 1,1, nMinYear );
1229 else if ( nYear > nMaxYear )
1230 aDate = Date( 31,12, nMaxYear );
1231 else
1233 aDate.SetMonth((USHORT) nMonth);
1234 aDate.SetYear((USHORT) nYear);
1235 if ( nDayOfMonth > 28 )
1236 aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) );
1239 break;
1240 case FILL_YEAR:
1242 long nYear = aDate.GetYear();
1243 nYear += nInc;
1244 if ( nYear < nMinYear )
1245 aDate = Date( 1,1, nMinYear );
1246 else if ( nYear > nMaxYear )
1247 aDate = Date( 31,12, nMaxYear );
1248 else
1249 aDate.SetYear((USHORT) nYear);
1251 break;
1252 default:
1254 // added to avoid warnings
1258 rVal = aDate - aNullDate;
1261 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1262 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1263 double nStepValue, double nMaxValue, USHORT nArgMinDigits,
1264 BOOL bAttribs, ScProgress& rProgress )
1267 // Richtung auswerten
1270 BOOL bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1271 BOOL bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1273 ULONG nCol = 0;
1274 ULONG nRow = 0;
1275 ULONG& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
1276 ULONG& rOuter = bVertical ? nCol : nRow;
1277 ULONG nOStart;
1278 ULONG nOEnd;
1279 ULONG nIStart;
1280 ULONG nIEnd;
1281 ULONG nISource;
1283 if (bVertical)
1285 nFillCount += (nRow2 - nRow1);
1286 if (nFillCount == 0)
1287 return;
1288 nOStart = nCol1;
1289 nOEnd = nCol2;
1290 if (bPositive)
1292 nISource = nRow1;
1293 nIStart = nRow1 + 1;
1294 nIEnd = nRow1 + nFillCount;
1296 else
1298 nISource = nRow2;
1299 nIStart = nRow2 - 1;
1300 nIEnd = nRow2 - nFillCount;
1303 else
1305 nFillCount += (nCol2 - nCol1);
1306 if (nFillCount == 0)
1307 return;
1308 nOStart = nRow1;
1309 nOEnd = nRow2;
1310 if (bPositive)
1312 nISource = nCol1;
1313 nIStart = nCol1 + 1;
1314 nIEnd = nCol1 + nFillCount;
1316 else
1318 nISource = nCol2;
1319 nIStart = nCol2 - 1;
1320 nIEnd = nCol2 - nFillCount;
1324 ULONG nIMin = nIStart;
1325 ULONG nIMax = nIEnd;
1326 PutInOrder(nIMin,nIMax);
1327 USHORT nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1328 if (bVertical)
1329 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1330 else
1331 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1333 ULONG nProgress = rProgress.GetState();
1336 // ausfuehren
1339 ULONG nActFormCnt = 0;
1340 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1342 BOOL bFirst = TRUE;
1343 rInner = nISource;
1344 ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow));
1346 if (bVertical && bAttribs)
1347 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
1349 if (bAttribs)
1351 const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1352 if (bVertical)
1353 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1354 static_cast<SCROW>(nIMax), *pSrcPattern, TRUE );
1355 else
1356 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1357 aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, TRUE);
1360 if (pSrcCell)
1362 CellType eCellType = pSrcCell->GetCellType();
1364 if (eFillCmd == FILL_SIMPLE) // kopieren
1366 if (eCellType == CELLTYPE_FORMULA)
1368 for (rInner = nIMin; rInner <= nIMax; rInner++)
1370 if (pDocument->RowFiltered( rInner, nTab))
1371 continue;
1372 ULONG nInd = nActFormCnt;
1373 FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell,
1374 static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) );
1375 bFirst = FALSE;
1376 rProgress.SetStateOnPercent( ++nProgress );
1379 else if (eCellType != CELLTYPE_NOTE)
1381 for (rInner = nIMin; rInner <= nIMax; rInner++)
1383 if (pDocument->RowFiltered( rInner, nTab))
1384 continue;
1385 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
1386 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
1388 nProgress += nIMax - nIMin + 1;
1389 rProgress.SetStateOnPercent( nProgress );
1392 else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1394 double nStartVal;
1395 if (eCellType == CELLTYPE_VALUE)
1396 nStartVal = ((ScValueCell*)pSrcCell)->GetValue();
1397 else
1398 nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue();
1399 double nVal = nStartVal;
1400 long nIndex = 0;
1402 BOOL bError = FALSE;
1403 BOOL bOverflow = FALSE;
1405 USHORT nDayOfMonth = 0;
1406 rInner = nIStart;
1407 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1409 if (!bError && !bOverflow)
1411 switch (eFillCmd)
1413 case FILL_LINEAR:
1415 // #86365# use multiplication instead of repeated addition
1416 // to avoid accumulating rounding errors
1417 nVal = nStartVal;
1418 double nAdd = nStepValue;
1419 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1420 !SubTotal::SafePlus( nVal, nAdd ) )
1421 bError = TRUE;
1423 break;
1424 case FILL_GROWTH:
1425 if (!SubTotal::SafeMult(nVal, nStepValue))
1426 bError = TRUE;
1427 break;
1428 case FILL_DATE:
1429 if (fabs(nVal) > _D_MAX_LONG_)
1430 bError = TRUE;
1431 else
1432 IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1433 break;
1434 default:
1436 // added to avoid warnings
1440 if (nStepValue >= 0)
1442 if (nVal > nMaxValue) // Zielwert erreicht?
1444 nVal = nMaxValue;
1445 bOverflow = TRUE;
1448 else
1450 if (nVal < nMaxValue)
1452 nVal = nMaxValue;
1453 bOverflow = TRUE;
1458 if (bError)
1459 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1460 else if (!bOverflow)
1461 aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1463 if (rInner == nIEnd) break;
1464 if (bPositive) ++rInner; else --rInner;
1466 nProgress += nIMax - nIMin + 1;
1467 rProgress.SetStateOnPercent( nProgress );
1469 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1471 if ( nStepValue >= 0 )
1473 if ( nMaxValue >= (double)LONG_MAX )
1474 nMaxValue = (double)LONG_MAX - 1;
1476 else
1478 if ( nMaxValue <= (double)LONG_MIN )
1479 nMaxValue = (double)LONG_MIN + 1;
1481 String aValue;
1482 if (eCellType == CELLTYPE_STRING)
1483 ((ScStringCell*)pSrcCell)->GetString( aValue );
1484 else
1485 ((ScEditCell*)pSrcCell)->GetString( aValue );
1486 sal_Int32 nStringValue;
1487 USHORT nMinDigits = nArgMinDigits;
1488 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1489 if ( nHeadNoneTail )
1491 double nStartVal = (double)nStringValue;
1492 double nVal = nStartVal;
1493 long nIndex = 0;
1494 BOOL bError = FALSE;
1495 BOOL bOverflow = FALSE;
1497 BOOL bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix(
1498 (sal_Int32)nStartVal));
1500 rInner = nIStart;
1501 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1503 if (!bError && !bOverflow)
1505 switch (eFillCmd)
1507 case FILL_LINEAR:
1509 // #86365# use multiplication instead of repeated addition
1510 // to avoid accumulating rounding errors
1511 nVal = nStartVal;
1512 double nAdd = nStepValue;
1513 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1514 !SubTotal::SafePlus( nVal, nAdd ) )
1515 bError = TRUE;
1517 break;
1518 case FILL_GROWTH:
1519 if (!SubTotal::SafeMult(nVal, nStepValue))
1520 bError = TRUE;
1521 break;
1522 default:
1524 // added to avoid warnings
1528 if (nStepValue >= 0)
1530 if (nVal > nMaxValue) // Zielwert erreicht?
1532 nVal = nMaxValue;
1533 bOverflow = TRUE;
1536 else
1538 if (nVal < nMaxValue)
1540 nVal = nMaxValue;
1541 bOverflow = TRUE;
1546 if (bError)
1547 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1548 else if (!bOverflow)
1550 nStringValue = (sal_Int32)nVal;
1551 String aStr;
1552 if ( nHeadNoneTail < 0 )
1554 aCol[nCol].Insert( static_cast<SCROW>(nRow),
1555 lcl_getSuffixCell( pDocument,
1556 nStringValue, nMinDigits, aValue,
1557 eCellType, bIsOrdinalSuffix ));
1559 else
1561 aStr = aValue;
1562 aStr += lcl_ValueString( nStringValue, nMinDigits );
1563 ScStringCell* pCell = new ScStringCell( aStr );
1564 aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell );
1568 if (rInner == nIEnd) break;
1569 if (bPositive) ++rInner; else --rInner;
1572 nProgress += nIMax - nIMin + 1;
1573 rProgress.SetStateOnPercent( nProgress );
1576 else
1578 nProgress += nIMax - nIMin + 1;
1579 rProgress.SetStateOnPercent( nProgress );
1581 ++nActFormCnt;
1585 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1586 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1587 double nStepValue, double nMaxValue)
1589 ULONG nProgCount;
1590 if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
1591 nProgCount = nCol2 - nCol1 + 1;
1592 else
1593 nProgCount = nRow2 - nRow1 + 1;
1594 nProgCount *= nFillCount;
1595 ScProgress aProgress( pDocument->GetDocumentShell(),
1596 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
1598 bSharedNameInserted = FALSE;
1600 if (eFillCmd == FILL_AUTO)
1601 FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
1602 else
1603 FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1604 eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, TRUE, aProgress);
1606 if (bSharedNameInserted) // Wurde Shared-Name eingefuegt?
1607 pDocument->GetRangeName()->SetSharedMaxIndex(
1608 pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen
1612 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1613 const ScPatternAttr& rAttr, USHORT nFormatNo)
1615 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1616 if (pAutoFormat)
1618 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1619 if (pData)
1621 // ScPatternAttr aPattern(pDocument->GetPool());
1622 // pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument);
1623 ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1628 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1629 USHORT nFormatNo )
1631 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1633 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1634 if (pAutoFormat)
1636 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1637 if (pData)
1639 ScPatternAttr* pPatternAttrs[16];
1640 for (sal_uInt8 i = 0; i < 16; ++i)
1642 pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1643 pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1646 SCCOL nCol = nStartCol;
1647 SCROW nRow = nStartRow;
1648 USHORT nIndex = 0;
1649 // Linke obere Ecke
1650 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1651 // Linke Spalte
1652 if (pData->IsEqualData(4, 8))
1653 AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1654 else
1656 nIndex = 4;
1657 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1659 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1660 if (nIndex == 4)
1661 nIndex = 8;
1662 else
1663 nIndex = 4;
1666 // Linke untere Ecke
1667 nRow = nEndRow;
1668 nIndex = 12;
1669 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1670 // Rechte obere Ecke
1671 nCol = nEndCol;
1672 nRow = nStartRow;
1673 nIndex = 3;
1674 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1675 // Rechte Spalte
1676 if (pData->IsEqualData(7, 11))
1677 AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1678 else
1680 nIndex = 7;
1681 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1683 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1684 if (nIndex == 7)
1685 nIndex = 11;
1686 else
1687 nIndex = 7;
1690 // Rechte untere Ecke
1691 nRow = nEndRow;
1692 nIndex = 15;
1693 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1694 nRow = nStartRow;
1695 nIndex = 1;
1696 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1698 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1699 if (nIndex == 1)
1700 nIndex = 2;
1701 else
1702 nIndex = 1;
1704 // Untere Zeile
1705 nRow = nEndRow;
1706 nIndex = 13;
1707 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1709 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1710 if (nIndex == 13)
1711 nIndex = 14;
1712 else
1713 nIndex = 13;
1715 // Boddy
1716 if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1717 AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1718 else
1720 if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1722 nIndex = 5;
1723 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1725 AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1726 if (nIndex == 5)
1727 nIndex = 6;
1728 else
1729 nIndex = 5;
1732 else
1734 nIndex = 5;
1735 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1737 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1739 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1740 if ((nIndex == 5) || (nIndex == 9))
1742 if (nIndex == 5)
1743 nIndex = 9;
1744 else
1745 nIndex = 5;
1747 else
1749 if (nIndex == 6)
1750 nIndex = 10;
1751 else
1752 nIndex = 6;
1754 } // for nRow
1755 if ((nIndex == 5) || (nIndex == 9))
1756 nIndex = 6;
1757 else
1758 nIndex = 5;
1759 } // for nCol
1760 } // if not equal Column
1761 } // if not all equal
1763 for (sal_uInt8 j = 0; j < 16; ++j)
1764 delete pPatternAttrs[j];
1765 } // if AutoFormatData != NULL
1766 } // if AutoFormat != NULL
1767 } // if ValidColRow
1770 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, USHORT nIndex, ScAutoFormatData& rData)
1772 UINT32 nFormatIndex = GetNumberFormat( nCol, nRow );
1773 ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1774 rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1777 #define LF_LEFT 1
1778 #define LF_TOP 2
1779 #define LF_RIGHT 4
1780 #define LF_BOTTOM 8
1781 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1783 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, USHORT nFlags, USHORT nIndex, ScAutoFormatData& rData)
1785 const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1786 const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1787 const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1788 const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1789 const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1791 SvxBoxItem aBox( ATTR_BORDER );
1792 if (nFlags & LF_LEFT)
1794 if (pLeftBox)
1796 if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1797 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1798 else
1799 aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1801 else
1802 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1804 if (nFlags & LF_TOP)
1806 if (pTopBox)
1808 if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
1809 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1810 else
1811 aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
1813 else
1814 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1816 if (nFlags & LF_RIGHT)
1818 if (pRightBox)
1820 if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
1821 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1822 else
1823 aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
1825 else
1826 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1828 if (nFlags & LF_BOTTOM)
1830 if (pBottomBox)
1832 if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
1833 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1834 else
1835 aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
1837 else
1838 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1840 rData.PutItem( nIndex, aBox );
1843 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
1845 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1847 if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
1849 // Linke obere Ecke
1850 GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
1851 GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
1852 // Linke Spalte
1853 GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
1854 GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
1855 GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
1856 if (nEndRow - nStartRow >= 4)
1857 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
1858 else
1859 rData.CopyItem( 8, 4, ATTR_BORDER );
1860 // Linke untere Ecke
1861 GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
1862 GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
1863 // Rechte obere Ecke
1864 GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
1865 GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
1866 // Rechte Spalte
1867 GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
1868 GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
1869 GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
1870 if (nEndRow - nStartRow >= 4)
1871 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
1872 else
1873 rData.CopyItem( 11, 7, ATTR_BORDER );
1874 // Rechte untere Ecke
1875 GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
1876 GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
1877 // Ober Zeile
1878 GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
1879 GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
1880 GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
1881 if (nEndCol - nStartCol >= 4)
1882 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
1883 else
1884 rData.CopyItem( 2, 1, ATTR_BORDER );
1885 // Untere Zeile
1886 GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
1887 GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
1888 GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
1889 if (nEndCol - nStartCol >= 4)
1890 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
1891 else
1892 rData.CopyItem( 14, 13, ATTR_BORDER );
1893 // Body
1894 GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
1895 GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
1896 GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
1897 GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
1898 GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
1899 if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
1901 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
1902 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
1903 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
1905 else
1907 rData.CopyItem( 6, 5, ATTR_BORDER );
1908 rData.CopyItem( 9, 5, ATTR_BORDER );
1909 rData.CopyItem( 10, 5, ATTR_BORDER );
1915 void ScTable::SetError( SCCOL nCol, SCROW nRow, USHORT nError)
1917 if (ValidColRow(nCol, nRow))
1918 aCol[nCol].SetError( nRow, nError );
1921 void ScTable::UpdateInsertTabAbs(SCTAB nTable)
1923 for (SCCOL i=0; i <= MAXCOL; i++)
1924 aCol[i].UpdateInsertTabAbs(nTable);
1927 //UNUSED2008-05 USHORT ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const
1928 //UNUSED2008-05 {
1929 //UNUSED2008-05 if (ValidColRow(nCol,nRow))
1930 //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow );
1931 //UNUSED2008-05 else
1932 //UNUSED2008-05 return 0;
1933 //UNUSED2008-05 }
1935 BOOL ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, BOOL bInSel,
1936 const ScMarkData& rMark) const
1938 if (rRow == MAXROW+2) // Tabellenende
1940 rRow = 0;
1941 rCol = 0;
1943 else
1945 rRow++;
1946 if (rRow == MAXROW+1)
1948 rCol++;
1949 rRow = 0;
1952 if (rCol == MAXCOL+1)
1953 return TRUE;
1954 else
1956 BOOL bStop = FALSE;
1957 while (!bStop)
1959 if (ValidCol(rCol))
1961 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
1962 if (bStop)
1963 return TRUE;
1964 else /*if (rRow == MAXROW+1) */
1966 rCol++;
1967 rRow = 0;
1970 else
1971 return TRUE;
1974 return FALSE;
1977 void ScTable::RemoveAutoSpellObj()
1979 for (SCCOL i=0; i <= MAXCOL; i++)
1980 aCol[i].RemoveAutoSpellObj();
1983 BOOL ScTable::TestTabRefAbs(SCTAB nTable)
1985 BOOL bRet = FALSE;
1986 for (SCCOL i=0; i <= MAXCOL; i++)
1987 if (aCol[i].TestTabRefAbs(nTable))
1988 bRet = TRUE;
1989 return bRet;
1992 void ScTable::CompileDBFormula()
1994 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
1997 void ScTable::CompileDBFormula( BOOL bCreateFormulaString )
1999 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
2002 void ScTable::CompileNameFormula( BOOL bCreateFormulaString )
2004 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
2007 void ScTable::CompileColRowNameFormula()
2009 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();