1. mst
  2. ooo340

Commits

Eike Rathke [er]  committed 03d5e8c

calcdatatables: create DataTable on selection

  • Participants
  • Parent commits 7263080
  • Branches default

Comments (0)

Files changed (10)

File offapi/com/sun/star/sheet/XDataTables.idl

View file
                 not exist.
      */
     com::sun::star::sheet::XDataTable getDataTableByDatabaseRangeName( [in] string aName )
+            raises( com::sun::star::container::NoSuchElementException );
+
+    //-------------------------------------------------------------------------
+
+    /** adds a new DataTable by cell range address and returns it.
+
+        If the specified cell range is within an already existing 
+        DataTable, that DataTable is returned instead of creating a new 
+        DataTable.
+
+        @throws <type scope="com::sun::star::lang">IndexOutOfBoundsException</type>
+                if the range passed is out of bounds.
+
+        @throws <type scope="com::sun::star::container">NoSuchElementException</type>
+                if there is already a DataTable intersecting or within 
+                the specified cell range.
+     */
+    com::sun::star::sheet::XDataTable addNewByRange(
+            [in] com::sun::star::table::CellRangeAddress aRange )
             raises( com::sun::star::lang::IndexOutOfBoundsException,
                     com::sun::star::container::NoSuchElementException );
 

File sc/inc/address.hxx

View file
 #define MAXROW      W16MAXROW
 #endif
 
-#define VALIDCOL(nCol)                  (ValidCol(nCol))
-#define VALIDROW(nRow)                  (ValidRow(nRow))
-#define VALIDTAB(nTab)                  (ValidTab(nTab))
-#define VALIDCOLROW(nCol,nRow)          (ValidColRow(nCol,nRow))
-#define VALIDCOLROWTAB(nCol,nRow,nTab)  (ValidColRowTab(nCol,nRow,nTab))
-
 // === old stuff defines end =================================================
 
-inline bool ValidCol( SCCOL nCol )
-{
-    return static_cast<SCCOL>(0) <= nCol && nCol <= MAXCOL;
-}
-
-inline bool ValidRow( SCROW nRow )
-{
-    return static_cast<SCROW>(0) <= nRow && nRow <= MAXROW;
-}
-
-inline bool ValidTab( SCTAB nTab )
-{
-    return static_cast<SCTAB>(0) <= nTab && nTab <= MAXTAB;
-}
-
-inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
-{
-    return static_cast<SCTAB>(0) <= nTab && nTab <= nMaxTab;
-}
-
-inline bool ValidColRow( SCCOL nCol, SCROW nRow )
-{
-    return ValidCol( nCol) && ValidRow( nRow);
-}
-
-inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab )
-{
-    return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab);
-}
-
-inline SCCOL SanitizeCol( SCCOL nCol )
-{
-    return nCol < 0 ? 0 : (nCol > MAXCOL ? MAXCOL : nCol);
-}
-
-inline SCROW SanitizeRow( SCROW nRow )
-{
-    return nRow < 0 ? 0 : (nRow > MAXROW ? MAXROW : nRow);
-}
-
-inline SCTAB SanitizeTab( SCTAB nTab )
-{
-    return nTab < 0 ? 0 : (nTab > MAXTAB ? MAXTAB : nTab);
-}
-
-inline SCTAB SanitizeTab( SCTAB nTab, SCTAB nMaxTab )
-{
-    return nTab < 0 ? 0 : (nTab > nMaxTab ? nMaxTab : nTab);
-}
-
 // === ScAddress =============================================================
 
 // The old cell address is combined in one UINT32:
 /// get column number of A..IV... string
 bool AlphaToCol( SCCOL& rCol, const String& rStr);
 
