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