From 1b243b14e9715b7b7da6359b5b752ee6d8278731 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Mon, 19 May 2014 23:42:05 -0400 Subject: cp#1000072: Load external documents when refreshing caches. Rather than just clearing the existing caches and loading the external documents on demand as the formula cells gets re-calculated. This has two advantages: 1) when the loading itself fails, we can keep the existing cache rather than turning all affected cells to error cells, and 2) this prevents on-demand loading after the external linkes get refreshed, which can make scrolling very slow & painful. Change-Id: Ie8243f6f94c5e477964413ab83f6b4b746fe3220 --- sc/source/ui/docshell/externalrefmgr.cxx | 85 ++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 25 deletions(-) (limited to 'sc/source/ui/docshell') diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 25dfe63ae1f7..549549a64c42 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -136,17 +136,18 @@ struct UpdateFormulaCell : public unary_function // Check to make sure the cell really contains ocExternalRef. // External names, external cell and range references all have a // ocExternalRef token. - const ScTokenArray* pCode = pCell->GetCode(); + ScTokenArray* pCode = pCell->GetCode(); if (!pCode->HasExternalRef()) return; - ScTokenArray* pArray = pCell->GetCode(); - if (pArray) + if (pCode->GetCodeError()) + { // Clear the error code, or a cell with error won't get re-compiled. - pArray->SetCodeError(0); + pCode->SetCodeError(0); + pCell->SetCompile(true); + pCell->CompileTokenArray(); + } - pCell->SetCompile(true); - pCell->CompileTokenArray(); pCell->SetDirty(); } }; @@ -1258,7 +1259,8 @@ void ScExternalRefLink::Closed() if (pCurFile->equals(aFile)) { // Refresh the current source document. - pMgr->refreshNames(mnFileId); + if (!pMgr->refreshSrcDocument(mnFileId)) + return ERROR_GENERAL; } else { @@ -2234,17 +2236,7 @@ ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId) return NULL; } - if (maDocShells.empty()) - { - // If this is the first source document insertion, start up the timer. - maSrcDocTimer.Start(); - } - - maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc)); - SfxObjectShell* p = aSrcDoc.maShell; - ScDocument* pSrcDoc = static_cast(p)->GetDocument(); - initDocInCache(maRefCache, pSrcDoc, nFileId); - return pSrcDoc; + return cacheNewDocShell(nFileId, aSrcDoc); } SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUString& rFilter) @@ -2321,7 +2313,12 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUSt } pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1; - pNewShell->DoLoad(pMedium.release()); + if (!pNewShell->DoLoad(pMedium.release())) + { + aRef->DoClose(); + aRef.Clear(); + return aRef; + } // with UseInteractionHandler, options may be set by dialog during DoLoad OUString aNew = ScDocumentLoader::GetOptions(*pNewShell->GetMedium()); @@ -2332,6 +2329,19 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, OUSt return aRef; } +ScDocument* ScExternalRefManager::cacheNewDocShell( sal_uInt16 nFileId, SrcShell& rSrcShell ) +{ + if (maDocShells.empty()) + // If this is the first source document insertion, start up the timer. + maSrcDocTimer.Start(); + + maDocShells.insert(DocShellMap::value_type(nFileId, rSrcShell)); + SfxObjectShell& rShell = *rSrcShell.maShell; + ScDocument* pSrcDoc = static_cast(rShell).GetDocument(); + initDocInCache(maRefCache, pSrcDoc, nFileId); + return pSrcDoc; +} + bool ScExternalRefManager::isFileLoadable(const OUString& rFile) const { if (rFile.isEmpty()) @@ -2548,18 +2558,43 @@ void ScExternalRefManager::clearCache(sal_uInt16 nFileId) maRefCache.clearCache(nFileId); } -void ScExternalRefManager::refreshNames(sal_uInt16 nFileId) +bool ScExternalRefManager::refreshSrcDocument(sal_uInt16 nFileId) { - clearCache(nFileId); - lcl_removeByFileId(nFileId, maDocShells); + OUString aFilter; + SfxObjectShellRef xDocShell; + try + { + xDocShell = loadSrcDocument(nFileId, aFilter); + } + catch ( const css::uno::Exception& ) {} - if (maDocShells.empty()) - maSrcDocTimer.Stop(); + if (!xDocShell.Is()) + // Failed to load the document. Bail out. + return false; + + // Clear the existing cache, and store the loaded doc shell until it expires. + clearCache(nFileId); + DocShellMap::iterator it = maDocShells.find(nFileId); + if (it != maDocShells.end()) + { + it->second.maShell->DoClose(); + it->second.maShell = xDocShell; + it->second.maLastAccess = Time(Time::SYSTEM); + } + else + { + SrcShell aSrcDoc; + aSrcDoc.maShell = xDocShell; + aSrcDoc.maLastAccess = Time(Time::SYSTEM); + cacheNewDocShell(nFileId, aSrcDoc); + } // Update all cells containing names from this source document. refreshAllRefCells(nFileId); notifyAllLinkListeners(nFileId, LINK_MODIFIED); + + return true; } void ScExternalRefManager::breakLink(sal_uInt16 nFileId) @@ -2615,7 +2650,7 @@ void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const OUString& rNe maSrcFiles[nFileId].maFilterName = rNewFilter; maSrcFiles[nFileId].maFilterOptions = OUString(); } - refreshNames(nFileId); + refreshSrcDocument(nFileId); } void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const OUString& rRelUrl) -- cgit