+
+// === Valid Col/Row/Tab =====================================================
+
+inline bool ValidCol( SCCOL nCol )
+{
+    return static_cast<SCCOL>(0) <= nCol && nCol <= MAXCOL;
+}
+
+inline bool ValidRow( SCROW nRow )
+{
+    return static_cast<SCROW>(0) <= nRow && nRow <= MAXROW;
+}
+
+inline bool ValidTab( SCTAB nTab )
+{
+    return static_cast<SCTAB>(0) <= nTab && nTab <= MAXTAB;
+}
+
+inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab )
+{
+    return static_cast<SCTAB>(0) <= nTab && nTab <= nMaxTab;
+}
+
+inline bool ValidColRow( SCCOL nCol, SCROW nRow )
+{
+    return ValidCol( nCol) && ValidRow( nRow);
+}
+
+inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab )
+{
+    return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab);
+}
+
+inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab, SCTAB nMaxTab )
+{
+    return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab, nMaxTab);
+}
+
+inline bool ValidRange( const ScRange& rRange, SCTAB nMaxTab )
+{
+    return ValidCol( rRange.aStart.Col()) && ValidRow( rRange.aStart.Row()) && 
+        ValidTab( rRange.aStart.Tab(), nMaxTab) &&
+        ValidCol( rRange.aEnd.Col()) && ValidRow( rRange.aEnd.Row()) && 
+        ValidTab( rRange.aEnd.Tab(), nMaxTab);
+}
+
+inline SCCOL SanitizeCol( SCCOL nCol )
+{
+    return nCol < 0 ? 0 : (nCol > MAXCOL ? MAXCOL : nCol);
+}
+
+inline SCROW SanitizeRow( SCROW nRow )
+{
+    return nRow < 0 ? 0 : (nRow > MAXROW ? MAXROW : nRow);
+}
+
+inline SCTAB SanitizeTab( SCTAB nTab )
+{
+    return nTab < 0 ? 0 : (nTab > MAXTAB ? MAXTAB : nTab);
+}
+
+inline SCTAB SanitizeTab( SCTAB nTab, SCTAB nMaxTab )
+{
+    return nTab < 0 ? 0 : (nTab > nMaxTab ? nMaxTab : nTab);
+}
+
+// === old stuff defines =====================================================
+
+#define VALIDCOL(nCol)                  (ValidCol(nCol))
+#define VALIDROW(nRow)                  (ValidRow(nRow))
+#define VALIDTAB(nTab)                  (ValidTab(nTab))
+#define VALIDCOLROW(nCol,nRow)          (ValidColRow(nCol,nRow))
+#define VALIDCOLROWTAB(nCol,nRow,nTab)  (ValidColRowTab(nCol,nRow,nTab))
+
+// === old stuff defines end =================================================
+
 #endif // SC_ADDRESS_HXX
 

File sc/inc/datatablestyle.hxx

View file
         const String&               GetStyleSheetName( DataTableStyleType eType ) const;
         SfxStyleSheetBase*          GetStyleSheet( DataTableStyleType eType ) const;
 
+        /** Set prefix to be used for style names to form 
+            "Prefix_00_whole_table" and the like.
+         */
+        void                        SetStyleSheetNamePrefix( const String& rPrefix ) { maStyleSheetNamePrefix = rPrefix; }
+
         /** Create all necessary styles if they aren't set already and don't 
             exist already and set them.
 
             entries.
 
             @param rPrefix
-                   Prefix to be used for style names to form "Prefix_...".
+                   Prefix to be used for style names to form "Prefix_..." if 
+                   prefix isn't set yet. Does not override an already set prefix.
 
             @returns Vector of newly created style names with offsets == DataTableStyleType.
          */
             InitStyles()
 
             @param rPrefix
-                   Prefix to be used for style names to form "Prefix_...".
+                   Prefix to be used for style names to form "Prefix_..." if 
+                   prefix isn't set yet. Does not override an already set prefix.
          */
         void                        InitDisplayFeatures( const String& rPrefix );
 
                                     /// Find all that are entirely covered by rRange.
         void                        FindInRange( ScDataTableMap & o_rDataTables, const ScRange& rRange ) const;
 
