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

Reply via email to