diff options
Diffstat (limited to 'sc')
38 files changed, 1182 insertions, 805 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 59d6617ae470..62c0ac0eb9a8 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -131,7 +131,6 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/core/data/pivot2 \ sc/source/core/data/poolhelp \ sc/source/core/data/postit \ - sc/source/core/data/scdpoutputimpl \ sc/source/core/data/segmenttree \ sc/source/core/data/sheetevents \ sc/source/core/data/sortparam \ diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 901bc3615ac2..19496d0f3f15 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -528,8 +528,8 @@ public: SC_DLLPUBLIC sal_Bool SetCodeName( SCTAB nTab, const String& rName ); SC_DLLPUBLIC sal_Bool GetTable( const String& rName, SCTAB& rTab ) const; - void SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData); - ScDBData* GetAnonymousDBData(SCTAB nTab); + SC_DLLPUBLIC void SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData); + SC_DLLPUBLIC ScDBData* GetAnonymousDBData(SCTAB nTab); SC_DLLPUBLIC inline SCTAB GetTableCount() const { return nMaxTableNumber; } SvNumberFormatterIndexTable* GetFormatExchangeList() const { return pFormatExchangeList; } @@ -1238,7 +1238,7 @@ public: SC_DLLPUBLIC sal_Bool ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ); - sal_Bool RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow, + SC_DLLPUBLIC sal_Bool RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags ); diff --git a/sc/inc/dpcachetable.hxx b/sc/inc/dpcachetable.hxx index 73b3d5e12727..9c6353d0b51a 100644 --- a/sc/inc/dpcachetable.hxx +++ b/sc/inc/dpcachetable.hxx @@ -58,6 +58,13 @@ struct ScQueryParam; class SC_DLLPUBLIC ScDPCacheTable { + struct RowFlag + { + bool mbShowByFilter:1; + bool mbShowByPage:1; + bool isActive() const; + RowFlag(); + }; public: /** individual filter item used in SingleFilter and GroupFilter. */ struct FilterItem @@ -121,7 +128,7 @@ public: Criterion(); }; - ScDPCacheTable(ScDPCache* pCache); + ScDPCacheTable(const ScDPCache* pCache); ~ScDPCacheTable(); sal_Int32 getRowSize() const; @@ -169,15 +176,13 @@ public: SCROW getOrder(long nDim, SCROW nIndex) const; void clear(); bool empty() const; - void setCache(ScDPCache* p); + void setCache(const ScDPCache* p); bool hasCache() const; private: ScDPCacheTable(); ScDPCacheTable(const ScDPCacheTable&); - ScDPCache* getCache(); - /** * Check if a given row meets all specified criteria. * @@ -190,11 +195,10 @@ private: /** unique field entires for each field (column). */ ::std::vector< ::std::vector<SCROW> > maFieldEntries; - /** used to track visibility of rows. The first row below the header row - has the index of 0. */ - ::std::vector<bool> maRowsVisible; + /** Row flags. The first row below the header row has the index of 0. */ + ::std::vector<RowFlag> maRowFlags; - ScDPCache* mpCache; + const ScDPCache* mpCache; }; #endif diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 59230d833491..30ca8406d11e 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -39,6 +39,7 @@ #include <boost/ptr_container/ptr_list.hpp> #include <boost/ptr_container/ptr_vector.hpp> +#include <boost/ptr_container/ptr_map.hpp> #include <boost/shared_ptr.hpp> namespace com { namespace sun { namespace star { namespace sheet { @@ -117,7 +118,6 @@ private: SC_DLLPRIVATE void CreateObjects(); SC_DLLPRIVATE void CreateOutput(); sal_Bool bRefresh; - long mnCacheId; public: ScDPObject(ScDocument* pD); @@ -257,13 +257,62 @@ public: class ScDPCollection { -private: - typedef ::boost::ptr_vector<ScDPObject> TablesType; +public: - ScDocument* pDoc; - TablesType maTables; + /** + * Stores and manages all caches from internal sheets. + */ + class SheetCaches + { + typedef ::boost::ptr_map<ScRange, ScDPCache> CachesType; + CachesType maCaches; + ScDocument* mpDoc; + public: + SheetCaches(ScDocument* pDoc); + const ScDPCache* getCache(const ScRange& rRange); + void removeCache(const ScRange& rRange); + }; + + /** + * Data caches for range name based source data. + */ + class NameCaches + { + typedef ::boost::ptr_map<rtl::OUString, ScDPCache> CachesType; + CachesType maCaches; + ScDocument* mpDoc; + public: + NameCaches(ScDocument* pDoc); + const ScDPCache* getCache(const ::rtl::OUString& rName, const ScRange& rRange); + void removeCache(const ::rtl::OUString& rName); + }; + + /** + * Defines connection type to external data source. Used as a key to look + * up database cache. + */ + struct DBType + { + sal_Int32 mnSdbType; + ::rtl::OUString maDBName; + ::rtl::OUString maCommand; + DBType(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + }; + + /** + * Data caches for external database sources. + */ + class DBCaches + { + typedef ::boost::ptr_map<DBType, ScDPCache> CachesType; + CachesType maCaches; + ScDocument* mpDoc; + public: + DBCaches(ScDocument* pDoc); + const ScDPCache* getCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + void removeCache(sal_Int32 nSdbType, const ::rtl::OUString& rDBName, const ::rtl::OUString& rCommand); + }; -public: ScDPCollection(ScDocument* pDocument); ScDPCollection(const ScDPCollection& r); ~ScDPCollection(); @@ -296,8 +345,22 @@ public: SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj); bool HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const; + + SheetCaches& GetSheetCaches(); + NameCaches& GetNameCaches(); + DBCaches& GetDBCaches(); + +private: + typedef ::boost::ptr_vector<ScDPObject> TablesType; + + ScDocument* pDoc; + TablesType maTables; + SheetCaches maSheetCaches; + NameCaches maNameCaches; + DBCaches maDBCaches; }; +bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right); #endif diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx index 99ca1ed82754..d1d07e2c42cb 100644 --- a/sc/inc/dpoutput.hxx +++ b/sc/inc/dpoutput.hxx @@ -81,7 +81,7 @@ private: com::sun::star::uno::Reference< com::sun::star::sheet::XDimensionsSupplier> xSource; ScAddress aStartPos; - sal_Bool bDoFilter; + bool bDoFilter; ScDPOutLevelData* pColFields; ScDPOutLevelData* pRowFields; ScDPOutLevelData* pPageFields; @@ -91,7 +91,7 @@ private: com::sun::star::uno::Sequence< com::sun::star::uno::Sequence< com::sun::star::sheet::DataResult> > aData; - sal_Bool bResultsError; + bool bResultsError; bool mbHasDataLayout; String aDataDescription; @@ -103,8 +103,8 @@ private: sal_uInt32 nSingleNumFmt; // Output geometry related parameters - sal_Bool bSizesValid; - sal_Bool bSizeOverflow; + bool bSizesValid; + bool bSizeOverflow; long nColCount; long nRowCount; long nHeaderSize; @@ -136,7 +136,7 @@ public: ScDPOutput( ScDocument* pD, const com::sun::star::uno::Reference< com::sun::star::sheet::XDimensionsSupplier>& xSrc, - const ScAddress& rPos, sal_Bool bFilter ); + const ScAddress& rPos, bool bFilter ); ~ScDPOutput(); void SetPosition( const ScAddress& rPos ); diff --git a/sc/inc/dpsdbtab.hxx b/sc/inc/dpsdbtab.hxx index b86d0869e404..87c3ccd1ec5c 100644 --- a/sc/inc/dpsdbtab.hxx +++ b/sc/inc/dpsdbtab.hxx @@ -41,8 +41,8 @@ class ScDocument; struct ScImportSourceDesc { - String aDBName; - String aObject; + ::rtl::OUString aDBName; + ::rtl::OUString aObject; sal_uInt16 nType; // enum DataImportMode bool bNative; ScDocument* mpDoc; @@ -56,7 +56,8 @@ struct ScImportSourceDesc bNative == rOther.bNative && mpDoc == rOther.mpDoc; } - ScDPCache* CreateCache() const; + sal_Int32 GetCommandType() const; + const ScDPCache* CreateCache() const; }; /** diff --git a/sc/inc/dpshttab.hxx b/sc/inc/dpshttab.hxx index 9215ef107dfb..505a2758ae78 100644 --- a/sc/inc/dpshttab.hxx +++ b/sc/inc/dpshttab.hxx @@ -78,7 +78,7 @@ public: const ScQueryParam& GetQueryParam() const; bool operator== ( const ScSheetSourceDesc& rOther ) const; - SC_DLLPUBLIC ScDPCache* CreateCache() const; + SC_DLLPUBLIC const ScDPCache* CreateCache() const; /** * Check the sanity of the data source range. @@ -111,7 +111,7 @@ private: ScDPCacheTable aCacheTable; public: - ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, ScDPCache* pCache); + ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache); virtual ~ScSheetDPData(); virtual long GetColumnCount(); diff --git a/sc/inc/dptabdat.hxx b/sc/inc/dptabdat.hxx index 7b3dde760246..31d32fe25706 100644 --- a/sc/inc/dptabdat.hxx +++ b/sc/inc/dptabdat.hxx @@ -39,6 +39,7 @@ #include <set> #include <boost/unordered_set.hpp> #include <boost/unordered_map.hpp> +#include <boost/noncopyable.hpp> namespace com { namespace sun { namespace star { namespace sheet { struct DataPilotFieldFilter; @@ -91,7 +92,7 @@ class ScDocument; * Base class that abstracts different data source types of a datapilot * table. */ -class SC_DLLPUBLIC ScDPTableData +class SC_DLLPUBLIC ScDPTableData : public ::boost::noncopyable { // cached data for GetDatePart long nLastDateVal; diff --git a/sc/inc/dptablecache.hxx b/sc/inc/dptablecache.hxx index c1ee4238193c..4bfb14dad727 100644 --- a/sc/inc/dptablecache.hxx +++ b/sc/inc/dptablecache.hxx @@ -48,7 +48,6 @@ struct ScQueryParam; */ class SC_DLLPUBLIC ScDPCache { - friend class ScDPCacheTable; public: typedef ::boost::ptr_vector<ScDPItemData> DataListType; private: @@ -58,20 +57,41 @@ private: ScDocument* mpDoc; long mnColumnCount; - DataGridType maTableDataValues; // Data Pilot Table's index - value map - RowGridType maSourceData; // Data Pilot Table's source data - RowGridType maGlobalOrder; // Sorted members index - mutable RowGridType maIndexOrder; // Index the sorted numbers - DataListType maLabelNames; // Source label data - std::vector<bool> mbEmptyRow; //If empty row? + /** + * This container stores only the unique instances of item data in each + * column. Duplicates are not allowed. + */ + DataGridType maTableDataValues; + + /** + * This container stores indices within maTableDataValues pointing to the + * data. The order of data are exactly as they appear in the original + * data source. + */ + RowGridType maSourceData; + + /** + * This container stores indices within maTableDataValues. The order of + * indices in each column represents ascending order of the actual data. + */ + RowGridType maGlobalOrder; + + /** + * This container stores the ranks of each unique data represented by + * their index. + */ + mutable RowGridType maIndexOrder; + + DataListType maLabelNames; // Stores dimension names. + std::vector<bool> mbEmptyRow; // Keeps track of empty rows. mutable ScDPItemDataPool maAdditionalData; public: - SCROW GetIdByItemData( long nDim, String sItemData ) const; + SCROW GetIdByItemData( long nDim, const String& sItemData ) const; SCROW GetIdByItemData( long nDim, const ScDPItemData& rData ) const; - SCROW GetAdditionalItemID ( String sItemData ) const; + SCROW GetAdditionalItemID ( const String& sItemData ) const; SCROW GetAdditionalItemID( const ScDPItemData& rData ) const; SCCOL GetDimensionIndex( String sName) const; @@ -81,6 +101,7 @@ public: bool IsDateDimension( long nDim ) const ; sal_uLong GetDimNumType( SCCOL nDim) const; SCROW GetDimMemberCount( SCCOL nDim ) const; + SCROW GetOrder( long nDim, SCROW nIndex ) const; SCROW GetSortedItemDataId( SCCOL nDim, SCROW nOrder ) const; const DataListType& GetDimMemberValues( SCCOL nDim ) const; @@ -93,7 +114,7 @@ public: bool IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const; bool IsRowEmpty( SCROW nRow ) const; bool IsValid() const; - bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, bool* pSpecial ); + bool ValidQuery( SCROW nRow, const ScQueryParam& rQueryParam, bool* pSpecial ) const; ScDocument* GetDoc() const;//ms-cache-core long GetColumnCount() const; @@ -103,12 +124,11 @@ public: bool operator== ( const ScDPCache& r ) const; ScDPCache(ScDocument* pDoc); - virtual ~ScDPCache(); + ~ScDPCache(); private: - SCROW GetOrder( long nDim, SCROW nIndex ) const; void AddLabel( ScDPItemData* pData); - bool AddData( long nDim, ScDPItemData* itemData ); + bool AddData(long nDim, ScDPItemData* pData); }; #endif diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 531528436ae5..35558d1a75a3 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -231,6 +231,7 @@ public: void testCSV(); void testMatrix(); void testDataPilot(); + void testDataPilotFilters(); void testSheetCopy(); void testExternalRef(); void testDataArea(); @@ -270,6 +271,7 @@ public: CPPUNIT_TEST(testCSV); CPPUNIT_TEST(testMatrix); CPPUNIT_TEST(testDataPilot); + CPPUNIT_TEST(testDataPilotFilters); CPPUNIT_TEST(testSheetCopy); CPPUNIT_TEST(testExternalRef); CPPUNIT_TEST(testDataArea); @@ -302,6 +304,28 @@ 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")); @@ -669,89 +693,66 @@ void Test::testMatrix() } } -void Test::testDataPilot() -{ - m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data"))); - m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table"))); - - // Dimension definition - struct { - const char* pName; sheet::DataPilotFieldOrientation eOrient; - } aFields[] = { - { "Name", sheet::DataPilotFieldOrientation_ROW }, - { "Group", sheet::DataPilotFieldOrientation_COLUMN }, - { "Score", sheet::DataPilotFieldOrientation_DATA } - }; - - // Raw data - struct { - const char* pName; const char* pGroup; int nScore; - } aData[] = { - { "Andy", "A", 30 }, - { "Bruce", "A", 20 }, - { "Charlie", "B", 45 }, - { "David", "B", 12 }, - { "Edward", "C", 8 }, - { "Frank", "C", 15 }, - }; - - // Expected output table content. 0 = empty cell - const char* aOutputCheck[][5] = { - { "Sum - Score", "Group", 0, 0, 0 }, - { "Name", "A", "B", "C", "Total Result" }, - { "Andy", "30", 0, 0, "30" }, - { "Bruce", "20", 0, 0, "20" }, - { "Charlie", 0, "45", 0, "45" }, - { "David", 0, "12", 0, "12" }, - { "Edward", 0, 0, "8", "8" }, - { "Frank", 0, 0, "15", "15" }, - { "Total Result", "50", "57", "23", "130" } - }; - - sal_uInt32 nFieldCount = SAL_N_ELEMENTS(aFields); - sal_uInt32 nDataCount = SAL_N_ELEMENTS(aData); - - // Insert field names in row 0. - for (sal_uInt32 i = 0; i < nFieldCount; ++i) - m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8)); - - // Insert data into row 1 and downward. - for (sal_uInt32 i = 0; i < nDataCount; ++i) - { - SCROW nRow = static_cast<SCROW>(i) + 1; - m_pDoc->SetString(0, nRow, 0, OUString(aData[i].pName, strlen(aData[i].pName), RTL_TEXTENCODING_UTF8)); - m_pDoc->SetString(1, nRow, 0, OUString(aData[i].pGroup, strlen(aData[i].pGroup), RTL_TEXTENCODING_UTF8)); - m_pDoc->SetValue(2, nRow, 0, aData[i].nScore); - } - - SCROW nRow1 = 0, nRow2 = 0; - SCCOL nCol1 = 0, nCol2 = 0; - m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false); - CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0); - CPPUNIT_ASSERT_MESSAGE("Unexpected data range.", - nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount)); +namespace { - SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1); - for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) +template<int _Size> +bool checkDPTableOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* aOutputCheck[][_Size], const char* pCaption) +{ + const ScAddress& s = aOutRange.aStart; + const ScAddress& e = aOutRange.aEnd; + SheetPrinter printer(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1); + SCROW nOutRowSize = e.Row() - s.Row() + 1; + SCCOL nOutColSize = e.Col() - s.Col() + 1; + for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow) { - for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol) { - String aVal; - m_pDoc->GetString(nCol, nRow, 0, aVal); + OUString aVal; + pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal); printer.set(nRow, nCol, aVal); + const char* p = aOutputCheck[nRow][nCol]; + if (p) + { + OUString aCheckVal = OUString::createFromAscii(p); + bool bEqual = aCheckVal.equals(aVal); + if (!bEqual) + { + cerr << "Expected: " << aCheckVal << " Actual: " << aVal << endl; + return false; + } + } + else if (!aVal.isEmpty()) + { + cerr << "Empty cell expected" << endl; + return false; + } } } - printer.print("Data sheet content"); - printer.clear(); + printer.print(pCaption); + return true; +} + +struct DPFieldDef +{ + const char* pName; + sheet::DataPilotFieldOrientation eOrient; +}; - ScSheetSourceDesc aSheetDesc(m_pDoc); - aSheetDesc.SetSourceRange(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0)); - ScDPObject* pDPObj = new ScDPObject(m_pDoc); +ScDPObject* createDPFromRange( + ScDocument* pDoc, const ScRange& rRange, DPFieldDef aFields[], size_t nFieldCount, + bool bFilterButton) +{ + SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row(); + SCCOL nCol1 = rRange.aStart.Col(); + + ScSheetSourceDesc aSheetDesc(pDoc); + aSheetDesc.SetSourceRange(rRange); + ScDPObject* pDPObj = new ScDPObject(pDoc); pDPObj->SetSheetDesc(aSheetDesc); pDPObj->SetOutRange(ScAddress(0, 0, 1)); ScPivotParam aParam; pDPObj->FillOldParam(aParam); - for (sal_uInt32 i = 0; i < nFieldCount; ++i) + for (size_t i = 0; i < nFieldCount; ++i) { vector<ScDPLabelData::Member> aMembers; pDPObj->GetMembers(i, 0, aMembers); @@ -763,7 +764,7 @@ void Test::testDataPilot() aSaveData.SetRepeatIfEmpty(false); aSaveData.SetColumnGrand(true); aSaveData.SetRowGrand(true); - aSaveData.SetFilterButton(false); + aSaveData.SetFilterButton(bFilterButton); aSaveData.SetDrillDown(true); // Check the sanity of the source range. @@ -774,7 +775,7 @@ void Test::testDataPilot() CPPUNIT_ASSERT_MESSAGE("source range contains no data!", nRow2 - nRow1 > 1); // Set the dimension information. - for (sal_uInt32 i = 0; i < nFieldCount; ++i) + for (size_t i = 0; i < nFieldCount; ++i) { OUString aDimName(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8); ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(aDimName); @@ -812,7 +813,7 @@ void Test::testDataPilot() { SCCOL nCol = nCol1 + static_cast<SCCOL>(i); String aVal; - m_pDoc->GetString(nCol, nRow, 0, aVal); + pDoc->GetString(nCol, nRow, 0, aVal); // This call is just to populate the member list for each dimension. ScDPSaveMember* pMem = pDim->GetMemberByName(aVal); pMem->SetShowDetails(true); @@ -827,12 +828,81 @@ void Test::testDataPilot() pDPObj->SetSaveData(aSaveData); pDPObj->SetAlive(true); + pDPObj->InvalidateData(); + + return pDPObj; +} + +} + +void Test::testDataPilot() +{ + m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data"))); + m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table"))); + + // Dimension definition + DPFieldDef aFields[] = { + { "Name", sheet::DataPilotFieldOrientation_ROW }, + { "Group", sheet::DataPilotFieldOrientation_COLUMN }, + { "Score", sheet::DataPilotFieldOrientation_DATA } + }; + + // Raw data + struct { + const char* pName; const char* pGroup; int nScore; + } aData[] = { + { "Andy", "A", 30 }, + { "Bruce", "A", 20 }, + { "Charlie", "B", 45 }, + { "David", "B", 12 }, + { "Edward", "C", 8 }, + { "Frank", "C", 15 }, + }; + + size_t nFieldCount = SAL_N_ELEMENTS(aFields); + size_t nDataCount = SAL_N_ELEMENTS(aData); + + // Insert field names in row 0. + for (size_t i = 0; i < nFieldCount; ++i) + m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8)); + + // Insert data into row 1 and downward. + for (size_t i = 0; i < nDataCount; ++i) + { + SCROW nRow = static_cast<SCROW>(i) + 1; + m_pDoc->SetString(0, nRow, 0, OUString(aData[i].pName, strlen(aData[i].pName), RTL_TEXTENCODING_UTF8)); + m_pDoc->SetString(1, nRow, 0, OUString(aData[i].pGroup, strlen(aData[i].pGroup), RTL_TEXTENCODING_UTF8)); + m_pDoc->SetValue(2, nRow, 0, aData[i].nScore); + } + + SCROW nRow1 = 0, nRow2 = 0; + SCCOL nCol1 = 0, nCol2 = 0; + m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false); + CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0); + CPPUNIT_ASSERT_MESSAGE("Unexpected data range.", + nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount)); + + SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1); + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + { + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + { + String aVal; + m_pDoc->GetString(nCol, nRow, 0, aVal); + printer.set(nRow, nCol, aVal); + } + } + printer.print("Data sheet content"); + printer.clear(); + + ScDPObject* pDPObj = createDPFromRange( + m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false); + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); bool bSuccess = pDPs->InsertNewTable(pDPObj); CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess); CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.", pDPs->GetCount() == 1); - pDPObj->InvalidateData(); pDPObj->SetName(pDPs->CreateNewName()); bool bOverFlow = false; @@ -841,41 +911,261 @@ void Test::testDataPilot() pDPObj->Output(aOutRange.aStart); aOutRange = pDPObj->GetOutRange(); - const ScAddress& s = aOutRange.aStart; - const ScAddress& e = aOutRange.aEnd; - printer.resize(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1); - SCROW nOutRowSize = SAL_N_ELEMENTS(aOutputCheck); - SCCOL nOutColSize = SAL_N_ELEMENTS(aOutputCheck[0]); - CPPUNIT_ASSERT_MESSAGE("Row size of the table output is not as expected.", - nOutRowSize == (e.Row()-s.Row()+1)); - CPPUNIT_ASSERT_MESSAGE("Column size of the table output is not as expected.", - nOutColSize == (e.Col()-s.Col()+1)); - for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow) { - for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol) + // Expected output table content. 0 = empty cell + const char* aOutputCheck[][5] = { + { "Sum - Score", "Group", 0, 0, 0 }, + { "Name", "A", "B", "C", "Total Result" }, + { "Andy", "30", 0, 0, "30" }, + { "Bruce", "20", 0, 0, "20" }, + { "Charlie", 0, "45", 0, "45" }, + { "David", 0, "12", 0, "12" }, + { "Edward", 0, 0, "8", "8" }, + { "Frank", 0, 0, "15", "15" }, + { "Total Result", "50", "57", "23", "130" } + }; + + bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output"); + CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); + } + + // Update the cell values. + double aData2[] = { 100, 200, 300, 400, 500, 600 }; + for (size_t i = 0; i < SAL_N_ELEMENTS(aData2); ++i) + { + SCROW nRow = i + 1; + m_pDoc->SetValue(2, nRow, 0, aData2[i]); + } + + printer.resize(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1); + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + { + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) { String aVal; - m_pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal); + m_pDoc->GetString(nCol, nRow, 0, aVal); printer.set(nRow, nCol, aVal); - const char* p = aOutputCheck[nRow][nCol]; - if (p) - { - OUString aCheckVal = OUString::createFromAscii(p); - bool bEqual = aCheckVal.equals(aVal); - if (!bEqual) - { - cerr << "Expected: " << aCheckVal << " Actual: " << aVal << endl; - CPPUNIT_ASSERT_MESSAGE("Unexpected cell content.", false); - } - } - else - CPPUNIT_ASSERT_MESSAGE("Empty cell expected.", aVal.Len() == 0); } } - printer.print("DataPilot table output"); + printer.print("Data sheet content (modified)"); printer.clear(); - // Now, delete the datapilot object. + // Now, create a copy of the datapilot object for the updated table, but + // don't clear the cache which should force the copy to use the old data + // from the cache. + ScDPObject* pDPObj2 = new ScDPObject(*pDPObj); + pDPs->FreeTable(pDPObj); + pDPs->InsertNewTable(pDPObj2); + + aOutRange = pDPObj2->GetOutRange(); + pDPObj2->ClearSource(); + pDPObj2->Output(aOutRange.aStart); + { + // Expected output table content. 0 = empty cell + const char* aOutputCheck[][5] = { + { "Sum - Score", "Group", 0, 0, 0 }, + { "Name", "A", "B", "C", "Total Result" }, + { "Andy", "30", 0, 0, "30" }, + { "Bruce", "20", 0, 0, "20" }, + { "Charlie", 0, "45", 0, "45" }, + { "David", 0, "12", 0, "12" }, + { "Edward", 0, 0, "8", "8" }, + { "Frank", 0, 0, "15", "15" }, + { "Total Result", "50", "57", "23", "130" } + }; + + bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (from old cache)"); + CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); + } + + // This time clear the cache to refresh the data from the source range. + CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData()); + ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches(); + const ScSheetSourceDesc* pDesc = pDPObj2->GetSheetDesc(); + rCaches.removeCache(pDesc->GetSourceRange()); + pDPObj2->ClearSource(); + pDPObj2->Output(aOutRange.aStart); + + { + // Expected output table content. 0 = empty cell + const char* aOutputCheck[][5] = { + { "Sum - Score", "Group", 0, 0, 0 }, + { "Name", "A", "B", "C", "Total Result" }, + { "Andy", "100", 0, 0, "100" }, + { "Bruce", "200", 0, 0, "200" }, + { "Charlie", 0, "300", 0, "300" }, + { "David", 0, "400", 0, "400" }, + { "Edward", 0, 0, "500", "500" }, + { "Frank", 0, 0, "600", "600" }, + { "Total Result", "300", "700", "1100", "2100" } + }; + + bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (refreshed)"); + CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); + } + + pDPs->FreeTable(pDPObj2); + CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.", + pDPs->GetCount() == 0); + + m_pDoc->DeleteTab(1); + m_pDoc->DeleteTab(0); +} + +void Test::testDataPilotFilters() +{ + m_pDoc->InsertTab(0, OUString(RTL_CONSTASCII_USTRINGPARAM("Data"))); + m_pDoc->InsertTab(1, OUString(RTL_CONSTASCII_USTRINGPARAM("Table"))); + + // Dimension definition + DPFieldDef aFields[] = { + { "Name", sheet::DataPilotFieldOrientation_HIDDEN }, + { "Group1", sheet::DataPilotFieldOrientation_HIDDEN }, + { "Group2", sheet::DataPilotFieldOrientation_PAGE }, + { "Val1", sheet::DataPilotFieldOrientation_DATA }, + { "Val2", sheet::DataPilotFieldOrientation_DATA } + }; + + // Raw data + const char* aData[][5] = { + { "A", "1", "A", "1", "10" }, + { "B", "1", "A", "1", "10" }, + { "C", "1", "B", "1", "10" }, + { "D", "1", "B", "1", "10" }, + { "E", "2", "A", "1", "10" }, + { "F", "2", "A", "1", "10" }, + { "G", "2", "B", "1", "10" }, + { "H", "2", "B", "1", "10" } + }; + + size_t nFieldCount = SAL_N_ELEMENTS(aFields); + size_t nDataCount = SAL_N_ELEMENTS(aData); + + // Insert field names in row 0. + for (size_t i = 0; i < nFieldCount; ++i) + m_pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8)); + + // Insert data into row 1 and downward. + for (size_t i = 0; i < nDataCount; ++i) + { + SCROW nRow = static_cast<SCROW>(i) + 1; + for (size_t j = 0; j < nFieldCount; ++j) + { + SCCOL nCol = static_cast<SCCOL>(j); + m_pDoc->SetString( + nCol, nRow, 0, OUString(aData[i][j], strlen(aData[i][j]), RTL_TEXTENCODING_UTF8)); + } + } + + SCROW nRow1 = 0, nRow2 = 0; + SCCOL nCol1 = 0, nCol2 = 0; + m_pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false); + CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0); + CPPUNIT_ASSERT_MESSAGE("Unexpected data range.", + nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount)); + + SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1); + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + { + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + { + String aVal; + m_pDoc->GetString(nCol, nRow, 0, aVal); + printer.set(nRow, nCol, aVal); + } + } + printer.print("Data sheet content"); + printer.clear(); + + ScDPObject* pDPObj = createDPFromRange( + m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, true); + + ScDPCollection* pDPs = m_pDoc->GetDPCollection(); + bool bSuccess = pDPs->InsertNewTable(pDPObj); + CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess); + CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.", + pDPs->GetCount() == 1); + pDPObj->SetName(pDPs->CreateNewName()); + + bool bOverFlow = false; + ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow); + CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow); + + pDPObj->Output(aOutRange.aStart); + aOutRange = pDPObj->GetOutRange(); + { + // Expected output table content. 0 = empty cell + const char* aOutputCheck[][2] = { + { "Filter", 0 }, + { "Group2", "- all -" }, + { 0, 0 }, + { "Data", 0 }, + { "Sum - Val1", "8" }, + { "Sum - Val2", "80" }, + { "Total Sum - Val1", "8" }, + { "Total Sum - Val2", "80" } + }; + + bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (unfiltered)"); + CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); + } + + // Set current page of 'Group2' to 'A'. + ScDPSaveData aSaveData(*pDPObj->GetSaveData()); + ScDPSaveDimension* pDim = aSaveData.GetDimensionByName( + OUString(RTL_CONSTASCII_USTRINGPARAM("Group2"))); + CPPUNIT_ASSERT_MESSAGE("Dimension not found", pDim); + OUString aPage(RTL_CONSTASCII_USTRINGPARAM("A")); + pDim->SetCurrentPage(&aPage); + pDPObj->SetSaveData(aSaveData); + pDPObj->Output(aOutRange.aStart); + aOutRange = pDPObj->GetOutRange(); + { + // Expected output table content. 0 = empty cell + const char* aOutputCheck[][2] = { + { "Filter", 0 }, + { "Group2", "A" }, + { 0, 0 }, + { "Data", 0 }, + { "Sum - Val1", "4" }, + { "Sum - Val2", "40" }, + { "Total Sum - Val1", "4" }, + { "Total Sum - Val2", "40" } + }; + + bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by page)"); + CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); + } + + // Set query filter. + ScSheetSourceDesc aDesc(*pDPObj->GetSheetDesc()); + ScQueryParam aQueryParam(aDesc.GetQueryParam()); + CPPUNIT_ASSERT_MESSAGE("There should be at least one query entry.", aQueryParam.GetEntryCount() > 0); + ScQueryEntry& rEntry = aQueryParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 1; // Group1 + rEntry.nVal = 1; + aDesc.SetQueryParam(aQueryParam); + pDPObj->SetSheetDesc(aDesc); + pDPObj->Output(aOutRange.aStart); + aOutRange = pDPObj->GetOutRange(); + { + // Expected output table content. 0 = empty cell + const char* aOutputCheck[][2] = { + { "Filter", 0 }, + { "Group2", "A" }, + { 0, 0 }, + { "Data", 0 }, + { "Sum - Val1", "2" }, + { "Sum - Val2", "20" }, + { "Total Sum - Val1", "2" }, + { "Total Sum - Val2", "20" } + }; + + bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by query)"); + CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess); + } + pDPs->FreeTable(pDPObj); CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.", pDPs->GetCount() == 0); diff --git a/sc/source/core/data/dpcachetable.cxx b/sc/source/core/data/dpcachetable.cxx index 67b55e7f0155..b177acff7be7 100644 --- a/sc/source/core/data/dpcachetable.cxx +++ b/sc/source/core/data/dpcachetable.cxx @@ -73,6 +73,17 @@ static sal_Bool lcl_HasQueryEntry( const ScQueryParam& rParam ) // ---------------------------------------------------------------------------- +bool ScDPCacheTable::RowFlag::isActive() const +{ + return mbShowByFilter && mbShowByPage; +} + +ScDPCacheTable::RowFlag::RowFlag() : + mbShowByFilter(true), + mbShowByPage(true) +{ +} + ScDPCacheTable::FilterItem::FilterItem() : mfValue(0.0), mbHasValue(false) @@ -158,14 +169,13 @@ ScDPCacheTable::Criterion::Criterion() : // ---------------------------------------------------------------------------- -ScDPCacheTable::ScDPCacheTable(ScDPCache* pCache) : +ScDPCacheTable::ScDPCacheTable(const ScDPCache* pCache) : mpCache(pCache) { } ScDPCacheTable::~ScDPCacheTable() { - delete mpCache; } sal_Int32 ScDPCacheTable::getRowSize() const @@ -181,13 +191,13 @@ sal_Int32 ScDPCacheTable::getColSize() const void ScDPCacheTable::fillTable( const ScQueryParam& rQuery, bool* pSpecial, bool bIgnoreEmptyRows, bool bRepeatIfEmpty) { - const SCROW nRowCount = getRowSize(); - const SCCOL nColCount = (SCCOL) getColSize(); - if ( nRowCount <= 0 || nColCount <= 0) + const SCROW nRowCount = getRowSize(); + const SCCOL nColCount = (SCCOL) getColSize(); + if ( nRowCount <= 0 || nColCount <= 0) return; - maRowsVisible.clear(); - maRowsVisible.reserve(nRowCount); + maRowFlags.clear(); + maRowFlags.reserve(nRowCount); // Initialize field entries container. maFieldEntries.clear(); @@ -199,7 +209,7 @@ void ScDPCacheTable::fillTable( SCROW nMemCount = getCache()->GetDimMemberCount( nCol ); if ( nMemCount ) { - std::vector< SCROW > pAdded( nMemCount, -1 ); + std::vector<SCROW> aAdded( nMemCount, -1 ); for (SCROW nRow = 0; nRow < nRowCount; ++nRow ) { @@ -207,24 +217,27 @@ void ScDPCacheTable::fillTable( SCROW nOrder = getOrder( nCol, nIndex ); if ( nCol == 0 ) - maRowsVisible.push_back(false); + { + maRowFlags.push_back(RowFlag()); + maRowFlags.back().mbShowByFilter = false; + } if ( lcl_HasQueryEntry(rQuery) && !getCache()->ValidQuery( nRow , rQuery, pSpecial ) ) continue; if ( bIgnoreEmptyRows && getCache()->IsRowEmpty( nRow ) ) continue; - // Insert a new row into cache table. + if ( nCol == 0 ) - maRowsVisible.back() = true; + maRowFlags.back().mbShowByFilter = true; - pAdded[nOrder] = nIndex; + aAdded[nOrder] = nIndex; } maFieldEntries.push_back( vector<SCROW>() ); for ( SCROW nRow = 0; nRow < nMemCount; nRow++ ) { - if ( pAdded[nRow] != -1 ) - maFieldEntries.back().push_back( pAdded[nRow] ); + if ( aAdded[nRow] != -1 ) + maFieldEntries.back().push_back( aAdded[nRow] ); } } } @@ -237,8 +250,8 @@ void ScDPCacheTable::fillTable() if ( nRowCount <= 0 || nColCount <= 0) return; - maRowsVisible.clear(); - maRowsVisible.reserve(nRowCount); + maRowFlags.clear(); + maRowFlags.reserve(nRowCount); // Initialize field entries container. @@ -259,8 +272,10 @@ void ScDPCacheTable::fillTable() SCROW nOrder = getOrder( nCol, nIndex ); if ( nCol == 0 ) - maRowsVisible.push_back(true); - + { + maRowFlags.push_back(RowFlag()); + maRowFlags.back().mbShowByFilter = true; + } pAdded[nOrder] = nIndex; } @@ -276,24 +291,24 @@ void ScDPCacheTable::fillTable() bool ScDPCacheTable::isRowActive(sal_Int32 nRow) const { - if (nRow < 0 || static_cast<size_t>(nRow) >= maRowsVisible.size()) + if (nRow < 0 || static_cast<size_t>(nRow) >= maRowFlags.size()) // row index out of bound return false; - return maRowsVisible[nRow]; + return maRowFlags[nRow].isActive(); } void ScDPCacheTable::filterByPageDimension(const vector<Criterion>& rCriteria, const boost::unordered_set<sal_Int32>& rRepeatIfEmptyDims) { sal_Int32 nRowSize = getRowSize(); - if (nRowSize != static_cast<sal_Int32>(maRowsVisible.size())) + if (nRowSize != static_cast<sal_Int32>(maRowFlags.size())) { // sizes of the two tables differ! return; } for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) - maRowsVisible[nRow] = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims); + maRowFlags[nRow].mbShowByPage = isRowQualified(nRow, rCriteria, rRepeatIfEmptyDims); } const ScDPItemData* ScDPCacheTable::getCell(SCCOL nCol, SCROW nRow, bool bRepeatIfEmpty) const @@ -359,7 +374,7 @@ void ScDPCacheTable::filterTable(const vector<Criterion>& rCriteria, Sequence< S for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow) { - if (!maRowsVisible[nRow]) + if (!maRowFlags[nRow].isActive()) // This row is filtered out. continue; @@ -401,8 +416,7 @@ SCROW ScDPCacheTable::getOrder(long nDim, SCROW nIndex) const void ScDPCacheTable::clear() { maFieldEntries.clear(); - maRowsVisible.clear(); - delete mpCache; + maRowFlags.clear(); mpCache = NULL; } @@ -411,9 +425,8 @@ bool ScDPCacheTable::empty() const return mpCache == NULL || maFieldEntries.empty(); } -void ScDPCacheTable::setCache(ScDPCache* p) +void ScDPCacheTable::setCache(const ScDPCache* p) { - delete mpCache; mpCache = p; } @@ -448,9 +461,4 @@ const ScDPCache* ScDPCacheTable::getCache() const return mpCache; } -ScDPCache* ScDPCacheTable::getCache() -{ - return mpCache; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 97e2f0db1bbc..9589fe838f7a 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -54,6 +54,7 @@ #include "dpglobal.hxx" #include "globstr.hrc" #include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/sdb/XCompletedExecution.hpp> #include <com/sun/star/sheet/GeneralFunction.hpp> #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> @@ -70,13 +71,15 @@ #include <com/sun/star/sheet/XDrillDownDataSupplier.hpp> #include <comphelper/processfactory.hxx> +#include <comphelper/types.hxx> #include <sal/macros.h> #include <tools/debug.hxx> #include <tools/diagnose_ex.h> #include <svl/zforlist.hxx> // IsNumberFormat +#include <vcl/msgbox.hxx> #include <vector> -#include <stdio.h> +#include <memory> using namespace com::sun::star; using ::std::vector; @@ -95,6 +98,13 @@ using ::com::sun::star::sheet::XDimensionsSupplier; using ::com::sun::star::beans::XPropertySet; using ::rtl::OUString; +#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet" +#define SC_SERVICE_INTHANDLER "com.sun.star.task.InteractionHandler" + +#define SC_DBPROP_DATASOURCENAME "DataSourceName" +#define SC_DBPROP_COMMAND "Command" +#define SC_DBPROP_COMMANDTYPE "CommandType" + // ----------------------------------------------------------------------- #define SCDPSOURCE_SERVICE "com.sun.star.sheet.DataPilotSource" @@ -417,7 +427,7 @@ ScDPTableData* ScDPObject::GetTableData() OSL_FAIL("no source descriptor"); pSheetDesc = new ScSheetSourceDesc(pDoc); // dummy defaults } - ScDPCache* pCache = pSheetDesc->CreateCache(); + const ScDPCache* pCache = pSheetDesc->CreateCache(); if (pCache) pData.reset(new ScSheetDPData(pDoc, *pSheetDesc, pCache)); } @@ -1843,17 +1853,20 @@ sal_Bool ScDPObject::FillOldParam(ScPivotParam& rParam) const rParam.nTab = aOutRange.aStart.Tab(); // ppLabelArr / nLabels is not changed - SCCOL nColAdd = pSheetDesc->GetSourceRange().aStart.Col(); + SCCOL nSrcColOffset = 0; + if (IsSheetData()) + // source data column offset is only for internal sheet source. + nSrcColOffset = pSheetDesc->GetSourceRange().aStart.Col(); bool bAddData = ( lcl_GetDataGetOrientation( xSource ) == sheet::DataPilotFieldOrientation_HIDDEN ); lcl_FillOldFields( - rParam.maPageFields, xSource, sheet::DataPilotFieldOrientation_PAGE, nColAdd, false); + rParam.maPageFields, xSource, sheet::DataPilotFieldOrientation_PAGE, nSrcColOffset, false); lcl_FillOldFields( - rParam.maColFields, xSource, sheet::DataPilotFieldOrientation_COLUMN, nColAdd, bAddData); + rParam.maColFields, xSource, sheet::DataPilotFieldOrientation_COLUMN, nSrcColOffset, bAddData); lcl_FillOldFields( - rParam.maRowFields, xSource, sheet::DataPilotFieldOrientation_ROW, nColAdd, false); + rParam.maRowFields, xSource, sheet::DataPilotFieldOrientation_ROW, nSrcColOffset, false); lcl_FillOldFields( - rParam.maDataFields, xSource, sheet::DataPilotFieldOrientation_DATA, nColAdd, false); + rParam.maDataFields, xSource, sheet::DataPilotFieldOrientation_DATA, nSrcColOffset, false); uno::Reference<beans::XPropertySet> xProp( xSource, uno::UNO_QUERY ); if (xProp.is()) @@ -2383,15 +2396,148 @@ uno::Reference<sheet::XDimensionsSupplier> ScDPObject::CreateSource( const ScDPS return xRet; } -// ---------------------------------------------------------------------------- +ScDPCollection::SheetCaches::SheetCaches(ScDocument* pDoc) : mpDoc(pDoc) {} + +const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange) +{ + CachesType::const_iterator itr = maCaches.find(rRange); + if (itr != maCaches.end()) + // already cached. + return itr->second; + + ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc)); + pCache->InitFromDoc(mpDoc, rRange); + const ScDPCache* p = pCache.get(); + maCaches.insert(rRange, pCache); + return p; +} + +void ScDPCollection::SheetCaches::removeCache(const ScRange& rRange) +{ + CachesType::iterator itr = maCaches.find(rRange); + if (itr != maCaches.end()) + maCaches.erase(itr); +} + +ScDPCollection::NameCaches::NameCaches(ScDocument* pDoc) : mpDoc(pDoc) {} + +const ScDPCache* ScDPCollection::NameCaches::getCache(const OUString& rName, const ScRange& rRange) +{ + CachesType::const_iterator itr = maCaches.find(rName); + if (itr != maCaches.end()) + // already cached. + return itr->second; + + ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc)); + pCache->InitFromDoc(mpDoc, rRange); + const ScDPCache* p = pCache.get(); + maCaches.insert(rName, pCache); + return p; +} + +void ScDPCollection::NameCaches::removeCache(const OUString& rName) +{ + CachesType::iterator itr = maCaches.find(rName); + if (itr != maCaches.end()) + maCaches.erase(itr); +} + +ScDPCollection::DBType::DBType(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) : + mnSdbType(nSdbType), maDBName(rDBName), maCommand(rCommand) {} + +ScDPCollection::DBCaches::DBCaches(ScDocument* pDoc) : mpDoc(pDoc) {} + +const ScDPCache* ScDPCollection::DBCaches::getCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) +{ + DBType aType(nSdbType, rDBName, rCommand); + CachesType::const_iterator itr = maCaches.find(aType); + if (itr != maCaches.end()) + // already cached. + return itr->second; + + uno::Reference<sdbc::XRowSet> xRowSet ; + try + { + xRowSet = uno::Reference<sdbc::XRowSet>( + comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_ROWSET )) ), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY ); + DBG_ASSERT( xRowProp.is(), "can't get RowSet" ); + if ( xRowProp.is() ) + { + // + // set source parameters + // + uno::Any aAny; + aAny <<= rDBName; + xRowProp->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny ); + + aAny <<= rCommand; + xRowProp->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny ); + + aAny <<= nSdbType; + xRowProp->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny ); + + uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY ); + if ( xExecute.is() ) + { + uno::Reference<task::XInteractionHandler> xHandler( + comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ), + uno::UNO_QUERY); + xExecute->executeWithCompletion( xHandler ); + } + else + xRowSet->execute(); + } + } + catch ( sdbc::SQLException& rError ) + { + //! store error message + InfoBox aInfoBox( 0, String(rError.Message) ); + aInfoBox.Execute(); + return NULL; + } + catch ( uno::Exception& ) + { + OSL_FAIL("Unexpected exception in database"); + return NULL; + } + + ::std::auto_ptr<ScDPCache> pCache(new ScDPCache(mpDoc)); + SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge); + pCache->InitFromDataBase(xRowSet, *aFormat.GetNullDate()); + ::comphelper::disposeComponent(xRowSet); + const ScDPCache* p = pCache.get(); + maCaches.insert(aType, pCache); + return p; +} + +void ScDPCollection::DBCaches::removeCache(sal_Int32 nSdbType, const OUString& rDBName, const OUString& rCommand) +{ + DBType aType(nSdbType, rDBName, rCommand); + CachesType::iterator itr = maCaches.find(aType); + if (itr != maCaches.end()) + maCaches.erase(itr); +} ScDPCollection::ScDPCollection(ScDocument* pDocument) : - pDoc( pDocument ) + pDoc( pDocument ), + maSheetCaches(pDocument), + maNameCaches(pDocument), + maDBCaches(pDocument) { } ScDPCollection::ScDPCollection(const ScDPCollection& r) : - pDoc(r.pDoc) + pDoc(r.pDoc), + maSheetCaches(r.pDoc), + maNameCaches(r.pDoc), + maDBCaches(r.pDoc) { } @@ -2584,4 +2730,30 @@ bool ScDPCollection::HasDPTable(SCCOL nCol, SCROW nRow, SCTAB nTab) const return pMergeAttr->HasDPTable(); } +ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches() +{ + return maSheetCaches; +} + +ScDPCollection::NameCaches& ScDPCollection::GetNameCaches() +{ + return maNameCaches; +} + +ScDPCollection::DBCaches& ScDPCollection::GetDBCaches() +{ + return maDBCaches; +} + +bool operator<(const ScDPCollection::DBType& left, const ScDPCollection::DBType& right) +{ + if (left.mnSdbType != right.mnSdbType) + return left.mnSdbType < right.mnSdbType; + + if (!left.maDBName.equals(right.maDBName)) + return left.maDBName < right.maDBName; + + return left.maCommand < right.maCommand; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index c0455819285c..8351c2f3dd28 100644 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -56,7 +56,6 @@ #include "scresid.hxx" #include "unonames.hxx" #include "sc.hrc" -#include "scdpoutputimpl.hxx" #include "dpglobal.hxx" #include <com/sun/star/beans/XPropertySet.hpp> @@ -83,15 +82,16 @@ using ::rtl::OUString; #define DP_PROP_POSITION "Position" #define DP_PROP_USEDHIERARCHY "UsedHierarchy" #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension" -#define DP_PROP_NUMBERFORMAT "NumberFormat" #define DP_PROP_FILTER "Filter" #define DP_PROP_COLUMNGRAND "ColumnGrand" #define DP_PROP_ROWGRAND "RowGrand" #define DP_PROP_SUBTOTALS "SubTotals" -// ----------------------------------------------------------------------- +#define SC_DP_FRAME_INNER_BOLD 20 +#define SC_DP_FRAME_OUTER_BOLD 40 + +#define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 ) -//! dynamic!!! #define SC_DPOUT_MAXLEVELS 256 struct ScDPOutLevelData @@ -121,7 +121,187 @@ struct ScDPOutLevelData //! bug (73840) in uno::Sequence - copy and then assign doesn't work! }; -// ----------------------------------------------------------------------- +namespace { + +bool lcl_compareColfuc ( SCCOL i, SCCOL j) { return (i<j); } +bool lcl_compareRowfuc ( SCROW i, SCROW j) { return (i<j); } + +class ScDPOutputImpl +{ + ScDocument* mpDoc; + sal_uInt16 mnTab; + ::std::vector< bool > mbNeedLineCols; + ::std::vector< SCCOL > mnCols; + + ::std::vector< bool > mbNeedLineRows; + ::std::vector< SCROW > mnRows; + + SCCOL mnTabStartCol; + SCROW mnTabStartRow; + SCCOL mnMemberStartCol; + SCROW mnMemberStartRow; + + SCCOL mnDataStartCol; + SCROW mnDataStartRow; + SCCOL mnTabEndCol; + SCROW mnTabEndRow; + +public: + ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab, + SCCOL nTabStartCol, + SCROW nTabStartRow, + SCCOL nMemberStartCol, + SCROW nMemberStartRow, + SCCOL nDataStartCol, + SCROW nDataStartRow, + SCCOL nTabEndCol, + SCROW nTabEndRow ); + bool AddRow( SCROW nRow ); + bool AddCol( SCCOL nCol ); + + void OutputDataArea(); + void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori = false ); + +}; + +void ScDPOutputImpl::OutputDataArea() +{ + AddRow( mnDataStartRow ); + AddCol( mnDataStartCol ); + + mnCols.push_back( mnTabEndCol+1); //set last row bottom + mnRows.push_back( mnTabEndRow+1); //set last col bottom + + bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() ); + + std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc ); + std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc ); + + for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ ) + { + if ( !bAllRows ) + { + if ( nCol < (SCCOL)mnCols.size()-2) + { + for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 ) + OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); + if ( mnRows.size()>=2 ) + OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 ); + } + else + { + for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ ) + OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); + } + } + else + OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows ); + } + //out put rows area outer framer + if ( mnTabStartCol != mnDataStartCol ) + { + if ( mnTabStartRow != mnDataStartRow ) + OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 ); + OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow ); + } + //out put cols area outer framer + OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 ); +} + +ScDPOutputImpl::ScDPOutputImpl( ScDocument* pDoc, sal_uInt16 nTab, + SCCOL nTabStartCol, + SCROW nTabStartRow, + SCCOL nMemberStartCol, + SCROW nMemberStartRow, + SCCOL nDataStartCol, + SCROW nDataStartRow, + SCCOL nTabEndCol, + SCROW nTabEndRow ): + mpDoc( pDoc ), + mnTab( nTab ), + mnTabStartCol( nTabStartCol ), + mnTabStartRow( nTabStartRow ), + mnMemberStartCol( nMemberStartCol), + mnMemberStartRow( nMemberStartRow), + mnDataStartCol ( nDataStartCol ), + mnDataStartRow ( nDataStartRow ), + mnTabEndCol( nTabEndCol ), + mnTabEndRow( nTabEndRow ) +{ + mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false ); + mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false ); + +} + +bool ScDPOutputImpl::AddRow( SCROW nRow ) +{ + if ( !mbNeedLineRows[ nRow - mnDataStartRow ] ) + { + mbNeedLineRows[ nRow - mnDataStartRow ] = true; + mnRows.push_back( nRow ); + return true; + } + else + return false; +} + +bool ScDPOutputImpl::AddCol( SCCOL nCol ) +{ + + if ( !mbNeedLineCols[ nCol - mnDataStartCol ] ) + { + mbNeedLineCols[ nCol - mnDataStartCol ] = true; + mnCols.push_back( nCol ); + return true; + } + else + return false; +} + +void ScDPOutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bHori ) +{ + Color color = SC_DP_FRAME_COLOR; + ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD ); + ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD ); + + SvxBoxItem aBox( ATTR_BORDER ); + + if ( nStartCol == mnTabStartCol ) + aBox.SetLine(&aOutLine, BOX_LINE_LEFT); + else + aBox.SetLine(&aLine, BOX_LINE_LEFT); + + if ( nStartRow == mnTabStartRow ) + aBox.SetLine(&aOutLine, BOX_LINE_TOP); + else + aBox.SetLine(&aLine, BOX_LINE_TOP); + + if ( nEndCol == mnTabEndCol ) //bottom row + aBox.SetLine(&aOutLine, BOX_LINE_RIGHT); + else + aBox.SetLine(&aLine, BOX_LINE_RIGHT); + + if ( nEndRow == mnTabEndRow ) //bottom + aBox.SetLine(&aOutLine, BOX_LINE_BOTTOM); + else + aBox.SetLine(&aLine, BOX_LINE_BOTTOM); + + + SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER ); + aBoxInfo.SetValid(VALID_VERT,false ); + if ( bHori ) + { + aBoxInfo.SetValid(VALID_HORI,sal_True); + aBoxInfo.SetLine( &aLine, BOXINFO_LINE_HORI ); + } + else + aBoxInfo.SetValid(VALID_HORI,false ); + + aBoxInfo.SetValid(VALID_DISTANCE,false); + + mpDoc->ApplyFrameAreaTab( ScRange( nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo ); + +} void lcl_SetStyleById( ScDocument* pDoc, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, @@ -214,7 +394,7 @@ void lcl_FillNumberFormats( sal_uInt32*& rFormats, long& rCount, aDataNames[nDataCount] = String( xDimName->getName() ); long nFormat = ScUnoHelpFunctions::GetLongProperty( xDimProp, - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(DP_PROP_NUMBERFORMAT)) ); + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_NUMFMT)) ); nDataFormats[nDataCount] = nFormat; if ( nFormat != 0 ) bAnySet = sal_True; @@ -280,7 +460,7 @@ sal_uInt32 lcl_GetFirstNumberFormat( const uno::Reference<container::XIndexAcces { long nFormat = ScUnoHelpFunctions::GetLongProperty( xDimProp, - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(DP_PROP_NUMBERFORMAT)) ); + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_NUMFMT)) ); return nFormat; // use format from first found data dimension } @@ -349,8 +529,10 @@ uno::Sequence<sheet::MemberResult> lcl_GetSelectedPageAsResult( const uno::Refer return aRet; } +} + ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsSupplier>& xSrc, - const ScAddress& rPos, sal_Bool bFilter ) : + const ScAddress& rPos, bool bFilter ) : pDoc( pD ), xSource( xSrc ), aStartPos( rPos ), @@ -526,7 +708,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS } catch (uno::RuntimeException&) { - bResultsError = sal_True; + bResultsError = true; } } @@ -618,7 +800,7 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab, if ( nFlags & sheet::MemberResultFlags::SUBTOTAL ) { - OutputImpl outputimp( pDoc, nTab, + ScDPOutputImpl outputimp( pDoc, nTab, nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow, nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow ); //! limit frames to horizontal or vertical? @@ -695,7 +877,7 @@ void ScDPOutput::CalcSizes() if ( aStartPos.Col() + nRowFieldCount + nColCount - 1 > MAXCOL || aStartPos.Row() + nPageSize + nHeaderSize + nColFieldCount + nRowCount > MAXROW ) { - bSizeOverflow = sal_True; + bSizeOverflow = true; } nTabStartCol = aStartPos.Col(); @@ -715,7 +897,7 @@ void ScDPOutput::CalcSizes() nTabEndRow = nDataStartRow + (SCROW)nRowCount - 1; else nTabEndRow = nDataStartRow; // single row will remain empty - bSizesValid = sal_True; + bSizesValid = true; } } @@ -838,7 +1020,7 @@ void ScDPOutput::Output() STR_PIVOT_STYLE_INNER ); // output column headers: - OutputImpl outputimp( pDoc, nTab, + ScDPOutputImpl outputimp( pDoc, nTab, nTabStartCol, nTabStartRow, nMemberStartCol, nMemberStartRow, nDataStartCol, nDataStartRow, nTabEndCol, nTabEndRow ); for (nField=0; nField<nColFieldCount; nField++) diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx index 7eeb4b93e284..72c0f06911b1 100644 --- a/sc/source/core/data/dpsdbtab.cxx +++ b/sc/source/core/data/dpsdbtab.cxx @@ -33,23 +33,6 @@ // INCLUDE -------------------------------------------------------------- -#include <tools/debug.hxx> -#include <vcl/msgbox.hxx> -#include <svl/zforlist.hxx> -#include <comphelper/processfactory.hxx> -#include <comphelper/types.hxx> - -#include <com/sun/star/sheet/DataImportMode.hpp> -#include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/sdb/CommandType.hpp> -#include <com/sun/star/sdb/XCompletedExecution.hpp> -#include <com/sun/star/sdbc/DataType.hpp> -#include <com/sun/star/sdbc/XRow.hpp> -#include <com/sun/star/sdbc/XRowSet.hpp> -#include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> - #include "dpsdbtab.hxx" #include "collect.hxx" #include "global.hxx" @@ -59,100 +42,41 @@ #include "document.hxx" #include "dpobject.hxx" +#include <com/sun/star/sheet/DataImportMode.hpp> +#include <com/sun/star/sdb/CommandType.hpp> + using namespace com::sun::star; using ::std::vector; using ::com::sun::star::uno::Sequence; -using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Any; -using ::com::sun::star::uno::UNO_QUERY; -#define SC_SERVICE_ROWSET "com.sun.star.sdb.RowSet" -#define SC_SERVICE_INTHANDLER "com.sun.star.task.InteractionHandler" - -//! move to a header file? -#define SC_DBPROP_DATASOURCENAME "DataSourceName" -#define SC_DBPROP_COMMAND "Command" -#define SC_DBPROP_COMMANDTYPE "CommandType" - -ScDPCache* ScImportSourceDesc::CreateCache() const +sal_Int32 ScImportSourceDesc::GetCommandType() const { - if (!mpDoc) - return NULL; - sal_Int32 nSdbType = -1; switch ( nType ) { - case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break; - case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break; - case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break; - default: - return NULL; + case sheet::DataImportMode_SQL: nSdbType = sdb::CommandType::COMMAND; break; + case sheet::DataImportMode_TABLE: nSdbType = sdb::CommandType::TABLE; break; + case sheet::DataImportMode_QUERY: nSdbType = sdb::CommandType::QUERY; break; + default: + ; } + return nSdbType; +} - ScDPCache* pCache = new ScDPCache(mpDoc); - - uno::Reference<sdbc::XRowSet> xRowSet ; - try - { - xRowSet = uno::Reference<sdbc::XRowSet>( - comphelper::getProcessServiceFactory()->createInstance( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_ROWSET )) ), - uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xRowProp( xRowSet, uno::UNO_QUERY ); - DBG_ASSERT( xRowProp.is(), "can't get RowSet" ); - if ( xRowProp.is() ) - { - // - // set source parameters - // - uno::Any aAny; - aAny <<= rtl::OUString( aDBName ); - xRowProp->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_DATASOURCENAME)), aAny ); - - aAny <<= rtl::OUString( aObject ); - xRowProp->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMAND)), aAny ); - - aAny <<= nSdbType; - xRowProp->setPropertyValue( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_DBPROP_COMMANDTYPE)), aAny ); - - uno::Reference<sdb::XCompletedExecution> xExecute( xRowSet, uno::UNO_QUERY ); - if ( xExecute.is() ) - { - uno::Reference<task::XInteractionHandler> xHandler( - comphelper::getProcessServiceFactory()->createInstance( - rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_SERVICE_INTHANDLER )) ), - uno::UNO_QUERY); - xExecute->executeWithCompletion( xHandler ); - } - else - xRowSet->execute(); - SvNumberFormatter aFormat(mpDoc->GetServiceManager(), ScGlobal::eLnge); - pCache->InitFromDataBase( xRowSet, *aFormat.GetNullDate() ); - } - } - catch ( sdbc::SQLException& rError ) - { - //! store error message - delete pCache; - pCache = NULL; - InfoBox aInfoBox( 0, String(rError.Message) ); - aInfoBox.Execute(); - } - catch ( uno::Exception& ) - { - delete pCache; - pCache = NULL; - OSL_FAIL("Unexpected exception in database"); - } +const ScDPCache* ScImportSourceDesc::CreateCache() const +{ + if (!mpDoc) + return NULL; + sal_Int32 nSdbType = GetCommandType(); + if (nSdbType < 0) + return NULL; - ::comphelper::disposeComponent( xRowSet ); - return pCache; + ScDPCollection::DBCaches& rCaches = mpDoc->GetDPCollection()->GetDBCaches(); + return rCaches.getCache(nSdbType, aDBName, aObject); } ScDatabaseDPData::ScDatabaseDPData(ScDocument* pDoc, const ScImportSourceDesc& rImport) : diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx index e4aca9a45253..cfad761377bc 100644 --- a/sc/source/core/data/dpshttab.cxx +++ b/sc/source/core/data/dpshttab.cxx @@ -60,7 +60,7 @@ using ::std::vector; // ----------------------------------------------------------------------- -ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, ScDPCache* pCache) : +ScSheetDPData::ScSheetDPData(ScDocument* pD, const ScSheetSourceDesc& rDesc, const ScDPCache* pCache) : ScDPTableData(pD), aQuery ( rDesc.GetQueryParam() ), pSpecial(NULL), @@ -307,7 +307,7 @@ bool ScSheetSourceDesc::operator== (const ScSheetSourceDesc& rOther) const maQueryParam == rOther.maQueryParam; } -ScDPCache* ScSheetSourceDesc::CreateCache() const +const ScDPCache* ScSheetSourceDesc::CreateCache() const { if (!mpDoc) return NULL; @@ -319,9 +319,17 @@ ScDPCache* ScSheetSourceDesc::CreateCache() const return NULL; } - ScDPCache* pCache = new ScDPCache(mpDoc); - pCache->InitFromDoc(mpDoc, GetSourceRange()); - return pCache; + // All cache instances are managed centrally by ScDPCollection. + ScDPCollection* pDPs = mpDoc->GetDPCollection(); + if (HasRangeName()) + { + // Name-based data source. + ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches(); + return rCaches.getCache(GetRangeName(), GetSourceRange()); + } + + ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches(); + return rCaches.getCache(GetSourceRange()); } long ScSheetSourceDesc::GetCacheId() const diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index 008cdfcf3935..35782e05bab7 100644 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -48,6 +48,8 @@ #include <com/sun/star/sdbc/XResultSetMetaData.hpp> #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> +#include <memory> + const double D_TIMEFACTOR = 86400.0; using namespace ::com::sun::star; @@ -57,26 +59,37 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::std::vector; +using ::std::auto_ptr; namespace { -bool lcl_isDate( sal_uLong nNumType ) +bool isDate( sal_uLong nNumType ) { return ((nNumType & NUMBERFORMAT_DATE) != 0) ? 1 : 0; } -bool lcl_Search( const ScDPCache::DataListType& list, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex) +/** + * Search for an item in the data array. If it's in the array, return its + * index to the caller. + * + * @param rArray dimension array + * @param rOrder global order (what's this?) + * @param item item to search for + * @param rIndex the index of the found item in the global order. + * + * @return true if the item is found, or false otherwise. + */ +bool hasItemInDimension(const ScDPCache::DataListType& rArray, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex) { - rIndex = list.size(); + rIndex = rArray.size(); bool bFound = false; SCROW nLo = 0; - SCROW nHi = list.size() - 1; - SCROW nIndex; + SCROW nHi = rArray.size() - 1; long nCompare; while (nLo <= nHi) { - nIndex = (nLo + nHi) / 2; - nCompare = ScDPItemData::Compare( list[rOrder[nIndex]], item ); + SCROW nIndex = (nLo + nHi) / 2; + nCompare = ScDPItemData::Compare( rArray[rOrder[nIndex]], item ); if (nCompare < 0) nLo = nIndex + 1; else @@ -173,7 +186,7 @@ ScDPItemData* lcl_GetItemValue( ScDPItemData::ScDPItemData(const String& rS, double fV, bool bHV, const sal_uLong nNumFormatP, bool bData) : nNumFormat( nNumFormatP ), aString(rS), fValue(fV), - mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) | (MK_DATE*!!lcl_isDate( nNumFormat ) ) ) + mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!false) | (MK_DATE*!!isDate( nNumFormat ) ) ) { } @@ -203,7 +216,7 @@ ScDPItemData::ScDPItemData(ScDocument* pDoc, SCROW nRow, sal_uInt16 nCol, sal_uI fValue = fVal; mbFlag |= MK_VAL|MK_DATA; nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ); - lcl_isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE); + isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE); } else if ( pDoc->HasData( nCol,nRow, nDocTab ) ) SetString ( aDocStr ); @@ -473,15 +486,12 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange) maIndexOrder.push_back(new vector<SCROW>()); } //check valid - for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow ++ ) + + for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol) { - for ( sal_uInt16 nCol = nStartCol; nCol <= nEndCol; nCol++ ) - { - if ( nRow == nStartRow ) - AddLabel( new ScDPItemData( pDoc, nRow, nCol, nDocTab ) ); - else - AddData( nCol - nStartCol, new ScDPItemData( pDoc, nRow, nCol, nDocTab ) ); - } + AddLabel(new ScDPItemData(pDoc, nStartRow, nCol, nDocTab)); + for (SCROW nRow = nStartRow + 1; nRow <= nEndRow; ++nRow) + AddData(nCol - nStartCol, new ScDPItemData(pDoc, nRow, nCol, nDocTab)); } return true; } @@ -489,7 +499,7 @@ bool ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange) bool ScDPCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) { if (!xRowSet.is()) - // Dont' even waste time to go any further. + // Don't even waste time to go any further. return false; try { @@ -565,7 +575,7 @@ sal_uLong ScDPCache::GetDimNumType( SCCOL nDim) const return GetNumType(maTableDataValues[nDim][0].nNumFormat); } -bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial) +bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, bool *pSpecial) const { if (!rParam.GetEntry(0).bDoQuery) return true; @@ -787,23 +797,23 @@ bool ScDPCache::IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const return !GetItemDataById( nColumn, GetItemDataId( nColumn, nRow, false ) )->IsHasData(); } -bool ScDPCache::AddData(long nDim, ScDPItemData* pitemData) +bool ScDPCache::AddData(long nDim, ScDPItemData* pData) { DBG_ASSERT( IsValid(), " IsValid() == false " ); DBG_ASSERT( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" ); - SCROW nIndex = 0; - bool bInserted = false; + // Wrap this instance with scoped pointer to ensure proper deletion. + auto_ptr<ScDPItemData> p(pData); + pData->SetDate(isDate(GetNumType(pData->nNumFormat))); - pitemData->SetDate( lcl_isDate( GetNumType( pitemData->nNumFormat ) ) ); - - if ( !lcl_Search( maTableDataValues[nDim], maGlobalOrder[nDim], *pitemData, nIndex ) ) + SCROW nIndex = 0; + if (!hasItemInDimension(maTableDataValues[nDim], maGlobalOrder[nDim], *pData, nIndex)) { - maTableDataValues[nDim].push_back( pitemData ); + // This item doesn't exist in the dimension array yet. + maTableDataValues[nDim].push_back(p); maGlobalOrder[nDim].insert( maGlobalOrder[nDim].begin()+nIndex, maTableDataValues[nDim].size()-1 ); DBG_ASSERT( (size_t) maGlobalOrder[nDim][nIndex] == maTableDataValues[nDim].size()-1 ,"ScDPTableDataCache::AddData "); maSourceData[nDim].push_back( maTableDataValues[nDim].size()-1 ); - bInserted = true; } else maSourceData[nDim].push_back( maGlobalOrder[nDim][nIndex] ); @@ -813,12 +823,9 @@ bool ScDPCache::AddData(long nDim, ScDPItemData* pitemData) while ( mbEmptyRow.size() <= nCurRow ) mbEmptyRow.push_back( true ); - if ( pitemData->IsHasData() ) + if ( pData->IsHasData() ) mbEmptyRow[ nCurRow ] = false; - if ( !bInserted ) - delete pitemData; - return true; } @@ -928,10 +935,26 @@ sal_uLong ScDPCache::GetNumberFormat( long nDim ) const { if ( nDim >= mnColumnCount ) return 0; - if ( maTableDataValues[nDim].size()==0 ) + + if (maTableDataValues[nDim].empty()) return 0; - else - return maTableDataValues[nDim][0].nNumFormat; + + // TODO: This is very ugly, but the best we can do right now. Check the + // first 10 dimension members, and take the first non-zero number format, + // else return the default number format (of 0). For the long-term, we + // need to redo this cache structure to properly indicate empty cells, and + // skip them when trying to determine the representative number format for + // a dimension. + size_t nCount = maTableDataValues[nDim].size(); + if (nCount > 10) + nCount = 10; + for (size_t i = 0; i < nCount; ++i) + { + sal_uLong n = maTableDataValues[nDim][i].nNumFormat; + if (n) + return n; + } + return 0; } bool ScDPCache::IsDateDimension( long nDim ) const @@ -967,7 +990,7 @@ SCCOL ScDPCache::GetDimensionIndex(String sName) const return -1; } -SCROW ScDPCache::GetIdByItemData(long nDim, String sItemData ) const +SCROW ScDPCache::GetIdByItemData(long nDim, const String& sItemData ) const { if ( nDim < mnColumnCount && nDim >=0 ) { @@ -995,7 +1018,7 @@ SCROW ScDPCache::GetIdByItemData( long nDim, const ScDPItemData& rData ) const return GetRowCount() + maAdditionalData.getDataId(rData); } -SCROW ScDPCache::GetAdditionalItemID ( String sItemData ) const +SCROW ScDPCache::GetAdditionalItemID ( const String& sItemData ) const { ScDPItemData rData ( sItemData ); return GetAdditionalItemID( rData ); diff --git a/sc/source/core/data/scdpoutputimpl.cxx b/sc/source/core/data/scdpoutputimpl.cxx deleted file mode 100644 index ce2201ef872c..000000000000 --- a/sc/source/core/data/scdpoutputimpl.cxx +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright IBM Corporation 2009. - * Copyright 2009 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sc.hxx" - -// INCLUDE --------------------------------------------------------------- -#include "scdpoutputimpl.hxx" -#include "scitems.hxx" -#include <editeng/boxitem.hxx> -// ----------------------------------------------------------------------- - -namespace -{ - bool lcl_compareColfuc ( SCCOL i, SCCOL j) { return (i<j); } - bool lcl_compareRowfuc ( SCROW i, SCROW j) { return (i<j); } -} - - -void OutputImpl::OutputDataArea() -{ - AddRow( mnDataStartRow ); - AddCol( mnDataStartCol ); - - mnCols.push_back( mnTabEndCol+1); //set last row bottom - mnRows.push_back( mnTabEndRow+1); //set last col bottom - - sal_Bool bAllRows = ( ( mnTabEndRow - mnDataStartRow + 2 ) == (SCROW) mnRows.size() ); - - std::sort( mnCols.begin(), mnCols.end(), lcl_compareColfuc ); - std::sort( mnRows.begin(), mnRows.end(), lcl_compareRowfuc ); - - for( SCCOL nCol = 0; nCol < (SCCOL)mnCols.size()-1; nCol ++ ) - { - if ( !bAllRows ) - { - if ( nCol < (SCCOL)mnCols.size()-2) - { - for ( SCROW i = nCol%2; i < (SCROW)mnRows.size()-2; i +=2 ) - OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); - if ( mnRows.size()>=2 ) - OutputBlockFrame( mnCols[nCol], mnRows[mnRows.size()-2], mnCols[nCol+1]-1, mnRows[mnRows.size()-1]-1 ); - } - else - { - for ( SCROW i = 0 ; i < (SCROW)mnRows.size()-1; i++ ) - OutputBlockFrame( mnCols[nCol], mnRows[i], mnCols[nCol+1]-1, mnRows[i+1]-1 ); - } - } - else - OutputBlockFrame( mnCols[nCol], mnRows.front(), mnCols[nCol+1]-1, mnRows.back()-1, bAllRows ); - } - //out put rows area outer framer - if ( mnTabStartCol != mnDataStartCol ) - { - if ( mnTabStartRow != mnDataStartRow ) - OutputBlockFrame( mnTabStartCol, mnTabStartRow, mnDataStartCol-1, mnDataStartRow-1 ); - OutputBlockFrame( mnTabStartCol, mnDataStartRow, mnDataStartCol-1, mnTabEndRow ); - } - //out put cols area outer framer - OutputBlockFrame( mnDataStartCol, mnTabStartRow, mnTabEndCol, mnDataStartRow-1 ); -} - -OutputImpl::OutputImpl( ScDocument* pDoc, sal_uInt16 nTab, - SCCOL nTabStartCol, - SCROW nTabStartRow, - SCCOL nMemberStartCol, - SCROW nMemberStartRow, - SCCOL nDataStartCol, - SCROW nDataStartRow, - SCCOL nTabEndCol, - SCROW nTabEndRow ): - mpDoc( pDoc ), - mnTab( nTab ), - mnTabStartCol( nTabStartCol ), - mnTabStartRow( nTabStartRow ), - mnMemberStartCol( nMemberStartCol), - mnMemberStartRow( nMemberStartRow), - mnDataStartCol ( nDataStartCol ), - mnDataStartRow ( nDataStartRow ), - mnTabEndCol( nTabEndCol ), - mnTabEndRow( nTabEndRow ) -{ - mbNeedLineCols.resize( nTabEndCol-nDataStartCol+1, false ); - mbNeedLineRows.resize( nTabEndRow-nDataStartRow+1, false ); - -} - -sal_Bool OutputImpl::AddRow( SCROW nRow ) -{ - if ( !mbNeedLineRows[ nRow - mnDataStartRow ] ) - { - mbNeedLineRows[ nRow - mnDataStartRow ] = true; - mnRows.push_back( nRow ); - return sal_True; - } - else - return false; -} - -sal_Bool OutputImpl::AddCol( SCCOL nCol ) -{ - - if ( !mbNeedLineCols[ nCol - mnDataStartCol ] ) - { - mbNeedLineCols[ nCol - mnDataStartCol ] = true; - mnCols.push_back( nCol ); - return sal_True; - } - else - return false; -} - -void OutputImpl::OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, sal_Bool bHori ) -{ - Color color = SC_DP_FRAME_COLOR; - ::editeng::SvxBorderLine aLine( &color, SC_DP_FRAME_INNER_BOLD ); - ::editeng::SvxBorderLine aOutLine( &color, SC_DP_FRAME_OUTER_BOLD ); - - SvxBoxItem aBox( ATTR_BORDER ); - - if ( nStartCol == mnTabStartCol ) - aBox.SetLine(&aOutLine, BOX_LINE_LEFT); - else - aBox.SetLine(&aLine, BOX_LINE_LEFT); - - if ( nStartRow == mnTabStartRow ) - aBox.SetLine(&aOutLine, BOX_LINE_TOP); - else - aBox.SetLine(&aLine, BOX_LINE_TOP); - - if ( nEndCol == mnTabEndCol ) //bottom row - aBox.SetLine(&aOutLine, BOX_LINE_RIGHT); - else - aBox.SetLine(&aLine, BOX_LINE_RIGHT); - - if ( nEndRow == mnTabEndRow ) //bottom - aBox.SetLine(&aOutLine, BOX_LINE_BOTTOM); - else - aBox.SetLine(&aLine, BOX_LINE_BOTTOM); - - - SvxBoxInfoItem aBoxInfo( ATTR_BORDER_INNER ); - aBoxInfo.SetValid(VALID_VERT,false ); - if ( bHori ) - { - aBoxInfo.SetValid(VALID_HORI,sal_True); - aBoxInfo.SetLine( &aLine, BOXINFO_LINE_HORI ); - } - else - aBoxInfo.SetValid(VALID_HORI,false ); - - aBoxInfo.SetValid(VALID_DISTANCE,false); - - mpDoc->ApplyFrameAreaTab( ScRange( nStartCol, nStartRow, mnTab, nEndCol, nEndRow , mnTab ), &aBox, &aBoxInfo ); - -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/scdpoutputimpl.hxx b/sc/source/core/data/scdpoutputimpl.hxx deleted file mode 100644 index 35a0a65a06fc..000000000000 --- a/sc/source/core/data/scdpoutputimpl.hxx +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright IBM Corporation 2009. - * Copyright 2009 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ -#ifndef SCDPOUTPUTIMPL_HXX -#define SCDPOUTPUTIMPL_HXX - -#include "document.hxx" - -#define SC_DP_FRAME_INNER_BOLD 20 -#define SC_DP_FRAME_OUTER_BOLD 40 - -#define SC_DP_FRAME_COLOR Color(0,0,0) //( 0x20, 0x40, 0x68 ) - -class OutputImpl -{ - ScDocument* mpDoc; - sal_uInt16 mnTab; - ::std::vector< bool > mbNeedLineCols; - ::std::vector< SCCOL > mnCols; - - ::std::vector< bool > mbNeedLineRows; - ::std::vector< SCROW > mnRows; - - SCCOL mnTabStartCol; - SCROW mnTabStartRow; - SCCOL mnMemberStartCol; - SCROW mnMemberStartRow; - - SCCOL mnDataStartCol; - SCROW mnDataStartRow; - SCCOL mnTabEndCol; - SCROW mnTabEndRow; - -public: - OutputImpl( ScDocument* pDoc, sal_uInt16 nTab, - SCCOL nTabStartCol, - SCROW nTabStartRow, - SCCOL nMemberStartCol, - SCROW nMemberStartRow, - SCCOL nDataStartCol, - SCROW nDataStartRow, - SCCOL nTabEndCol, - SCROW nTabEndRow ); - sal_Bool AddRow( SCROW nRow ); - sal_Bool AddCol( SCCOL nCol ); - - void OutputDataArea(); - void OutputBlockFrame ( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, sal_Bool bHori = false ); - -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx index 43f1da0844c1..a1bbe57dbc0c 100644 --- a/sc/source/filter/excel/excimp8.cxx +++ b/sc/source/filter/excel/excimp8.cxx @@ -82,6 +82,7 @@ #include "attrib.hxx" #include "conditio.hxx" #include "dbcolect.hxx" +#include "globalnames.hxx" #include "editutil.hxx" #include "markdata.hxx" #include "rangenam.hxx" @@ -468,8 +469,6 @@ void ImportExcel8::FilterMode( void ) // then the latter is true.. if( !pExcRoot->pAutoFilterBuffer ) return; - pExcRoot->pAutoFilterBuffer->IncrementActiveAF(); - XclImpAutoFilterData* pData = pExcRoot->pAutoFilterBuffer->GetByTab( GetCurrScTab() ); if( pData ) pData->SetAutoOrAdvanced(); @@ -498,15 +497,14 @@ void ImportExcel8::AutoFilter( void ) -XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange, const String& rName ) : +XclImpAutoFilterData::XclImpAutoFilterData( RootData* pRoot, const ScRange& rRange ) : ExcRoot( pRoot ), pCurrDBData(NULL), nFirstEmpty( 0 ), bActive( false ), bHasConflict( false ), bCriteria( false ), - bAutoOrAdvanced(false), - aFilterName(rName) + bAutoOrAdvanced(false) { aParam.nCol1 = rRange.aStart.Col(); aParam.nRow1 = rRange.aStart.Row(); @@ -750,9 +748,9 @@ void XclImpAutoFilterData::SetExtractPos( const ScAddress& rAddr ) aParam.bDestPers = sal_True; } -void XclImpAutoFilterData::Apply( const sal_Bool bUseUnNamed ) +void XclImpAutoFilterData::Apply() { - CreateScDBData(bUseUnNamed); + CreateScDBData(); if( bActive ) { @@ -774,35 +772,27 @@ void XclImpAutoFilterData::Apply( const sal_Bool bUseUnNamed ) } } -void XclImpAutoFilterData::CreateScDBData( const sal_Bool bUseUnNamed ) +void XclImpAutoFilterData::CreateScDBData() { // Create the ScDBData() object if the AutoFilter is activated // or if we need to create the Advanced Filter. if( bActive || bCriteria) { - ScDBCollection& rColl = pExcRoot->pIR->GetDatabaseRanges(); - pCurrDBData = rColl.GetDBAtArea( Tab(), StartCol(), StartRow(), EndCol(), EndRow() ); - if( !pCurrDBData ) + ScDocument* pDoc = pExcRoot->pIR->GetDocPtr(); + String aNewName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)); + pCurrDBData = new ScDBData(aNewName , Tab(), + StartCol(),StartRow(), EndCol(),EndRow() ); + if(bCriteria) { - AmendAFName(bUseUnNamed); - - pCurrDBData = new ScDBData( aFilterName, Tab(), StartCol(), StartRow(), EndCol(), EndRow() ); - - if( pCurrDBData ) - { - if(bCriteria) - { - EnableRemoveFilter(); + EnableRemoveFilter(); - pCurrDBData->SetQueryParam( aParam ); - pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange); - } - else - pCurrDBData->SetAdvancedQuerySource(NULL); - rColl.Insert( pCurrDBData ); - } + pCurrDBData->SetQueryParam( aParam ); + pCurrDBData->SetAdvancedQuerySource(&aCriteriaRange); } + else + pCurrDBData->SetAdvancedQuerySource(NULL); + pDoc->SetAnonymousDBData(Tab(), pCurrDBData); } } @@ -822,18 +812,7 @@ void XclImpAutoFilterData::EnableRemoveFilter() // inside the advanced range } -void XclImpAutoFilterData::AmendAFName(const sal_Bool bUseUnNamed) -{ - // If-and-only-if we have one AF filter then - // use the Calc "unnamed" range name. Calc - // only supports one in total while Excel - // supports one per sheet. - if( bUseUnNamed && bAutoOrAdvanced ) - aFilterName = ScGlobal::GetRscString(STR_DB_NONAME); -} - -XclImpAutoFilterBuffer::XclImpAutoFilterBuffer() : - nAFActiveCount( 0 ) +XclImpAutoFilterBuffer::XclImpAutoFilterBuffer() { } @@ -843,11 +822,10 @@ XclImpAutoFilterBuffer::~XclImpAutoFilterBuffer() delete pData; } -void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange, - const String& rName ) +void XclImpAutoFilterBuffer::Insert( RootData* pRoot, const ScRange& rRange) { if( !GetByTab( rRange.aStart.Tab() ) ) - Append( new XclImpAutoFilterData( pRoot, rRange, rName ) ); + Append( new XclImpAutoFilterData( pRoot, rRange) ); } void XclImpAutoFilterBuffer::AddAdvancedRange( const ScRange& rRange ) @@ -867,7 +845,7 @@ void XclImpAutoFilterBuffer::AddExtractPos( const ScRange& rRange ) void XclImpAutoFilterBuffer::Apply() { for( XclImpAutoFilterData* pData = _First(); pData; pData = _Next() ) - pData->Apply(UseUnNamed()); + pData->Apply(); } XclImpAutoFilterData* XclImpAutoFilterBuffer::GetByTab( SCTAB nTab ) diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx index ec4c425c1621..d3671b4d1cbe 100644 --- a/sc/source/filter/excel/excrecds.cxx +++ b/sc/source/filter/excel/excrecds.cxx @@ -856,31 +856,18 @@ ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab ) : pFilterInfo( NULL ) , mbAutoFilter (false) { - ScDBCollection& rDBColl = GetDatabaseRanges(); XclExpNameManager& rNameMgr = GetNameManager(); - // search for first DB-range with filter - sal_uInt16 nIndex = 0; sal_Bool bFound = false; sal_Bool bAdvanced = false; - ScDBData* pData = NULL; + ScDBData* pData = rRoot.GetDoc().GetAnonymousDBData(nTab); ScRange aAdvRange; - while( (nIndex < rDBColl.GetCount()) && !bFound ) + if (pData) { - pData = rDBColl[ nIndex ]; - if( pData ) - { - ScRange aRange; - pData->GetArea( aRange ); - bAdvanced = pData->GetAdvancedQuerySource( aAdvRange ); - bFound = (aRange.aStart.Tab() == nTab) && - (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced); - } - if( !bFound ) - nIndex++; + bAdvanced = pData->GetAdvancedQuerySource( aAdvRange ); + bFound = (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced); } - - if( pData && bFound ) + if( bFound ) { ScQueryParam aParam; pData->GetQueryParam( aParam ); diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx index 7acec465c4ac..dab35e4ba7b8 100644 --- a/sc/source/filter/excel/xeformula.cxx +++ b/sc/source/filter/excel/xeformula.cxx @@ -418,7 +418,6 @@ private: void ProcessExternalRangeRef( const XclExpScToken& rTokData ); void ProcessDefinedName( const XclExpScToken& rTokData ); void ProcessExternalName( const XclExpScToken& rTokData ); - void ProcessDatabaseArea( const XclExpScToken& rTokData ); // token vector ----------------------------------------------------------- @@ -1184,7 +1183,6 @@ XclExpScToken XclExpFmlaCompImpl::Factor( XclExpScToken aTokData ) case ocBad: ProcessBad( aTokData ); break; case ocOpen: ProcessParentheses( aTokData ); break; case ocName: ProcessDefinedName( aTokData ); break; - case ocDBArea: ProcessDatabaseArea( aTokData ); break; case ocFalse: case ocTrue: ProcessBoolean( aTokData ); break; case ocDde: ProcessDdeLink( aTokData ); break; @@ -2138,12 +2136,6 @@ void XclExpFmlaCompImpl::ProcessExternalName( const XclExpScToken& rTokData ) AppendErrorToken( EXC_ERR_NAME, rTokData.mnSpaces ); } -void XclExpFmlaCompImpl::ProcessDatabaseArea( const XclExpScToken& rTokData ) -{ - sal_uInt16 nNameIdx = GetNameManager().InsertDBRange( rTokData.mpScToken->GetIndex() ); - AppendNameToken( nNameIdx, rTokData.mnSpaces ); -} - // token vector --------------------------------------------------------------- void XclExpFmlaCompImpl::PushOperandPos( sal_uInt16 nTokPos ) diff --git a/sc/source/filter/excel/xename.cxx b/sc/source/filter/excel/xename.cxx index 846e6229aa10..69377c5d06f4 100644 --- a/sc/source/filter/excel/xename.cxx +++ b/sc/source/filter/excel/xename.cxx @@ -38,6 +38,7 @@ #include "dbcolect.hxx" #include "xehelper.hxx" #include "xelink.hxx" +#include "globalnames.hxx" // for filter manager #include "excrecds.hxx" @@ -138,11 +139,10 @@ public: /** Inserts the Calc name with the passed index and returns the Excel NAME index. */ sal_uInt16 InsertName( SCTAB nTab, sal_uInt16 nScNameIdx ); - /** Inserts the Calc database range with the passed index and returns the Excel NAME index. */ - sal_uInt16 InsertDBRange( sal_uInt16 nScDBRangeIdx ); /** Inserts a new built-in defined name. */ sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab ); + sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange ); /** Inserts a new defined name. Sets another unused name, if rName already exists. */ sal_uInt16 InsertUniqueName( const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab ); /** Returns index of an existing name, or creates a name without definition. */ @@ -179,10 +179,6 @@ private: */ sal_uInt16 FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx ); - /** - * Find the index of a NAME record from Calc's database range index. - */ - sal_uInt16 FindDBNameIdx( sal_uInt16 nScIdx ) const; /** Returns the index of an existing built-in NAME record with the passed definition, otherwise 0. */ sal_uInt16 FindBuiltInNameIdx( const String& rName, const XclTokenArray& rTokArr, bool bDBRange ) const; @@ -203,8 +199,6 @@ private: void CreateBuiltInNames(); /** Creates NAME records for all user-defined names in the document. */ void CreateUserNames(); - /** Creates NAME records for all database ranges in the document. */ - void CreateDatabaseNames(); private: /** @@ -214,8 +208,6 @@ private: */ NamedExpIndexMap maNamedExpMap; XclExpNameList maNameList; /// List of NAME records. - XclExpIndexMap maDBRangeMap; /// Maps Calc database ranges to Excel NAME records. - String maUnnamedDBName; /// Name of the hidden unnamed database range. size_t mnFirstUserIdx; /// List index of first user-defined NAME record. }; @@ -254,9 +246,11 @@ XclExpName::XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn ) : { String aName( XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE ) ); mxName = XclExpStringHelper::CreateString( rRoot, aName, EXC_STR_8BITLENGTH ); + maOrigName = XclTools::GetXclBuiltInDefName( cBuiltIn ); } else { + maOrigName = XclTools::GetBuiltInDefNameXml( cBuiltIn ) ; mxName = XclExpStringHelper::CreateString( rRoot, cBuiltIn, EXC_STR_8BITLENGTH ); ::set_flag( mnFlags, EXC_NAME_BUILTIN ); } @@ -336,10 +330,6 @@ void XclExpName::Save( XclExpStream& rStrm ) void XclExpName::SaveXml( XclExpXmlStream& rStrm ) { - // For some reason, AutoFilter creates exportable names where maOrigName=="" - if( maOrigName.Len() == 0 ) - return; - sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream(); rWorkbook->startElement( XML_definedName, // OOXTODO: XML_comment, "", @@ -383,7 +373,6 @@ void XclExpName::WriteBody( XclExpStream& rStrm ) XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot& rRoot ) : XclExpRoot( rRoot ), - maUnnamedDBName( ScGlobal::GetRscString( STR_DB_NONAME ) ), mnFirstUserIdx( 0 ) { } @@ -393,7 +382,6 @@ void XclExpNameManagerImpl::Initialize() CreateBuiltInNames(); mnFirstUserIdx = maNameList.GetSize(); CreateUserNames(); - CreateDatabaseNames(); } sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx ) @@ -413,13 +401,15 @@ sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx return nNameIdx; } -sal_uInt16 XclExpNameManagerImpl::InsertDBRange( sal_uInt16 nScDBRangeIdx ) +sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange ) { - sal_uInt16 nNameIdx = FindDBNameIdx( nScDBRangeIdx ); - if( nNameIdx == 0 ) - if( const ScDBData* pDBData = GetDatabaseRanges().FindIndex( nScDBRangeIdx ) ) - nNameIdx = CreateName( *pDBData ); - return nNameIdx; + XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) ); + xName->SetTokenArray( xTokArr ); + xName->SetLocalTab( aRange.aStart.Tab() ); + String sSymbol; + aRange.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ScAddress::Details( ::formula::FormulaGrammar::CONV_XL_A1 ) ); + xName->SetSymbol( sSymbol ); + return Append( xName ); } sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab ) @@ -515,18 +505,12 @@ sal_uInt16 XclExpNameManagerImpl::FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScI return (itr == maNamedExpMap.end()) ? 0 : itr->second; } -sal_uInt16 XclExpNameManagerImpl::FindDBNameIdx( sal_uInt16 nScIdx ) const -{ - XclExpIndexMap::const_iterator aIt = maDBRangeMap.find( nScIdx ); - return (aIt == maDBRangeMap.end()) ? 0 : aIt->second; -} - sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx( const String& rName, const XclTokenArray& rTokArr, bool bDBRange ) const { /* Get built-in index from the name. Special case: the database range 'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */ - sal_Unicode cBuiltIn = (bDBRange && (rName == maUnnamedDBName)) ? + sal_Unicode cBuiltIn = (bDBRange && (rName == String(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)))) ? EXC_BUILTIN_FILTERDATABASE : XclTools::GetBuiltInDefNameIndex( rName ); if( cBuiltIn < EXC_BUILTIN_UNKNOWN ) @@ -622,29 +606,6 @@ sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRa return nNameIdx; } -sal_uInt16 XclExpNameManagerImpl::CreateName( const ScDBData& rDBData ) -{ - // get name and source range, and create the definition formula - const String& rName = rDBData.GetName(); - ScRange aRange; - rDBData.GetArea( aRange ); - XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, aRange ); - - // try to use an existing built-in name - sal_uInt16 nNameIdx = FindBuiltInNameIdx( rName, *xTokArr, true ); - if( nNameIdx == 0 ) - { - // insert a new name into the list - XclExpNameRef xName( new XclExpName( GetRoot(), GetUnusedName( rName ) ) ); - xName->SetTokenArray( xTokArr ); - nNameIdx = Append( xName ); - } - - // store the index of the NAME record in the lookup map - maDBRangeMap[ rDBData.GetIndex() ] = nNameIdx; - return nNameIdx; -} - void XclExpNameManagerImpl::CreateBuiltInNames() { ScDocument& rDoc = GetDoc(); @@ -718,19 +679,6 @@ void XclExpNameManagerImpl::CreateUserNames() } } -void XclExpNameManagerImpl::CreateDatabaseNames() -{ - const ScDBCollection& rDBRanges = GetDatabaseRanges(); - for( sal_uInt16 nDBIdx = 0, nDBCount = rDBRanges.GetCount(); nDBIdx < nDBCount; ++nDBIdx ) - { - const ScDBData* pDBData = rDBRanges[ nDBIdx ]; - DBG_ASSERT( pDBData, "XclExpNameManagerImpl::CreateDatabaseNames - missing database range" ); - // skip hidden "unnamed" range - if( pDBData && (pDBData->GetName() != maUnnamedDBName) && !FindDBNameIdx( pDBData->GetIndex() ) ) - CreateName( *pDBData ); - } -} - // ---------------------------------------------------------------------------- XclExpNameManager::XclExpNameManager( const XclExpRoot& rRoot ) : @@ -753,15 +701,10 @@ sal_uInt16 XclExpNameManager::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx ) return mxImpl->InsertName( nTab, nScNameIdx ); } -sal_uInt16 XclExpNameManager::InsertDBRange( sal_uInt16 nScDBRangeIdx ) -{ - return mxImpl->InsertDBRange( nScDBRangeIdx ); -} - sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRange& rRange ) { XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRange ); - return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange.aStart.Tab() ); + return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange ); } sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRangeList& rRangeList ) diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx index 8139a25b8b08..be8557eac430 100644 --- a/sc/source/filter/excel/xepivot.cxx +++ b/sc/source/filter/excel/xepivot.cxx @@ -538,7 +538,7 @@ void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScD if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() ) { // get the string collection with original source elements - ScDPCache* pCache = pSrcDesc->CreateCache(); + const ScDPCache* pCache = pSrcDesc->CreateCache(); if (!pCache) return; diff --git a/sc/source/filter/excel/xiname.cxx b/sc/source/filter/excel/xiname.cxx index eeba8e356f9b..15bf618d8530 100644 --- a/sc/source/filter/excel/xiname.cxx +++ b/sc/source/filter/excel/xiname.cxx @@ -186,7 +186,7 @@ XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) : switch( mcBuiltIn ) { case EXC_BUILTIN_FILTERDATABASE: - GetFilterManager().Insert( &GetOldRoot(), aRange, maScName ); + GetFilterManager().Insert( &GetOldRoot(), aRange); break; case EXC_BUILTIN_CRITERIA: GetFilterManager().AddAdvancedRange( aRange ); diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx index 0bb694d2b29e..a26b132f198d 100644 --- a/sc/source/filter/excel/xipivot.cxx +++ b/sc/source/filter/excel/xipivot.cxx @@ -1010,8 +1010,12 @@ void XclImpPTField::ConvertPageField( ScDPSaveData& rSaveData ) const DBG_ASSERT( maFieldInfo.mnAxes & EXC_SXVD_AXIS_PAGE, "XclImpPTField::ConvertPageField - no page field" ); if( ScDPSaveDimension* pSaveDim = ConvertRCPField( rSaveData ) ) { - const rtl::OUString aName = *GetItemName( maPageInfo.mnSelItem ); - pSaveDim->SetCurrentPage( &aName ); + const String* pName = GetItemName( maPageInfo.mnSelItem ); + if (pName) + { + const OUString aName(*pName); + pSaveDim->SetCurrentPage(&aName); + } } } diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx index 062413de46f8..aba8b38fc340 100644 --- a/sc/source/filter/excel/xltools.cxx +++ b/sc/source/filter/excel/xltools.cxx @@ -469,6 +469,8 @@ String XclTools::GetXclFontName( const String& rFontName ) const String XclTools::maDefNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) ); +const String XclTools::maDefNamePrefixXml ( RTL_CONSTASCII_USTRINGPARAM( "_xlnm." ) ); + static const sal_Char* const ppcDefNames[] = { "Consolidate_Area", @@ -504,6 +506,11 @@ String XclTools::GetBuiltInDefName( sal_Unicode cBuiltIn ) return String( maDefNamePrefix ).Append( GetXclBuiltInDefName( cBuiltIn ) ); } +String XclTools::GetBuiltInDefNameXml( sal_Unicode cBuiltIn ) +{ + return String( maDefNamePrefixXml ).Append( GetXclBuiltInDefName( cBuiltIn ) ); +} + sal_Unicode XclTools::GetBuiltInDefNameIndex( const String& rDefName ) { xub_StrLen nPrefixLen = maDefNamePrefix.Len(); diff --git a/sc/source/filter/inc/excimp8.hxx b/sc/source/filter/inc/excimp8.hxx index 65adb65b16e6..923bec596d88 100644 --- a/sc/source/filter/inc/excimp8.hxx +++ b/sc/source/filter/inc/excimp8.hxx @@ -103,7 +103,6 @@ private: sal_Bool bCriteria; sal_Bool bAutoOrAdvanced; ScRange aCriteriaRange; - String aFilterName; void CreateFromDouble( String& rStr, double fVal ); void SetCellAttribs(); @@ -114,8 +113,7 @@ protected: public: XclImpAutoFilterData( RootData* pRoot, - const ScRange& rRange, - const String& rName ); + const ScRange& rRange); inline bool IsActive() const { return bActive; } inline bool IsFiltered() const { return bAutoOrAdvanced; } @@ -131,8 +129,8 @@ public: void SetAdvancedRange( const ScRange* pRange ); void SetExtractPos( const ScAddress& rAddr ); inline void SetAutoOrAdvanced() { bAutoOrAdvanced = sal_True; } - void Apply( const sal_Bool bUseUnNamed = false ); - void CreateScDBData( const sal_Bool bUseUnNamed ); + void Apply(); + void CreateScDBData(); void EnableRemoveFilter(); }; @@ -142,8 +140,6 @@ class XclImpAutoFilterBuffer : private List private: using List::Insert; - sal_uInt16 nAFActiveCount; - inline XclImpAutoFilterData* _First() { return (XclImpAutoFilterData*) List::First(); } inline XclImpAutoFilterData* _Next() { return (XclImpAutoFilterData*) List::Next(); } @@ -154,15 +150,12 @@ public: XclImpAutoFilterBuffer(); virtual ~XclImpAutoFilterBuffer(); - void Insert( RootData* pRoot, const ScRange& rRange, - const String& rName ); + void Insert( RootData* pRoot, const ScRange& rRange); void AddAdvancedRange( const ScRange& rRange ); void AddExtractPos( const ScRange& rRange ); void Apply(); XclImpAutoFilterData* GetByTab( SCTAB nTab ); - inline void IncrementActiveAF() { nAFActiveCount++; } - inline sal_Bool UseUnNamed() { return nAFActiveCount == 1; } }; #endif diff --git a/sc/source/filter/inc/xltools.hxx b/sc/source/filter/inc/xltools.hxx index bfe284f198da..e9e306e2f1c6 100644 --- a/sc/source/filter/inc/xltools.hxx +++ b/sc/source/filter/inc/xltools.hxx @@ -187,6 +187,10 @@ public: @descr Adds a prefix to the representation returned by GetXclBuiltInDefName(). @param cBuiltIn Excel index of the built-in name. */ static String GetBuiltInDefName( sal_Unicode cBuiltIn ); + /** Returns the Excel built-in name with OOXML prefix + @descr Adds the "_xlnm." prefix to the representation returned by GetXclBuiltInDefName() + @param cBuiltIn Excel index of the built in name.*/ + static String GetBuiltInDefNameXml( sal_Unicode cBuiltIn ); /** Returns the Excel built-in name index of the passed defined name from Calc. @descr Ignores any characters following a valid representation of a built-in name. @param pcBuiltIn (out-param) If not 0, the index of the built-in name will be returned here. @@ -245,6 +249,7 @@ public: // ------------------------------------------------------------------------ private: static const String maDefNamePrefix; /// Prefix for built-in defined names. + static const String maDefNamePrefixXml; /// Prefix for built-in defined names for OOX static const String maStyleNamePrefix1; /// Prefix for built-in cell style names. static const String maStyleNamePrefix2; /// Prefix for built-in cell style names from OOX filter. static const String maCFStyleNamePrefix1; /// Prefix for cond. formatting style names. diff --git a/sc/source/filter/xml/XMLExportDataPilot.cxx b/sc/source/filter/xml/XMLExportDataPilot.cxx index 968c37f0e1b5..d0071a9428b2 100644 --- a/sc/source/filter/xml/XMLExportDataPilot.cxx +++ b/sc/source/filter/xml/XMLExportDataPilot.cxx @@ -858,24 +858,24 @@ void ScXMLExportDataPilot::WriteDataPilots(const uno::Reference <sheet::XSpreads case sheet::DataImportMode_NONE : break; case sheet::DataImportMode_QUERY : { - rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName)); - rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, rtl::OUString(pImpSource->aObject)); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_QUERY_NAME, pImpSource->aObject); SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_QUERY, sal_True, sal_True); rExport.CheckAttrList(); } break; case sheet::DataImportMode_TABLE : { - rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName)); - rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, rtl::OUString(pImpSource->aObject)); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_TABLE_NAME, pImpSource->aObject); SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_TABLE, sal_True, sal_True); rExport.CheckAttrList(); } break; case sheet::DataImportMode_SQL : { - rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, rtl::OUString(pImpSource->aDBName)); - rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, rtl::OUString(pImpSource->aObject)); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_DATABASE_NAME, pImpSource->aDBName); + rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_SQL_STATEMENT, pImpSource->aObject); if (!pImpSource->bNative) rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_PARSE_SQL_STATEMENT, XML_TRUE); SvXMLElementExport aElemID(rExport, XML_NAMESPACE_TABLE, XML_DATABASE_SOURCE_SQL, sal_True, sal_True); diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index 06214774a91e..a7755b840bca 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -1089,7 +1089,7 @@ void ScXMLTableRowCellContext::EndElement() pCellObj->SetFormulaWithGrammar( pOUFormula->first, pOUFormula->second, eGrammar); if (bFormulaTextResult && pOUTextValue && pOUTextValue->getLength()) pCellObj->SetFormulaResultString( *pOUTextValue); - else if (fValue != 0.0) + else pCellObj->SetFormulaResultDouble( fValue); } } diff --git a/sc/source/ui/attrdlg/scabstdlg.cxx b/sc/source/ui/attrdlg/scabstdlg.cxx index 7ab625e03f61..db85484e6228 100644 --- a/sc/source/ui/attrdlg/scabstdlg.cxx +++ b/sc/source/ui/attrdlg/scabstdlg.cxx @@ -48,7 +48,8 @@ ScAbstractDialogFactory* ScAbstractDialogFactory::Create() OUStringBuffer aStrBuf; aStrBuf.appendAscii( SVLIBRARY("scui") ); - if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, aStrBuf.makeStringAndClear() ) ) + if ( aDialogLibrary.is() || aDialogLibrary.loadRelative( &thisModule, aStrBuf.makeStringAndClear(), + SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY ) ) fp = ( ScAbstractDialogFactory* (__LOADONCALLAPI*)() ) aDialogLibrary.getFunctionSymbol( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreateDialogFactory")) ); if ( fp ) diff --git a/sc/source/ui/cctrl/dpcontrol.cxx b/sc/source/ui/cctrl/dpcontrol.cxx index 2a5d415410dc..380cdf9cfeef 100644 --- a/sc/source/ui/cctrl/dpcontrol.cxx +++ b/sc/source/ui/cctrl/dpcontrol.cxx @@ -1032,6 +1032,7 @@ ScDPFieldPopupWindow::ScDPFieldPopupWindow(Window* pParent, ScDocument* pDoc) : maChkToggleAll.SetPosSizePixel(aPos, aSize); maChkToggleAll.SetFont(getLabelFont()); maChkToggleAll.SetText(ScRscStrLoader(RID_POPUP_FILTER, STR_BTN_TOGGLE_ALL).GetString()); + maChkToggleAll.SetTextColor(rStyle.GetMenuTextColor()); maChkToggleAll.SetControlBackground(rStyle.GetMenuColor()); maChkToggleAll.SetClickHdl( LINK(this, ScDPFieldPopupWindow, TriStateHdl) ); maChkToggleAll.Show(); diff --git a/sc/source/ui/dbgui/dapidata.cxx b/sc/source/ui/dbgui/dapidata.cxx index 63d11e1141ae..c73d701a6eb9 100644 --- a/sc/source/ui/dbgui/dapidata.cxx +++ b/sc/source/ui/dbgui/dapidata.cxx @@ -130,7 +130,7 @@ void ScDataPilotDatabaseDlg::GetValues( ScImportSourceDesc& rDesc ) rDesc.aDBName = aLbDatabase.GetSelectEntry(); rDesc.aObject = aCbObject.GetText(); - if ( !rDesc.aDBName.Len() || !rDesc.aObject.Len() ) + if (rDesc.aDBName.isEmpty() || rDesc.aObject.isEmpty()) rDesc.nType = sheet::DataImportMode_NONE; else if ( nSelect == DP_TYPELIST_TABLE ) rDesc.nType = sheet::DataImportMode_TABLE; diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index e9376dd15668..c9d600f34d9c 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -4344,17 +4344,14 @@ sal_Bool ScDocFunc::MergeCells( const ScCellMergeOption& rOption, sal_Bool bCont for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() ) bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0); - if (bNeedContents || bHasNotes || rOption.mbCenter) + if (!pUndoDoc) { - if (!pUndoDoc) - { - pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); - pUndoDoc->InitUndo(pDoc, nTab1, nTab2); - } - // note captions are collected by drawing undo - pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, - IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc ); + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo(pDoc, nTab1, nTab2); } + // note captions are collected by drawing undo + pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, + IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc ); if( bHasNotes ) pDoc->BeginDrawUndo(); } diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx index 6fabe3684d6c..060969fc2c63 100644 --- a/sc/source/ui/docshell/impex.cxx +++ b/sc/source/ui/docshell/impex.cxx @@ -2086,7 +2086,7 @@ ScFormatFilterPlugin &ScFormatFilter::Get() ::rtl::OUString sFilterLib(RTL_CONSTASCII_USTRINGPARAM(SVLIBRARY("scfilt"))); static ::osl::Module aModule; - bool bLoaded = aModule.loadRelative(&thisModule, sFilterLib); + bool bLoaded = aModule.loadRelative(&thisModule, sFilterLib, SAL_LOADMODULE_GLOBAL | SAL_LOADMODULE_LAZY); if (!bLoaded) bLoaded = aModule.load(sFilterLib); if (bLoaded) diff --git a/sc/source/ui/vba/vbaworksheet.cxx b/sc/source/ui/vba/vbaworksheet.cxx index 87fb2e9a07e3..4152fb0fd412 100644 --- a/sc/source/ui/vba/vbaworksheet.cxx +++ b/sc/source/ui/vba/vbaworksheet.cxx @@ -108,6 +108,8 @@ #include "vbasheetobjects.hxx" #include "viewuno.hxx" +#include "attrib.hxx" + #define STANDARDWIDTH 2267 #define STANDARDHEIGHT 427 #define DOESNOTEXIST -1 @@ -444,38 +446,39 @@ ScVbaWorksheet::setEnableSelection( sal_Int32 nSelection ) throw (uno::RuntimeEx } -uno::Reference< beans::XPropertySet > ScVbaWorksheet::getFirstDBRangeProperties() throw (uno::RuntimeException) -{ - uno::Reference< beans::XPropertySet > xModelProps( mxModel, uno::UNO_QUERY_THROW ); - uno::Reference< container::XIndexAccess > xDBRangesIA( xModelProps->getPropertyValue( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DatabaseRanges" ) ) ), uno::UNO_QUERY_THROW ); - - for( sal_Int32 nIndex = 0, nCount = xDBRangesIA->getCount(); nIndex < nCount; ++nIndex ) - { - uno::Reference< sheet::XCellRangeReferrer > xDBRange( xDBRangesIA->getByIndex( nIndex ), uno::UNO_QUERY_THROW ); - // check if the database area is on this sheet - uno::Reference< sheet::XCellRangeAddressable > xRangeAddr( xDBRange->getReferredCells(), uno::UNO_QUERY_THROW ); - if( getSheetID() == xRangeAddr->getRangeAddress().Sheet ) - return uno::Reference< beans::XPropertySet >( xDBRange, uno::UNO_QUERY_THROW ); - } - return uno::Reference< beans::XPropertySet >(); -} - sal_Bool SAL_CALL ScVbaWorksheet::getAutoFilterMode() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xDBRangeProps = getFirstDBRangeProperties(); - sal_Bool bAutoFilterMode = false; - return - xDBRangeProps.is() && - (xDBRangeProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AutoFilter" ) ) ) >>= bAutoFilterMode) && - bAutoFilterMode; + uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); + ScDocument* pDoc = excel::getDocShell( xModel )->GetDocument(); + ScDBData* pDBData = pDoc->GetAnonymousDBData(getSheetID()); + if (pDBData) + return pDBData->HasAutoFilter(); + return false; } void SAL_CALL ScVbaWorksheet::setAutoFilterMode( sal_Bool bAutoFilterMode ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xDBRangeProps = getFirstDBRangeProperties(); - if( xDBRangeProps.is() ) - xDBRangeProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AutoFilter" ) ), uno::Any( bAutoFilterMode ) ); + uno::Reference< frame::XModel > xModel( getModel(), uno::UNO_QUERY_THROW ); + ScDocShell* pDocShell = excel::getDocShell( xModel ); + ScDocument* pDoc = pDocShell->GetDocument(); + ScDBData* pDBData = pDoc->GetAnonymousDBData(getSheetID()); + if (pDBData) + { + pDBData->SetAutoFilter(bAutoFilterMode); + ScRange aRange; + pDBData->GetArea(aRange); + if (bAutoFilterMode && pDoc) + pDoc->ApplyFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), SC_MF_AUTO ); + else if (!bAutoFilterMode && pDoc) + pDoc->RemoveFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), SC_MF_AUTO ); + ScRange aPaintRange(aRange.aStart, aRange.aEnd); + aPaintRange.aEnd.SetRow(aPaintRange.aStart.Row()); + pDocShell->PostPaint(aPaintRange, PAINT_GRID); + } } uno::Reference< excel::XRange > diff --git a/sc/source/ui/vba/vbaworksheet.hxx b/sc/source/ui/vba/vbaworksheet.hxx index 2736083a8561..95c933e0b7c0 100644 --- a/sc/source/ui/vba/vbaworksheet.hxx +++ b/sc/source/ui/vba/vbaworksheet.hxx @@ -72,8 +72,6 @@ class ScVbaWorksheet : public WorksheetImpl_BASE css::uno::Reference< css::container::XNameAccess > getFormControls(); css::uno::Any getControlShape( const rtl::OUString& sName ); - css::uno::Reference< css::beans::XPropertySet > getFirstDBRangeProperties() throw (css::uno::RuntimeException); - protected: ScVbaWorksheet( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext ); diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index d2e185d05b47..e8e5baafb1f7 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -72,6 +72,8 @@ #include "dbdocfun.hxx" #include "dpoutput.hxx" #include "dptabsrc.hxx" +#include "dpshttab.hxx" +#include "dpsdbtab.hxx" #include "editable.hxx" #include "docpool.hxx" #include "patattr.hxx" @@ -697,13 +699,47 @@ void ScDBFunc::RecalcPivotTable() ScDocShell* pDocSh = GetViewData()->GetDocShell(); ScDocument* pDoc = GetViewData()->GetDocument(); - // old pivot not used any more - + ScDPCollection* pDPs = pDoc->GetDPCollection(); ScDPObject* pDPObj = pDoc->GetDPAtCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); - if ( pDPObj ) + if (pDPs && pDPObj) { + // Remove existing data cache for the data that this datapilot uses, + // to force re-build data cache. + if (pDPObj->IsSheetData()) + { + // data source is internal sheet. + const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc(); + if (!pDesc) + { + ErrorMessage(STR_PIVOT_NOTFOUND); + return; + } + if (pDesc->HasRangeName()) + { + ScDPCollection::NameCaches& rCaches = pDPs->GetNameCaches(); + rCaches.removeCache(pDesc->GetRangeName()); + } + else + { + ScDPCollection::SheetCaches& rCaches = pDPs->GetSheetCaches(); + rCaches.removeCache(pDesc->GetSourceRange()); + } + } + else if (pDPObj->IsImportData()) + { + // data source is external database. + const ScImportSourceDesc* pDesc = pDPObj->GetImportSourceDesc(); + if (!pDesc) + { + ErrorMessage(STR_PIVOT_NOTFOUND); + return; + } + ScDPCollection::DBCaches& rCaches = pDPs->GetDBCaches(); + rCaches.removeCache(pDesc->GetCommandType(), pDesc->aDBName, pDesc->aObject); + } + ScDBDocFunc aFunc( *pDocSh ); aFunc.DataPilotUpdate( pDPObj, pDPObj, true, false ); CursorPosChanged(); // shells may be switched |