1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_sc.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir // INCLUDE --------------------------------------------------------------- 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir #include "externalrefmgr.hxx" 36*cdf0e10cSrcweir #include "document.hxx" 37*cdf0e10cSrcweir #include "token.hxx" 38*cdf0e10cSrcweir #include "tokenarray.hxx" 39*cdf0e10cSrcweir #include "address.hxx" 40*cdf0e10cSrcweir #include "tablink.hxx" 41*cdf0e10cSrcweir #include "docsh.hxx" 42*cdf0e10cSrcweir #include "scextopt.hxx" 43*cdf0e10cSrcweir #include "rangenam.hxx" 44*cdf0e10cSrcweir #include "cell.hxx" 45*cdf0e10cSrcweir #include "viewdata.hxx" 46*cdf0e10cSrcweir #include "tabvwsh.hxx" 47*cdf0e10cSrcweir #include "sc.hrc" 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir #include "sfx2/app.hxx" 50*cdf0e10cSrcweir #include "sfx2/docfilt.hxx" 51*cdf0e10cSrcweir #include "sfx2/docfile.hxx" 52*cdf0e10cSrcweir #include "sfx2/fcontnr.hxx" 53*cdf0e10cSrcweir #include "sfx2/sfxsids.hrc" 54*cdf0e10cSrcweir #include "sfx2/objsh.hxx" 55*cdf0e10cSrcweir #include "svl/broadcast.hxx" 56*cdf0e10cSrcweir #include "svl/smplhint.hxx" 57*cdf0e10cSrcweir #include "svl/itemset.hxx" 58*cdf0e10cSrcweir #include "svl/stritem.hxx" 59*cdf0e10cSrcweir #include "svl/urihelper.hxx" 60*cdf0e10cSrcweir #include "svl/zformat.hxx" 61*cdf0e10cSrcweir #include "sfx2/linkmgr.hxx" 62*cdf0e10cSrcweir #include "tools/urlobj.hxx" 63*cdf0e10cSrcweir #include "unotools/ucbhelper.hxx" 64*cdf0e10cSrcweir #include "unotools/localfilehelper.hxx" 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir #include <memory> 67*cdf0e10cSrcweir #include <algorithm> 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir #include <boost/scoped_ptr.hpp> 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir using ::std::auto_ptr; 72*cdf0e10cSrcweir using ::com::sun::star::uno::Any; 73*cdf0e10cSrcweir using ::rtl::OUString; 74*cdf0e10cSrcweir using ::std::vector; 75*cdf0e10cSrcweir using ::std::find; 76*cdf0e10cSrcweir using ::std::find_if; 77*cdf0e10cSrcweir using ::std::distance; 78*cdf0e10cSrcweir using ::std::pair; 79*cdf0e10cSrcweir using ::std::list; 80*cdf0e10cSrcweir using ::std::unary_function; 81*cdf0e10cSrcweir using namespace formula; 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir #define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of a sec) 84*cdf0e10cSrcweir #define SRCDOC_SCAN_INTERVAL 1000*5 // every 5 seconds (in msec) 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir namespace { 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir class TabNameSearchPredicate : public unary_function<bool, ScExternalRefCache::TableName> 89*cdf0e10cSrcweir { 90*cdf0e10cSrcweir public: 91*cdf0e10cSrcweir explicit TabNameSearchPredicate(const String& rSearchName) : 92*cdf0e10cSrcweir maSearchName(ScGlobal::pCharClass->upper(rSearchName)) 93*cdf0e10cSrcweir { 94*cdf0e10cSrcweir } 95*cdf0e10cSrcweir 96*cdf0e10cSrcweir bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const 97*cdf0e10cSrcweir { 98*cdf0e10cSrcweir // Ok, I'm doing case insensitive search here. 99*cdf0e10cSrcweir return rTabNameSet.maUpperName.Equals(maSearchName); 100*cdf0e10cSrcweir } 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir private: 103*cdf0e10cSrcweir String maSearchName; 104*cdf0e10cSrcweir }; 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir class FindSrcFileByName : public unary_function<ScExternalRefManager::SrcFileData, bool> 107*cdf0e10cSrcweir { 108*cdf0e10cSrcweir public: 109*cdf0e10cSrcweir FindSrcFileByName(const String& rMatchName) : 110*cdf0e10cSrcweir mrMatchName(rMatchName) 111*cdf0e10cSrcweir { 112*cdf0e10cSrcweir } 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const 115*cdf0e10cSrcweir { 116*cdf0e10cSrcweir return rSrcData.maFileName.Equals(mrMatchName); 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir private: 120*cdf0e10cSrcweir const String& mrMatchName; 121*cdf0e10cSrcweir }; 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir class NotifyLinkListener : public unary_function<ScExternalRefManager::LinkListener*, void> 124*cdf0e10cSrcweir { 125*cdf0e10cSrcweir public: 126*cdf0e10cSrcweir NotifyLinkListener(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) : 127*cdf0e10cSrcweir mnFileId(nFileId), meType(eType) {} 128*cdf0e10cSrcweir 129*cdf0e10cSrcweir NotifyLinkListener(const NotifyLinkListener& r) : 130*cdf0e10cSrcweir mnFileId(r.mnFileId), meType(r.meType) {} 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir void operator() (ScExternalRefManager::LinkListener* p) const 133*cdf0e10cSrcweir { 134*cdf0e10cSrcweir p->notify(mnFileId, meType); 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir private: 137*cdf0e10cSrcweir sal_uInt16 mnFileId; 138*cdf0e10cSrcweir ScExternalRefManager::LinkUpdateType meType; 139*cdf0e10cSrcweir }; 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir struct UpdateFormulaCell : public unary_function<ScFormulaCell*, void> 142*cdf0e10cSrcweir { 143*cdf0e10cSrcweir void operator() (ScFormulaCell* pCell) const 144*cdf0e10cSrcweir { 145*cdf0e10cSrcweir // Check to make sure the cell really contains ocExternalRef. 146*cdf0e10cSrcweir // External names, external cell and range references all have a 147*cdf0e10cSrcweir // ocExternalRef token. 148*cdf0e10cSrcweir const ScTokenArray* pCode = pCell->GetCode(); 149*cdf0e10cSrcweir if (!pCode->HasOpCode( ocExternalRef)) 150*cdf0e10cSrcweir return; 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir ScTokenArray* pArray = pCell->GetCode(); 153*cdf0e10cSrcweir if (pArray) 154*cdf0e10cSrcweir // Clear the error code, or a cell with error won't get re-compiled. 155*cdf0e10cSrcweir pArray->SetCodeError(0); 156*cdf0e10cSrcweir 157*cdf0e10cSrcweir pCell->SetCompile(true); 158*cdf0e10cSrcweir pCell->CompileTokenArray(); 159*cdf0e10cSrcweir pCell->SetDirty(); 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir }; 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir class RemoveFormulaCell : public unary_function<pair<const sal_uInt16, ScExternalRefManager::RefCellSet>, void> 164*cdf0e10cSrcweir { 165*cdf0e10cSrcweir public: 166*cdf0e10cSrcweir explicit RemoveFormulaCell(ScFormulaCell* p) : mpCell(p) {} 167*cdf0e10cSrcweir void operator() (pair<const sal_uInt16, ScExternalRefManager::RefCellSet>& r) const 168*cdf0e10cSrcweir { 169*cdf0e10cSrcweir r.second.erase(mpCell); 170*cdf0e10cSrcweir } 171*cdf0e10cSrcweir private: 172*cdf0e10cSrcweir ScFormulaCell* mpCell; 173*cdf0e10cSrcweir }; 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir class ConvertFormulaToStatic : public unary_function<ScFormulaCell*, void> 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir public: 178*cdf0e10cSrcweir explicit ConvertFormulaToStatic(ScDocument* pDoc) : mpDoc(pDoc) {} 179*cdf0e10cSrcweir void operator() (ScFormulaCell* pCell) const 180*cdf0e10cSrcweir { 181*cdf0e10cSrcweir ScAddress aPos = pCell->aPos; 182*cdf0e10cSrcweir 183*cdf0e10cSrcweir // We don't check for empty cells because empty external cells are 184*cdf0e10cSrcweir // treated as having a value of 0. 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir if (pCell->IsValue()) 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir // Turn this into value cell. 189*cdf0e10cSrcweir double fVal = pCell->GetValue(); 190*cdf0e10cSrcweir mpDoc->PutCell(aPos, new ScValueCell(fVal)); 191*cdf0e10cSrcweir } 192*cdf0e10cSrcweir else 193*cdf0e10cSrcweir { 194*cdf0e10cSrcweir // string cell otherwise. 195*cdf0e10cSrcweir String aVal; 196*cdf0e10cSrcweir pCell->GetString(aVal); 197*cdf0e10cSrcweir mpDoc->PutCell(aPos, new ScStringCell(aVal)); 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir private: 201*cdf0e10cSrcweir ScDocument* mpDoc; 202*cdf0e10cSrcweir }; 203*cdf0e10cSrcweir 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir // ============================================================================ 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir ScExternalRefCache::Table::Table() 209*cdf0e10cSrcweir : meReferenced( REFERENCED_MARKED ) 210*cdf0e10cSrcweir // Prevent accidental data loss due to lack of knowledge. 211*cdf0e10cSrcweir { 212*cdf0e10cSrcweir } 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir ScExternalRefCache::Table::~Table() 215*cdf0e10cSrcweir { 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag ) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir meReferenced = eFlag; 221*cdf0e10cSrcweir } 222*cdf0e10cSrcweir 223*cdf0e10cSrcweir void ScExternalRefCache::Table::setReferenced( bool bReferenced ) 224*cdf0e10cSrcweir { 225*cdf0e10cSrcweir if (meReferenced != REFERENCED_PERMANENT) 226*cdf0e10cSrcweir meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED); 227*cdf0e10cSrcweir } 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir return meReferenced; 232*cdf0e10cSrcweir } 233*cdf0e10cSrcweir 234*cdf0e10cSrcweir bool ScExternalRefCache::Table::isReferenced() const 235*cdf0e10cSrcweir { 236*cdf0e10cSrcweir return meReferenced != UNREFERENCED; 237*cdf0e10cSrcweir } 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex, bool bSetCacheRange) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir using ::std::pair; 242*cdf0e10cSrcweir RowsDataType::iterator itrRow = maRows.find(nRow); 243*cdf0e10cSrcweir if (itrRow == maRows.end()) 244*cdf0e10cSrcweir { 245*cdf0e10cSrcweir // This row does not exist yet. 246*cdf0e10cSrcweir pair<RowsDataType::iterator, bool> res = maRows.insert( 247*cdf0e10cSrcweir RowsDataType::value_type(nRow, RowDataType())); 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir if (!res.second) 250*cdf0e10cSrcweir return; 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir itrRow = res.first; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir // Insert this token into the specified column location. I don't need to 256*cdf0e10cSrcweir // check for existing data. Just overwrite it. 257*cdf0e10cSrcweir RowDataType& rRow = itrRow->second; 258*cdf0e10cSrcweir ScExternalRefCache::Cell aCell; 259*cdf0e10cSrcweir aCell.mxToken = pToken; 260*cdf0e10cSrcweir aCell.mnFmtIndex = nFmtIndex; 261*cdf0e10cSrcweir rRow.insert(RowDataType::value_type(nCol, aCell)); 262*cdf0e10cSrcweir if (bSetCacheRange) 263*cdf0e10cSrcweir setCachedCell(nCol, nRow); 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir RowsDataType::const_iterator itrTable = maRows.find(nRow); 269*cdf0e10cSrcweir if (itrTable == maRows.end()) 270*cdf0e10cSrcweir { 271*cdf0e10cSrcweir // this table doesn't have the specified row. 272*cdf0e10cSrcweir return getEmptyOrNullToken(nCol, nRow); 273*cdf0e10cSrcweir } 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir const RowDataType& rRowData = itrTable->second; 276*cdf0e10cSrcweir RowDataType::const_iterator itrRow = rRowData.find(nCol); 277*cdf0e10cSrcweir if (itrRow == rRowData.end()) 278*cdf0e10cSrcweir { 279*cdf0e10cSrcweir // this row doesn't have the specified column. 280*cdf0e10cSrcweir return getEmptyOrNullToken(nCol, nRow); 281*cdf0e10cSrcweir } 282*cdf0e10cSrcweir 283*cdf0e10cSrcweir const Cell& rCell = itrRow->second; 284*cdf0e10cSrcweir if (pnFmtIndex) 285*cdf0e10cSrcweir *pnFmtIndex = rCell.mnFmtIndex; 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir return rCell.mxToken; 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir bool ScExternalRefCache::Table::hasRow( SCROW nRow ) const 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir RowsDataType::const_iterator itrRow = maRows.find(nRow); 293*cdf0e10cSrcweir return itrRow != maRows.end(); 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows, SCROW nLow, SCROW nHigh) const 297*cdf0e10cSrcweir { 298*cdf0e10cSrcweir vector<SCROW> aRows; 299*cdf0e10cSrcweir aRows.reserve(maRows.size()); 300*cdf0e10cSrcweir RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end(); 301*cdf0e10cSrcweir for (; itr != itrEnd; ++itr) 302*cdf0e10cSrcweir if (nLow <= itr->first && itr->first <= nHigh) 303*cdf0e10cSrcweir aRows.push_back(itr->first); 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir // hash map is not ordered, so we need to explicitly sort it. 306*cdf0e10cSrcweir ::std::sort(aRows.begin(), aRows.end()); 307*cdf0e10cSrcweir rRows.swap(aRows); 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir ::std::pair< SCROW, SCROW > ScExternalRefCache::Table::getRowRange() const 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir ::std::pair< SCROW, SCROW > aRange( 0, 0 ); 313*cdf0e10cSrcweir if( !maRows.empty() ) 314*cdf0e10cSrcweir { 315*cdf0e10cSrcweir // iterate over entire container (hash map is not sorted by key) 316*cdf0e10cSrcweir RowsDataType::const_iterator itr = maRows.begin(), itrEnd = maRows.end(); 317*cdf0e10cSrcweir aRange.first = itr->first; 318*cdf0e10cSrcweir aRange.second = itr->first + 1; 319*cdf0e10cSrcweir while( ++itr != itrEnd ) 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir if( itr->first < aRange.first ) 322*cdf0e10cSrcweir aRange.first = itr->first; 323*cdf0e10cSrcweir else if( itr->first >= aRange.second ) 324*cdf0e10cSrcweir aRange.second = itr->first + 1; 325*cdf0e10cSrcweir } 326*cdf0e10cSrcweir } 327*cdf0e10cSrcweir return aRange; 328*cdf0e10cSrcweir } 329*cdf0e10cSrcweir 330*cdf0e10cSrcweir void ScExternalRefCache::Table::getAllCols(SCROW nRow, vector<SCCOL>& rCols, SCCOL nLow, SCCOL nHigh) const 331*cdf0e10cSrcweir { 332*cdf0e10cSrcweir RowsDataType::const_iterator itrRow = maRows.find(nRow); 333*cdf0e10cSrcweir if (itrRow == maRows.end()) 334*cdf0e10cSrcweir // this table doesn't have the specified row. 335*cdf0e10cSrcweir return; 336*cdf0e10cSrcweir 337*cdf0e10cSrcweir const RowDataType& rRowData = itrRow->second; 338*cdf0e10cSrcweir vector<SCCOL> aCols; 339*cdf0e10cSrcweir aCols.reserve(rRowData.size()); 340*cdf0e10cSrcweir RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end(); 341*cdf0e10cSrcweir for (; itrCol != itrColEnd; ++itrCol) 342*cdf0e10cSrcweir if (nLow <= itrCol->first && itrCol->first <= nHigh) 343*cdf0e10cSrcweir aCols.push_back(itrCol->first); 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir // hash map is not ordered, so we need to explicitly sort it. 346*cdf0e10cSrcweir ::std::sort(aCols.begin(), aCols.end()); 347*cdf0e10cSrcweir rCols.swap(aCols); 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir ::std::pair< SCCOL, SCCOL > ScExternalRefCache::Table::getColRange( SCROW nRow ) const 351*cdf0e10cSrcweir { 352*cdf0e10cSrcweir ::std::pair< SCCOL, SCCOL > aRange( 0, 0 ); 353*cdf0e10cSrcweir 354*cdf0e10cSrcweir RowsDataType::const_iterator itrRow = maRows.find( nRow ); 355*cdf0e10cSrcweir if (itrRow == maRows.end()) 356*cdf0e10cSrcweir // this table doesn't have the specified row. 357*cdf0e10cSrcweir return aRange; 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir const RowDataType& rRowData = itrRow->second; 360*cdf0e10cSrcweir if( !rRowData.empty() ) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir // iterate over entire container (hash map is not sorted by key) 363*cdf0e10cSrcweir RowDataType::const_iterator itr = rRowData.begin(), itrEnd = rRowData.end(); 364*cdf0e10cSrcweir aRange.first = itr->first; 365*cdf0e10cSrcweir aRange.second = itr->first + 1; 366*cdf0e10cSrcweir while( ++itr != itrEnd ) 367*cdf0e10cSrcweir { 368*cdf0e10cSrcweir if( itr->first < aRange.first ) 369*cdf0e10cSrcweir aRange.first = itr->first; 370*cdf0e10cSrcweir else if( itr->first >= aRange.second ) 371*cdf0e10cSrcweir aRange.second = itr->first + 1; 372*cdf0e10cSrcweir } 373*cdf0e10cSrcweir } 374*cdf0e10cSrcweir return aRange; 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const 378*cdf0e10cSrcweir { 379*cdf0e10cSrcweir RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end(); 380*cdf0e10cSrcweir for (; itrRow != itrRowEnd; ++itrRow) 381*cdf0e10cSrcweir { 382*cdf0e10cSrcweir const RowDataType& rRowData = itrRow->second; 383*cdf0e10cSrcweir RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end(); 384*cdf0e10cSrcweir for (; itrCol != itrColEnd; ++itrCol) 385*cdf0e10cSrcweir { 386*cdf0e10cSrcweir const Cell& rCell = itrCol->second; 387*cdf0e10cSrcweir rNumFmts.push_back(rCell.mnFmtIndex); 388*cdf0e10cSrcweir } 389*cdf0e10cSrcweir } 390*cdf0e10cSrcweir } 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir const ScRangeList& ScExternalRefCache::Table::getCachedRanges() const 393*cdf0e10cSrcweir { 394*cdf0e10cSrcweir return maCachedRanges; 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir bool ScExternalRefCache::Table::isRangeCached(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const 398*cdf0e10cSrcweir { 399*cdf0e10cSrcweir return maCachedRanges.In(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0)); 400*cdf0e10cSrcweir } 401*cdf0e10cSrcweir 402*cdf0e10cSrcweir void ScExternalRefCache::Table::setCachedCell(SCCOL nCol, SCROW nRow) 403*cdf0e10cSrcweir { 404*cdf0e10cSrcweir setCachedCellRange(nCol, nRow, nCol, nRow); 405*cdf0e10cSrcweir } 406*cdf0e10cSrcweir 407*cdf0e10cSrcweir void ScExternalRefCache::Table::setCachedCellRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) 408*cdf0e10cSrcweir { 409*cdf0e10cSrcweir ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0); 410*cdf0e10cSrcweir if (!maCachedRanges.Count()) 411*cdf0e10cSrcweir maCachedRanges.Append(aRange); 412*cdf0e10cSrcweir else 413*cdf0e10cSrcweir maCachedRanges.Join(aRange); 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir String aStr; 416*cdf0e10cSrcweir maCachedRanges.Format(aStr, SCA_VALID); 417*cdf0e10cSrcweir } 418*cdf0e10cSrcweir 419*cdf0e10cSrcweir void ScExternalRefCache::Table::setWholeTableCached() 420*cdf0e10cSrcweir { 421*cdf0e10cSrcweir setCachedCellRange(0, 0, MAXCOL, MAXROW); 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir 424*cdf0e10cSrcweir bool ScExternalRefCache::Table::isInCachedRanges(SCCOL nCol, SCROW nRow) const 425*cdf0e10cSrcweir { 426*cdf0e10cSrcweir return maCachedRanges.In(ScRange(nCol, nRow, 0, nCol, nRow, 0)); 427*cdf0e10cSrcweir } 428*cdf0e10cSrcweir 429*cdf0e10cSrcweir ScExternalRefCache::TokenRef ScExternalRefCache::Table::getEmptyOrNullToken( 430*cdf0e10cSrcweir SCCOL nCol, SCROW nRow) const 431*cdf0e10cSrcweir { 432*cdf0e10cSrcweir if (isInCachedRanges(nCol, nRow)) 433*cdf0e10cSrcweir { 434*cdf0e10cSrcweir TokenRef p(new ScEmptyCellToken(false, false)); 435*cdf0e10cSrcweir return p; 436*cdf0e10cSrcweir } 437*cdf0e10cSrcweir return TokenRef(); 438*cdf0e10cSrcweir } 439*cdf0e10cSrcweir 440*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) : 443*cdf0e10cSrcweir maUpperName(rUpper), maRealName(rReal) 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir } 446*cdf0e10cSrcweir 447*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 448*cdf0e10cSrcweir 449*cdf0e10cSrcweir ScExternalRefCache::CellFormat::CellFormat() : 450*cdf0e10cSrcweir mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0) 451*cdf0e10cSrcweir { 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir ScExternalRefCache::ScExternalRefCache() 457*cdf0e10cSrcweir { 458*cdf0e10cSrcweir } 459*cdf0e10cSrcweir ScExternalRefCache::~ScExternalRefCache() 460*cdf0e10cSrcweir { 461*cdf0e10cSrcweir } 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir const String* ScExternalRefCache::getRealTableName(sal_uInt16 nFileId, const String& rTabName) const 464*cdf0e10cSrcweir { 465*cdf0e10cSrcweir DocDataType::const_iterator itrDoc = maDocs.find(nFileId); 466*cdf0e10cSrcweir if (itrDoc == maDocs.end()) 467*cdf0e10cSrcweir { 468*cdf0e10cSrcweir // specified document is not cached. 469*cdf0e10cSrcweir return NULL; 470*cdf0e10cSrcweir } 471*cdf0e10cSrcweir 472*cdf0e10cSrcweir const DocItem& rDoc = itrDoc->second; 473*cdf0e10cSrcweir TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find( 474*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rTabName)); 475*cdf0e10cSrcweir if (itrTabId == rDoc.maTableNameIndex.end()) 476*cdf0e10cSrcweir { 477*cdf0e10cSrcweir // the specified table is not in cache. 478*cdf0e10cSrcweir return NULL; 479*cdf0e10cSrcweir } 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir return &rDoc.maTableNames[itrTabId->second].maRealName; 482*cdf0e10cSrcweir } 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir const String* ScExternalRefCache::getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const 485*cdf0e10cSrcweir { 486*cdf0e10cSrcweir DocDataType::const_iterator itrDoc = maDocs.find(nFileId); 487*cdf0e10cSrcweir if (itrDoc == maDocs.end()) 488*cdf0e10cSrcweir { 489*cdf0e10cSrcweir // specified document is not cached. 490*cdf0e10cSrcweir return NULL; 491*cdf0e10cSrcweir } 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir const DocItem& rDoc = itrDoc->second; 494*cdf0e10cSrcweir NamePairMap::const_iterator itr = rDoc.maRealRangeNameMap.find( 495*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rRangeName)); 496*cdf0e10cSrcweir if (itr == rDoc.maRealRangeNameMap.end()) 497*cdf0e10cSrcweir // range name not found. 498*cdf0e10cSrcweir return NULL; 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir return &itr->second; 501*cdf0e10cSrcweir } 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir ScExternalRefCache::TokenRef ScExternalRefCache::getCellData( 504*cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir DocDataType::const_iterator itrDoc = maDocs.find(nFileId); 507*cdf0e10cSrcweir if (itrDoc == maDocs.end()) 508*cdf0e10cSrcweir { 509*cdf0e10cSrcweir // specified document is not cached. 510*cdf0e10cSrcweir return TokenRef(); 511*cdf0e10cSrcweir } 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir const DocItem& rDoc = itrDoc->second; 514*cdf0e10cSrcweir TableNameIndexMap::const_iterator itrTabId = rDoc.maTableNameIndex.find( 515*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rTabName)); 516*cdf0e10cSrcweir if (itrTabId == rDoc.maTableNameIndex.end()) 517*cdf0e10cSrcweir { 518*cdf0e10cSrcweir // the specified table is not in cache. 519*cdf0e10cSrcweir return TokenRef(); 520*cdf0e10cSrcweir } 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir const TableTypeRef& pTableData = rDoc.maTables[itrTabId->second]; 523*cdf0e10cSrcweir if (!pTableData.get()) 524*cdf0e10cSrcweir { 525*cdf0e10cSrcweir // the table data is not instantiated yet. 526*cdf0e10cSrcweir return TokenRef(); 527*cdf0e10cSrcweir } 528*cdf0e10cSrcweir 529*cdf0e10cSrcweir return pTableData->getCell(nCol, nRow, pnFmtIndex); 530*cdf0e10cSrcweir } 531*cdf0e10cSrcweir 532*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData( 533*cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange) 534*cdf0e10cSrcweir { 535*cdf0e10cSrcweir DocDataType::iterator itrDoc = maDocs.find(nFileId); 536*cdf0e10cSrcweir if (itrDoc == maDocs.end()) 537*cdf0e10cSrcweir // specified document is not cached. 538*cdf0e10cSrcweir return TokenArrayRef(); 539*cdf0e10cSrcweir 540*cdf0e10cSrcweir DocItem& rDoc = itrDoc->second; 541*cdf0e10cSrcweir 542*cdf0e10cSrcweir TableNameIndexMap::iterator itrTabId = rDoc.maTableNameIndex.find( 543*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rTabName)); 544*cdf0e10cSrcweir if (itrTabId == rDoc.maTableNameIndex.end()) 545*cdf0e10cSrcweir // the specified table is not in cache. 546*cdf0e10cSrcweir return TokenArrayRef(); 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir const ScAddress& s = rRange.aStart; 549*cdf0e10cSrcweir const ScAddress& e = rRange.aEnd; 550*cdf0e10cSrcweir 551*cdf0e10cSrcweir SCTAB nTab1 = s.Tab(), nTab2 = e.Tab(); 552*cdf0e10cSrcweir SCCOL nCol1 = s.Col(), nCol2 = e.Col(); 553*cdf0e10cSrcweir SCROW nRow1 = s.Row(), nRow2 = e.Row(); 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir // Make sure I have all the tables cached. 556*cdf0e10cSrcweir size_t nTabFirstId = itrTabId->second; 557*cdf0e10cSrcweir size_t nTabLastId = nTabFirstId + nTab2 - nTab1; 558*cdf0e10cSrcweir if (nTabLastId >= rDoc.maTables.size()) 559*cdf0e10cSrcweir // not all tables are cached. 560*cdf0e10cSrcweir return TokenArrayRef(); 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId)); 563*cdf0e10cSrcweir 564*cdf0e10cSrcweir RangeArrayMap::const_iterator itrRange = rDoc.maRangeArrays.find( aCacheRange); 565*cdf0e10cSrcweir if (itrRange != rDoc.maRangeArrays.end()) 566*cdf0e10cSrcweir // Cache hit! 567*cdf0e10cSrcweir return itrRange->second; 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir ::boost::scoped_ptr<ScRange> pNewRange; 570*cdf0e10cSrcweir TokenArrayRef pArray; 571*cdf0e10cSrcweir bool bFirstTab = true; 572*cdf0e10cSrcweir for (size_t nTab = nTabFirstId; nTab <= nTabLastId; ++nTab) 573*cdf0e10cSrcweir { 574*cdf0e10cSrcweir TableTypeRef pTab = rDoc.maTables[nTab]; 575*cdf0e10cSrcweir if (!pTab.get()) 576*cdf0e10cSrcweir return TokenArrayRef(); 577*cdf0e10cSrcweir 578*cdf0e10cSrcweir SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2; 579*cdf0e10cSrcweir SCROW nDataRow1 = nRow1, nDataRow2 = nRow2; 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir if (!pTab->isRangeCached(nDataCol1, nDataRow1, nDataCol2, nDataRow2)) 582*cdf0e10cSrcweir { 583*cdf0e10cSrcweir // specified range is not entirely within cached ranges. 584*cdf0e10cSrcweir return TokenArrayRef(); 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir 587*cdf0e10cSrcweir ScMatrixRef xMat = new ScMatrix( 588*cdf0e10cSrcweir static_cast<SCSIZE>(nDataCol2-nDataCol1+1), static_cast<SCSIZE>(nDataRow2-nDataRow1+1)); 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir #if 0 591*cdf0e10cSrcweir // TODO: Switch to this code block once we have support for sparsely-filled 592*cdf0e10cSrcweir // matrices in ScMatrix. 593*cdf0e10cSrcweir 594*cdf0e10cSrcweir // Only fill non-empty cells, for better performance. 595*cdf0e10cSrcweir vector<SCROW> aRows; 596*cdf0e10cSrcweir pTab->getAllRows(aRows, nDataRow1, nDataRow2); 597*cdf0e10cSrcweir for (vector<SCROW>::const_iterator itr = aRows.begin(), itrEnd = aRows.end(); itr != itrEnd; ++itr) 598*cdf0e10cSrcweir { 599*cdf0e10cSrcweir SCROW nRow = *itr; 600*cdf0e10cSrcweir vector<SCCOL> aCols; 601*cdf0e10cSrcweir pTab->getAllCols(nRow, aCols, nDataCol1, nDataCol2); 602*cdf0e10cSrcweir for (vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end(); itrCol != itrColEnd; ++itrCol) 603*cdf0e10cSrcweir { 604*cdf0e10cSrcweir SCCOL nCol = *itrCol; 605*cdf0e10cSrcweir TokenRef pToken = pTab->getCell(nCol, nRow); 606*cdf0e10cSrcweir if (!pToken) 607*cdf0e10cSrcweir // This should never happen! 608*cdf0e10cSrcweir return TokenArrayRef(); 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir SCSIZE nC = nCol - nDataCol1, nR = nRow - nDataRow1; 611*cdf0e10cSrcweir switch (pToken->GetType()) 612*cdf0e10cSrcweir { 613*cdf0e10cSrcweir case svDouble: 614*cdf0e10cSrcweir xMat->PutDouble(pToken->GetDouble(), nC, nR); 615*cdf0e10cSrcweir break; 616*cdf0e10cSrcweir case svString: 617*cdf0e10cSrcweir xMat->PutString(pToken->GetString(), nC, nR); 618*cdf0e10cSrcweir break; 619*cdf0e10cSrcweir default: 620*cdf0e10cSrcweir ; 621*cdf0e10cSrcweir } 622*cdf0e10cSrcweir } 623*cdf0e10cSrcweir } 624*cdf0e10cSrcweir #else 625*cdf0e10cSrcweir vector<SCROW> aRows; 626*cdf0e10cSrcweir pTab->getAllRows(aRows, nDataRow1, nDataRow2); 627*cdf0e10cSrcweir if (aRows.empty()) 628*cdf0e10cSrcweir // Cache is empty. 629*cdf0e10cSrcweir return TokenArrayRef(); 630*cdf0e10cSrcweir else 631*cdf0e10cSrcweir // Trim the column below the last non-empty row. 632*cdf0e10cSrcweir nDataRow2 = aRows.back(); 633*cdf0e10cSrcweir 634*cdf0e10cSrcweir // Empty all matrix elements first, and fill only non-empty elements. 635*cdf0e10cSrcweir for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow) 636*cdf0e10cSrcweir { 637*cdf0e10cSrcweir for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol) 638*cdf0e10cSrcweir { 639*cdf0e10cSrcweir TokenRef pToken = pTab->getCell(nCol, nRow); 640*cdf0e10cSrcweir SCSIZE nC = nCol - nCol1, nR = nRow - nRow1; 641*cdf0e10cSrcweir if (!pToken) 642*cdf0e10cSrcweir return TokenArrayRef(); 643*cdf0e10cSrcweir 644*cdf0e10cSrcweir switch (pToken->GetType()) 645*cdf0e10cSrcweir { 646*cdf0e10cSrcweir case svDouble: 647*cdf0e10cSrcweir xMat->PutDouble(pToken->GetDouble(), nC, nR); 648*cdf0e10cSrcweir break; 649*cdf0e10cSrcweir case svString: 650*cdf0e10cSrcweir xMat->PutString(pToken->GetString(), nC, nR); 651*cdf0e10cSrcweir break; 652*cdf0e10cSrcweir default: 653*cdf0e10cSrcweir xMat->PutEmpty(nC, nR); 654*cdf0e10cSrcweir } 655*cdf0e10cSrcweir } 656*cdf0e10cSrcweir } 657*cdf0e10cSrcweir #endif 658*cdf0e10cSrcweir 659*cdf0e10cSrcweir if (!bFirstTab) 660*cdf0e10cSrcweir pArray->AddOpCode(ocSep); 661*cdf0e10cSrcweir 662*cdf0e10cSrcweir ScMatrix* pMat2 = xMat; 663*cdf0e10cSrcweir ScMatrixToken aToken(pMat2); 664*cdf0e10cSrcweir if (!pArray) 665*cdf0e10cSrcweir pArray.reset(new ScTokenArray); 666*cdf0e10cSrcweir pArray->AddToken(aToken); 667*cdf0e10cSrcweir 668*cdf0e10cSrcweir bFirstTab = false; 669*cdf0e10cSrcweir 670*cdf0e10cSrcweir if (!pNewRange) 671*cdf0e10cSrcweir pNewRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); 672*cdf0e10cSrcweir else 673*cdf0e10cSrcweir pNewRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); 674*cdf0e10cSrcweir } 675*cdf0e10cSrcweir 676*cdf0e10cSrcweir if (pNewRange) 677*cdf0e10cSrcweir rDoc.maRangeArrays.insert( RangeArrayMap::value_type(*pNewRange, pArray)); 678*cdf0e10cSrcweir return pArray; 679*cdf0e10cSrcweir } 680*cdf0e10cSrcweir 681*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef ScExternalRefCache::getRangeNameTokens(sal_uInt16 nFileId, const String& rName) 682*cdf0e10cSrcweir { 683*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 684*cdf0e10cSrcweir if (!pDoc) 685*cdf0e10cSrcweir return TokenArrayRef(); 686*cdf0e10cSrcweir 687*cdf0e10cSrcweir RangeNameMap& rMap = pDoc->maRangeNames; 688*cdf0e10cSrcweir RangeNameMap::const_iterator itr = rMap.find( 689*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rName)); 690*cdf0e10cSrcweir if (itr == rMap.end()) 691*cdf0e10cSrcweir return TokenArrayRef(); 692*cdf0e10cSrcweir 693*cdf0e10cSrcweir return itr->second; 694*cdf0e10cSrcweir } 695*cdf0e10cSrcweir 696*cdf0e10cSrcweir void ScExternalRefCache::setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray) 697*cdf0e10cSrcweir { 698*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 699*cdf0e10cSrcweir if (!pDoc) 700*cdf0e10cSrcweir return; 701*cdf0e10cSrcweir 702*cdf0e10cSrcweir String aUpperName = ScGlobal::pCharClass->upper(rName); 703*cdf0e10cSrcweir RangeNameMap& rMap = pDoc->maRangeNames; 704*cdf0e10cSrcweir rMap.insert(RangeNameMap::value_type(aUpperName, pArray)); 705*cdf0e10cSrcweir pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName)); 706*cdf0e10cSrcweir } 707*cdf0e10cSrcweir 708*cdf0e10cSrcweir void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, 709*cdf0e10cSrcweir TokenRef pToken, sal_uInt32 nFmtIndex) 710*cdf0e10cSrcweir { 711*cdf0e10cSrcweir if (!isDocInitialized(nFileId)) 712*cdf0e10cSrcweir return; 713*cdf0e10cSrcweir 714*cdf0e10cSrcweir using ::std::pair; 715*cdf0e10cSrcweir DocItem* pDocItem = getDocItem(nFileId); 716*cdf0e10cSrcweir if (!pDocItem) 717*cdf0e10cSrcweir return; 718*cdf0e10cSrcweir 719*cdf0e10cSrcweir DocItem& rDoc = *pDocItem; 720*cdf0e10cSrcweir 721*cdf0e10cSrcweir // See if the table by this name already exists. 722*cdf0e10cSrcweir TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find( 723*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rTabName)); 724*cdf0e10cSrcweir if (itrTabName == rDoc.maTableNameIndex.end()) 725*cdf0e10cSrcweir // Table not found. Maybe the table name or the file id is wrong ??? 726*cdf0e10cSrcweir return; 727*cdf0e10cSrcweir 728*cdf0e10cSrcweir TableTypeRef& pTableData = rDoc.maTables[itrTabName->second]; 729*cdf0e10cSrcweir if (!pTableData.get()) 730*cdf0e10cSrcweir pTableData.reset(new Table); 731*cdf0e10cSrcweir 732*cdf0e10cSrcweir pTableData->setCell(nCol, nRow, pToken, nFmtIndex); 733*cdf0e10cSrcweir pTableData->setCachedCell(nCol, nRow); 734*cdf0e10cSrcweir } 735*cdf0e10cSrcweir 736*cdf0e10cSrcweir void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData, 737*cdf0e10cSrcweir TokenArrayRef pArray) 738*cdf0e10cSrcweir { 739*cdf0e10cSrcweir using ::std::pair; 740*cdf0e10cSrcweir if (rData.empty() || !isDocInitialized(nFileId)) 741*cdf0e10cSrcweir // nothing to cache 742*cdf0e10cSrcweir return; 743*cdf0e10cSrcweir 744*cdf0e10cSrcweir // First, get the document item for the given file ID. 745*cdf0e10cSrcweir DocItem* pDocItem = getDocItem(nFileId); 746*cdf0e10cSrcweir if (!pDocItem) 747*cdf0e10cSrcweir return; 748*cdf0e10cSrcweir 749*cdf0e10cSrcweir DocItem& rDoc = *pDocItem; 750*cdf0e10cSrcweir 751*cdf0e10cSrcweir // Now, find the table position of the first table to cache. 752*cdf0e10cSrcweir const String& rFirstTabName = rData.front().maTableName; 753*cdf0e10cSrcweir TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find( 754*cdf0e10cSrcweir ScGlobal::pCharClass->upper(rFirstTabName)); 755*cdf0e10cSrcweir if (itrTabName == rDoc.maTableNameIndex.end()) 756*cdf0e10cSrcweir { 757*cdf0e10cSrcweir // table index not found. 758*cdf0e10cSrcweir return; 759*cdf0e10cSrcweir } 760*cdf0e10cSrcweir 761*cdf0e10cSrcweir size_t nTabFirstId = itrTabName->second; 762*cdf0e10cSrcweir SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row(); 763*cdf0e10cSrcweir SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col(); 764*cdf0e10cSrcweir vector<SingleRangeData>::const_iterator itrDataBeg = rData.begin(), itrDataEnd = rData.end(); 765*cdf0e10cSrcweir for (vector<SingleRangeData>::const_iterator itrData = itrDataBeg; itrData != itrDataEnd; ++itrData) 766*cdf0e10cSrcweir { 767*cdf0e10cSrcweir size_t i = nTabFirstId + ::std::distance(itrDataBeg, itrData); 768*cdf0e10cSrcweir TableTypeRef& pTabData = rDoc.maTables[i]; 769*cdf0e10cSrcweir if (!pTabData.get()) 770*cdf0e10cSrcweir pTabData.reset(new Table); 771*cdf0e10cSrcweir 772*cdf0e10cSrcweir for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) 773*cdf0e10cSrcweir { 774*cdf0e10cSrcweir for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) 775*cdf0e10cSrcweir { 776*cdf0e10cSrcweir SCSIZE nC = nCol - nCol1, nR = nRow - nRow1; 777*cdf0e10cSrcweir TokenRef pToken; 778*cdf0e10cSrcweir const ScMatrixRef& pMat = itrData->mpRangeData; 779*cdf0e10cSrcweir if (pMat->IsEmpty(nC, nR)) 780*cdf0e10cSrcweir // Don't cache empty cells. 781*cdf0e10cSrcweir continue; 782*cdf0e10cSrcweir 783*cdf0e10cSrcweir if (pMat->IsValue(nC, nR)) 784*cdf0e10cSrcweir pToken.reset(new formula::FormulaDoubleToken(pMat->GetDouble(nC, nR))); 785*cdf0e10cSrcweir else if (pMat->IsString(nC, nR)) 786*cdf0e10cSrcweir pToken.reset(new formula::FormulaStringToken(pMat->GetString(nC, nR))); 787*cdf0e10cSrcweir 788*cdf0e10cSrcweir if (pToken) 789*cdf0e10cSrcweir // Don't mark this cell 'cached' here, for better performance. 790*cdf0e10cSrcweir pTabData->setCell(nCol, nRow, pToken, 0, false); 791*cdf0e10cSrcweir } 792*cdf0e10cSrcweir } 793*cdf0e10cSrcweir // Mark the whole range 'cached'. 794*cdf0e10cSrcweir pTabData->setCachedCellRange(nCol1, nRow1, nCol2, nRow2); 795*cdf0e10cSrcweir } 796*cdf0e10cSrcweir 797*cdf0e10cSrcweir size_t nTabLastId = nTabFirstId + rRange.aEnd.Tab() - rRange.aStart.Tab(); 798*cdf0e10cSrcweir ScRange aCacheRange( nCol1, nRow1, static_cast<SCTAB>(nTabFirstId), nCol2, nRow2, static_cast<SCTAB>(nTabLastId)); 799*cdf0e10cSrcweir 800*cdf0e10cSrcweir rDoc.maRangeArrays.insert( RangeArrayMap::value_type( aCacheRange, pArray)); 801*cdf0e10cSrcweir } 802*cdf0e10cSrcweir 803*cdf0e10cSrcweir bool ScExternalRefCache::isDocInitialized(sal_uInt16 nFileId) 804*cdf0e10cSrcweir { 805*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 806*cdf0e10cSrcweir if (!pDoc) 807*cdf0e10cSrcweir return false; 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir return pDoc->mbInitFromSource; 810*cdf0e10cSrcweir } 811*cdf0e10cSrcweir 812*cdf0e10cSrcweir static bool lcl_getTableDataIndex(const ScExternalRefCache::TableNameIndexMap& rMap, const String& rName, size_t& rIndex) 813*cdf0e10cSrcweir { 814*cdf0e10cSrcweir ScExternalRefCache::TableNameIndexMap::const_iterator itr = rMap.find(rName); 815*cdf0e10cSrcweir if (itr == rMap.end()) 816*cdf0e10cSrcweir return false; 817*cdf0e10cSrcweir 818*cdf0e10cSrcweir rIndex = itr->second; 819*cdf0e10cSrcweir return true; 820*cdf0e10cSrcweir } 821*cdf0e10cSrcweir 822*cdf0e10cSrcweir void ScExternalRefCache::initializeDoc(sal_uInt16 nFileId, const vector<String>& rTabNames) 823*cdf0e10cSrcweir { 824*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 825*cdf0e10cSrcweir if (!pDoc) 826*cdf0e10cSrcweir return; 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir size_t n = rTabNames.size(); 829*cdf0e10cSrcweir 830*cdf0e10cSrcweir // table name list - the list must include all table names in the source 831*cdf0e10cSrcweir // document and only to be populated when loading the source document, not 832*cdf0e10cSrcweir // when loading cached data from, say, Excel XCT/CRN records. 833*cdf0e10cSrcweir vector<TableName> aNewTabNames; 834*cdf0e10cSrcweir aNewTabNames.reserve(n); 835*cdf0e10cSrcweir for (vector<String>::const_iterator itr = rTabNames.begin(), itrEnd = rTabNames.end(); 836*cdf0e10cSrcweir itr != itrEnd; ++itr) 837*cdf0e10cSrcweir { 838*cdf0e10cSrcweir TableName aNameItem(ScGlobal::pCharClass->upper(*itr), *itr); 839*cdf0e10cSrcweir aNewTabNames.push_back(aNameItem); 840*cdf0e10cSrcweir } 841*cdf0e10cSrcweir pDoc->maTableNames.swap(aNewTabNames); 842*cdf0e10cSrcweir 843*cdf0e10cSrcweir // data tables - preserve any existing data that may have been set during 844*cdf0e10cSrcweir // file import. 845*cdf0e10cSrcweir vector<TableTypeRef> aNewTables(n); 846*cdf0e10cSrcweir for (size_t i = 0; i < n; ++i) 847*cdf0e10cSrcweir { 848*cdf0e10cSrcweir size_t nIndex; 849*cdf0e10cSrcweir if (lcl_getTableDataIndex(pDoc->maTableNameIndex, pDoc->maTableNames[i].maUpperName, nIndex)) 850*cdf0e10cSrcweir { 851*cdf0e10cSrcweir aNewTables[i] = pDoc->maTables[nIndex]; 852*cdf0e10cSrcweir } 853*cdf0e10cSrcweir } 854*cdf0e10cSrcweir pDoc->maTables.swap(aNewTables); 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir // name index map 857*cdf0e10cSrcweir TableNameIndexMap aNewNameIndex; 858*cdf0e10cSrcweir for (size_t i = 0; i < n; ++i) 859*cdf0e10cSrcweir aNewNameIndex.insert(TableNameIndexMap::value_type(pDoc->maTableNames[i].maUpperName, i)); 860*cdf0e10cSrcweir pDoc->maTableNameIndex.swap(aNewNameIndex); 861*cdf0e10cSrcweir 862*cdf0e10cSrcweir pDoc->mbInitFromSource = true; 863*cdf0e10cSrcweir } 864*cdf0e10cSrcweir 865*cdf0e10cSrcweir String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const 866*cdf0e10cSrcweir { 867*cdf0e10cSrcweir if( DocItem* pDoc = getDocItem( nFileId ) ) 868*cdf0e10cSrcweir if( nCacheId < pDoc->maTableNames.size() ) 869*cdf0e10cSrcweir return pDoc->maTableNames[ nCacheId ].maRealName; 870*cdf0e10cSrcweir return EMPTY_STRING; 871*cdf0e10cSrcweir } 872*cdf0e10cSrcweir 873*cdf0e10cSrcweir void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const 874*cdf0e10cSrcweir { 875*cdf0e10cSrcweir rTabNames.clear(); 876*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 877*cdf0e10cSrcweir if (!pDoc) 878*cdf0e10cSrcweir return; 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir size_t n = pDoc->maTableNames.size(); 881*cdf0e10cSrcweir rTabNames.reserve(n); 882*cdf0e10cSrcweir for (vector<TableName>::const_iterator itr = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end(); 883*cdf0e10cSrcweir itr != itrEnd; ++itr) 884*cdf0e10cSrcweir rTabNames.push_back(itr->maRealName); 885*cdf0e10cSrcweir } 886*cdf0e10cSrcweir 887*cdf0e10cSrcweir SCsTAB ScExternalRefCache::getTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const 888*cdf0e10cSrcweir { 889*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 890*cdf0e10cSrcweir if (!pDoc) 891*cdf0e10cSrcweir return -1; 892*cdf0e10cSrcweir 893*cdf0e10cSrcweir vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(); 894*cdf0e10cSrcweir vector<TableName>::const_iterator itrEnd = pDoc->maTableNames.end(); 895*cdf0e10cSrcweir 896*cdf0e10cSrcweir vector<TableName>::const_iterator itrStartTab = ::std::find_if( itrBeg, itrEnd, 897*cdf0e10cSrcweir TabNameSearchPredicate( rStartTabName)); 898*cdf0e10cSrcweir if (itrStartTab == itrEnd) 899*cdf0e10cSrcweir return -1; 900*cdf0e10cSrcweir 901*cdf0e10cSrcweir vector<TableName>::const_iterator itrEndTab = ::std::find_if( itrBeg, itrEnd, 902*cdf0e10cSrcweir TabNameSearchPredicate( rEndTabName)); 903*cdf0e10cSrcweir if (itrEndTab == itrEnd) 904*cdf0e10cSrcweir return 0; 905*cdf0e10cSrcweir 906*cdf0e10cSrcweir size_t nStartDist = ::std::distance( itrBeg, itrStartTab); 907*cdf0e10cSrcweir size_t nEndDist = ::std::distance( itrBeg, itrEndTab); 908*cdf0e10cSrcweir return nStartDist <= nEndDist ? static_cast<SCsTAB>(nEndDist - nStartDist + 1) : -static_cast<SCsTAB>(nStartDist - nEndDist + 1); 909*cdf0e10cSrcweir } 910*cdf0e10cSrcweir 911*cdf0e10cSrcweir void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const 912*cdf0e10cSrcweir { 913*cdf0e10cSrcweir using ::std::sort; 914*cdf0e10cSrcweir using ::std::unique; 915*cdf0e10cSrcweir 916*cdf0e10cSrcweir vector<sal_uInt32> aNumFmts; 917*cdf0e10cSrcweir for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end(); 918*cdf0e10cSrcweir itrDoc != itrDocEnd; ++itrDoc) 919*cdf0e10cSrcweir { 920*cdf0e10cSrcweir const vector<TableTypeRef>& rTables = itrDoc->second.maTables; 921*cdf0e10cSrcweir for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end(); 922*cdf0e10cSrcweir itrTab != itrTabEnd; ++itrTab) 923*cdf0e10cSrcweir { 924*cdf0e10cSrcweir TableTypeRef pTab = *itrTab; 925*cdf0e10cSrcweir if (!pTab) 926*cdf0e10cSrcweir continue; 927*cdf0e10cSrcweir 928*cdf0e10cSrcweir pTab->getAllNumberFormats(aNumFmts); 929*cdf0e10cSrcweir } 930*cdf0e10cSrcweir } 931*cdf0e10cSrcweir 932*cdf0e10cSrcweir // remove duplicates. 933*cdf0e10cSrcweir sort(aNumFmts.begin(), aNumFmts.end()); 934*cdf0e10cSrcweir aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end()); 935*cdf0e10cSrcweir rNumFmts.swap(aNumFmts); 936*cdf0e10cSrcweir } 937*cdf0e10cSrcweir 938*cdf0e10cSrcweir bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId ) 939*cdf0e10cSrcweir { 940*cdf0e10cSrcweir DocItem* pDocItem = getDocItem(nFileId); 941*cdf0e10cSrcweir if (!pDocItem) 942*cdf0e10cSrcweir return areAllCacheTablesReferenced(); 943*cdf0e10cSrcweir 944*cdf0e10cSrcweir for (::std::vector<TableTypeRef>::iterator itrTab = pDocItem->maTables.begin(); 945*cdf0e10cSrcweir itrTab != pDocItem->maTables.end(); ++itrTab) 946*cdf0e10cSrcweir { 947*cdf0e10cSrcweir if ((*itrTab).get()) 948*cdf0e10cSrcweir (*itrTab)->setReferenced( true); 949*cdf0e10cSrcweir } 950*cdf0e10cSrcweir addCacheDocToReferenced( nFileId); 951*cdf0e10cSrcweir return areAllCacheTablesReferenced(); 952*cdf0e10cSrcweir } 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent ) 955*cdf0e10cSrcweir { 956*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 957*cdf0e10cSrcweir if (pDoc) 958*cdf0e10cSrcweir { 959*cdf0e10cSrcweir size_t nIndex = 0; 960*cdf0e10cSrcweir String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName); 961*cdf0e10cSrcweir if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex)) 962*cdf0e10cSrcweir { 963*cdf0e10cSrcweir size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size()); 964*cdf0e10cSrcweir for (size_t i = nIndex; i < nStop; ++i) 965*cdf0e10cSrcweir { 966*cdf0e10cSrcweir TableTypeRef pTab = pDoc->maTables[i]; 967*cdf0e10cSrcweir if (pTab.get()) 968*cdf0e10cSrcweir { 969*cdf0e10cSrcweir Table::ReferencedFlag eNewFlag = (bPermanent ? 970*cdf0e10cSrcweir Table::REFERENCED_PERMANENT : 971*cdf0e10cSrcweir Table::REFERENCED_MARKED); 972*cdf0e10cSrcweir Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag(); 973*cdf0e10cSrcweir if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag) 974*cdf0e10cSrcweir { 975*cdf0e10cSrcweir pTab->setReferencedFlag( eNewFlag); 976*cdf0e10cSrcweir addCacheTableToReferenced( nFileId, i); 977*cdf0e10cSrcweir } 978*cdf0e10cSrcweir } 979*cdf0e10cSrcweir } 980*cdf0e10cSrcweir } 981*cdf0e10cSrcweir } 982*cdf0e10cSrcweir return areAllCacheTablesReferenced(); 983*cdf0e10cSrcweir } 984*cdf0e10cSrcweir 985*cdf0e10cSrcweir void ScExternalRefCache::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) 986*cdf0e10cSrcweir { 987*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 988*cdf0e10cSrcweir if (pDoc) 989*cdf0e10cSrcweir { 990*cdf0e10cSrcweir size_t nIndex = 0; 991*cdf0e10cSrcweir String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName); 992*cdf0e10cSrcweir if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex)) 993*cdf0e10cSrcweir { 994*cdf0e10cSrcweir size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size()); 995*cdf0e10cSrcweir for (size_t i = nIndex; i < nStop; ++i) 996*cdf0e10cSrcweir { 997*cdf0e10cSrcweir TableTypeRef pTab = pDoc->maTables[i]; 998*cdf0e10cSrcweir if (pTab.get()) 999*cdf0e10cSrcweir pTab->setReferencedFlag( Table::REFERENCED_PERMANENT); 1000*cdf0e10cSrcweir } 1001*cdf0e10cSrcweir } 1002*cdf0e10cSrcweir } 1003*cdf0e10cSrcweir } 1004*cdf0e10cSrcweir 1005*cdf0e10cSrcweir void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced ) 1006*cdf0e10cSrcweir { 1007*cdf0e10cSrcweir if (bReferenced) 1008*cdf0e10cSrcweir { 1009*cdf0e10cSrcweir maReferenced.reset(0); 1010*cdf0e10cSrcweir for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc) 1011*cdf0e10cSrcweir { 1012*cdf0e10cSrcweir ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second; 1013*cdf0e10cSrcweir for (::std::vector<TableTypeRef>::iterator itrTab = rDocItem.maTables.begin(); 1014*cdf0e10cSrcweir itrTab != rDocItem.maTables.end(); ++itrTab) 1015*cdf0e10cSrcweir { 1016*cdf0e10cSrcweir if ((*itrTab).get()) 1017*cdf0e10cSrcweir (*itrTab)->setReferenced( true); 1018*cdf0e10cSrcweir } 1019*cdf0e10cSrcweir } 1020*cdf0e10cSrcweir } 1021*cdf0e10cSrcweir else 1022*cdf0e10cSrcweir { 1023*cdf0e10cSrcweir size_t nDocs = 0; 1024*cdf0e10cSrcweir for (DocDataType::const_iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc) 1025*cdf0e10cSrcweir { 1026*cdf0e10cSrcweir if (nDocs <= (*itrDoc).first) 1027*cdf0e10cSrcweir nDocs = (*itrDoc).first + 1; 1028*cdf0e10cSrcweir } 1029*cdf0e10cSrcweir maReferenced.reset( nDocs); 1030*cdf0e10cSrcweir 1031*cdf0e10cSrcweir for (DocDataType::iterator itrDoc = maDocs.begin(); itrDoc != maDocs.end(); ++itrDoc) 1032*cdf0e10cSrcweir { 1033*cdf0e10cSrcweir ScExternalRefCache::DocItem& rDocItem = (*itrDoc).second; 1034*cdf0e10cSrcweir sal_uInt16 nFileId = (*itrDoc).first; 1035*cdf0e10cSrcweir size_t nTables = rDocItem.maTables.size(); 1036*cdf0e10cSrcweir ReferencedStatus::DocReferenced & rDocReferenced = maReferenced.maDocs[nFileId]; 1037*cdf0e10cSrcweir // All referenced => non-existing tables evaluate as completed. 1038*cdf0e10cSrcweir rDocReferenced.maTables.resize( nTables, true); 1039*cdf0e10cSrcweir for (size_t i=0; i < nTables; ++i) 1040*cdf0e10cSrcweir { 1041*cdf0e10cSrcweir TableTypeRef & xTab = rDocItem.maTables[i]; 1042*cdf0e10cSrcweir if (xTab.get()) 1043*cdf0e10cSrcweir { 1044*cdf0e10cSrcweir if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT) 1045*cdf0e10cSrcweir addCacheTableToReferenced( nFileId, i); 1046*cdf0e10cSrcweir else 1047*cdf0e10cSrcweir { 1048*cdf0e10cSrcweir xTab->setReferencedFlag( Table::UNREFERENCED); 1049*cdf0e10cSrcweir rDocReferenced.maTables[i] = false; 1050*cdf0e10cSrcweir rDocReferenced.mbAllTablesReferenced = false; 1051*cdf0e10cSrcweir // An addCacheTableToReferenced() actually may have 1052*cdf0e10cSrcweir // resulted in mbAllReferenced been set. Clear it. 1053*cdf0e10cSrcweir maReferenced.mbAllReferenced = false; 1054*cdf0e10cSrcweir } 1055*cdf0e10cSrcweir } 1056*cdf0e10cSrcweir } 1057*cdf0e10cSrcweir } 1058*cdf0e10cSrcweir } 1059*cdf0e10cSrcweir } 1060*cdf0e10cSrcweir 1061*cdf0e10cSrcweir void ScExternalRefCache::addCacheTableToReferenced( sal_uInt16 nFileId, size_t nIndex ) 1062*cdf0e10cSrcweir { 1063*cdf0e10cSrcweir if (nFileId >= maReferenced.maDocs.size()) 1064*cdf0e10cSrcweir return; 1065*cdf0e10cSrcweir 1066*cdf0e10cSrcweir ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables; 1067*cdf0e10cSrcweir size_t nTables = rTables.size(); 1068*cdf0e10cSrcweir if (nIndex >= nTables) 1069*cdf0e10cSrcweir return; 1070*cdf0e10cSrcweir 1071*cdf0e10cSrcweir if (!rTables[nIndex]) 1072*cdf0e10cSrcweir { 1073*cdf0e10cSrcweir rTables[nIndex] = true; 1074*cdf0e10cSrcweir size_t i = 0; 1075*cdf0e10cSrcweir while (i < nTables && rTables[i]) 1076*cdf0e10cSrcweir ++i; 1077*cdf0e10cSrcweir if (i == nTables) 1078*cdf0e10cSrcweir { 1079*cdf0e10cSrcweir maReferenced.maDocs[nFileId].mbAllTablesReferenced = true; 1080*cdf0e10cSrcweir maReferenced.checkAllDocs(); 1081*cdf0e10cSrcweir } 1082*cdf0e10cSrcweir } 1083*cdf0e10cSrcweir } 1084*cdf0e10cSrcweir 1085*cdf0e10cSrcweir void ScExternalRefCache::addCacheDocToReferenced( sal_uInt16 nFileId ) 1086*cdf0e10cSrcweir { 1087*cdf0e10cSrcweir if (nFileId >= maReferenced.maDocs.size()) 1088*cdf0e10cSrcweir return; 1089*cdf0e10cSrcweir 1090*cdf0e10cSrcweir if (!maReferenced.maDocs[nFileId].mbAllTablesReferenced) 1091*cdf0e10cSrcweir { 1092*cdf0e10cSrcweir ::std::vector<bool> & rTables = maReferenced.maDocs[nFileId].maTables; 1093*cdf0e10cSrcweir size_t nSize = rTables.size(); 1094*cdf0e10cSrcweir for (size_t i=0; i < nSize; ++i) 1095*cdf0e10cSrcweir rTables[i] = true; 1096*cdf0e10cSrcweir maReferenced.maDocs[nFileId].mbAllTablesReferenced = true; 1097*cdf0e10cSrcweir maReferenced.checkAllDocs(); 1098*cdf0e10cSrcweir } 1099*cdf0e10cSrcweir } 1100*cdf0e10cSrcweir 1101*cdf0e10cSrcweir bool ScExternalRefCache::areAllCacheTablesReferenced() const 1102*cdf0e10cSrcweir { 1103*cdf0e10cSrcweir return maReferenced.mbAllReferenced; 1104*cdf0e10cSrcweir } 1105*cdf0e10cSrcweir 1106*cdf0e10cSrcweir ScExternalRefCache::ReferencedStatus::ReferencedStatus() : 1107*cdf0e10cSrcweir mbAllReferenced(false) 1108*cdf0e10cSrcweir { 1109*cdf0e10cSrcweir reset(0); 1110*cdf0e10cSrcweir } 1111*cdf0e10cSrcweir 1112*cdf0e10cSrcweir ScExternalRefCache::ReferencedStatus::ReferencedStatus( size_t nDocs ) : 1113*cdf0e10cSrcweir mbAllReferenced(false) 1114*cdf0e10cSrcweir { 1115*cdf0e10cSrcweir reset( nDocs); 1116*cdf0e10cSrcweir } 1117*cdf0e10cSrcweir 1118*cdf0e10cSrcweir void ScExternalRefCache::ReferencedStatus::reset( size_t nDocs ) 1119*cdf0e10cSrcweir { 1120*cdf0e10cSrcweir if (nDocs) 1121*cdf0e10cSrcweir { 1122*cdf0e10cSrcweir mbAllReferenced = false; 1123*cdf0e10cSrcweir DocReferencedVec aRefs( nDocs); 1124*cdf0e10cSrcweir maDocs.swap( aRefs); 1125*cdf0e10cSrcweir } 1126*cdf0e10cSrcweir else 1127*cdf0e10cSrcweir { 1128*cdf0e10cSrcweir mbAllReferenced = true; 1129*cdf0e10cSrcweir DocReferencedVec aRefs; 1130*cdf0e10cSrcweir maDocs.swap( aRefs); 1131*cdf0e10cSrcweir } 1132*cdf0e10cSrcweir } 1133*cdf0e10cSrcweir 1134*cdf0e10cSrcweir void ScExternalRefCache::ReferencedStatus::checkAllDocs() 1135*cdf0e10cSrcweir { 1136*cdf0e10cSrcweir for (DocReferencedVec::const_iterator itr = maDocs.begin(); itr != maDocs.end(); ++itr) 1137*cdf0e10cSrcweir { 1138*cdf0e10cSrcweir if (!(*itr).mbAllTablesReferenced) 1139*cdf0e10cSrcweir return; 1140*cdf0e10cSrcweir } 1141*cdf0e10cSrcweir mbAllReferenced = true; 1142*cdf0e10cSrcweir } 1143*cdf0e10cSrcweir 1144*cdf0e10cSrcweir ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const 1145*cdf0e10cSrcweir { 1146*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 1147*cdf0e10cSrcweir if (!pDoc || nTabIndex >= pDoc->maTables.size()) 1148*cdf0e10cSrcweir return TableTypeRef(); 1149*cdf0e10cSrcweir 1150*cdf0e10cSrcweir return pDoc->maTables[nTabIndex]; 1151*cdf0e10cSrcweir } 1152*cdf0e10cSrcweir 1153*cdf0e10cSrcweir ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex) 1154*cdf0e10cSrcweir { 1155*cdf0e10cSrcweir // In API, the index is transported as cached sheet ID of type sal_Int32 in 1156*cdf0e10cSrcweir // sheet::SingleReference.Sheet or sheet::ComplexReference.Reference1.Sheet 1157*cdf0e10cSrcweir // in a sheet::FormulaToken, choose a sensible value for N/A. Effectively 1158*cdf0e10cSrcweir // being 0xffffffff 1159*cdf0e10cSrcweir const size_t nNotAvailable = static_cast<size_t>( static_cast<sal_Int32>( -1)); 1160*cdf0e10cSrcweir 1161*cdf0e10cSrcweir DocItem* pDoc = getDocItem(nFileId); 1162*cdf0e10cSrcweir if (!pDoc) 1163*cdf0e10cSrcweir { 1164*cdf0e10cSrcweir if (pnIndex) *pnIndex = nNotAvailable; 1165*cdf0e10cSrcweir return TableTypeRef(); 1166*cdf0e10cSrcweir } 1167*cdf0e10cSrcweir 1168*cdf0e10cSrcweir DocItem& rDoc = *pDoc; 1169*cdf0e10cSrcweir 1170*cdf0e10cSrcweir size_t nIndex; 1171*cdf0e10cSrcweir String aTabNameUpper = ScGlobal::pCharClass->upper(rTabName); 1172*cdf0e10cSrcweir if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex)) 1173*cdf0e10cSrcweir { 1174*cdf0e10cSrcweir // specified table found. 1175*cdf0e10cSrcweir if( pnIndex ) *pnIndex = nIndex; 1176*cdf0e10cSrcweir if (bCreateNew && !rDoc.maTables[nIndex]) 1177*cdf0e10cSrcweir rDoc.maTables[nIndex].reset(new Table); 1178*cdf0e10cSrcweir 1179*cdf0e10cSrcweir return rDoc.maTables[nIndex]; 1180*cdf0e10cSrcweir } 1181*cdf0e10cSrcweir 1182*cdf0e10cSrcweir if (!bCreateNew) 1183*cdf0e10cSrcweir { 1184*cdf0e10cSrcweir if (pnIndex) *pnIndex = nNotAvailable; 1185*cdf0e10cSrcweir return TableTypeRef(); 1186*cdf0e10cSrcweir } 1187*cdf0e10cSrcweir 1188*cdf0e10cSrcweir // Specified table doesn't exist yet. Create one. 1189*cdf0e10cSrcweir nIndex = rDoc.maTables.size(); 1190*cdf0e10cSrcweir if( pnIndex ) *pnIndex = nIndex; 1191*cdf0e10cSrcweir TableTypeRef pTab(new Table); 1192*cdf0e10cSrcweir rDoc.maTables.push_back(pTab); 1193*cdf0e10cSrcweir rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName)); 1194*cdf0e10cSrcweir rDoc.maTableNameIndex.insert( 1195*cdf0e10cSrcweir TableNameIndexMap::value_type(aTabNameUpper, nIndex)); 1196*cdf0e10cSrcweir return pTab; 1197*cdf0e10cSrcweir } 1198*cdf0e10cSrcweir 1199*cdf0e10cSrcweir void ScExternalRefCache::clearCache(sal_uInt16 nFileId) 1200*cdf0e10cSrcweir { 1201*cdf0e10cSrcweir maDocs.erase(nFileId); 1202*cdf0e10cSrcweir } 1203*cdf0e10cSrcweir 1204*cdf0e10cSrcweir ScExternalRefCache::DocItem* ScExternalRefCache::getDocItem(sal_uInt16 nFileId) const 1205*cdf0e10cSrcweir { 1206*cdf0e10cSrcweir using ::std::pair; 1207*cdf0e10cSrcweir DocDataType::iterator itrDoc = maDocs.find(nFileId); 1208*cdf0e10cSrcweir if (itrDoc == maDocs.end()) 1209*cdf0e10cSrcweir { 1210*cdf0e10cSrcweir // specified document is not cached. 1211*cdf0e10cSrcweir pair<DocDataType::iterator, bool> res = maDocs.insert( 1212*cdf0e10cSrcweir DocDataType::value_type(nFileId, DocItem())); 1213*cdf0e10cSrcweir 1214*cdf0e10cSrcweir if (!res.second) 1215*cdf0e10cSrcweir // insertion failed. 1216*cdf0e10cSrcweir return NULL; 1217*cdf0e10cSrcweir 1218*cdf0e10cSrcweir itrDoc = res.first; 1219*cdf0e10cSrcweir } 1220*cdf0e10cSrcweir 1221*cdf0e10cSrcweir return &itrDoc->second; 1222*cdf0e10cSrcweir } 1223*cdf0e10cSrcweir 1224*cdf0e10cSrcweir // ============================================================================ 1225*cdf0e10cSrcweir 1226*cdf0e10cSrcweir ScExternalRefLink::ScExternalRefLink(ScDocument* pDoc, sal_uInt16 nFileId, const String& rFilter) : 1227*cdf0e10cSrcweir ::sfx2::SvBaseLink(::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE), 1228*cdf0e10cSrcweir mnFileId(nFileId), 1229*cdf0e10cSrcweir maFilterName(rFilter), 1230*cdf0e10cSrcweir mpDoc(pDoc), 1231*cdf0e10cSrcweir mbDoRefresh(true) 1232*cdf0e10cSrcweir { 1233*cdf0e10cSrcweir } 1234*cdf0e10cSrcweir 1235*cdf0e10cSrcweir ScExternalRefLink::~ScExternalRefLink() 1236*cdf0e10cSrcweir { 1237*cdf0e10cSrcweir } 1238*cdf0e10cSrcweir 1239*cdf0e10cSrcweir void ScExternalRefLink::Closed() 1240*cdf0e10cSrcweir { 1241*cdf0e10cSrcweir ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager(); 1242*cdf0e10cSrcweir pMgr->breakLink(mnFileId); 1243*cdf0e10cSrcweir } 1244*cdf0e10cSrcweir 1245*cdf0e10cSrcweir void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rValue*/) 1246*cdf0e10cSrcweir { 1247*cdf0e10cSrcweir if (!mbDoRefresh) 1248*cdf0e10cSrcweir return; 1249*cdf0e10cSrcweir 1250*cdf0e10cSrcweir String aFile, aFilter; 1251*cdf0e10cSrcweir mpDoc->GetLinkManager()->GetDisplayNames(this, NULL, &aFile, NULL, &aFilter); 1252*cdf0e10cSrcweir ScExternalRefManager* pMgr = mpDoc->GetExternalRefManager(); 1253*cdf0e10cSrcweir const String* pCurFile = pMgr->getExternalFileName(mnFileId); 1254*cdf0e10cSrcweir if (!pCurFile) 1255*cdf0e10cSrcweir return; 1256*cdf0e10cSrcweir 1257*cdf0e10cSrcweir if (pCurFile->Equals(aFile)) 1258*cdf0e10cSrcweir { 1259*cdf0e10cSrcweir // Refresh the current source document. 1260*cdf0e10cSrcweir pMgr->refreshNames(mnFileId); 1261*cdf0e10cSrcweir } 1262*cdf0e10cSrcweir else 1263*cdf0e10cSrcweir { 1264*cdf0e10cSrcweir // The source document has changed. 1265*cdf0e10cSrcweir ScDocShell* pDocShell = ScDocShell::GetViewData()->GetDocShell(); 1266*cdf0e10cSrcweir ScDocShellModificator aMod(*pDocShell); 1267*cdf0e10cSrcweir pMgr->switchSrcFile(mnFileId, aFile, aFilter); 1268*cdf0e10cSrcweir maFilterName = aFilter; 1269*cdf0e10cSrcweir aMod.SetDocumentModified(); 1270*cdf0e10cSrcweir } 1271*cdf0e10cSrcweir } 1272*cdf0e10cSrcweir 1273*cdf0e10cSrcweir void ScExternalRefLink::Edit(Window* pParent, const Link& /*rEndEditHdl*/) 1274*cdf0e10cSrcweir { 1275*cdf0e10cSrcweir SvBaseLink::Edit(pParent, LINK(this, ScExternalRefLink, ExternalRefEndEditHdl)); 1276*cdf0e10cSrcweir } 1277*cdf0e10cSrcweir 1278*cdf0e10cSrcweir void ScExternalRefLink::SetDoReferesh(bool b) 1279*cdf0e10cSrcweir { 1280*cdf0e10cSrcweir mbDoRefresh = b; 1281*cdf0e10cSrcweir } 1282*cdf0e10cSrcweir 1283*cdf0e10cSrcweir IMPL_LINK( ScExternalRefLink, ExternalRefEndEditHdl, ::sfx2::SvBaseLink*, EMPTYARG ) 1284*cdf0e10cSrcweir { 1285*cdf0e10cSrcweir return 0; 1286*cdf0e10cSrcweir } 1287*cdf0e10cSrcweir 1288*cdf0e10cSrcweir // ============================================================================ 1289*cdf0e10cSrcweir 1290*cdf0e10cSrcweir static FormulaToken* lcl_convertToToken(ScBaseCell* pCell) 1291*cdf0e10cSrcweir { 1292*cdf0e10cSrcweir if (!pCell || pCell->HasEmptyData()) 1293*cdf0e10cSrcweir { 1294*cdf0e10cSrcweir bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA); 1295*cdf0e10cSrcweir return new ScEmptyCellToken( bInherited, false); 1296*cdf0e10cSrcweir } 1297*cdf0e10cSrcweir 1298*cdf0e10cSrcweir switch (pCell->GetCellType()) 1299*cdf0e10cSrcweir { 1300*cdf0e10cSrcweir case CELLTYPE_EDIT: 1301*cdf0e10cSrcweir { 1302*cdf0e10cSrcweir String aStr; 1303*cdf0e10cSrcweir static_cast<ScEditCell*>(pCell)->GetString(aStr); 1304*cdf0e10cSrcweir return new formula::FormulaStringToken(aStr); 1305*cdf0e10cSrcweir } 1306*cdf0e10cSrcweir //break; 1307*cdf0e10cSrcweir case CELLTYPE_STRING: 1308*cdf0e10cSrcweir { 1309*cdf0e10cSrcweir String aStr; 1310*cdf0e10cSrcweir static_cast<ScStringCell*>(pCell)->GetString(aStr); 1311*cdf0e10cSrcweir return new formula::FormulaStringToken(aStr); 1312*cdf0e10cSrcweir } 1313*cdf0e10cSrcweir //break; 1314*cdf0e10cSrcweir case CELLTYPE_VALUE: 1315*cdf0e10cSrcweir { 1316*cdf0e10cSrcweir double fVal = static_cast<ScValueCell*>(pCell)->GetValue(); 1317*cdf0e10cSrcweir return new formula::FormulaDoubleToken(fVal); 1318*cdf0e10cSrcweir } 1319*cdf0e10cSrcweir //break; 1320*cdf0e10cSrcweir case CELLTYPE_FORMULA: 1321*cdf0e10cSrcweir { 1322*cdf0e10cSrcweir ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 1323*cdf0e10cSrcweir sal_uInt16 nError = pFCell->GetErrCode(); 1324*cdf0e10cSrcweir if (nError) 1325*cdf0e10cSrcweir return new FormulaErrorToken( nError); 1326*cdf0e10cSrcweir else if (pFCell->IsValue()) 1327*cdf0e10cSrcweir { 1328*cdf0e10cSrcweir double fVal = pFCell->GetValue(); 1329*cdf0e10cSrcweir return new formula::FormulaDoubleToken(fVal); 1330*cdf0e10cSrcweir } 1331*cdf0e10cSrcweir else 1332*cdf0e10cSrcweir { 1333*cdf0e10cSrcweir String aStr; 1334*cdf0e10cSrcweir pFCell->GetString(aStr); 1335*cdf0e10cSrcweir return new formula::FormulaStringToken(aStr); 1336*cdf0e10cSrcweir } 1337*cdf0e10cSrcweir } 1338*cdf0e10cSrcweir //break; 1339*cdf0e10cSrcweir default: 1340*cdf0e10cSrcweir DBG_ERROR("attempted to convert an unknown cell type."); 1341*cdf0e10cSrcweir } 1342*cdf0e10cSrcweir 1343*cdf0e10cSrcweir return NULL; 1344*cdf0e10cSrcweir } 1345*cdf0e10cSrcweir 1346*cdf0e10cSrcweir static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, ScRange& rRange, 1347*cdf0e10cSrcweir vector<ScExternalRefCache::SingleRangeData>& rCacheData) 1348*cdf0e10cSrcweir { 1349*cdf0e10cSrcweir ScAddress& s = rRange.aStart; 1350*cdf0e10cSrcweir ScAddress& e = rRange.aEnd; 1351*cdf0e10cSrcweir 1352*cdf0e10cSrcweir SCTAB nTab1 = s.Tab(), nTab2 = e.Tab(); 1353*cdf0e10cSrcweir SCCOL nCol1 = s.Col(), nCol2 = e.Col(); 1354*cdf0e10cSrcweir SCROW nRow1 = s.Row(), nRow2 = e.Row(); 1355*cdf0e10cSrcweir 1356*cdf0e10cSrcweir if (nTab2 != nTab1) 1357*cdf0e10cSrcweir // For now, we don't support multi-sheet ranges intentionally because 1358*cdf0e10cSrcweir // we don't have a way to express them in a single token. In the 1359*cdf0e10cSrcweir // future we can introduce a new stack variable type svMatrixList with 1360*cdf0e10cSrcweir // a new token type that can store a 3D matrix value and convert a 3D 1361*cdf0e10cSrcweir // range to it. 1362*cdf0e10cSrcweir return NULL; 1363*cdf0e10cSrcweir 1364*cdf0e10cSrcweir ::boost::scoped_ptr<ScRange> pUsedRange; 1365*cdf0e10cSrcweir 1366*cdf0e10cSrcweir auto_ptr<ScTokenArray> pArray(new ScTokenArray); 1367*cdf0e10cSrcweir bool bFirstTab = true; 1368*cdf0e10cSrcweir vector<ScExternalRefCache::SingleRangeData>::iterator 1369*cdf0e10cSrcweir itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end(); 1370*cdf0e10cSrcweir 1371*cdf0e10cSrcweir for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache) 1372*cdf0e10cSrcweir { 1373*cdf0e10cSrcweir // Only loop within the data area. 1374*cdf0e10cSrcweir SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2; 1375*cdf0e10cSrcweir SCROW nDataRow1 = nRow1, nDataRow2 = nRow2; 1376*cdf0e10cSrcweir bool bShrunk; 1377*cdf0e10cSrcweir if (!pSrcDoc->ShrinkToUsedDataArea( bShrunk, nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2, false)) 1378*cdf0e10cSrcweir // no data within specified range. 1379*cdf0e10cSrcweir continue; 1380*cdf0e10cSrcweir 1381*cdf0e10cSrcweir if (pUsedRange.get()) 1382*cdf0e10cSrcweir // Make sure the used area only grows, not shrinks. 1383*cdf0e10cSrcweir pUsedRange->ExtendTo(ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); 1384*cdf0e10cSrcweir else 1385*cdf0e10cSrcweir pUsedRange.reset(new ScRange(nDataCol1, nDataRow1, 0, nDataCol2, nDataRow2, 0)); 1386*cdf0e10cSrcweir 1387*cdf0e10cSrcweir ScMatrixRef xMat = new ScMatrix( 1388*cdf0e10cSrcweir static_cast<SCSIZE>(nDataCol2-nDataCol1+1), 1389*cdf0e10cSrcweir static_cast<SCSIZE>(nDataRow2-nDataRow1+1)); 1390*cdf0e10cSrcweir 1391*cdf0e10cSrcweir for (SCCOL nCol = nDataCol1; nCol <= nDataCol2; ++nCol) 1392*cdf0e10cSrcweir { 1393*cdf0e10cSrcweir for (SCROW nRow = nDataRow1; nRow <= nDataRow2; ++nRow) 1394*cdf0e10cSrcweir { 1395*cdf0e10cSrcweir SCSIZE nC = nCol - nCol1, nR = nRow - nRow1; 1396*cdf0e10cSrcweir ScBaseCell* pCell; 1397*cdf0e10cSrcweir pSrcDoc->GetCell(nCol, nRow, nTab, pCell); 1398*cdf0e10cSrcweir if (!pCell || pCell->HasEmptyData()) 1399*cdf0e10cSrcweir xMat->PutEmpty(nC, nR); 1400*cdf0e10cSrcweir else 1401*cdf0e10cSrcweir { 1402*cdf0e10cSrcweir switch (pCell->GetCellType()) 1403*cdf0e10cSrcweir { 1404*cdf0e10cSrcweir case CELLTYPE_EDIT: 1405*cdf0e10cSrcweir { 1406*cdf0e10cSrcweir String aStr; 1407*cdf0e10cSrcweir static_cast<ScEditCell*>(pCell)->GetString(aStr); 1408*cdf0e10cSrcweir xMat->PutString(aStr, nC, nR); 1409*cdf0e10cSrcweir } 1410*cdf0e10cSrcweir break; 1411*cdf0e10cSrcweir case CELLTYPE_STRING: 1412*cdf0e10cSrcweir { 1413*cdf0e10cSrcweir String aStr; 1414*cdf0e10cSrcweir static_cast<ScStringCell*>(pCell)->GetString(aStr); 1415*cdf0e10cSrcweir xMat->PutString(aStr, nC, nR); 1416*cdf0e10cSrcweir } 1417*cdf0e10cSrcweir break; 1418*cdf0e10cSrcweir case CELLTYPE_VALUE: 1419*cdf0e10cSrcweir { 1420*cdf0e10cSrcweir double fVal = static_cast<ScValueCell*>(pCell)->GetValue(); 1421*cdf0e10cSrcweir xMat->PutDouble(fVal, nC, nR); 1422*cdf0e10cSrcweir } 1423*cdf0e10cSrcweir break; 1424*cdf0e10cSrcweir case CELLTYPE_FORMULA: 1425*cdf0e10cSrcweir { 1426*cdf0e10cSrcweir ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); 1427*cdf0e10cSrcweir sal_uInt16 nError = pFCell->GetErrCode(); 1428*cdf0e10cSrcweir if (nError) 1429*cdf0e10cSrcweir xMat->PutDouble( CreateDoubleError( nError), nC, nR); 1430*cdf0e10cSrcweir else if (pFCell->IsValue()) 1431*cdf0e10cSrcweir { 1432*cdf0e10cSrcweir double fVal = pFCell->GetValue(); 1433*cdf0e10cSrcweir xMat->PutDouble(fVal, nC, nR); 1434*cdf0e10cSrcweir } 1435*cdf0e10cSrcweir else 1436*cdf0e10cSrcweir { 1437*cdf0e10cSrcweir String aStr; 1438*cdf0e10cSrcweir pFCell->GetString(aStr); 1439*cdf0e10cSrcweir xMat->PutString(aStr, nC, nR); 1440*cdf0e10cSrcweir } 1441*cdf0e10cSrcweir } 1442*cdf0e10cSrcweir break; 1443*cdf0e10cSrcweir default: 1444*cdf0e10cSrcweir DBG_ERROR("attempted to convert an unknown cell type."); 1445*cdf0e10cSrcweir } 1446*cdf0e10cSrcweir } 1447*cdf0e10cSrcweir } 1448*cdf0e10cSrcweir } 1449*cdf0e10cSrcweir if (!bFirstTab) 1450*cdf0e10cSrcweir pArray->AddOpCode(ocSep); 1451*cdf0e10cSrcweir 1452*cdf0e10cSrcweir ScMatrix* pMat2 = xMat; 1453*cdf0e10cSrcweir ScMatrixToken aToken(pMat2); 1454*cdf0e10cSrcweir pArray->AddToken(aToken); 1455*cdf0e10cSrcweir 1456*cdf0e10cSrcweir itrCache->mpRangeData = xMat; 1457*cdf0e10cSrcweir 1458*cdf0e10cSrcweir bFirstTab = false; 1459*cdf0e10cSrcweir } 1460*cdf0e10cSrcweir 1461*cdf0e10cSrcweir if (!pUsedRange.get()) 1462*cdf0e10cSrcweir return NULL; 1463*cdf0e10cSrcweir 1464*cdf0e10cSrcweir s.SetCol(pUsedRange->aStart.Col()); 1465*cdf0e10cSrcweir s.SetRow(pUsedRange->aStart.Row()); 1466*cdf0e10cSrcweir e.SetCol(pUsedRange->aEnd.Col()); 1467*cdf0e10cSrcweir e.SetRow(pUsedRange->aEnd.Row()); 1468*cdf0e10cSrcweir 1469*cdf0e10cSrcweir return pArray.release(); 1470*cdf0e10cSrcweir } 1471*cdf0e10cSrcweir 1472*cdf0e10cSrcweir static ScTokenArray* lcl_fillEmptyMatrix(const ScRange& rRange) 1473*cdf0e10cSrcweir { 1474*cdf0e10cSrcweir SCSIZE nC = static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1); 1475*cdf0e10cSrcweir SCSIZE nR = static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1); 1476*cdf0e10cSrcweir ScMatrixRef xMat = new ScMatrix(nC, nR); 1477*cdf0e10cSrcweir for (SCSIZE i = 0; i < nC; ++i) 1478*cdf0e10cSrcweir for (SCSIZE j = 0; j < nR; ++j) 1479*cdf0e10cSrcweir xMat->PutEmpty(i, j); 1480*cdf0e10cSrcweir 1481*cdf0e10cSrcweir ScMatrix* pMat2 = xMat; 1482*cdf0e10cSrcweir ScMatrixToken aToken(pMat2); 1483*cdf0e10cSrcweir auto_ptr<ScTokenArray> pArray(new ScTokenArray); 1484*cdf0e10cSrcweir pArray->AddToken(aToken); 1485*cdf0e10cSrcweir return pArray.release(); 1486*cdf0e10cSrcweir } 1487*cdf0e10cSrcweir 1488*cdf0e10cSrcweir ScExternalRefManager::ScExternalRefManager(ScDocument* pDoc) : 1489*cdf0e10cSrcweir mpDoc(pDoc), 1490*cdf0e10cSrcweir mbInReferenceMarking(false), 1491*cdf0e10cSrcweir mbUserInteractionEnabled(true) 1492*cdf0e10cSrcweir { 1493*cdf0e10cSrcweir maSrcDocTimer.SetTimeoutHdl( LINK(this, ScExternalRefManager, TimeOutHdl) ); 1494*cdf0e10cSrcweir maSrcDocTimer.SetTimeout(SRCDOC_SCAN_INTERVAL); 1495*cdf0e10cSrcweir } 1496*cdf0e10cSrcweir 1497*cdf0e10cSrcweir ScExternalRefManager::~ScExternalRefManager() 1498*cdf0e10cSrcweir { 1499*cdf0e10cSrcweir clear(); 1500*cdf0e10cSrcweir } 1501*cdf0e10cSrcweir 1502*cdf0e10cSrcweir String ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const 1503*cdf0e10cSrcweir { 1504*cdf0e10cSrcweir return maRefCache.getTableName(nFileId, nTabIndex); 1505*cdf0e10cSrcweir } 1506*cdf0e10cSrcweir 1507*cdf0e10cSrcweir ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const 1508*cdf0e10cSrcweir { 1509*cdf0e10cSrcweir return maRefCache.getCacheTable(nFileId, nTabIndex); 1510*cdf0e10cSrcweir } 1511*cdf0e10cSrcweir 1512*cdf0e10cSrcweir ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex) 1513*cdf0e10cSrcweir { 1514*cdf0e10cSrcweir return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex); 1515*cdf0e10cSrcweir } 1516*cdf0e10cSrcweir 1517*cdf0e10cSrcweir // ============================================================================ 1518*cdf0e10cSrcweir 1519*cdf0e10cSrcweir ScExternalRefManager::LinkListener::LinkListener() 1520*cdf0e10cSrcweir { 1521*cdf0e10cSrcweir } 1522*cdf0e10cSrcweir 1523*cdf0e10cSrcweir ScExternalRefManager::LinkListener::~LinkListener() 1524*cdf0e10cSrcweir { 1525*cdf0e10cSrcweir } 1526*cdf0e10cSrcweir 1527*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1528*cdf0e10cSrcweir 1529*cdf0e10cSrcweir ScExternalRefManager::ApiGuard::ApiGuard(ScDocument* pDoc) : 1530*cdf0e10cSrcweir mpMgr(pDoc->GetExternalRefManager()), 1531*cdf0e10cSrcweir mbOldInteractionEnabled(mpMgr->mbUserInteractionEnabled) 1532*cdf0e10cSrcweir { 1533*cdf0e10cSrcweir // We don't want user interaction handled in the API. 1534*cdf0e10cSrcweir mpMgr->mbUserInteractionEnabled = false; 1535*cdf0e10cSrcweir } 1536*cdf0e10cSrcweir 1537*cdf0e10cSrcweir ScExternalRefManager::ApiGuard::~ApiGuard() 1538*cdf0e10cSrcweir { 1539*cdf0e10cSrcweir // Restore old value. 1540*cdf0e10cSrcweir mpMgr->mbUserInteractionEnabled = mbOldInteractionEnabled; 1541*cdf0e10cSrcweir } 1542*cdf0e10cSrcweir 1543*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 1544*cdf0e10cSrcweir 1545*cdf0e10cSrcweir void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const 1546*cdf0e10cSrcweir { 1547*cdf0e10cSrcweir maRefCache.getAllTableNames(nFileId, rTabNames); 1548*cdf0e10cSrcweir } 1549*cdf0e10cSrcweir 1550*cdf0e10cSrcweir SCsTAB ScExternalRefManager::getCachedTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const 1551*cdf0e10cSrcweir { 1552*cdf0e10cSrcweir return maRefCache.getTabSpan( nFileId, rStartTabName, rEndTabName); 1553*cdf0e10cSrcweir } 1554*cdf0e10cSrcweir 1555*cdf0e10cSrcweir void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const 1556*cdf0e10cSrcweir { 1557*cdf0e10cSrcweir maRefCache.getAllNumberFormats(rNumFmts); 1558*cdf0e10cSrcweir } 1559*cdf0e10cSrcweir 1560*cdf0e10cSrcweir sal_uInt16 ScExternalRefManager::getExternalFileCount() const 1561*cdf0e10cSrcweir { 1562*cdf0e10cSrcweir return static_cast< sal_uInt16 >( maSrcFiles.size() ); 1563*cdf0e10cSrcweir } 1564*cdf0e10cSrcweir 1565*cdf0e10cSrcweir bool ScExternalRefManager::markUsedByLinkListeners() 1566*cdf0e10cSrcweir { 1567*cdf0e10cSrcweir bool bAllMarked = false; 1568*cdf0e10cSrcweir for (LinkListenerMap::const_iterator itr = maLinkListeners.begin(); 1569*cdf0e10cSrcweir itr != maLinkListeners.end() && !bAllMarked; ++itr) 1570*cdf0e10cSrcweir { 1571*cdf0e10cSrcweir if (!(*itr).second.empty()) 1572*cdf0e10cSrcweir bAllMarked = maRefCache.setCacheDocReferenced( (*itr).first); 1573*cdf0e10cSrcweir /* TODO: LinkListeners should remember the table they're listening to. 1574*cdf0e10cSrcweir * As is, listening to one table will mark all tables of the document 1575*cdf0e10cSrcweir * being referenced. */ 1576*cdf0e10cSrcweir } 1577*cdf0e10cSrcweir return bAllMarked; 1578*cdf0e10cSrcweir } 1579*cdf0e10cSrcweir 1580*cdf0e10cSrcweir bool ScExternalRefManager::markUsedExternalRefCells() 1581*cdf0e10cSrcweir { 1582*cdf0e10cSrcweir RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); 1583*cdf0e10cSrcweir for (; itr != itrEnd; ++itr) 1584*cdf0e10cSrcweir { 1585*cdf0e10cSrcweir RefCellSet::iterator itrCell = itr->second.begin(), itrCellEnd = itr->second.end(); 1586*cdf0e10cSrcweir for (; itrCell != itrCellEnd; ++itrCell) 1587*cdf0e10cSrcweir { 1588*cdf0e10cSrcweir ScFormulaCell* pCell = *itrCell; 1589*cdf0e10cSrcweir bool bUsed = pCell->MarkUsedExternalReferences(); 1590*cdf0e10cSrcweir if (bUsed) 1591*cdf0e10cSrcweir // Return true when at least one cell references external docs. 1592*cdf0e10cSrcweir return true; 1593*cdf0e10cSrcweir } 1594*cdf0e10cSrcweir } 1595*cdf0e10cSrcweir return false; 1596*cdf0e10cSrcweir } 1597*cdf0e10cSrcweir 1598*cdf0e10cSrcweir bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) 1599*cdf0e10cSrcweir { 1600*cdf0e10cSrcweir return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false); 1601*cdf0e10cSrcweir } 1602*cdf0e10cSrcweir 1603*cdf0e10cSrcweir void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) 1604*cdf0e10cSrcweir { 1605*cdf0e10cSrcweir if (isInReferenceMarking()) 1606*cdf0e10cSrcweir // Do all maintenance work. 1607*cdf0e10cSrcweir maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, true); 1608*cdf0e10cSrcweir else 1609*cdf0e10cSrcweir // Set only the permanent flag. 1610*cdf0e10cSrcweir maRefCache.setCacheTableReferencedPermanently( nFileId, rTabName, nSheets); 1611*cdf0e10cSrcweir } 1612*cdf0e10cSrcweir 1613*cdf0e10cSrcweir void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced ) 1614*cdf0e10cSrcweir { 1615*cdf0e10cSrcweir mbInReferenceMarking = !bReferenced; 1616*cdf0e10cSrcweir maRefCache.setAllCacheTableReferencedStati( bReferenced ); 1617*cdf0e10cSrcweir } 1618*cdf0e10cSrcweir 1619*cdf0e10cSrcweir void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray) 1620*cdf0e10cSrcweir { 1621*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef pArray(rArray.Clone()); 1622*cdf0e10cSrcweir maRefCache.setRangeNameTokens(nFileId, rName, pArray); 1623*cdf0e10cSrcweir } 1624*cdf0e10cSrcweir 1625*cdf0e10cSrcweir ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken( 1626*cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, 1627*cdf0e10cSrcweir const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt) 1628*cdf0e10cSrcweir { 1629*cdf0e10cSrcweir if (pCurPos) 1630*cdf0e10cSrcweir insertRefCell(nFileId, *pCurPos); 1631*cdf0e10cSrcweir 1632*cdf0e10cSrcweir maybeLinkExternalFile(nFileId); 1633*cdf0e10cSrcweir 1634*cdf0e10cSrcweir if (pTab) 1635*cdf0e10cSrcweir *pTab = -1; 1636*cdf0e10cSrcweir 1637*cdf0e10cSrcweir if (pFmt) 1638*cdf0e10cSrcweir pFmt->mbIsSet = false; 1639*cdf0e10cSrcweir 1640*cdf0e10cSrcweir // Check if the given table name and the cell position is cached. 1641*cdf0e10cSrcweir sal_uInt32 nFmtIndex = 0; 1642*cdf0e10cSrcweir ScExternalRefCache::TokenRef pToken = maRefCache.getCellData( 1643*cdf0e10cSrcweir nFileId, rTabName, rCell.Col(), rCell.Row(), &nFmtIndex); 1644*cdf0e10cSrcweir if (pToken) 1645*cdf0e10cSrcweir { 1646*cdf0e10cSrcweir // Cache hit ! 1647*cdf0e10cSrcweir if (pFmt) 1648*cdf0e10cSrcweir { 1649*cdf0e10cSrcweir short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex); 1650*cdf0e10cSrcweir if (nFmtType != NUMBERFORMAT_UNDEFINED) 1651*cdf0e10cSrcweir { 1652*cdf0e10cSrcweir pFmt->mbIsSet = true; 1653*cdf0e10cSrcweir pFmt->mnIndex = nFmtIndex; 1654*cdf0e10cSrcweir pFmt->mnType = nFmtType; 1655*cdf0e10cSrcweir } 1656*cdf0e10cSrcweir } 1657*cdf0e10cSrcweir return pToken; 1658*cdf0e10cSrcweir } 1659*cdf0e10cSrcweir 1660*cdf0e10cSrcweir // reference not cached. read from the source document. 1661*cdf0e10cSrcweir ScDocument* pSrcDoc = getSrcDocument(nFileId); 1662*cdf0e10cSrcweir if (!pSrcDoc) 1663*cdf0e10cSrcweir { 1664*cdf0e10cSrcweir // Source document not reachable. Throw a reference error. 1665*cdf0e10cSrcweir pToken.reset(new FormulaErrorToken(errNoRef)); 1666*cdf0e10cSrcweir return pToken; 1667*cdf0e10cSrcweir } 1668*cdf0e10cSrcweir 1669*cdf0e10cSrcweir ScBaseCell* pCell = NULL; 1670*cdf0e10cSrcweir SCTAB nTab; 1671*cdf0e10cSrcweir if (!pSrcDoc->GetTable(rTabName, nTab)) 1672*cdf0e10cSrcweir { 1673*cdf0e10cSrcweir // specified table name doesn't exist in the source document. 1674*cdf0e10cSrcweir pToken.reset(new FormulaErrorToken(errNoRef)); 1675*cdf0e10cSrcweir return pToken; 1676*cdf0e10cSrcweir } 1677*cdf0e10cSrcweir 1678*cdf0e10cSrcweir if (pTab) 1679*cdf0e10cSrcweir *pTab = nTab; 1680*cdf0e10cSrcweir 1681*cdf0e10cSrcweir SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL; 1682*cdf0e10cSrcweir SCROW nDataRow1 = 0, nDataRow2 = MAXROW; 1683*cdf0e10cSrcweir bool bData = pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2); 1684*cdf0e10cSrcweir if (!bData || rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row()) 1685*cdf0e10cSrcweir { 1686*cdf0e10cSrcweir // requested cell is outside the data area. Don't even bother caching 1687*cdf0e10cSrcweir // this data, but add it to the cached range to prevent accessing the 1688*cdf0e10cSrcweir // source document time and time again. 1689*cdf0e10cSrcweir ScExternalRefCache::TableTypeRef pCacheTab = 1690*cdf0e10cSrcweir maRefCache.getCacheTable(nFileId, rTabName, true, NULL); 1691*cdf0e10cSrcweir if (pCacheTab) 1692*cdf0e10cSrcweir pCacheTab->setCachedCell(rCell.Col(), rCell.Row()); 1693*cdf0e10cSrcweir 1694*cdf0e10cSrcweir pToken.reset(new ScEmptyCellToken(false, false)); 1695*cdf0e10cSrcweir return pToken; 1696*cdf0e10cSrcweir } 1697*cdf0e10cSrcweir 1698*cdf0e10cSrcweir pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell); 1699*cdf0e10cSrcweir ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell)); 1700*cdf0e10cSrcweir 1701*cdf0e10cSrcweir pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), nTab, nFmtIndex); 1702*cdf0e10cSrcweir nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc); 1703*cdf0e10cSrcweir if (pFmt) 1704*cdf0e10cSrcweir { 1705*cdf0e10cSrcweir short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex); 1706*cdf0e10cSrcweir if (nFmtType != NUMBERFORMAT_UNDEFINED) 1707*cdf0e10cSrcweir { 1708*cdf0e10cSrcweir pFmt->mbIsSet = true; 1709*cdf0e10cSrcweir pFmt->mnIndex = nFmtIndex; 1710*cdf0e10cSrcweir pFmt->mnType = nFmtType; 1711*cdf0e10cSrcweir } 1712*cdf0e10cSrcweir } 1713*cdf0e10cSrcweir 1714*cdf0e10cSrcweir if (!pTok.get()) 1715*cdf0e10cSrcweir { 1716*cdf0e10cSrcweir // Generate an error for unresolvable cells. 1717*cdf0e10cSrcweir pTok.reset( new FormulaErrorToken( errNoValue)); 1718*cdf0e10cSrcweir } 1719*cdf0e10cSrcweir 1720*cdf0e10cSrcweir // Now, insert the token into cache table but don't cache empty cells. 1721*cdf0e10cSrcweir if (pTok->GetType() != formula::svEmptyCell) 1722*cdf0e10cSrcweir maRefCache.setCellData(nFileId, rTabName, rCell.Col(), rCell.Row(), pTok, nFmtIndex); 1723*cdf0e10cSrcweir 1724*cdf0e10cSrcweir return pTok; 1725*cdf0e10cSrcweir } 1726*cdf0e10cSrcweir 1727*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens( 1728*cdf0e10cSrcweir sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos) 1729*cdf0e10cSrcweir { 1730*cdf0e10cSrcweir if (pCurPos) 1731*cdf0e10cSrcweir insertRefCell(nFileId, *pCurPos); 1732*cdf0e10cSrcweir 1733*cdf0e10cSrcweir maybeLinkExternalFile(nFileId); 1734*cdf0e10cSrcweir 1735*cdf0e10cSrcweir // Check if the given table name and the cell position is cached. 1736*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef pArray = 1737*cdf0e10cSrcweir maRefCache.getCellRangeData(nFileId, rTabName, rRange); 1738*cdf0e10cSrcweir if (pArray) 1739*cdf0e10cSrcweir // Cache hit ! 1740*cdf0e10cSrcweir return pArray; 1741*cdf0e10cSrcweir 1742*cdf0e10cSrcweir ScDocument* pSrcDoc = getSrcDocument(nFileId); 1743*cdf0e10cSrcweir if (!pSrcDoc) 1744*cdf0e10cSrcweir { 1745*cdf0e10cSrcweir // Source document is not reachable. Throw a reference error. 1746*cdf0e10cSrcweir pArray.reset(new ScTokenArray); 1747*cdf0e10cSrcweir pArray->AddToken(FormulaErrorToken(errNoRef)); 1748*cdf0e10cSrcweir return pArray; 1749*cdf0e10cSrcweir } 1750*cdf0e10cSrcweir 1751*cdf0e10cSrcweir SCTAB nTab1; 1752*cdf0e10cSrcweir if (!pSrcDoc->GetTable(rTabName, nTab1)) 1753*cdf0e10cSrcweir { 1754*cdf0e10cSrcweir // specified table name doesn't exist in the source document. 1755*cdf0e10cSrcweir pArray.reset(new ScTokenArray); 1756*cdf0e10cSrcweir pArray->AddToken(FormulaErrorToken(errNoRef)); 1757*cdf0e10cSrcweir return pArray; 1758*cdf0e10cSrcweir } 1759*cdf0e10cSrcweir 1760*cdf0e10cSrcweir ScRange aRange(rRange); 1761*cdf0e10cSrcweir SCTAB nTabSpan = aRange.aEnd.Tab() - aRange.aStart.Tab(); 1762*cdf0e10cSrcweir 1763*cdf0e10cSrcweir vector<ScExternalRefCache::SingleRangeData> aCacheData; 1764*cdf0e10cSrcweir aCacheData.reserve(nTabSpan+1); 1765*cdf0e10cSrcweir aCacheData.push_back(ScExternalRefCache::SingleRangeData()); 1766*cdf0e10cSrcweir aCacheData.back().maTableName = ScGlobal::pCharClass->upper(rTabName); 1767*cdf0e10cSrcweir 1768*cdf0e10cSrcweir for (SCTAB i = 1; i < nTabSpan + 1; ++i) 1769*cdf0e10cSrcweir { 1770*cdf0e10cSrcweir String aTabName; 1771*cdf0e10cSrcweir if (!pSrcDoc->GetName(nTab1 + 1, aTabName)) 1772*cdf0e10cSrcweir // source document doesn't have any table by the specified name. 1773*cdf0e10cSrcweir break; 1774*cdf0e10cSrcweir 1775*cdf0e10cSrcweir aCacheData.push_back(ScExternalRefCache::SingleRangeData()); 1776*cdf0e10cSrcweir aCacheData.back().maTableName = ScGlobal::pCharClass->upper(aTabName); 1777*cdf0e10cSrcweir } 1778*cdf0e10cSrcweir 1779*cdf0e10cSrcweir aRange.aStart.SetTab(nTab1); 1780*cdf0e10cSrcweir aRange.aEnd.SetTab(nTab1 + nTabSpan); 1781*cdf0e10cSrcweir 1782*cdf0e10cSrcweir pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData)); 1783*cdf0e10cSrcweir 1784*cdf0e10cSrcweir if (pArray) 1785*cdf0e10cSrcweir // Cache these values. 1786*cdf0e10cSrcweir maRefCache.setCellRangeData(nFileId, aRange, aCacheData, pArray); 1787*cdf0e10cSrcweir else 1788*cdf0e10cSrcweir { 1789*cdf0e10cSrcweir // Array is empty. Fill it with an empty matrix of the required size. 1790*cdf0e10cSrcweir pArray.reset(lcl_fillEmptyMatrix(rRange)); 1791*cdf0e10cSrcweir 1792*cdf0e10cSrcweir // Make sure to set this range 'cached', to prevent unnecessarily 1793*cdf0e10cSrcweir // accessing the src document time and time again. 1794*cdf0e10cSrcweir ScExternalRefCache::TableTypeRef pCacheTab = 1795*cdf0e10cSrcweir maRefCache.getCacheTable(nFileId, rTabName, true, NULL); 1796*cdf0e10cSrcweir if (pCacheTab) 1797*cdf0e10cSrcweir pCacheTab->setCachedCellRange( 1798*cdf0e10cSrcweir rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row()); 1799*cdf0e10cSrcweir } 1800*cdf0e10cSrcweir 1801*cdf0e10cSrcweir return pArray; 1802*cdf0e10cSrcweir } 1803*cdf0e10cSrcweir 1804*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos) 1805*cdf0e10cSrcweir { 1806*cdf0e10cSrcweir if (pCurPos) 1807*cdf0e10cSrcweir insertRefCell(nFileId, *pCurPos); 1808*cdf0e10cSrcweir 1809*cdf0e10cSrcweir maybeLinkExternalFile(nFileId); 1810*cdf0e10cSrcweir 1811*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef pArray = maRefCache.getRangeNameTokens(nFileId, rName); 1812*cdf0e10cSrcweir if (pArray.get()) 1813*cdf0e10cSrcweir return pArray; 1814*cdf0e10cSrcweir 1815*cdf0e10cSrcweir ScDocument* pSrcDoc = getSrcDocument(nFileId); 1816*cdf0e10cSrcweir if (!pSrcDoc) 1817*cdf0e10cSrcweir return ScExternalRefCache::TokenArrayRef(); 1818*cdf0e10cSrcweir 1819*cdf0e10cSrcweir ScRangeName* pExtNames = pSrcDoc->GetRangeName(); 1820*cdf0e10cSrcweir String aUpperName = ScGlobal::pCharClass->upper(rName); 1821*cdf0e10cSrcweir sal_uInt16 n; 1822*cdf0e10cSrcweir bool bRes = pExtNames->SearchNameUpper(aUpperName, n); 1823*cdf0e10cSrcweir if (!bRes) 1824*cdf0e10cSrcweir return ScExternalRefCache::TokenArrayRef(); 1825*cdf0e10cSrcweir 1826*cdf0e10cSrcweir ScRangeData* pRangeData = (*pExtNames)[n]; 1827*cdf0e10cSrcweir if (!pRangeData) 1828*cdf0e10cSrcweir return ScExternalRefCache::TokenArrayRef(); 1829*cdf0e10cSrcweir 1830*cdf0e10cSrcweir // Parse all tokens in this external range data, and replace each absolute 1831*cdf0e10cSrcweir // reference token with an external reference token, and cache them. Also 1832*cdf0e10cSrcweir // register the source document with the link manager if it's a new 1833*cdf0e10cSrcweir // source. 1834*cdf0e10cSrcweir 1835*cdf0e10cSrcweir ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray); 1836*cdf0e10cSrcweir 1837*cdf0e10cSrcweir ScTokenArray* pCode = pRangeData->GetCode(); 1838*cdf0e10cSrcweir for (FormulaToken* pToken = pCode->First(); pToken; pToken = pCode->Next()) 1839*cdf0e10cSrcweir { 1840*cdf0e10cSrcweir bool bTokenAdded = false; 1841*cdf0e10cSrcweir switch (pToken->GetType()) 1842*cdf0e10cSrcweir { 1843*cdf0e10cSrcweir case svSingleRef: 1844*cdf0e10cSrcweir { 1845*cdf0e10cSrcweir const ScSingleRefData& rRef = static_cast<ScToken*>(pToken)->GetSingleRef(); 1846*cdf0e10cSrcweir String aTabName; 1847*cdf0e10cSrcweir pSrcDoc->GetName(rRef.nTab, aTabName); 1848*cdf0e10cSrcweir ScExternalSingleRefToken aNewToken(nFileId, aTabName, static_cast<ScToken*>(pToken)->GetSingleRef()); 1849*cdf0e10cSrcweir pNew->AddToken(aNewToken); 1850*cdf0e10cSrcweir bTokenAdded = true; 1851*cdf0e10cSrcweir } 1852*cdf0e10cSrcweir break; 1853*cdf0e10cSrcweir case svDoubleRef: 1854*cdf0e10cSrcweir { 1855*cdf0e10cSrcweir const ScSingleRefData& rRef = static_cast<ScToken*>(pToken)->GetSingleRef(); 1856*cdf0e10cSrcweir String aTabName; 1857*cdf0e10cSrcweir pSrcDoc->GetName(rRef.nTab, aTabName); 1858*cdf0e10cSrcweir ScExternalDoubleRefToken aNewToken(nFileId, aTabName, static_cast<ScToken*>(pToken)->GetDoubleRef()); 1859*cdf0e10cSrcweir pNew->AddToken(aNewToken); 1860*cdf0e10cSrcweir bTokenAdded = true; 1861*cdf0e10cSrcweir } 1862*cdf0e10cSrcweir break; 1863*cdf0e10cSrcweir default: 1864*cdf0e10cSrcweir ; // nothing 1865*cdf0e10cSrcweir } 1866*cdf0e10cSrcweir 1867*cdf0e10cSrcweir if (!bTokenAdded) 1868*cdf0e10cSrcweir pNew->AddToken(*pToken); 1869*cdf0e10cSrcweir } 1870*cdf0e10cSrcweir 1871*cdf0e10cSrcweir // Make sure to pass the correctly-cased range name here. 1872*cdf0e10cSrcweir maRefCache.setRangeNameTokens(nFileId, pRangeData->GetName(), pNew); 1873*cdf0e10cSrcweir return pNew; 1874*cdf0e10cSrcweir } 1875*cdf0e10cSrcweir 1876*cdf0e10cSrcweir void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId) 1877*cdf0e10cSrcweir { 1878*cdf0e10cSrcweir RefCellMap::iterator itrFile = maRefCells.find(nFileId); 1879*cdf0e10cSrcweir if (itrFile == maRefCells.end()) 1880*cdf0e10cSrcweir return; 1881*cdf0e10cSrcweir 1882*cdf0e10cSrcweir RefCellSet& rRefCells = itrFile->second; 1883*cdf0e10cSrcweir for_each(rRefCells.begin(), rRefCells.end(), UpdateFormulaCell()); 1884*cdf0e10cSrcweir 1885*cdf0e10cSrcweir ScViewData* pViewData = ScDocShell::GetViewData(); 1886*cdf0e10cSrcweir if (!pViewData) 1887*cdf0e10cSrcweir return; 1888*cdf0e10cSrcweir 1889*cdf0e10cSrcweir ScTabViewShell* pVShell = pViewData->GetViewShell(); 1890*cdf0e10cSrcweir if (!pVShell) 1891*cdf0e10cSrcweir return; 1892*cdf0e10cSrcweir 1893*cdf0e10cSrcweir // Repainting the grid also repaints the texts, but is there a better way 1894*cdf0e10cSrcweir // to refresh texts? 1895*cdf0e10cSrcweir pVShell->Invalidate(FID_REPAINT); 1896*cdf0e10cSrcweir pVShell->PaintGrid(); 1897*cdf0e10cSrcweir } 1898*cdf0e10cSrcweir 1899*cdf0e10cSrcweir void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell) 1900*cdf0e10cSrcweir { 1901*cdf0e10cSrcweir RefCellMap::iterator itr = maRefCells.find(nFileId); 1902*cdf0e10cSrcweir if (itr == maRefCells.end()) 1903*cdf0e10cSrcweir { 1904*cdf0e10cSrcweir RefCellSet aRefCells; 1905*cdf0e10cSrcweir pair<RefCellMap::iterator, bool> r = maRefCells.insert( 1906*cdf0e10cSrcweir RefCellMap::value_type(nFileId, aRefCells)); 1907*cdf0e10cSrcweir if (!r.second) 1908*cdf0e10cSrcweir // insertion failed. 1909*cdf0e10cSrcweir return; 1910*cdf0e10cSrcweir 1911*cdf0e10cSrcweir itr = r.first; 1912*cdf0e10cSrcweir } 1913*cdf0e10cSrcweir 1914*cdf0e10cSrcweir ScBaseCell* pCell = mpDoc->GetCell(rCell); 1915*cdf0e10cSrcweir if (pCell && pCell->GetCellType() == CELLTYPE_FORMULA) 1916*cdf0e10cSrcweir itr->second.insert(static_cast<ScFormulaCell*>(pCell)); 1917*cdf0e10cSrcweir } 1918*cdf0e10cSrcweir 1919*cdf0e10cSrcweir ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId) 1920*cdf0e10cSrcweir { 1921*cdf0e10cSrcweir if (!mpDoc->IsExecuteLinkEnabled()) 1922*cdf0e10cSrcweir return NULL; 1923*cdf0e10cSrcweir 1924*cdf0e10cSrcweir DocShellMap::iterator itrEnd = maDocShells.end(); 1925*cdf0e10cSrcweir DocShellMap::iterator itr = maDocShells.find(nFileId); 1926*cdf0e10cSrcweir 1927*cdf0e10cSrcweir if (itr != itrEnd) 1928*cdf0e10cSrcweir { 1929*cdf0e10cSrcweir // document already loaded. 1930*cdf0e10cSrcweir 1931*cdf0e10cSrcweir // TODO: Find out a way to access a document that's already open in 1932*cdf0e10cSrcweir // memory and re-use that instance, instead of loading it from the 1933*cdf0e10cSrcweir // disk again. 1934*cdf0e10cSrcweir 1935*cdf0e10cSrcweir SfxObjectShell* p = itr->second.maShell; 1936*cdf0e10cSrcweir itr->second.maLastAccess = Time(); 1937*cdf0e10cSrcweir return static_cast<ScDocShell*>(p)->GetDocument(); 1938*cdf0e10cSrcweir } 1939*cdf0e10cSrcweir 1940*cdf0e10cSrcweir const String* pFile = getExternalFileName(nFileId); 1941*cdf0e10cSrcweir if (!pFile) 1942*cdf0e10cSrcweir // no file name associated with this ID. 1943*cdf0e10cSrcweir return NULL; 1944*cdf0e10cSrcweir 1945*cdf0e10cSrcweir String aFilter; 1946*cdf0e10cSrcweir SrcShell aSrcDoc; 1947*cdf0e10cSrcweir aSrcDoc.maShell = loadSrcDocument(nFileId, aFilter); 1948*cdf0e10cSrcweir if (!aSrcDoc.maShell.Is()) 1949*cdf0e10cSrcweir { 1950*cdf0e10cSrcweir // source document could not be loaded. 1951*cdf0e10cSrcweir return NULL; 1952*cdf0e10cSrcweir } 1953*cdf0e10cSrcweir 1954*cdf0e10cSrcweir if (maDocShells.empty()) 1955*cdf0e10cSrcweir { 1956*cdf0e10cSrcweir // If this is the first source document insertion, start up the timer. 1957*cdf0e10cSrcweir maSrcDocTimer.Start(); 1958*cdf0e10cSrcweir } 1959*cdf0e10cSrcweir 1960*cdf0e10cSrcweir maDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc)); 1961*cdf0e10cSrcweir SfxObjectShell* p = aSrcDoc.maShell; 1962*cdf0e10cSrcweir ScDocument* pSrcDoc = static_cast<ScDocShell*>(p)->GetDocument(); 1963*cdf0e10cSrcweir 1964*cdf0e10cSrcweir SCTAB nTabCount = pSrcDoc->GetTableCount(); 1965*cdf0e10cSrcweir if (!maRefCache.isDocInitialized(nFileId) && nTabCount) 1966*cdf0e10cSrcweir { 1967*cdf0e10cSrcweir // Populate the cache with all table names in the source document. 1968*cdf0e10cSrcweir vector<String> aTabNames; 1969*cdf0e10cSrcweir aTabNames.reserve(nTabCount); 1970*cdf0e10cSrcweir for (SCTAB i = 0; i < nTabCount; ++i) 1971*cdf0e10cSrcweir { 1972*cdf0e10cSrcweir String aName; 1973*cdf0e10cSrcweir pSrcDoc->GetName(i, aName); 1974*cdf0e10cSrcweir aTabNames.push_back(aName); 1975*cdf0e10cSrcweir } 1976*cdf0e10cSrcweir maRefCache.initializeDoc(nFileId, aTabNames); 1977*cdf0e10cSrcweir } 1978*cdf0e10cSrcweir return pSrcDoc; 1979*cdf0e10cSrcweir } 1980*cdf0e10cSrcweir 1981*cdf0e10cSrcweir SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, String& rFilter) 1982*cdf0e10cSrcweir { 1983*cdf0e10cSrcweir const SrcFileData* pFileData = getExternalFileData(nFileId); 1984*cdf0e10cSrcweir if (!pFileData) 1985*cdf0e10cSrcweir return NULL; 1986*cdf0e10cSrcweir 1987*cdf0e10cSrcweir // Always load the document by using the path created from the relative 1988*cdf0e10cSrcweir // path. If the referenced document is not there, simply exit. The 1989*cdf0e10cSrcweir // original file name should be used only when the relative path is not 1990*cdf0e10cSrcweir // given. 1991*cdf0e10cSrcweir String aFile = pFileData->maFileName; 1992*cdf0e10cSrcweir maybeCreateRealFileName(nFileId); 1993*cdf0e10cSrcweir if (pFileData->maRealFileName.Len()) 1994*cdf0e10cSrcweir aFile = pFileData->maRealFileName; 1995*cdf0e10cSrcweir 1996*cdf0e10cSrcweir if (!isFileLoadable(aFile)) 1997*cdf0e10cSrcweir return NULL; 1998*cdf0e10cSrcweir 1999*cdf0e10cSrcweir String aOptions( pFileData->maFilterOptions ); 2000*cdf0e10cSrcweir if ( pFileData->maFilterName.Len() ) 2001*cdf0e10cSrcweir rFilter = pFileData->maFilterName; // don't overwrite stored filter with guessed filter 2002*cdf0e10cSrcweir else 2003*cdf0e10cSrcweir ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false); 2004*cdf0e10cSrcweir const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter); 2005*cdf0e10cSrcweir 2006*cdf0e10cSrcweir if (!pFileData->maRelativeName.Len()) 2007*cdf0e10cSrcweir { 2008*cdf0e10cSrcweir // Generate a relative file path. 2009*cdf0e10cSrcweir INetURLObject aBaseURL(getOwnDocumentName()); 2010*cdf0e10cSrcweir aBaseURL.insertName(OUString::createFromAscii("content.xml")); 2011*cdf0e10cSrcweir 2012*cdf0e10cSrcweir String aStr = URIHelper::simpleNormalizedMakeRelative( 2013*cdf0e10cSrcweir aBaseURL.GetMainURL(INetURLObject::NO_DECODE), aFile); 2014*cdf0e10cSrcweir 2015*cdf0e10cSrcweir setRelativeFileName(nFileId, aStr); 2016*cdf0e10cSrcweir } 2017*cdf0e10cSrcweir 2018*cdf0e10cSrcweir SfxItemSet* pSet = new SfxAllItemSet(SFX_APP()->GetPool()); 2019*cdf0e10cSrcweir if (aOptions.Len()) 2020*cdf0e10cSrcweir pSet->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, aOptions)); 2021*cdf0e10cSrcweir 2022*cdf0e10cSrcweir // make medium hidden to prevent assertion from progress bar 2023*cdf0e10cSrcweir pSet->Put( SfxBoolItem( SID_HIDDEN, sal_True ) ); 2024*cdf0e10cSrcweir 2025*cdf0e10cSrcweir auto_ptr<SfxMedium> pMedium(new SfxMedium(aFile, STREAM_STD_READ, false, pFilter, pSet)); 2026*cdf0e10cSrcweir if (pMedium->GetError() != ERRCODE_NONE) 2027*cdf0e10cSrcweir return NULL; 2028*cdf0e10cSrcweir 2029*cdf0e10cSrcweir // To load encrypted documents with password, user interaction needs to be enabled. 2030*cdf0e10cSrcweir pMedium->UseInteractionHandler(mbUserInteractionEnabled); 2031*cdf0e10cSrcweir 2032*cdf0e10cSrcweir ScDocShell* pNewShell = new ScDocShell(SFX_CREATE_MODE_INTERNAL); 2033*cdf0e10cSrcweir SfxObjectShellRef aRef = pNewShell; 2034*cdf0e10cSrcweir 2035*cdf0e10cSrcweir // increment the recursive link count of the source document. 2036*cdf0e10cSrcweir ScExtDocOptions* pExtOpt = mpDoc->GetExtDocOptions(); 2037*cdf0e10cSrcweir sal_uInt32 nLinkCount = pExtOpt ? pExtOpt->GetDocSettings().mnLinkCnt : 0; 2038*cdf0e10cSrcweir ScDocument* pSrcDoc = pNewShell->GetDocument(); 2039*cdf0e10cSrcweir pSrcDoc->EnableExecuteLink(false); // to prevent circular access of external references. 2040*cdf0e10cSrcweir pSrcDoc->EnableUndo(false); 2041*cdf0e10cSrcweir pSrcDoc->EnableAdjustHeight(false); 2042*cdf0e10cSrcweir 2043*cdf0e10cSrcweir ScExtDocOptions* pExtOptNew = pSrcDoc->GetExtDocOptions(); 2044*cdf0e10cSrcweir if (!pExtOptNew) 2045*cdf0e10cSrcweir { 2046*cdf0e10cSrcweir pExtOptNew = new ScExtDocOptions; 2047*cdf0e10cSrcweir pSrcDoc->SetExtDocOptions(pExtOptNew); 2048*cdf0e10cSrcweir } 2049*cdf0e10cSrcweir pExtOptNew->GetDocSettings().mnLinkCnt = nLinkCount + 1; 2050*cdf0e10cSrcweir 2051*cdf0e10cSrcweir pNewShell->DoLoad(pMedium.release()); 2052*cdf0e10cSrcweir 2053*cdf0e10cSrcweir // with UseInteractionHandler, options may be set by dialog during DoLoad 2054*cdf0e10cSrcweir String aNew = ScDocumentLoader::GetOptions(*pNewShell->GetMedium()); 2055*cdf0e10cSrcweir if (aNew.Len() && aNew != aOptions) 2056*cdf0e10cSrcweir aOptions = aNew; 2057*cdf0e10cSrcweir setFilterData(nFileId, rFilter, aOptions); // update the filter data, including the new options 2058*cdf0e10cSrcweir 2059*cdf0e10cSrcweir return aRef; 2060*cdf0e10cSrcweir } 2061*cdf0e10cSrcweir 2062*cdf0e10cSrcweir bool ScExternalRefManager::isFileLoadable(const String& rFile) const 2063*cdf0e10cSrcweir { 2064*cdf0e10cSrcweir if (!rFile.Len()) 2065*cdf0e10cSrcweir return false; 2066*cdf0e10cSrcweir 2067*cdf0e10cSrcweir if (isOwnDocument(rFile)) 2068*cdf0e10cSrcweir return false; 2069*cdf0e10cSrcweir 2070*cdf0e10cSrcweir String aPhysical; 2071*cdf0e10cSrcweir if (utl::LocalFileHelper::ConvertURLToPhysicalName(rFile, aPhysical) && aPhysical.Len()) 2072*cdf0e10cSrcweir { 2073*cdf0e10cSrcweir // #i114504# try IsFolder/Exists only for file URLs 2074*cdf0e10cSrcweir 2075*cdf0e10cSrcweir if (utl::UCBContentHelper::IsFolder(rFile)) 2076*cdf0e10cSrcweir return false; 2077*cdf0e10cSrcweir 2078*cdf0e10cSrcweir return utl::UCBContentHelper::Exists(rFile); 2079*cdf0e10cSrcweir } 2080*cdf0e10cSrcweir else 2081*cdf0e10cSrcweir return true; // for http and others, Exists doesn't work, but the URL can still be opened 2082*cdf0e10cSrcweir } 2083*cdf0e10cSrcweir 2084*cdf0e10cSrcweir void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId) 2085*cdf0e10cSrcweir { 2086*cdf0e10cSrcweir if (maLinkedDocs.count(nFileId)) 2087*cdf0e10cSrcweir // file alerady linked, or the link has been broken. 2088*cdf0e10cSrcweir return; 2089*cdf0e10cSrcweir 2090*cdf0e10cSrcweir // Source document not linked yet. Link it now. 2091*cdf0e10cSrcweir const String* pFileName = getExternalFileName(nFileId); 2092*cdf0e10cSrcweir if (!pFileName) 2093*cdf0e10cSrcweir return; 2094*cdf0e10cSrcweir 2095*cdf0e10cSrcweir String aFilter, aOptions; 2096*cdf0e10cSrcweir const SrcFileData* pFileData = getExternalFileData(nFileId); 2097*cdf0e10cSrcweir if (pFileData) 2098*cdf0e10cSrcweir { 2099*cdf0e10cSrcweir aFilter = pFileData->maFilterName; 2100*cdf0e10cSrcweir aOptions = pFileData->maFilterOptions; 2101*cdf0e10cSrcweir } 2102*cdf0e10cSrcweir // If a filter was already set (for example, loading the cached table), 2103*cdf0e10cSrcweir // don't call GetFilterName which has to access the source file. 2104*cdf0e10cSrcweir if (!aFilter.Len()) 2105*cdf0e10cSrcweir ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false); 2106*cdf0e10cSrcweir sfx2::LinkManager* pLinkMgr = mpDoc->GetLinkManager(); 2107*cdf0e10cSrcweir ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, aFilter); 2108*cdf0e10cSrcweir DBG_ASSERT(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL"); 2109*cdf0e10cSrcweir pLinkMgr->InsertFileLink(*pLink, OBJECT_CLIENT_FILE, *pFileName, &aFilter); 2110*cdf0e10cSrcweir 2111*cdf0e10cSrcweir pLink->SetDoReferesh(false); 2112*cdf0e10cSrcweir pLink->Update(); 2113*cdf0e10cSrcweir pLink->SetDoReferesh(true); 2114*cdf0e10cSrcweir 2115*cdf0e10cSrcweir maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true)); 2116*cdf0e10cSrcweir } 2117*cdf0e10cSrcweir 2118*cdf0e10cSrcweir void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName) 2119*cdf0e10cSrcweir { 2120*cdf0e10cSrcweir if (!maRelativeName.Len()) 2121*cdf0e10cSrcweir // No relative path given. Nothing to do. 2122*cdf0e10cSrcweir return; 2123*cdf0e10cSrcweir 2124*cdf0e10cSrcweir if (maRealFileName.Len()) 2125*cdf0e10cSrcweir // Real file name already created. Nothing to do. 2126*cdf0e10cSrcweir return; 2127*cdf0e10cSrcweir 2128*cdf0e10cSrcweir // Formulate the absolute file path from the relative path. 2129*cdf0e10cSrcweir const String& rRelPath = maRelativeName; 2130*cdf0e10cSrcweir INetURLObject aBaseURL(rOwnDocName); 2131*cdf0e10cSrcweir aBaseURL.insertName(OUString::createFromAscii("content.xml")); 2132*cdf0e10cSrcweir bool bWasAbs = false; 2133*cdf0e10cSrcweir maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE); 2134*cdf0e10cSrcweir } 2135*cdf0e10cSrcweir 2136*cdf0e10cSrcweir void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId) 2137*cdf0e10cSrcweir { 2138*cdf0e10cSrcweir if (nFileId >= maSrcFiles.size()) 2139*cdf0e10cSrcweir return; 2140*cdf0e10cSrcweir 2141*cdf0e10cSrcweir maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName()); 2142*cdf0e10cSrcweir } 2143*cdf0e10cSrcweir 2144*cdf0e10cSrcweir const String& ScExternalRefManager::getOwnDocumentName() const 2145*cdf0e10cSrcweir { 2146*cdf0e10cSrcweir SfxObjectShell* pShell = mpDoc->GetDocumentShell(); 2147*cdf0e10cSrcweir if (!pShell) 2148*cdf0e10cSrcweir // This should not happen! 2149*cdf0e10cSrcweir return EMPTY_STRING; 2150*cdf0e10cSrcweir 2151*cdf0e10cSrcweir SfxMedium* pMed = pShell->GetMedium(); 2152*cdf0e10cSrcweir if (!pMed) 2153*cdf0e10cSrcweir return EMPTY_STRING; 2154*cdf0e10cSrcweir 2155*cdf0e10cSrcweir return pMed->GetName(); 2156*cdf0e10cSrcweir } 2157*cdf0e10cSrcweir 2158*cdf0e10cSrcweir bool ScExternalRefManager::isOwnDocument(const String& rFile) const 2159*cdf0e10cSrcweir { 2160*cdf0e10cSrcweir return getOwnDocumentName().Equals(rFile); 2161*cdf0e10cSrcweir } 2162*cdf0e10cSrcweir 2163*cdf0e10cSrcweir void ScExternalRefManager::convertToAbsName(String& rFile) const 2164*cdf0e10cSrcweir { 2165*cdf0e10cSrcweir SfxObjectShell* pDocShell = mpDoc->GetDocumentShell(); 2166*cdf0e10cSrcweir rFile = ScGlobal::GetAbsDocName(rFile, pDocShell); 2167*cdf0e10cSrcweir } 2168*cdf0e10cSrcweir 2169*cdf0e10cSrcweir sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile) 2170*cdf0e10cSrcweir { 2171*cdf0e10cSrcweir vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end(); 2172*cdf0e10cSrcweir vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile)); 2173*cdf0e10cSrcweir if (itr != itrEnd) 2174*cdf0e10cSrcweir { 2175*cdf0e10cSrcweir size_t nId = distance(itrBeg, itr); 2176*cdf0e10cSrcweir return static_cast<sal_uInt16>(nId); 2177*cdf0e10cSrcweir } 2178*cdf0e10cSrcweir 2179*cdf0e10cSrcweir SrcFileData aData; 2180*cdf0e10cSrcweir aData.maFileName = rFile; 2181*cdf0e10cSrcweir maSrcFiles.push_back(aData); 2182*cdf0e10cSrcweir return static_cast<sal_uInt16>(maSrcFiles.size() - 1); 2183*cdf0e10cSrcweir } 2184*cdf0e10cSrcweir 2185*cdf0e10cSrcweir const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal) 2186*cdf0e10cSrcweir { 2187*cdf0e10cSrcweir if (nFileId >= maSrcFiles.size()) 2188*cdf0e10cSrcweir return NULL; 2189*cdf0e10cSrcweir 2190*cdf0e10cSrcweir if (bForceOriginal) 2191*cdf0e10cSrcweir return &maSrcFiles[nFileId].maFileName; 2192*cdf0e10cSrcweir 2193*cdf0e10cSrcweir maybeCreateRealFileName(nFileId); 2194*cdf0e10cSrcweir 2195*cdf0e10cSrcweir if (maSrcFiles[nFileId].maRealFileName.Len()) 2196*cdf0e10cSrcweir return &maSrcFiles[nFileId].maRealFileName; 2197*cdf0e10cSrcweir else 2198*cdf0e10cSrcweir return &maSrcFiles[nFileId].maFileName; 2199*cdf0e10cSrcweir } 2200*cdf0e10cSrcweir 2201*cdf0e10cSrcweir bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const 2202*cdf0e10cSrcweir { 2203*cdf0e10cSrcweir return nFileId < maSrcFiles.size(); 2204*cdf0e10cSrcweir } 2205*cdf0e10cSrcweir 2206*cdf0e10cSrcweir bool ScExternalRefManager::hasExternalFile(const String& rFile) const 2207*cdf0e10cSrcweir { 2208*cdf0e10cSrcweir vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end(); 2209*cdf0e10cSrcweir vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile)); 2210*cdf0e10cSrcweir return itr != itrEnd; 2211*cdf0e10cSrcweir } 2212*cdf0e10cSrcweir 2213*cdf0e10cSrcweir const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const 2214*cdf0e10cSrcweir { 2215*cdf0e10cSrcweir if (nFileId >= maSrcFiles.size()) 2216*cdf0e10cSrcweir return NULL; 2217*cdf0e10cSrcweir 2218*cdf0e10cSrcweir return &maSrcFiles[nFileId]; 2219*cdf0e10cSrcweir } 2220*cdf0e10cSrcweir 2221*cdf0e10cSrcweir const String* ScExternalRefManager::getRealTableName(sal_uInt16 nFileId, const String& rTabName) const 2222*cdf0e10cSrcweir { 2223*cdf0e10cSrcweir return maRefCache.getRealTableName(nFileId, rTabName); 2224*cdf0e10cSrcweir } 2225*cdf0e10cSrcweir 2226*cdf0e10cSrcweir const String* ScExternalRefManager::getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const 2227*cdf0e10cSrcweir { 2228*cdf0e10cSrcweir return maRefCache.getRealRangeName(nFileId, rRangeName); 2229*cdf0e10cSrcweir } 2230*cdf0e10cSrcweir 2231*cdf0e10cSrcweir template<typename MapContainer> 2232*cdf0e10cSrcweir void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap) 2233*cdf0e10cSrcweir { 2234*cdf0e10cSrcweir typename MapContainer::iterator itr = rMap.find(nFileId); 2235*cdf0e10cSrcweir if (itr != rMap.end()) 2236*cdf0e10cSrcweir rMap.erase(itr); 2237*cdf0e10cSrcweir } 2238*cdf0e10cSrcweir 2239*cdf0e10cSrcweir void ScExternalRefManager::refreshNames(sal_uInt16 nFileId) 2240*cdf0e10cSrcweir { 2241*cdf0e10cSrcweir maRefCache.clearCache(nFileId); 2242*cdf0e10cSrcweir lcl_removeByFileId(nFileId, maDocShells); 2243*cdf0e10cSrcweir 2244*cdf0e10cSrcweir if (maDocShells.empty()) 2245*cdf0e10cSrcweir maSrcDocTimer.Stop(); 2246*cdf0e10cSrcweir 2247*cdf0e10cSrcweir // Update all cells containing names from this source document. 2248*cdf0e10cSrcweir refreshAllRefCells(nFileId); 2249*cdf0e10cSrcweir 2250*cdf0e10cSrcweir notifyAllLinkListeners(nFileId, LINK_MODIFIED); 2251*cdf0e10cSrcweir } 2252*cdf0e10cSrcweir 2253*cdf0e10cSrcweir void ScExternalRefManager::breakLink(sal_uInt16 nFileId) 2254*cdf0e10cSrcweir { 2255*cdf0e10cSrcweir // Turn all formula cells referencing this external document into static 2256*cdf0e10cSrcweir // cells. 2257*cdf0e10cSrcweir RefCellMap::iterator itrRefs = maRefCells.find(nFileId); 2258*cdf0e10cSrcweir if (itrRefs != maRefCells.end()) 2259*cdf0e10cSrcweir { 2260*cdf0e10cSrcweir // Make a copy because removing the formula cells below will modify 2261*cdf0e10cSrcweir // the original container. 2262*cdf0e10cSrcweir RefCellSet aSet = itrRefs->second; 2263*cdf0e10cSrcweir for_each(aSet.begin(), aSet.end(), ConvertFormulaToStatic(mpDoc)); 2264*cdf0e10cSrcweir maRefCells.erase(nFileId); 2265*cdf0e10cSrcweir } 2266*cdf0e10cSrcweir 2267*cdf0e10cSrcweir lcl_removeByFileId(nFileId, maDocShells); 2268*cdf0e10cSrcweir 2269*cdf0e10cSrcweir if (maDocShells.empty()) 2270*cdf0e10cSrcweir maSrcDocTimer.Stop(); 2271*cdf0e10cSrcweir 2272*cdf0e10cSrcweir LinkedDocMap::iterator itr = maLinkedDocs.find(nFileId); 2273*cdf0e10cSrcweir if (itr != maLinkedDocs.end()) 2274*cdf0e10cSrcweir itr->second = false; 2275*cdf0e10cSrcweir 2276*cdf0e10cSrcweir notifyAllLinkListeners(nFileId, LINK_BROKEN); 2277*cdf0e10cSrcweir } 2278*cdf0e10cSrcweir 2279*cdf0e10cSrcweir void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter) 2280*cdf0e10cSrcweir { 2281*cdf0e10cSrcweir maSrcFiles[nFileId].maFileName = rNewFile; 2282*cdf0e10cSrcweir maSrcFiles[nFileId].maRelativeName.Erase(); 2283*cdf0e10cSrcweir maSrcFiles[nFileId].maRealFileName.Erase(); 2284*cdf0e10cSrcweir if (!maSrcFiles[nFileId].maFilterName.Equals(rNewFilter)) 2285*cdf0e10cSrcweir { 2286*cdf0e10cSrcweir // Filter type has changed. 2287*cdf0e10cSrcweir maSrcFiles[nFileId].maFilterName = rNewFilter; 2288*cdf0e10cSrcweir maSrcFiles[nFileId].maFilterOptions.Erase(); 2289*cdf0e10cSrcweir } 2290*cdf0e10cSrcweir refreshNames(nFileId); 2291*cdf0e10cSrcweir } 2292*cdf0e10cSrcweir 2293*cdf0e10cSrcweir void ScExternalRefManager::setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl) 2294*cdf0e10cSrcweir { 2295*cdf0e10cSrcweir if (nFileId >= maSrcFiles.size()) 2296*cdf0e10cSrcweir return; 2297*cdf0e10cSrcweir maSrcFiles[nFileId].maRelativeName = rRelUrl; 2298*cdf0e10cSrcweir } 2299*cdf0e10cSrcweir 2300*cdf0e10cSrcweir void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions) 2301*cdf0e10cSrcweir { 2302*cdf0e10cSrcweir if (nFileId >= maSrcFiles.size()) 2303*cdf0e10cSrcweir return; 2304*cdf0e10cSrcweir maSrcFiles[nFileId].maFilterName = rFilterName; 2305*cdf0e10cSrcweir maSrcFiles[nFileId].maFilterOptions = rOptions; 2306*cdf0e10cSrcweir } 2307*cdf0e10cSrcweir 2308*cdf0e10cSrcweir void ScExternalRefManager::clear() 2309*cdf0e10cSrcweir { 2310*cdf0e10cSrcweir DocShellMap::iterator itrEnd = maDocShells.end(); 2311*cdf0e10cSrcweir for (DocShellMap::iterator itr = maDocShells.begin(); itr != itrEnd; ++itr) 2312*cdf0e10cSrcweir itr->second.maShell->DoClose(); 2313*cdf0e10cSrcweir 2314*cdf0e10cSrcweir maDocShells.clear(); 2315*cdf0e10cSrcweir maSrcDocTimer.Stop(); 2316*cdf0e10cSrcweir } 2317*cdf0e10cSrcweir 2318*cdf0e10cSrcweir bool ScExternalRefManager::hasExternalData() const 2319*cdf0e10cSrcweir { 2320*cdf0e10cSrcweir return !maSrcFiles.empty(); 2321*cdf0e10cSrcweir } 2322*cdf0e10cSrcweir 2323*cdf0e10cSrcweir void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl) 2324*cdf0e10cSrcweir { 2325*cdf0e10cSrcweir for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end(); 2326*cdf0e10cSrcweir itr != itrEnd; ++itr) 2327*cdf0e10cSrcweir { 2328*cdf0e10cSrcweir // Re-generate relative file name from the absolute file name. 2329*cdf0e10cSrcweir String aAbsName = itr->maRealFileName; 2330*cdf0e10cSrcweir if (!aAbsName.Len()) 2331*cdf0e10cSrcweir aAbsName = itr->maFileName; 2332*cdf0e10cSrcweir 2333*cdf0e10cSrcweir itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative( 2334*cdf0e10cSrcweir rBaseFileUrl, aAbsName); 2335*cdf0e10cSrcweir } 2336*cdf0e10cSrcweir } 2337*cdf0e10cSrcweir 2338*cdf0e10cSrcweir void ScExternalRefManager::updateAbsAfterLoad() 2339*cdf0e10cSrcweir { 2340*cdf0e10cSrcweir String aOwn( getOwnDocumentName() ); 2341*cdf0e10cSrcweir for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end(); 2342*cdf0e10cSrcweir itr != itrEnd; ++itr) 2343*cdf0e10cSrcweir { 2344*cdf0e10cSrcweir // update maFileName to the real file name, 2345*cdf0e10cSrcweir // to be called when the original name is no longer needed (after CompileXML) 2346*cdf0e10cSrcweir 2347*cdf0e10cSrcweir itr->maybeCreateRealFileName( aOwn ); 2348*cdf0e10cSrcweir String aReal = itr->maRealFileName; 2349*cdf0e10cSrcweir if (aReal.Len()) 2350*cdf0e10cSrcweir itr->maFileName = aReal; 2351*cdf0e10cSrcweir } 2352*cdf0e10cSrcweir } 2353*cdf0e10cSrcweir 2354*cdf0e10cSrcweir void ScExternalRefManager::removeRefCell(ScFormulaCell* pCell) 2355*cdf0e10cSrcweir { 2356*cdf0e10cSrcweir for_each(maRefCells.begin(), maRefCells.end(), RemoveFormulaCell(pCell)); 2357*cdf0e10cSrcweir } 2358*cdf0e10cSrcweir 2359*cdf0e10cSrcweir void ScExternalRefManager::addLinkListener(sal_uInt16 nFileId, LinkListener* pListener) 2360*cdf0e10cSrcweir { 2361*cdf0e10cSrcweir LinkListenerMap::iterator itr = maLinkListeners.find(nFileId); 2362*cdf0e10cSrcweir if (itr == maLinkListeners.end()) 2363*cdf0e10cSrcweir { 2364*cdf0e10cSrcweir pair<LinkListenerMap::iterator, bool> r = maLinkListeners.insert( 2365*cdf0e10cSrcweir LinkListenerMap::value_type(nFileId, LinkListeners())); 2366*cdf0e10cSrcweir if (!r.second) 2367*cdf0e10cSrcweir { 2368*cdf0e10cSrcweir DBG_ERROR("insertion of new link listener list failed"); 2369*cdf0e10cSrcweir return; 2370*cdf0e10cSrcweir } 2371*cdf0e10cSrcweir 2372*cdf0e10cSrcweir itr = r.first; 2373*cdf0e10cSrcweir } 2374*cdf0e10cSrcweir 2375*cdf0e10cSrcweir LinkListeners& rList = itr->second; 2376*cdf0e10cSrcweir rList.insert(pListener); 2377*cdf0e10cSrcweir } 2378*cdf0e10cSrcweir 2379*cdf0e10cSrcweir void ScExternalRefManager::removeLinkListener(sal_uInt16 nFileId, LinkListener* pListener) 2380*cdf0e10cSrcweir { 2381*cdf0e10cSrcweir LinkListenerMap::iterator itr = maLinkListeners.find(nFileId); 2382*cdf0e10cSrcweir if (itr == maLinkListeners.end()) 2383*cdf0e10cSrcweir // no listeners for a specified file. 2384*cdf0e10cSrcweir return; 2385*cdf0e10cSrcweir 2386*cdf0e10cSrcweir LinkListeners& rList = itr->second; 2387*cdf0e10cSrcweir rList.erase(pListener); 2388*cdf0e10cSrcweir 2389*cdf0e10cSrcweir if (rList.empty()) 2390*cdf0e10cSrcweir // No more listeners for this file. Remove its entry. 2391*cdf0e10cSrcweir maLinkListeners.erase(itr); 2392*cdf0e10cSrcweir } 2393*cdf0e10cSrcweir 2394*cdf0e10cSrcweir void ScExternalRefManager::removeLinkListener(LinkListener* pListener) 2395*cdf0e10cSrcweir { 2396*cdf0e10cSrcweir LinkListenerMap::iterator itr = maLinkListeners.begin(), itrEnd = maLinkListeners.end(); 2397*cdf0e10cSrcweir for (; itr != itrEnd; ++itr) 2398*cdf0e10cSrcweir itr->second.erase(pListener); 2399*cdf0e10cSrcweir } 2400*cdf0e10cSrcweir 2401*cdf0e10cSrcweir void ScExternalRefManager::notifyAllLinkListeners(sal_uInt16 nFileId, LinkUpdateType eType) 2402*cdf0e10cSrcweir { 2403*cdf0e10cSrcweir LinkListenerMap::iterator itr = maLinkListeners.find(nFileId); 2404*cdf0e10cSrcweir if (itr == maLinkListeners.end()) 2405*cdf0e10cSrcweir // no listeners for a specified file. 2406*cdf0e10cSrcweir return; 2407*cdf0e10cSrcweir 2408*cdf0e10cSrcweir LinkListeners& rList = itr->second; 2409*cdf0e10cSrcweir for_each(rList.begin(), rList.end(), NotifyLinkListener(nFileId, eType)); 2410*cdf0e10cSrcweir } 2411*cdf0e10cSrcweir 2412*cdf0e10cSrcweir void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut) 2413*cdf0e10cSrcweir { 2414*cdf0e10cSrcweir DocShellMap aNewDocShells; 2415*cdf0e10cSrcweir DocShellMap::iterator itr = maDocShells.begin(), itrEnd = maDocShells.end(); 2416*cdf0e10cSrcweir for (; itr != itrEnd; ++itr) 2417*cdf0e10cSrcweir { 2418*cdf0e10cSrcweir // in 100th of a second. 2419*cdf0e10cSrcweir sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime(); 2420*cdf0e10cSrcweir if (nSinceLastAccess < nTimeOut) 2421*cdf0e10cSrcweir aNewDocShells.insert(*itr); 2422*cdf0e10cSrcweir } 2423*cdf0e10cSrcweir maDocShells.swap(aNewDocShells); 2424*cdf0e10cSrcweir 2425*cdf0e10cSrcweir if (maDocShells.empty()) 2426*cdf0e10cSrcweir maSrcDocTimer.Stop(); 2427*cdf0e10cSrcweir } 2428*cdf0e10cSrcweir 2429*cdf0e10cSrcweir sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc) 2430*cdf0e10cSrcweir { 2431*cdf0e10cSrcweir NumFmtMap::iterator itr = maNumFormatMap.find(nFileId); 2432*cdf0e10cSrcweir if (itr == maNumFormatMap.end()) 2433*cdf0e10cSrcweir { 2434*cdf0e10cSrcweir // Number formatter map is not initialized for this external document. 2435*cdf0e10cSrcweir pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert( 2436*cdf0e10cSrcweir NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap())); 2437*cdf0e10cSrcweir 2438*cdf0e10cSrcweir if (!r.second) 2439*cdf0e10cSrcweir // insertion failed. 2440*cdf0e10cSrcweir return nNumFmt; 2441*cdf0e10cSrcweir 2442*cdf0e10cSrcweir itr = r.first; 2443*cdf0e10cSrcweir mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable()); 2444*cdf0e10cSrcweir SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap(); 2445*cdf0e10cSrcweir itr->second.swap(aMap); 2446*cdf0e10cSrcweir } 2447*cdf0e10cSrcweir const SvNumberFormatterMergeMap& rMap = itr->second; 2448*cdf0e10cSrcweir SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt); 2449*cdf0e10cSrcweir if (itrNumFmt != rMap.end()) 2450*cdf0e10cSrcweir // mapped value found. 2451*cdf0e10cSrcweir return itrNumFmt->second; 2452*cdf0e10cSrcweir 2453*cdf0e10cSrcweir return nNumFmt; 2454*cdf0e10cSrcweir } 2455*cdf0e10cSrcweir 2456*cdf0e10cSrcweir IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer) 2457*cdf0e10cSrcweir { 2458*cdf0e10cSrcweir if (pTimer == &maSrcDocTimer) 2459*cdf0e10cSrcweir purgeStaleSrcDocument(SRCDOC_LIFE_SPAN); 2460*cdf0e10cSrcweir 2461*cdf0e10cSrcweir return 0; 2462*cdf0e10cSrcweir } 2463*cdf0e10cSrcweir 2464