| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| // System - Includes ----------------------------------------------------- |
| |
| |
| |
| #ifdef _MSC_VER |
| #pragma optimize("",off) |
| // sonst Absturz Win beim Fuellen |
| #endif |
| |
| // INCLUDE --------------------------------------------------------------- |
| |
| #include "scitems.hxx" |
| #include <svx/algitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <editeng/brshitem.hxx> |
| #include <editeng/cntritem.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/crsditem.hxx> |
| #include <editeng/fhgtitem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <editeng/langitem.hxx> |
| #include <editeng/postitem.hxx> |
| #include <editeng/shdditem.hxx> |
| #include <editeng/udlnitem.hxx> |
| #include <editeng/wghtitem.hxx> |
| #include <svx/rotmodit.hxx> |
| #include <editeng/editobj.hxx> |
| #include <editeng/editeng.hxx> |
| #include <editeng/eeitem.hxx> |
| #include <editeng/escpitem.hxx> |
| #include <svl/zforlist.hxx> |
| #include <vcl/keycodes.hxx> |
| #include <rtl/math.hxx> |
| #include <unotools/charclass.hxx> |
| |
| #include "attrib.hxx" |
| #include "patattr.hxx" |
| #include "cell.hxx" |
| #include "table.hxx" |
| #include "globstr.hrc" |
| #include "global.hxx" |
| #include "document.hxx" |
| #include "autoform.hxx" |
| #include "userlist.hxx" |
| #include "zforauto.hxx" |
| #include "subtotal.hxx" |
| #include "formula/errorcodes.hxx" |
| #include "rangenam.hxx" |
| #include "docpool.hxx" |
| #include "progress.hxx" |
| #include "segmenttree.hxx" |
| |
| #include <math.h> |
| |
| // STATIC DATA ----------------------------------------------------------- |
| |
| #define _D_MAX_LONG_ (double) 0x7fffffff |
| |
| extern sal_uInt16 nScFillModeMouseModifier; // global.cxx |
| |
| // ----------------------------------------------------------------------- |
| |
| short lcl_DecompValueString( String& aValue, sal_Int32& nVal, sal_uInt16* pMinDigits = NULL ) |
| { |
| if ( !aValue.Len() ) |
| { |
| nVal = 0; |
| return 0; |
| } |
| const sal_Unicode* p = aValue.GetBuffer(); |
| xub_StrLen nNeg = 0; |
| xub_StrLen nNum = 0; |
| if ( p[nNum] == '-' ) |
| nNum = nNeg = 1; |
| while ( p[nNum] && CharClass::isAsciiNumeric( p[nNum] ) ) |
| nNum++; |
| |
| sal_Unicode cNext = p[nNum]; // 0 if at the end |
| sal_Unicode cLast = p[aValue.Len()-1]; |
| |
| // #i5550# If there are numbers at the beginning and the end, |
| // prefer the one at the beginning only if it's followed by a space. |
| // Otherwise, use the number at the end, to enable things like IP addresses. |
| if ( nNum > nNeg && ( cNext == 0 || cNext == ' ' || !CharClass::isAsciiNumeric(cLast) ) ) |
| { // number at the beginning |
| nVal = aValue.Copy( 0, nNum ).ToInt32(); |
| // #60893# any number with a leading zero sets the minimum number of digits |
| if ( p[nNeg] == '0' && pMinDigits && ( nNum - nNeg > *pMinDigits ) ) |
| *pMinDigits = nNum - nNeg; |
| aValue.Erase( 0, nNum ); |
| return -1; |
| } |
| else |
| { |
| nNeg = 0; |
| xub_StrLen nEnd = nNum = aValue.Len() - 1; |
| while ( nNum && CharClass::isAsciiNumeric( p[nNum] ) ) |
| nNum--; |
| if ( p[nNum] == '-' ) |
| { |
| nNum--; |
| nNeg = 1; |
| } |
| if ( nNum < nEnd - nNeg ) |
| { // number at the end |
| nVal = aValue.Copy( nNum + 1 ).ToInt32(); |
| // #60893# any number with a leading zero sets the minimum number of digits |
| if ( p[nNum+1+nNeg] == '0' && pMinDigits && ( nEnd - nNum - nNeg > *pMinDigits ) ) |
| *pMinDigits = nEnd - nNum - nNeg; |
| aValue.Erase( nNum + 1 ); |
| return 1; |
| } |
| } |
| nVal = 0; |
| return 0; |
| } |
| |
| String lcl_ValueString( sal_Int32 nValue, sal_uInt16 nMinDigits ) |
| { |
| if ( nMinDigits <= 1 ) |
| return String::CreateFromInt32( nValue ); // simple case... |
| else |
| { |
| String aStr = String::CreateFromInt32( Abs( nValue ) ); |
| if ( aStr.Len() < nMinDigits ) |
| { |
| String aZero; |
| aZero.Fill( nMinDigits - aStr.Len(), '0' ); |
| aStr.Insert( aZero, 0 ); |
| } |
| // nMinDigits doesn't include the '-' sign -> add after inserting zeros |
| if ( nValue < 0 ) |
| aStr.Insert( '-', 0 ); |
| return aStr; |
| } |
| } |
| |
| static ScBaseCell * lcl_getSuffixCell( ScDocument* pDocument, sal_Int32 nValue, |
| sal_uInt16 nDigits, const String& rSuffix, CellType eCellType, |
| sal_Bool bIsOrdinalSuffix ) |
| { |
| String aValue( lcl_ValueString( nValue, nDigits )); |
| if (!bIsOrdinalSuffix) |
| return new ScStringCell( aValue += rSuffix); |
| |
| String aOrdinalSuffix( ScGlobal::GetOrdinalSuffix( nValue)); |
| if (eCellType != CELLTYPE_EDIT) |
| return new ScStringCell( aValue += aOrdinalSuffix); |
| |
| EditEngine aEngine( pDocument->GetEnginePool() ); |
| SfxItemSet aAttr = aEngine.GetEmptyItemSet(); |
| aAttr.Put( SvxEscapementItem( SVX_ESCAPEMENT_SUPERSCRIPT, EE_CHAR_ESCAPEMENT)); |
| aEngine.SetText( aValue ); |
| aEngine.QuickInsertText( aOrdinalSuffix, ESelection( 0, aValue.Len(), 0, |
| aValue.Len() + aOrdinalSuffix.Len())); |
| aEngine.QuickSetAttribs( aAttr, ESelection( 0, aValue.Len(), 0, aValue.Len() + |
| aOrdinalSuffix.Len())); |
| return new ScEditCell( aEngine.CreateTextObject(), pDocument, NULL ); |
| } |
| |
| void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, |
| FillCmd& rCmd, FillDateCmd& rDateCmd, |
| double& rInc, sal_uInt16& rMinDigits, |
| ScUserListData*& rListData, sal_uInt16& rListIndex) |
| { |
| DBG_ASSERT( nCol1==nCol2 || nRow1==nRow2, "FillAnalyse: falscher Bereich" ); |
| |
| rInc = 0.0; |
| rMinDigits = 0; |
| rListData = NULL; |
| rCmd = FILL_SIMPLE; |
| if (( nScFillModeMouseModifier & KEY_MOD1 )||IsDataFiltered()) //i89232 |
| return ; // Ctrl-Taste: Copy |
| |
| SCCOL nAddX; |
| SCROW nAddY; |
| SCSIZE nCount; |
| if (nCol1 == nCol2) |
| { |
| nAddX = 0; |
| nAddY = 1; |
| nCount = static_cast<SCSIZE>(nRow2 - nRow1 + 1); |
| } |
| else |
| { |
| nAddX = 1; |
| nAddY = 0; |
| nCount = static_cast<SCSIZE>(nCol2 - nCol1 + 1); |
| } |
| |
| SCCOL nCol = nCol1; |
| SCROW nRow = nRow1; |
| |
| ScBaseCell* pFirstCell = GetCell( nCol, nRow ); |
| CellType eCellType = pFirstCell ? pFirstCell->GetCellType() : CELLTYPE_NONE; |
| |
| if (eCellType == CELLTYPE_VALUE) |
| { |
| sal_uInt32 nFormat = ((const SfxUInt32Item*)GetAttr(nCol,nRow,ATTR_VALUE_FORMAT))->GetValue(); |
| sal_Bool bDate = ( pDocument->GetFormatTable()->GetType(nFormat) == NUMBERFORMAT_DATE ); |
| if (bDate) |
| { |
| if (nCount > 1) |
| { |
| long nCmpInc = 0; |
| double nVal; |
| Date aNullDate = *pDocument->GetFormatTable()->GetNullDate(); |
| Date aDate1 = aNullDate; |
| nVal = ((ScValueCell*)pFirstCell)->GetValue(); |
| aDate1 += (long)nVal; |
| Date aDate2 = aNullDate; |
| nVal = GetValue(nCol+nAddX, nRow+nAddY); |
| aDate2 += (long)nVal; |
| if ( aDate1 != aDate2 ) |
| { |
| FillDateCmd eType; |
| long nDDiff = aDate2.GetDay() - (long) aDate1.GetDay(); |
| long nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth(); |
| long nYDiff = aDate2.GetYear() - (long) aDate1.GetYear(); |
| if ( nDDiff ) |
| { |
| eType = FILL_DAY; |
| nCmpInc = aDate2 - aDate1; |
| } |
| else |
| { |
| eType = FILL_MONTH; |
| nCmpInc = nMDiff + 12 * nYDiff; |
| } |
| |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| sal_Bool bVal = sal_True; |
| for (sal_uInt16 i=1; i<nCount && bVal; i++) |
| { |
| ScBaseCell* pCell = GetCell(nCol,nRow); |
| if (pCell && pCell->GetCellType() == CELLTYPE_VALUE) |
| { |
| nVal = ((ScValueCell*)pCell)->GetValue(); |
| aDate2 = aNullDate + (long) nVal; |
| if ( eType == FILL_DAY ) |
| { |
| if ( aDate2-aDate1 != nCmpInc ) |
| bVal = sal_False; |
| } |
| else |
| { |
| nDDiff = aDate2.GetDay() - (long) aDate1.GetDay(); |
| nMDiff = aDate2.GetMonth() - (long) aDate1.GetMonth(); |
| nYDiff = aDate2.GetYear() - (long) aDate1.GetYear(); |
| if (nDDiff || ( nMDiff + 12 * nYDiff != nCmpInc )) |
| bVal = sal_False; |
| } |
| aDate1 = aDate2; |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| } |
| else |
| bVal = sal_False; // #50965# kein Datum passt auch nicht |
| } |
| if (bVal) |
| { |
| if ( eType == FILL_MONTH && ( nCmpInc % 12 == 0 ) ) |
| { |
| eType = FILL_YEAR; |
| nCmpInc /= 12; |
| } |
| rCmd = FILL_DATE; |
| rDateCmd = eType; |
| rInc = nCmpInc; |
| } |
| } |
| } |
| else // einzelnes Datum -> Tage hochzaehlen |
| { |
| rCmd = FILL_DATE; |
| rDateCmd = FILL_DAY; |
| rInc = 1.0; |
| } |
| } |
| else |
| { |
| if (nCount > 1) |
| { |
| double nVal1 = ((ScValueCell*)pFirstCell)->GetValue(); |
| double nVal2 = GetValue(nCol+nAddX, nRow+nAddY); |
| rInc = nVal2 - nVal1; |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| sal_Bool bVal = sal_True; |
| for (sal_uInt16 i=1; i<nCount && bVal; i++) |
| { |
| ScBaseCell* pCell = GetCell(nCol,nRow); |
| if (pCell && pCell->GetCellType() == CELLTYPE_VALUE) |
| { |
| nVal2 = ((ScValueCell*)pCell)->GetValue(); |
| double nDiff = nVal2 - nVal1; |
| if ( !::rtl::math::approxEqual( nDiff, rInc ) ) |
| bVal = sal_False; |
| nVal1 = nVal2; |
| } |
| else |
| bVal = sal_False; |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| } |
| if (bVal) |
| rCmd = FILL_LINEAR; |
| } |
| } |
| } |
| else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) |
| { |
| String aStr; |
| GetString(nCol, nRow, aStr); |
| rListData = (ScUserListData*)(ScGlobal::GetUserList()->GetData(aStr)); |
| if (rListData) |
| { |
| rListData->GetSubIndex(aStr, rListIndex); |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| for (sal_uInt16 i=1; i<nCount && rListData; i++) |
| { |
| GetString(nCol, nRow, aStr); |
| if (!rListData->GetSubIndex(aStr, rListIndex)) |
| rListData = NULL; |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| } |
| } |
| else if ( nCount > 1 ) |
| { |
| // pass rMinDigits to all DecompValueString calls |
| // -> longest number defines rMinDigits |
| |
| sal_Int32 nVal1; |
| short nFlag1 = lcl_DecompValueString( aStr, nVal1, &rMinDigits ); |
| if ( nFlag1 ) |
| { |
| sal_Int32 nVal2; |
| GetString( nCol+nAddX, nRow+nAddY, aStr ); |
| short nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits ); |
| if ( nFlag1 == nFlag2 ) |
| { |
| rInc = (double)nVal2 - (double)nVal1; |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| sal_Bool bVal = sal_True; |
| for (sal_uInt16 i=1; i<nCount && bVal; i++) |
| { |
| ScBaseCell* pCell = GetCell(nCol,nRow); |
| CellType eType = pCell ? pCell->GetCellType() : CELLTYPE_NONE; |
| if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT ) |
| { |
| if ( eType == CELLTYPE_STRING ) |
| ((ScStringCell*)pCell)->GetString( aStr ); |
| else |
| ((ScEditCell*)pCell)->GetString( aStr ); |
| nFlag2 = lcl_DecompValueString( aStr, nVal2, &rMinDigits ); |
| if ( nFlag1 == nFlag2 ) |
| { |
| double nDiff = (double)nVal2 - (double)nVal1; |
| if ( !::rtl::math::approxEqual( nDiff, rInc ) ) |
| bVal = sal_False; |
| nVal1 = nVal2; |
| } |
| else |
| bVal = sal_False; |
| } |
| else |
| bVal = sal_False; |
| nCol = sal::static_int_cast<SCCOL>( nCol + nAddX ); |
| nRow = sal::static_int_cast<SCROW>( nRow + nAddY ); |
| } |
| if (bVal) |
| rCmd = FILL_LINEAR; |
| } |
| } |
| } |
| else |
| { |
| // call DecompValueString to set rMinDigits |
| sal_Int32 nDummy; |
| lcl_DecompValueString( aStr, nDummy, &rMinDigits ); |
| } |
| } |
| } |
| |
| void ScTable::FillFormula(sal_uLong& /* nFormulaCounter */, sal_Bool /* bFirst */, ScFormulaCell* pSrcCell, |
| SCCOL nDestCol, SCROW nDestRow, sal_Bool bLast ) |
| { |
| /* sal_uInt16 nTokArrLen = pSrcCell->GetTokenArrayLen(); |
| if ( nTokArrLen > 15 ) // mehr als =A1 oder =67 |
| { |
| ScRangeName* pRangeName = pDocument->GetRangeName(); |
| String aName("___SC_"); // Wird dieser String veraendert, |
| // auch in document2 EraseNonUsed... |
| // mitaendern!! |
| aName += pRangeName->GetSharedMaxIndex() + 1; |
| aName += '_'; |
| aName += nFormulaCounter; |
| nFormulaCounter++; |
| if (bFirst) |
| { |
| ScRangeData *pAktRange = new ScRangeData( |
| pDocument, aName, pSrcCell->GetTokenArray(), nTokArrLen, |
| pSrcCell->GetCol(), pSrcCell->GetRow(), nTab ,RT_SHARED); |
| if (!pRangeName->Insert( pAktRange )) |
| delete pAktRange; |
| else |
| bSharedNameInserted = sal_True; |
| } |
| sal_uInt16 nIndex; |
| pRangeName->SearchName(aName, nIndex); |
| if (!pRangeName) |
| { |
| DBG_ERROR("ScTable::FillFormula: Falscher Name"); |
| return; |
| } |
| nIndex = ((ScRangeData*) ((*pRangeName)[nIndex]))->GetIndex(); |
| ScTokenArray aArr; |
| aArr.AddName(nIndex); |
| aArr.AddOpCode(ocStop); |
| ScFormulaCell* pDestCell = new ScFormulaCell |
| (pDocument, ScAddress( nDestCol, nDestRow, nTab ), aArr ); |
| aCol[nDestCol].Insert(nDestRow, pDestCell); |
| } |
| else |
| */ { |
| pDocument->SetNoListening( sal_True ); // noch falsche Referenzen |
| ScAddress aAddr( nDestCol, nDestRow, nTab ); |
| ScFormulaCell* pDestCell = new ScFormulaCell( *pSrcCell, *pDocument, aAddr ); |
| aCol[nDestCol].Insert(nDestRow, pDestCell); |
| #if 0 |
| // mit RelRefs unnoetig |
| pDestCell->UpdateReference(URM_COPY, |
| ScRange( aAddr, aAddr ), |
| nDestCol - pSrcCell->aPos.Col(), |
| nDestRow - pSrcCell->aPos.Row(), 0); |
| #endif |
| if ( bLast && pDestCell->GetMatrixFlag() ) |
| { |
| ScAddress aOrg; |
| if ( pDestCell->GetMatrixOrigin( aOrg ) ) |
| { |
| if ( nDestCol >= aOrg.Col() && nDestRow >= aOrg.Row() ) |
| { |
| ScBaseCell* pOrgCell = pDocument->GetCell( aOrg ); |
| if ( pOrgCell && pOrgCell->GetCellType() == CELLTYPE_FORMULA |
| && ((ScFormulaCell*)pOrgCell)->GetMatrixFlag() == MM_FORMULA ) |
| { |
| ((ScFormulaCell*)pOrgCell)->SetMatColsRows( |
| nDestCol - aOrg.Col() + 1, |
| nDestRow - aOrg.Row() + 1 ); |
| } |
| else |
| { |
| DBG_ERRORFILE( "FillFormula: MatrixOrigin keine Formelzelle mit MM_FORMULA" ); |
| } |
| } |
| else |
| { |
| DBG_ERRORFILE( "FillFormula: MatrixOrigin rechts unten" ); |
| } |
| } |
| else |
| { |
| DBG_ERRORFILE( "FillFormula: kein MatrixOrigin" ); |
| } |
| } |
| pDocument->SetNoListening( sal_False ); |
| pDestCell->StartListeningTo( pDocument ); |
| } |
| } |
| |
| void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, |
| sal_uLong nFillCount, FillDir eFillDir, ScProgress& rProgress ) |
| { |
| if ( (nFillCount == 0) || !ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2) ) |
| return; |
| |
| // |
| // Richtung auswerten |
| // |
| |
| sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP); |
| sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT); |
| |
| sal_uLong nCol = 0; |
| sal_uLong nRow = 0; |
| sal_uLong& rInner = bVertical ? nRow : nCol; // Schleifenvariablen |
| sal_uLong& rOuter = bVertical ? nCol : nRow; |
| sal_uLong nOStart; |
| sal_uLong nOEnd; |
| sal_uLong nIStart; |
| sal_uLong nIEnd; |
| sal_uLong nISrcStart; |
| sal_uLong nISrcEnd; |
| |
| if (bVertical) |
| { |
| nOStart = nCol1; |
| nOEnd = nCol2; |
| if (bPositive) |
| { |
| nISrcStart = nRow1; |
| nISrcEnd = nRow2; |
| nIStart = nRow2 + 1; |
| nIEnd = nRow2 + nFillCount; |
| } |
| else |
| { |
| nISrcStart = nRow2; |
| nISrcEnd = nRow1; |
| nIStart = nRow1 - 1; |
| nIEnd = nRow1 - nFillCount; |
| } |
| } |
| else |
| { |
| nOStart = nRow1; |
| nOEnd = nRow2; |
| if (bPositive) |
| { |
| nISrcStart = nCol1; |
| nISrcEnd = nCol2; |
| nIStart = nCol2 + 1; |
| nIEnd = nCol2 + nFillCount; |
| } |
| else |
| { |
| nISrcStart = nCol2; |
| nISrcEnd = nCol1; |
| nIStart = nCol1 - 1; |
| nIEnd = nCol1 - nFillCount; |
| } |
| } |
| sal_uLong nIMin = nIStart; |
| sal_uLong nIMax = nIEnd; |
| PutInOrder(nIMin,nIMax); |
| sal_Bool bHasFiltered = IsDataFiltered(); |
| if (!bHasFiltered) //modify for i89232 |
| { |
| if (bVertical) |
| DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL); |
| else |
| DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL); |
| } |
| sal_uLong nProgress = rProgress.GetState(); |
| |
| // |
| // ausfuehren |
| // |
| |
| sal_uLong nActFormCnt = 0; |
| for (rOuter = nOStart; rOuter <= nOEnd; rOuter++) |
| { |
| sal_uLong nMaxFormCnt = 0; // fuer Formeln |
| |
| // Attributierung uebertragen |
| |
| const ScPatternAttr* pSrcPattern = NULL; |
| const ScStyleSheet* pStyleSheet = NULL; |
| sal_uLong nAtSrc = nISrcStart; |
| ScPatternAttr* pNewPattern = NULL; |
| sal_Bool bGetPattern = sal_True; |
| rInner = nIStart; |
| while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes |
| { |
| if ( bGetPattern ) |
| { |
| if ( pNewPattern ) |
| delete pNewPattern; |
| if (bVertical) // rInner&:=nRow, rOuter&:=nCol |
| pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nAtSrc)); |
| else // rInner&:=nCol, rOuter&:=nRow |
| pSrcPattern = aCol[nAtSrc].GetPattern(static_cast<SCROW>(nRow)); |
| bGetPattern = sal_False; |
| pStyleSheet = pSrcPattern->GetStyleSheet(); |
| // Merge/Mergeflag nicht uebernehmen, |
| const SfxItemSet& rSet = pSrcPattern->GetItemSet(); |
| if ( rSet.GetItemState(ATTR_MERGE, sal_False) == SFX_ITEM_SET |
| || rSet.GetItemState(ATTR_MERGE_FLAG, sal_False) == SFX_ITEM_SET ) |
| { |
| pNewPattern = new ScPatternAttr( *pSrcPattern ); |
| SfxItemSet& rNewSet = pNewPattern->GetItemSet(); |
| rNewSet.ClearItem(ATTR_MERGE); |
| rNewSet.ClearItem(ATTR_MERGE_FLAG); |
| } |
| else |
| pNewPattern = NULL; |
| } |
| |
| if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered ) |
| { |
| // Attribute komplett am Stueck setzen |
| if (pNewPattern || pSrcPattern != pDocument->GetDefPattern()) |
| { |
| // Default steht schon da (DeleteArea) |
| SCROW nY1 = static_cast<SCROW>(Min( nIStart, nIEnd )); |
| SCROW nY2 = static_cast<SCROW>(Max( nIStart, nIEnd )); |
| if ( pStyleSheet ) |
| aCol[nCol].ApplyStyleArea( nY1, nY2, *pStyleSheet ); |
| if ( pNewPattern ) |
| aCol[nCol].ApplyPatternArea( nY1, nY2, *pNewPattern ); |
| else |
| aCol[nCol].ApplyPatternArea( nY1, nY2, *pSrcPattern ); |
| } |
| break; // Schleife abbrechen |
| } |
| |
| if ( !RowFiltered(nRow) ) |
| { |
| if ( bHasFiltered ) |
| DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), |
| static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL); |
| |
| if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) ) |
| { |
| // Vorlage auch uebernehmen |
| //! am AttrArray mit ApplyPattern zusammenfassen ?? |
| if ( pStyleSheet ) |
| aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet ); |
| |
| // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen |
| if ( pNewPattern ) |
| aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern ); |
| else |
| aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern ); |
| } |
| |
| if (nAtSrc==nISrcEnd) |
| { |
| if ( nAtSrc != nISrcStart ) |
| { // mehr als eine Source-Zelle |
| nAtSrc = nISrcStart; |
| bGetPattern = sal_True; |
| } |
| } |
| else if (bPositive) |
| { |
| ++nAtSrc; |
| bGetPattern = sal_True; |
| } |
| else |
| { |
| --nAtSrc; |
| bGetPattern = sal_True; |
| } |
| } |
| |
| if (rInner == nIEnd) break; |
| if (bPositive) ++rInner; else --rInner; |
| } |
| if ( pNewPattern ) |
| delete pNewPattern; |
| |
| // Analyse |
| |
| FillCmd eFillCmd; |
| FillDateCmd eDateCmd; |
| double nInc; |
| sal_uInt16 nMinDigits; |
| ScUserListData* pListData = NULL; |
| sal_uInt16 nListIndex; |
| if (bVertical) |
| FillAnalyse(static_cast<SCCOL>(nCol),nRow1, |
| static_cast<SCCOL>(nCol),nRow2, eFillCmd,eDateCmd, |
| nInc,nMinDigits, pListData,nListIndex); |
| else |
| FillAnalyse(nCol1,static_cast<SCROW>(nRow), |
| nCol2,static_cast<SCROW>(nRow), eFillCmd,eDateCmd, |
| nInc,nMinDigits, pListData,nListIndex); |
| |
| if (bVertical) |
| aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount ); |
| |
| if (pListData) |
| { |
| sal_uInt16 nListCount = pListData->GetSubCount(); |
| if ( !bPositive ) |
| { |
| // nListIndex auf FillAnalyse zeigt auf den letzten Eintrag -> anpassen |
| sal_uLong nSub = nISrcStart - nISrcEnd; |
| for (sal_uLong i=0; i<nSub; i++) |
| { |
| if (nListIndex == 0) nListIndex = nListCount; |
| --nListIndex; |
| } |
| } |
| |
| rInner = nIStart; |
| while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes |
| { |
| if (bPositive) |
| { |
| ++nListIndex; |
| if (nListIndex >= nListCount) nListIndex = 0; |
| } |
| else |
| { |
| if (nListIndex == 0) nListIndex = nListCount; |
| --nListIndex; |
| } |
| aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScStringCell(pListData->GetSubStr(nListIndex))); |
| |
| if (rInner == nIEnd) break; |
| if (bPositive) ++rInner; else --rInner; |
| } |
| nProgress += nIMax - nIMin + 1; |
| rProgress.SetStateOnPercent( nProgress ); |
| } |
| else if (eFillCmd == FILL_SIMPLE) // Auffuellen mit Muster |
| { |
| sal_uLong nSource = nISrcStart; |
| double nDelta; |
| if (( nScFillModeMouseModifier & KEY_MOD1 )||bHasFiltered) //i89232 |
| nDelta = 0.0; |
| else if ( bPositive ) |
| nDelta = 1.0; |
| else |
| nDelta = -1.0; |
| double nVal = 0.0; |
| sal_uLong nFormulaCounter = nActFormCnt; |
| sal_Bool bFirst = sal_True; |
| sal_Bool bGetCell = sal_True; |
| sal_uInt16 nCellDigits = 0; |
| short nHeadNoneTail = 0; |
| sal_Int32 nStringValue = 0; |
| String aValue; |
| ScBaseCell* pSrcCell = NULL; |
| CellType eCellType = CELLTYPE_NONE; |
| sal_Bool bIsOrdinalSuffix = sal_False; |
| sal_Bool bRowFiltered = sal_False; //i89232 |
| |
| rInner = nIStart; |
| while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes |
| { |
| if ( bGetCell ) |
| { |
| if (bVertical) // rInner&:=nRow, rOuter&:=nCol |
| pSrcCell = aCol[nCol].GetCell( static_cast<SCROW>(nSource) ); |
| else // rInner&:=nCol, rOuter&:=nRow |
| pSrcCell = aCol[nSource].GetCell( static_cast<SCROW>(nRow) ); |
| bGetCell = sal_False; |
| if ( pSrcCell ) |
| { |
| eCellType = pSrcCell->GetCellType(); |
| switch ( eCellType ) |
| { |
| case CELLTYPE_VALUE: |
| nVal = ((ScValueCell*)pSrcCell)->GetValue(); |
| break; |
| case CELLTYPE_STRING: |
| case CELLTYPE_EDIT: |
| if ( eCellType == CELLTYPE_STRING ) |
| ((ScStringCell*)pSrcCell)->GetString( aValue ); |
| else |
| ((ScEditCell*)pSrcCell)->GetString( aValue ); |
| if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered) //i89232 |
| { |
| nCellDigits = 0; // look at each source cell individually |
| nHeadNoneTail = lcl_DecompValueString( |
| aValue, nStringValue, &nCellDigits ); |
| |
| bIsOrdinalSuffix = aValue.Equals( |
| ScGlobal::GetOrdinalSuffix( nStringValue)); |
| } |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| } |
| else |
| eCellType = CELLTYPE_NONE; |
| } |
| |
| //Modify for i89232 |
| bRowFiltered = mpFilteredRows->getValue(nRow); |
| |
| if (!bRowFiltered) |
| { |
| //End of i89232 |
| |
| switch (eCellType) |
| { |
| case CELLTYPE_VALUE: |
| aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta)); |
| break; |
| case CELLTYPE_STRING: |
| case CELLTYPE_EDIT: |
| if ( nHeadNoneTail ) |
| { |
| // #i48009# with the "nStringValue+(long)nDelta" expression within the |
| // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3), |
| // so nNextValue is now calculated ahead. |
| sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta; |
| |
| String aStr; |
| if ( nHeadNoneTail < 0 ) |
| { |
| aCol[nCol].Insert( static_cast<SCROW>(nRow), |
| lcl_getSuffixCell( pDocument, |
| nNextValue, nCellDigits, aValue, |
| eCellType, bIsOrdinalSuffix)); |
| } |
| else |
| { |
| aStr = aValue; |
| aStr += lcl_ValueString( nNextValue, nCellDigits ); |
| aCol[nCol].Insert( static_cast<SCROW>(nRow), |
| new ScStringCell( aStr)); |
| } |
| } |
| else |
| { |
| ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); |
| switch ( eCellType ) |
| { |
| case CELLTYPE_STRING: |
| case CELLTYPE_EDIT: |
| aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) ); |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| } |
| break; |
| case CELLTYPE_FORMULA : |
| FillFormula( nFormulaCounter, bFirst, |
| (ScFormulaCell*) pSrcCell, |
| static_cast<SCCOL>(nCol), |
| static_cast<SCROW>(nRow), (rInner == nIEnd) ); |
| if (nFormulaCounter - nActFormCnt > nMaxFormCnt) |
| nMaxFormCnt = nFormulaCounter - nActFormCnt; |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| |
| if (nSource==nISrcEnd) |
| { |
| if ( nSource != nISrcStart ) |
| { // mehr als eine Source-Zelle |
| nSource = nISrcStart; |
| bGetCell = sal_True; |
| } |
| if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered ) //i89232 |
| { |
| if ( bPositive ) |
| nDelta += 1.0; |
| else |
| nDelta -= 1.0; |
| } |
| nFormulaCounter = nActFormCnt; |
| bFirst = sal_False; |
| } |
| else if (bPositive) |
| { |
| ++nSource; |
| bGetCell = sal_True; |
| } |
| else |
| { |
| --nSource; |
| bGetCell = sal_True; |
| } |
| } |
| |
| // Progress in der inneren Schleife nur bei teuren Zellen, |
| // und auch dann nicht fuer jede einzelne |
| |
| ++nProgress; |
| if ( eCellType == CELLTYPE_FORMULA || eCellType == CELLTYPE_EDIT ) |
| rProgress.SetStateOnPercent( nProgress ); |
| |
| if (rInner == nIEnd) break; |
| if (bPositive) ++rInner; else --rInner; |
| } |
| rProgress.SetStateOnPercent( nProgress ); |
| } |
| else |
| { |
| if (!bPositive) |
| nInc = -nInc; |
| double nEndVal = (nInc>=0.0) ? MAXDOUBLE : -MAXDOUBLE; |
| if (bVertical) |
| FillSeries( static_cast<SCCOL>(nCol), nRow1, |
| static_cast<SCCOL>(nCol), nRow2, nFillCount, eFillDir, |
| eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False, |
| rProgress ); |
| else |
| FillSeries( nCol1, static_cast<SCROW>(nRow), nCol2, |
| static_cast<SCROW>(nRow), nFillCount, eFillDir, |
| eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False, |
| rProgress ); |
| nProgress = rProgress.GetState(); |
| } |
| |
| nActFormCnt += nMaxFormCnt; |
| } |
| } |
| |
| String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY ) |
| { |
| String aValue; |
| |
| SCCOL nCol1 = rSource.aStart.Col(); |
| SCROW nRow1 = rSource.aStart.Row(); |
| SCCOL nCol2 = rSource.aEnd.Col(); |
| SCROW nRow2 = rSource.aEnd.Row(); |
| sal_Bool bOk = sal_True; |
| long nIndex = 0; |
| sal_uLong nSrcCount = 0; |
| FillDir eFillDir = FILL_TO_BOTTOM; |
| if ( nEndX == nCol2 && nEndY == nRow2 ) // leer |
| bOk = sal_False; |
| else if ( nEndX == nCol2 ) // nach oben/unten |
| { |
| nEndX = nCol2 = nCol1; // nur erste Spalte ansehen |
| nSrcCount = nRow2 - nRow1 + 1; |
| nIndex = ((long)nEndY) - nRow1; // kann negativ werden |
| if ( nEndY >= nRow1 ) |
| eFillDir = FILL_TO_BOTTOM; |
| else |
| eFillDir = FILL_TO_TOP; |
| } |
| else if ( nEndY == nRow2 ) // nach links/rechts |
| { |
| nEndY = nRow2 = nRow1; // nur erste Zeile ansehen |
| nSrcCount = nCol2 - nCol1 + 1; |
| nIndex = ((long)nEndX) - nCol1; // kann negativ werden |
| if ( nEndX >= nCol1 ) |
| eFillDir = FILL_TO_RIGHT; |
| else |
| eFillDir = FILL_TO_LEFT; |
| } |
| else // Richtung nicht eindeutig |
| bOk = sal_False; |
| |
| if ( bOk ) |
| { |
| FillCmd eFillCmd; |
| FillDateCmd eDateCmd; |
| double nInc; |
| sal_uInt16 nMinDigits; |
| ScUserListData* pListData = NULL; |
| sal_uInt16 nListIndex; |
| |
| FillAnalyse(nCol1,nRow1, nCol2,nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex); |
| |
| if ( pListData ) // benutzerdefinierte Liste |
| { |
| sal_uInt16 nListCount = pListData->GetSubCount(); |
| if ( nListCount ) |
| { |
| sal_uLong nSub = nSrcCount - 1; // nListIndex ist vom letzten Source-Eintrag |
| while ( nIndex < sal::static_int_cast<long>(nSub) ) |
| nIndex += nListCount; |
| sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount; |
| aValue = pListData->GetSubStr(sal::static_int_cast<sal_uInt16>(nPos)); |
| } |
| } |
| else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster |
| { |
| //Add for i89232 |
| if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP)) |
| { |
| long nBegin = 0; |
| long nEnd = 0; |
| if (nEndY > nRow1) |
| { |
| nBegin = nRow2+1; |
| nEnd = nEndY; |
| } |
| else |
| { |
| nBegin = nEndY; |
| nEnd = nRow1 -1; |
| } |
| long nNonFiltered = CountNonFilteredRows(nBegin, nEnd); |
| long nFiltered = nEnd + 1 - nBegin - nNonFiltered; |
| if (nIndex >0) |
| nIndex = nIndex - nFiltered; |
| else |
| nIndex = nIndex + nFiltered; |
| } |
| //End of i89232 |
| |
| long nPosIndex = nIndex; |
| while ( nPosIndex < 0 ) |
| nPosIndex += nSrcCount; |
| sal_uLong nPos = nPosIndex % nSrcCount; |
| SCCOL nSrcX = nCol1; |
| SCROW nSrcY = nRow1; |
| if ( eFillDir == FILL_TO_TOP || eFillDir == FILL_TO_BOTTOM ) |
| nSrcY = sal::static_int_cast<SCROW>( nSrcY + static_cast<SCROW>(nPos) ); |
| else |
| nSrcX = sal::static_int_cast<SCCOL>( nSrcX + static_cast<SCCOL>(nPos) ); |
| |
| ScBaseCell* pCell = GetCell( nSrcX, nSrcY ); |
| if ( pCell ) |
| { |
| sal_Int32 nDelta; |
| if (nIndex >= 0) |
| nDelta = nIndex / nSrcCount; |
| else |
| nDelta = ( nIndex - nSrcCount + 1 ) / nSrcCount; // -1 -> -1 |
| |
| CellType eType = pCell->GetCellType(); |
| switch ( eType ) |
| { |
| case CELLTYPE_STRING: |
| case CELLTYPE_EDIT: |
| { |
| if ( eType == CELLTYPE_STRING ) |
| ((ScStringCell*)pCell)->GetString( aValue ); |
| else |
| ((ScEditCell*)pCell)->GetString( aValue ); |
| if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232 |
| { |
| sal_Int32 nVal; |
| sal_uInt16 nCellDigits = 0; // look at each source cell individually |
| short nFlag = lcl_DecompValueString( aValue, nVal, &nCellDigits ); |
| if ( nFlag < 0 ) |
| { |
| if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal))) |
| aValue = ScGlobal::GetOrdinalSuffix( nVal + nDelta); |
| |
| aValue.Insert( lcl_ValueString( nVal + nDelta, nCellDigits ), 0 ); |
| } |
| else if ( nFlag > 0 ) |
| aValue += lcl_ValueString( nVal + nDelta, nCellDigits ); |
| } |
| } |
| break; |
| case CELLTYPE_VALUE: |
| { |
| // dabei kann's keinen Ueberlauf geben... |
| double nVal = ((ScValueCell*)pCell)->GetValue(); |
| if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232 |
| nVal += (double) nDelta; |
| |
| Color* pColor; |
| sal_uLong nNumFmt = GetNumberFormat( nSrcX, nSrcY ); |
| pDocument->GetFormatTable()-> |
| GetOutputString( nVal, nNumFmt, aValue, &pColor ); |
| } |
| break; |
| // Formeln nicht |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| } |
| } |
| else if ( eFillCmd == FILL_LINEAR || eFillCmd == FILL_DATE ) // Werte |
| { |
| sal_Bool bValueOk; |
| double nStart; |
| sal_Int32 nVal = 0; |
| short nHeadNoneTail = 0; |
| ScBaseCell* pCell = GetCell( nCol1, nRow1 ); |
| if ( pCell ) |
| { |
| CellType eType = pCell->GetCellType(); |
| switch ( eType ) |
| { |
| case CELLTYPE_STRING: |
| case CELLTYPE_EDIT: |
| { |
| if ( eType == CELLTYPE_STRING ) |
| ((ScStringCell*)pCell)->GetString( aValue ); |
| else |
| ((ScEditCell*)pCell)->GetString( aValue ); |
| nHeadNoneTail = lcl_DecompValueString( aValue, nVal ); |
| if ( nHeadNoneTail ) |
| nStart = (double)nVal; |
| else |
| nStart = 0.0; |
| } |
| break; |
| case CELLTYPE_VALUE: |
| nStart = ((ScValueCell*)pCell)->GetValue(); |
| break; |
| case CELLTYPE_FORMULA: |
| nStart = ((ScFormulaCell*)pCell)->GetValue(); |
| break; |
| default: |
| nStart = 0.0; |
| } |
| } |
| else |
| nStart = 0.0; |
| if ( eFillCmd == FILL_LINEAR ) |
| { |
| double nAdd = nInc; |
| bValueOk = ( SubTotal::SafeMult( nAdd, (double) nIndex ) && |
| SubTotal::SafePlus( nStart, nAdd ) ); |
| } |
| else // Datum |
| { |
| bValueOk = sal_True; |
| sal_uInt16 nDayOfMonth = 0; |
| if ( nIndex < 0 ) |
| { |
| nIndex = -nIndex; |
| nInc = -nInc; |
| } |
| for (long i=0; i<nIndex; i++) |
| IncDate( nStart, nDayOfMonth, nInc, eDateCmd ); |
| } |
| |
| if (bValueOk) |
| { |
| if ( nHeadNoneTail ) |
| { |
| if ( nHeadNoneTail < 0 ) |
| { |
| if (aValue.Equals( ScGlobal::GetOrdinalSuffix( nVal))) |
| aValue = ScGlobal::GetOrdinalSuffix( (sal_Int32)nStart ); |
| |
| aValue.Insert( lcl_ValueString( (sal_Int32)nStart, nMinDigits ), 0 ); |
| } |
| else |
| aValue += lcl_ValueString( (sal_Int32)nStart, nMinDigits ); |
| } |
| else |
| { |
| //! Zahlformat je nach Index holen? |
| Color* pColor; |
| sal_uLong nNumFmt = GetNumberFormat( nCol1, nRow1 ); |
| pDocument->GetFormatTable()-> |
| GetOutputString( nStart, nNumFmt, aValue, &pColor ); |
| } |
| } |
| } |
| else |
| { |
| DBG_ERROR("GetAutoFillPreview: falscher Modus"); |
| } |
| } |
| |
| return aValue; |
| } |
| |
| void ScTable::IncDate(double& rVal, sal_uInt16& nDayOfMonth, double nStep, FillDateCmd eCmd) |
| { |
| if (eCmd == FILL_DAY) |
| { |
| rVal += nStep; |
| return; |
| } |
| |
| // class Date Grenzen |
| const sal_uInt16 nMinYear = 1583; |
| const sal_uInt16 nMaxYear = 9956; |
| |
| long nInc = (long) nStep; // nach oben/unten begrenzen ? |
| Date aNullDate = *pDocument->GetFormatTable()->GetNullDate(); |
| Date aDate = aNullDate; |
| aDate += (long)rVal; |
| switch (eCmd) |
| { |
| case FILL_WEEKDAY: |
| { |
| aDate += nInc; |
| DayOfWeek eWeekDay = aDate.GetDayOfWeek(); |
| if (nInc >= 0) |
| { |
| if (eWeekDay == SATURDAY) |
| aDate += 2; |
| else if (eWeekDay == SUNDAY) |
| aDate += 1; |
| } |
| else |
| { |
| if (eWeekDay == SATURDAY) |
| aDate -= 1; |
| else if (eWeekDay == SUNDAY) |
| aDate -= 2; |
| } |
| } |
| break; |
| case FILL_MONTH: |
| { |
| if ( nDayOfMonth == 0 ) |
| nDayOfMonth = aDate.GetDay(); // init |
| long nMonth = aDate.GetMonth(); |
| long nYear = aDate.GetYear(); |
| |
| nMonth += nInc; |
| |
| if (nInc >= 0) |
| { |
| if (nMonth > 12) |
| { |
| long nYAdd = (nMonth-1) / 12; |
| nMonth -= nYAdd * 12; |
| nYear += nYAdd; |
| } |
| } |
| else |
| { |
| if (nMonth < 1) |
| { |
| long nYAdd = 1 - nMonth / 12; // positiv |
| nMonth += nYAdd * 12; |
| nYear -= nYAdd; |
| } |
| } |
| |
| if ( nYear < nMinYear ) |
| aDate = Date( 1,1, nMinYear ); |
| else if ( nYear > nMaxYear ) |
| aDate = Date( 31,12, nMaxYear ); |
| else |
| { |
| aDate.SetMonth((sal_uInt16) nMonth); |
| aDate.SetYear((sal_uInt16) nYear); |
| if ( nDayOfMonth > 28 ) |
| aDate.SetDay( Min( aDate.GetDaysInMonth(), nDayOfMonth ) ); |
| } |
| } |
| break; |
| case FILL_YEAR: |
| { |
| long nYear = aDate.GetYear(); |
| nYear += nInc; |
| if ( nYear < nMinYear ) |
| aDate = Date( 1,1, nMinYear ); |
| else if ( nYear > nMaxYear ) |
| aDate = Date( 31,12, nMaxYear ); |
| else |
| aDate.SetYear((sal_uInt16) nYear); |
| } |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| |
| rVal = aDate - aNullDate; |
| } |
| |
| void ScTable::FillSeries( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, |
| sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, |
| double nStepValue, double nMaxValue, sal_uInt16 nArgMinDigits, |
| sal_Bool bAttribs, ScProgress& rProgress ) |
| { |
| // |
| // Richtung auswerten |
| // |
| |
| sal_Bool bVertical = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP); |
| sal_Bool bPositive = (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_RIGHT); |
| |
| sal_uLong nCol = 0; |
| sal_uLong nRow = 0; |
| sal_uLong& rInner = bVertical ? nRow : nCol; // Schleifenvariablen |
| sal_uLong& rOuter = bVertical ? nCol : nRow; |
| sal_uLong nOStart; |
| sal_uLong nOEnd; |
| sal_uLong nIStart; |
| sal_uLong nIEnd; |
| sal_uLong nISource; |
| |
| if (bVertical) |
| { |
| nFillCount += (nRow2 - nRow1); |
| if (nFillCount == 0) |
| return; |
| nOStart = nCol1; |
| nOEnd = nCol2; |
| if (bPositive) |
| { |
| nISource = nRow1; |
| nIStart = nRow1 + 1; |
| nIEnd = nRow1 + nFillCount; |
| } |
| else |
| { |
| nISource = nRow2; |
| nIStart = nRow2 - 1; |
| nIEnd = nRow2 - nFillCount; |
| } |
| } |
| else |
| { |
| nFillCount += (nCol2 - nCol1); |
| if (nFillCount == 0) |
| return; |
| nOStart = nRow1; |
| nOEnd = nRow2; |
| if (bPositive) |
| { |
| nISource = nCol1; |
| nIStart = nCol1 + 1; |
| nIEnd = nCol1 + nFillCount; |
| } |
| else |
| { |
| nISource = nCol2; |
| nIStart = nCol2 - 1; |
| nIEnd = nCol2 - nFillCount; |
| } |
| } |
| |
| sal_uLong nIMin = nIStart; |
| sal_uLong nIMax = nIEnd; |
| PutInOrder(nIMin,nIMax); |
| sal_uInt16 nDel = bAttribs ? IDF_AUTOFILL : (IDF_AUTOFILL & IDF_CONTENTS); |
| if (bVertical) |
| DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), nDel); |
| else |
| DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, nDel); |
| |
| sal_uLong nProgress = rProgress.GetState(); |
| |
| // |
| // ausfuehren |
| // |
| |
| sal_uLong nActFormCnt = 0; |
| for (rOuter = nOStart; rOuter <= nOEnd; rOuter++) |
| { |
| sal_Bool bFirst = sal_True; |
| rInner = nISource; |
| ScBaseCell* pSrcCell = aCol[nCol].GetCell(static_cast<SCROW>(nRow)); |
| |
| if (bVertical && bAttribs) |
| aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount ); |
| |
| if (bAttribs) |
| { |
| const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow)); |
| if (bVertical) |
| aCol[nCol].SetPatternArea( static_cast<SCROW>(nIMin), |
| static_cast<SCROW>(nIMax), *pSrcPattern, sal_True ); |
| else |
| for (SCCOL nAtCol = static_cast<SCCOL>(nIMin); nAtCol <= sal::static_int_cast<SCCOL>(nIMax); nAtCol++) |
| aCol[nAtCol].SetPattern(static_cast<SCROW>(nRow), *pSrcPattern, sal_True); |
| } |
| |
| if (pSrcCell) |
| { |
| CellType eCellType = pSrcCell->GetCellType(); |
| |
| if (eFillCmd == FILL_SIMPLE) // kopieren |
| { |
| if (eCellType == CELLTYPE_FORMULA) |
| { |
| for (rInner = nIMin; rInner <= nIMax; rInner++) |
| { |
| sal_uLong nInd = nActFormCnt; |
| FillFormula(nInd, bFirst, (ScFormulaCell*)pSrcCell, |
| static_cast<SCCOL>(nCol), nRow, (rInner == nIEnd) ); |
| bFirst = sal_False; |
| rProgress.SetStateOnPercent( ++nProgress ); |
| } |
| } |
| else if (eCellType != CELLTYPE_NOTE) |
| { |
| for (rInner = nIMin; rInner <= nIMax; rInner++) |
| { |
| ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); |
| aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) ); |
| } |
| nProgress += nIMax - nIMin + 1; |
| rProgress.SetStateOnPercent( nProgress ); |
| } |
| } |
| else if (eCellType == CELLTYPE_VALUE || eCellType == CELLTYPE_FORMULA) |
| { |
| double nStartVal; |
| if (eCellType == CELLTYPE_VALUE) |
| nStartVal = ((ScValueCell*)pSrcCell)->GetValue(); |
| else |
| nStartVal = ((ScFormulaCell*)pSrcCell)->GetValue(); |
| double nVal = nStartVal; |
| long nIndex = 0; |
| |
| sal_Bool bError = sal_False; |
| sal_Bool bOverflow = sal_False; |
| |
| sal_uInt16 nDayOfMonth = 0; |
| rInner = nIStart; |
| while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes |
| { |
| if (!bError && !bOverflow) |
| { |
| switch (eFillCmd) |
| { |
| case FILL_LINEAR: |
| { |
| // #86365# use multiplication instead of repeated addition |
| // to avoid accumulating rounding errors |
| nVal = nStartVal; |
| double nAdd = nStepValue; |
| if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) || |
| !SubTotal::SafePlus( nVal, nAdd ) ) |
| bError = sal_True; |
| } |
| break; |
| case FILL_GROWTH: |
| if (!SubTotal::SafeMult(nVal, nStepValue)) |
| bError = sal_True; |
| break; |
| case FILL_DATE: |
| if (fabs(nVal) > _D_MAX_LONG_) |
| bError = sal_True; |
| else |
| IncDate(nVal, nDayOfMonth, nStepValue, eFillDateCmd); |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| |
| if (nStepValue >= 0) |
| { |
| if (nVal > nMaxValue) // Zielwert erreicht? |
| { |
| nVal = nMaxValue; |
| bOverflow = sal_True; |
| } |
| } |
| else |
| { |
| if (nVal < nMaxValue) |
| { |
| nVal = nMaxValue; |
| bOverflow = sal_True; |
| } |
| } |
| } |
| |
| if (bError) |
| aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue); |
| else if (!bOverflow) |
| aCol[nCol].SetValue(static_cast<SCROW>(nRow), nVal); |
| |
| if (rInner == nIEnd) break; |
| if (bPositive) ++rInner; else --rInner; |
| } |
| nProgress += nIMax - nIMin + 1; |
| rProgress.SetStateOnPercent( nProgress ); |
| } |
| else if (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) |
| { |
| if ( nStepValue >= 0 ) |
| { |
| if ( nMaxValue >= (double)LONG_MAX ) |
| nMaxValue = (double)LONG_MAX - 1; |
| } |
| else |
| { |
| if ( nMaxValue <= (double)LONG_MIN ) |
| nMaxValue = (double)LONG_MIN + 1; |
| } |
| String aValue; |
| if (eCellType == CELLTYPE_STRING) |
| ((ScStringCell*)pSrcCell)->GetString( aValue ); |
| else |
| ((ScEditCell*)pSrcCell)->GetString( aValue ); |
| sal_Int32 nStringValue; |
| sal_uInt16 nMinDigits = nArgMinDigits; |
| short nHeadNoneTail = lcl_DecompValueString( aValue, nStringValue, &nMinDigits ); |
| if ( nHeadNoneTail ) |
| { |
| double nStartVal = (double)nStringValue; |
| double nVal = nStartVal; |
| long nIndex = 0; |
| sal_Bool bError = sal_False; |
| sal_Bool bOverflow = sal_False; |
| |
| sal_Bool bIsOrdinalSuffix = aValue.Equals( ScGlobal::GetOrdinalSuffix( |
| (sal_Int32)nStartVal)); |
| |
| rInner = nIStart; |
| while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes |
| { |
| if (!bError && !bOverflow) |
| { |
| switch (eFillCmd) |
| { |
| case FILL_LINEAR: |
| { |
| // #86365# use multiplication instead of repeated addition |
| // to avoid accumulating rounding errors |
| nVal = nStartVal; |
| double nAdd = nStepValue; |
| if ( !SubTotal::SafeMult( nAdd, (double) ++nIndex ) || |
| !SubTotal::SafePlus( nVal, nAdd ) ) |
| bError = sal_True; |
| } |
| break; |
| case FILL_GROWTH: |
| if (!SubTotal::SafeMult(nVal, nStepValue)) |
| bError = sal_True; |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| |
| if (nStepValue >= 0) |
| { |
| if (nVal > nMaxValue) // Zielwert erreicht? |
| { |
| nVal = nMaxValue; |
| bOverflow = sal_True; |
| } |
| } |
| else |
| { |
| if (nVal < nMaxValue) |
| { |
| nVal = nMaxValue; |
| bOverflow = sal_True; |
| } |
| } |
| } |
| |
| if (bError) |
| aCol[nCol].SetError(static_cast<SCROW>(nRow), errNoValue); |
| else if (!bOverflow) |
| { |
| nStringValue = (sal_Int32)nVal; |
| String aStr; |
| if ( nHeadNoneTail < 0 ) |
| { |
| aCol[nCol].Insert( static_cast<SCROW>(nRow), |
| lcl_getSuffixCell( pDocument, |
| nStringValue, nMinDigits, aValue, |
| eCellType, bIsOrdinalSuffix )); |
| } |
| else |
| { |
| aStr = aValue; |
| aStr += lcl_ValueString( nStringValue, nMinDigits ); |
| ScStringCell* pCell = new ScStringCell( aStr ); |
| aCol[nCol].Insert( static_cast<SCROW>(nRow), pCell ); |
| } |
| } |
| |
| if (rInner == nIEnd) break; |
| if (bPositive) ++rInner; else --rInner; |
| } |
| } |
| nProgress += nIMax - nIMin + 1; |
| rProgress.SetStateOnPercent( nProgress ); |
| } |
| } |
| else |
| { |
| nProgress += nIMax - nIMin + 1; |
| rProgress.SetStateOnPercent( nProgress ); |
| } |
| ++nActFormCnt; |
| } |
| } |
| |
| void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, |
| sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd, |
| double nStepValue, double nMaxValue) |
| { |
| sal_uLong nProgCount; |
| if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP) |
| nProgCount = nCol2 - nCol1 + 1; |
| else |
| nProgCount = nRow2 - nRow1 + 1; |
| nProgCount *= nFillCount; |
| ScProgress aProgress( pDocument->GetDocumentShell(), |
| ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount ); |
| |
| bSharedNameInserted = sal_False; |
| |
| if (eFillCmd == FILL_AUTO) |
| FillAuto(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, aProgress); |
| else |
| FillSeries(nCol1, nRow1, nCol2, nRow2, nFillCount, eFillDir, |
| eFillCmd, eFillDateCmd, nStepValue, nMaxValue, 0, sal_True, aProgress); |
| |
| if (bSharedNameInserted) // Wurde Shared-Name eingefuegt? |
| pDocument->GetRangeName()->SetSharedMaxIndex( |
| pDocument->GetRangeName()->GetSharedMaxIndex()+1); // dann hochzaehlen |
| } |
| |
| |
| void ScTable::AutoFormatArea(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, |
| const ScPatternAttr& rAttr, sal_uInt16 nFormatNo) |
| { |
| ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); |
| if (pAutoFormat) |
| { |
| ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo]; |
| if (pData) |
| { |
| // ScPatternAttr aPattern(pDocument->GetPool()); |
| // pData->FillToItemSet(nIndex, aPattern.GetItemSet(), *pDocument); |
| ApplyPatternArea(nStartCol, nStartRow, nEndCol, nEndRow, rAttr); |
| } |
| } |
| } |
| |
| void ScTable::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, |
| sal_uInt16 nFormatNo ) |
| { |
| if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) |
| { |
| ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); |
| if (pAutoFormat) |
| { |
| ScAutoFormatData* pData = (*pAutoFormat)[nFormatNo]; |
| if (pData) |
| { |
| ScPatternAttr* pPatternAttrs[16]; |
| for (sal_uInt8 i = 0; i < 16; ++i) |
| { |
| pPatternAttrs[i] = new ScPatternAttr(pDocument->GetPool()); |
| pData->FillToItemSet(i, pPatternAttrs[i]->GetItemSet(), *pDocument); |
| } |
| |
| SCCOL nCol = nStartCol; |
| SCROW nRow = nStartRow; |
| sal_uInt16 nIndex = 0; |
| // Linke obere Ecke |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| // Linke Spalte |
| if (pData->IsEqualData(4, 8)) |
| AutoFormatArea(nStartCol, nStartRow + 1, nStartCol, nEndRow - 1, *pPatternAttrs[4], nFormatNo); |
| else |
| { |
| nIndex = 4; |
| for (nRow = nStartRow + 1; nRow < nEndRow; nRow++) |
| { |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| if (nIndex == 4) |
| nIndex = 8; |
| else |
| nIndex = 4; |
| } |
| } |
| // Linke untere Ecke |
| nRow = nEndRow; |
| nIndex = 12; |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| // Rechte obere Ecke |
| nCol = nEndCol; |
| nRow = nStartRow; |
| nIndex = 3; |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| // Rechte Spalte |
| if (pData->IsEqualData(7, 11)) |
| AutoFormatArea(nEndCol, nStartRow + 1, nEndCol, nEndRow - 1, *pPatternAttrs[7], nFormatNo); |
| else |
| { |
| nIndex = 7; |
| for (nRow = nStartRow + 1; nRow < nEndRow; nRow++) |
| { |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| if (nIndex == 7) |
| nIndex = 11; |
| else |
| nIndex = 7; |
| } |
| } |
| // Rechte untere Ecke |
| nRow = nEndRow; |
| nIndex = 15; |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| nRow = nStartRow; |
| nIndex = 1; |
| for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) |
| { |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| if (nIndex == 1) |
| nIndex = 2; |
| else |
| nIndex = 1; |
| } |
| // Untere Zeile |
| nRow = nEndRow; |
| nIndex = 13; |
| for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) |
| { |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| if (nIndex == 13) |
| nIndex = 14; |
| else |
| nIndex = 13; |
| } |
| // Boddy |
| if ((pData->IsEqualData(5, 6)) && (pData->IsEqualData(9, 10)) && (pData->IsEqualData(5, 9))) |
| AutoFormatArea(nStartCol + 1, nStartRow + 1, nEndCol-1, nEndRow - 1, *pPatternAttrs[5], nFormatNo); |
| else |
| { |
| if ((pData->IsEqualData(5, 9)) && (pData->IsEqualData(6, 10))) |
| { |
| nIndex = 5; |
| for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) |
| { |
| AutoFormatArea(nCol, nStartRow + 1, nCol, nEndRow - 1, *pPatternAttrs[nIndex], nFormatNo); |
| if (nIndex == 5) |
| nIndex = 6; |
| else |
| nIndex = 5; |
| } |
| } |
| else |
| { |
| nIndex = 5; |
| for (nCol = nStartCol + 1; nCol < nEndCol; nCol++) |
| { |
| for (nRow = nStartRow + 1; nRow < nEndRow; nRow++) |
| { |
| AutoFormatArea(nCol, nRow, nCol, nRow, *pPatternAttrs[nIndex], nFormatNo); |
| if ((nIndex == 5) || (nIndex == 9)) |
| { |
| if (nIndex == 5) |
| nIndex = 9; |
| else |
| nIndex = 5; |
| } |
| else |
| { |
| if (nIndex == 6) |
| nIndex = 10; |
| else |
| nIndex = 6; |
| } |
| } // for nRow |
| if ((nIndex == 5) || (nIndex == 9)) |
| nIndex = 6; |
| else |
| nIndex = 5; |
| } // for nCol |
| } // if not equal Column |
| } // if not all equal |
| |
| for (sal_uInt8 j = 0; j < 16; ++j) |
| delete pPatternAttrs[j]; |
| } // if AutoFormatData != NULL |
| } // if AutoFormat != NULL |
| } // if ValidColRow |
| } |
| |
| void ScTable::GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData) |
| { |
| sal_uInt32 nFormatIndex = GetNumberFormat( nCol, nRow ); |
| ScNumFormatAbbrev aNumFormat( nFormatIndex, *pDocument->GetFormatTable() ); |
| rData.GetFromItemSet( nIndex, GetPattern( nCol, nRow )->GetItemSet(), aNumFormat ); |
| } |
| |
| #define LF_LEFT 1 |
| #define LF_TOP 2 |
| #define LF_RIGHT 4 |
| #define LF_BOTTOM 8 |
| #define LF_ALL (LF_LEFT | LF_TOP | LF_RIGHT | LF_BOTTOM) |
| |
| void ScTable::GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData) |
| { |
| const SvxBoxItem* pTheBox = (SvxBoxItem*)GetAttr(nCol, nRow, ATTR_BORDER); |
| const SvxBoxItem* pLeftBox = (SvxBoxItem*)GetAttr(nCol - 1, nRow, ATTR_BORDER); |
| const SvxBoxItem* pTopBox = (SvxBoxItem*)GetAttr(nCol, nRow - 1, ATTR_BORDER); |
| const SvxBoxItem* pRightBox = (SvxBoxItem*)GetAttr(nCol + 1, nRow, ATTR_BORDER); |
| const SvxBoxItem* pBottomBox = (SvxBoxItem*)GetAttr(nCol, nRow + 1, ATTR_BORDER); |
| |
| SvxBoxItem aBox( ATTR_BORDER ); |
| if (nFlags & LF_LEFT) |
| { |
| if (pLeftBox) |
| { |
| if (ScHasPriority(pTheBox->GetLeft(), pLeftBox->GetRight())) |
| aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT); |
| else |
| aBox.SetLine(pLeftBox->GetRight(), BOX_LINE_LEFT); |
| } |
| else |
| aBox.SetLine(pTheBox->GetLeft(), BOX_LINE_LEFT); |
| } |
| if (nFlags & LF_TOP) |
| { |
| if (pTopBox) |
| { |
| if (ScHasPriority(pTheBox->GetTop(), pTopBox->GetBottom())) |
| aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP); |
| else |
| aBox.SetLine(pTopBox->GetBottom(), BOX_LINE_TOP); |
| } |
| else |
| aBox.SetLine(pTheBox->GetTop(), BOX_LINE_TOP); |
| } |
| if (nFlags & LF_RIGHT) |
| { |
| if (pRightBox) |
| { |
| if (ScHasPriority(pTheBox->GetRight(), pRightBox->GetLeft())) |
| aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT); |
| else |
| aBox.SetLine(pRightBox->GetLeft(), BOX_LINE_RIGHT); |
| } |
| else |
| aBox.SetLine(pTheBox->GetRight(), BOX_LINE_RIGHT); |
| } |
| if (nFlags & LF_BOTTOM) |
| { |
| if (pBottomBox) |
| { |
| if (ScHasPriority(pTheBox->GetBottom(), pBottomBox->GetTop())) |
| aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM); |
| else |
| aBox.SetLine(pBottomBox->GetTop(), BOX_LINE_BOTTOM); |
| } |
| else |
| aBox.SetLine(pTheBox->GetBottom(), BOX_LINE_BOTTOM); |
| } |
| rData.PutItem( nIndex, aBox ); |
| } |
| |
| void ScTable::GetAutoFormatData(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScAutoFormatData& rData) |
| { |
| if (ValidColRow(nStartCol, nStartRow) && ValidColRow(nEndCol, nEndRow)) |
| { |
| if ((nEndCol - nStartCol >= 3) && (nEndRow - nStartRow >= 3)) |
| { |
| // Linke obere Ecke |
| GetAutoFormatAttr(nStartCol, nStartRow, 0, rData); |
| GetAutoFormatFrame(nStartCol, nStartRow, LF_ALL, 0, rData); |
| // Linke Spalte |
| GetAutoFormatAttr(nStartCol, nStartRow + 1, 4, rData); |
| GetAutoFormatAttr(nStartCol, nStartRow + 2, 8, rData); |
| GetAutoFormatFrame(nStartCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 4, rData); |
| if (nEndRow - nStartRow >= 4) |
| GetAutoFormatFrame(nStartCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 8, rData); |
| else |
| rData.CopyItem( 8, 4, ATTR_BORDER ); |
| // Linke untere Ecke |
| GetAutoFormatAttr(nStartCol, nEndRow, 12, rData); |
| GetAutoFormatFrame(nStartCol, nEndRow, LF_ALL, 12, rData); |
| // Rechte obere Ecke |
| GetAutoFormatAttr(nEndCol, nStartRow, 3, rData); |
| GetAutoFormatFrame(nEndCol, nStartRow, LF_ALL, 3, rData); |
| // Rechte Spalte |
| GetAutoFormatAttr(nEndCol, nStartRow + 1, 7, rData); |
| GetAutoFormatAttr(nEndCol, nStartRow + 2, 11, rData); |
| GetAutoFormatFrame(nEndCol, nStartRow + 1, LF_LEFT | LF_RIGHT | LF_BOTTOM, 7, rData); |
| if (nEndRow - nStartRow >= 4) |
| GetAutoFormatFrame(nEndCol, nStartRow + 2, LF_LEFT | LF_RIGHT | LF_BOTTOM, 11, rData); |
| else |
| rData.CopyItem( 11, 7, ATTR_BORDER ); |
| // Rechte untere Ecke |
| GetAutoFormatAttr(nEndCol, nEndRow, 15, rData); |
| GetAutoFormatFrame(nEndCol, nEndRow, LF_ALL, 15, rData); |
| // Ober Zeile |
| GetAutoFormatAttr(nStartCol + 1, nStartRow, 1, rData); |
| GetAutoFormatAttr(nStartCol + 2, nStartRow, 2, rData); |
| GetAutoFormatFrame(nStartCol + 1, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 1, rData); |
| if (nEndCol - nStartCol >= 4) |
| GetAutoFormatFrame(nStartCol + 2, nStartRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 2, rData); |
| else |
| rData.CopyItem( 2, 1, ATTR_BORDER ); |
| // Untere Zeile |
| GetAutoFormatAttr(nStartCol + 1, nEndRow, 13, rData); |
| GetAutoFormatAttr(nStartCol + 2, nEndRow, 14, rData); |
| GetAutoFormatFrame(nStartCol + 1, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 13, rData); |
| if (nEndCol - nStartCol >= 4) |
| GetAutoFormatFrame(nStartCol + 2, nEndRow, LF_TOP | LF_BOTTOM | LF_RIGHT, 14, rData); |
| else |
| rData.CopyItem( 14, 13, ATTR_BORDER ); |
| // Body |
| GetAutoFormatAttr(nStartCol + 1, nStartRow + 1, 5, rData); |
| GetAutoFormatAttr(nStartCol + 2, nStartRow + 1, 6, rData); |
| GetAutoFormatAttr(nStartCol + 1, nStartRow + 2, 9, rData); |
| GetAutoFormatAttr(nStartCol + 2, nStartRow + 2, 10, rData); |
| GetAutoFormatFrame(nStartCol + 1, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 5, rData); |
| if ((nEndCol - nStartCol >= 4) && (nEndRow - nStartRow >= 4)) |
| { |
| GetAutoFormatFrame(nStartCol + 2, nStartRow + 1, LF_RIGHT | LF_BOTTOM, 6, rData); |
| GetAutoFormatFrame(nStartCol + 1, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 9, rData); |
| GetAutoFormatFrame(nStartCol + 2, nStartRow + 2, LF_RIGHT | LF_BOTTOM, 10, rData); |
| } |
| else |
| { |
| rData.CopyItem( 6, 5, ATTR_BORDER ); |
| rData.CopyItem( 9, 5, ATTR_BORDER ); |
| rData.CopyItem( 10, 5, ATTR_BORDER ); |
| } |
| } |
| } |
| } |
| |
| void ScTable::SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError) |
| { |
| if (ValidColRow(nCol, nRow)) |
| aCol[nCol].SetError( nRow, nError ); |
| } |
| |
| void ScTable::UpdateInsertTabAbs(SCTAB nTable) |
| { |
| for (SCCOL i=0; i <= MAXCOL; i++) |
| aCol[i].UpdateInsertTabAbs(nTable); |
| } |
| |
| //UNUSED2008-05 sal_uInt16 ScTable::GetErrorData( SCCOL nCol, SCROW nRow ) const |
| //UNUSED2008-05 { |
| //UNUSED2008-05 if (ValidColRow(nCol,nRow)) |
| //UNUSED2008-05 return aCol[nCol].GetErrorData( nRow ); |
| //UNUSED2008-05 else |
| //UNUSED2008-05 return 0; |
| //UNUSED2008-05 } |
| |
| sal_Bool ScTable::GetNextSpellingCell(SCCOL& rCol, SCROW& rRow, sal_Bool bInSel, |
| const ScMarkData& rMark) const |
| { |
| if (rRow == MAXROW+2) // Tabellenende |
| { |
| rRow = 0; |
| rCol = 0; |
| } |
| else |
| { |
| rRow++; |
| if (rRow == MAXROW+1) |
| { |
| rCol++; |
| rRow = 0; |
| } |
| } |
| if (rCol == MAXCOL+1) |
| return sal_True; |
| else |
| { |
| sal_Bool bStop = sal_False; |
| while (!bStop) |
| { |
| if (ValidCol(rCol)) |
| { |
| bStop = aCol[rCol].GetNextSpellingCell(rRow, bInSel, rMark); |
| if (bStop) |
| return sal_True; |
| else /*if (rRow == MAXROW+1) */ |
| { |
| rCol++; |
| rRow = 0; |
| } |
| } |
| else |
| return sal_True; |
| } |
| } |
| return sal_False; |
| } |
| |
| void ScTable::RemoveAutoSpellObj() |
| { |
| for (SCCOL i=0; i <= MAXCOL; i++) |
| aCol[i].RemoveAutoSpellObj(); |
| } |
| |
| sal_Bool ScTable::TestTabRefAbs(SCTAB nTable) |
| { |
| sal_Bool bRet = sal_False; |
| for (SCCOL i=0; i <= MAXCOL; i++) |
| if (aCol[i].TestTabRefAbs(nTable)) |
| bRet = sal_True; |
| return bRet; |
| } |
| |
| void ScTable::CompileDBFormula() |
| { |
| for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula(); |
| } |
| |
| void ScTable::CompileDBFormula( sal_Bool bCreateFormulaString ) |
| { |
| for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString ); |
| } |
| |
| void ScTable::CompileNameFormula( sal_Bool bCreateFormulaString ) |
| { |
| for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString ); |
| } |
| |
| void ScTable::CompileColRowNameFormula() |
| { |
| for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula(); |
| } |
| |
| SCSIZE ScTable::GetPatternCount( SCCOL nCol ) |
| { |
| if( ValidCol( nCol ) ) |
| return aCol[nCol].GetPatternCount(); |
| else |
| return 0; |
| } |
| |
| SCSIZE ScTable::GetPatternCount( SCCOL nCol, SCROW nRw1, SCROW nRw2 ) |
| { |
| if( ValidCol( nCol ) && ValidRow( nRw1 ) && ValidRow( nRw2 ) ) |
| return aCol[nCol].GetPatternCount( nRw1, nRw2 ); |
| else |
| return 0; |
| } |
| |
| bool ScTable::ReservedPatternCount( SCCOL nCol, SCSIZE nReserved ) |
| { |
| if( ValidCol( nCol ) ) |
| return aCol[nCol].ReservedPatternCount( nReserved ); |
| else |
| return false; |
| } |