+                                    /// Find all that intersect rRange.
+        void                        FindIntersecting( ScDataTableMap & o_rDataTables, const ScRange& rRange ) const;
+
         /** Find all that contain nRow entirely within nStartCol and nEndCol, 
             or where inserting cells at nRow would result in an expanded 
             DataTable. Additionally test whether cells can be inserted 

File sc/inc/datatableuno.hxx

View file
 
     // XDataTables
     virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDataTable > SAL_CALL getDataTableByPosition( const ::com::sun::star::table::CellAddress& aPosition ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
-    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDataTable > SAL_CALL getDataTableByDatabaseRangeName( const ::rtl::OUString& aName ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDataTable > SAL_CALL getDataTableByDatabaseRangeName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDataTable > SAL_CALL addNewByRange( const ::com::sun::star::table::CellRangeAddress& aRange ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException);
 
     // XEnumerationAccess
     virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createEnumeration(  ) throw (::com::sun::star::uno::RuntimeException);

File sc/inc/globstr.hrc

View file
 #define STR_UNDO_SET_MULTI_TAB_BG_COLOR 439
 
 #define STR_SHIFT_CELLS_TABLE       440
+#define STR_DATATABLE_NAMEPREFIX    441
 
-#define STR_COUNT                   441
+#define STR_COUNT                   442
 
 #endif
 

File sc/source/core/data/datatablestyle.cxx

View file
 }
 
 
+void ScDataTableFormatList::FindIntersecting( ScDataTableMap & o_rDataTables, const ScRange& rRange ) const
+{
+    USHORT nCount = Count();
+    for (USHORT i=0; i < nCount; i++)
+    {
+        if ((*this)[i]->GetTableRange().Intersects( rRange))
+        {
+            sal_uInt32 nKey = (*this)[i]->GetKey();
+            o_rDataTables.insert( ScDataTableMap::value_type( nKey, ScDataTableMapEntry( nKey, false)));
+        }
+    }
+}
+
+
 bool ScDataTableFormatList::FindInsertWithRow( ::std::vector<sal_uInt32> & o_rDataTables,
         SCCOL nStartCol, SCCOL nEndCol, SCROW nRow, const ::std::vector<SCTAB> & rTabs,
         bool bTestOnly ) const

File sc/source/ui/docshell/docfunc.cxx

View file
 #include "clipparam.hxx"
 #include "externalrefmgr.hxx"
 #include "datatablestyle.hxx"
+#include "dbcolect.hxx"
 
 #include <memory>
 #include <basic/basmgr.hxx>
 }
 
 
+sal_uInt32 ScDocFunc::CreateDataTable( const ScRange& rRange, bool bRecord, bool bApi )
+{
+    sal_uInt32 nKey = 0;
+    ScDocument* pDoc = rDocShell.GetDocument();
+    const ScDataTableFormatList* pList = pDoc->GetDataTableFormatList();
+    if (pList)
+    {
+        ScDataTableMap aDataTableMap;
+        pList->FindIntersecting( aDataTableMap, rRange);
+        if (!aDataTableMap.empty())
+        {
+            // More than one DataTable are ambigious anyway.
+            if (aDataTableMap.size() == 1)
+            {
+                nKey = (*aDataTableMap.begin()).first;
+                const ScDataTableFormat* pDTab = pDoc->GetDataTableFormat( nKey);
+                if (!pDTab || !pDTab->GetTableRange().In( rRange))
+                    nKey = 0;
+            }
+            return nKey;
+        }
+    }
+
+    if (bRecord && !pDoc->IsUndoEnabled())
+        bRecord = false;
+
+    DBG_ASSERT( !bRecord, "ScDocFunc::CreateDataTable: Undo not implemented");
+
+    ScDocShellModificator aModificator( rDocShell );
+
+    // Insert new DataTable.
+    ScDataTableFormat aDTab( 0, pDoc);
+    aDTab.SetTableRange( rRange);
+    bool bHeaderRowFlag = true;
+    aDTab.SetHeaderRowFlag( bHeaderRowFlag);
+    nKey = pDoc->AddDataTableFormat( aDTab);
+
+    // Apply attribute.
+    ScPatternAttr aPattern( pDoc->GetPool());
+    aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_DATATABLE, nKey));
+    ScMarkData aMark;
+    aMark.SelectTable( rRange.aStart.Tab(), true);
+    aMark.SetMarkArea( rRange);
+    if (!ApplyAttributes( aMark, aPattern, bRecord, bApi))
+        bHeaderRowFlag = false;     // no attribute => no autofilter either
+
+    // Apply AutoFilter buttons.
+    if (bHeaderRowFlag)
+    {
+        for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+        {
+            sal_uInt16 nFlag = ((ScMergeFlagAttr*) pDoc->GetAttr( nCol, 
+                        rRange.aStart.Row(), rRange.aStart.Tab(), 
+                        ATTR_MERGE_FLAG))->GetValue();
+            pDoc->ApplyAttr( nCol, rRange.aStart.Row(), rRange.aStart.Tab(), 
+                    ScMergeFlagAttr( nFlag | SC_MF_AUTO));
+        }
+    }
+
+    // Insert associated DB range.
+    ScDBCollection* pDBCol = pDoc->GetDBCollection();
+    String aRangeName;
+    sal_Int32 nSuffix = 1;
+    sal_uInt16 nFoundAt;
+    do
+    {
+        aRangeName = ScGlobal::GetRscString( STR_DATATABLE_NAMEPREFIX);
+        aRangeName += String::CreateFromInt32( nSuffix++);
+    } while (pDBCol->SearchName( aRangeName, nFoundAt));
+    ScDBData* pDBData = new ScDBData( aRangeName, rRange.aStart.Tab(), 
+            rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), 
+            rRange.aEnd.Row(), true, bHeaderRowFlag);
+    pDBData->SetDataTable( nKey);
+    pDBData->SetAutoFilter( bHeaderRowFlag);
+    pDBCol->Insert( pDBData);
+
+    // Use DB name as style sheet name prefix.
+    ScDataTableFormat* pDTab = pDoc->GetDataTableFormatNonConst( nKey);
+    if (pDTab)
+    {
+        pDTab->SetStyleSheetNamePrefix( aRangeName);
+        /* TODO DataTable: remove display features? Currently this exists to 
+         * show _some_ table.. */
+        pDTab->InitDisplayFeatures( String());
+    }
+
+    aModificator.SetDocumentModified();
+    SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
+    SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
+    return nKey;
+}
+
+
 BOOL ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
 									BOOL bRecord, BOOL bApi )
 {

File sc/source/ui/inc/docfunc.hxx

View file
      */
     bool            GrowDataTable( const ScDataTableFormat& rDataTable, SCROW nGrowY, bool bRecord );
 
+    /** Create a DataTable on rRange.
+        If the specified cell range is within an already existing DataTable, 
+        that DataTable is returned instead of creating a new DataTable. If 
+        existing DataTables intersect the range, 0 is returned.
+     */
+    sal_uInt32      CreateDataTable( const ScRange& rRange, bool bRecord, bool bApi );
+
 	BOOL			InsertCells( const ScRange& rRange,const ScMarkData* pTabMark,
                                  InsCellCmd eCmd, BOOL bRecord, BOOL bApi,
 									BOOL bPartOfPaste = FALSE );

File sc/source/ui/src/globstr.src

View file
     {
         Text [ en-US ] = "This operation would shift cells in a data table and is not allowed." ;
     };
+	String STR_DATATABLE_NAMEPREFIX
+    {
+        Text [ en-US ] = "DataTable" ;
+        Text [ x-comment ] = "Used as name of DB range associated with a DataTable and the prefix of the style sheet names.";
+    };
 };
 

