Commits

kz  committed 7b1d611

CWS-TOOLING: integrate CWS calclinkfixes
2009-04-27 11:47:56 +0200 nn r271258 : #i101273# Uno broadcasts in DoRecalc/DoHardRecalc
2009-04-24 17:20:19 +0200 nn r271226 : #i101304# don't load source file of external ref for empty cells in the cached data
2009-04-24 14:15:43 +0200 nn r271212 : #i101319# handle merged cells and row groups when loading cached data for external refs

  • Participants
  • Parent commits d36f049

Comments (0)

Files changed (10)

File sc/inc/brdcst.hxx

 #define SC_HINT_DYING		SFX_HINT_DYING
 #define SC_HINT_DATACHANGED	SFX_HINT_DATACHANGED
 #define SC_HINT_TABLEOPDIRTY	SFX_HINT_USER00
+#define SC_HINT_CALCALL         SFX_HINT_USER01
 
 class ScHint : public SfxSimpleHint
 {

File sc/inc/externalrefmgr.hxx

      */
     ScExternalRefCache::TokenRef getCellData(
         sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow,
-        bool bEmptyCellOnNull, sal_uInt32* pnFmtIndex = NULL);
+        bool bEmptyCellOnNull, bool bWriteEmpty, sal_uInt32* pnFmtIndex);
 
     /**
      * Get a cached cell range data.
      *         guaranteed if the TokenArrayRef is properly used..
      */
     ScExternalRefCache::TokenArrayRef getCellRangeData(
-        sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull);
+        sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull, bool bWriteEmpty);
 
     ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName);
     void setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray);

File sc/source/filter/xml/xmlexternaltabi.cxx

 
 // ============================================================================
 
+ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
+    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+    const Reference<XAttributeList>& /* xAttrList */, ScXMLExternalTabData& rRefInfo ) :
+    SvXMLImportContext( rImport, nPrefix, rLName ),
+    mrScImport(rImport),
+    mrExternalRefInfo(rRefInfo)
+{
+}
+
+ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
+{
+}
+
+SvXMLImportContext* ScXMLExternalRefRowsContext::CreateChildContext(
+    USHORT nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
+{
+    // #i101319# row elements inside group, rows or header-rows
+    // are treated like row elements directly in the table element
+
+    const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowsElemTokenMap();
+    sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
+    switch (nToken)
+    {
+        case XML_TOK_TABLE_ROWS_ROW_GROUP:
+        case XML_TOK_TABLE_ROWS_HEADER_ROWS:
+        case XML_TOK_TABLE_ROWS_ROWS:
+            return new ScXMLExternalRefRowsContext(
+                mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
+        case XML_TOK_TABLE_ROWS_ROW:
+            return new ScXMLExternalRefRowContext(
+                mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
+        default:
+            ;
+    }
+    return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
+}
+
+void ScXMLExternalRefRowsContext::EndElement()
+{
+}
+
+// ============================================================================
+
 ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
     ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
     const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
 {
     const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
     sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
-    if (nToken == XML_TOK_TABLE_ROW_CELL)
+    if (nToken == XML_TOK_TABLE_ROW_CELL || nToken == XML_TOK_TABLE_ROW_COVERED_CELL)
         return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
 
     return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);

File sc/source/filter/xml/xmlexternaltabi.hxx

 
 // ============================================================================
 
+class ScXMLExternalRefRowsContext : public SvXMLImportContext
+{
+public:
+    ScXMLExternalRefRowsContext( ScXMLImport& rImport, USHORT nPrefix,
+                        const ::rtl::OUString& rLName,
+                        const ::com::sun::star::uno::Reference<
+                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
+                        ScXMLExternalTabData& rRefInfo );
+
+    virtual ~ScXMLExternalRefRowsContext();
+
+    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+                                     const ::rtl::OUString& rLocalName,
+                                     const ::com::sun::star::uno::Reference<
+                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+    virtual void EndElement();
+private:
+    ScXMLImport&            mrScImport;
+    ScXMLExternalTabData&   mrExternalRefInfo;
+};
+
+// ============================================================================
+
 class ScXMLExternalRefRowContext : public SvXMLImportContext
 {
 public:

File sc/source/filter/xml/xmltabi.cxx

         // external cache data.
         switch (nToken)
         {
+            case XML_TOK_TABLE_ROW_GROUP:
+            case XML_TOK_TABLE_HEADER_ROWS:
+            case XML_TOK_TABLE_ROWS:
+                // #i101319# don't discard rows in groups or header (repeat range)
+                return new ScXMLExternalRefRowsContext(
+                    GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);
             case XML_TOK_TABLE_ROW:
                 return new ScXMLExternalRefRowContext(
                     GetScImport(), nPrefix, rLName, xAttrList, *pExternalRefInfo);

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

 	pModificator = new ScDocShellModificator( *this );
 
     aDocument.SetImportingXML( TRUE );
+    aDocument.EnableExecuteLink( false );   // #i101304# to be safe, prevent nested loading from external references
     aDocument.EnableUndo( FALSE );
 	// prevent unnecessary broadcasts and "half way listeners"
 	aDocument.SetInsertingFromOtherDoc( TRUE );
 		aDocument.SetInsertingFromOtherDoc( FALSE );
 
 	aDocument.SetImportingXML( FALSE );
+    aDocument.EnableExecuteLink( true );
     aDocument.EnableUndo( TRUE );
     bIsEmpty = FALSE;
 

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

 		if ( pSh )
 			pSh->UpdateCharts(TRUE);
 
+        aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+
 		//	#47939# Wenn es Charts gibt, dann alles painten, damit nicht
 		//	PostDataChanged und die Charts nacheinander kommen und Teile
 		//	doppelt gepainted werden.
 	GetDocFunc().DetectiveRefresh();	// erzeugt eigenes Undo
 	if ( pSh )
 		pSh->UpdateCharts(TRUE);
+
+    // CalcAll doesn't broadcast value changes, so SC_HINT_CALCALL is broadcasted globally
+    // in addition to SFX_HINT_DATACHANGED.
+    aDocument.BroadcastUno( SfxSimpleHint( SC_HINT_CALCALL ) );
+    aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+
 	PostPaintGridAll();
 }
 

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

 
 ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
     sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, 
-    bool bEmptyCellOnNull, sal_uInt32* pnFmtIndex)
+    bool bEmptyCellOnNull, bool bWriteEmpty, sal_uInt32* pnFmtIndex)
 {
     DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
 
     TokenRef pToken = pTableData->getCell(nCol, nRow, pnFmtIndex);
     if (!pToken && bEmptyCellOnNull)
+    {
         pToken.reset(new ScEmptyCellToken(false, false));
+        if (bWriteEmpty)
+            pTableData->setCell(nCol, nRow, pToken);
+    }
     return pToken;
 }
 
 ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(
-    sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull)
+    sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, bool bEmptyCellOnNull, bool bWriteEmpty)
 {
     DocDataType::iterator itrDoc = maDocs.find(nFileId);
     if (itrDoc == maDocs.end())
                 if (!pToken)
                 {
                     if (bEmptyCellOnNull)
+                    {
                         pToken.reset(new ScEmptyCellToken(false, false));
+                        if (bWriteEmpty)
+                            pTab->setCell(nCol, nRow, pToken);
+                    }
                     else
                         return TokenArrayRef();
                 }
     if (pFmt)
         pFmt->mbIsSet = false;
 
+    bool bLoading = mpDoc->IsImportingXML();
+
     // Check if the given table name and the cell position is cached.
+    // #i101304# When loading a file, the saved cache (hidden sheet)
+    // is assumed to contain all data for the loaded formulas.
+    // No cache entries are created from empty cells in the saved sheet,
+    // so they have to be created here (bWriteEmpty parameter).
+    // Otherwise, later interpretation of the loaded formulas would
+    // load the source document even if the user didn't want to update.
     sal_uInt32 nFmtIndex = 0;
     ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
-        nFileId, rTabName, rCell.Col(), rCell.Row(), false, &nFmtIndex);
+        nFileId, rTabName, rCell.Col(), rCell.Row(), bLoading, bLoading, &nFmtIndex);
     if (pToken)
     {
         if (pFmt)
         // once again, but this time treat a non-cached cell as an empty cell
         // as long as the table itself is cached.
         pToken = maRefCache.getCellData(
-            nFileId, rTabName, rCell.Col(), rCell.Row(), true, &nFmtIndex);
+            nFileId, rTabName, rCell.Col(), rCell.Row(), true, false, &nFmtIndex);
         return pToken;
     }
 
 
     maybeLinkExternalFile(nFileId);
 
+    bool bLoading = mpDoc->IsImportingXML();
+
     // Check if the given table name and the cell position is cached.
-    ScExternalRefCache::TokenArrayRef p = maRefCache.getCellRangeData(nFileId, rTabName, rRange, false);
+    // #i101304# When loading, put empty cells into cache, see getSingleRefToken.
+    ScExternalRefCache::TokenArrayRef p = maRefCache.getCellRangeData(nFileId, rTabName, rRange, bLoading, bLoading);
     if (p.get())
         return p;
 
         // Source document is not reachable.  Try to get data from the cache 
         // once again, but this time treat non-cached cells as empty cells as
         // long as the table itself is cached.
-        return maRefCache.getCellRangeData(nFileId, rTabName, rRange, true);
+        return maRefCache.getCellRangeData(nFileId, rTabName, rRange, true, false);
     }
 
     SCTAB nTab1;

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

 				bGotDataChangedHint = FALSE;
 			}
 		}
+        else if ( nId == SC_HINT_CALCALL )
+        {
+            // broadcast from DoHardRecalc - set bGotDataChangedHint
+            // (SFX_HINT_DATACHANGED follows separately)
+
+            if ( aValueListeners.Count() )
+                bGotDataChangedHint = TRUE;
+        }
 	}
     else if ( rHint.ISA( ScUnoRefUndoHint ) )
     {

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

                                     break;
     
                                 if (pFCell->HasValueData())
+                                {
                                     rItem.mfValue = pFCell->GetValue();
                                     rItem.mbIsValue = true;
+                                }
                             }
                             break;
 #if DBG_UTIL
                 m_bGotDataChangedHint = false;
             }
         }
+        else if ( nId == SC_HINT_CALCALL )
+        {
+            // broadcast from DoHardRecalc - set m_bGotDataChangedHint
+            // (SFX_HINT_DATACHANGED follows separately)
+
+            if ( m_aValueListeners.Count() )
+                m_bGotDataChangedHint = true;
+        }
     }
     else if ( rHint.ISA( ScUpdateRefHint ) )
     {