1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <comphelper/string.hxx>
22 #include <svx/algitem.hxx>
23 #include <editeng/boxitem.hxx>
24 #include <editeng/brushitem.hxx>
25 #include <editeng/contouritem.hxx>
26 #include <editeng/colritem.hxx>
27 #include <editeng/crossedoutitem.hxx>
28 #include <editeng/fhgtitem.hxx>
29 #include <editeng/fontitem.hxx>
30 #include <editeng/langitem.hxx>
31 #include <editeng/postitem.hxx>
32 #include <editeng/shdditem.hxx>
33 #include <editeng/udlnitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <svx/rotmodit.hxx>
36 #include <editeng/editobj.hxx>
37 #include <editeng/editeng.hxx>
38 #include <editeng/eeitem.hxx>
39 #include <editeng/escapementitem.hxx>
40 #include <svl/zforlist.hxx>
41 #include <vcl/keycodes.hxx>
42 #include <rtl/math.hxx>
43 #include <unotools/charclass.hxx>
46 #include "patattr.hxx"
47 #include "formulacell.hxx"
49 #include "globstr.hrc"
51 #include "document.hxx"
52 #include "autoform.hxx"
53 #include "userlist.hxx"
54 #include "zforauto.hxx"
55 #include "subtotal.hxx"
56 #include "formula/errorcodes.hxx"
57 #include "rangenam.hxx"
58 #include "docpool.hxx"
59 #include "progress.hxx"
60 #include "segmenttree.hxx"
61 #include "conditio.hxx"
62 #include "editutil.hxx"
65 #include <boost/scoped_ptr.hpp>
67 // STATIC DATA -----------------------------------------------------------
69 #define _D_MAX_LONG_ (double) 0x7fffffff
71 extern sal_uInt16 nScFillModeMouseModifier
; // global.cxx
75 short lcl_DecompValueString( OUString
& rValue
, sal_Int32
& nVal
, sal_uInt16
* pMinDigits
= NULL
)
77 if ( rValue
.isEmpty() )
82 const sal_Unicode
* p
= rValue
.getStr();
87 while ( p
[nNum
] && CharClass::isAsciiNumeric( OUString(p
[nNum
]) ) )
90 sal_Unicode cNext
= p
[nNum
]; // 0 if at the end
91 sal_Unicode cLast
= p
[rValue
.getLength()-1];
93 // #i5550# If there are numbers at the beginning and the end,
94 // prefer the one at the beginning only if it's followed by a space.
95 // Otherwise, use the number at the end, to enable things like IP addresses.
96 if ( nNum
> nNeg
&& ( cNext
== 0 || cNext
== ' ' || !CharClass::isAsciiNumeric(OUString(cLast
)) ) )
97 { // number at the beginning
98 nVal
= rValue
.copy( 0, nNum
).toInt32();
99 // any number with a leading zero sets the minimum number of digits
100 if ( p
[nNeg
] == '0' && pMinDigits
&& ( nNum
- nNeg
> *pMinDigits
) )
101 *pMinDigits
= nNum
- nNeg
;
102 rValue
= rValue
.copy(nNum
);
108 sal_Int32 nEnd
= nNum
= rValue
.getLength() - 1;
109 while ( nNum
&& CharClass::isAsciiNumeric( OUString(p
[nNum
]) ) )
111 if ( p
[nNum
] == '-' )
116 if ( nNum
< nEnd
- nNeg
)
117 { // number at the end
118 nVal
= rValue
.copy( nNum
+ 1 ).toInt32();
119 // any number with a leading zero sets the minimum number of digits
120 if ( p
[nNum
+1+nNeg
] == '0' && pMinDigits
&& ( nEnd
- nNum
- nNeg
> *pMinDigits
) )
121 *pMinDigits
= nEnd
- nNum
- nNeg
;
122 rValue
= rValue
.copy(0, nNum
+ 1);
130 OUString
lcl_ValueString( sal_Int32 nValue
, sal_uInt16 nMinDigits
)
132 if ( nMinDigits
<= 1 )
133 return OUString::number( nValue
); // simple case...
136 OUString aStr
= OUString::number( std::abs( nValue
) );
137 if ( aStr
.getLength() < nMinDigits
)
139 OUStringBuffer aZero
;
140 comphelper::string::padToLength(aZero
, nMinDigits
- aStr
.getLength(), '0');
141 aStr
= aZero
.makeStringAndClear() + aStr
;
143 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
151 ScColumn
& rColumn
, SCROW nRow
, sal_Int32 nValue
, sal_uInt16 nDigits
, const OUString
& rSuffix
,
152 CellType eCellType
, bool bIsOrdinalSuffix
)
154 ScDocument
& rDoc
= rColumn
.GetDoc();
155 OUString aValue
= lcl_ValueString(nValue
, nDigits
);
156 if (!bIsOrdinalSuffix
)
158 rColumn
.SetRawString(nRow
, aValue
+= rSuffix
);
162 OUString aOrdinalSuffix
= ScGlobal::GetOrdinalSuffix(nValue
);
163 if (eCellType
!= CELLTYPE_EDIT
)
165 rColumn
.SetRawString(nRow
, aValue
+= aOrdinalSuffix
);
169 EditEngine
aEngine(rDoc
.GetEnginePool());
170 aEngine
.SetEditTextObjectPool(rDoc
.GetEditPool());
172 SfxItemSet aAttr
= aEngine
.GetEmptyItemSet();
173 aAttr
.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT
, EE_CHAR_ESCAPEMENT
));
174 aEngine
.SetText( aValue
);
175 aEngine
.QuickInsertText(
177 ESelection(0, aValue
.getLength(), 0, aValue
.getLength() + aOrdinalSuffix
.getLength()));
179 aEngine
.QuickSetAttribs(
181 ESelection(0, aValue
.getLength(), 0, aValue
.getLength() + aOrdinalSuffix
.getLength()));
183 // Text object instance will be owned by the cell.
184 rColumn
.SetEditText(nRow
, aEngine
.CreateTextObject());
189 void ScTable::FillAnalyse( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
190 FillCmd
& rCmd
, FillDateCmd
& rDateCmd
,
191 double& rInc
, sal_uInt16
& rMinDigits
,
192 ScUserListData
*& rListData
, sal_uInt16
& rListIndex
)
194 OSL_ENSURE( nCol1
==nCol2
|| nRow1
==nRow2
, "FillAnalyse: invalid range" );
200 if ( (nScFillModeMouseModifier
& KEY_MOD1
) )
201 return ; // Ctrl-key: Copy
210 nCount
= static_cast<SCSIZE
>(nRow2
- nRow1
+ 1);
216 nCount
= static_cast<SCSIZE
>(nCol2
- nCol1
+ 1);
222 ScRefCellValue aFirstCell
= GetCellValue(nCol
, nRow
);
223 CellType eCellType
= aFirstCell
.meType
;
225 if (eCellType
== CELLTYPE_VALUE
)
227 sal_uInt32 nFormat
= ((const SfxUInt32Item
*)GetAttr(nCol
,nRow
,ATTR_VALUE_FORMAT
))->GetValue();
228 bool bDate
= ( pDocument
->GetFormatTable()->GetType(nFormat
) == NUMBERFORMAT_DATE
);
234 Date aNullDate
= *pDocument
->GetFormatTable()->GetNullDate();
235 Date aDate1
= aNullDate
;
236 nVal
= aFirstCell
.mfValue
;
237 aDate1
+= (long)nVal
;
238 Date aDate2
= aNullDate
;
239 nVal
= GetValue(nCol
+nAddX
, nRow
+nAddY
);
240 aDate2
+= (long)nVal
;
241 if ( aDate1
!= aDate2
)
245 long nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
246 long nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
247 long nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
251 nCmpInc
= aDate2
- aDate1
;
256 nCmpInc
= nMDiff
+ 12 * nYDiff
;
259 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
260 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
262 for (sal_uInt16 i
=1; i
<nCount
&& bVal
; i
++)
264 ScRefCellValue aCell
= GetCellValue(nCol
,nRow
);
265 if (aCell
.meType
== CELLTYPE_VALUE
)
267 nVal
= aCell
.mfValue
;
268 aDate2
= aNullDate
+ (long) nVal
;
269 if ( eType
== FILL_DAY
)
271 if ( aDate2
-aDate1
!= nCmpInc
)
276 nDDiff
= aDate2
.GetDay() - (long) aDate1
.GetDay();
277 nMDiff
= aDate2
.GetMonth() - (long) aDate1
.GetMonth();
278 nYDiff
= aDate2
.GetYear() - (long) aDate1
.GetYear();
279 if (nDDiff
|| ( nMDiff
+ 12 * nYDiff
!= nCmpInc
))
283 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
284 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
287 bVal
= false; // kein Datum passt auch nicht
291 if ( eType
== FILL_MONTH
&& ( nCmpInc
% 12 == 0 ) )
302 else // single date -> increment by days
313 double nVal1
= aFirstCell
.mfValue
;
314 double nVal2
= GetValue(nCol
+nAddX
, nRow
+nAddY
);
315 rInc
= nVal2
- nVal1
;
316 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
317 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
319 for (sal_uInt16 i
=1; i
<nCount
&& bVal
; i
++)
321 ScRefCellValue aCell
= GetCellValue(nCol
,nRow
);
322 if (aCell
.meType
== CELLTYPE_VALUE
)
324 nVal2
= aCell
.mfValue
;
325 double nDiff
= nVal2
- nVal1
;
326 if ( !::rtl::math::approxEqual( nDiff
, rInc
, 13 ) )
332 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
333 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
340 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
343 GetString(nCol
, nRow
, aStr
);
345 // fdo#39500 don't deduce increment from multiple equal list entries
346 bool bAllSame
= true;
347 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
350 GetString(static_cast<SCCOL
>(nCol
+ i
* nAddX
), static_cast<SCROW
>(nRow
+ i
* nAddY
), aTestStr
);
357 if(bAllSame
&& nCount
> 1)
360 rListData
= (ScUserListData
*)(ScGlobal::GetUserList()->GetData(aStr
));
363 rListData
->GetSubIndex(aStr
, rListIndex
);
364 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
365 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
366 for (sal_uInt16 i
=1; i
<nCount
&& rListData
; i
++)
368 GetString(nCol
, nRow
, aStr
);
369 if (!rListData
->GetSubIndex(aStr
, rListIndex
))
371 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
372 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
375 else if ( nCount
> 1 )
377 // pass rMinDigits to all DecompValueString calls
378 // -> longest number defines rMinDigits
381 short nFlag1
= lcl_DecompValueString( aStr
, nVal1
, &rMinDigits
);
385 GetString( nCol
+nAddX
, nRow
+nAddY
, aStr
);
386 short nFlag2
= lcl_DecompValueString( aStr
, nVal2
, &rMinDigits
);
387 if ( nFlag1
== nFlag2
)
389 rInc
= (double)nVal2
- (double)nVal1
;
390 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
391 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
393 for (sal_uInt16 i
=1; i
<nCount
&& bVal
; i
++)
395 ScRefCellValue aCell
= GetCellValue(nCol
, nRow
);
396 CellType eType
= aCell
.meType
;
397 if ( eType
== CELLTYPE_STRING
|| eType
== CELLTYPE_EDIT
)
399 aStr
= aCell
.getString(pDocument
);
400 nFlag2
= lcl_DecompValueString( aStr
, nVal2
, &rMinDigits
);
401 if ( nFlag1
== nFlag2
)
403 double nDiff
= (double)nVal2
- (double)nVal1
;
404 if ( !::rtl::math::approxEqual( nDiff
, rInc
, 13 ) )
413 nCol
= sal::static_int_cast
<SCCOL
>( nCol
+ nAddX
);
414 nRow
= sal::static_int_cast
<SCROW
>( nRow
+ nAddY
);
423 // call DecompValueString to set rMinDigits
425 lcl_DecompValueString( aStr
, nDummy
, &rMinDigits
);
430 void ScTable::FillFormula(sal_uLong
& /* nFormulaCounter */, bool /* bFirst */, ScFormulaCell
* pSrcCell
,
431 SCCOL nDestCol
, SCROW nDestRow
, bool bLast
)
434 pDocument
->SetNoListening( true ); // still the wrong reference
435 ScAddress
aAddr( nDestCol
, nDestRow
, nTab
);
436 ScFormulaCell
* pDestCell
= new ScFormulaCell( *pSrcCell
, *pDocument
, aAddr
);
437 aCol
[nDestCol
].SetFormulaCell(nDestRow
, pDestCell
);
439 if ( bLast
&& pDestCell
->GetMatrixFlag() )
442 if ( pDestCell
->GetMatrixOrigin( aOrg
) )
444 if ( nDestCol
>= aOrg
.Col() && nDestRow
>= aOrg
.Row() )
446 ScFormulaCell
* pOrgCell
= pDocument
->GetFormulaCell(aOrg
);
447 if (pOrgCell
&& pOrgCell
->GetMatrixFlag() == MM_FORMULA
)
449 ((ScFormulaCell
*)pOrgCell
)->SetMatColsRows(
450 nDestCol
- aOrg
.Col() + 1,
451 nDestRow
- aOrg
.Row() + 1 );
455 OSL_FAIL( "FillFormula: MatrixOrigin no forumla cell with MM_FORMULA" );
460 OSL_FAIL( "FillFormula: MatrixOrigin bottom right" );
465 OSL_FAIL( "FillFormula: no MatrixOrigin" );
468 pDocument
->SetNoListening( false );
469 pDestCell
->StartListeningTo( pDocument
);
473 void ScTable::FillAuto( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
474 sal_uLong nFillCount
, FillDir eFillDir
, ScProgress
* pProgress
)
476 if ( (nFillCount
== 0) || !ValidColRow(nCol1
, nRow1
) || !ValidColRow(nCol2
, nRow2
) )
483 bool bVertical
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
);
484 bool bPositive
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_RIGHT
);
488 sal_uLong
& rInner
= bVertical
? nRow
: nCol
; // loop variables
489 sal_uLong
& rOuter
= bVertical
? nCol
: nRow
;
494 sal_uLong nISrcStart
;
507 nIEnd
= nRow2
+ nFillCount
;
508 aFillRange
= ScRange(nCol1
, nRow2
+1, 0, nCol2
, nRow2
+ nFillCount
, 0);
515 nIEnd
= nRow1
- nFillCount
;
516 aFillRange
= ScRange(nCol1
, nRow1
-1, 0, nCol2
, nRow2
- nFillCount
, 0);
528 nIEnd
= nCol2
+ nFillCount
;
529 aFillRange
= ScRange(nCol2
+ 1, nRow1
, 0, nCol2
+ nFillCount
, nRow2
, 0);
536 nIEnd
= nCol1
- nFillCount
;
537 aFillRange
= ScRange(nCol1
- 1, nRow1
, 0, nCol1
- nFillCount
, nRow2
, 0);
540 sal_uLong nIMin
= nIStart
;
541 sal_uLong nIMax
= nIEnd
;
542 PutInOrder(nIMin
,nIMax
);
543 bool bHasFiltered
= IsDataFiltered(aFillRange
);
548 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), IDF_AUTOFILL
);
550 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, IDF_AUTOFILL
);
553 sal_uLong nProgress
= 0;
555 nProgress
= pProgress
->GetState();
561 sal_uLong nActFormCnt
= 0;
562 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
564 sal_uLong nMaxFormCnt
= 0; // for formulas
566 // transfer attributes
568 const ScPatternAttr
* pSrcPattern
= NULL
;
569 const ScStyleSheet
* pStyleSheet
= NULL
;
570 sal_uLong nAtSrc
= nISrcStart
;
571 ScPatternAttr
* pNewPattern
= NULL
;
572 bool bGetPattern
= true;
574 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
576 if (!ColHidden(nCol
) && !RowHidden(nRow
))
581 if (bVertical
) // rInner&:=nRow, rOuter&:=nCol
582 pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nAtSrc
));
583 else // rInner&:=nCol, rOuter&:=nRow
584 pSrcPattern
= aCol
[nAtSrc
].GetPattern(static_cast<SCROW
>(nRow
));
586 pStyleSheet
= pSrcPattern
->GetStyleSheet();
587 // do not transfer ATTR_MERGE / ATTR_MERGE_FLAG
588 const SfxItemSet
& rSet
= pSrcPattern
->GetItemSet();
589 if ( rSet
.GetItemState(ATTR_MERGE
, false) == SFX_ITEM_SET
590 || rSet
.GetItemState(ATTR_MERGE_FLAG
, false) == SFX_ITEM_SET
)
592 pNewPattern
= new ScPatternAttr( *pSrcPattern
);
593 SfxItemSet
& rNewSet
= pNewPattern
->GetItemSet();
594 rNewSet
.ClearItem(ATTR_MERGE
);
595 rNewSet
.ClearItem(ATTR_MERGE_FLAG
);
601 const ScCondFormatItem
& rCondFormatItem
= static_cast<const ScCondFormatItem
&>(pSrcPattern
->GetItem(ATTR_CONDITIONAL
));
602 const std::vector
<sal_uInt32
>& rCondFormatIndex
= rCondFormatItem
.GetCondFormatData();
604 if ( bVertical
&& nISrcStart
== nISrcEnd
&& !bHasFiltered
)
606 // set all attributes at once (en bloc)
607 if (pNewPattern
|| pSrcPattern
!= pDocument
->GetDefPattern())
609 // Default is already present (DeleteArea)
610 SCROW nY1
= static_cast<SCROW
>(std::min( nIStart
, nIEnd
));
611 SCROW nY2
= static_cast<SCROW
>(std::max( nIStart
, nIEnd
));
613 aCol
[nCol
].ApplyStyleArea( nY1
, nY2
, *pStyleSheet
);
615 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pNewPattern
);
617 aCol
[nCol
].ApplyPatternArea( nY1
, nY2
, *pSrcPattern
);
619 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
620 itr
!= itrEnd
; ++itr
)
622 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
623 ScRangeList aRange
= pCondFormat
->GetRange();
624 aRange
.Join(ScRange(nCol
, nY1
, nTab
, nCol
, nY2
, nTab
));
625 pCondFormat
->AddRange(aRange
);
634 DeleteArea(static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
),
635 static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), IDF_AUTOFILL
);
637 if ( pSrcPattern
!= aCol
[nCol
].GetPattern( static_cast<SCROW
>(nRow
) ) )
639 // Transfer template too
640 //! Merge ApplyPattern to AttrArray ??
642 aCol
[nCol
].ApplyStyle( static_cast<SCROW
>(nRow
), *pStyleSheet
);
644 // Use ApplyPattern instead of SetPattern to keep old MergeFlags
646 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pNewPattern
);
648 aCol
[nCol
].ApplyPattern( static_cast<SCROW
>(nRow
), *pSrcPattern
);
650 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
651 itr
!= itrEnd
; ++itr
)
653 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
654 ScRangeList aRange
= pCondFormat
->GetRange();
655 aRange
.Join(ScRange(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
));
656 pCondFormat
->AddRange(aRange
);
660 if (nAtSrc
==nISrcEnd
)
662 if ( nAtSrc
!= nISrcStart
)
663 { // More than one source cell
680 if (rInner
== nIEnd
) break;
681 if (bPositive
) ++rInner
; else --rInner
;
689 FillDateCmd eDateCmd
;
691 sal_uInt16 nMinDigits
;
692 ScUserListData
* pListData
= NULL
;
693 sal_uInt16 nListIndex
;
695 FillAnalyse(static_cast<SCCOL
>(nCol
),nRow1
,
696 static_cast<SCCOL
>(nCol
),nRow2
, eFillCmd
,eDateCmd
,
697 nInc
,nMinDigits
, pListData
,nListIndex
);
699 FillAnalyse(nCol1
,static_cast<SCROW
>(nRow
),
700 nCol2
,static_cast<SCROW
>(nRow
), eFillCmd
,eDateCmd
,
701 nInc
,nMinDigits
, pListData
,nListIndex
);
705 sal_uInt16 nListCount
= pListData
->GetSubCount();
708 // nListIndex of FillAnalyse points to the last entry -> adjust
709 sal_uLong nSub
= nISrcStart
- nISrcEnd
;
710 for (sal_uLong i
=0; i
<nSub
; i
++)
712 if (nListIndex
== 0) nListIndex
= nListCount
;
718 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
720 if(!ColHidden(nCol
) && !RowHidden(nRow
))
725 if (nListIndex
>= nListCount
) nListIndex
= 0;
729 if (nListIndex
== 0) nListIndex
= nListCount
;
732 aCol
[nCol
].SetRawString(static_cast<SCROW
>(nRow
), pListData
->GetSubStr(nListIndex
));
735 if (rInner
== nIEnd
) break;
736 if (bPositive
) ++rInner
; else --rInner
;
740 nProgress
+= nIMax
- nIMin
+ 1;
741 pProgress
->SetStateOnPercent( nProgress
);
744 else if (eFillCmd
== FILL_SIMPLE
) // fill with pattern/sample
746 sal_uLong nSource
= nISrcStart
;
748 if ( (nScFillModeMouseModifier
& KEY_MOD1
) )
750 else if ( bPositive
)
755 sal_uLong nFormulaCounter
= nActFormCnt
;
757 bool bGetCell
= true;
758 sal_uInt16 nCellDigits
= 0;
759 short nHeadNoneTail
= 0;
760 sal_Int32 nStringValue
= 0;
762 ScCellValue aSrcCell
;
763 CellType eCellType
= CELLTYPE_NONE
;
764 bool bIsOrdinalSuffix
= false;
767 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
769 if(!ColHidden(nCol
) && !RowHidden(nRow
))
773 if (bVertical
) // rInner&:=nRow, rOuter&:=nCol
774 aSrcCell
= aCol
[nCol
].GetCellValue(static_cast<SCROW
>(nSource
));
775 else // rInner&:=nCol, rOuter&:=nRow
776 aSrcCell
= aCol
[nSource
].GetCellValue(static_cast<SCROW
>(nRow
));
779 if (!aSrcCell
.isEmpty())
781 eCellType
= aSrcCell
.meType
;
785 nVal
= aSrcCell
.mfValue
;
787 case CELLTYPE_STRING
:
789 if ( eCellType
== CELLTYPE_STRING
)
790 aValue
= aSrcCell
.mpString
->getString();
792 aValue
= ScEditUtil::GetString(*aSrcCell
.mpEditText
, pDocument
);
793 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) && !bHasFiltered
)
795 nCellDigits
= 0; // look at each source cell individually
796 nHeadNoneTail
= lcl_DecompValueString(
797 aValue
, nStringValue
, &nCellDigits
);
799 bIsOrdinalSuffix
= aValue
.equals(
800 ScGlobal::GetOrdinalSuffix( nStringValue
));
805 // added to avoid warnings
810 eCellType
= CELLTYPE_NONE
;
816 aCol
[nCol
].SetValue(static_cast<SCROW
>(nRow
), nVal
+ nDelta
);
818 case CELLTYPE_STRING
:
822 // #i48009# with the "nStringValue+(long)nDelta" expression within the
823 // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3),
824 // so nNextValue is now calculated ahead.
825 sal_Int32 nNextValue
= nStringValue
+(sal_Int32
)nDelta
;
828 if ( nHeadNoneTail
< 0 )
831 aCol
[nCol
], static_cast<SCROW
>(nRow
),
832 nNextValue
, nCellDigits
, aValue
,
833 eCellType
, bIsOrdinalSuffix
);
837 aStr
= aValue
+ lcl_ValueString( nNextValue
, nCellDigits
);
838 aCol
[nCol
].SetRawString(static_cast<SCROW
>(nRow
), aStr
);
842 aSrcCell
.commit(aCol
[nCol
], nRow
);
845 case CELLTYPE_FORMULA
:
846 FillFormula( nFormulaCounter
, bFirst
, aSrcCell
.mpFormula
,
847 static_cast<SCCOL
>(nCol
),
848 static_cast<SCROW
>(nRow
), (rInner
== nIEnd
) );
849 if (nFormulaCounter
- nActFormCnt
> nMaxFormCnt
)
850 nMaxFormCnt
= nFormulaCounter
- nActFormCnt
;
854 // added to avoid warnings
858 if (nSource
==nISrcEnd
)
860 if ( nSource
!= nISrcStart
)
861 { // More than one source cell
862 nSource
= nISrcStart
;
865 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
872 nFormulaCounter
= nActFormCnt
;
887 if (rInner
== nIEnd
) break;
888 if (bPositive
) ++rInner
; else --rInner
;
890 // Progress in inner loop only for expensive cells,
891 // and even then not individually for each one
894 if ( pProgress
&& (eCellType
== CELLTYPE_FORMULA
|| eCellType
== CELLTYPE_EDIT
) )
895 pProgress
->SetStateOnPercent( nProgress
);
899 pProgress
->SetStateOnPercent( nProgress
);
905 double nEndVal
= (nInc
>=0.0) ? MAXDOUBLE
: -MAXDOUBLE
;
907 FillSeries( static_cast<SCCOL
>(nCol
), nRow1
,
908 static_cast<SCCOL
>(nCol
), nRow2
, nFillCount
, eFillDir
,
909 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, false,
912 FillSeries( nCol1
, static_cast<SCROW
>(nRow
), nCol2
,
913 static_cast<SCROW
>(nRow
), nFillCount
, eFillDir
,
914 eFillCmd
, eDateCmd
, nInc
, nEndVal
, nMinDigits
, false,
917 nProgress
= pProgress
->GetState();
920 nActFormCnt
+= nMaxFormCnt
;
924 OUString
ScTable::GetAutoFillPreview( const ScRange
& rSource
, SCCOL nEndX
, SCROW nEndY
)
928 SCCOL nCol1
= rSource
.aStart
.Col();
929 SCROW nRow1
= rSource
.aStart
.Row();
930 SCCOL nCol2
= rSource
.aEnd
.Col();
931 SCROW nRow2
= rSource
.aEnd
.Row();
934 sal_uLong nSrcCount
= 0;
935 FillDir eFillDir
= FILL_TO_BOTTOM
;
936 if ( nEndX
== nCol2
&& nEndY
== nRow2
) // empty
938 else if ( nEndX
== nCol2
) // to up / down
940 nEndX
= nCol2
= nCol1
; // use only first column
941 nSrcCount
= nRow2
- nRow1
+ 1;
942 nIndex
= ((long)nEndY
) - nRow1
; // can be negative
943 if ( nEndY
>= nRow1
)
944 eFillDir
= FILL_TO_BOTTOM
;
946 eFillDir
= FILL_TO_TOP
;
948 else if ( nEndY
== nRow2
) // to left / right
950 nEndY
= nRow2
= nRow1
; // use only first row
951 nSrcCount
= nCol2
- nCol1
+ 1;
952 nIndex
= ((long)nEndX
) - nCol1
; // can be negative
953 if ( nEndX
>= nCol1
)
954 eFillDir
= FILL_TO_RIGHT
;
956 eFillDir
= FILL_TO_LEFT
;
958 else // direction not clear
964 FillDateCmd eDateCmd
;
966 sal_uInt16 nMinDigits
;
967 ScUserListData
* pListData
= NULL
;
968 sal_uInt16 nListIndex
;
970 FillAnalyse(nCol1
,nRow1
, nCol2
,nRow2
, eFillCmd
,eDateCmd
, nInc
,nMinDigits
, pListData
,nListIndex
);
972 if ( pListData
) // user defined list
974 sal_uInt16 nListCount
= pListData
->GetSubCount();
977 sal_uLong nSub
= nSrcCount
- 1; // nListIndex is from last source entry
978 while ( nIndex
< sal::static_int_cast
<long>(nSub
) )
979 nIndex
+= nListCount
;
980 sal_uLong nPos
= ( nListIndex
+ nIndex
- nSub
) % nListCount
;
981 aValue
= pListData
->GetSubStr(sal::static_int_cast
<sal_uInt16
>(nPos
));
984 else if ( eFillCmd
== FILL_SIMPLE
) // fill with pattern/sample
986 if ((eFillDir
== FILL_TO_BOTTOM
)||(eFillDir
== FILL_TO_TOP
))
1001 long nNonFiltered
= CountNonFilteredRows(nBegin
, nEnd
);
1002 long nFiltered
= nEnd
+ 1 - nBegin
- nNonFiltered
;
1005 nIndex
= nIndex
- nFiltered
;
1007 nIndex
= nIndex
+ nFiltered
;
1010 long nPosIndex
= nIndex
;
1011 while ( nPosIndex
< 0 )
1012 nPosIndex
+= nSrcCount
;
1013 sal_uLong nPos
= nPosIndex
% nSrcCount
;
1014 SCCOL nSrcX
= nCol1
;
1015 SCROW nSrcY
= nRow1
;
1016 if ( eFillDir
== FILL_TO_TOP
|| eFillDir
== FILL_TO_BOTTOM
)
1017 nSrcY
= sal::static_int_cast
<SCROW
>( nSrcY
+ static_cast<SCROW
>(nPos
) );
1019 nSrcX
= sal::static_int_cast
<SCCOL
>( nSrcX
+ static_cast<SCCOL
>(nPos
) );
1021 ScRefCellValue aCell
= GetCellValue(nSrcX
, nSrcY
);
1022 if (!aCell
.isEmpty())
1026 nDelta
= nIndex
/ nSrcCount
;
1028 nDelta
= ( nIndex
- nSrcCount
+ 1 ) / nSrcCount
; // -1 -> -1
1030 CellType eType
= aCell
.meType
;
1033 case CELLTYPE_STRING
:
1036 aValue
= aCell
.getString(pDocument
);
1038 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
1041 sal_uInt16 nCellDigits
= 0; // look at each source cell individually
1042 short nFlag
= lcl_DecompValueString( aValue
, nVal
, &nCellDigits
);
1045 if (aValue
.equals( ScGlobal::GetOrdinalSuffix( nVal
)))
1046 aValue
= ScGlobal::GetOrdinalSuffix( nVal
+ nDelta
);
1048 aValue
= lcl_ValueString( nVal
+ nDelta
, nCellDigits
) + aValue
;
1050 else if ( nFlag
> 0 )
1051 aValue
+= lcl_ValueString( nVal
+ nDelta
, nCellDigits
);
1055 case CELLTYPE_VALUE
:
1057 // overflow is possible...
1058 double nVal
= aCell
.mfValue
;
1059 if ( !(nScFillModeMouseModifier
& KEY_MOD1
) )
1060 nVal
+= (double) nDelta
;
1063 sal_uLong nNumFmt
= GetNumberFormat( nSrcX
, nSrcY
);
1064 OUString
sTmp(aValue
);
1065 pDocument
->GetFormatTable()->GetOutputString( nVal
, nNumFmt
, sTmp
, &pColor
);
1072 // added to avoid warnings
1077 else if ( eFillCmd
== FILL_LINEAR
|| eFillCmd
== FILL_DATE
) // values
1082 short nHeadNoneTail
= 0;
1083 ScRefCellValue aCell
= GetCellValue(nCol1
, nRow1
);
1084 if (!aCell
.isEmpty())
1086 CellType eType
= aCell
.meType
;
1089 case CELLTYPE_STRING
:
1092 aValue
= aCell
.getString(pDocument
);
1093 nHeadNoneTail
= lcl_DecompValueString( aValue
, nVal
);
1094 if ( nHeadNoneTail
)
1095 nStart
= (double)nVal
;
1100 case CELLTYPE_VALUE
:
1101 nStart
= aCell
.mfValue
;
1103 case CELLTYPE_FORMULA
:
1104 nStart
= aCell
.mpFormula
->GetValue();
1112 if ( eFillCmd
== FILL_LINEAR
)
1115 bValueOk
= ( SubTotal::SafeMult( nAdd
, (double) nIndex
) &&
1116 SubTotal::SafePlus( nStart
, nAdd
) );
1121 sal_uInt16 nDayOfMonth
= 0;
1127 for (long i
=0; i
<nIndex
; i
++)
1128 IncDate( nStart
, nDayOfMonth
, nInc
, eDateCmd
);
1133 if ( nHeadNoneTail
)
1135 if ( nHeadNoneTail
< 0 )
1137 if (aValue
.equals( ScGlobal::GetOrdinalSuffix( nVal
)))
1138 aValue
= ScGlobal::GetOrdinalSuffix( (sal_Int32
)nStart
);
1140 aValue
= lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
) + aValue
;
1143 aValue
+= lcl_ValueString( (sal_Int32
)nStart
, nMinDigits
);
1147 //! Zahlformat je nach Index holen?
1149 sal_uLong nNumFmt
= GetNumberFormat( nCol1
, nRow1
);
1150 OUString
sTmp(aValue
);
1151 pDocument
->GetFormatTable()->GetOutputString( nStart
, nNumFmt
, sTmp
, &pColor
);
1158 OSL_FAIL("GetAutoFillPreview: invalid mode");
1165 void ScTable::IncDate(double& rVal
, sal_uInt16
& nDayOfMonth
, double nStep
, FillDateCmd eCmd
)
1167 if (eCmd
== FILL_DAY
)
1173 // class Date limits
1174 const sal_uInt16 nMinYear
= 1583;
1175 const sal_uInt16 nMaxYear
= 9956;
1177 long nInc
= (long) nStep
; // upper/lower limits ?
1178 Date aNullDate
= *pDocument
->GetFormatTable()->GetNullDate();
1179 Date aDate
= aNullDate
;
1180 aDate
+= (long)rVal
;
1186 DayOfWeek eWeekDay
= aDate
.GetDayOfWeek();
1189 if (eWeekDay
== SATURDAY
)
1191 else if (eWeekDay
== SUNDAY
)
1196 if (eWeekDay
== SATURDAY
)
1198 else if (eWeekDay
== SUNDAY
)
1205 if ( nDayOfMonth
== 0 )
1206 nDayOfMonth
= aDate
.GetDay(); // init
1207 long nMonth
= aDate
.GetMonth();
1208 long nYear
= aDate
.GetYear();
1216 long nYAdd
= (nMonth
-1) / 12;
1217 nMonth
-= nYAdd
* 12;
1225 long nYAdd
= 1 - nMonth
/ 12; // positive
1226 nMonth
+= nYAdd
* 12;
1231 if ( nYear
< nMinYear
)
1232 aDate
= Date( 1,1, nMinYear
);
1233 else if ( nYear
> nMaxYear
)
1234 aDate
= Date( 31,12, nMaxYear
);
1237 aDate
.SetMonth((sal_uInt16
) nMonth
);
1238 aDate
.SetYear((sal_uInt16
) nYear
);
1239 aDate
.SetDay( std::min( Date::GetDaysInMonth( nMonth
, nYear
), nDayOfMonth
) );
1245 long nYear
= aDate
.GetYear();
1247 if ( nYear
< nMinYear
)
1248 aDate
= Date( 1,1, nMinYear
);
1249 else if ( nYear
> nMaxYear
)
1250 aDate
= Date( 31,12, nMaxYear
);
1252 aDate
.SetYear((sal_uInt16
) nYear
);
1257 // added to avoid warnings
1261 rVal
= aDate
- aNullDate
;
1267 bool HiddenRowColumn(sal_uLong nRowColumn
, bool bVertical
, ScTable
* pTable
)
1271 return pTable
->RowHidden(static_cast<SCROW
>(nRowColumn
));
1275 return pTable
->ColHidden(static_cast<SCCOL
>(nRowColumn
));
1281 void ScTable::FillSeries( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1282 sal_uLong nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
1283 double nStepValue
, double nMaxValue
, sal_uInt16 nArgMinDigits
,
1284 bool bAttribs
, ScProgress
* pProgress
)
1290 bool bVertical
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_TOP
);
1291 bool bPositive
= (eFillDir
== FILL_TO_BOTTOM
|| eFillDir
== FILL_TO_RIGHT
);
1295 sal_uLong
& rInner
= bVertical
? nRow
: nCol
; // loop variables
1296 sal_uLong
& rOuter
= bVertical
? nCol
: nRow
;
1306 nFillCount
+= (nRow2
- nRow1
);
1307 if (nFillCount
== 0)
1314 nIStart
= nRow1
+ 1;
1315 nIEnd
= nRow1
+ nFillCount
;
1316 aFillRange
= ScRange(nCol1
, nRow1
+ 1, nTab
, nCol2
, nRow1
+ nFillCount
, nTab
);
1321 nIStart
= nRow2
- 1;
1322 nIEnd
= nRow2
- nFillCount
;
1323 aFillRange
= ScRange(nCol1
, nRow2
-1, nTab
, nCol2
, nRow2
- nFillCount
, nTab
);
1328 nFillCount
+= (nCol2
- nCol1
);
1329 if (nFillCount
== 0)
1336 nIStart
= nCol1
+ 1;
1337 nIEnd
= nCol1
+ nFillCount
;
1338 aFillRange
= ScRange(nCol1
+ 1, nRow1
, nTab
, nCol1
+ nFillCount
, nRow2
, nTab
);
1343 nIStart
= nCol2
- 1;
1344 nIEnd
= nCol2
- nFillCount
;
1345 aFillRange
= ScRange(nCol2
- 1, nRow1
, nTab
, nCol2
- nFillCount
, nRow2
, nTab
);
1349 sal_uLong nIMin
= nIStart
;
1350 sal_uLong nIMax
= nIEnd
;
1351 PutInOrder(nIMin
,nIMax
);
1352 sal_uInt16 nDel
= bAttribs
? IDF_AUTOFILL
: (IDF_AUTOFILL
& IDF_CONTENTS
);
1354 bool bIsFiltered
= IsDataFiltered(aFillRange
);
1358 DeleteArea(nCol1
, static_cast<SCROW
>(nIMin
), nCol2
, static_cast<SCROW
>(nIMax
), nDel
);
1360 DeleteArea(static_cast<SCCOL
>(nIMin
), nRow1
, static_cast<SCCOL
>(nIMax
), nRow2
, nDel
);
1363 sal_uLong nProgress
= 0;
1365 nProgress
= pProgress
->GetState();
1371 sal_uLong nActFormCnt
= 0;
1372 for (rOuter
= nOStart
; rOuter
<= nOEnd
; rOuter
++)
1376 // Source cell value. We need to clone the value since it may be inserted repeatedly.
1377 ScCellValue aSrcCell
= aCol
[nCol
].GetCellValue(static_cast<SCROW
>(nRow
));
1381 const ScPatternAttr
* pSrcPattern
= aCol
[nCol
].GetPattern(static_cast<SCROW
>(nRow
));
1383 const ScCondFormatItem
& rCondFormatItem
= static_cast<const ScCondFormatItem
&>(pSrcPattern
->GetItem(ATTR_CONDITIONAL
));
1384 const std::vector
<sal_uInt32
>& rCondFormatIndex
= rCondFormatItem
.GetCondFormatData();
1388 // if not filtered use the faster method
1389 // hidden cols/rows should be skiped
1392 aCol
[nCol
].SetPatternArea( static_cast<SCROW
>(nIMin
),
1393 static_cast<SCROW
>(nIMax
), *pSrcPattern
, true );
1395 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
1396 itr
!= itrEnd
; ++itr
)
1398 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
1399 ScRangeList aRange
= pCondFormat
->GetRange();
1400 aRange
.Join(ScRange(nCol
, nIMin
, nTab
, nCol
, nIMax
, nTab
));
1401 pCondFormat
->AddRange(aRange
);
1406 for(SCROW nAtRow
= static_cast<SCROW
>(nIMin
); nAtRow
<= static_cast<SCROW
>(nIMax
); ++nAtRow
)
1408 if(!RowHidden(nAtRow
))
1410 aCol
[nCol
].SetPatternArea( static_cast<SCROW
>(nAtRow
),
1411 static_cast<SCROW
>(nAtRow
), *pSrcPattern
, true);
1412 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
1413 itr
!= itrEnd
; ++itr
)
1415 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
1416 ScRangeList aRange
= pCondFormat
->GetRange();
1417 aRange
.Join(ScRange(nCol
, nAtRow
, nTab
, nCol
, nAtRow
, nTab
));
1418 pCondFormat
->AddRange(aRange
);
1426 for (SCCOL nAtCol
= static_cast<SCCOL
>(nIMin
); nAtCol
<= sal::static_int_cast
<SCCOL
>(nIMax
); nAtCol
++)
1427 if(!ColHidden(nAtCol
))
1429 aCol
[nAtCol
].SetPattern(static_cast<SCROW
>(nRow
), *pSrcPattern
, true);
1430 for(std::vector
<sal_uInt32
>::const_iterator itr
= rCondFormatIndex
.begin(), itrEnd
= rCondFormatIndex
.end();
1431 itr
!= itrEnd
; ++itr
)
1433 ScConditionalFormat
* pCondFormat
= mpCondFormatList
->GetFormat(*itr
);
1434 ScRangeList aRange
= pCondFormat
->GetRange();
1435 aRange
.Join(ScRange(nAtCol
, static_cast<SCROW
>(nRow
), nTab
, nAtCol
, static_cast<SCROW
>(nRow
), nTab
));
1436 pCondFormat
->AddRange(aRange
);
1441 if (!aSrcCell
.isEmpty())
1443 CellType eCellType
= aSrcCell
.meType
;
1445 if (eFillCmd
== FILL_SIMPLE
) // copy
1447 if (eCellType
== CELLTYPE_FORMULA
)
1450 for (rInner
= nIMin
; rInner
<= nIMax
; rInner
++)
1452 if(HiddenRowColumn(rInner
, bVertical
, this))
1454 sal_uLong nInd
= nActFormCnt
;
1455 FillFormula(nInd
, bFirst
, aSrcCell
.mpFormula
,
1456 static_cast<SCCOL
>(nCol
), nRow
, (rInner
== nIEnd
) );
1459 pProgress
->SetStateOnPercent( ++nProgress
);
1464 for (rInner
= nIMin
; rInner
<= nIMax
; rInner
++)
1466 if(HiddenRowColumn(rInner
, bVertical
, this))
1468 ScAddress
aDestPos( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), nTab
);
1469 aSrcCell
.commit(aCol
[nCol
], aDestPos
.Row());
1471 nProgress
+= nIMax
- nIMin
+ 1;
1473 pProgress
->SetStateOnPercent( nProgress
);
1476 else if (eCellType
== CELLTYPE_VALUE
|| eCellType
== CELLTYPE_FORMULA
)
1479 if (eCellType
== CELLTYPE_VALUE
)
1480 nStartVal
= aSrcCell
.mfValue
;
1482 nStartVal
= aSrcCell
.mpFormula
->GetValue();
1483 double nVal
= nStartVal
;
1486 bool bError
= false;
1487 bool bOverflow
= false;
1489 sal_uInt16 nDayOfMonth
= 0;
1491 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1493 if(!ColHidden(nCol
) && !RowHidden(nRow
))
1495 if (!bError
&& !bOverflow
)
1501 // use multiplication instead of repeated addition
1502 // to avoid accumulating rounding errors
1504 double nAdd
= nStepValue
;
1505 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1506 !SubTotal::SafePlus( nVal
, nAdd
) )
1511 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1515 if (fabs(nVal
) > _D_MAX_LONG_
)
1518 IncDate(nVal
, nDayOfMonth
, nStepValue
, eFillDateCmd
);
1522 // added to avoid warnings
1526 if (nStepValue
>= 0)
1528 if (nVal
> nMaxValue
) // target value reached ?
1536 if (nVal
< nMaxValue
)
1545 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1547 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errIllegalFPOperation
);
1549 aCol
[nCol
].SetValue(static_cast<SCROW
>(nRow
), nVal
);
1552 if (rInner
== nIEnd
)
1563 nProgress
+= nIMax
- nIMin
+ 1;
1565 pProgress
->SetStateOnPercent( nProgress
);
1567 else if (eCellType
== CELLTYPE_STRING
|| eCellType
== CELLTYPE_EDIT
)
1569 if ( nStepValue
>= 0 )
1571 if ( nMaxValue
>= (double)LONG_MAX
)
1572 nMaxValue
= (double)LONG_MAX
- 1;
1576 if ( nMaxValue
<= (double)LONG_MIN
)
1577 nMaxValue
= (double)LONG_MIN
+ 1;
1580 if (eCellType
== CELLTYPE_STRING
)
1581 aValue
= aSrcCell
.mpString
->getString();
1583 aValue
= ScEditUtil::GetString(*aSrcCell
.mpEditText
, pDocument
);
1584 sal_Int32 nStringValue
;
1585 sal_uInt16 nMinDigits
= nArgMinDigits
;
1586 short nHeadNoneTail
= lcl_DecompValueString( aValue
, nStringValue
, &nMinDigits
);
1587 if ( nHeadNoneTail
)
1589 double nStartVal
= (double)nStringValue
;
1590 double nVal
= nStartVal
;
1592 bool bError
= false;
1593 bool bOverflow
= false;
1595 bool bIsOrdinalSuffix
= aValue
.equals( ScGlobal::GetOrdinalSuffix(
1596 (sal_Int32
)nStartVal
));
1599 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1601 if(!ColHidden(nCol
) && !RowHidden(nRow
))
1603 if (!bError
&& !bOverflow
)
1609 // use multiplication instead of repeated addition
1610 // to avoid accumulating rounding errors
1612 double nAdd
= nStepValue
;
1613 if ( !SubTotal::SafeMult( nAdd
, (double) ++nIndex
) ||
1614 !SubTotal::SafePlus( nVal
, nAdd
) )
1619 if (!SubTotal::SafeMult(nVal
, nStepValue
))
1624 // added to avoid warnings
1628 if (nStepValue
>= 0)
1630 if (nVal
> nMaxValue
) // target value reached ?
1638 if (nVal
< nMaxValue
)
1647 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errNoValue
);
1649 aCol
[nCol
].SetError(static_cast<SCROW
>(nRow
), errIllegalFPOperation
);
1652 nStringValue
= (sal_Int32
)nVal
;
1654 if ( nHeadNoneTail
< 0 )
1657 aCol
[nCol
], static_cast<SCROW
>(nRow
),
1658 nStringValue
, nMinDigits
, aValue
,
1659 eCellType
, bIsOrdinalSuffix
);
1664 aStr
+= lcl_ValueString( nStringValue
, nMinDigits
);
1665 aCol
[nCol
].SetRawString(static_cast<SCROW
>(nRow
), aStr
);
1670 if (rInner
== nIEnd
) break;
1671 if (bPositive
) ++rInner
; else --rInner
;
1676 nProgress
+= nIMax
- nIMin
+ 1;
1677 pProgress
->SetStateOnPercent( nProgress
);
1683 nProgress
+= nIMax
- nIMin
+ 1;
1684 pProgress
->SetStateOnPercent( nProgress
);
1690 void ScTable::Fill( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1691 sal_uLong nFillCount
, FillDir eFillDir
, FillCmd eFillCmd
, FillDateCmd eFillDateCmd
,
1692 double nStepValue
, double nMaxValue
, ScProgress
* pProgress
)
1694 if (eFillCmd
== FILL_AUTO
)
1695 FillAuto(nCol1
, nRow1
, nCol2
, nRow2
, nFillCount
, eFillDir
, pProgress
);
1697 FillSeries(nCol1
, nRow1
, nCol2
, nRow2
, nFillCount
, eFillDir
,
1698 eFillCmd
, eFillDateCmd
, nStepValue
, nMaxValue
, 0, true, pProgress
);
1702 void ScTable::AutoFormatArea(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1703 const ScPatternAttr
& rAttr
, sal_uInt16 nFormatNo
)
1705 ScAutoFormat
& rFormat
= *ScGlobal::GetOrCreateAutoFormat();
1706 ScAutoFormatData
* pData
= rFormat
.findByIndex(nFormatNo
);
1709 ApplyPatternArea(nStartCol
, nStartRow
, nEndCol
, nEndRow
, rAttr
);
1713 void ScTable::AutoFormat( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1714 sal_uInt16 nFormatNo
)
1716 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
1718 ScAutoFormat
& rFormat
= *ScGlobal::GetOrCreateAutoFormat();
1719 ScAutoFormatData
* pData
= rFormat
.findByIndex(nFormatNo
);
1722 ScPatternAttr
* pPatternAttrs
[16];
1723 for (sal_uInt8 i
= 0; i
< 16; ++i
)
1725 pPatternAttrs
[i
] = new ScPatternAttr(pDocument
->GetPool());
1726 pData
->FillToItemSet(i
, pPatternAttrs
[i
]->GetItemSet(), *pDocument
);
1729 SCCOL nCol
= nStartCol
;
1730 SCROW nRow
= nStartRow
;
1731 sal_uInt16 nIndex
= 0;
1733 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1735 if (pData
->IsEqualData(4, 8))
1736 AutoFormatArea(nStartCol
, nStartRow
+ 1, nStartCol
, nEndRow
- 1, *pPatternAttrs
[4], nFormatNo
);
1740 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1742 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1749 // Left bottom corner
1752 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1757 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1759 if (pData
->IsEqualData(7, 11))
1760 AutoFormatArea(nEndCol
, nStartRow
+ 1, nEndCol
, nEndRow
- 1, *pPatternAttrs
[7], nFormatNo
);
1764 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1766 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1773 // Right bottom corner
1776 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1779 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1781 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1790 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1792 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1799 if ((pData
->IsEqualData(5, 6)) && (pData
->IsEqualData(9, 10)) && (pData
->IsEqualData(5, 9)))
1800 AutoFormatArea(nStartCol
+ 1, nStartRow
+ 1, nEndCol
-1, nEndRow
- 1, *pPatternAttrs
[5], nFormatNo
);
1803 if ((pData
->IsEqualData(5, 9)) && (pData
->IsEqualData(6, 10)))
1806 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1808 AutoFormatArea(nCol
, nStartRow
+ 1, nCol
, nEndRow
- 1, *pPatternAttrs
[nIndex
], nFormatNo
);
1818 for (nCol
= nStartCol
+ 1; nCol
< nEndCol
; nCol
++)
1820 for (nRow
= nStartRow
+ 1; nRow
< nEndRow
; nRow
++)
1822 AutoFormatArea(nCol
, nRow
, nCol
, nRow
, *pPatternAttrs
[nIndex
], nFormatNo
);
1823 if ((nIndex
== 5) || (nIndex
== 9))
1838 if ((nIndex
== 5) || (nIndex
== 9))
1843 } // if not equal Column
1844 } // if not all equal
1846 for (sal_uInt8 j
= 0; j
< 16; ++j
)
1847 delete pPatternAttrs
[j
];
1848 } // if AutoFormatData != NULL
1852 void ScTable::GetAutoFormatAttr(SCCOL nCol
, SCROW nRow
, sal_uInt16 nIndex
, ScAutoFormatData
& rData
)
1854 sal_uInt32 nFormatIndex
= GetNumberFormat( nCol
, nRow
);
1855 ScNumFormatAbbrev
aNumFormat( nFormatIndex
, *pDocument
->GetFormatTable() );
1856 rData
.GetFromItemSet( nIndex
, GetPattern( nCol
, nRow
)->GetItemSet(), aNumFormat
);
1863 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1865 void ScTable::GetAutoFormatFrame(SCCOL nCol
, SCROW nRow
, sal_uInt16 nFlags
, sal_uInt16 nIndex
, ScAutoFormatData
& rData
)
1867 const SvxBoxItem
* pTheBox
= (SvxBoxItem
*)GetAttr(nCol
, nRow
, ATTR_BORDER
);
1868 const SvxBoxItem
* pLeftBox
= (SvxBoxItem
*)GetAttr(nCol
- 1, nRow
, ATTR_BORDER
);
1869 const SvxBoxItem
* pTopBox
= (SvxBoxItem
*)GetAttr(nCol
, nRow
- 1, ATTR_BORDER
);
1870 const SvxBoxItem
* pRightBox
= (SvxBoxItem
*)GetAttr(nCol
+ 1, nRow
, ATTR_BORDER
);
1871 const SvxBoxItem
* pBottomBox
= (SvxBoxItem
*)GetAttr(nCol
, nRow
+ 1, ATTR_BORDER
);
1873 SvxBoxItem
aBox( ATTR_BORDER
);
1874 if (nFlags
& LF_LEFT
)
1878 if (ScHasPriority(pTheBox
->GetLeft(), pLeftBox
->GetRight()))
1879 aBox
.SetLine(pTheBox
->GetLeft(), BOX_LINE_LEFT
);
1881 aBox
.SetLine(pLeftBox
->GetRight(), BOX_LINE_LEFT
);
1884 aBox
.SetLine(pTheBox
->GetLeft(), BOX_LINE_LEFT
);
1886 if (nFlags
& LF_TOP
)
1890 if (ScHasPriority(pTheBox
->GetTop(), pTopBox
->GetBottom()))
1891 aBox
.SetLine(pTheBox
->GetTop(), BOX_LINE_TOP
);
1893 aBox
.SetLine(pTopBox
->GetBottom(), BOX_LINE_TOP
);
1896 aBox
.SetLine(pTheBox
->GetTop(), BOX_LINE_TOP
);
1898 if (nFlags
& LF_RIGHT
)
1902 if (ScHasPriority(pTheBox
->GetRight(), pRightBox
->GetLeft()))
1903 aBox
.SetLine(pTheBox
->GetRight(), BOX_LINE_RIGHT
);
1905 aBox
.SetLine(pRightBox
->GetLeft(), BOX_LINE_RIGHT
);
1908 aBox
.SetLine(pTheBox
->GetRight(), BOX_LINE_RIGHT
);
1910 if (nFlags
& LF_BOTTOM
)
1914 if (ScHasPriority(pTheBox
->GetBottom(), pBottomBox
->GetTop()))
1915 aBox
.SetLine(pTheBox
->GetBottom(), BOX_LINE_BOTTOM
);
1917 aBox
.SetLine(pBottomBox
->GetTop(), BOX_LINE_BOTTOM
);
1920 aBox
.SetLine(pTheBox
->GetBottom(), BOX_LINE_BOTTOM
);
1922 rData
.PutItem( nIndex
, aBox
);
1925 void ScTable::GetAutoFormatData(SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
, ScAutoFormatData
& rData
)
1927 if (ValidColRow(nStartCol
, nStartRow
) && ValidColRow(nEndCol
, nEndRow
))
1929 if ((nEndCol
- nStartCol
>= 3) && (nEndRow
- nStartRow
>= 3))
1932 GetAutoFormatAttr(nStartCol
, nStartRow
, 0, rData
);
1933 GetAutoFormatFrame(nStartCol
, nStartRow
, LF_ALL
, 0, rData
);
1935 GetAutoFormatAttr(nStartCol
, nStartRow
+ 1, 4, rData
);
1936 GetAutoFormatAttr(nStartCol
, nStartRow
+ 2, 8, rData
);
1937 GetAutoFormatFrame(nStartCol
, nStartRow
+ 1, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 4, rData
);
1938 if (nEndRow
- nStartRow
>= 4)
1939 GetAutoFormatFrame(nStartCol
, nStartRow
+ 2, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 8, rData
);
1941 rData
.CopyItem( 8, 4, ATTR_BORDER
);
1942 // Left bottom corner
1943 GetAutoFormatAttr(nStartCol
, nEndRow
, 12, rData
);
1944 GetAutoFormatFrame(nStartCol
, nEndRow
, LF_ALL
, 12, rData
);
1946 GetAutoFormatAttr(nEndCol
, nStartRow
, 3, rData
);
1947 GetAutoFormatFrame(nEndCol
, nStartRow
, LF_ALL
, 3, rData
);
1949 GetAutoFormatAttr(nEndCol
, nStartRow
+ 1, 7, rData
);
1950 GetAutoFormatAttr(nEndCol
, nStartRow
+ 2, 11, rData
);
1951 GetAutoFormatFrame(nEndCol
, nStartRow
+ 1, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 7, rData
);
1952 if (nEndRow
- nStartRow
>= 4)
1953 GetAutoFormatFrame(nEndCol
, nStartRow
+ 2, LF_LEFT
| LF_RIGHT
| LF_BOTTOM
, 11, rData
);
1955 rData
.CopyItem( 11, 7, ATTR_BORDER
);
1956 // Right bottom corner
1957 GetAutoFormatAttr(nEndCol
, nEndRow
, 15, rData
);
1958 GetAutoFormatFrame(nEndCol
, nEndRow
, LF_ALL
, 15, rData
);
1960 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
, 1, rData
);
1961 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
, 2, rData
);
1962 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 1, rData
);
1963 if (nEndCol
- nStartCol
>= 4)
1964 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 2, rData
);
1966 rData
.CopyItem( 2, 1, ATTR_BORDER
);
1968 GetAutoFormatAttr(nStartCol
+ 1, nEndRow
, 13, rData
);
1969 GetAutoFormatAttr(nStartCol
+ 2, nEndRow
, 14, rData
);
1970 GetAutoFormatFrame(nStartCol
+ 1, nEndRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 13, rData
);
1971 if (nEndCol
- nStartCol
>= 4)
1972 GetAutoFormatFrame(nStartCol
+ 2, nEndRow
, LF_TOP
| LF_BOTTOM
| LF_RIGHT
, 14, rData
);
1974 rData
.CopyItem( 14, 13, ATTR_BORDER
);
1976 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
+ 1, 5, rData
);
1977 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
+ 1, 6, rData
);
1978 GetAutoFormatAttr(nStartCol
+ 1, nStartRow
+ 2, 9, rData
);
1979 GetAutoFormatAttr(nStartCol
+ 2, nStartRow
+ 2, 10, rData
);
1980 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
+ 1, LF_RIGHT
| LF_BOTTOM
, 5, rData
);
1981 if ((nEndCol
- nStartCol
>= 4) && (nEndRow
- nStartRow
>= 4))
1983 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
+ 1, LF_RIGHT
| LF_BOTTOM
, 6, rData
);
1984 GetAutoFormatFrame(nStartCol
+ 1, nStartRow
+ 2, LF_RIGHT
| LF_BOTTOM
, 9, rData
);
1985 GetAutoFormatFrame(nStartCol
+ 2, nStartRow
+ 2, LF_RIGHT
| LF_BOTTOM
, 10, rData
);
1989 rData
.CopyItem( 6, 5, ATTR_BORDER
);
1990 rData
.CopyItem( 9, 5, ATTR_BORDER
);
1991 rData
.CopyItem( 10, 5, ATTR_BORDER
);
1997 void ScTable::SetError( SCCOL nCol
, SCROW nRow
, sal_uInt16 nError
)
1999 if (ValidColRow(nCol
, nRow
))
2000 aCol
[nCol
].SetError( nRow
, nError
);
2003 void ScTable::UpdateInsertTabAbs(SCTAB nTable
)
2005 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
2006 aCol
[i
].UpdateInsertTabAbs(nTable
);
2009 bool ScTable::GetNextSpellingCell(SCCOL
& rCol
, SCROW
& rRow
, bool bInSel
,
2010 const ScMarkData
& rMark
) const
2012 if (rRow
== MAXROW
+2) // end of table
2020 if (rRow
== MAXROW
+1)
2026 if (rCol
== MAXCOL
+1)
2035 bStop
= aCol
[rCol
].GetNextSpellingCell(rRow
, bInSel
, rMark
);
2038 else /*if (rRow == MAXROW+1) */
2051 bool ScTable::TestTabRefAbs(SCTAB nTable
) const
2053 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
2054 if (aCol
[i
].TestTabRefAbs(nTable
))
2059 void ScTable::CompileDBFormula()
2061 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileDBFormula();
2064 void ScTable::CompileDBFormula( bool bCreateFormulaString
)
2066 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileDBFormula( bCreateFormulaString
);
2069 void ScTable::CompileNameFormula( bool bCreateFormulaString
)
2071 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileNameFormula( bCreateFormulaString
);
2074 void ScTable::CompileColRowNameFormula()
2076 for (SCCOL i
=0; i
<=MAXCOL
; i
++) aCol
[i
].CompileColRowNameFormula();
2084 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */