sc/source/filter/excel/xename.cxx | 36 ++++++++++++++++++++++++++++++---- sc/source/filter/excel/xestream.cxx | 7 +++++- sc/source/filter/excel/xetable.cxx | 38 +++++++++++++++++++++++++++++++++--- sc/source/filter/inc/xestream.hxx | 2 + 4 files changed, 75 insertions(+), 8 deletions(-)
New commits: commit 7ff554c05222ea8e60468cf362c48b72d9f17417 Author: Karthik Godha <[email protected]> AuthorDate: Tue Jan 13 21:17:30 2026 +0530 Commit: Karthik Godha <[email protected]> CommitDate: Thu Feb 26 17:22:05 2026 +0100 XLS -> XLSX: Skip writing macros in formulas During XLS import, formulas containing named references which are not in ScRangeList are imported as macros. These are not handled during XLSX export. bug document: forum-en-1357.xls Change-Id: I6584117c4956ca1e0166bb0a15b19cee404154b7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197200 Reviewed-by: Michael Stahl <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> (cherry picked from commit 973d218475a071407cf3593ef9ab6243bc9c595c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199418 Reviewed-by: Karthik Godha <[email protected]> Tested-by: Jenkins Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199660 diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index d1650cfc1c41..e09776f35d6a 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -817,7 +817,12 @@ OUString XclXmlUtils::ToOUString( else { if (nErrCode != FormulaError::NONE) - aCompiler.AppendErrorConstant( aBuffer, nErrCode); + { + if (nErrCode == FormulaError::NoMacro) + aCompiler.AppendErrorConstant(aBuffer, FormulaError::NoRef); + else + aCompiler.AppendErrorConstant(aBuffer, nErrCode); + } else { // No code SHOULD be an "error cell", assert caller thought of that diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index 3b3981f118c5..2c65d08c2daa 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -1015,15 +1015,47 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) if (bWriteFormula) { + ScTokenArray aTokenArray(*mrScFmlaCell.GetCode()); + // If XLSX export then remove macro tokens from the array + if (!rStrm.IsExportVBA()) + { + formula::FormulaTokenArrayPlainIterator aIter(aTokenArray); + formula::FormulaToken* t = aIter.First(); + while (t) + { + if (t->GetOpCode() == ocMacro) + { + sal_uInt16 nStart = aIter.GetIndex() - 1; + formula::FormulaToken* pNext = aIter.PeekNext(); + if (pNext && pNext->GetOpCode() == ocOpen) + { + sal_uInt16 nParenthesis = 0; + do + { + if (pNext->GetOpCode() == ocOpen) + nParenthesis++; + else if (pNext->GetOpCode() == ocClose) + nParenthesis--; + + aIter.Next(); + pNext = aIter.PeekNext(); + } while (nParenthesis > 0 && pNext); + } + aTokenArray.RemoveToken(nStart, aIter.GetIndex() - nStart); + aIter.AfterRemoveToken(nStart, aIter.GetIndex() - nStart); + } + t = aIter.Next(); + } + } if (!bTagStarted) { rWorksheet->startElement( XML_f, XML_aca, ToPsz( (mxTokArr && mxTokArr->IsVolatile()) || (mxAddRec && mxAddRec->IsVolatile()) ) ); } - rWorksheet->writeEscaped( XclXmlUtils::ToOUString( - rStrm.GetRoot().GetCompileFormulaContext(), mrScFmlaCell.aPos, mrScFmlaCell.GetCode(), - mrScFmlaCell.GetErrCode())); + rWorksheet->writeEscaped(XclXmlUtils::ToOUString(rStrm.GetRoot().GetCompileFormulaContext(), + mrScFmlaCell.aPos, &aTokenArray, + mrScFmlaCell.GetErrCode())); rWorksheet->endElement( XML_f ); } diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx index 4da0e0b6067a..b5bfd7e84afd 100644 --- a/sc/source/filter/inc/xestream.hxx +++ b/sc/source/filter/inc/xestream.hxx @@ -290,6 +290,8 @@ public: /** Returns the filter root data. */ const XclExpRoot& GetRoot() const { return *mpRoot; } + bool IsExportVBA() const { return mbExportVBA; } + sax_fastparser::FSHelperPtr& GetCurrentStream(); void PushStream( sax_fastparser::FSHelperPtr const & aStream ); void PopStream(); commit ac98dea203c9dee6e227bb4d811e8f8f7edd6483 Author: Karthik Godha <[email protected]> AuthorDate: Wed Jan 21 18:36:43 2026 +0530 Commit: Karthik Godha <[email protected]> CommitDate: Thu Feb 26 17:21:54 2026 +0100 sc: Invalid external references in defined names External links are exported through `XclExpSupbookBuffer::SaveXML`, though defined names are written after external links, they are generated before writing external links through `XclExpNameManagerImpl::CreateName` . Because of this, defined names containing external references may contain invalid index. During export regenerate defined names if they contain external refs bug document: forum-mso-de-18719.xls Change-Id: I62d87d3556c474a822c91342dc5cc7bced006af6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197746 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit 96a07be28a28945dbf45cb91e81dec0a3a444d67) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199420 Tested-by: Jenkins Reviewed-by: Karthik Godha <[email protected]> Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199659 diff --git a/sc/source/filter/excel/xename.cxx b/sc/source/filter/excel/xename.cxx index 092ab5e53e7f..7d8de704b8a5 100644 --- a/sc/source/filter/excel/xename.cxx +++ b/sc/source/filter/excel/xename.cxx @@ -69,6 +69,8 @@ public: @param sValue the name's symbolic value */ void SetSymbol( const OUString& rValue ); + void SetScTokenArray( std::unique_ptr<ScTokenArray> pScTokArr, const ScAddress& rPos ); + /** Returns the original name (title) of this defined name. */ const OUString& GetOrigName() const { return maOrigName; } /** Returns the Excel built-in name index of this defined name. @@ -78,6 +80,9 @@ public: /** Returns the symbol value for this defined name. */ const OUString& GetSymbol() const { return msSymbol; } + const ScAddress& GetPos() const { return maPos; } + ScTokenArray* GetScTokenArray() const { return mpScTokenArray.get(); } + /** Returns true, if this is a document-global defined name. */ bool IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; } /** Returns the Calc sheet of a local defined name. */ @@ -105,6 +110,8 @@ private: OUString msSymbol; /// The value of the symbol XclExpStringRef mxName; /// The name as Excel string object. XclTokenArrayRef mxTokArr; /// The definition of the defined name. + std::unique_ptr<ScTokenArray> mpScTokenArray; + ScAddress maPos; sal_Unicode mcBuiltIn; /// The built-in index for built-in names. SCTAB mnScTab; /// The Calc sheet index for local names. sal_uInt16 mnFlags; /// Additional flags for this defined name. @@ -242,6 +249,12 @@ void XclExpName::SetTokenArray( const XclTokenArrayRef& xTokArr ) mxTokArr = xTokArr; } +void XclExpName::SetScTokenArray( std::unique_ptr<ScTokenArray> pScTokArr, const ScAddress& rPos ) +{ + mpScTokenArray = std::move(pScTokArr); + maPos = rPos; +} + void XclExpName::SetLocalTab( SCTAB nScTab ) { OSL_ENSURE( GetTabInfo().IsExportTab( nScTab ), "XclExpName::SetLocalTab - invalid sheet index" ); @@ -348,6 +361,18 @@ void XclExpName::SaveXml( XclExpXmlStream& rStrm ) sName = "_" + sName; } + // Regenerate symbol for external references + if (ScTokenArray* pScTokArr = GetScTokenArray()) + { + formula::FormulaTokenArrayPlainIterator aIter(*pScTokArr); + formula::FormulaToken* t = aIter.First(); + while (t && !t->IsExternalRef()) + t = aIter.Next(); + + if (t) + msSymbol = XclXmlUtils::ToOUString(GetCompileFormulaContext(), GetPos(), pScTokArr); + } + rWorkbook->startElement( XML_definedName, // OOXTODO: XML_comment, "", // OOXTODO: XML_customMenu, "", @@ -658,17 +683,19 @@ sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRa { XclTokenArrayRef xTokArr; OUString sSymbol; + std::unique_ptr<ScTokenArray> pScTokArrCopy + = std::make_unique<ScTokenArray>(pScTokArr->CloneValue()); + // MSO requires named ranges to have absolute sheet references if ( rRangeData.HasType( ScRangeData::Type::AbsPos ) || rRangeData.HasType( ScRangeData::Type::AbsArea ) ) { // Don't modify the actual document; use a temporary copy to create the export formulas. - ScTokenArray aTokenCopy( pScTokArr->CloneValue() ); - lcl_EnsureAbs3DToken(nTab, aTokenCopy.FirstToken()); + lcl_EnsureAbs3DToken(nTab, pScTokArrCopy->FirstToken()); - xTokArr = GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_NAME, aTokenCopy); + xTokArr = GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_NAME, *pScTokArrCopy); if ( GetOutput() != EXC_OUTPUT_BINARY ) { - ScCompiler aComp(GetDoc(), rRangeData.GetPos(), aTokenCopy, + ScCompiler aComp(GetDoc(), rRangeData.GetPos(), *pScTokArrCopy, formula::FormulaGrammar::GRAM_OOXML); aComp.CreateStringFromTokenArray( sSymbol ); } @@ -683,6 +710,7 @@ sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRa } xName->SetTokenArray( xTokArr ); xName->SetSymbol( sSymbol ); + xName->SetScTokenArray( std::move(pScTokArrCopy), rRangeData.GetPos() ); /* Try to replace by existing built-in name - complete token array is needed for comparison, and due to the recursion problem above this
