/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError )
{ if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
{
OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar"); // Anything is almost as bad as this, but we might have the best choice // if not loading documents.
eTempGrammar = FormulaGrammar::GRAM_NATIVE;
}
FormulaTokenArrayPlainIterator aIter(*pCode);
FormulaToken* p = aIter.GetNextReference(); if( p )
{ // first token is a reference /* FIXME: wouldn't that need a check if it's exactly one reference? */ if( p->GetType() == svSingleRef )
eType = eType | Type::AbsPos; else
eType = eType | Type::AbsArea;
} // For manual input set an error for an incomplete formula. if (!rDoc.IsImportingXML())
{
aComp.CompileTokenArray();
pCode->DelRPN();
}
}
void ScRangeData::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt )
{ if (pCode->GetCodeError() == FormulaError::NoName)
{ // Reconstruct the symbol/formula and then recompile.
OUString aSymbol;
rCxt.setGrammar(eTempGrammar);
ScCompiler aComp(rCxt, aPos, *pCode);
aComp.CreateStringFromTokenArray( aSymbol); // Don't let the compiler set an error for unknown names on final // compile, errors are handled by the interpreter thereafter.
CompileRangeData( aSymbol, false);
rCxt.getDoc().CheckLinkFormulaNeedingCheck( *pCode);
}
}
// if the first character is an invalid start character, precede with '_' if ( !rName.isEmpty() && !ScCompiler::IsCharFlagAllConventions( rName, 0, ScCharFlags::CharName ) )
rName = "_" + rName;
// replace invalid with '_'
nLen = rName.getLength(); for (nPos=0; nPos<nLen; nPos++)
{ if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, ScCharFlags::Name) )
rName = rName.replaceAt( nPos, 1, u"_" );
}
// Ensure that the proposed name is not a reference under any convention, // same as in IsNameValid()
ScAddress aAddr;
ScRange aRange; for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
{
ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) ); // Don't check Parse on VALID, any partial only VALID may result in // #REF! during compile later! while (aRange.Parse(rName, rDoc, details) != ScRefFlags::ZERO ||
aAddr.Parse(rName, rDoc, details) != ScRefFlags::ZERO)
{ // Range Parse is partially valid also with invalid sheet name, // Address Parse ditto, during compile name would generate a #REF! if ( rName.indexOf( '.' ) != -1 )
rName = rName.replaceFirst( ".", "_" ); else
rName = "_" + rName;
}
}
}
ScRangeData::IsNameValidType ScRangeData::IsNameValid( const OUString& rName, const ScDocument& rDoc )
{ /* XXX If changed, sc/source/filter/ftools/ftools.cxx
* ScfTools::ConvertToScDefinedName needs to be changed too. */ charconst a('.'); if (rName.indexOf(a) != -1) return IsNameValidType::NAME_INVALID_BAD_STRING;
sal_Int32 nPos = 0;
sal_Int32 nLen = rName.getLength(); if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, ScCharFlags::CharName ) ) return IsNameValidType::NAME_INVALID_BAD_STRING; while ( nPos < nLen )
{ if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, ScCharFlags::Name ) ) return IsNameValidType::NAME_INVALID_BAD_STRING;
}
ScAddress aAddr;
ScRange aRange; for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
{
ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) ); // Don't check Parse on VALID, any partial only VALID may result in // #REF! during compile later! if (aRange.Parse(rName, rDoc, details) != ScRefFlags::ZERO ||
aAddr.Parse(rName, rDoc, details) != ScRefFlags::ZERO )
{ return IsNameValidType::NAME_INVALID_CELL_REF;
}
} return IsNameValidType::NAME_VALID;
}
bool ScRangeData::HasPossibleAddressConflict() const
{ // Similar to part of IsNameValid(), but only check if the name is a valid address.
ScAddress aAddr; for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
{
ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) ); // Don't check Parse on VALID, any partial only VALID may result in // #REF! during compile later! if(aAddr.Parse(aUpperName, rDoc, details) != ScRefFlags::ZERO) returntrue;
} returnfalse;
}
sal_uInt32 ScRangeData::GetUnoType() const
{
sal_uInt32 nUnoType = 0; if ( HasType(Type::Criteria) ) nUnoType |= css::sheet::NamedRangeFlag::FILTER_CRITERIA; if ( HasType(Type::PrintArea) ) nUnoType |= css::sheet::NamedRangeFlag::PRINT_AREA; if ( HasType(Type::ColHeader) ) nUnoType |= css::sheet::NamedRangeFlag::COLUMN_HEADER; if ( HasType(Type::RowHeader) ) nUnoType |= css::sheet::NamedRangeFlag::ROW_HEADER; if ( HasType(Type::Hidden) ) nUnoType |= css::sheet::NamedRangeFlag::HIDDEN; return nUnoType;
}
void ScRangeData::ValidateTabRefs()
{ // try to make sure all relative references and the reference position // are within existing tables, so they can be represented as text // (if the range of used tables is more than the existing tables, // the result may still contain invalid tables, because the relative // references aren't changed so formulas stay the same)
void ScRangeName::UpdateReference(sc::RefUpdateContext& rCxt, SCTAB nLocalTab )
{ if (rCxt.meMode == URM_COPY) // Copying cells does not modify named expressions. return;
for (autoconst& itr : m_Data)
{
itr.second->UpdateReference(rCxt, nLocalTab);
}
}
if (!p->GetIndex())
{ // Assign a new index. An index must be unique and is never 0. if (bReuseFreeIndex)
{
IndexDataType::iterator itr = std::find(
maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(nullptr)); if (itr != maIndexToData.end())
{ // Empty slot exists. Re-use it.
size_t nPos = std::distance(maIndexToData.begin(), itr);
p->SetIndex(nPos + 1);
} else // No empty slot. Append it to the end.
p->SetIndex(maIndexToData.size() + 1);
} else
{
p->SetIndex(maIndexToData.size() + 1);
}
}
OUString aName(p->GetUpperName());
erase(aName); // ptr_map won't insert it if a duplicate name exists.
pair<DataType::iterator, bool> r =
m_Data.insert(std::make_pair(aName, std::unique_ptr<ScRangeData>(p))); if (r.second)
{ // Data inserted. Store its index for mapping.
size_t nPos = p->GetIndex() - 1; if (nPos >= maIndexToData.size())
maIndexToData.resize(nPos+1, nullptr);
maIndexToData[nPos] = p;
mHasPossibleAddressConflictDirty = true;
} return r.second;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.