File sc/source/ui/unoobj/datatableuno.cxx

View file
 #include "dbcolect.hxx"
 #include "miscuno.hxx"
 #include "cellsuno.hxx"
+#include "convuno.hxx"
+#include "docfunc.hxx"
 
 using namespace com::sun::star;
 
     const ScDataTableFormat* pDTab = GetDataTableFormat();
     const ScRange& rRange = pDTab->GetTableRange();
     table::CellRangeAddress aArea;
-    aArea.Sheet = rRange.aStart.Tab();
-    aArea.StartColumn = rRange.aStart.Col();
-    aArea.StartRow = rRange.aStart.Row();
-    aArea.EndColumn = rRange.aEnd.Col();
-    aArea.EndRow = rRange.aEnd.Row();
+    ScUnoConversion::FillApiRange( aArea, rRange);
     return aArea;
 }
 
     ScUnoGuard aGuard;
     if (!mpDocShell)
         throw uno::RuntimeException();
+
     SCCOL nCol = aPosition.Column;
     SCROW nRow = aPosition.Row;
     SCTAB nTab = aPosition.Sheet;
-    if (!ValidColRowTab( nCol, nRow, nTab))
+    const ScDocument* pDoc = mpDocShell->GetDocument();
+    if (!ValidColRowTab( nCol, nRow, nTab, pDoc->GetTableCount()-1))
         throw lang::IndexOutOfBoundsException();
 
-    const ScDocument* pDoc = mpDocShell->GetDocument();
     const ScDataTableFormat* pDTab = pDoc->GetDataTableFormat( nCol, nRow, nTab);
     if (!pDTab)
         throw container::NoSuchElementException();
 
 ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDataTable > 
 SAL_CALL ScDataTablesObj::getDataTableByDatabaseRangeName( const ::rtl::OUString& aName )
-throw (::com::sun::star::lang::IndexOutOfBoundsException, 
-        ::com::sun::star::container::NoSuchElementException, 
+throw (::com::sun::star::container::NoSuchElementException, 
         ::com::sun::star::uno::RuntimeException)
 {
     ScUnoGuard aGuard;
     if (!pDTab)
         throw container::NoSuchElementException();
 
-    uno::Reference<sheet::XDataTable> xDTab( new ScDataTableObj( mpDocShell, pDTab->GetKey()));
+    uno::Reference<sheet::XDataTable> xDTab( new ScDataTableObj( mpDocShell, nKey));
+    return xDTab;
+}
+
+
+::com::sun::star::uno::Reference< ::com::sun::star::sheet::XDataTable > 
+SAL_CALL ScDataTablesObj::addNewByRange( const ::com::sun::star::table::CellRangeAddress& aRange )
+throw (::com::sun::star::lang::IndexOutOfBoundsException, 
+        ::com::sun::star::container::NoSuchElementException, 
+        ::com::sun::star::uno::RuntimeException)
+{
+    ScUnoGuard aGuard;
+    if (!mpDocShell)
+        throw uno::RuntimeException();
+
+    ScRange aScRange;
+    ScUnoConversion::FillScRange( aScRange, aRange);
+    const ScDocument* pDoc = mpDocShell->GetDocument();
+    if (!ValidRange( aScRange, pDoc->GetTableCount()-1))
+        throw lang::IndexOutOfBoundsException();
+
+    ScDocFunc aFunc( *mpDocShell);
+    sal_uInt32 nKey = aFunc.CreateDataTable( aScRange, false, true);
+    if (!nKey)
+        throw container::NoSuchElementException();
+    uno::Reference<sheet::XDataTable> xDTab( new ScDataTableObj( mpDocShell, nKey));
     return xDTab;
 }