diff options
Diffstat (limited to 'sc')
33 files changed, 579 insertions, 320 deletions
diff --git a/sc/inc/datauno.hxx b/sc/inc/datauno.hxx index cf47b7b3bc62..34345e4a3c07 100644 --- a/sc/inc/datauno.hxx +++ b/sc/inc/datauno.hxx @@ -40,6 +40,7 @@ #include <com/sun/star/sheet/XConsolidationDescriptor.hpp> #include <com/sun/star/sheet/XDatabaseRanges.hpp> #include <com/sun/star/sheet/XDatabaseRange.hpp> +#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp> #include <com/sun/star/sheet/XSubTotalDescriptor.hpp> #include <com/sun/star/sheet/XSubTotalField.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -501,6 +502,8 @@ private: String aName; SfxItemPropertySet aPropSet; XDBRefreshListenerArr_Impl aRefreshListeners; + bool bIsUnnamed; + SCTAB aTab; private: ScDBData* GetDBData_Impl() const; @@ -508,6 +511,7 @@ private: public: ScDatabaseRangeObj(ScDocShell* pDocSh, const String& rNm); + ScDatabaseRangeObj(ScDocShell* pDocSh, const SCTAB nTab); virtual ~ScDatabaseRangeObj(); virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); @@ -662,6 +666,32 @@ public: throw(::com::sun::star::uno::RuntimeException); }; +class ScUnnamedDatabaseRangesObj : public cppu::WeakImplHelper1< + com::sun::star::sheet::XUnnamedDatabaseRanges>, + public SfxListener +{ +private: + ScDocShell* pDocShell; + +public: + ScUnnamedDatabaseRangesObj(ScDocShell* pDocSh); + virtual ~ScUnnamedDatabaseRangesObj(); + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + + // XUnnamedDatabaseRanges + virtual void SAL_CALL setByTable( const ::com::sun::star::table::CellRangeAddress& aRange ) + throw(::com::sun::star::uno::RuntimeException, + ::com::sun::star::lang::IndexOutOfBoundsException ); + virtual com::sun::star::uno::Any SAL_CALL getByTable( const sal_Int32 nTab ) + throw(::com::sun::star::uno::RuntimeException, + ::com::sun::star::lang::IndexOutOfBoundsException, + ::com::sun::star::container::NoSuchElementException ); + virtual sal_Bool SAL_CALL hasByTable( sal_Int32 nTab ) + throw (::com::sun::star::uno::RuntimeException, + ::com::sun::star::lang::IndexOutOfBoundsException); +}; + #endif diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 19496d0f3f15..3c485fd48575 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1487,7 +1487,6 @@ public: VirtualDevice* GetVirtualDevice_100th_mm(); SC_DLLPUBLIC OutputDevice* GetRefDevice(); // WYSIWYG: Printer, otherwise VirtualDevice... - void EraseNonUsedSharedNames(sal_uInt16 nLevel); sal_Bool GetNextSpellingCell(SCCOL& nCol, SCROW& nRow, SCTAB nTab, sal_Bool bInSel, const ScMarkData& rMark) const; diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 30ca8406d11e..d71040906443 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -297,6 +297,11 @@ public: ::rtl::OUString maDBName; ::rtl::OUString maCommand; DBType(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + + struct less : public ::std::binary_function<DBType, DBType, bool> + { + bool operator() (const DBType& left, const DBType& right) const; + }; }; /** @@ -304,7 +309,7 @@ public: */ class DBCaches { - typedef ::boost::ptr_map<DBType, ScDPCache> CachesType; + typedef ::boost::ptr_map<DBType, ScDPCache, DBType::less> CachesType; CachesType maCaches; ScDocument* mpDoc; public: diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index c9e00e64dfb1..3689634ba62d 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -181,7 +181,6 @@ class ScRangeName private: typedef ::boost::ptr_set<ScRangeData> DataType; DataType maData; - sal_uInt16 mnSharedMaxIndex; public: /// Map that manages stored ScRangeName instances. @@ -208,8 +207,6 @@ public: void UpdateTabRef(SCTAB nTable, sal_uInt16 nFlag, SCTAB nNewTable = 0); void UpdateTranspose(const ScRange& rSource, const ScAddress& rDest); void UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY); - sal_uInt16 GetSharedMaxIndex(); - void SetSharedMaxIndex(sal_uInt16 nInd); SC_DLLPUBLIC const_iterator begin() const; SC_DLLPUBLIC const_iterator end() const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 26cb8a846263..cf30f6b23cd8 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -173,7 +173,6 @@ private: ScSortParam aSortParam; CollatorWrapper* pSortCollator; sal_Bool bGlobalKeepQuery; - sal_Bool bSharedNameInserted; ScRangeVec aPrintRanges; bool bPrintEntireSheet; diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 5fb6edaf592d..7bc50f1af812 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -48,6 +48,7 @@ #define SC_UNO_EXTERNALDOCLINKS "ExternalDocLinks" #define SC_UNO_COLLABELRNG "ColumnLabelRanges" #define SC_UNO_DATABASERNG "DatabaseRanges" +#define SC_UNO_UNNAMEDDBRNG "UnnamedDatabaseRanges" #define SC_UNO_NAMEDRANGES "NamedRanges" #define SC_UNO_ROWLABELRNG "RowLabelRanges" #define SC_UNO_SHEETLINKS "SheetLinks" diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 35558d1a75a3..56e205c696a2 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -49,6 +49,8 @@ #include <cppuhelper/bootstrap.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/oslfile2streamwrap.hxx> +#include <i18npool/mslangid.hxx> +#include <unotools/syslocaleoptions.hxx> #include <vcl/svapp.hxx> #include "scdll.hxx" @@ -224,7 +226,7 @@ public: void testCollator(); void testInput(); - void testSUM(); + void testCellFunctions(); void testVolatileFunc(); void testFuncParam(); void testNamedRange(); @@ -264,7 +266,7 @@ public: CPPUNIT_TEST_SUITE(Test); CPPUNIT_TEST(testCollator); CPPUNIT_TEST(testInput); - CPPUNIT_TEST(testSUM); + CPPUNIT_TEST(testCellFunctions); CPPUNIT_TEST(testVolatileFunc); CPPUNIT_TEST(testFuncParam); CPPUNIT_TEST(testNamedRange); @@ -304,28 +306,6 @@ Test::Test() //of retaining references to the root ServiceFactory as its passed around comphelper::setProcessServiceFactory(xSM); -#if 0 - // TODO: attempt to explicitly set UI locale to en-US, to get the unit - // test to work under non-English build environment. But this causes - // runtime exception.... - uno::Reference<lang::XMultiServiceFactory> theConfigProvider = - uno::Reference<lang::XMultiServiceFactory> ( - xSM->createInstance( - OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider"))), uno::UNO_QUERY_THROW); - - uno::Sequence<uno::Any> theArgs(1); - OUString aLocalePath(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Linguistic/General")); - theArgs[0] <<= aLocalePath; - uno::Reference<beans::XPropertySet> xProp( - theConfigProvider->createInstanceWithArguments( - OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationUpdateAccess")), theArgs), uno::UNO_QUERY_THROW); - - OUString aLang(RTL_CONSTASCII_USTRINGPARAM("en-US")); - uno::Any aAny; - aAny <<= aLang; - xProp->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("UILocale")), aAny); -#endif - // initialise UCB-Broker uno::Sequence<uno::Any> aUcbInitSequence(2); aUcbInitSequence[0] <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Local")); @@ -339,8 +319,19 @@ Test::Test() rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.FileContentProvider"))), uno::UNO_QUERY); xUcb->registerContentProvider(xFileProvider, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("file")), sal_True); - InitVCL(xSM); + // force locale (and resource files loaded) to en-US + const LanguageType eLang=LANGUAGE_ENGLISH_US; + + rtl::OUString aLang, aCountry; + MsLangId::convertLanguageToIsoNames(eLang, aLang, aCountry); + lang::Locale aLocale(aLang, aCountry, rtl::OUString()); + ResMgr::SetDefaultLocale( aLocale ); + SvtSysLocaleOptions aLocalOptions; + aLocalOptions.SetUILocaleConfigString( + MsLangId::convertLanguageToIsoString( eLang ) ); + + InitVCL(xSM); ScDLL::Init(); oslProcessError err = osl_getProcessWorkingDir(&m_aPWDURL.pData); @@ -398,11 +389,13 @@ void Test::testInput() m_pDoc->DeleteTab(0); } -void Test::testSUM() +void Test::testCellFunctions() { rtl::OUString aTabName(RTL_CONSTASCII_USTRINGPARAM("foo")); CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet", m_pDoc->InsertTab (0, aTabName)); + + // SUM double val = 1; m_pDoc->SetValue (0, 0, 0, val); m_pDoc->SetValue (0, 1, 0, val); @@ -412,6 +405,23 @@ void Test::testSUM() m_pDoc->GetValue (0, 2, 0, result); CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 2.0); + // PRODUCT + val = 1; + m_pDoc->SetValue(0, 0, 0, val); + val = 2; + m_pDoc->SetValue(0, 1, 0, val); + val = 3; + m_pDoc->SetValue(0, 2, 0, val); + m_pDoc->SetString(0, 3, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=PRODUCT(A1:A3)"))); + m_pDoc->CalcAll(); + m_pDoc->GetValue(0, 3, 0, result); + CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT failed", result == 6.0); + + m_pDoc->SetString(0, 4, 0, OUString(RTL_CONSTASCII_USTRINGPARAM("=PRODUCT({1;2;3})"))); + m_pDoc->CalcAll(); + m_pDoc->GetValue(0, 4, 0, result); + CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT with inline array failed", result == 6.0); + m_pDoc->DeleteTab(0); } @@ -779,7 +789,7 @@ ScDPObject* createDPFromRange( { OUString aDimName(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8); ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName); - pDim->SetOrientation(aFields[i].eOrient); + pDim->SetOrientation(static_cast<sal_uInt16>(aFields[i].eOrient)); pDim->SetUsedHierarchy(0); pDim->SetShowEmpty(true); diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 40390816128b..2668893ed4d3 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -1270,7 +1270,8 @@ ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) : pAreas( NULL ), nKey( r.nKey ), ppEntries( NULL ), - nEntryCount( r.nEntryCount ) + nEntryCount( r.nEntryCount ), + pRanges( NULL ) { if (nEntryCount) { @@ -1281,7 +1282,8 @@ ScConditionalFormat::ScConditionalFormat(const ScConditionalFormat& r) : ppEntries[i]->SetParent(this); } } - pRanges = new ScRangeList( *r.pRanges ); + if (r.pRanges) + pRanges = new ScRangeList( *r.pRanges ); } ScConditionalFormat* ScConditionalFormat::Clone(ScDocument* pNewDoc) const @@ -1320,10 +1322,16 @@ sal_Bool ScConditionalFormat::EqualEntries( const ScConditionalFormat& r ) const if ( ! (*ppEntries[i] == *r.ppEntries[i]) ) return false; - if( *pRanges != *r.pRanges ) - return false; + if (pRanges) + { + if (r.pRanges) + return *pRanges == *r.pRanges; + else + return false; + } - return true; + // pRanges is NULL, which means r.pRanges must be NULL. + return r.pRanges.Is() == false; } void ScConditionalFormat::AddRangeInfo( const ScRangeListRef& rRanges ) diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 2188a458a855..756990e681bc 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -1130,53 +1130,6 @@ void ScDocument::SetError( SCCOL nCol, SCROW nRow, SCTAB nTab, const sal_uInt16 pTab[nTab]->SetError( nCol, nRow, nError ); } -namespace { - -bool eraseUnusedSharedName(ScRangeName* pRangeName, ScTable* pTab[], sal_uInt16 nLevel) -{ - if (!pRangeName) - return false; - - ScRangeName::iterator itr = pRangeName->begin(), itrEnd = pRangeName->end(); - for (; itr != itrEnd; ++itr) - { - if (!itr->HasType(RT_SHARED)) - continue; - - String aName; - itr->GetName(aName); - aName.Erase(0, 6); // !!! vgl. Table4, FillFormula !! - sal_uInt16 nInd = static_cast<sal_uInt16>(aName.ToInt32()); - if (nInd > nLevel) - continue; - - sal_uInt16 nIndex = itr->GetIndex(); - - bool bInUse = false; - for (SCTAB j = 0; !bInUse && (j <= MAXTAB); ++j) - { - if (pTab[j]) - bInUse = pTab[j]->IsRangeNameInUse(0, 0, MAXCOL-1, MAXROW-1, nIndex); - } - if (!bInUse) - { - pRangeName->erase(itr); - return true; - } - } - return false; -} - -} - -void ScDocument::EraseNonUsedSharedNames(sal_uInt16 nLevel) -{ - if (!pRangeName) - return; - while (eraseUnusedSharedName(pRangeName, pTab, nLevel)) - ; -} - // ---------------------------------------------------------------------------- void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData ) diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index 1958bf721a4c..b9c79e1c9ebf 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -296,42 +296,71 @@ void ScDocument::InsertTableOp(const ScTabOpParam& rParam, // Mehrfachopera pTab[i]->PutCell( j, k, aRefCell.CloneWithoutNote( *this, ScAddress( j, k, i ), SC_CLONECELL_STARTLISTENING ) ); } +namespace { + +bool setCacheTableReferenced(ScToken& rToken, ScExternalRefManager& rRefMgr) +{ + switch (rToken.GetType()) + { + case svExternalSingleRef: + return rRefMgr.setCacheTableReferenced( + rToken.GetIndex(), rToken.GetString(), 1); + case svExternalDoubleRef: + { + const ScComplexRefData& rRef = rToken.GetDoubleRef(); + size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1; + return rRefMgr.setCacheTableReferenced( + rToken.GetIndex(), rToken.GetString(), nSheets); + } + case svExternalName: + /* TODO: external names aren't supported yet, but would + * have to be marked as well, if so. Mechanism would be + * different. */ + DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!"); + default: + ; + } + return false; +} + +} + bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr ) { + if (!rArr.GetLen()) + return false; + + ScExternalRefManager* pRefMgr = NULL; + rArr.Reset(); + ScToken* t = NULL; bool bAllMarked = false; - if (rArr.GetLen()) + while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL) { - ScExternalRefManager* pRefMgr = NULL; - rArr.Reset(); - ScToken* t; - while (!bAllMarked && (t = static_cast<ScToken*>(rArr.GetNextReferenceOrName())) != NULL) + if (t->IsExternalRef()) + { + if (!pRefMgr) + pRefMgr = GetExternalRefManager(); + + bAllMarked = setCacheTableReferenced(*t, *pRefMgr); + } + else if (t->GetType() == svIndex) { - if (t->IsExternalRef()) + // this is a named range. Check if the range contains an external + // reference. + ScRangeData* pRangeData = GetRangeName()->findByIndex(t->GetIndex()); + if (!pRangeData) + continue; + + ScTokenArray* pArray = pRangeData->GetCode(); + for (t = static_cast<ScToken*>(pArray->First()); t; t = static_cast<ScToken*>(pArray->Next())) { + if (!t->IsExternalRef()) + continue; + if (!pRefMgr) pRefMgr = GetExternalRefManager(); - switch (t->GetType()) - { - case svExternalSingleRef: - bAllMarked = pRefMgr->setCacheTableReferenced( - t->GetIndex(), t->GetString(), 1); - break; - case svExternalDoubleRef: - { - const ScComplexRefData& rRef = t->GetDoubleRef(); - size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1; - bAllMarked = pRefMgr->setCacheTableReferenced( - t->GetIndex(), t->GetString(), nSheets); - } - break; - case svExternalName: - /* TODO: external names aren't supported yet, but would - * have to be marked as well, if so. Mechanism would be - * different. */ - DBG_ERRORFILE("ScDocument::MarkUsedExternalReferences: implement the svExternalName case!"); - break; - default: break; - } + + bAllMarked = setCacheTableReferenced(*t, *pRefMgr); } } } diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 8d236383dac2..b8f026503dc4 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -5422,7 +5422,14 @@ void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange) void ScDocument::EnableUndo( bool bVal ) { - GetUndoManager()->EnableUndo(bVal); + // The undo manager increases lock count every time undo is disabled. + // Because of this, we shouldn't disable undo unless it's currently + // enabled, or else re-enabling it may not actually re-enable undo unless + // the lock count becomes zero. + + if (bVal != GetUndoManager()->IsUndoEnabled()) + GetUndoManager()->EnableUndo(bVal); + mbUndoEnabled = bVal; } diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 9589fe838f7a..7f5abef802ea 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -2445,6 +2445,11 @@ void ScDPCollection::NameCaches::removeCache(const OUString& rName) ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) : mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {} +bool ScDPCollection::DBType::less::operator() (const DBType& left, const DBType& right) const +{ + return left < right; +} + ScDPCollection::DBCaches::DBCaches(ScDocument* pDoc) : mpDoc(pDoc) {} const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index d4c194676471..554a22773dd6 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -1696,6 +1696,8 @@ void ScTable::SetRepeatColRange( const ScRange* pNew ) if (IsStreamValid()) SetStreamValid(false); + + InvalidatePageBreaks(); } void ScTable::SetRepeatRowRange( const ScRange* pNew ) @@ -1704,6 +1706,8 @@ void ScTable::SetRepeatRowRange( const ScRange* pNew ) if (IsStreamValid()) SetStreamValid(false); + + InvalidatePageBreaks(); } void ScTable::ClearPrintRanges() @@ -1713,6 +1717,8 @@ void ScTable::ClearPrintRanges() if (IsStreamValid()) SetStreamValid(false); + + InvalidatePageBreaks(); } void ScTable::AddPrintRange( const ScRange& rNew ) @@ -1723,6 +1729,8 @@ void ScTable::AddPrintRange( const ScRange& rNew ) if (IsStreamValid()) SetStreamValid(false); + + InvalidatePageBreaks(); } diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 646be060b6a9..c5e2c7644085 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -157,18 +157,17 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE if (!maRowManualBreaks.empty()) { - std::set<SCROW>::reverse_iterator rit = maRowManualBreaks.rbegin(); - while (rit != maRowManualBreaks.rend()) - { - SCROW nRow = *rit; - if (nRow < nStartRow) - break; // while - else - { - maRowManualBreaks.erase( (++rit).base()); - maRowManualBreaks.insert( static_cast<SCROW>( nRow + nSize)); - } - } + // Copy all breaks up to nStartRow (non-inclusive). + ::std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow); + ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1); + + // Copy all breaks from nStartRow (inclusive) to the last element, + // but add nSize to each value. + ::std::set<SCROW>::iterator itr2 = maRowManualBreaks.end(); + for (; itr1 != itr2; ++itr1) + aNewBreaks.insert(static_cast<SCROW>(*itr1 + nSize)); + + maRowManualBreaks.swap(aNewBreaks); } } @@ -208,14 +207,21 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE if (!maRowManualBreaks.empty()) { - std::set<SCROW>::iterator it = maRowManualBreaks.upper_bound( static_cast<SCROW>( nStartRow + nSize - 1)); - maRowManualBreaks.erase( maRowManualBreaks.lower_bound( nStartRow), it); - while (it != maRowManualBreaks.end()) - { - SCROW nRow = *it; - maRowManualBreaks.erase( it++); - maRowManualBreaks.insert( static_cast<SCROW>( nRow - nSize)); - } + // Erase all manual breaks between nStartRow and nStartRow + nSize - 1 (inclusive). + std::set<SCROW>::iterator itr1 = maRowManualBreaks.lower_bound(nStartRow); + std::set<SCROW>::iterator itr2 = maRowManualBreaks.upper_bound(static_cast<SCROW>(nStartRow + nSize - 1)); + maRowManualBreaks.erase(itr1, itr2); + + // Copy all breaks from the 1st element up to nStartRow to the new container. + itr1 = maRowManualBreaks.lower_bound(nStartRow); + ::std::set<SCROW> aNewBreaks(maRowManualBreaks.begin(), itr1); + + // Copy all breaks from nStartRow to the last element, but subtract each value by nSize. + itr2 = maRowManualBreaks.end(); + for (; itr1 != itr2; ++itr1) + aNewBreaks.insert(static_cast<SCROW>(*itr1 - nSize)); + + maRowManualBreaks.swap(aNewBreaks); } } diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index 55b4da849665..edba012fadd1 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -1576,17 +1576,11 @@ void ScTable::Fill( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScProgress aProgress( pDocument->GetDocumentShell(), ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount ); - bSharedNameInserted = 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 } diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index ce59c16ffa20..7caee7518f8b 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -316,6 +316,7 @@ void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCac void PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef); void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray); void PopExternalDoubleRef(ScMatrixRef& rMat); +void GetExternalDoubleRef(sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray); sal_Bool PopDoubleRefOrSingleRef( ScAddress& rAdr ); void PopDoubleRefPushMatrix(); // If MatrixFormula: convert formula::svDoubleRef to svMatrix, create JumpMatrix. diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 476eb6ef2cb0..c4a8cdd346cd 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -810,6 +810,38 @@ double ScInterpreter::Compare() } } break; + case svExternalSingleRef: + { + ScMatrixRef pMat = GetMatrix(); + if (!pMat) + { + SetError( errIllegalParameter); + break; + } + + SCSIZE nC, nR; + pMat->GetDimensions(nC, nR); + if (!nC || !nR) + { + SetError( errIllegalParameter); + break; + } + if (pMat->IsEmpty(0, 0)) + aComp.bEmpty[i] = true; + else if (pMat->IsString(0, 0)) + { + *aComp.pVal[i] = pMat->GetString(0, 0); + aComp.bVal[i] = false; + } + else + { + aComp.nVal[i] = pMat->GetDouble(0, 0); + aComp.bVal[i] = true; + } + } + break; + case svExternalDoubleRef: + // TODO: Find out how to handle this... default: SetError( errIllegalParameter); break; @@ -2908,8 +2940,10 @@ void ScInterpreter::ScMin( sal_Bool bTextAsZero ) } break; case svMatrix : + case svExternalSingleRef: + case svExternalDoubleRef: { - ScMatrixRef pMat = PopMatrix(); + ScMatrixRef pMat = GetMatrix(); if (pMat) { SCSIZE nC, nR; @@ -3029,8 +3063,10 @@ void ScInterpreter::ScMax( sal_Bool bTextAsZero ) } break; case svMatrix : + case svExternalSingleRef: + case svExternalDoubleRef: { - ScMatrixRef pMat = PopMatrix(); + ScMatrixRef pMat = GetMatrix(); if (pMat) { nFuncFmtType = NUMBERFORMAT_NUMBER; @@ -4603,7 +4639,9 @@ void ScInterpreter::ScCountIf() } } break; - case svMatrix : + case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: { ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString); @@ -4648,23 +4686,25 @@ void ScInterpreter::ScCountIf() nTab2 = nTab1; break; case svMatrix: + case svExternalSingleRef: + case svExternalDoubleRef: + { + pQueryMatrix = GetMatrix(); + if (!pQueryMatrix) { - pQueryMatrix = PopMatrix(); - if (!pQueryMatrix) - { - PushIllegalParameter(); - return; - } - nCol1 = 0; - nRow1 = 0; - nTab1 = 0; - SCSIZE nC, nR; - pQueryMatrix->GetDimensions( nC, nR); - nCol2 = static_cast<SCCOL>(nC - 1); - nRow2 = static_cast<SCROW>(nR - 1); - nTab2 = 0; + PushIllegalParameter(); + return; } - break; + nCol1 = 0; + nRow1 = 0; + nTab1 = 0; + SCSIZE nC, nR; + pQueryMatrix->GetDimensions( nC, nR); + nCol2 = static_cast<SCCOL>(nC - 1); + nRow2 = static_cast<SCROW>(nR - 1); + nTab2 = 0; + } + break; default: PushIllegalParameter(); return ; diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 1c7ecdd33c78..bfe5b6b632ac 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -1519,6 +1519,28 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr if (nGlobalError) return; + GetExternalDoubleRef(nFileId, aTabName, aData, rArray); + if (nGlobalError) + return; +} + +void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat) +{ + ScExternalRefCache::TokenArrayRef pArray; + PopExternalDoubleRef(pArray); + if (nGlobalError) + return; + + // For now, we only support single range data for external + // references, which means the array should only contain a + // single matrix token. + ScToken* p = static_cast<ScToken*>(pArray->First()); + rMat = p->GetMatrix(); +} + +void ScInterpreter::GetExternalDoubleRef( + sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray) +{ ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager(); const String* pFile = pRefMgr->getExternalFileName(nFileId); if (!pFile) @@ -1526,18 +1548,19 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr SetError(errNoName); return; } - if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel()) + if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel()) { OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!"); SetError(errNoRef); return; } + ScComplexRefData aData(rData); aData.CalcAbsIfRel(aPos); ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab, aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab); ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens( - nFileId, aTabName, aRange, &aPos); + nFileId, rTabName, aRange, &aPos); if (!pArray) { @@ -1562,20 +1585,6 @@ void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArr rArray = pArray; } -void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat) -{ - ScExternalRefCache::TokenArrayRef pArray; - PopExternalDoubleRef(pArray); - if (nGlobalError) - return; - - // For now, we only support single range data for external - // references, which means the array should only contain a - // single matrix token. - ScToken* p = static_cast<ScToken*>(pArray->First()); - rMat = p->GetMatrix(); -} - sal_Bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr ) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefOrSingleRef" ); @@ -1643,6 +1652,7 @@ bool ScInterpreter::ConvertMatrixParameters() case svDouble: case svString: case svSingleRef: + case svExternalSingleRef: case svMissing: case svError: case svEmptyCell: @@ -1700,6 +1710,35 @@ bool ScInterpreter::ConvertMatrixParameters() } } break; + case svExternalDoubleRef: + { + ScParameterClassification::Type eType = + ScParameterClassification::GetParameterType( pCur, nParams - i); + if (eType == ScParameterClassification::Array) + { + sal_uInt16 nFileId = p->GetIndex(); + const String& rTabName = p->GetString(); + const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef(); + ScExternalRefCache::TokenArrayRef pArray; + GetExternalDoubleRef(nFileId, rTabName, rRef, pArray); + if (nGlobalError) + break; + + ScToken* pTemp = static_cast<ScToken*>(pArray->First()); + if (!pTemp) + break; + + ScMatrixRef pMat = pTemp->GetMatrix(); + if (pMat) + { + ScToken* pNew = new ScMatrixToken( pMat); + pNew->IncRef(); + pStack[ sp - i ] = pNew; + p->DecRef(); // p may be dead now! + } + } + } + break; case svRefList: { ScParameterClassification::Type eType = @@ -2350,13 +2389,9 @@ ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble, ScMatrixRef pMat; StackVar eType = GetStackType(); - if (eType == svExternalDoubleRef) - { - PopExternalDoubleRef(pMat); - } - else if (eType == svMatrix) + if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix) { - pMat = PopMatrix(); + pMat = GetMatrix(); } else { diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 440a9598e59e..df5f43617ae1 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -729,11 +729,10 @@ void ScRangeName::copyLocalNames(const TabNameMap& rNames, TabNameCopyMap& rCopy } } -ScRangeName::ScRangeName() : - mnSharedMaxIndex(0) {} +ScRangeName::ScRangeName() {} ScRangeName::ScRangeName(const ScRangeName& r) : - maData(r.maData), mnSharedMaxIndex(r.mnSharedMaxIndex) {} + maData(r.maData) {} const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const { @@ -806,16 +805,6 @@ void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) itr->UpdateGrow(rArea, nGrowX, nGrowY); } -sal_uInt16 ScRangeName::GetSharedMaxIndex() -{ - return mnSharedMaxIndex; -} - -void ScRangeName::SetSharedMaxIndex(sal_uInt16 nInd) -{ - mnSharedMaxIndex = nInd; -} - ScRangeName::const_iterator ScRangeName::begin() const { return maData.begin(); @@ -886,7 +875,7 @@ void ScRangeName::clear() bool ScRangeName::operator== (const ScRangeName& r) const { - return maData == r.maData && mnSharedMaxIndex == r.mnSharedMaxIndex; + return maData == r.maData; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index c03799aa6ffe..8cb3d6e136e8 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -1533,7 +1533,7 @@ ScNameInputType lcl_GetInputType( const String& rText ) sal_Int32 nNumeric; if ( aRange.Parse( rText, pDoc, eConv ) & SCA_VALID ) - eRet = SC_NAME_INPUT_NAMEDRANGE; + eRet = SC_NAME_INPUT_RANGE; else if ( aAddress.Parse( rText, pDoc, eConv ) & SCA_VALID ) eRet = SC_NAME_INPUT_CELL; else if ( aRangeUtil.MakeRangeFromName( rText, pDoc, nTab, aRange, RUTL_NAMES, eConv ) ) @@ -1697,11 +1697,14 @@ void ScPosWnd::DoEnter() else { // for all selection types, excecute the SID_CURRENTCELL slot. - // Note that SID_CURRENTCELL always expects address to be - // in Calc A1 format. Convert the text. - ScRange aRange; - aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention()); - aRange.Format(aText, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO); + if (eType == SC_NAME_INPUT_CELL || eType == SC_NAME_INPUT_RANGE) + { + // Note that SID_CURRENTCELL always expects address to + // be in Calc A1 format. Convert the text. + ScRange aRange; + aRange.ParseAny(aText, pDoc, pDoc->GetAddressConvention()); + aRange.Format(aText, SCR_ABS_3D, pDoc, ::formula::FormulaGrammar::CONV_OOO); + } SfxStringItem aPosItem( SID_CURRENTCELL, aText ); SfxBoolItem aUnmarkItem( FN_PARAM_1, sal_True ); // remove existing selection diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx index f280af43f7e0..fa063bcf7ab8 100644 --- a/sc/source/ui/dbgui/pvlaydlg.cxx +++ b/sc/source/ui/dbgui/pvlaydlg.cxx @@ -1450,11 +1450,24 @@ void ScDPLayoutDlg::UpdateSrcRange() switch (eSrcType) { case SRC_REF: + { // data source is a range reference. if (inSheet.GetSourceRange() == aNewRange) // new range is identical to the current range. Nothing to do. return; inSheet.SetSourceRange(aNewRange); + sal_uLong nError = inSheet.CheckSourceRange(); + if (nError) + { + // The error number corresponds with string ID for the error + // message. In the future we should display the error message + // somewhere in the dialog to let the user know of the reason + // for error. + aEdInPos.SetRefValid(false); + aBtnOk.Disable(); + return; + } + } break; case SRC_NAME: // data source is a range name. diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 8991706293a1..8fde7e29e57a 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -255,7 +255,7 @@ sal_Bool ScDBDocFunc::ModifyDBData( const ScDBData& rNewData, sal_Bool /* bApi * // ----------------------------------------------------------------- -sal_Bool ScDBDocFunc::RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi ) +sal_Bool ScDBDocFunc::RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi, bool bIsUnnamed, SCTAB aTab ) { //! auch fuer ScDBFunc::RepeatDB benutzen! @@ -263,12 +263,21 @@ sal_Bool ScDBDocFunc::RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Boo ScDocument* pDoc = rDocShell.GetDocument(); if (bRecord && !pDoc->IsUndoEnabled()) bRecord = false; - ScDBCollection* pColl = pDoc->GetDBCollection(); - sal_uInt16 nIndex; - if ( pColl && pColl->SearchName( rDBName, nIndex ) ) + ScDBData* pDBData = NULL; + if (bIsUnnamed) { - ScDBData* pDBData = (*pColl)[nIndex]; + pDBData = pDoc->GetAnonymousDBData( aTab ); + } + else + { + sal_uInt16 nIndex; + ScDBCollection* pColl = pDoc->GetDBCollection(); + if ( pColl && pColl->SearchName( rDBName, nIndex ) ) + pDBData = (*pColl)[nIndex]; + } + if ( pDBData ) + { ScQueryParam aQueryParam; pDBData->GetQueryParam( aQueryParam ); sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery; diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index c9d600f34d9c..62ced922b01f 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -4023,8 +4023,7 @@ sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMar { rDocShell.GetUndoManager()->AddUndoAction( new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, - eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307, - pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); + eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307) ); } rDocShell.PostPaintGridAll(); @@ -4143,8 +4142,7 @@ sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMar { rDocShell.GetUndoManager()->AddUndoAction( new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, - eDir, eCmd, eDateCmd, fStart, fStep, fMax, - pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); + eDir, eCmd, eDateCmd, fStart, fStep, fMax) ); } bSuccess = sal_True; @@ -4271,8 +4269,7 @@ sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark, FillD { rDocShell.GetUndoManager()->AddUndoAction( new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark, - eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax, - pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) ); + eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax) ); } rDocShell.PostPaintGridAll(); diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index f9de3e8c0c48..1bfdc8b5b88f 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -74,6 +74,7 @@ using ::rtl::OUString; using ::std::vector; using ::std::find; using ::std::find_if; +using ::std::remove_if; using ::std::distance; using ::std::pair; using ::std::list; @@ -85,7 +86,7 @@ using namespace formula; namespace { -class TabNameSearchPredicate : public unary_function<bool, ScExternalRefCache::TableName> +class TabNameSearchPredicate : public unary_function<ScExternalRefCache::TableName, bool> { public: explicit TabNameSearchPredicate(const String& rSearchName) : @@ -201,6 +202,56 @@ private: ScDocument* mpDoc; }; +/** + * Check whether a named range contains an external reference to a + * particular document. + */ +bool hasRefsToSrcDoc(ScRangeData& rData, sal_uInt16 nFileId) +{ + ScTokenArray* pArray = rData.GetCode(); + if (!pArray) + return false; + + pArray->Reset(); + ScToken* p = static_cast<ScToken*>(pArray->GetNextReference()); + for (; p; p = static_cast<ScToken*>(pArray->GetNextReference())) + { + if (!p->IsExternalRef()) + continue; + + if (p->GetIndex() == nFileId) + return true; + } + return false; +} + +class EraseRangeByIterator : unary_function<ScRangeName::iterator, void> +{ + ScRangeName& mrRanges; +public: + EraseRangeByIterator(ScRangeName& rRanges) : mrRanges(rRanges) {} + void operator() (const ScRangeName::iterator& itr) + { + mrRanges.erase(itr); + } +}; + +/** + * Remove all named ranges that contain references to specified source + * document. + */ +void removeRangeNamesBySrcDoc(ScRangeName& rRanges, sal_uInt16 nFileId) +{ + ScRangeName::iterator itr = rRanges.begin(), itrEnd = rRanges.end(); + vector<ScRangeName::iterator> v; + for (; itr != itrEnd; ++itr) + { + if (hasRefsToSrcDoc(*itr, nFileId)) + v.push_back(itr); + } + for_each(v.begin(), v.end(), EraseRangeByIterator(rRanges)); +} + } // ============================================================================ @@ -2358,9 +2409,14 @@ void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap) { typename MapContainer::iterator itr = rMap.find(nFileId); if (itr != rMap.end()) + { + // Close this document shell. + itr->second.maShell->DoClose(); rMap.erase(itr); + } } + void ScExternalRefManager::refreshNames(sal_uInt16 nFileId) { maRefCache.clearCache(nFileId); @@ -2389,6 +2445,21 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId) maRefCells.erase(nFileId); } + // Remove all named ranges that reference this document. + + // Global named ranges. + ScRangeName* pRanges = mpDoc->GetRangeName(); + if (pRanges) + removeRangeNamesBySrcDoc(*pRanges, nFileId); + + // Sheet-local named ranges. + for (SCTAB i = 0, n = mpDoc->GetTableCount(); i < n; ++i) + { + pRanges = mpDoc->GetRangeName(i); + if (pRanges) + removeRangeNamesBySrcDoc(*pRanges, nFileId); + } + lcl_removeByFileId(nFileId, maDocShells); if (maDocShells.empty()) @@ -2528,6 +2599,9 @@ void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut) sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime(); if (nSinceLastAccess < nTimeOut) aNewDocShells.insert(*itr); + else + // Timed out. Let's close this. + itr->second.maShell->DoClose(); } maDocShells.swap(aNewDocShells); diff --git a/sc/source/ui/inc/dbdocfun.hxx b/sc/source/ui/inc/dbdocfun.hxx index 132eb9a3750b..11b2ce27ef62 100644 --- a/sc/source/ui/inc/dbdocfun.hxx +++ b/sc/source/ui/inc/dbdocfun.hxx @@ -114,7 +114,7 @@ public: sal_Bool RenameDBRange( const String& rOld, const String& rNew, sal_Bool bApi ); sal_Bool ModifyDBData( const ScDBData& rNewData, sal_Bool bApi ); // Name unveraendert - sal_Bool RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi ); + sal_Bool RepeatDB( const String& rDBName, sal_Bool bRecord, sal_Bool bApi, bool bIsUnnamed=false, SCTAB aTab = 0); sal_Bool DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj, sal_Bool bRecord, sal_Bool bApi, sal_Bool bAllowMove = false ); diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx index d8617490219a..16fc7591ac08 100644 --- a/sc/source/ui/inc/undoblk.hxx +++ b/sc/source/ui/inc/undoblk.hxx @@ -421,8 +421,7 @@ public: ScDocument* pNewUndoDoc, const ScMarkData& rMark, FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd, - double fNewStartValue, double fNewStepValue, double fNewMaxValue, - sal_uInt16 nMaxShIndex ); + double fNewStartValue, double fNewStepValue, double fNewMaxValue ); virtual ~ScUndoAutoFill(); virtual void Undo(); @@ -444,7 +443,6 @@ private: double fMaxValue; sal_uLong nStartChangeAction; sal_uLong nEndChangeAction; - sal_uInt16 nMaxSharedIndex; void SetChangeTrack(); }; diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx index 446e3dede1c6..45ea822f2090 100644 --- a/sc/source/ui/undo/undoblk3.cxx +++ b/sc/source/ui/undo/undoblk3.cxx @@ -602,8 +602,7 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell, const ScRange& rRange, const ScRange& rSourceArea, ScDocument* pNewUndoDoc, const ScMarkData& rMark, FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd, - double fNewStartValue, double fNewStepValue, double fNewMaxValue, - sal_uInt16 nMaxShIndex ) + double fNewStartValue, double fNewStepValue, double fNewMaxValue ) // : ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ), // @@ -615,8 +614,7 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell, eFillDateCmd ( eNewFillDateCmd ), fStartValue ( fNewStartValue ), fStepValue ( fNewStepValue ), - fMaxValue ( fNewMaxValue ), - nMaxSharedIndex ( nMaxShIndex) + fMaxValue ( fNewMaxValue ) { SetChangeTrack(); } @@ -626,7 +624,6 @@ ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell, ScUndoAutoFill::~ScUndoAutoFill() { - pDocShell->GetDocument()->EraseNonUsedSharedNames(nMaxSharedIndex); delete pUndoDoc; } @@ -649,26 +646,6 @@ void ScUndoAutoFill::SetChangeTrack() nStartChangeAction = nEndChangeAction = 0; } -namespace { - -bool eraseNameContaining(ScRangeName& rNames, const rtl::OUString& rCriteria) -{ - ScRangeName::iterator itr = rNames.begin(), itrEnd = rNames.end(); - for (; itr != itrEnd; ++itr) - { - rtl::OUString aRName = itr->GetName(); - if (aRName.indexOf(rCriteria) >= 0) - { - // Criteria found. Erase this. - rNames.erase(itr); - return true; - } - } - return false; -} - -} - void ScUndoAutoFill::Undo() { BeginUndo(); @@ -698,29 +675,6 @@ void ScUndoAutoFill::Undo() if (pViewShell) pViewShell->CellContentChanged(); -// Shared-Names loeschen -// Falls Undo ins Dokument gespeichert -// => automatisches Loeschen am Ende -// umarbeiten!! - - String aName = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("___SC_")); - aName += String::CreateFromInt32(nMaxSharedIndex); - aName += '_'; - ScRangeName* pRangeName = pDoc->GetRangeName(); - bool bHasFound = false; - // Remove all range names that contain ___SC_... - while (true) - { - bool bErased = eraseNameContaining(*pRangeName, aName); - if (bErased) - bHasFound = true; - else - break; - } - - if (bHasFound) - pRangeName->SetSharedMaxIndex(pRangeName->GetSharedMaxIndex()-1); - ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack(); if ( pChangeTrack ) pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx index f5f2ab6071d0..a1ee63dc8b26 100644 --- a/sc/source/ui/unoobj/datauno.cxx +++ b/sc/source/ui/unoobj/datauno.cxx @@ -57,6 +57,7 @@ #include "docsh.hxx" #include "dbdocfun.hxx" #include "unonames.hxx" +#include "globalnames.hxx" #include "globstr.hrc" #include "convuno.hxx" #include "hints.hxx" @@ -1607,7 +1608,18 @@ void ScDataPilotFilterDescriptor::PutData( const ScQueryParam& rParam ) ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, const String& rNm) : pDocShell( pDocSh ), aName( rNm ), - aPropSet( lcl_GetDBRangePropertyMap() ) + aPropSet( lcl_GetDBRangePropertyMap() ), + bIsUnnamed(false) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, const SCTAB nTab) : + pDocShell( pDocSh ), + aName(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)), + aPropSet( lcl_GetDBRangePropertyMap() ), + bIsUnnamed(true), + aTab( nTab ) { pDocShell->GetDocument()->AddUnoObject(*this); } @@ -1641,12 +1653,19 @@ ScDBData* ScDatabaseRangeObj::GetDBData_Impl() const ScDBData* pRet = NULL; if (pDocShell) { - ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); - if (pNames) + if (bIsUnnamed) { - sal_uInt16 nPos = 0; - if (pNames->SearchName( aName, nPos )) - pRet = (*pNames)[nPos]; + pRet = pDocShell->GetDocument()->GetAnonymousDBData(aTab); + } + else + { + ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); + if (pNames) + { + sal_uInt16 nPos = 0; + if (pNames->SearchName( aName, nPos )) + pRet = (*pNames)[nPos]; + } } } return pRet; @@ -1889,7 +1908,7 @@ void SAL_CALL ScDatabaseRangeObj::refresh() throw(uno::RuntimeException) // interne Operationen (sort, query, subtotal) nur, wenn kein Fehler if (bContinue) - aFunc.RepeatDB( pData->GetName(), sal_True, sal_True ); + aFunc.RepeatDB( pData->GetName(), true, true, bIsUnnamed, aTab ); } } @@ -2079,7 +2098,7 @@ uno::Any SAL_CALL ScDatabaseRangeObj::getPropertyValue( const rtl::OUString& aPr { // all database ranges except "unnamed" are user defined ScUnoHelpFunctions::SetBoolInAny( aRet, - ( pData->GetName() != ScGlobal::GetRscString(STR_DB_NONAME) ) ); + ( pData->GetName() != String(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)) ) ); } else if ( aString.EqualsAscii( SC_UNO_LINKDISPBIT ) ) { @@ -2354,8 +2373,90 @@ sal_Bool SAL_CALL ScDatabaseRangesObj::hasByName( const rtl::OUString& aName ) //------------------------------------------------------------------------ +ScUnnamedDatabaseRangesObj::ScUnnamedDatabaseRangesObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScUnnamedDatabaseRangesObj::~ScUnnamedDatabaseRangesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScUnnamedDatabaseRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XUnnamedDatabaseRanges + +void ScUnnamedDatabaseRangesObj::setByTable( const table::CellRangeAddress& aRange ) + throw( uno::RuntimeException, + lang::IndexOutOfBoundsException ) +{ + SolarMutexGuard aGuard; + bool bDone = false; + if (pDocShell) + { + if ( pDocShell->GetDocument()->GetTableCount() <= aRange.Sheet ) + throw lang::IndexOutOfBoundsException(); + ScDBDocFunc aFunc(*pDocShell); + String aString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)); + ScRange aUnnamedRange( (SCCOL)aRange.StartColumn, (SCROW)aRange.StartRow, aRange.Sheet, + (SCCOL)aRange.EndColumn, (SCROW)aRange.EndRow, aRange.Sheet ); + bDone = aFunc.AddDBRange( aString, aUnnamedRange, sal_True ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} +uno::Any ScUnnamedDatabaseRangesObj::getByTable( const sal_Int32 nTab ) + throw(uno::RuntimeException, + lang::IndexOutOfBoundsException, + container::NoSuchElementException) +{ + SolarMutexGuard aGuard; + if (pDocShell) + { + if ( pDocShell->GetDocument()->GetTableCount() <= nTab ) + throw lang::IndexOutOfBoundsException(); + uno::Reference<sheet::XDatabaseRange> xRange( new ScDatabaseRangeObj(pDocShell, (SCTAB) nTab) ); + if (xRange.is()) + return uno::makeAny(xRange); + else + throw container::NoSuchElementException(); + } + else + throw uno::RuntimeException(); +} + +sal_Bool ScUnnamedDatabaseRangesObj::hasByTable( sal_Int32 nTab ) + throw (uno::RuntimeException, + lang::IndexOutOfBoundsException) +{ + SolarMutexGuard aGuard; + if (pDocShell) + { + if (pDocShell->GetDocument()->GetTableCount() <= nTab) + throw lang::IndexOutOfBoundsException(); + if (pDocShell->GetDocument()->GetAnonymousDBData((SCTAB) nTab)) + return true; + return false; + } + else + return false; +} + +//------------------------------------------------------------------------ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index e84f6756757e..15673f35c0b8 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -56,6 +56,7 @@ #include <com/sun/star/util/Date.hpp> #include <com/sun/star/sheet/XNamedRanges.hpp> #include <com/sun/star/sheet/XLabelRanges.hpp> +#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp> #include <com/sun/star/i18n/XForbiddenCharacters.hpp> #include <com/sun/star/script/XLibraryContainer.hpp> #include <com/sun/star/lang/XInitialization.hpp> @@ -1780,6 +1781,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa { aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell )); } + else if ( aString.EqualsAscii( SC_UNO_UNNAMEDDBRNG ) ) + { + aRet <<= uno::Reference<sheet::XUnnamedDatabaseRanges>(new ScUnnamedDatabaseRangesObj(pDocShell)); + } else if ( aString.EqualsAscii( SC_UNO_COLLABELRNG ) ) { aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, sal_True )); diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx index d98f1ac7ee1e..cbf30eba603d 100644 --- a/sc/source/ui/vba/excelvbahelper.cxx +++ b/sc/source/ui/vba/excelvbahelper.cxx @@ -66,36 +66,33 @@ GetDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException ) return xDBRanges; } +uno::Reference< sheet::XUnnamedDatabaseRanges > +GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( uno::RuntimeException ) +{ + uno::Reference< frame::XModel > xModel; + if ( pShell ) + xModel.set( pShell->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xModelProps( xModel, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( xModelProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UnnamedDatabaseRanges") ) ), uno::UNO_QUERY_THROW ); + return xUnnamedDBRanges; +} + // returns the XDatabaseRange for the autofilter on sheet (nSheet) // also populates sName with the name of range uno::Reference< sheet::XDatabaseRange > -GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet, rtl::OUString& sName ) throw ( uno::RuntimeException ) +GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( uno::RuntimeException ) { - uno::Reference< container::XIndexAccess > xIndexAccess( GetDataBaseRanges( pShell ), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XUnnamedDatabaseRanges > xUnnamedDBRanges( GetUnnamedDataBaseRanges( pShell ), uno::UNO_QUERY_THROW ); uno::Reference< sheet::XDatabaseRange > xDataBaseRange; - table::CellRangeAddress dbAddress; - for ( sal_Int32 index=0; index < xIndexAccess->getCount(); ++index ) + if (xUnnamedDBRanges->hasByTable( nSheet ) ) { - uno::Reference< sheet::XDatabaseRange > xDBRange( xIndexAccess->getByIndex( index ), uno::UNO_QUERY_THROW ); - uno::Reference< container::XNamed > xNamed( xDBRange, uno::UNO_QUERY_THROW ); - // autofilters work weirdly with openoffice, unnamed is the default - // named range which is used to create an autofilter, but - // its also possible that another name could be used - // this also causes problems when an autofilter is created on - // another sheet - // ( but.. you can use any named range ) - dbAddress = xDBRange->getDataArea(); - if ( dbAddress.Sheet == nSheet ) + uno::Reference< sheet::XDatabaseRange > xDBRange( xUnnamedDBRanges->getByTable( nSheet ) , uno::UNO_QUERY_THROW ); + sal_Bool bHasAuto = false; + uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW ); + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ) ) >>= bHasAuto; + if ( bHasAuto ) { - sal_Bool bHasAuto = false; - uno::Reference< beans::XPropertySet > xProps( xDBRange, uno::UNO_QUERY_THROW ); - xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ) ) >>= bHasAuto; - if ( bHasAuto ) - { - sName = xNamed->getName(); - xDataBaseRange=xDBRange; - break; - } + xDataBaseRange=xDBRange; } } return xDataBaseRange; diff --git a/sc/source/ui/vba/excelvbahelper.hxx b/sc/source/ui/vba/excelvbahelper.hxx index 9befc1548357..1cc0546a4fd7 100644 --- a/sc/source/ui/vba/excelvbahelper.hxx +++ b/sc/source/ui/vba/excelvbahelper.hxx @@ -32,6 +32,7 @@ #include "docsh.hxx" #include <com/sun/star/sheet/XDatabaseRanges.hpp> #include <com/sun/star/sheet/XDatabaseRange.hpp> +#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp> #include <com/sun/star/table/XCellRange.hpp> #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp> #include <com/sun/star/sheet/XSpreadsheet.hpp> @@ -65,8 +66,9 @@ formula::FormulaGrammar::Grammar GetFormulaGrammar( ScDocument* pDoc, const ScAd void CompileExcelFormulaToODF( ScDocument* pDoc, const String& rOldFormula, String& rNewFormula ); void CompileODFFormulaToExcel( ScDocument* pDoc, const String& rOldFormula, String& rNewFormula, const formula::FormulaGrammar::Grammar eGrammar ); css::uno::Reference< css::sheet::XDatabaseRanges > GetDataBaseRanges( ScDocShell* pShell ) throw ( css::uno::RuntimeException ); +css::uno::Reference< css::sheet::XUnnamedDatabaseRanges > GetUnnamedDataBaseRanges( ScDocShell* pShell ) throw ( css::uno::RuntimeException ); -css::uno::Reference< css::sheet::XDatabaseRange > GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet, rtl::OUString& sName ) throw ( css::uno::RuntimeException ); +css::uno::Reference< css::sheet::XDatabaseRange > GetAutoFiltRange( ScDocShell* pShell, sal_Int16 nSheet ) throw ( css::uno::RuntimeException ); css::uno::Reference< ooo::vba::XHelperInterface > getUnoSheetModuleObj( const css::uno::Reference< css::sheet::XSpreadsheet >& xSheet ) throw ( css::uno::RuntimeException ); css::uno::Reference< ooo::vba::XHelperInterface > getUnoSheetModuleObj( const css::uno::Reference< css::sheet::XSheetCellRangeContainer >& xRanges ) throw ( css::uno::RuntimeException ); css::uno::Reference< ooo::vba::XHelperInterface > getUnoSheetModuleObj( const css::uno::Reference< css::table::XCellRange >& xRange ) throw ( css::uno::RuntimeException ); diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index df750a774ad4..9c199423abd0 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -39,6 +39,7 @@ #include <com/sun/star/script/vba/XVBAEventProcessor.hpp> #include <com/sun/star/sheet/XDatabaseRange.hpp> #include <com/sun/star/sheet/XDatabaseRanges.hpp> +#include <com/sun/star/sheet/XUnnamedDatabaseRanges.hpp> #include <com/sun/star/sheet/XGoalSeek.hpp> #include <com/sun/star/sheet/XSheetOperation.hpp> #include <com/sun/star/sheet/CellFlags.hpp> @@ -4334,20 +4335,10 @@ ScVbaRange::ApplicationRange( const uno::Reference< uno::XComponentContext >& xC // Helper functions for AutoFilter ScDBData* lcl_GetDBData_Impl( ScDocShell* pDocShell, sal_Int16 nSheet ) { - rtl::OUString sName; - excel::GetAutoFiltRange( pDocShell, nSheet, sName ); - OSL_TRACE("lcl_GetDBData_Impl got autofilter range %s for sheet %d", - rtl::OUStringToOString( sName, RTL_TEXTENCODING_UTF8 ).getStr() , nSheet ); ScDBData* pRet = NULL; if (pDocShell) { - ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); - if (pNames) - { - sal_uInt16 nPos = 0; - if (pNames->SearchName( sName , nPos )) - pRet = (*pNames)[nPos]; - } + pRet = pDocShell->GetDocument()->GetAnonymousDBData(nSheet); } return pRet; } @@ -4501,8 +4492,7 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const sal_Int16 nSheet = thisAddress.Sheet; ScDocShell* pShell = getScDocShell(); sal_Bool bHasAuto = false; - rtl::OUString sAutofiltRangeName; - uno::Reference< sheet::XDatabaseRange > xDataBaseRange = excel::GetAutoFiltRange( pShell, nSheet, sAutofiltRangeName ); + uno::Reference< sheet::XDatabaseRange > xDataBaseRange = excel::GetAutoFiltRange( pShell, nSheet ); if ( xDataBaseRange.is() ) bHasAuto = true; @@ -4549,16 +4539,13 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const } } - uno::Reference< sheet::XDatabaseRanges > xDBRanges = excel::GetDataBaseRanges( pShell ); + uno::Reference< sheet::XUnnamedDatabaseRanges > xDBRanges = excel::GetUnnamedDataBaseRanges( pShell ); if ( xDBRanges.is() ) { - rtl::OUString sGenName( RTL_CONSTASCII_USTRINGPARAM("VBA_Autofilter_") ); - sGenName += rtl::OUString::valueOf( static_cast< sal_Int32 >( nSheet ) ); - OSL_TRACE("Going to add new autofilter range.. name %s", - rtl::OUStringToOString( sGenName, RTL_TEXTENCODING_UTF8 ).getStr() , nSheet ); - if ( !xDBRanges->hasByName( sGenName ) ) - xDBRanges->addNewByName( sGenName, autoFiltAddress ); - xDataBaseRange.set( xDBRanges->getByName( sGenName ), uno::UNO_QUERY_THROW ); + OSL_TRACE("Going to add new autofilter range.. sheet %i", nSheet ); + if ( !xDBRanges->hasByTable( nSheet ) ) + xDBRanges->setByTable( autoFiltAddress ); + xDataBaseRange.set( xDBRanges->getByTable(nSheet ), uno::UNO_QUERY_THROW ); } if ( !xDataBaseRange.is() ) throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Failed to find the autofilter placeholder range" ) ), uno::Reference< uno::XInterface >() ); diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 2918410d0923..cc85ef7b7137 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -97,10 +97,13 @@ static void lcl_PostRepaintCondFormat( const ScConditionalFormat *pCondFmt, ScDo { if( pCondFmt ) { - const ScRangeListRef& aRanges = pCondFmt->GetRangeInfo(); - size_t nCount = aRanges->size(); + const ScRangeListRef& xRanges = pCondFmt->GetRangeInfo(); + if (!xRanges) + return; + + size_t nCount = xRanges->size(); for( size_t n = 0 ; n < nCount; n++ ) - pDocSh->PostPaint( *((*aRanges)[n]), PAINT_ALL ); + pDocSh->PostPaint( *((*xRanges)[n]), PAINT_ALL ); } } |