tdf#115159 XLSX export: don't duplicate print titles

In FindBuiltInNameIdx(), check the duplication by
using the exported symbol of the ranges, instead
of the (in the case of whole rows) always different
XclTokenArray data.

Change-Id: Iba439d765bbbfaf5379113548f3d86d1c984e71c
Reviewed-on: https://gerrit.libreoffice.org/70507
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sc/qa/unit/data/xlsx/tdf115159.xlsx b/sc/qa/unit/data/xlsx/tdf115159.xlsx
new file mode 100644
index 0000000..e1b625d
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tdf115159.xlsx
Binary files differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 1591528..76acc6b 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -213,6 +213,7 @@
    void testTdf114969XLSX();
    void testTdf115192XLSX();
    void testTdf91634XLSX();
    void testTdf115159();

    void testXltxExport();

@@ -333,6 +334,7 @@
    CPPUNIT_TEST(testTdf114969XLSX);
    CPPUNIT_TEST(testTdf115192XLSX);
    CPPUNIT_TEST(testTdf91634XLSX);
    CPPUNIT_TEST(testTdf115159);

    CPPUNIT_TEST(testXltxExport);

@@ -4204,6 +4206,23 @@
    assertXPath(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId1']", "TargetMode", "External");
}

void ScExportTest::testTdf115159()
{
    ScDocShellRef xShell = loadDoc("tdf115159.", FORMAT_XLSX);
    CPPUNIT_ASSERT(xShell.is());
    ScDocShellRef xDocSh = saveAndReload(xShell.get(), FORMAT_XLSX);
    CPPUNIT_ASSERT(xDocSh.is());
    xShell->DoClose();

    xmlDocPtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/workbook.xml", FORMAT_XLSX);
    CPPUNIT_ASSERT(pDoc);

    //assert the existing OOXML built-in name is not duplicated
    assertXPath(pDoc, "/x:workbook/x:definedNames/x:definedName", 1);

    xDocSh->DoClose();
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/filter/excel/xename.cxx b/sc/source/filter/excel/xename.cxx
index 6255787..c0db80c 100644
--- a/sc/source/filter/excel/xename.cxx
+++ b/sc/source/filter/excel/xename.cxx
@@ -70,8 +70,8 @@
        @return  The built-in name index or EXC_BUILTIN_UNKNOWN for user-defined names. */
    sal_Unicode  GetBuiltInName() const { return mcBuiltIn; }

    /** Returns the token array for this defined name. */
    const XclTokenArrayRef& GetTokenArray() const { return mxTokArr; }
    /** Returns the symbol value for this defined name. */
    const OUString& GetSymbol() const { return msSymbol; }

    /** Returns true, if this is a document-global defined name. */
    bool         IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; }
@@ -157,7 +157,7 @@

    /** Returns the index of an existing built-in NAME record with the passed definition, otherwise 0. */
    sal_uInt16          FindBuiltInNameIdx( const OUString& rName,
                            const XclTokenArray& rTokArr ) const;
                            const OUString& sSymbol ) const;
    /** Returns an unused name for the passed name. */
    OUString            GetUnusedName( const OUString& rName ) const;

@@ -525,7 +525,7 @@
}

sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx(
        const OUString& rName, const XclTokenArray& rTokArr ) const
        const OUString& rName, const OUString& sSymbol ) const
{
    /*  Get built-in index from the name. Special case: the database range
        'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */
@@ -537,11 +537,9 @@
        for( size_t nPos = 0; nPos < mnFirstUserIdx; ++nPos )
        {
            XclExpNameRef xName = maNameList.GetRecord( nPos );
            if( xName->GetBuiltInName() == cBuiltIn )
            if( xName->GetBuiltInName() == cBuiltIn && xName->GetSymbol() == sSymbol )
            {
                XclTokenArrayRef xTokArr = xName->GetTokenArray();
                if( xTokArr && (*xTokArr == rTokArr) )
                    return static_cast< sal_uInt16 >( nPos + 1 );
                return static_cast< sal_uInt16 >( nPos + 1 );
            }
        }
    }
@@ -628,7 +626,7 @@
            cannot be done earlier. If a built-in name is found, the created NAME
            record for this name and all following records in the list must be
            deleted, otherwise they may contain wrong name list indexes. */
        sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, *xTokArr );
        sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, sSymbol );
        if( nBuiltInIdx != 0 )
        {
            // delete the new NAME records