/************************************************************** * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 // 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(nRow2 - nRow1 + 1); } else { nAddX = 1; nAddY = 0; nCount = static_cast(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( nCol + nAddX ); nRow = sal::static_int_cast( nRow + nAddY ); sal_Bool bVal = sal_True; for (sal_uInt16 i=1; iGetCellType() == 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( nCol + nAddX ); nRow = sal::static_int_cast( 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( nCol + nAddX ); nRow = sal::static_int_cast( nRow + nAddY ); sal_Bool bVal = sal_True; for (sal_uInt16 i=1; iGetCellType() == 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( nCol + nAddX ); nRow = sal::static_int_cast( 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( nCol + nAddX ); nRow = sal::static_int_cast( nRow + nAddY ); for (sal_uInt16 i=1; iGetSubIndex(aStr, rListIndex)) rListData = NULL; nCol = sal::static_int_cast( nCol + nAddX ); nRow = sal::static_int_cast( 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( nCol + nAddX ); nRow = sal::static_int_cast( nRow + nAddY ); sal_Bool bVal = sal_True; for (sal_uInt16 i=1; iGetCellType() : 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( nCol + nAddX ); nRow = sal::static_int_cast( 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(nIMin), nCol2, static_cast(nIMax), IDF_AUTOFILL); else DeleteArea(static_cast(nIMin), nRow1, static_cast(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(nAtSrc)); else // rInner&:=nCol, rOuter&:=nRow pSrcPattern = aCol[nAtSrc].GetPattern(static_cast(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(Min( nIStart, nIEnd )); SCROW nY2 = static_cast(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(nCol), static_cast(nRow), static_cast(nCol), static_cast(nRow), IDF_AUTOFILL); if ( pSrcPattern != aCol[nCol].GetPattern( static_cast(nRow) ) ) { // Vorlage auch uebernehmen //! am AttrArray mit ApplyPattern zusammenfassen ?? if ( pStyleSheet ) aCol[nCol].ApplyStyle( static_cast(nRow), *pStyleSheet ); // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen if ( pNewPattern ) aCol[nCol].ApplyPattern( static_cast(nRow), *pNewPattern ); else aCol[nCol].ApplyPattern( static_cast(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(nCol),nRow1, static_cast(nCol),nRow2, eFillCmd,eDateCmd, nInc,nMinDigits, pListData,nListIndex); else FillAnalyse(nCol1,static_cast(nRow), nCol2,static_cast(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= nListCount) nListIndex = 0; } else { if (nListIndex == 0) nListIndex = nListCount; --nListIndex; } aCol[nCol].Insert(static_cast(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(nSource) ); else // rInner&:=nCol, rOuter&:=nRow pSrcCell = aCol[nSource].GetCell( static_cast(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(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(nRow), lcl_getSuffixCell( pDocument, nNextValue, nCellDigits, aValue, eCellType, bIsOrdinalSuffix)); } else { aStr = aValue; aStr += lcl_ValueString( nNextValue, nCellDigits ); aCol[nCol].Insert( static_cast(nRow), new ScStringCell( aStr)); } } else { ScAddress aDestPos( static_cast(nCol), static_cast(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(nCol), static_cast(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(nCol), nRow1, static_cast(nCol), nRow2, nFillCount, eFillDir, eFillCmd, eDateCmd, nInc, nEndVal, nMinDigits, sal_False, rProgress ); else FillSeries( nCol1, static_cast(nRow), nCol2, static_cast(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(nSub) ) nIndex += nListCount; sal_uLong nPos = ( nListIndex + nIndex - nSub ) % nListCount; aValue = pListData->GetSubStr(sal::static_int_cast(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( nSrcY + static_cast(nPos) ); else nSrcX = sal::static_int_cast( nSrcX + static_cast(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; iGetFormatTable()-> 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(nIMin), nCol2, static_cast(nIMax), nDel); else DeleteArea(static_cast(nIMin), nRow1, static_cast(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(nRow)); if (bVertical && bAttribs) aCol[nCol].Resize( aCol[nCol].GetCellCount() + nFillCount ); if (bAttribs) { const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast(nRow)); if (bVertical) aCol[nCol].SetPatternArea( static_cast(nIMin), static_cast(nIMax), *pSrcPattern, sal_True ); else for (SCCOL nAtCol = static_cast(nIMin); nAtCol <= sal::static_int_cast(nIMax); nAtCol++) aCol[nAtCol].SetPattern(static_cast(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(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(nCol), static_cast(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(nRow), errNoValue); else if (!bOverflow) aCol[nCol].SetValue(static_cast(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(nRow), errNoValue); else if (!bOverflow) { nStringValue = (sal_Int32)nVal; String aStr; if ( nHeadNoneTail < 0 ) { aCol[nCol].Insert( static_cast(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(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; }