1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27 // System - Includes -----------------------------------------------------
28
29
30
31 #ifdef _MSC_VER
32 #pragma optimize("",off)
33 // sonst Absturz Win beim Fuellen
34 #endif
35
36 // INCLUDE ---------------------------------------------------------------
37
38 #include "scitems.hxx"
39 #include <svx/algitem.hxx>
40 #include <editeng/boxitem.hxx>
41 #include <editeng/brshitem.hxx>
42 #include <editeng/cntritem.hxx>
43 #include <editeng/colritem.hxx>
44 #include <editeng/crsditem.hxx>
45 #include <editeng/fhgtitem.hxx>
46 #include <editeng/fontitem.hxx>
47 #include <editeng/langitem.hxx>
48 #include <editeng/postitem.hxx>
49 #include <editeng/shdditem.hxx>
50 #include <editeng/udlnitem.hxx>
51 #include <editeng/wghtitem.hxx>
52 #include <svx/rotmodit.hxx>
53 #include <editeng/editobj.hxx>
54 #include <editeng/editeng.hxx>
55 #include <editeng/eeitem.hxx>
56 #include <editeng/escpitem.hxx>
57 #include <svl/zforlist.hxx>
58 #include <vcl/keycodes.hxx>
59 #include <rtl/math.hxx>
60 #include <unotools/charclass.hxx>
61
62 #include "attrib.hxx"
63 #include "patattr.hxx"
64 #include "cell.hxx"
65 #include "table.hxx"
66 #include "globstr.hrc"
67 #include "global.hxx"
68 #include "document.hxx"
69 #include "autoform.hxx"
70 #include "userlist.hxx"
71 #include "zforauto.hxx"
72 #include "subtotal.hxx"
73 #include "formula/errorcodes.hxx"
74 #include "rangenam.hxx"
75 #include "docpool.hxx"
76 #include "progress.hxx"
77 #include "segmenttree.hxx"
78
79 #include <math.h>
80
81 // STATIC DATA -----------------------------------------------------------
82
83 #define _D_MAX_LONG_ (double) 0x7fffffff
84
85 extern sal_uInt16 nScFillModeMouseModifier; // global.cxx
86
87 // -----------------------------------------------------------------------
88
lcl_DecompValueString(String & aValue,sal_Int32 & nVal,sal_uInt16 * pMinDigits=NULL)89 short lcl_DecompValueString( String& aValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL )
90 {
91 if ( !aValue.Len() )
92 {
93 nVal = 0;
94 return 0;
95 }
96 const sal_Unicode* p = aValue.GetBuffer();
97 xub_StrLen nNeg = 0;
98 xub_StrLen nNum = 0;
99 if ( p[nNum] == '-' )
100 nNum = nNeg = 1;
101 while ( p[nNum] && CharClass::isAsciiNumeric( p[nNum] ) )
102 nNum++;
103
104 sal_Unicode cNext = p[nNum]; // 0 if at the end
105 sal_Unicode cLast = p[aValue.Len()-1];
106
107 // #i5550# If there are numbers at the beginning and the end,
108 // prefer the one at the beginning only if it's followed by a space.
109 // Otherwise, use the number at the end, to enable things like IP addresses.
110 if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(cLast) ) )
111 { // number at the beginning
112 nVal = aValue.Copy( 0, nNum ).ToInt32();
113 // #60893# any number with a leading zero sets the minimum number of digits
114 if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) )
115 *pMinDigits = nNum - nNeg;
116 aValue.Erase( 0, nNum );
117 return -1;
118 }
119 else
120 {
121 nNeg = 0;
122 xub_StrLen nEnd = nNum = aValue.Len() - 1;
123 while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) )
124 nNum--;
125 if ( p[nNum] == '-' )
126 {
127 nNum--;
128 nNeg = 1;
129 }
130 if ( nNum < nEnd - nNeg )
131 { // number at the end
132 nVal = aValue.Copy( nNum + 1 ).ToInt32();
133 // #60893# any number with a leading zero sets the minimum number of digits
134 if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) )
135 *pMinDigits = nEnd - nNum - nNeg;
136 aValue.Erase( nNum + 1 );
137 return 1;
138 }
139 }
140 nVal = 0;
141 return 0;
142 }
143
lcl_ValueString(sal_Int32 nValue,sal_uInt16 nMinDigits)144 String lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits )
145 {
146 if ( nMinDigits <= 1 )
147 return String::CreateFromInt32( nValue ); // simple case...
148 else
149 {
150 String aStr = String::CreateFromInt32( Abs( nValue ) );
151 if ( aStr.Len() < nMinDigits )
152 {
153 String aZero;
154 aZero.Fill( nMinDigits - aStr.Len(), '0' );
155 aStr.Insert( aZero, 0 );
156 }
157 // nMinDigits doesn't include the '-' sign -> add after inserting zeros
158 if ( nValue < 0 )
159 aStr.Insert( '-', 0 );
160 return aStr;
161 }
162 }
163
lcl_getSuffixCell(ScDocument * pDocument,sal_Int32 nValue,sal_uInt16 nDigits,const String & rSuffix,CellType eCellType,sal_Bool bIsOrdinalSuffix)164 static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue,
165 sal_uInt16 nDigits, const String& rSuffix, CellType eCellType,
166 sal_Bool bIsOrdinalSuffix )
167 {
168 String aValue( lcl_ValueString( nValue, nDigits ));
169 if (!bIsOrdinalSuffix)
170 return new ScStringCell( aValue += rSuffix);
171
172 String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue));
173 if (eCellType != CELLTYPE_EDIT)
174 return new ScStringCell( aValue += aOrdinalSuffix);
175
176 EditEngine aEngine( pDocument->GetEnginePool() );
177 SfxItemSet aAttr = aEngine.GetEmptyItemSet();
178 aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT));
179 aEngine.SetText( aValue );
180 aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0,
181 aValue.Len() + aOrdinalSuffix.Len()));
182 aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() +
183 aOrdinalSuffix.Len()));
184 return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL );
185 }
186
FillAnalyse(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,FillCmd & rCmd,FillDateCmd & rDateCmd,double & rInc,sal_uInt16 & rMinDigits,ScUserListData * & rListData,sal_uInt16 & rListIndex)187 void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
188 FillCmd& rCmd, FillDateCmd& rDateCmd,
189 double& rInc, sal_uInt16& rMinDigits,
190 ScUserListData*& rListData, sal_uInt16& rListIndex)
191 {
192 DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" );
193
194 rInc = 0.0;
195 rMinDigits = 0;
196 rListData = NULL;
197 rCmd = FILL_SIMPLE;
198 if (( nScFillModeMouseModifier & KEY_MOD1 )||IsDataFiltered()) //i89232
199 return ; // Ctrl-Taste: Copy
200
201 SCCOL nAddX;
202 SCROW nAddY;
203 SCSIZE nCount;
204 if (nCol1 == nCol2)
205 {
206 nAddX = 0;
207 nAddY = 1;
208 nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
209 }
210 else
211 {
212 nAddX = 1;
213 nAddY = 0;
214 nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
215 }
216
217 SCCOL nCol = nCol1;
218 SCROW nRow = nRow1;
219
220 ScBaseCell* pFirstCell = GetCell( nCol, nRow );
221 CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE;
222
223 if (eCellType == CELLTYPE_VALUE)
224 {
225 sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue();
226 sal_Bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE );
227 if (bDate)
228 {
229 if (nCount > 1)
230 {
231 long nCmpInc = 0;
232 double nVal;
233 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
234 Date aDate1 = aNullDate;
235 nVal = ((ScValueCell*)pFirstCell)->GetValue();
236 aDate1 += (long)nVal;
237 Date aDate2 = aNullDate;
238 nVal = GetValue(nCol+nAddX, nRow+nAddY);
239 aDate2 += (long)nVal;
240 if ( aDate1 != aDate2 )
241 {
242 FillDateCmd eType;
243 long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
244 long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
245 long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
246 if ( nDDiff )
247 {
248 eType = FILL_DAY;
249 nCmpInc = aDate2 - aDate1;
250 }
251 else
252 {
253 eType = FILL_MONTH;
254 nCmpInc = nMDiff + 12 * nYDiff;
255 }
256
257 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
258 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
259 sal_Bool bVal = sal_True;
260 for (sal_uInt16 i=1; i<nCount && bVal; i++)
261 {
262 ScBaseCell* pCell = GetCell(nCol,nRow);
263 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
264 {
265 nVal = ((ScValueCell*)pCell)->GetValue();
266 aDate2 = aNullDate + (long) nVal;
267 if ( eType == FILL_DAY )
268 {
269 if ( aDate2-aDate1 != nCmpInc )
270 bVal = sal_False;
271 }
272 else
273 {
274 nDDiff = aDate2.GetDay() - (long) aDate1.GetDay();
275 nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth();
276 nYDiff = aDate2.GetYear() - (long) aDate1.GetYear();
277 if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc ))
278 bVal = sal_False;
279 }
280 aDate1 = aDate2;
281 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
282 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
283 }
284 else
285 bVal = sal_False; // #50965# kein Datum passt auch nicht
286 }
287 if (bVal)
288 {
289 if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) )
290 {
291 eType = FILL_YEAR;
292 nCmpInc /= 12;
293 }
294 rCmd = FILL_DATE;
295 rDateCmd = eType;
296 rInc = nCmpInc;
297 }
298 }
299 }
300 else // einzelnes Datum -> Tage hochzaehlen
301 {
302 rCmd = FILL_DATE;
303 rDateCmd = FILL_DAY;
304 rInc = 1.0;
305 }
306 }
307 else
308 {
309 if (nCount > 1)
310 {
311 double nVal1 = ((ScValueCell*)pFirstCell)->GetValue();
312 double nVal2 = GetValue(nCol+nAddX, nRow+nAddY);
313 rInc = nVal2 - nVal1;
314 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
315 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
316 sal_Bool bVal = sal_True;
317 for (sal_uInt16 i=1; i<nCount && bVal; i++)
318 {
319 ScBaseCell* pCell = GetCell(nCol,nRow);
320 if (pCell && pCell->GetCellType() == CELLTYPE_VALUE)
321 {
322 nVal2 = ((ScValueCell*)pCell)->GetValue();
323 double nDiff = nVal2 - nVal1;
324 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
325 bVal = sal_False;
326 nVal1 = nVal2;
327 }
328 else
329 bVal = sal_False;
330 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
331 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
332 }
333 if (bVal)
334 rCmd = FILL_LINEAR;
335 }
336 }
337 }
338 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
339 {
340 String aStr;
341 GetString(nCol, nRow, aStr);
342 rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr));
343 if (rListData)
344 {
345 rListData->GetSubIndex(aStr, rListIndex);
346 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
347 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
348 for (sal_uInt16 i=1; i<nCount && rListData; i++)
349 {
350 GetString(nCol, nRow, aStr);
351 if (!rListData->GetSubIndex(aStr, rListIndex))
352 rListData = NULL;
353 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
354 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
355 }
356 }
357 else if ( nCount > 1 )
358 {
359 // pass rMinDigits to all DecompValueString calls
360 // -> longest number defines rMinDigits
361
362 sal_Int32 nVal1;
363 short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits );
364 if ( nFlag1 )
365 {
366 sal_Int32 nVal2;
367 GetString( nCol+nAddX, nRow+nAddY, aStr );
368 short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
369 if ( nFlag1 == nFlag2 )
370 {
371 rInc = (double)nVal2 - (double)nVal1;
372 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
373 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
374 sal_Bool bVal = sal_True;
375 for (sal_uInt16 i=1; i<nCount && bVal; i++)
376 {
377 ScBaseCell* pCell = GetCell(nCol,nRow);
378 CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE;
379 if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
380 {
381 if ( eType == CELLTYPE_STRING )
382 ((ScStringCell*)pCell)->GetString( aStr );
383 else
384 ((ScEditCell*)pCell)->GetString( aStr );
385 nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits );
386 if ( nFlag1 == nFlag2 )
387 {
388 double nDiff = (double)nVal2 - (double)nVal1;
389 if ( !::rtl::math::approxEqual( nDiff, rInc ) )
390 bVal = sal_False;
391 nVal1 = nVal2;
392 }
393 else
394 bVal = sal_False;
395 }
396 else
397 bVal = sal_False;
398 nCol = sal::static_int_cast<SCCOL>( nCol + nAddX );
399 nRow = sal::static_int_cast<SCROW>( nRow + nAddY );
400 }
401 if (bVal)
402 rCmd = FILL_LINEAR;
403 }
404 }
405 }
406 else
407 {
408 // call DecompValueString to set rMinDigits
409 sal_Int32 nDummy;
410 lcl_DecompValueString( aStr, nDummy, &rMinDigits );
411 }
412 }
413 }
414
FillFormula(sal_uLong &,sal_Bool,ScFormulaCell * pSrcCell,SCCOL nDestCol,SCROW nDestRow,sal_Bool bLast)415 void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, sal_Bool /* bFirst */, ScFormulaCell* pSrcCell,
416 SCCOL nDestCol, SCROW nDestRow, sal_Bool bLast )
417 {
418 /* sal_uInt16 nTokArrLen = pSrcCell->GetTokenArrayLen();
419 if ( nTokArrLen > 15 ) // mehr als =A1 oder =67
420 {
421 ScRangeName* pRangeName = pDocument->GetRangeName();
422 String aName("___SC_"); // Wird dieser String veraendert,
423 // auch in document2 EraseNonUsed...
424 // mitaendern!!
425 aName += pRangeName->GetSharedMaxIndex() + 1;
426 aName += '_';
427 aName += nFormulaCounter;
428 nFormulaCounter++;
429 if (bFirst)
430 {
431 ScRangeData *pAktRange = new ScRangeData(
432 pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen,
433 pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED);
434 if (!pRangeName->Insert( pAktRange ))
435 delete pAktRange;
436 else
437 bSharedNameInserted = sal_True;
438 }
439 sal_uInt16 nIndex;
440 pRangeName->SearchName(aName, nIndex);
441 if (!pRangeName)
442 {
443 DBG_ERROR("ScTable::FillFormula: Falscher Name");
444 return;
445 }
446 nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex();
447 ScTokenArray aArr;
448 aArr.AddName(nIndex);
449 aArr.AddOpCode(ocStop);
450 ScFormulaCell* pDestCell = new ScFormulaCell
451 (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr );
452 aCol[nDestCol].Insert(nDestRow, pDestCell);
453 }
454 else
455 */ {
456 pDocument->SetNoListening( sal_True ); // noch falsche Referenzen
457 ScAddress aAddr( nDestCol, nDestRow, nTab );
458 ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr );
459 aCol[nDestCol].Insert(nDestRow, pDestCell);
460 #if 0
461 // mit RelRefs unnoetig
462 pDestCell->UpdateReference(URM_COPY,
463 ScRange( aAddr, aAddr ),
464 nDestCol - pSrcCell->aPos.Col(),
465 nDestRow - pSrcCell->aPos.Row(), 0);
466 #endif
467 if ( bLast && pDestCell->GetMatrixFlag() )
468 {
469 ScAddress aOrg;
470 if ( pDestCell->GetMatrixOrigin( aOrg ) )
471 {
472 if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() )
473 {
474 ScBaseCell* pOrgCell = pDocument->GetCell( aOrg );
475 if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA
476 && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA )
477 {
478 ((ScFormulaCell*)pOrgCell)->SetMatColsRows(
479 nDestCol - aOrg.Col() + 1,
480 nDestRow - aOrg.Row() + 1 );
481 }
482 else
483 {
484 DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" );
485 }
486 }
487 else
488 {
489 DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" );
490 }
491 }
492 else
493 {
494 DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" );
495 }
496 }
497 pDocument->SetNoListening( sal_False );
498 pDestCell->StartListeningTo( pDocument );
499 }
500 }
501
FillAuto(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uLong nFillCount,FillDir eFillDir,ScProgress & rProgress)502 void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
503 sal_uLong nFillCount, FillDir eFillDir, ScProgress& rProgress )
504 {
505 if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) )
506 return;
507
508 //
509 // Richtung auswerten
510 //
511
512 sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
513 sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
514
515 sal_uLong nCol = 0;
516 sal_uLong nRow = 0;
517 sal_uLong& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
518 sal_uLong& rOuter = bVertical ? nCol : nRow;
519 sal_uLong nOStart;
520 sal_uLong nOEnd;
521 sal_uLong nIStart;
522 sal_uLong nIEnd;
523 sal_uLong nISrcStart;
524 sal_uLong nISrcEnd;
525
526 if (bVertical)
527 {
528 nOStart = nCol1;
529 nOEnd = nCol2;
530 if (bPositive)
531 {
532 nISrcStart = nRow1;
533 nISrcEnd = nRow2;
534 nIStart = nRow2 + 1;
535 nIEnd = nRow2 + nFillCount;
536 }
537 else
538 {
539 nISrcStart = nRow2;
540 nISrcEnd = nRow1;
541 nIStart = nRow1 - 1;
542 nIEnd = nRow1 - nFillCount;
543 }
544 }
545 else
546 {
547 nOStart = nRow1;
548 nOEnd = nRow2;
549 if (bPositive)
550 {
551 nISrcStart = nCol1;
552 nISrcEnd = nCol2;
553 nIStart = nCol2 + 1;
554 nIEnd = nCol2 + nFillCount;
555 }
556 else
557 {
558 nISrcStart = nCol2;
559 nISrcEnd = nCol1;
560 nIStart = nCol1 - 1;
561 nIEnd = nCol1 - nFillCount;
562 }
563 }
564 sal_uLong nIMin = nIStart;
565 sal_uLong nIMax = nIEnd;
566 PutInOrder(nIMin,nIMax);
567 sal_Bool bHasFiltered = IsDataFiltered();
568 if (!bHasFiltered) //modify for i89232
569 {
570 if (bVertical)
571 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL);
572 else
573 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL);
574 }
575 sal_uLong nProgress = rProgress.GetState();
576
577 //
578 // ausfuehren
579 //
580
581 sal_uLong nActFormCnt = 0;
582 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
583 {
584 sal_uLong nMaxFormCnt = 0; // fuer Formeln
585
586 // Attributierung uebertragen
587
588 const ScPatternAttr* pSrcPattern = NULL;
589 const ScStyleSheet* pStyleSheet = NULL;
590 sal_uLong nAtSrc = nISrcStart;
591 ScPatternAttr* pNewPattern = NULL;
592 sal_Bool bGetPattern = sal_True;
593 rInner = nIStart;
594 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
595 {
596 if ( bGetPattern )
597 {
598 if ( pNewPattern )
599 delete pNewPattern;
600 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
601 pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc));
602 else // rInner&:=nCol, rOuter&:=nRow
603 pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow));
604 bGetPattern = sal_False;
605 pStyleSheet = pSrcPattern->GetStyleSheet();
606 // Merge/Mergeflag nicht uebernehmen,
607 const SfxItemSet& rSet = pSrcPattern->GetItemSet();
608 if ( rSet.GetItemState(ATTR_MERGE, sal_False) == SFX_ITEM_SET
609 || rSet.GetItemState(ATTR_MERGE_FLAG, sal_False) == SFX_ITEM_SET )
610 {
611 pNewPattern = new ScPatternAttr( *pSrcPattern );
612 SfxItemSet& rNewSet = pNewPattern->GetItemSet();
613 rNewSet.ClearItem(ATTR_MERGE);
614 rNewSet.ClearItem(ATTR_MERGE_FLAG);
615 }
616 else
617 pNewPattern = NULL;
618 }
619
620 if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
621 {
622 // Attribute komplett am Stueck setzen
623 if (pNewPattern || pSrcPattern != pDocument->GetDefPattern())
624 {
625 // Default steht schon da (DeleteArea)
626 SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd ));
627 SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd ));
628 if ( pStyleSheet )
629 aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet );
630 if ( pNewPattern )
631 aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern );
632 else
633 aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern );
634 }
635 break; // Schleife abbrechen
636 }
637
638 if ( !RowFiltered(nRow) )
639 {
640 if ( bHasFiltered )
641 DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow),
642 static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL);
643
644 if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) )
645 {
646 // Vorlage auch uebernehmen
647 //! am AttrArray mit ApplyPattern zusammenfassen ??
648 if ( pStyleSheet )
649 aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet );
650
651 // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen
652 if ( pNewPattern )
653 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern );
654 else
655 aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern );
656 }
657
658 if (nAtSrc==nISrcEnd)
659 {
660 if ( nAtSrc != nISrcStart )
661 { // mehr als eine Source-Zelle
662 nAtSrc = nISrcStart;
663 bGetPattern = sal_True;
664 }
665 }
666 else if (bPositive)
667 {
668 ++nAtSrc;
669 bGetPattern = sal_True;
670 }
671 else
672 {
673 --nAtSrc;
674 bGetPattern = sal_True;
675 }
676 }
677
678 if (rInner == nIEnd) break;
679 if (bPositive) ++rInner; else --rInner;
680 }
681 if ( pNewPattern )
682 delete pNewPattern;
683
684 // Analyse
685
686 FillCmd eFillCmd;
687 FillDateCmd eDateCmd;
688 double nInc;
689 sal_uInt16 nMinDigits;
690 ScUserListData* pListData = NULL;
691 sal_uInt16 nListIndex;
692 if (bVertical)
693 FillAnalyse(static_cast<SCCOL>(nCol),nRow1,
694 static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd,
695 nInc,nMinDigits, pListData,nListIndex);
696 else
697 FillAnalyse(nCol1,static_cast<SCROW>(nRow),
698 nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd,
699 nInc,nMinDigits, pListData,nListIndex);
700
701 if (bVertical)
702 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
703
704 if (pListData)
705 {
706 sal_uInt16 nListCount = pListData->GetSubCount();
707 if ( !bPositive )
708 {
709 // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen
710 sal_uLong nSub = nISrcStart - nISrcEnd;
711 for (sal_uLong i=0; i<nSub; i++)
712 {
713 if (nListIndex == 0) nListIndex = nListCount;
714 --nListIndex;
715 }
716 }
717
718 rInner = nIStart;
719 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
720 {
721 if (bPositive)
722 {
723 ++nListIndex;
724 if (nListIndex >= nListCount) nListIndex = 0;
725 }
726 else
727 {
728 if (nListIndex == 0) nListIndex = nListCount;
729 --nListIndex;
730 }
731 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex)));
732
733 if (rInner == nIEnd) break;
734 if (bPositive) ++rInner; else --rInner;
735 }
736 nProgress += nIMax - nIMin + 1;
737 rProgress.SetStateOnPercent( nProgress );
738 }
739 else if (eFillCmd == FILL_SIMPLE) // Auffuellen mit Muster
740 {
741 sal_uLong nSource = nISrcStart;
742 double nDelta;
743 if (( nScFillModeMouseModifier & KEY_MOD1 )||bHasFiltered) //i89232
744 nDelta = 0.0;
745 else if ( bPositive )
746 nDelta = 1.0;
747 else
748 nDelta = -1.0;
749 double nVal = 0.0;
750 sal_uLong nFormulaCounter = nActFormCnt;
751 sal_Bool bFirst = sal_True;
752 sal_Bool bGetCell = sal_True;
753 sal_uInt16 nCellDigits = 0;
754 short nHeadNoneTail = 0;
755 sal_Int32 nStringValue = 0;
756 String aValue;
757 ScBaseCell* pSrcCell = NULL;
758 CellType eCellType = CELLTYPE_NONE;
759 sal_Bool bIsOrdinalSuffix = sal_False;
760 sal_Bool bRowFiltered = sal_False; //i89232
761
762 rInner = nIStart;
763 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
764 {
765 if ( bGetCell )
766 {
767 if (bVertical) // rInner&:=nRow, rOuter&:=nCol
768 pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) );
769 else // rInner&:=nCol, rOuter&:=nRow
770 pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) );
771 bGetCell = sal_False;
772 if ( pSrcCell )
773 {
774 eCellType = pSrcCell->GetCellType();
775 switch ( eCellType )
776 {
777 case CELLTYPE_VALUE:
778 nVal = ((ScValueCell*)pSrcCell)->GetValue();
779 break;
780 case CELLTYPE_STRING:
781 case CELLTYPE_EDIT:
782 if ( eCellType == CELLTYPE_STRING )
783 ((ScStringCell*)pSrcCell)->GetString( aValue );
784 else
785 ((ScEditCell*)pSrcCell)->GetString( aValue );
786 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered) //i89232
787 {
788 nCellDigits = 0; // look at each source cell individually
789 nHeadNoneTail = lcl_DecompValueString(
790 aValue, nStringValue, &nCellDigits );
791
792 bIsOrdinalSuffix = aValue.Equals(
793 ScGlobal::GetOrdinalSuffix( nStringValue));
794 }
795 break;
796 default:
797 {
798 // added to avoid warnings
799 }
800 }
801 }
802 else
803 eCellType = CELLTYPE_NONE;
804 }
805
806 //Modify for i89232
807 bRowFiltered = mpFilteredRows->getValue(nRow);
808
809 if (!bRowFiltered)
810 {
811 //End of i89232
812
813 switch (eCellType)
814 {
815 case CELLTYPE_VALUE:
816 aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta));
817 break;
818 case CELLTYPE_STRING:
819 case CELLTYPE_EDIT:
820 if ( nHeadNoneTail )
821 {
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;
826
827 String aStr;
828 if ( nHeadNoneTail < 0 )
829 {
830 aCol[nCol].Insert( static_cast<SCROW>(nRow),
831 lcl_getSuffixCell( pDocument,
832 nNextValue, nCellDigits, aValue,
833 eCellType, bIsOrdinalSuffix));
834 }
835 else
836 {
837 aStr = aValue;
838 aStr += lcl_ValueString( nNextValue, nCellDigits );
839 aCol[nCol].Insert( static_cast<SCROW>(nRow),
840 new ScStringCell( aStr));
841 }
842 }
843 else
844 {
845 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
846 switch ( eCellType )
847 {
848 case CELLTYPE_STRING:
849 case CELLTYPE_EDIT:
850 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
851 break;
852 default:
853 {
854 // added to avoid warnings
855 }
856 }
857 }
858 break;
859 case CELLTYPE_FORMULA :
860 FillFormula( nFormulaCounter, bFirst,
861 (ScFormulaCell*) pSrcCell,
862 static_cast<SCCOL>(nCol),
863 static_cast<SCROW>(nRow), (rInner == nIEnd) );
864 if (nFormulaCounter - nActFormCnt > nMaxFormCnt)
865 nMaxFormCnt = nFormulaCounter - nActFormCnt;
866 break;
867 default:
868 {
869 // added to avoid warnings
870 }
871 }
872
873 if (nSource==nISrcEnd)
874 {
875 if ( nSource != nISrcStart )
876 { // mehr als eine Source-Zelle
877 nSource = nISrcStart;
878 bGetCell = sal_True;
879 }
880 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered ) //i89232
881 {
882 if ( bPositive )
883 nDelta += 1.0;
884 else
885 nDelta -= 1.0;
886 }
887 nFormulaCounter = nActFormCnt;
888 bFirst = sal_False;
889 }
890 else if (bPositive)
891 {
892 ++nSource;
893 bGetCell = sal_True;
894 }
895 else
896 {
897 --nSource;
898 bGetCell = sal_True;
899 }
900 }
901
902 // Progress in der inneren Schleife nur bei teuren Zellen,
903 // und auch dann nicht fuer jede einzelne
904
905 ++nProgress;
906 if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT )
907 rProgress.SetStateOnPercent( nProgress );
908
909 if (rInner == nIEnd) break;
910 if (bPositive) ++rInner; else --rInner;
911 }
912 rProgress.SetStateOnPercent( nProgress );
913 }
914 else
915 {
916 if (!bPositive)
917 nInc = -nInc;
918 double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE;
919 if (bVertical)
920 FillSeries( static_cast<SCCOL>(nCol), nRow1,
921 static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir,
922 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False,
923 rProgress );
924 else
925 FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2,
926 static_cast<SCROW>(nRow), nFillCount, eFillDir,
927 eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False,
928 rProgress );
929 nProgress = rProgress.GetState();
930 }
931
932 nActFormCnt += nMaxFormCnt;
933 }
934 }
935
GetAutoFillPreview(const ScRange & rSource,SCCOL nEndX,SCROW nEndY)936 String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
937 {
938 String aValue;
939
940 SCCOL nCol1 = rSource.aStart.Col();
941 SCROW nRow1 = rSource.aStart.Row();
942 SCCOL nCol2 = rSource.aEnd.Col();
943 SCROW nRow2 = rSource.aEnd.Row();
944 sal_Bool bOk = sal_True;
945 long nIndex = 0;
946 sal_uLong nSrcCount = 0;
947 FillDir eFillDir = FILL_TO_BOTTOM;
948 if ( nEndX == nCol2 && nEndY == nRow2 ) // leer
949 bOk = sal_False;
950 else if ( nEndX == nCol2 ) // nach oben/unten
951 {
952 nEndX = nCol2 = nCol1; // nur erste Spalte ansehen
953 nSrcCount = nRow2 - nRow1 + 1;
954 nIndex = ((long)nEndY) - nRow1; // kann negativ werden
955 if ( nEndY >= nRow1 )
956 eFillDir = FILL_TO_BOTTOM;
957 else
958 eFillDir = FILL_TO_TOP;
959 }
960 else if ( nEndY == nRow2 ) // nach links/rechts
961 {
962 nEndY = nRow2 = nRow1; // nur erste Zeile ansehen
963 nSrcCount = nCol2 - nCol1 + 1;
964 nIndex = ((long)nEndX) - nCol1; // kann negativ werden
965 if ( nEndX >= nCol1 )
966 eFillDir = FILL_TO_RIGHT;
967 else
968 eFillDir = FILL_TO_LEFT;
969 }
970 else // Richtung nicht eindeutig
971 bOk = sal_False;
972
973 if ( bOk )
974 {
975 FillCmd eFillCmd;
976 FillDateCmd eDateCmd;
977 double nInc;
978 sal_uInt16 nMinDigits;
979 ScUserListData* pListData = NULL;
980 sal_uInt16 nListIndex;
981
982 FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex);
983
984 if ( pListData ) // benutzerdefinierte Liste
985 {
986 sal_uInt16 nListCount = pListData->GetSubCount();
987 if ( nListCount )
988 {
989 sal_uLong nSub = nSrcCount - 1; // nListIndex ist vom letzten Source-Eintrag
990 while ( nIndex < sal::static_int_cast<long>(nSub) )
991 nIndex += nListCount;
992 sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount;
993 aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos));
994 }
995 }
996 else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster
997 {
998 //Add for i89232
999 if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP))
1000 {
1001 long nBegin = 0;
1002 long nEnd = 0;
1003 if (nEndY > nRow1)
1004 {
1005 nBegin = nRow2+1;
1006 nEnd = nEndY;
1007 }
1008 else
1009 {
1010 nBegin = nEndY;
1011 nEnd = nRow1 -1;
1012 }
1013 long nNonFiltered = CountNonFilteredRows(nBegin, nEnd);
1014 long nFiltered = nEnd + 1 - nBegin - nNonFiltered;
1015 if (nIndex >0)
1016 nIndex = nIndex - nFiltered;
1017 else
1018 nIndex = nIndex + nFiltered;
1019 }
1020 //End of i89232
1021
1022 long nPosIndex = nIndex;
1023 while ( nPosIndex < 0 )
1024 nPosIndex += nSrcCount;
1025 sal_uLong nPos = nPosIndex % nSrcCount;
1026 SCCOL nSrcX = nCol1;
1027 SCROW nSrcY = nRow1;
1028 if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM )
1029 nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) );
1030 else
1031 nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) );
1032
1033 ScBaseCell* pCell = GetCell( nSrcX, nSrcY );
1034 if ( pCell )
1035 {
1036 sal_Int32 nDelta;
1037 if (nIndex >= 0)
1038 nDelta = nIndex / nSrcCount;
1039 else
1040 nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1
1041
1042 CellType eType = pCell->GetCellType();
1043 switch ( eType )
1044 {
1045 case CELLTYPE_STRING:
1046 case CELLTYPE_EDIT:
1047 {
1048 if ( eType == CELLTYPE_STRING )
1049 ((ScStringCell*)pCell)->GetString( aValue );
1050 else
1051 ((ScEditCell*)pCell)->GetString( aValue );
1052 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232
1053 {
1054 sal_Int32 nVal;
1055 sal_uInt16 nCellDigits = 0; // look at each source cell individually
1056 short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits );
1057 if ( nFlag < 0 )
1058 {
1059 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1060 aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta);
1061
1062 aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 );
1063 }
1064 else if ( nFlag > 0 )
1065 aValue += lcl_ValueString( nVal + nDelta, nCellDigits );
1066 }
1067 }
1068 break;
1069 case CELLTYPE_VALUE:
1070 {
1071 // dabei kann's keinen Ueberlauf geben...
1072 double nVal = ((ScValueCell*)pCell)->GetValue();
1073 if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232
1074 nVal += (double) nDelta;
1075
1076 Color* pColor;
1077 sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY );
1078 pDocument->GetFormatTable()->
1079 GetOutputString( nVal, nNumFmt, aValue, &pColor );
1080 }
1081 break;
1082 // Formeln nicht
1083 default:
1084 {
1085 // added to avoid warnings
1086 }
1087 }
1088 }
1089 }
1090 else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // Werte
1091 {
1092 sal_Bool bValueOk;
1093 double nStart;
1094 sal_Int32 nVal = 0;
1095 short nHeadNoneTail = 0;
1096 ScBaseCell* pCell = GetCell( nCol1, nRow1 );
1097 if ( pCell )
1098 {
1099 CellType eType = pCell->GetCellType();
1100 switch ( eType )
1101 {
1102 case CELLTYPE_STRING:
1103 case CELLTYPE_EDIT:
1104 {
1105 if ( eType == CELLTYPE_STRING )
1106 ((ScStringCell*)pCell)->GetString( aValue );
1107 else
1108 ((ScEditCell*)pCell)->GetString( aValue );
1109 nHeadNoneTail = lcl_DecompValueString( aValue, nVal );
1110 if ( nHeadNoneTail )
1111 nStart = (double)nVal;
1112 else
1113 nStart = 0.0;
1114 }
1115 break;
1116 case CELLTYPE_VALUE:
1117 nStart = ((ScValueCell*)pCell)->GetValue();
1118 break;
1119 case CELLTYPE_FORMULA:
1120 nStart = ((ScFormulaCell*)pCell)->GetValue();
1121 break;
1122 default:
1123 nStart = 0.0;
1124 }
1125 }
1126 else
1127 nStart = 0.0;
1128 if ( eFillCmd == FILL_LINEAR )
1129 {
1130 double nAdd = nInc;
1131 bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) &&
1132 SubTotal::SafePlus( nStart, nAdd ) );
1133 }
1134 else // Datum
1135 {
1136 bValueOk = sal_True;
1137 sal_uInt16 nDayOfMonth = 0;
1138 if ( nIndex < 0 )
1139 {
1140 nIndex = -nIndex;
1141 nInc = -nInc;
1142 }
1143 for (long i=0; i<nIndex; i++)
1144 IncDate( nStart, nDayOfMonth, nInc, eDateCmd );
1145 }
1146
1147 if (bValueOk)
1148 {
1149 if ( nHeadNoneTail )
1150 {
1151 if ( nHeadNoneTail < 0 )
1152 {
1153 if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal)))
1154 aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart );
1155
1156 aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 );
1157 }
1158 else
1159 aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits );
1160 }
1161 else
1162 {
1163 //! Zahlformat je nach Index holen?
1164 Color* pColor;
1165 sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 );
1166 pDocument->GetFormatTable()->
1167 GetOutputString( nStart, nNumFmt, aValue, &pColor );
1168 }
1169 }
1170 }
1171 else
1172 {
1173 DBG_ERROR("GetAutoFillPreview: falscher Modus");
1174 }
1175 }
1176
1177 return aValue;
1178 }
1179
IncDate(double & rVal,sal_uInt16 & nDayOfMonth,double nStep,FillDateCmd eCmd)1180 void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd)
1181 {
1182 if (eCmd == FILL_DAY)
1183 {
1184 rVal += nStep;
1185 return;
1186 }
1187
1188 // class Date Grenzen
1189 const sal_uInt16 nMinYear = 1583;
1190 const sal_uInt16 nMaxYear = 9956;
1191
1192 long nInc = (long) nStep; // nach oben/unten begrenzen ?
1193 Date aNullDate = *pDocument->GetFormatTable()->GetNullDate();
1194 Date aDate = aNullDate;
1195 aDate += (long)rVal;
1196 switch (eCmd)
1197 {
1198 case FILL_WEEKDAY:
1199 {
1200 aDate += nInc;
1201 DayOfWeek eWeekDay = aDate.GetDayOfWeek();
1202 if (nInc >= 0)
1203 {
1204 if (eWeekDay == SATURDAY)
1205 aDate += 2;
1206 else if (eWeekDay == SUNDAY)
1207 aDate += 1;
1208 }
1209 else
1210 {
1211 if (eWeekDay == SATURDAY)
1212 aDate -= 1;
1213 else if (eWeekDay == SUNDAY)
1214 aDate -= 2;
1215 }
1216 }
1217 break;
1218 case FILL_MONTH:
1219 {
1220 if ( nDayOfMonth == 0 )
1221 nDayOfMonth = aDate.GetDay(); // init
1222 long nMonth = aDate.GetMonth();
1223 long nYear = aDate.GetYear();
1224
1225 nMonth += nInc;
1226
1227 if (nInc >= 0)
1228 {
1229 if (nMonth > 12)
1230 {
1231 long nYAdd = (nMonth-1) / 12;
1232 nMonth -= nYAdd * 12;
1233 nYear += nYAdd;
1234 }
1235 }
1236 else
1237 {
1238 if (nMonth < 1)
1239 {
1240 long nYAdd = 1 - nMonth / 12; // positiv
1241 nMonth += nYAdd * 12;
1242 nYear -= nYAdd;
1243 }
1244 }
1245
1246 if ( nYear < nMinYear )
1247 aDate = Date( 1,1, nMinYear );
1248 else if ( nYear > nMaxYear )
1249 aDate = Date( 31,12, nMaxYear );
1250 else
1251 {
1252 aDate.SetMonth((sal_uInt16) nMonth);
1253 aDate.SetYear((sal_uInt16) nYear);
1254 if ( nDayOfMonth > 28 )
1255 aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) );
1256 }
1257 }
1258 break;
1259 case FILL_YEAR:
1260 {
1261 long nYear = aDate.GetYear();
1262 nYear += nInc;
1263 if ( nYear < nMinYear )
1264 aDate = Date( 1,1, nMinYear );
1265 else if ( nYear > nMaxYear )
1266 aDate = Date( 31,12, nMaxYear );
1267 else
1268 aDate.SetYear((sal_uInt16) nYear);
1269 }
1270 break;
1271 default:
1272 {
1273 // added to avoid warnings
1274 }
1275 }
1276
1277 rVal = aDate - aNullDate;
1278 }
1279
FillSeries(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uLong nFillCount,FillDir eFillDir,FillCmd eFillCmd,FillDateCmd eFillDateCmd,double nStepValue,double nMaxValue,sal_uInt16 nArgMinDigits,sal_Bool bAttribs,ScProgress & rProgress)1280 void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1281 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1282 double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits,
1283 sal_Bool bAttribs, ScProgress& rProgress )
1284 {
1285 //
1286 // Richtung auswerten
1287 //
1288
1289 sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP);
1290 sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT);
1291
1292 sal_uLong nCol = 0;
1293 sal_uLong nRow = 0;
1294 sal_uLong& rInner = bVertical ? nRow : nCol; // Schleifenvariablen
1295 sal_uLong& rOuter = bVertical ? nCol : nRow;
1296 sal_uLong nOStart;
1297 sal_uLong nOEnd;
1298 sal_uLong nIStart;
1299 sal_uLong nIEnd;
1300 sal_uLong nISource;
1301
1302 if (bVertical)
1303 {
1304 nFillCount += (nRow2 - nRow1);
1305 if (nFillCount == 0)
1306 return;
1307 nOStart = nCol1;
1308 nOEnd = nCol2;
1309 if (bPositive)
1310 {
1311 nISource = nRow1;
1312 nIStart = nRow1 + 1;
1313 nIEnd = nRow1 + nFillCount;
1314 }
1315 else
1316 {
1317 nISource = nRow2;
1318 nIStart = nRow2 - 1;
1319 nIEnd = nRow2 - nFillCount;
1320 }
1321 }
1322 else
1323 {
1324 nFillCount += (nCol2 - nCol1);
1325 if (nFillCount == 0)
1326 return;
1327 nOStart = nRow1;
1328 nOEnd = nRow2;
1329 if (bPositive)
1330 {
1331 nISource = nCol1;
1332 nIStart = nCol1 + 1;
1333 nIEnd = nCol1 + nFillCount;
1334 }
1335 else
1336 {
1337 nISource = nCol2;
1338 nIStart = nCol2 - 1;
1339 nIEnd = nCol2 - nFillCount;
1340 }
1341 }
1342
1343 sal_uLong nIMin = nIStart;
1344 sal_uLong nIMax = nIEnd;
1345 PutInOrder(nIMin,nIMax);
1346 sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS);
1347 if (bVertical)
1348 DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel);
1349 else
1350 DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel);
1351
1352 sal_uLong nProgress = rProgress.GetState();
1353
1354 //
1355 // ausfuehren
1356 //
1357
1358 sal_uLong nActFormCnt = 0;
1359 for (rOuter = nOStart; rOuter <= nOEnd; rOuter++)
1360 {
1361 sal_Bool bFirst = sal_True;
1362 rInner = nISource;
1363 ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow));
1364
1365 if (bVertical && bAttribs)
1366 aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount );
1367
1368 if (bAttribs)
1369 {
1370 const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));
1371 if (bVertical)
1372 aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin),
1373 static_cast<SCROW>(nIMax), *pSrcPattern, sal_True );
1374 else
1375 for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++)
1376 aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, sal_True);
1377 }
1378
1379 if (pSrcCell)
1380 {
1381 CellType eCellType = pSrcCell->GetCellType();
1382
1383 if (eFillCmd == FILL_SIMPLE) // kopieren
1384 {
1385 if (eCellType == CELLTYPE_FORMULA)
1386 {
1387 for (rInner = nIMin; rInner <= nIMax; rInner++)
1388 {
1389 sal_uLong nInd = nActFormCnt;
1390 FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell,
1391 static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) );
1392 bFirst = sal_False;
1393 rProgress.SetStateOnPercent( ++nProgress );
1394 }
1395 }
1396 else if (eCellType != CELLTYPE_NOTE)
1397 {
1398 for (rInner = nIMin; rInner <= nIMax; rInner++)
1399 {
1400 ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab );
1401 aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) );
1402 }
1403 nProgress += nIMax - nIMin + 1;
1404 rProgress.SetStateOnPercent( nProgress );
1405 }
1406 }
1407 else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA)
1408 {
1409 double nStartVal;
1410 if (eCellType == CELLTYPE_VALUE)
1411 nStartVal = ((ScValueCell*)pSrcCell)->GetValue();
1412 else
1413 nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue();
1414 double nVal = nStartVal;
1415 long nIndex = 0;
1416
1417 sal_Bool bError = sal_False;
1418 sal_Bool bOverflow = sal_False;
1419
1420 sal_uInt16 nDayOfMonth = 0;
1421 rInner = nIStart;
1422 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1423 {
1424 if (!bError && !bOverflow)
1425 {
1426 switch (eFillCmd)
1427 {
1428 case FILL_LINEAR:
1429 {
1430 // #86365# use multiplication instead of repeated addition
1431 // to avoid accumulating rounding errors
1432 nVal = nStartVal;
1433 double nAdd = nStepValue;
1434 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1435 !SubTotal::SafePlus( nVal, nAdd ) )
1436 bError = sal_True;
1437 }
1438 break;
1439 case FILL_GROWTH:
1440 if (!SubTotal::SafeMult(nVal, nStepValue))
1441 bError = sal_True;
1442 break;
1443 case FILL_DATE:
1444 if (fabs(nVal) > _D_MAX_LONG_)
1445 bError = sal_True;
1446 else
1447 IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd);
1448 break;
1449 default:
1450 {
1451 // added to avoid warnings
1452 }
1453 }
1454
1455 if (nStepValue >= 0)
1456 {
1457 if (nVal > nMaxValue) // Zielwert erreicht?
1458 {
1459 nVal = nMaxValue;
1460 bOverflow = sal_True;
1461 }
1462 }
1463 else
1464 {
1465 if (nVal < nMaxValue)
1466 {
1467 nVal = nMaxValue;
1468 bOverflow = sal_True;
1469 }
1470 }
1471 }
1472
1473 if (bError)
1474 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1475 else if (!bOverflow)
1476 aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal);
1477
1478 if (rInner == nIEnd) break;
1479 if (bPositive) ++rInner; else --rInner;
1480 }
1481 nProgress += nIMax - nIMin + 1;
1482 rProgress.SetStateOnPercent( nProgress );
1483 }
1484 else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT)
1485 {
1486 if ( nStepValue >= 0 )
1487 {
1488 if ( nMaxValue >= (double)LONG_MAX )
1489 nMaxValue = (double)LONG_MAX - 1;
1490 }
1491 else
1492 {
1493 if ( nMaxValue <= (double)LONG_MIN )
1494 nMaxValue = (double)LONG_MIN + 1;
1495 }
1496 String aValue;
1497 if (eCellType == CELLTYPE_STRING)
1498 ((ScStringCell*)pSrcCell)->GetString( aValue );
1499 else
1500 ((ScEditCell*)pSrcCell)->GetString( aValue );
1501 sal_Int32 nStringValue;
1502 sal_uInt16 nMinDigits = nArgMinDigits;
1503 short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits );
1504 if ( nHeadNoneTail )
1505 {
1506 double nStartVal = (double)nStringValue;
1507 double nVal = nStartVal;
1508 long nIndex = 0;
1509 sal_Bool bError = sal_False;
1510 sal_Bool bOverflow = sal_False;
1511
1512 sal_Bool bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix(
1513 (sal_Int32)nStartVal));
1514
1515 rInner = nIStart;
1516 while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes
1517 {
1518 if (!bError && !bOverflow)
1519 {
1520 switch (eFillCmd)
1521 {
1522 case FILL_LINEAR:
1523 {
1524 // #86365# use multiplication instead of repeated addition
1525 // to avoid accumulating rounding errors
1526 nVal = nStartVal;
1527 double nAdd = nStepValue;
1528 if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) ||
1529 !SubTotal::SafePlus( nVal, nAdd ) )
1530 bError = sal_True;
1531 }
1532 break;
1533 case FILL_GROWTH:
1534 if (!SubTotal::SafeMult(nVal, nStepValue))
1535 bError = sal_True;
1536 break;
1537 default:
1538 {
1539 // added to avoid warnings
1540 }
1541 }
1542
1543 if (nStepValue >= 0)
1544 {
1545 if (nVal > nMaxValue) // Zielwert erreicht?
1546 {
1547 nVal = nMaxValue;
1548 bOverflow = sal_True;
1549 }
1550 }
1551 else
1552 {
1553 if (nVal < nMaxValue)
1554 {
1555 nVal = nMaxValue;
1556 bOverflow = sal_True;
1557 }
1558 }
1559 }
1560
1561 if (bError)
1562 aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue);
1563 else if (!bOverflow)
1564 {
1565 nStringValue = (sal_Int32)nVal;
1566 String aStr;
1567 if ( nHeadNoneTail < 0 )
1568 {
1569 aCol[nCol].Insert( static_cast<SCROW>(nRow),
1570 lcl_getSuffixCell( pDocument,
1571 nStringValue, nMinDigits, aValue,
1572 eCellType, bIsOrdinalSuffix ));
1573 }
1574 else
1575 {
1576 aStr = aValue;
1577 aStr += lcl_ValueString( nStringValue, nMinDigits );
1578 ScStringCell* pCell = new ScStringCell( aStr );
1579 aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell );
1580 }
1581 }
1582
1583 if (rInner == nIEnd) break;
1584 if (bPositive) ++rInner; else --rInner;
1585 }
1586 }
1587 nProgress += nIMax - nIMin + 1;
1588 rProgress.SetStateOnPercent( nProgress );
1589 }
1590 }
1591 else
1592 {
1593 nProgress += nIMax - nIMin + 1;
1594 rProgress.SetStateOnPercent( nProgress );
1595 }
1596 ++nActFormCnt;
1597 }
1598 }
1599
Fill(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uLong nFillCount,FillDir eFillDir,FillCmd eFillCmd,FillDateCmd eFillDateCmd,double nStepValue,double nMaxValue)1600 void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1601 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1602 double nStepValue, double nMaxValue)
1603 {
1604 sal_uLong nProgCount;
1605 if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
1606 nProgCount = nCol2 - nCol1 + 1;
1607 else
1608 nProgCount = nRow2 - nRow1 + 1;
1609 nProgCount *= nFillCount;
1610 ScProgress aProgress( pDocument->GetDocumentShell(),
1611 ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
1612
1613 bSharedNameInserted = sal_False;
1614
1615 if (eFillCmd == FILL_AUTO)
1616 FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress);
1617 else
1618 FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir,
1619 eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress);
1620
1621 if (bSharedNameInserted) // Wurde Shared-Name eingefuegt?
1622 pDocument->GetRangeName()->SetSharedMaxIndex(
1623 pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen
1624 }
1625
1626
AutoFormatArea(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,const ScPatternAttr & rAttr,sal_uInt16 nFormatNo)1627 void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1628 const ScPatternAttr& rAttr, sal_uInt16 nFormatNo)
1629 {
1630 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1631 if (pAutoFormat)
1632 {
1633 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1634 if (pData)
1635 {
1636 // ScPatternAttr aPattern(pDocument->GetPool());
1637 // pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument);
1638 ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr);
1639 }
1640 }
1641 }
1642
AutoFormat(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,sal_uInt16 nFormatNo)1643 void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1644 sal_uInt16 nFormatNo )
1645 {
1646 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1647 {
1648 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
1649 if (pAutoFormat)
1650 {
1651 ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo];
1652 if (pData)
1653 {
1654 ScPatternAttr* pPatternAttrs[16];
1655 for (sal_uInt8 i = 0; i < 16; ++i)
1656 {
1657 pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool());
1658 pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument);
1659 }
1660
1661 SCCOL nCol = nStartCol;
1662 SCROW nRow = nStartRow;
1663 sal_uInt16 nIndex = 0;
1664 // Linke obere Ecke
1665 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1666 // Linke Spalte
1667 if (pData->IsEqualData(4, 8))
1668 AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo);
1669 else
1670 {
1671 nIndex = 4;
1672 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1673 {
1674 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1675 if (nIndex == 4)
1676 nIndex = 8;
1677 else
1678 nIndex = 4;
1679 }
1680 }
1681 // Linke untere Ecke
1682 nRow = nEndRow;
1683 nIndex = 12;
1684 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1685 // Rechte obere Ecke
1686 nCol = nEndCol;
1687 nRow = nStartRow;
1688 nIndex = 3;
1689 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1690 // Rechte Spalte
1691 if (pData->IsEqualData(7, 11))
1692 AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo);
1693 else
1694 {
1695 nIndex = 7;
1696 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1697 {
1698 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1699 if (nIndex == 7)
1700 nIndex = 11;
1701 else
1702 nIndex = 7;
1703 }
1704 }
1705 // Rechte untere Ecke
1706 nRow = nEndRow;
1707 nIndex = 15;
1708 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1709 nRow = nStartRow;
1710 nIndex = 1;
1711 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1712 {
1713 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1714 if (nIndex == 1)
1715 nIndex = 2;
1716 else
1717 nIndex = 1;
1718 }
1719 // Untere Zeile
1720 nRow = nEndRow;
1721 nIndex = 13;
1722 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1723 {
1724 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1725 if (nIndex == 13)
1726 nIndex = 14;
1727 else
1728 nIndex = 13;
1729 }
1730 // Boddy
1731 if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9)))
1732 AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo);
1733 else
1734 {
1735 if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10)))
1736 {
1737 nIndex = 5;
1738 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1739 {
1740 AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo);
1741 if (nIndex == 5)
1742 nIndex = 6;
1743 else
1744 nIndex = 5;
1745 }
1746 }
1747 else
1748 {
1749 nIndex = 5;
1750 for (nCol = nStartCol + 1; nCol < nEndCol; nCol++)
1751 {
1752 for (nRow = nStartRow + 1; nRow < nEndRow; nRow++)
1753 {
1754 AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo);
1755 if ((nIndex == 5) || (nIndex == 9))
1756 {
1757 if (nIndex == 5)
1758 nIndex = 9;
1759 else
1760 nIndex = 5;
1761 }
1762 else
1763 {
1764 if (nIndex == 6)
1765 nIndex = 10;
1766 else
1767 nIndex = 6;
1768 }
1769 } // for nRow
1770 if ((nIndex == 5) || (nIndex == 9))
1771 nIndex = 6;
1772 else
1773 nIndex = 5;
1774 } // for nCol
1775 } // if not equal Column
1776 } // if not all equal
1777
1778 for (sal_uInt8 j = 0; j < 16; ++j)
1779 delete pPatternAttrs[j];
1780 } // if AutoFormatData != NULL
1781 } // if AutoFormat != NULL
1782 } // if ValidColRow
1783 }
1784
GetAutoFormatAttr(SCCOL nCol,SCROW nRow,sal_uInt16 nIndex,ScAutoFormatData & rData)1785 void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData)
1786 {
1787 sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow );
1788 ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() );
1789 rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat );
1790 }
1791
1792 #define LF_LEFT 1
1793 #define LF_TOP 2
1794 #define LF_RIGHT 4
1795 #define LF_BOTTOM 8
1796 #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM)
1797
GetAutoFormatFrame(SCCOL nCol,SCROW nRow,sal_uInt16 nFlags,sal_uInt16 nIndex,ScAutoFormatData & rData)1798 void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData)
1799 {
1800 const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER);
1801 const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER);
1802 const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER);
1803 const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER);
1804 const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER);
1805
1806 SvxBoxItem aBox( ATTR_BORDER );
1807 if (nFlags & LF_LEFT)
1808 {
1809 if (pLeftBox)
1810 {
1811 if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight()))
1812 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1813 else
1814 aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT);
1815 }
1816 else
1817 aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT);
1818 }
1819 if (nFlags & LF_TOP)
1820 {
1821 if (pTopBox)
1822 {
1823 if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom()))
1824 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1825 else
1826 aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP);
1827 }
1828 else
1829 aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP);
1830 }
1831 if (nFlags & LF_RIGHT)
1832 {
1833 if (pRightBox)
1834 {
1835 if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft()))
1836 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1837 else
1838 aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT);
1839 }
1840 else
1841 aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT);
1842 }
1843 if (nFlags & LF_BOTTOM)
1844 {
1845 if (pBottomBox)
1846 {
1847 if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop()))
1848 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1849 else
1850 aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM);
1851 }
1852 else
1853 aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM);
1854 }
1855 rData.PutItem( nIndex, aBox );
1856 }
1857
GetAutoFormatData(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,ScAutoFormatData & rData)1858 void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData)
1859 {
1860 if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow))
1861 {
1862 if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3))
1863 {
1864 // Linke obere Ecke
1865 GetAutoFormatAttr(nStartCol, nStartRow, 0, rData);
1866 GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData);
1867 // Linke Spalte
1868 GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData);
1869 GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData);
1870 GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData);
1871 if (nEndRow - nStartRow >= 4)
1872 GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData);
1873 else
1874 rData.CopyItem( 8, 4, ATTR_BORDER );
1875 // Linke untere Ecke
1876 GetAutoFormatAttr(nStartCol, nEndRow, 12, rData);
1877 GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData);
1878 // Rechte obere Ecke
1879 GetAutoFormatAttr(nEndCol, nStartRow, 3, rData);
1880 GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData);
1881 // Rechte Spalte
1882 GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData);
1883 GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData);
1884 GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData);
1885 if (nEndRow - nStartRow >= 4)
1886 GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData);
1887 else
1888 rData.CopyItem( 11, 7, ATTR_BORDER );
1889 // Rechte untere Ecke
1890 GetAutoFormatAttr(nEndCol, nEndRow, 15, rData);
1891 GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData);
1892 // Ober Zeile
1893 GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData);
1894 GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData);
1895 GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData);
1896 if (nEndCol - nStartCol >= 4)
1897 GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData);
1898 else
1899 rData.CopyItem( 2, 1, ATTR_BORDER );
1900 // Untere Zeile
1901 GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData);
1902 GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData);
1903 GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData);
1904 if (nEndCol - nStartCol >= 4)
1905 GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData);
1906 else
1907 rData.CopyItem( 14, 13, ATTR_BORDER );
1908 // Body
1909 GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData);
1910 GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData);
1911 GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData);
1912 GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData);
1913 GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData);
1914 if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4))
1915 {
1916 GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData);
1917 GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData);
1918 GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData);
1919 }
1920 else
1921 {
1922 rData.CopyItem( 6, 5, ATTR_BORDER );
1923 rData.CopyItem( 9, 5, ATTR_BORDER );
1924 rData.CopyItem( 10, 5, ATTR_BORDER );
1925 }
1926 }
1927 }
1928 }
1929
SetError(SCCOL nCol,SCROW nRow,sal_uInt16 nError)1930 void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError)
1931 {
1932 if (ValidColRow(nCol, nRow))
1933 aCol[nCol].SetError( nRow, nError );
1934 }
1935
UpdateInsertTabAbs(SCTAB nTable)1936 void ScTable::UpdateInsertTabAbs(SCTAB nTable)
1937 {
1938 for (SCCOL i=0; i <= MAXCOL; i++)
1939 aCol[i].UpdateInsertTabAbs(nTable);
1940 }
1941
1942 //UNUSED2008-05 sal_uInt16 ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const
1943 //UNUSED2008-05 {
1944 //UNUSED2008-05 if (ValidColRow(nCol,nRow))
1945 //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow );
1946 //UNUSED2008-05 else
1947 //UNUSED2008-05 return 0;
1948 //UNUSED2008-05 }
1949
GetNextSpellingCell(SCCOL & rCol,SCROW & rRow,sal_Bool bInSel,const ScMarkData & rMark) const1950 sal_Bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, sal_Bool bInSel,
1951 const ScMarkData& rMark) const
1952 {
1953 if (rRow == MAXROW+2) // Tabellenende
1954 {
1955 rRow = 0;
1956 rCol = 0;
1957 }
1958 else
1959 {
1960 rRow++;
1961 if (rRow == MAXROW+1)
1962 {
1963 rCol++;
1964 rRow = 0;
1965 }
1966 }
1967 if (rCol == MAXCOL+1)
1968 return sal_True;
1969 else
1970 {
1971 sal_Bool bStop = sal_False;
1972 while (!bStop)
1973 {
1974 if (ValidCol(rCol))
1975 {
1976 bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark);
1977 if (bStop)
1978 return sal_True;
1979 else /*if (rRow == MAXROW+1) */
1980 {
1981 rCol++;
1982 rRow = 0;
1983 }
1984 }
1985 else
1986 return sal_True;
1987 }
1988 }
1989 return sal_False;
1990 }
1991
RemoveAutoSpellObj()1992 void ScTable::RemoveAutoSpellObj()
1993 {
1994 for (SCCOL i=0; i <= MAXCOL; i++)
1995 aCol[i].RemoveAutoSpellObj();
1996 }
1997
TestTabRefAbs(SCTAB nTable)1998 sal_Bool ScTable::TestTabRefAbs(SCTAB nTable)
1999 {
2000 sal_Bool bRet = sal_False;
2001 for (SCCOL i=0; i <= MAXCOL; i++)
2002 if (aCol[i].TestTabRefAbs(nTable))
2003 bRet = sal_True;
2004 return bRet;
2005 }
2006
CompileDBFormula()2007 void ScTable::CompileDBFormula()
2008 {
2009 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula();
2010 }
2011
CompileDBFormula(sal_Bool bCreateFormulaString)2012 void ScTable::CompileDBFormula( sal_Bool bCreateFormulaString )
2013 {
2014 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString );
2015 }
2016
CompileNameFormula(sal_Bool bCreateFormulaString)2017 void ScTable::CompileNameFormula( sal_Bool bCreateFormulaString )
2018 {
2019 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString );
2020 }
2021
CompileColRowNameFormula()2022 void ScTable::CompileColRowNameFormula()
2023 {
2024 for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula();
2025 }
2026
GetPatternCount(SCCOL nCol)2027 SCSIZE ScTable::GetPatternCount( SCCOL nCol )
2028 {
2029 if( ValidCol( nCol ) )
2030 return aCol[nCol].GetPatternCount();
2031 else
2032 return 0;
2033 }
2034
GetPatternCount(SCCOL nCol,SCROW nRw1,SCROW nRw2)2035 SCSIZE ScTable::GetPatternCount( SCCOL nCol, SCROW nRw1, SCROW nRw2 )
2036 {
2037 if( ValidCol( nCol ) && ValidRow( nRw1 ) && ValidRow( nRw2 ) )
2038 return aCol[nCol].GetPatternCount( nRw1, nRw2 );
2039 else
2040 return 0;
2041 }
2042
ReservedPatternCount(SCCOL nCol,SCSIZE nReserved)2043 bool ScTable::ReservedPatternCount( SCCOL nCol, SCSIZE nReserved )
2044 {
2045 if( ValidCol( nCol ) )
2046 return aCol[nCol].ReservedPatternCount( nReserved );
2047 else
2048 return false;
2049 }
2050