formula/source/core/api/FormulaCompiler.cxx | 4 - formula/source/core/api/token.cxx | 2 offapi/UnoApi_offapi.mk | 1 offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl | 12 +++ offapi/com/sun/star/sheet/TableRefToken.idl | 44 ++++++++++++ sc/source/core/tool/token.cxx | 33 ++++++++- sc/source/ui/unoobj/tokenuno.cxx | 46 +++++++++++-- 7 files changed, 132 insertions(+), 10 deletions(-)
New commits: commit 4c3f65ea3b1f2e7f6d92c732f72936fecc017b29 Author: Eike Rathke <er...@redhat.com> AuthorDate: Mon Jul 29 11:41:41 2024 +0200 Commit: Eike Rathke <er...@redhat.com> CommitDate: Mon Jul 29 16:29:19 2024 +0200 Resolves: tdf#159343 Implement TableRef API token conversion Change-Id: I1b0d9e002d267e62dc7cbbbfc9f5c5c728374345 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171165 Reviewed-by: Eike Rathke <er...@redhat.com> Tested-by: Jenkins diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx index 93886a061b25..c58c9023c3a7 100644 --- a/formula/source/core/api/FormulaCompiler.cxx +++ b/formula/source/core/api/FormulaCompiler.cxx @@ -529,10 +529,10 @@ uno::Sequence< sheet::FormulaOpCodeMapEntry > FormulaCompiler::OpCodeMap::create { FormulaMapGroupSpecialOffset::SPACES , ocSpaces } , { FormulaMapGroupSpecialOffset::MAT_REF , ocMatRef } , { FormulaMapGroupSpecialOffset::DB_AREA , ocDBArea } , - /* TODO: { FormulaMapGroupSpecialOffset::TABLE_REF , ocTableRef } , */ { FormulaMapGroupSpecialOffset::MACRO , ocMacro } , { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName } , - { FormulaMapGroupSpecialOffset::WHITESPACE , ocWhitespace } + { FormulaMapGroupSpecialOffset::WHITESPACE , ocWhitespace } , + { FormulaMapGroupSpecialOffset::TABLE_REF , ocTableRef } }; const size_t nCount = SAL_N_ELEMENTS(aMap); // Preallocate vector elements. diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx index c8124672d4bf..1167b3ebcd0d 100644 --- a/formula/source/core/api/token.cxx +++ b/formula/source/core/api/token.cxx @@ -418,8 +418,6 @@ bool FormulaTokenArray::AddFormulaToken( sal_Int32 nValue = rToken.Data.get<sal_Int32>(); if ( eOpCode == ocDBArea ) Add( new formula::FormulaIndexToken( eOpCode, static_cast<sal_uInt16>(nValue) ) ); - else if ( eOpCode == ocTableRef ) - bError = true; /* TODO: implementation */ else if ( eOpCode == ocSpaces ) Add( new formula::FormulaByteToken( ocSpaces, static_cast<sal_uInt8>(nValue) ) ); else diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index cf86c82a2ab9..b3c1c4e52ddf 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -3476,6 +3476,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/sheet,\ TableFilterField3 \ TableOperationMode \ TablePageBreakData \ + TableRefToken \ TableValidationVisibility \ ValidationAlertStyle \ ValidationType \ diff --git a/offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl b/offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl index 9b525a13d7a7..122a64e7c497 100644 --- a/offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl +++ b/offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl @@ -189,6 +189,18 @@ constants FormulaMapGroupSpecialOffset const long WHITESPACE = 13; + /** Formula tokens containing the op-code obtained from this offset + describe the reference to an item of a database range used in + formulas. + + <p>The FormulaToken::Data member shall contain a struct of type + `TableRefToken`.</p> + + @since LibreOffice 25.2 + */ + const long TABLE_REF = 14; + + }; diff --git a/offapi/com/sun/star/sheet/TableRefToken.idl b/offapi/com/sun/star/sheet/TableRefToken.idl new file mode 100644 index 000000000000..ff238d3c4a0a --- /dev/null +++ b/offapi/com/sun/star/sheet/TableRefToken.idl @@ -0,0 +1,44 @@ +/* -*- 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/. + */ + + +module com { module sun { module star { module sheet { + + +/** contains the information regarding table structured reference tokens + + @see DatabaseRange + @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::TABLE_REF + + @since LibreOffice 25.2 + */ +struct TableRefToken +{ + /** The index of the database range. This index can be obtained from + the database range using its DatabaseRange::TokenIndex property. + */ + long Index; + + + /** The item specifier, type of the table reference within the + database range. + */ + short Item; + + + /** The corresponding cell range reference. + */ + ComplexReference Reference; + +}; + + +}; }; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 9881f33e2f6a..d78b04df8bd8 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -51,6 +51,7 @@ #include <com/sun/star/sheet/FormulaToken.hpp> #include <com/sun/star/sheet/ReferenceFlags.hpp> #include <com/sun/star/sheet/NameToken.hpp> +#include <com/sun/star/sheet/TableRefToken.hpp> #include <utility> #include <o3tl/safeint.hxx> #include <o3tl/sorted_vector.hxx> @@ -1195,8 +1196,36 @@ bool ScTokenArray::AddFormulaToken( } else if (eOpCode == ocDBArea) AddDBRange(aTokenData.Index); - else if (eOpCode == ocTableRef) - bError = true; /* TODO: implementation */ + else + bError = true; + } + else if ( aType.equals( cppu::UnoType<sheet::TableRefToken>::get() ) ) + { + if (eOpCode == ocTableRef) + { + sheet::TableRefToken aTokenData; + rToken.Data >>= aTokenData; + ScTableRefToken* pToken = new ScTableRefToken( aTokenData.Index, + static_cast<ScTableRefToken::Item>(aTokenData.Item)); + if (Add(pToken)) // else pToken is deleted + { + if (aTokenData.Reference.Reference1 == aTokenData.Reference.Reference2) + { + ScSingleRefData aRefData; + lcl_SingleRefToCalc( aRefData, aTokenData.Reference.Reference1 ); + pToken->SetAreaRefRPN( new ScSingleRefToken( *mxSheetLimits, aRefData)); + } + else + { + ScComplexRefData aRefData; + lcl_SingleRefToCalc( aRefData.Ref1, aTokenData.Reference.Reference1 ); + lcl_SingleRefToCalc( aRefData.Ref2, aTokenData.Reference.Reference2 ); + pToken->SetAreaRefRPN( new ScDoubleRefToken( *mxSheetLimits, aRefData)); + } + } + else + bError = true; + } else bError = true; } diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx index c5f34540f87f..1f867189687a 100644 --- a/sc/source/ui/unoobj/tokenuno.cxx +++ b/sc/source/ui/unoobj/tokenuno.cxx @@ -28,6 +28,7 @@ #include <com/sun/star/sheet/ReferenceFlags.hpp> #include <com/sun/star/sheet/AddressConvention.hpp> #include <com/sun/star/sheet/NameToken.hpp> +#include <com/sun/star/sheet/TableRefToken.hpp> #include <com/sun/star/table/CellAddress.hpp> #include <svl/itemprop.hxx> @@ -143,6 +144,14 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( SetCompilerFlags( aCompiler ); std::unique_ptr<ScTokenArray> pCode = aCompiler.CompileString( aFormula ); + if (pCode->HasOpCode(ocTableRef)) + { + FormulaError nErr = pCode->GetCodeError(); + aCompiler.EnableJumpCommandReorder(true); + aCompiler.CompileTokenArray(); // needed for corresponding inner reference + pCode->DelRPN(); // can be discarded + pCode->SetCodeError(nErr); // reset to parsing error, if any + } ScTokenConversion::ConvertToTokenSequence( rDoc, aRet, *pCode ); } @@ -442,10 +451,39 @@ void ScTokenConversion::ConvertToTokenSequence( const ScDocument& rDoc, break; case svIndex: { - sheet::NameToken aNameToken; - aNameToken.Index = static_cast<sal_Int32>( rToken.GetIndex() ); - aNameToken.Sheet = rToken.GetSheet(); - rAPI.Data <<= aNameToken; + const ScTableRefToken* pTR; + if (rToken.GetOpCode() == ocTableRef && (pTR = dynamic_cast<const ScTableRefToken*>(&rToken))) + { + sheet::TableRefToken aTableRefToken; + aTableRefToken.Index = static_cast<sal_Int32>( pTR->GetIndex()); + aTableRefToken.Item = static_cast<sal_Int16>( pTR->GetItem()); + const FormulaToken* pRef = pTR->GetAreaRefRPN(); + assert(pRef && "something forgot to create RPN for ocTableRef inner reference"); + if (pRef) + { + switch (pRef->GetType()) + { + case svSingleRef: + lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, *pRef->GetSingleRef()); + aTableRefToken.Reference.Reference2 = aTableRefToken.Reference.Reference1; + break; + case svDoubleRef: + lcl_SingleRefToApi( aTableRefToken.Reference.Reference1, *pRef->GetSingleRef()); + lcl_SingleRefToApi( aTableRefToken.Reference.Reference2, *pRef->GetSingleRef2()); + break; + default: + ; // nothing + } + } + rAPI.Data <<= aTableRefToken; + } + else + { + sheet::NameToken aNameToken; + aNameToken.Index = static_cast<sal_Int32>( rToken.GetIndex() ); + aNameToken.Sheet = rToken.GetSheet(); + rAPI.Data <<= aNameToken; + } } break; case svMatrix: