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
)
102 const sal_Unicode
* p
= aValue
.GetBuffer();
105 if ( p
[nNum
] == '-' )
107 while ( p
[nNum
] && CharClass::isAsciiNumeric( p
[nNum
] ) )
110 sal_Unicode cNext
= p
[nNum
]; // 0 if at the end
111 sal_Unicode cLast
= p
[aValue
.Len()-1];
113 // #i5550# If there are numbers at the beginning and the end,
114 // prefer the one at the beginning only if it's followed by a space.
115 // Otherwise, use the number at the end, to enable things like IP addresses.
116 if ( nNum
> nNeg
&& ( cNext
== 0 || cNext
== ' ' || !CharClass::isAsciiNumeric(cLast
) ) )
117 { // number at the beginning
118 nVal
= aValue
.Copy( 0, nNum
).ToInt32();
119 // #60893# any number with a leading zero sets the minimum number of digits
120 if ( p
[nNeg
] == '0' && pMinDigits
&& ( nNum
- nNeg
> *pMinDigits
) )
121 *pMinDigits
= nNum
- nNeg
;
122 aValue
.Erase( 0, nNum
);
128 xub_StrLen nEnd
= nNum
= aValue
.Len() - 1;
129 while ( nNum
&& CharClass::isAsciiNumeric( p
[nNum
] ) )
131 if ( p
[nNum
] == '-' )
136 if ( nNum
< nEnd
- nNeg
)
137 { // number at the end
138 nVal
= aValue
.Copy( nNum
+ 1 ).ToInt32();
139 // #60893# any number with a leading zero sets the minimum number of digits
140 if ( p
[nNum
+1+nNeg
] == '0' && pMinDigits
&& ( nEnd
- nNum
- nNeg
> *pMinDigits
) )
141 *pMinDigits
= nEnd
- nNum
- nNeg
;
142 aValue
.Erase( nNum
+ 1 );
150 String
lcl_ValueString( sal_Int32 nValue
, USHORT nMinDigits
)
152 if ( nMinDigits
<= 1 )
153 return String::CreateFromInt32( nValue
); // simple case...
156 String aStr
= String::CreateFromInt32( Abs( nValue
) );
157 if ( aStr
.Len() < nMinDigits
)
160 aZero
.Fill( nMinDigits
- aStr
.Len(), '0' );
161 aStr
.Insert( aZero
, 0 );
163 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
165 aStr
.Insert( '-', 0 );
170 static ScBaseCell
* lcl_getSuffixCell( ScDocument
* pDocument
, sal_Int32 nValue
,
171 USHORT nDigits
, const String
& rSuffix
, CellType eCellType
,
172 BOOL bIsOrdinalSuffix
)
174 String
aValue( lcl_ValueString( nValue
, nDigits
));
175 if (!bIsOrdinalSuffix
)
176 return new ScStringCell( aValue
+= rSuffix
);
178 String
aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue
));
179 if (eCellType
!= CELLTYPE_EDIT
)
180 return new ScStringCell( aValue
+= aOrdinalSuffix
);
182 EditEngine
aEngine( pDocument
->GetEnginePool() );
183 SfxItemSet aAttr
= aEngine
.GetEmptyItemSet();
184 aAttr
.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT
, EE_CHAR_ESCAPEMENT
));
185 aEngine
.SetText( aValue
);
186 aEngine
.QuickInsertText( aOrdinalSuffix
, ESelection( 0, aValue
.Len(), 0,
187 aValue
.Len() + aOrdinalSuffix
.Len()));
188 aEngine
.QuickSetAttribs( aAttr
, ESelection( 0, aValue
.Len(), 0, aValue
.Len() +
189 aOrdinalSuffix
.Len()));
190 return new ScEditCell( aEngine
.CreateTextObject(), pDocument
, NULL
);
193 void ScTable::FillAnalyse( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
194 FillCmd
& rCmd
, FillDateCmd
& rDateCmd
,
195 double& rInc
, USHORT
& rMinDigits
,
196 ScUserListData
*& rListData
, USHORT
& rListIndex
)
198 DBG_ASSERT( nCol1
==nCol2
|| nRow1
==nRow2
, "FillAnalyse: falscher Bereich" );
204 if ( nScFillModeMouseModifier
& KEY_MOD1
)
205 return ; // Ctrl-Taste: Copy
214 nCount
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
220 nCount
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
226 ScBaseCell
* pFirstCell
= GetCell( nCol
, nRow
);
227 CellType eCellType
= pFirstCell
? pFirstCell
->GetCellType() : CELLTYPE_NONE
;
229 if (eCellType
== CELLTYPE_VALUE
)
231 UINT32 nFormat
= ((const SfxUInt32Item
*)GetAttr(nCol
,nRow
,ATTR_VALUE_FORMAT
))->GetValue();
232 BOOL bDate
= ( pDocument
->GetFormatTable()->GetType(nFormat
) == NUMBERFORMAT_DATE
);
239 Date aNullDate
= *pDocument
->GetFormatTable()->GetNullDate();
240 Date aDate1
= aNullDate
;
241 nVal
= ((ScValueCell
*)pFirstCell
)->GetValue();
242 aDate1
+= (long)nVal
;
243 Date aDate2
= aNullDate
;
244 nVal
= GetValue(nCol
+nAddX
, nRow
+nAddY
);
245 aDate2
+= (long)nVal
;
246 if ( aDate1
!= aDate2
)
249 long nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
250 long nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
251 long nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
255 nCmpInc
= aDate2
- aDate1
;
260 nCmpInc
= nMDiff
+ 12 * nYDiff
;
263 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
264 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
266 for (USHORT i
=1; i
<nCount
&& bVal
; i
++)
268 ScBaseCell
* pCell
= GetCell(nCol
,nRow
);
269 if (pCell
&& pCell
->GetCellType() == CELLTYPE_VALUE
)
271 nVal
= ((ScValueCell
*)pCell
)->GetValue();
272 aDate2
= aNullDate
+ (long) nVal
;
273 if ( eType
== FILL_DAY
)
275 if ( aDate2
-aDate1
!= nCmpInc
)
280 nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
281 nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
282 nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
283 if (nDDiff
|| ( nMDiff
+ 12 * nYDiff
!= nCmpInc
))
287 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
288 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
291 bVal
= FALSE
; // #50965# kein Datum passt auch nicht
295 if ( eType
== FILL_MONTH
&& ( nCmpInc
% 12 == 0 ) )
306 else // einzelnes Datum -> Tage hochzaehlen
317 double nVal1
= ((ScValueCell
*)pFirstCell
)->GetValue();
318 double nVal2
= GetValue(nCol
+nAddX
, nRow
+nAddY
);
319 rInc
= nVal2
- nVal1
;
320 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
321 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
323 for (USHORT i
=1; i
<nCount
&& bVal
; i
++)
325 ScBaseCell
* pCell
= GetCell(nCol
,nRow
);
326 if (pCell
&& pCell
->GetCellType() == CELLTYPE_VALUE
)
328 nVal2
= ((ScValueCell
*)pCell
)->GetValue();
329 double nDiff
= nVal2
- nVal1
;
330 if ( !::rtl::math::approxEqual( nDiff
, rInc
) )
336 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
337 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
344 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
347 GetString(nCol
, nRow
, aStr
);
348 rListData
= (ScUserListData
*)(ScGlobal::GetUserList()->GetData(aStr
));
351 rListData
->GetSubIndex(aStr
, rListIndex
);
352 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
353 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
354 for (USHORT i
=1; i
<nCount
&& rListData
; i
++)
356 GetString(nCol
, nRow
, aStr
);
357 if (!rListData
->GetSubIndex(aStr
, rListIndex
))
359 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
360 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
363 else if ( nCount
> 1 )
365 // pass rMinDigits to all DecompValueString calls
366 // -> longest number defines rMinDigits
369 short nFlag1
= lcl_DecompValueString( aStr
, nVal1
, &rMinDigits
);
373 GetString( nCol
+nAddX
, nRow
+nAddY
, aStr
);
374 short nFlag2
= lcl_DecompValueString( aStr
, nVal2
, &rMinDigits
);
375 if ( nFlag1
== nFlag2
)
377 rInc
= (double)nVal2
- (double)nVal1
;
378 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
379 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
381 for (USHORT i
=1; i
<nCount
&& bVal
; i
++)
383 ScBaseCell
* pCell
= GetCell(nCol
,nRow
);
384 CellType eType
= pCell
? pCell
->GetCellType() : CELLTYPE_NONE
;
385 if ( eType
== CELLTYPE_STRING
|| eType
== CELLTYPE_EDIT
)
387 if ( eType
== CELLTYPE_STRING
)
388 ((ScStringCell
*)pCell
)->GetString( aStr
);
390 ((ScEditCell
*)pCell
)->GetString( aStr
);
391 nFlag2
= lcl_DecompValueString( aStr
, nVal2
, &rMinDigits
);
392 if ( nFlag1
== nFlag2
)
394 double nDiff
= (double)nVal2
- (double)nVal1
;
395 if ( !::rtl::math::approxEqual( nDiff
, rInc
) )
404 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
405 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
414 // call DecompValueString to set rMinDigits
416 lcl_DecompValueString( aStr
, nDummy
, &rMinDigits
);
421 void ScTable::FillFormula(ULONG
& /* nFormulaCounter */, BOOL
/* bFirst */, ScFormulaCell
* pSrcCell
,
422 SCCOL nDestCol
, SCROW nDestRow
, BOOL bLast
)
424 /* USHORT nTokArrLen = pSrcCell->GetTokenArrayLen();
425 if ( nTokArrLen > 15 ) // mehr als =A1 oder =67
427 ScRangeName* pRangeName = pDocument->GetRangeName();
428 String aName("___SC_"); // Wird dieser String veraendert,
429 // auch in document2 EraseNonUsed...
431 aName += pRangeName->GetSharedMaxIndex() + 1;
433 aName += nFormulaCounter;
437 ScRangeData *pAktRange = new ScRangeData(
438 pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
439 pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
440 if (!pRangeName->Insert( pAktRange ))
443 bSharedNameInserted = TRUE;
446 pRangeName->SearchName(aName, nIndex);
449 DBG_ERROR("ScTable::FillFormula: Falscher Name");
452 nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
454 aArr.AddName(nIndex);
455 aArr.AddOpCode(ocStop);
456 ScFormulaCell* pDestCell = new ScFormulaCell
457 (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
458 aCol[nDestCol].Insert(nDestRow, pDestCell);
462 pDocument
->SetNoListening( TRUE
); // noch falsche Referenzen
463 ScAddress
aAddr( nDestCol
, nDestRow
, nTab
);
464 ScFormulaCell
* pDestCell
= new ScFormulaCell( *pSrcCell
, *pDocument
, aAddr
);
465 aCol
[nDestCol
].Insert(nDestRow
, pDestCell
);
467 // mit RelRefs unnoetig
468 pDestCell
->UpdateReference(URM_COPY
,
469 ScRange( aAddr
, aAddr
),
470 nDestCol
- pSrcCell
->aPos
.Col(),
471 nDestRow
- pSrcCell
->aPos
.Row(), 0);
473 if ( bLast
&& pDestCell
->GetMatrixFlag() )
476 if ( pDestCell
->GetMatrixOrigin( aOrg
) )
478 if ( nDestCol
>= aOrg
.Col() && nDestRow
>= aOrg
.Row() )
480 ScBaseCell
* pOrgCell
= pDocument
->GetCell( aOrg
);
481 if ( pOrgCell
&& pOrgCell
->GetCellType() == CELLTYPE_FORMULA
482 && ((ScFormulaCell
*)pOrgCell
)->GetMatrixFlag() == MM_FORMULA
)
484 ((ScFormulaCell
*)pOrgCell
)->SetMatColsRows(
485 nDestCol
- aOrg
.Col() + 1,
486 nDestRow
- aOrg
.Row() + 1 );
490 DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
495 DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
500 DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
503 pDocument
->SetNoListening( FALSE
);
504 pDestCell
->StartListeningTo( pDocument
);
508 void ScTable::FillAuto( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
509 ULONG nFillCount
, FillDir eFillDir
, ScProgress
& rProgress
)
511 if ( (nFillCount
== 0) || !ValidColRow(nCol1
, nRow1
) || !ValidColRow(nCol2
, nRow2
) )
515 // Richtung auswerten
518 BOOL bVertical
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
);
519 BOOL bPositive
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_RIGHT
);
523 ULONG
& rInner
= bVertical
? nRow
: nCol
; // Schleifenvariablen
524 ULONG
& rOuter
= bVertical
? nCol
: nRow
;
541 nIEnd
= nRow2
+ nFillCount
;
548 nIEnd
= nRow1
- nFillCount
;
560 nIEnd
= nCol2
+ nFillCount
;
567 nIEnd
= nCol1
- nFillCount
;
570 ULONG nIMin
= nIStart
;
572 PutInOrder(nIMin
,nIMax
);
574 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), IDF_AUTOFILL
);
576 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, IDF_AUTOFILL
);
578 ULONG nProgress
= rProgress
.GetState();
584 ULONG nActFormCnt
= 0;
585 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
587 ULONG nMaxFormCnt
= 0; // fuer Formeln
589 // Attributierung uebertragen
591 const ScPatternAttr
* pSrcPattern
= NULL
;
592 ULONG nAtSrc
= nISrcStart
;
593 ScPatternAttr
* pNewPattern
= NULL
;
594 BOOL bGetPattern
= TRUE
;
596 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
598 const ScStyleSheet
* pStyleSheet
= NULL
;
603 if (bVertical
) // rInner&:=nRow, rOuter&:=nCol
604 pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nAtSrc
));
605 else // rInner&:=nCol, rOuter&:=nRow
606 pSrcPattern
= aCol
[nAtSrc
].GetPattern(static_cast<SCROW
>(nRow
));
608 pStyleSheet
= pSrcPattern
->GetStyleSheet();
609 // Merge/Mergeflag nicht uebernehmen,
610 const SfxItemSet
& rSet
= pSrcPattern
->GetItemSet();
611 if ( rSet
.GetItemState(ATTR_MERGE
, FALSE
) == SFX_ITEM_SET
612 || rSet
.GetItemState(ATTR_MERGE_FLAG
, FALSE
) == SFX_ITEM_SET
)
614 pNewPattern
= new ScPatternAttr( *pSrcPattern
);
615 SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
616 rNewSet
.ClearItem(ATTR_MERGE
);
617 rNewSet
.ClearItem(ATTR_MERGE_FLAG
);
623 if ( bVertical
&& nISrcStart
== nISrcEnd
)
625 // Attribute komplett am Stueck setzen
626 if (pNewPattern
|| pSrcPattern
!= pDocument
->GetDefPattern())
628 // Default steht schon da (DeleteArea)
629 SCROW nY1
= static_cast<SCROW
>(Min( nIStart
, nIEnd
));
630 SCROW nY2
= static_cast<SCROW
>(Max( nIStart
, nIEnd
));
632 aCol
[nCol
].ApplyStyleArea( nY1
, nY2
, *pStyleSheet
);
634 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pNewPattern
);
636 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pSrcPattern
);
638 break; // Schleife abbrechen
641 if ( pSrcPattern
!= aCol
[nCol
].GetPattern( static_cast<SCROW
>(nRow
) ) )
643 // Vorlage auch uebernehmen
644 //! am AttrArray mit ApplyPattern zusammenfassen ??
646 aCol
[nCol
].ApplyStyle( static_cast<SCROW
>(nRow
), *pStyleSheet
);
648 // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
650 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pNewPattern
);
652 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pSrcPattern
);
655 if (nAtSrc
==nISrcEnd
)
657 if ( nAtSrc
!= nISrcStart
)
658 { // mehr als eine Source-Zelle
674 if (rInner
== nIEnd
) break;
675 if (bPositive
) ++rInner
; else --rInner
;
683 FillDateCmd eDateCmd
;
686 ScUserListData
* pListData
= NULL
;
689 FillAnalyse(static_cast<SCCOL
>(nCol
),nRow1
,
690 static_cast<SCCOL
>(nCol
),nRow2
, eFillCmd
,eDateCmd
,
691 nInc
,nMinDigits
, pListData
,nListIndex
);
693 FillAnalyse(nCol1
,static_cast<SCROW
>(nRow
),
694 nCol2
,static_cast<SCROW
>(nRow
), eFillCmd
,eDateCmd
,
695 nInc
,nMinDigits
, pListData
,nListIndex
);
698 aCol
[nCol
].Resize( aCol
[nCol
].GetCellCount() + nFillCount
);
702 USHORT nListCount
= pListData
->GetSubCount();
705 // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
706 ULONG nSub
= nISrcStart
- nISrcEnd
;
707 for (ULONG i
=0; i
<nSub
; i
++)
709 if (nListIndex
== 0) nListIndex
= nListCount
;
715 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
720 if (nListIndex
>= nListCount
) nListIndex
= 0;
724 if (nListIndex
== 0) nListIndex
= nListCount
;
727 aCol
[nCol
].Insert(static_cast<SCROW
>(nRow
), new ScStringCell(pListData
->GetSubStr(nListIndex
)));
729 if (rInner
== nIEnd
) break;
730 if (bPositive
) ++rInner
; else --rInner
;
732 nProgress
+= nIMax
- nIMin
+ 1;
733 rProgress
.SetStateOnPercent( nProgress
);
735 else if (eFillCmd
== FILL_SIMPLE
) // Auffuellen mit Muster
737 ULONG nSource
= nISrcStart
;
739 if ( nScFillModeMouseModifier
& KEY_MOD1
)
741 else if ( bPositive
)
746 ULONG nFormulaCounter
= nActFormCnt
;
748 BOOL bGetCell
= TRUE
;
749 USHORT nCellDigits
= 0;
750 short nHeadNoneTail
= 0;
751 sal_Int32 nStringValue
= 0;
753 ScBaseCell
* pSrcCell
= NULL
;
754 CellType eCellType
= CELLTYPE_NONE
;
755 BOOL bIsOrdinalSuffix
= FALSE
;
758 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
762 if (bVertical
) // rInner&:=nRow, rOuter&:=nCol
763 pSrcCell
= aCol
[nCol
].GetCell( static_cast<SCROW
>(nSource
) );
764 else // rInner&:=nCol, rOuter&:=nRow
765 pSrcCell
= aCol
[nSource
].GetCell( static_cast<SCROW
>(nRow
) );
769 eCellType
= pSrcCell
->GetCellType();
773 nVal
= ((ScValueCell
*)pSrcCell
)->GetValue();
775 case CELLTYPE_STRING
:
777 if ( eCellType
== CELLTYPE_STRING
)
778 ((ScStringCell
*)pSrcCell
)->GetString( aValue
);
780 ((ScEditCell
*)pSrcCell
)->GetString( aValue
);
781 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
783 nCellDigits
= 0; // look at each source cell individually
784 nHeadNoneTail
= lcl_DecompValueString(
785 aValue
, nStringValue
, &nCellDigits
);
787 bIsOrdinalSuffix
= aValue
.Equals(
788 ScGlobal::GetOrdinalSuffix( nStringValue
));
793 // added to avoid warnings
798 eCellType
= CELLTYPE_NONE
;
803 aCol
[nCol
].Insert(static_cast<SCROW
>(nRow
), new ScValueCell(nVal
+ nDelta
));
805 case CELLTYPE_STRING
:
809 // #i48009# with the "nStringValue+(long)nDelta" expression within the
810 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
811 // so nNextValue is now calculated ahead.
812 sal_Int32 nNextValue
= nStringValue
+(sal_Int32
)nDelta
;
815 if ( nHeadNoneTail
< 0 )
817 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
),
818 lcl_getSuffixCell( pDocument
,
819 nNextValue
, nCellDigits
, aValue
,
820 eCellType
, bIsOrdinalSuffix
));
825 aStr
+= lcl_ValueString( nNextValue
, nCellDigits
);
826 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
),
827 new ScStringCell( aStr
));
832 ScAddress
aDestPos( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), nTab
);
835 case CELLTYPE_STRING
:
837 aCol
[nCol
].Insert( aDestPos
.Row(), pSrcCell
->CloneWithoutNote( *pDocument
) );
841 // added to avoid warnings
846 case CELLTYPE_FORMULA
:
847 FillFormula( nFormulaCounter
, bFirst
,
848 (ScFormulaCell
*) pSrcCell
,
849 static_cast<SCCOL
>(nCol
),
850 static_cast<SCROW
>(nRow
), (rInner
== nIEnd
) );
851 if (nFormulaCounter
- nActFormCnt
> nMaxFormCnt
)
852 nMaxFormCnt
= nFormulaCounter
- nActFormCnt
;
856 // added to avoid warnings
860 if (nSource
==nISrcEnd
)
862 if ( nSource
!= nISrcStart
)
863 { // mehr als eine Source-Zelle
864 nSource
= nISrcStart
;
867 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
874 nFormulaCounter
= nActFormCnt
;
888 // Progress in der inneren Schleife nur bei teuren Zellen,
889 // und auch dann nicht fuer jede einzelne
892 if ( eCellType
== CELLTYPE_FORMULA
|| eCellType
== CELLTYPE_EDIT
)
893 rProgress
.SetStateOnPercent( nProgress
);
895 if (rInner
== nIEnd
) break;
896 if (bPositive
) ++rInner
; else --rInner
;
898 rProgress
.SetStateOnPercent( nProgress
);
904 double nEndVal
= (nInc
>=0.0) ? MAXDOUBLE
: -MAXDOUBLE
;
906 FillSeries( static_cast<SCCOL
>(nCol
), nRow1
,
907 static_cast<SCCOL
>(nCol
), nRow2
, nFillCount
, eFillDir
,
908 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, FALSE
,
911 FillSeries( nCol1
, static_cast<SCROW
>(nRow
), nCol2
,
912 static_cast<SCROW
>(nRow
), nFillCount
, eFillDir
,
913 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, FALSE
,
915 nProgress
= rProgress
.GetState();
918 nActFormCnt
+= nMaxFormCnt
;
922 String
ScTable::GetAutoFillPreview( const ScRange
& rSource
, SCCOL nEndX
, SCROW nEndY
)
926 SCCOL nCol1
= rSource
.aStart
.Col();
927 SCROW nRow1
= rSource
.aStart
.Row();
928 SCCOL nCol2
= rSource
.aEnd
.Col();
929 SCROW nRow2
= rSource
.aEnd
.Row();
933 FillDir eFillDir
= FILL_TO_BOTTOM
;
934 if ( nEndX
== nCol2
&& nEndY
== nRow2
) // leer
936 else if ( nEndX
== nCol2
) // nach oben/unten
938 nEndX
= nCol2
= nCol1
; // nur erste Spalte ansehen
939 nSrcCount
= nRow2
- nRow1
+ 1;
940 nIndex
= ((long)nEndY
) - nRow1
; // kann negativ werden
941 if ( nEndY
>= nRow1
)
942 eFillDir
= FILL_TO_BOTTOM
;
944 eFillDir
= FILL_TO_TOP
;
946 else if ( nEndY
== nRow2
) // nach links/rechts
948 nEndY
= nRow2
= nRow1
; // nur erste Zeile ansehen
949 nSrcCount
= nCol2
- nCol1
+ 1;
950 nIndex
= ((long)nEndX
) - nCol1
; // kann negativ werden
951 if ( nEndX
>= nCol1
)
952 eFillDir
= FILL_TO_RIGHT
;
954 eFillDir
= FILL_TO_LEFT
;
956 else // Richtung nicht eindeutig
962 FillDateCmd eDateCmd
;
965 ScUserListData
* pListData
= NULL
;
968 FillAnalyse(nCol1
,nRow1
, nCol2
,nRow2
, eFillCmd
,eDateCmd
, nInc
,nMinDigits
, pListData
,nListIndex
);
970 if ( pListData
) // benutzerdefinierte Liste
972 USHORT nListCount
= pListData
->GetSubCount();
975 ULONG nSub
= nSrcCount
- 1; // nListIndex ist vom letzten Source-Eintrag
976 while ( nIndex
< sal::static_int_cast
<long>(nSub
) )
977 nIndex
+= nListCount
;
978 ULONG nPos
= ( nListIndex
+ nIndex
- nSub
) % nListCount
;
979 aValue
= pListData
->GetSubStr(sal::static_int_cast
<USHORT
>(nPos
));
982 else if ( eFillCmd
== FILL_SIMPLE
) // Auffuellen mit Muster
984 long nPosIndex
= nIndex
;
985 while ( nPosIndex
< 0 )
986 nPosIndex
+= nSrcCount
;
987 ULONG nPos
= nPosIndex
% nSrcCount
;
990 if ( eFillDir
== FILL_TO_TOP
|| eFillDir
== FILL_TO_BOTTOM
)
991 nSrcY
= sal::static_int_cast
<SCROW
>( nSrcY
+ static_cast<SCROW
>(nPos
) );
993 nSrcX
= sal::static_int_cast
<SCCOL
>( nSrcX
+ static_cast<SCCOL
>(nPos
) );
995 ScBaseCell
* pCell
= GetCell( nSrcX
, nSrcY
);
1000 nDelta
= nIndex
/ nSrcCount
;
1002 nDelta
= ( nIndex
- nSrcCount
+ 1 ) / nSrcCount
; // -1 -> -1
1004 CellType eType
= pCell
->GetCellType();
1007 case CELLTYPE_STRING
:
1010 if ( eType
== CELLTYPE_STRING
)
1011 ((ScStringCell
*)pCell
)->GetString( aValue
);
1013 ((ScEditCell
*)pCell
)->GetString( aValue
);
1014 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
1017 USHORT nCellDigits
= 0; // look at each source cell individually
1018 short nFlag
= lcl_DecompValueString( aValue
, nVal
, &nCellDigits
);
1021 if (aValue
.Equals( ScGlobal::GetOrdinalSuffix( nVal
)))
1022 aValue
= ScGlobal::GetOrdinalSuffix( nVal
+ nDelta
);
1024 aValue
.Insert( lcl_ValueString( nVal
+ nDelta
, nCellDigits
), 0 );
1026 else if ( nFlag
> 0 )
1027 aValue
+= lcl_ValueString( nVal
+ nDelta
, nCellDigits
);
1031 case CELLTYPE_VALUE
:
1033 // dabei kann's keinen Ueberlauf geben...
1034 double nVal
= ((ScValueCell
*)pCell
)->GetValue();
1035 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
1036 nVal
+= (double) nDelta
;
1039 ULONG nNumFmt
= GetNumberFormat( nSrcX
, nSrcY
);
1040 pDocument
->GetFormatTable()->
1041 GetOutputString( nVal
, nNumFmt
, aValue
, &pColor
);
1047 // added to avoid warnings
1052 else if ( eFillCmd
== FILL_LINEAR
|| eFillCmd
== FILL_DATE
) // Werte
1057 short nHeadNoneTail
= 0;
1058 ScBaseCell
* pCell
= GetCell( nCol1
, nRow1
);
1061 CellType eType
= pCell
->GetCellType();
1064 case CELLTYPE_STRING
:
1067 if ( eType
== CELLTYPE_STRING
)
1068 ((ScStringCell
*)pCell
)->GetString( aValue
);
1070 ((ScEditCell
*)pCell
)->GetString( aValue
);
1071 nHeadNoneTail
= lcl_DecompValueString( aValue
, nVal
);
1072 if ( nHeadNoneTail
)
1073 nStart
= (double)nVal
;
1078 case CELLTYPE_VALUE
:
1079 nStart
= ((ScValueCell
*)pCell
)->GetValue();
1081 case CELLTYPE_FORMULA
:
1082 nStart
= ((ScFormulaCell
*)pCell
)->GetValue();
1090 if ( eFillCmd
== FILL_LINEAR
)
1093 bValueOk
= ( SubTotal::SafeMult( nAdd
, (double) nIndex
) &&
1094 SubTotal::SafePlus( nStart
, nAdd
) );
1099 USHORT nDayOfMonth
= 0;
1105 for (long i
=0; i
<nIndex
; i
++)
1106 IncDate( nStart
, nDayOfMonth
, nInc
, eDateCmd
);
1111 if ( nHeadNoneTail
)
1113 if ( nHeadNoneTail
< 0 )
1115 if (aValue
.Equals( ScGlobal::GetOrdinalSuffix( nVal
)))
1116 aValue
= ScGlobal::GetOrdinalSuffix( (sal_Int32
)nStart
);
1118 aValue
.Insert( lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
), 0 );
1121 aValue
+= lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
);
1125 //! Zahlformat je nach Index holen?
1127 ULONG nNumFmt
= GetNumberFormat( nCol1
, nRow1
);
1128 pDocument
->GetFormatTable()->
1129 GetOutputString( nStart
, nNumFmt
, aValue
, &pColor
);
1135 DBG_ERROR("GetAutoFillPreview: falscher Modus");
1142 void ScTable::IncDate(double& rVal
, USHORT
& nDayOfMonth
, double nStep
, FillDateCmd eCmd
)
1144 if (eCmd
== FILL_DAY
)
1150 // class Date Grenzen
1151 const USHORT nMinYear
= 1583;
1152 const USHORT nMaxYear
= 9956;
1154 long nInc
= (long) nStep
; // nach oben/unten begrenzen ?
1155 Date aNullDate
= *pDocument
->GetFormatTable()->GetNullDate();
1156 Date aDate
= aNullDate
;
1157 aDate
+= (long)rVal
;
1163 DayOfWeek eWeekDay
= aDate
.GetDayOfWeek();
1166 if (eWeekDay
== SATURDAY
)
1168 else if (eWeekDay
== SUNDAY
)
1173 if (eWeekDay
== SATURDAY
)
1175 else if (eWeekDay
== SUNDAY
)
1182 if ( nDayOfMonth
== 0 )
1183 nDayOfMonth
= aDate
.GetDay(); // init
1184 long nMonth
= aDate
.GetMonth();
1185 long nYear
= aDate
.GetYear();
1193 long nYAdd
= (nMonth
-1) / 12;
1194 nMonth
-= nYAdd
* 12;
1202 long nYAdd
= 1 - nMonth
/ 12; // positiv
1203 nMonth
+= nYAdd
* 12;
1208 if ( nYear
< nMinYear
)
1209 aDate
= Date( 1,1, nMinYear
);
1210 else if ( nYear
> nMaxYear
)
1211 aDate
= Date( 31,12, nMaxYear
);
1214 aDate
.SetMonth((USHORT
) nMonth
);
1215 aDate
.SetYear((USHORT
) nYear
);
1216 if ( nDayOfMonth
> 28 )
1217 aDate
.SetDay( Min( aDate
.GetDaysInMonth(), nDayOfMonth
) );
1223 long nYear
= aDate
.GetYear();
1225 if ( nYear
< nMinYear
)
1226 aDate
= Date( 1,1, nMinYear
);
1227 else if ( nYear
> nMaxYear
)
1228 aDate
= Date( 31,12, nMaxYear
);
1230 aDate
.SetYear((USHORT
) nYear
);
1235 // added to avoid warnings
1239 rVal
= aDate
- aNullDate
;
1242 void ScTable::FillSeries( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1243 ULONG nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
1244 double nStepValue
, double nMaxValue
, USHORT nArgMinDigits
,
1245 BOOL bAttribs
, ScProgress
& rProgress
)
1248 // Richtung auswerten
1251 BOOL bVertical
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
);
1252 BOOL bPositive
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_RIGHT
);
1256 ULONG
& rInner
= bVertical
? nRow
: nCol
; // Schleifenvariablen
1257 ULONG
& rOuter
= bVertical
? nCol
: nRow
;
1266 nFillCount
+= (nRow2
- nRow1
);
1267 if (nFillCount
== 0)
1274 nIStart
= nRow1
+ 1;
1275 nIEnd
= nRow1
+ nFillCount
;
1280 nIStart
= nRow2
- 1;
1281 nIEnd
= nRow2
- nFillCount
;
1286 nFillCount
+= (nCol2
- nCol1
);
1287 if (nFillCount
== 0)
1294 nIStart
= nCol1
+ 1;
1295 nIEnd
= nCol1
+ nFillCount
;
1300 nIStart
= nCol2
- 1;
1301 nIEnd
= nCol2
- nFillCount
;
1305 ULONG nIMin
= nIStart
;
1306 ULONG nIMax
= nIEnd
;
1307 PutInOrder(nIMin
,nIMax
);
1308 USHORT nDel
= bAttribs
? IDF_AUTOFILL
: (IDF_AUTOFILL
& IDF_CONTENTS
);
1310 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), nDel
);
1312 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, nDel
);
1314 ULONG nProgress
= rProgress
.GetState();
1320 ULONG nActFormCnt
= 0;
1321 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
1325 ScBaseCell
* pSrcCell
= aCol
[nCol
].GetCell(static_cast<SCROW
>(nRow
));
1327 if (bVertical
&& bAttribs
)
1328 aCol
[nCol
].Resize( aCol
[nCol
].GetCellCount() + nFillCount
);
1332 const ScPatternAttr
* pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nRow
));
1334 aCol
[nCol
].SetPatternArea( static_cast<SCROW
>(nIMin
),
1335 static_cast<SCROW
>(nIMax
), *pSrcPattern
, TRUE
);
1337 for (SCCOL nAtCol
= static_cast<SCCOL
>(nIMin
); nAtCol
<= sal::static_int_cast
<SCCOL
>(nIMax
); nAtCol
++)
1338 aCol
[nAtCol
].SetPattern(static_cast<SCROW
>(nRow
), *pSrcPattern
, TRUE
);
1343 CellType eCellType
= pSrcCell
->GetCellType();
1345 if (eFillCmd
== FILL_SIMPLE
) // kopieren
1347 if (eCellType
== CELLTYPE_FORMULA
)
1349 for (rInner
= nIMin
; rInner
<= nIMax
; rInner
++)
1351 if (pDocument
->RowFiltered( rInner
, nTab
))
1353 ULONG nInd
= nActFormCnt
;
1354 FillFormula(nInd
, bFirst
, (ScFormulaCell
*)pSrcCell
,
1355 static_cast<SCCOL
>(nCol
), nRow
, (rInner
== nIEnd
) );
1357 rProgress
.SetStateOnPercent( ++nProgress
);
1360 else if (eCellType
!= CELLTYPE_NOTE
)
1362 for (rInner
= nIMin
; rInner
<= nIMax
; rInner
++)
1364 if (pDocument
->RowFiltered( rInner
, nTab
))
1366 ScAddress
aDestPos( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), nTab
);
1367 aCol
[nCol
].Insert( aDestPos
.Row(), pSrcCell
->CloneWithoutNote( *pDocument
) );
1369 nProgress
+= nIMax
- nIMin
+ 1;
1370 rProgress
.SetStateOnPercent( nProgress
);
1373 else if (eCellType
== CELLTYPE_VALUE
|| eCellType
== CELLTYPE_FORMULA
)
1376 if (eCellType
== CELLTYPE_VALUE
)
1377 nStartVal
= ((ScValueCell
*)pSrcCell
)->GetValue();
1379 nStartVal
= ((ScFormulaCell
*)pSrcCell
)->GetValue();
1380 double nVal
= nStartVal
;
1383 BOOL bError
= FALSE
;
1384 BOOL bOverflow
= FALSE
;
1386 USHORT nDayOfMonth
= 0;
1388 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1390 if (!bError
&& !bOverflow
)
1396 // #86365# use multiplication instead of repeated addition
1397 // to avoid accumulating rounding errors
1399 double nAdd
= nStepValue
;
1400 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1401 !SubTotal::SafePlus( nVal
, nAdd
) )
1406 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1410 if (fabs(nVal
) > _D_MAX_LONG_
)
1413 IncDate(nVal
, nDayOfMonth
, nStepValue
, eFillDateCmd
);
1417 // added to avoid warnings
1421 if (nStepValue
>= 0)
1423 if (nVal
> nMaxValue
) // Zielwert erreicht?
1431 if (nVal
< nMaxValue
)
1440 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1441 else if (!bOverflow
)
1442 aCol
[nCol
].SetValue(static_cast<SCROW
>(nRow
), nVal
);
1444 if (rInner
== nIEnd
) break;
1445 if (bPositive
) ++rInner
; else --rInner
;
1447 nProgress
+= nIMax
- nIMin
+ 1;
1448 rProgress
.SetStateOnPercent( nProgress
);
1450 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
1452 if ( nStepValue
>= 0 )
1454 if ( nMaxValue
>= (double)LONG_MAX
)
1455 nMaxValue
= (double)LONG_MAX
- 1;
1459 if ( nMaxValue
<= (double)LONG_MIN
)
1460 nMaxValue
= (double)LONG_MIN
+ 1;
1463 if (eCellType
== CELLTYPE_STRING
)
1464 ((ScStringCell
*)pSrcCell
)->GetString( aValue
);
1466 ((ScEditCell
*)pSrcCell
)->GetString( aValue
);
1467 sal_Int32 nStringValue
;
1468 USHORT nMinDigits
= nArgMinDigits
;
1469 short nHeadNoneTail
= lcl_DecompValueString( aValue
, nStringValue
, &nMinDigits
);
1470 if ( nHeadNoneTail
)
1472 double nStartVal
= (double)nStringValue
;
1473 double nVal
= nStartVal
;
1475 BOOL bError
= FALSE
;
1476 BOOL bOverflow
= FALSE
;
1478 BOOL bIsOrdinalSuffix
= aValue
.Equals( ScGlobal::GetOrdinalSuffix(
1479 (sal_Int32
)nStartVal
));
1482 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1484 if (!bError
&& !bOverflow
)
1490 // #86365# use multiplication instead of repeated addition
1491 // to avoid accumulating rounding errors
1493 double nAdd
= nStepValue
;
1494 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1495 !SubTotal::SafePlus( nVal
, nAdd
) )
1500 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1505 // added to avoid warnings
1509 if (nStepValue
>= 0)
1511 if (nVal
> nMaxValue
) // Zielwert erreicht?
1519 if (nVal
< nMaxValue
)
1528 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1529 else if (!bOverflow
)
1531 nStringValue
= (sal_Int32
)nVal
;
1533 if ( nHeadNoneTail
< 0 )
1535 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
),
1536 lcl_getSuffixCell( pDocument
,
1537 nStringValue
, nMinDigits
, aValue
,
1538 eCellType
, bIsOrdinalSuffix
));
1543 aStr
+= lcl_ValueString( nStringValue
, nMinDigits
);
1544 ScStringCell
* pCell
= new ScStringCell( aStr
);
1545 aCol
[nCol
].Insert( static_cast<SCROW
>(nRow
), pCell
);
1549 if (rInner
== nIEnd
) break;
1550 if (bPositive
) ++rInner
; else --rInner
;
1553 nProgress
+= nIMax
- nIMin
+ 1;
1554 rProgress
.SetStateOnPercent( nProgress
);
1559 nProgress
+= nIMax
- nIMin
+ 1;
1560 rProgress
.SetStateOnPercent( nProgress
);
1566 void ScTable::Fill( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1567 ULONG nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
1568 double nStepValue
, double nMaxValue
)
1571 if (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
)
1572 nProgCount
= nCol2
- nCol1
+ 1;
1574 nProgCount
= nRow2
- nRow1
+ 1;
1575 nProgCount
*= nFillCount
;
1576 ScProgress
aProgress( pDocument
->GetDocumentShell(),
1577 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS
), nProgCount
);
1579 bSharedNameInserted
= FALSE
;
1581 if (eFillCmd
== FILL_AUTO
)
1582 FillAuto(nCol1
, nRow1
, nCol2
, nRow2
, nFillCount
, eFillDir
, aProgress
);
1584 FillSeries(nCol1
, nRow1
, nCol2
, nRow2
, nFillCount
, eFillDir
,
1585 eFillCmd
, eFillDateCmd
, nStepValue
, nMaxValue
, 0, TRUE
, aProgress
);
1587 if (bSharedNameInserted
) // Wurde Shared-Name eingefuegt?
1588 pDocument
->GetRangeName()->SetSharedMaxIndex(
1589 pDocument
->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen
1593 void ScTable::AutoFormatArea(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1594 const ScPatternAttr
& rAttr
, USHORT nFormatNo
)
1596 ScAutoFormat
* pAutoFormat
= ScGlobal::GetAutoFormat();
1599 ScAutoFormatData
* pData
= (*pAutoFormat
)[nFormatNo
];
1602 // ScPatternAttr aPattern(pDocument->GetPool());
1603 // pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument);
1604 ApplyPatternArea(nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
);
1609 void ScTable::AutoFormat( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1612 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
1614 ScAutoFormat
* pAutoFormat
= ScGlobal::GetAutoFormat();
1617 ScAutoFormatData
* pData
= (*pAutoFormat
)[nFormatNo
];
1620 ScPatternAttr
* pPatternAttrs
[16];
1621 for (sal_uInt8 i
= 0; i
< 16; ++i
)
1623 pPatternAttrs
[i
] = new ScPatternAttr(pDocument
->GetPool());
1624 pData
->FillToItemSet(i
, pPatternAttrs
[i
]->GetItemSet(), *pDocument
);
1627 SCCOL nCol
= nStartCol
;
1628 SCROW nRow
= nStartRow
;
1631 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1633 if (pData
->IsEqualData(4, 8))
1634 AutoFormatArea(nStartCol
, nStartRow
+ 1, nStartCol
, nEndRow
- 1, *pPatternAttrs
[4], nFormatNo
);
1638 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1640 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1647 // Linke untere Ecke
1650 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1651 // Rechte obere Ecke
1655 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1657 if (pData
->IsEqualData(7, 11))
1658 AutoFormatArea(nEndCol
, nStartRow
+ 1, nEndCol
, nEndRow
- 1, *pPatternAttrs
[7], nFormatNo
);
1662 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1664 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1671 // Rechte untere Ecke
1674 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1677 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1679 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1688 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1690 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1697 if ((pData
->IsEqualData(5, 6)) && (pData
->IsEqualData(9, 10)) && (pData
->IsEqualData(5, 9)))
1698 AutoFormatArea(nStartCol
+ 1, nStartRow
+ 1, nEndCol
-1, nEndRow
- 1, *pPatternAttrs
[5], nFormatNo
);
1701 if ((pData
->IsEqualData(5, 9)) && (pData
->IsEqualData(6, 10)))
1704 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1706 AutoFormatArea(nCol
, nStartRow
+ 1, nCol
, nEndRow
- 1, *pPatternAttrs
[nIndex
], nFormatNo
);
1716 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1718 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1720 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1721 if ((nIndex
== 5) || (nIndex
== 9))
1736 if ((nIndex
== 5) || (nIndex
== 9))
1741 } // if not equal Column
1742 } // if not all equal
1744 for (sal_uInt8 j
= 0; j
< 16; ++j
)
1745 delete pPatternAttrs
[j
];
1746 } // if AutoFormatData != NULL
1747 } // if AutoFormat != NULL
1751 void ScTable::GetAutoFormatAttr(SCCOL nCol
, SCROW nRow
, USHORT nIndex
, ScAutoFormatData
& rData
)
1753 UINT32 nFormatIndex
= GetNumberFormat( nCol
, nRow
);
1754 ScNumFormatAbbrev
aNumFormat( nFormatIndex
, *pDocument
->GetFormatTable() );
1755 rData
.GetFromItemSet( nIndex
, GetPattern( nCol
, nRow
)->GetItemSet(), aNumFormat
);
1762 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1764 void ScTable::GetAutoFormatFrame(SCCOL nCol
, SCROW nRow
, USHORT nFlags
, USHORT nIndex
, ScAutoFormatData
& rData
)
1766 const SvxBoxItem
* pTheBox
= (SvxBoxItem
*)GetAttr(nCol
, nRow
, ATTR_BORDER
);
1767 const SvxBoxItem
* pLeftBox
= (SvxBoxItem
*)GetAttr(nCol
- 1, nRow
, ATTR_BORDER
);
1768 const SvxBoxItem
* pTopBox
= (SvxBoxItem
*)GetAttr(nCol
, nRow
- 1, ATTR_BORDER
);
1769 const SvxBoxItem
* pRightBox
= (SvxBoxItem
*)GetAttr(nCol
+ 1, nRow
, ATTR_BORDER
);
1770 const SvxBoxItem
* pBottomBox
= (SvxBoxItem
*)GetAttr(nCol
, nRow
+ 1, ATTR_BORDER
);
1772 SvxBoxItem
aBox( ATTR_BORDER
);
1773 if (nFlags
& LF_LEFT
)
1777 if (ScHasPriority(pTheBox
->GetLeft(), pLeftBox
->GetRight()))
1778 aBox
.SetLine(pTheBox
->GetLeft(), BOX_LINE_LEFT
);
1780 aBox
.SetLine(pLeftBox
->GetRight(), BOX_LINE_LEFT
);
1783 aBox
.SetLine(pTheBox
->GetLeft(), BOX_LINE_LEFT
);
1785 if (nFlags
& LF_TOP
)
1789 if (ScHasPriority(pTheBox
->GetTop(), pTopBox
->GetBottom()))
1790 aBox
.SetLine(pTheBox
->GetTop(), BOX_LINE_TOP
);
1792 aBox
.SetLine(pTopBox
->GetBottom(), BOX_LINE_TOP
);
1795 aBox
.SetLine(pTheBox
->GetTop(), BOX_LINE_TOP
);
1797 if (nFlags
& LF_RIGHT
)
1801 if (ScHasPriority(pTheBox
->GetRight(), pRightBox
->GetLeft()))
1802 aBox
.SetLine(pTheBox
->GetRight(), BOX_LINE_RIGHT
);
1804 aBox
.SetLine(pRightBox
->GetLeft(), BOX_LINE_RIGHT
);
1807 aBox
.SetLine(pTheBox
->GetRight(), BOX_LINE_RIGHT
);
1809 if (nFlags
& LF_BOTTOM
)
1813 if (ScHasPriority(pTheBox
->GetBottom(), pBottomBox
->GetTop()))
1814 aBox
.SetLine(pTheBox
->GetBottom(), BOX_LINE_BOTTOM
);
1816 aBox
.SetLine(pBottomBox
->GetTop(), BOX_LINE_BOTTOM
);
1819 aBox
.SetLine(pTheBox
->GetBottom(), BOX_LINE_BOTTOM
);
1821 rData
.PutItem( nIndex
, aBox
);
1824 void ScTable::GetAutoFormatData(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
, ScAutoFormatData
& rData
)
1826 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
1828 if ((nEndCol
- nStartCol
>= 3) && (nEndRow
- nStartRow
>= 3))
1831 GetAutoFormatAttr(nStartCol
, nStartRow
, 0, rData
);
1832 GetAutoFormatFrame(nStartCol
, nStartRow
, LF_ALL
, 0, rData
);
1834 GetAutoFormatAttr(nStartCol
, nStartRow
+ 1, 4, rData
);
1835 GetAutoFormatAttr(nStartCol
, nStartRow
+ 2, 8, rData
);
1836 GetAutoFormatFrame(nStartCol
, nStartRow
+ 1, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 4, rData
);
1837 if (nEndRow
- nStartRow
>= 4)
1838 GetAutoFormatFrame(nStartCol
, nStartRow
+ 2, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 8, rData
);
1840 rData
.CopyItem( 8, 4, ATTR_BORDER
);
1841 // Linke untere Ecke
1842 GetAutoFormatAttr(nStartCol
, nEndRow
, 12, rData
);
1843 GetAutoFormatFrame(nStartCol
, nEndRow
, LF_ALL
, 12, rData
);
1844 // Rechte obere Ecke
1845 GetAutoFormatAttr(nEndCol
, nStartRow
, 3, rData
);
1846 GetAutoFormatFrame(nEndCol
, nStartRow
, LF_ALL
, 3, rData
);
1848 GetAutoFormatAttr(nEndCol
, nStartRow
+ 1, 7, rData
);
1849 GetAutoFormatAttr(nEndCol
, nStartRow
+ 2, 11, rData
);
1850 GetAutoFormatFrame(nEndCol
, nStartRow
+ 1, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 7, rData
);
1851 if (nEndRow
- nStartRow
>= 4)
1852 GetAutoFormatFrame(nEndCol
, nStartRow
+ 2, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 11, rData
);
1854 rData
.CopyItem( 11, 7, ATTR_BORDER
);
1855 // Rechte untere Ecke
1856 GetAutoFormatAttr(nEndCol
, nEndRow
, 15, rData
);
1857 GetAutoFormatFrame(nEndCol
, nEndRow
, LF_ALL
, 15, rData
);
1859 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
, 1, rData
);
1860 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
, 2, rData
);
1861 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 1, rData
);
1862 if (nEndCol
- nStartCol
>= 4)
1863 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 2, rData
);
1865 rData
.CopyItem( 2, 1, ATTR_BORDER
);
1867 GetAutoFormatAttr(nStartCol
+ 1, nEndRow
, 13, rData
);
1868 GetAutoFormatAttr(nStartCol
+ 2, nEndRow
, 14, rData
);
1869 GetAutoFormatFrame(nStartCol
+ 1, nEndRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 13, rData
);
1870 if (nEndCol
- nStartCol
>= 4)
1871 GetAutoFormatFrame(nStartCol
+ 2, nEndRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 14, rData
);
1873 rData
.CopyItem( 14, 13, ATTR_BORDER
);
1875 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
+ 1, 5, rData
);
1876 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
+ 1, 6, rData
);
1877 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
+ 2, 9, rData
);
1878 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
+ 2, 10, rData
);
1879 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
+ 1, LF_RIGHT
| LF_BOTTOM
, 5, rData
);
1880 if ((nEndCol
- nStartCol
>= 4) && (nEndRow
- nStartRow
>= 4))
1882 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
+ 1, LF_RIGHT
| LF_BOTTOM
, 6, rData
);
1883 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
+ 2, LF_RIGHT
| LF_BOTTOM
, 9, rData
);
1884 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
+ 2, LF_RIGHT
| LF_BOTTOM
, 10, rData
);
1888 rData
.CopyItem( 6, 5, ATTR_BORDER
);
1889 rData
.CopyItem( 9, 5, ATTR_BORDER
);
1890 rData
.CopyItem( 10, 5, ATTR_BORDER
);
1896 void ScTable::SetError( SCCOL nCol
, SCROW nRow
, USHORT nError
)
1898 if (ValidColRow(nCol
, nRow
))
1899 aCol
[nCol
].SetError( nRow
, nError
);
1902 void ScTable::UpdateInsertTabAbs(SCTAB nTable
)
1904 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1905 aCol
[i
].UpdateInsertTabAbs(nTable
);
1908 //UNUSED2008-05 USHORT ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const
1910 //UNUSED2008-05 if (ValidColRow(nCol,nRow))
1911 //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow );
1912 //UNUSED2008-05 else
1913 //UNUSED2008-05 return 0;
1916 BOOL
ScTable::GetNextSpellingCell(SCCOL
& rCol
, SCROW
& rRow
, BOOL bInSel
,
1917 const ScMarkData
& rMark
) const
1919 if (rRow
== MAXROW
+2) // Tabellenende
1927 if (rRow
== MAXROW
+1)
1933 if (rCol
== MAXCOL
+1)
1942 bStop
= aCol
[rCol
].GetNextSpellingCell(rRow
, bInSel
, rMark
);
1945 else /*if (rRow == MAXROW+1) */
1958 void ScTable::RemoveAutoSpellObj()
1960 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1961 aCol
[i
].RemoveAutoSpellObj();
1964 BOOL
ScTable::TestTabRefAbs(SCTAB nTable
)
1967 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1968 if (aCol
[i
].TestTabRefAbs(nTable
))
1973 void ScTable::CompileDBFormula()
1975 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileDBFormula();
1978 void ScTable::CompileDBFormula( BOOL bCreateFormulaString
)
1980 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileDBFormula( bCreateFormulaString
);
1983 void ScTable::CompileNameFormula( BOOL bCreateFormulaString
)
1985 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileNameFormula( bCreateFormulaString
);
1988 void ScTable::CompileColRowNameFormula()
1990 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileColRowNameFormula();