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 -----------------------------------------------------
39 #pragma optimize("",off)
40 // sonst Absturz Win beim Fuellen
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>
70 #include "patattr.hxx"
73 #include "globstr.hrc"
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"
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();
103 const sal_Unicode
* p
= aValue
.GetBuffer();
104 xub_StrLen nSign
= (p
[0] == '+' || p
[0] == '-') ? 1 : 0;
105 xub_StrLen nDot
= nLen
, nFirst
= nLen
;
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
!= '-')
129 // if it's a dot, erase the buffer and keep going.
139 // If a dot has been previously encountered, then use the
140 // first numerical segment.
142 aBuf
= aValue
.Copy(0, nFirst
);
145 nVal
= aBuf
.ToInt32();
146 if (nSign
&& p
[0] == '-')
150 *pMinDigits
= i
- nSign
;
157 xub_StrLen nBufLen
= aBuf
.Len();
158 nVal
= aBuf
.ToInt32();
159 aValue
.Erase(nLen
- nBufLen
);
161 *pMinDigits
= nBufLen
;
169 String
lcl_ValueString( sal_Int32 nValue
, USHORT nMinDigits
)
171 if ( nMinDigits
<= 1 )
172 return String::CreateFromInt32( nValue
); // simple case...
175 String aStr
= String::CreateFromInt32( Abs( nValue
) );
176 if ( aStr
.Len() < nMinDigits
)
179 aZero
.Fill( nMinDigits
- aStr
.Len(), '0' );
180 aStr
.Insert( aZero
, 0 );
182 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
184 aStr
.Insert( '-', 0 );
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" );
223 if ( nScFillModeMouseModifier
& KEY_MOD1
)
224 return ; // Ctrl-Taste: Copy
233 nCount
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
239 nCount
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
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
);
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
)
268 long nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
269 long nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
270 long nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
274 nCmpInc
= aDate2
- aDate1
;
279 nCmpInc
= nMDiff
+ 12 * nYDiff
;
282 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
283 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
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
)
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
))
306 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
307 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
310 bVal
= FALSE
; // #50965# kein Datum passt auch nicht
314 if ( eType
== FILL_MONTH
&& ( nCmpInc
% 12 == 0 ) )
325 else // einzelnes Datum -> Tage hochzaehlen
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
);
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
) )
355 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
356 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
363 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
366 GetString(nCol
, nRow
, aStr
);
367 rListData
= (ScUserListData
*)(ScGlobal::GetUserList()->GetData(aStr
));
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
))
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
388 short nFlag1
= lcl_DecompValueString( aStr
, nVal1
, &rMinDigits
);
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
);
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
);
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
) )
423 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
424 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
433 // call DecompValueString to set rMinDigits
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...
450 aName += pRangeName->GetSharedMaxIndex() + 1;
452 aName += nFormulaCounter;
456 ScRangeData *pAktRange = new ScRangeData(
457 pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
458 pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
459 if (!pRangeName->Insert( pAktRange ))
462 bSharedNameInserted = TRUE;
465 pRangeName->SearchName(aName, nIndex);
468 DBG_ERROR("ScTable::FillFormula: Falscher Name");
471 nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
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);
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
);
486 // mit RelRefs unnoetig
487 pDestCell
->UpdateReference(URM_COPY
,
488 ScRange( aAddr
, aAddr
),
489 nDestCol
- pSrcCell
->aPos
.Col(),
490 nDestRow
- pSrcCell
->aPos
.Row(), 0);
492 if ( bLast
&& pDestCell
->GetMatrixFlag() )
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 );
509 DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
514 DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
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
) )
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
);
542 ULONG
& rInner
= bVertical
? nRow
: nCol
; // Schleifenvariablen
543 ULONG
& rOuter
= bVertical
? nCol
: nRow
;
560 nIEnd
= nRow2
+ nFillCount
;
567 nIEnd
= nRow1
- nFillCount
;
579 nIEnd
= nCol2
+ nFillCount
;
586 nIEnd
= nCol1
- nFillCount
;
589 ULONG nIMin
= nIStart
;
591 PutInOrder(nIMin
,nIMax
);
593 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), IDF_AUTOFILL
);
595 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, IDF_AUTOFILL
);
597 ULONG nProgress
= rProgress
.GetState();
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
;
615 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
617 const ScStyleSheet
* pStyleSheet
= NULL
;
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
));
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
);
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
));
651 aCol
[nCol
].ApplyStyleArea( nY1
, nY2
, *pStyleSheet
);
653 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pNewPattern
);
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 ??
665 aCol
[nCol
].ApplyStyle( static_cast<SCROW
>(nRow
), *pStyleSheet
);
667 // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
669 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pNewPattern
);
671 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pSrcPattern
);
674 if (nAtSrc
==nISrcEnd
)
676 if ( nAtSrc
!= nISrcStart
)
677 { // mehr als eine Source-Zelle
693 if (rInner
== nIEnd
) break;
694 if (bPositive
) ++rInner
; else --rInner
;
702 FillDateCmd eDateCmd
;
705 ScUserListData
* pListData
= NULL
;
708 FillAnalyse(static_cast<SCCOL
>(nCol
),nRow1
,
709 static_cast<SCCOL
>(nCol
),nRow2
, eFillCmd
,eDateCmd
,
710 nInc
,nMinDigits
, pListData
,nListIndex
);
712 FillAnalyse(nCol1
,static_cast<SCROW
>(nRow
),
713 nCol2
,static_cast<SCROW
>(nRow
), eFillCmd
,eDateCmd
,
714 nInc
,nMinDigits
, pListData
,nListIndex
);
717 aCol
[nCol
].Resize( aCol
[nCol
].GetCellCount() + nFillCount
);
721 USHORT nListCount
= pListData
->GetSubCount();
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
;
734 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
739 if (nListIndex
>= nListCount
) nListIndex
= 0;
743 if (nListIndex
== 0) nListIndex
= nListCount
;
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
;
758 if ( nScFillModeMouseModifier
& KEY_MOD1
)
760 else if ( bPositive
)
765 ULONG nFormulaCounter
= nActFormCnt
;
767 BOOL bGetCell
= TRUE
;
768 USHORT nCellDigits
= 0;
769 short nHeadNoneTail
= 0;
770 sal_Int32 nStringValue
= 0;
772 ScBaseCell
* pSrcCell
= NULL
;
773 CellType eCellType
= CELLTYPE_NONE
;
774 BOOL bIsOrdinalSuffix
= FALSE
;
777 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
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
) );
788 eCellType
= pSrcCell
->GetCellType();
792 nVal
= ((ScValueCell
*)pSrcCell
)->GetValue();
794 case CELLTYPE_STRING
:
796 if ( eCellType
== CELLTYPE_STRING
)
797 ((ScStringCell
*)pSrcCell
)->GetString( aValue
);
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
));
812 // added to avoid warnings
817 eCellType
= CELLTYPE_NONE
;
822 aCol
[nCol
].Insert(static_cast<SCROW
>(nRow
), new ScValueCell(nVal
+ nDelta
));
824 case CELLTYPE_STRING
:
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
;
834 if ( nHeadNoneTail
< 0 )
836 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
),
837 lcl_getSuffixCell( pDocument
,
838 nNextValue
, nCellDigits
, aValue
,
839 eCellType
, bIsOrdinalSuffix
));
844 aStr
+= lcl_ValueString( nNextValue
, nCellDigits
);
845 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
),
846 new ScStringCell( aStr
));
851 ScAddress
aDestPos( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), nTab
);
854 case CELLTYPE_STRING
:
856 aCol
[nCol
].Insert( aDestPos
.Row(), pSrcCell
->CloneWithoutNote( *pDocument
) );
860 // added to avoid warnings
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
;
875 // added to avoid warnings
879 if (nSource
==nISrcEnd
)
881 if ( nSource
!= nISrcStart
)
882 { // mehr als eine Source-Zelle
883 nSource
= nISrcStart
;
886 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
893 nFormulaCounter
= nActFormCnt
;
907 // Progress in der inneren Schleife nur bei teuren Zellen,
908 // und auch dann nicht fuer jede einzelne
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
);
923 double nEndVal
= (nInc
>=0.0) ? MAXDOUBLE
: -MAXDOUBLE
;
925 FillSeries( static_cast<SCCOL
>(nCol
), nRow1
,
926 static_cast<SCCOL
>(nCol
), nRow2
, nFillCount
, eFillDir
,
927 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, FALSE
,
930 FillSeries( nCol1
, static_cast<SCROW
>(nRow
), nCol2
,
931 static_cast<SCROW
>(nRow
), nFillCount
, eFillDir
,
932 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, FALSE
,
934 nProgress
= rProgress
.GetState();
937 nActFormCnt
+= nMaxFormCnt
;
941 String
ScTable::GetAutoFillPreview( const ScRange
& rSource
, SCCOL nEndX
, SCROW nEndY
)
945 SCCOL nCol1
= rSource
.aStart
.Col();
946 SCROW nRow1
= rSource
.aStart
.Row();
947 SCCOL nCol2
= rSource
.aEnd
.Col();
948 SCROW nRow2
= rSource
.aEnd
.Row();
952 FillDir eFillDir
= FILL_TO_BOTTOM
;
953 if ( nEndX
== nCol2
&& nEndY
== nRow2
) // leer
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
;
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
;
973 eFillDir
= FILL_TO_LEFT
;
975 else // Richtung nicht eindeutig
981 FillDateCmd eDateCmd
;
984 ScUserListData
* pListData
= NULL
;
987 FillAnalyse(nCol1
,nRow1
, nCol2
,nRow2
, eFillCmd
,eDateCmd
, nInc
,nMinDigits
, pListData
,nListIndex
);
989 if ( pListData
) // benutzerdefinierte Liste
991 USHORT nListCount
= pListData
->GetSubCount();
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
) );
1012 nSrcX
= sal::static_int_cast
<SCCOL
>( nSrcX
+ static_cast<SCCOL
>(nPos
) );
1014 ScBaseCell
* pCell
= GetCell( nSrcX
, nSrcY
);
1019 nDelta
= nIndex
/ nSrcCount
;
1021 nDelta
= ( nIndex
- nSrcCount
+ 1 ) / nSrcCount
; // -1 -> -1
1023 CellType eType
= pCell
->GetCellType();
1026 case CELLTYPE_STRING
:
1029 if ( eType
== CELLTYPE_STRING
)
1030 ((ScStringCell
*)pCell
)->GetString( aValue
);
1032 ((ScEditCell
*)pCell
)->GetString( aValue
);
1033 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
1036 USHORT nCellDigits
= 0; // look at each source cell individually
1037 short nFlag
= lcl_DecompValueString( aValue
, nVal
, &nCellDigits
);
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
);
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
;
1058 ULONG nNumFmt
= GetNumberFormat( nSrcX
, nSrcY
);
1059 pDocument
->GetFormatTable()->
1060 GetOutputString( nVal
, nNumFmt
, aValue
, &pColor
);
1066 // added to avoid warnings
1071 else if ( eFillCmd
== FILL_LINEAR
|| eFillCmd
== FILL_DATE
) // Werte
1076 short nHeadNoneTail
= 0;
1077 ScBaseCell
* pCell
= GetCell( nCol1
, nRow1
);
1080 CellType eType
= pCell
->GetCellType();
1083 case CELLTYPE_STRING
:
1086 if ( eType
== CELLTYPE_STRING
)
1087 ((ScStringCell
*)pCell
)->GetString( aValue
);
1089 ((ScEditCell
*)pCell
)->GetString( aValue
);
1090 nHeadNoneTail
= lcl_DecompValueString( aValue
, nVal
);
1091 if ( nHeadNoneTail
)
1092 nStart
= (double)nVal
;
1097 case CELLTYPE_VALUE
:
1098 nStart
= ((ScValueCell
*)pCell
)->GetValue();
1100 case CELLTYPE_FORMULA
:
1101 nStart
= ((ScFormulaCell
*)pCell
)->GetValue();
1109 if ( eFillCmd
== FILL_LINEAR
)
1112 bValueOk
= ( SubTotal::SafeMult( nAdd
, (double) nIndex
) &&
1113 SubTotal::SafePlus( nStart
, nAdd
) );
1118 USHORT nDayOfMonth
= 0;
1124 for (long i
=0; i
<nIndex
; i
++)
1125 IncDate( nStart
, nDayOfMonth
, nInc
, eDateCmd
);
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 );
1140 aValue
+= lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
);
1144 //! Zahlformat je nach Index holen?
1146 ULONG nNumFmt
= GetNumberFormat( nCol1
, nRow1
);
1147 pDocument
->GetFormatTable()->
1148 GetOutputString( nStart
, nNumFmt
, aValue
, &pColor
);
1154 DBG_ERROR("GetAutoFillPreview: falscher Modus");
1161 void ScTable::IncDate(double& rVal
, USHORT
& nDayOfMonth
, double nStep
, FillDateCmd eCmd
)
1163 if (eCmd
== FILL_DAY
)
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
;
1182 DayOfWeek eWeekDay
= aDate
.GetDayOfWeek();
1185 if (eWeekDay
== SATURDAY
)
1187 else if (eWeekDay
== SUNDAY
)
1192 if (eWeekDay
== SATURDAY
)
1194 else if (eWeekDay
== SUNDAY
)
1201 if ( nDayOfMonth
== 0 )
1202 nDayOfMonth
= aDate
.GetDay(); // init
1203 long nMonth
= aDate
.GetMonth();
1204 long nYear
= aDate
.GetYear();
1212 long nYAdd
= (nMonth
-1) / 12;
1213 nMonth
-= nYAdd
* 12;
1221 long nYAdd
= 1 - nMonth
/ 12; // positiv
1222 nMonth
+= nYAdd
* 12;
1227 if ( nYear
< nMinYear
)
1228 aDate
= Date( 1,1, nMinYear
);
1229 else if ( nYear
> nMaxYear
)
1230 aDate
= Date( 31,12, nMaxYear
);
1233 aDate
.SetMonth((USHORT
) nMonth
);
1234 aDate
.SetYear((USHORT
) nYear
);
1235 if ( nDayOfMonth
> 28 )
1236 aDate
.SetDay( Min( aDate
.GetDaysInMonth(), nDayOfMonth
) );
1242 long nYear
= aDate
.GetYear();
1244 if ( nYear
< nMinYear
)
1245 aDate
= Date( 1,1, nMinYear
);
1246 else if ( nYear
> nMaxYear
)
1247 aDate
= Date( 31,12, nMaxYear
);
1249 aDate
.SetYear((USHORT
) nYear
);
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
);
1275 ULONG
& rInner
= bVertical
? nRow
: nCol
; // Schleifenvariablen
1276 ULONG
& rOuter
= bVertical
? nCol
: nRow
;
1285 nFillCount
+= (nRow2
- nRow1
);
1286 if (nFillCount
== 0)
1293 nIStart
= nRow1
+ 1;
1294 nIEnd
= nRow1
+ nFillCount
;
1299 nIStart
= nRow2
- 1;
1300 nIEnd
= nRow2
- nFillCount
;
1305 nFillCount
+= (nCol2
- nCol1
);
1306 if (nFillCount
== 0)
1313 nIStart
= nCol1
+ 1;
1314 nIEnd
= nCol1
+ nFillCount
;
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
);
1329 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), nDel
);
1331 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, nDel
);
1333 ULONG nProgress
= rProgress
.GetState();
1339 ULONG nActFormCnt
= 0;
1340 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
1344 ScBaseCell
* pSrcCell
= aCol
[nCol
].GetCell(static_cast<SCROW
>(nRow
));
1346 if (bVertical
&& bAttribs
)
1347 aCol
[nCol
].Resize( aCol
[nCol
].GetCellCount() + nFillCount
);
1351 const ScPatternAttr
* pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nRow
));
1353 aCol
[nCol
].SetPatternArea( static_cast<SCROW
>(nIMin
),
1354 static_cast<SCROW
>(nIMax
), *pSrcPattern
, TRUE
);
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
);
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
))
1372 ULONG nInd
= nActFormCnt
;
1373 FillFormula(nInd
, bFirst
, (ScFormulaCell
*)pSrcCell
,
1374 static_cast<SCCOL
>(nCol
), nRow
, (rInner
== nIEnd
) );
1376 rProgress
.SetStateOnPercent( ++nProgress
);
1379 else if (eCellType
!= CELLTYPE_NOTE
)
1381 for (rInner
= nIMin
; rInner
<= nIMax
; rInner
++)
1383 if (pDocument
->RowFiltered( rInner
, nTab
))
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
)
1395 if (eCellType
== CELLTYPE_VALUE
)
1396 nStartVal
= ((ScValueCell
*)pSrcCell
)->GetValue();
1398 nStartVal
= ((ScFormulaCell
*)pSrcCell
)->GetValue();
1399 double nVal
= nStartVal
;
1402 BOOL bError
= FALSE
;
1403 BOOL bOverflow
= FALSE
;
1405 USHORT nDayOfMonth
= 0;
1407 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1409 if (!bError
&& !bOverflow
)
1415 // #86365# use multiplication instead of repeated addition
1416 // to avoid accumulating rounding errors
1418 double nAdd
= nStepValue
;
1419 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1420 !SubTotal::SafePlus( nVal
, nAdd
) )
1425 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1429 if (fabs(nVal
) > _D_MAX_LONG_
)
1432 IncDate(nVal
, nDayOfMonth
, nStepValue
, eFillDateCmd
);
1436 // added to avoid warnings
1440 if (nStepValue
>= 0)
1442 if (nVal
> nMaxValue
) // Zielwert erreicht?
1450 if (nVal
< nMaxValue
)
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;
1478 if ( nMaxValue
<= (double)LONG_MIN
)
1479 nMaxValue
= (double)LONG_MIN
+ 1;
1482 if (eCellType
== CELLTYPE_STRING
)
1483 ((ScStringCell
*)pSrcCell
)->GetString( aValue
);
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
;
1494 BOOL bError
= FALSE
;
1495 BOOL bOverflow
= FALSE
;
1497 BOOL bIsOrdinalSuffix
= aValue
.Equals( ScGlobal::GetOrdinalSuffix(
1498 (sal_Int32
)nStartVal
));
1501 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1503 if (!bError
&& !bOverflow
)
1509 // #86365# use multiplication instead of repeated addition
1510 // to avoid accumulating rounding errors
1512 double nAdd
= nStepValue
;
1513 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1514 !SubTotal::SafePlus( nVal
, nAdd
) )
1519 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1524 // added to avoid warnings
1528 if (nStepValue
>= 0)
1530 if (nVal
> nMaxValue
) // Zielwert erreicht?
1538 if (nVal
< nMaxValue
)
1547 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1548 else if (!bOverflow
)
1550 nStringValue
= (sal_Int32
)nVal
;
1552 if ( nHeadNoneTail
< 0 )
1554 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
),
1555 lcl_getSuffixCell( pDocument
,
1556 nStringValue
, nMinDigits
, aValue
,
1557 eCellType
, bIsOrdinalSuffix
));
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
);
1578 nProgress
+= nIMax
- nIMin
+ 1;
1579 rProgress
.SetStateOnPercent( nProgress
);
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
)
1590 if (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
)
1591 nProgCount
= nCol2
- nCol1
+ 1;
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
);
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();
1618 ScAutoFormatData
* pData
= (*pAutoFormat
)[nFormatNo
];
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
,
1631 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
1633 ScAutoFormat
* pAutoFormat
= ScGlobal::GetAutoFormat();
1636 ScAutoFormatData
* pData
= (*pAutoFormat
)[nFormatNo
];
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
;
1650 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1652 if (pData
->IsEqualData(4, 8))
1653 AutoFormatArea(nStartCol
, nStartRow
+ 1, nStartCol
, nEndRow
- 1, *pPatternAttrs
[4], nFormatNo
);
1657 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1659 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1666 // Linke untere Ecke
1669 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1670 // Rechte obere Ecke
1674 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1676 if (pData
->IsEqualData(7, 11))
1677 AutoFormatArea(nEndCol
, nStartRow
+ 1, nEndCol
, nEndRow
- 1, *pPatternAttrs
[7], nFormatNo
);
1681 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1683 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1690 // Rechte untere Ecke
1693 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1696 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1698 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1707 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1709 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
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
);
1720 if ((pData
->IsEqualData(5, 9)) && (pData
->IsEqualData(6, 10)))
1723 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1725 AutoFormatArea(nCol
, nStartRow
+ 1, nCol
, nEndRow
- 1, *pPatternAttrs
[nIndex
], nFormatNo
);
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))
1755 if ((nIndex
== 5) || (nIndex
== 9))
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
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
);
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
)
1796 if (ScHasPriority(pTheBox
->GetLeft(), pLeftBox
->GetRight()))
1797 aBox
.SetLine(pTheBox
->GetLeft(), BOX_LINE_LEFT
);
1799 aBox
.SetLine(pLeftBox
->GetRight(), BOX_LINE_LEFT
);
1802 aBox
.SetLine(pTheBox
->GetLeft(), BOX_LINE_LEFT
);
1804 if (nFlags
& LF_TOP
)
1808 if (ScHasPriority(pTheBox
->GetTop(), pTopBox
->GetBottom()))
1809 aBox
.SetLine(pTheBox
->GetTop(), BOX_LINE_TOP
);
1811 aBox
.SetLine(pTopBox
->GetBottom(), BOX_LINE_TOP
);
1814 aBox
.SetLine(pTheBox
->GetTop(), BOX_LINE_TOP
);
1816 if (nFlags
& LF_RIGHT
)
1820 if (ScHasPriority(pTheBox
->GetRight(), pRightBox
->GetLeft()))
1821 aBox
.SetLine(pTheBox
->GetRight(), BOX_LINE_RIGHT
);
1823 aBox
.SetLine(pRightBox
->GetLeft(), BOX_LINE_RIGHT
);
1826 aBox
.SetLine(pTheBox
->GetRight(), BOX_LINE_RIGHT
);
1828 if (nFlags
& LF_BOTTOM
)
1832 if (ScHasPriority(pTheBox
->GetBottom(), pBottomBox
->GetTop()))
1833 aBox
.SetLine(pTheBox
->GetBottom(), BOX_LINE_BOTTOM
);
1835 aBox
.SetLine(pBottomBox
->GetTop(), BOX_LINE_BOTTOM
);
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))
1850 GetAutoFormatAttr(nStartCol
, nStartRow
, 0, rData
);
1851 GetAutoFormatFrame(nStartCol
, nStartRow
, LF_ALL
, 0, rData
);
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
);
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
);
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
);
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
);
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
);
1884 rData
.CopyItem( 2, 1, ATTR_BORDER
);
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
);
1892 rData
.CopyItem( 14, 13, ATTR_BORDER
);
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
);
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
1929 //UNUSED2008-05 if (ValidColRow(nCol,nRow))
1930 //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow );
1931 //UNUSED2008-05 else
1932 //UNUSED2008-05 return 0;
1935 BOOL
ScTable::GetNextSpellingCell(SCCOL
& rCol
, SCROW
& rRow
, BOOL bInSel
,
1936 const ScMarkData
& rMark
) const
1938 if (rRow
== MAXROW
+2) // Tabellenende
1946 if (rRow
== MAXROW
+1)
1952 if (rCol
== MAXCOL
+1)
1961 bStop
= aCol
[rCol
].GetNextSpellingCell(rRow
, bInSel
, rMark
);
1964 else /*if (rRow == MAXROW+1) */
1977 void ScTable::RemoveAutoSpellObj()
1979 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1980 aCol
[i
].RemoveAutoSpellObj();
1983 BOOL
ScTable::TestTabRefAbs(SCTAB nTable
)
1986 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1987 if (aCol
[i
].TestTabRefAbs(nTable
))
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();