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