cui/source/options/optchart.cxx                                 |   65 
+++++++---
 include/oox/core/filterdetect.hxx                               |    1 
 officecfg/registry/data/org/openoffice/TypeDetection/UISort.xcu |    2 
 oox/source/core/filterdetect.cxx                                |   55 ++++++++
 sc/inc/scextopt.hxx                                             |    1 
 sc/qa/unit/subsequent_export_test2.cxx                          |   32 ++++
 sc/source/filter/excel/excdoc.cxx                               |   12 +
 sc/source/filter/inc/workbooksettings.hxx                       |    5 
 sc/source/filter/oox/workbookfragment.cxx                       |    1 
 sc/source/filter/oox/workbooksettings.cxx                       |   16 ++
 10 files changed, 162 insertions(+), 28 deletions(-)

New commits:
commit b89190783eca21c16b4406e5d825c4bc51ecad84
Author:     Jim Raykowski <[email protected]>
AuthorDate: Tue Dec 9 11:12:48 2025 -0900
Commit:     Xisco Fauli <[email protected]>
CommitDate: Tue Dec 16 16:48:28 2025 +0100

    related tdf#163347 Improve sync color table to chart colors list
    
    ...entry selection
    
    * 'Custom', 'Theme colors', and 'Document colors' palettes are included
    in the search.
    * When no palette is found having the chart colors list entry selection
    color, the palette combobox text is set empty and the color valueset is
    cleared. This can happen when a chart colors list entry selection color
    was made from the 'Theme colors' palette and the SvxDefaultColorOptPage
    is opened from the start center backing window.
    
    Change-Id: I8ad9956c0bb9ee7de5fdcff77a250e81d7a58a9b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195335
    Reviewed-by: Jim Raykowski <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 7c836d8722a032ebc586a709659dffb15cbf84a6)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195545
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/cui/source/options/optchart.cxx b/cui/source/options/optchart.cxx
index e90b7289c31c..bd99a339d2cf 100644
--- a/cui/source/options/optchart.cxx
+++ b/cui/source/options/optchart.cxx
@@ -99,26 +99,55 @@ IMPL_LINK_NOARG(SvxDefaultColorOptPage, 
LbChartColorsSelectionChangedHdl, weld::
     Color& rColor(aColorList[nIndex]);
 
     XColorListRef xColorList;
-    for (size_t i = 0, nSize = aPaletteManager.GetPaletteList().size(); i < 
nSize; ++i)
+    for (sal_uInt16 nPalettePos = 0, nPaletteCount = 
aPaletteManager.GetPaletteCount();
+         nPalettePos < nPaletteCount; ++nPalettePos)
     {
-        aPaletteManager.SetPalette(i, true/*bPosOnly*/);
-
-        xColorList = 
XPropertyList::AsColorList(XPropertyList::CreatePropertyListFromURL(
-            XPropertyListType::Color, 
aPaletteManager.GetSelectedPalettePath()));
-        if (!xColorList->Load())
-            continue;
-
-        auto nPos = xColorList->GetIndexOfColor(rColor);
-        if (nPos == -1)
-            continue;
-
-        
m_xLbPaletteSelector->set_active_text(aPaletteManager.GetPaletteName());
-        SelectPaletteLbHdl(*m_xLbPaletteSelector);
-
-        m_xValSetColorBox->SelectItem(m_xValSetColorBox->GetItemId(nPos));
-
-        return;
+        aPaletteManager.SetPalette(nPalettePos, true /*bPosOnly*/);
+
+        if (/*custom palette*/ nPalettePos == 0 ||
+            /*theme colors palette*/ aPaletteManager.IsThemePaletteSelected() 
||
+            /*document colors palette*/ nPalettePos == 
aPaletteManager.GetPaletteCount() - 1)
+        {
+            aPaletteManager.ReloadColorSet(*m_xValSetColorBox);
+
+            for (size_t nItemPos = 0, nItemCount = 
m_xValSetColorBox->GetItemCount();
+                 nItemPos < nItemCount; nItemPos++)
+            {
+                auto nItemId = m_xValSetColorBox->GetItemId(nItemPos);
+                if (m_xValSetColorBox->GetItemColor(nItemId) == rColor)
+                {
+                    
m_xLbPaletteSelector->set_active_text(aPaletteManager.GetPaletteName());
+                    SelectPaletteLbHdl(*m_xLbPaletteSelector);
+
+                    m_xValSetColorBox->SelectItem(nItemId);
+
+                    return;
+                }
+            }
+        }
+        else
+        {
+            xColorList = 
XPropertyList::AsColorList(XPropertyList::CreatePropertyListFromURL(
+                XPropertyListType::Color, 
aPaletteManager.GetSelectedPalettePath()));
+            if (!xColorList->Load())
+                continue;
+
+            auto nPos = xColorList->GetIndexOfColor(rColor);
+            if (nPos == -1)
+                continue;
+
+            
m_xLbPaletteSelector->set_active_text(aPaletteManager.GetPaletteName());
+            SelectPaletteLbHdl(*m_xLbPaletteSelector);
+
+            m_xValSetColorBox->SelectItem(m_xValSetColorBox->GetItemId(nPos));
+
+            return;
+        }
     }
+
+    // color not found in any palette
+    m_xLbPaletteSelector->set_active_text(OUString());
+    m_xValSetColorBox->Clear();
 }
 
 SvxDefaultColorOptPage::SvxDefaultColorOptPage(weld::Container* pPage, 
weld::DialogController* pController, const SfxItemSet& rInAttrs)
commit b677fab9172ae1c8d5a1b54419d5d171702bb62b
Author:     Justin Luth <[email protected]>
AuthorDate: Sat Nov 29 17:08:59 2025 -0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Tue Dec 16 16:48:23 2025 +0100

    tdf#165180 xlsx UI: round-trip as 2007 Spreadsheet, not 2010-365
    
    Historically we have ALWAYS round-tripped with the 2007 filter.
    
    A recent change (in this patchset)
    started importing xlsx without a lowestEdited as 2010+ documents,
    and thus they will then also export as 2010+.
    
    With this patch, we round-trip the original lowestEdited,
    and thus we can again round-trip 2007 as 2007.
    
    make CppunitTest_sc_subsequent_export_test2 \
        CPPUNIT_TEST_NAME=testMatrixMultiplicationXLSX
    
    Change-Id: I85c4163f76902f2972193a2fdfe7ee9b4dd510c0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195035
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <[email protected]>
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195527

diff --git a/sc/inc/scextopt.hxx b/sc/inc/scextopt.hxx
index 4a71fdd7dd30..1cc8b3f3bcd7 100644
--- a/sc/inc/scextopt.hxx
+++ b/sc/inc/scextopt.hxx
@@ -30,6 +30,7 @@ struct ScExtDocSettings
     double              mfTabBarWidth;      ///< Width of the tabbar, relative 
to frame window width (0.0 ... 1.0).
     sal_uInt32          mnLinkCnt;          ///< Recursive counter for loading 
external documents.
     SCTAB               mnDisplTab;         ///< Index of displayed sheet.
+    std::optional<sal_Int16> moLowestEdited; ///< Oldest Excel version that 
edited this document.
 
     explicit            ScExtDocSettings();
 };
diff --git a/sc/qa/unit/subsequent_export_test2.cxx 
b/sc/qa/unit/subsequent_export_test2.cxx
index 1e7f7a0ce920..f0cf473f2c04 100644
--- a/sc/qa/unit/subsequent_export_test2.cxx
+++ b/sc/qa/unit/subsequent_export_test2.cxx
@@ -127,6 +127,13 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, 
testMatrixMultiplicationXLSX)
 {
     createScDoc("xlsx/matrix-multiplication.xlsx");
 
+    // tdf#165180: should be recognized as a 2007 XLSX format when loaded (and 
resaved...)
+    SfxMedium* pMedium = getScDocShell()->GetMedium();
+    SfxFilterMatcher aMatcher(u"com.sun.star.sheet.SpreadsheetDocument"_ustr);
+    std::shared_ptr<const SfxFilter> pFilter;
+    aMatcher.DetectFilter(*pMedium, pFilter);
+    CPPUNIT_ASSERT_EQUAL(u"Calc MS Excel 2007 XML"_ustr, 
pFilter->GetFilterName());
+
     save(TestFilter::XLSX);
 
     xmlDocUniquePtr pDoc = parseExport(u"xl/worksheets/sheet1.xml"_ustr);
@@ -141,6 +148,11 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, 
testMatrixMultiplicationXLSX)
 
     // make sure that the CellFormulaType is array.
     CPPUNIT_ASSERT_EQUAL(u"array"_ustr, CellFormulaType);
+
+    // tdf#165180: should be recognizable as a 2007 XLSX format when saved
+    xmlDocUniquePtr pWorkbook = parseExport(u"xl/workbook.xml"_ustr);
+    // lowestEdited = 4 needs to be round-tripped in order to detect as a 2007 
ECMA_376_1ST_EDITION
+    assertXPath(pWorkbook, "/x:workbook/x:fileVersion", "lowestEdited", u"4");
 }
 
 CPPUNIT_TEST_FIXTURE(ScExportTest2, testRefStringXLSX)
@@ -1418,7 +1430,7 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf123645XLSX)
 CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf125173XLSX)
 {
     createScDoc("ods/text_box_hyperlink.ods");
-    save(TestFilter::XLSX);
+    saveAndReload(TestFilter::XLSX);
 
     xmlDocUniquePtr pDoc = parseExport(u"xl/drawings/drawing1.xml"_ustr);
     CPPUNIT_ASSERT(pDoc);
@@ -1430,6 +1442,13 @@ CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf125173XLSX)
                 u"http://www.google.com/";);
     assertXPath(pXmlRels, "/rels:Relationships/rels:Relationship[@Id='rId1']", 
"TargetMode",
                 u"External");
+
+    // tdf#137883: should be recognized as a 2010+ XLSX format when reloaded 
(and resaved...)
+    SfxMedium* pMedium = getScDocShell()->GetMedium();
+    SfxFilterMatcher aMatcher(u"com.sun.star.sheet.SpreadsheetDocument"_ustr);
+    std::shared_ptr<const SfxFilter> pFilter;
+    aMatcher.DetectFilter(*pMedium, pFilter);
+    CPPUNIT_ASSERT_EQUAL(u"Calc Office Open XML"_ustr, 
pFilter->GetFilterName());
 }
 
 CPPUNIT_TEST_FIXTURE(ScExportTest2, testTdf79972XLSX)
diff --git a/sc/source/filter/excel/excdoc.cxx 
b/sc/source/filter/excel/excdoc.cxx
index 0d0c6655aaab..fc794b00ab60 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -852,13 +852,17 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm )
             FSNS(XML_xmlns, XML_xr6), rStrm.getNamespaceURL(OOX_NS(xr6)),
             FSNS(XML_xmlns, XML_xr10), rStrm.getNamespaceURL(OOX_NS(xr10)),
             FSNS(XML_xmlns, XML_xr2), rStrm.getNamespaceURL(OOX_NS(xr2)) );
-    rWorkbook->singleElement( XML_fileVersion,
-            XML_appName, "Calc"
+
+    rtl::Reference<sax_fastparser::FastAttributeList> pAttrListFileVersion
+        = sax_fastparser::FastSerializerHelper::createAttrList();
+    pAttrListFileVersion->add(XML_appName, "Calc");
+    std::optional<sal_Int16> oLow = 
GetExtDocOptions().GetDocSettings().moLowestEdited;
+    if (oLow.has_value())
+        pAttrListFileVersion->add(XML_lowestEdited, OString::number(*oLow));
             // OOXTODO: XML_codeName
             // OOXTODO: XML_lastEdited
-            // OOXTODO: XML_lowestEdited
             // OOXTODO: XML_rupBuild
-    );
+    rWorkbook->singleElement(XML_fileVersion, pAttrListFileVersion);
 
     if (bHasPasswordHash)
         rWorkbook->singleElement(XML_fileSharing,
diff --git a/sc/source/filter/inc/workbooksettings.hxx 
b/sc/source/filter/inc/workbooksettings.hxx
index 1078b3e6c096..729daa754664 100644
--- a/sc/source/filter/inc/workbooksettings.hxx
+++ b/sc/source/filter/inc/workbooksettings.hxx
@@ -19,6 +19,7 @@
 
 #pragma once
 
+#include <scextopt.hxx>
 #include "workbookhelper.hxx"
 
 namespace oox { class AttributeList; }
@@ -81,9 +82,12 @@ class WorkbookSettings : public WorkbookHelper
 {
 public:
     explicit            WorkbookSettings( const WorkbookHelper& rHelper );
+    ~WorkbookSettings();
 
     /** Imports the fileSharing element containing write protection settings. 
*/
     void                importFileSharing( const AttributeList& rAttribs );
+    /** Imports the fileVersion element containing last-edited-by settings. */
+    void                importFileVersion( const AttributeList& rAttribs );
     /** Imports the workbookPr element containing global workbook settings. */
     void                importWorkbookPr( const AttributeList& rAttribs );
     /** Imports the calcPr element containing workbook calculation settings. */
@@ -112,6 +116,7 @@ private:
     FileSharingModel    maFileSharing;
     WorkbookSettingsModel maBookSettings;
     CalcSettingsModel   maCalcSettings;
+    ScExtDocOptions maExtDocOptions;
 };
 
 } // namespace oox::xls
diff --git a/sc/source/filter/oox/workbookfragment.cxx 
b/sc/source/filter/oox/workbookfragment.cxx
index 18eed29be335..14db1335349d 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -118,6 +118,7 @@ ContextHandlerRef WorkbookFragment::onCreateContext( 
sal_Int32 nElement, const A
                 case XLS_TOKEN( pivotCaches ):          return this;
 
                 case XLS_TOKEN( fileSharing ):          
getWorkbookSettings().importFileSharing( rAttribs );    break;
+                case XLS_TOKEN( fileVersion ):          
getWorkbookSettings().importFileVersion( rAttribs );    break;
                 case XLS_TOKEN( workbookPr ):           
getWorkbookSettings().importWorkbookPr( rAttribs );     break;
                 case XLS_TOKEN( calcPr ):               
getWorkbookSettings().importCalcPr( rAttribs );         break;
                 case XLS_TOKEN( oleSize ):              
getViewSettings().importOleSize( rAttribs );            break;
diff --git a/sc/source/filter/oox/workbooksettings.cxx 
b/sc/source/filter/oox/workbooksettings.cxx
index 2308c644e6fa..d514d8d30b58 100644
--- a/sc/source/filter/oox/workbooksettings.cxx
+++ b/sc/source/filter/oox/workbooksettings.cxx
@@ -37,7 +37,9 @@
 #include <oox/token/tokens.hxx>
 #include <unitconverter.hxx>
 #include <biffhelper.hxx>
+#include <document.hxx>
 #include <docuno.hxx>
+#include <scextopt.hxx>
 
 namespace oox::xls {
 
@@ -106,6 +108,13 @@ CalcSettingsModel::CalcSettingsModel() :
 WorkbookSettings::WorkbookSettings( const WorkbookHelper& rHelper ) :
     WorkbookHelper( rHelper )
 {
+    if (getScDocument().GetExtDocOptions())
+        maExtDocOptions = *getScDocument().GetExtDocOptions();
+}
+
+WorkbookSettings::~WorkbookSettings()
+{
+    
getScDocument().SetExtDocOptions(std::make_unique<ScExtDocOptions>(maExtDocOptions));
 }
 
 void WorkbookSettings::importFileSharing( const AttributeList& rAttribs )
@@ -119,6 +128,13 @@ void WorkbookSettings::importFileSharing( const 
AttributeList& rAttribs )
     maFileSharing.mbRecommendReadOnly = rAttribs.getBool( 
XML_readOnlyRecommended, false );
 }
 
+void WorkbookSettings::importFileVersion(const AttributeList& rAttribs)
+{
+    const sal_Int16 nLow = rAttribs.getInteger(XML_lowestEdited, -1);
+    if (nLow != -1)
+        maExtDocOptions.GetDocSettings().moLowestEdited = nLow;
+}
+
 void WorkbookSettings::importWorkbookPr( const AttributeList& rAttribs )
 {
     maBookSettings.maCodeName          = rAttribs.getString( XML_codeName, 
OUString() );
commit 5e8a2f525d1eb3f1ad51a14792e50f0a63a66c08
Author:     Justin Luth <[email protected]>
AuthorDate: Sat Nov 29 16:06:52 2025 -0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Tue Dec 16 16:48:18 2025 +0100

    tdf#165180 xlsx UI: prefer Excel 2010–365 Spreadsheet, not 2007
    
    A prior commit in this patchset
    clarified what "Calc Office Open XML" is targeted for.
    
    Probably it is time for us to intentionally target the 2010+ format...
    
    However, this does not yet result in the right filter
    being chosen for round-tripping an xlsx file...
    
    Change-Id: Ia4dc82bd55aecb24854eba66dc0c77a214d251a8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195034
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <[email protected]>
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195526

diff --git a/officecfg/registry/data/org/openoffice/TypeDetection/UISort.xcu 
b/officecfg/registry/data/org/openoffice/TypeDetection/UISort.xcu
index 7ccb01532d03..f8dc51a005d0 100644
--- a/officecfg/registry/data/org/openoffice/TypeDetection/UISort.xcu
+++ b/officecfg/registry/data/org/openoffice/TypeDetection/UISort.xcu
@@ -21,7 +21,7 @@
   <node oor:name="ModuleDependendFilterOrder">
     <node oor:name="com.sun.star.sheet.SpreadsheetDocument" oor:op="replace" 
install:module="calc">
       <prop oor:name="SortedFilterList">
-        <value oor:separator=";">calc8;calc8_template;StarOffice XML 
(Calc);calc_StarOffice_XML_Calc_Template;OpenDocument Spreadsheet Flat XML;UOF 
spreadsheet;Calc MS Excel 2007 XML;Calc MS Excel 2007 XML Template;Calc MS 
Excel 2007 Binary;MS Excel 2003 XML;MS Excel 97;MS Excel 97 Vorlage/Template;MS 
Excel 95;MS Excel 95 Vorlage/Template;MS Excel 5.0/95;MS Excel 5.0/95 
Vorlage/Template;MS Excel 4.0;MS Excel 4.0 Vorlage/Template;;DIF;dBase;HTML 
(StarCalc);Lotus;Pocket Excel;Quattro Pro 6.0;Rich Text Format 
(StarCalc);SYLK;Text - txt - csv (StarCalc);calc_HTML_WebQuery;Calc Office Open 
XML;Calc Office Open XML Template;ADO Rowset XML</value>
+        <value oor:separator=";">calc8;calc8_template;StarOffice XML 
(Calc);calc_StarOffice_XML_Calc_Template;OpenDocument Spreadsheet Flat XML;UOF 
spreadsheet;Calc Office Open XML;Calc Office Open XML Template;;MS Excel 97;MS 
Excel 97 Vorlage/Template;MS Excel 95;MS Excel 95 Vorlage/Template;MS Excel 
5.0/95;MS Excel 5.0/95 Vorlage/Template;MS Excel 4.0;MS Excel 4.0 
Vorlage/Template;;DIF;dBase;HTML (StarCalc);Lotus;Pocket Excel;Quattro Pro 
6.0;Rich Text Format (StarCalc);SYLK;Text - txt - csv 
(StarCalc);calc_HTML_WebQuery;ADO Rowset XML;Calc MS Excel 2007 XML;Calc MS 
Excel 2007 XML Template;Calc MS Excel 2007 Binary;Calc MS Excel 2007 VBA XML;MS 
Excel 2003 XML</value>
       </prop>
     </node>
     <node oor:name="com.sun.star.drawing.DrawingDocument" oor:op="replace" 
install:module="draw">
commit 7c8fa069de60572d37d3230f383716a16270e5bb
Author:     Justin Luth <[email protected]>
AuthorDate: Fri Dec 5 20:25:47 2025 -0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Tue Dec 16 16:48:13 2025 +0100

    tdf#165180 xlsx import: detect lowestEdited > 4 as 2010+ filter
    
    WARNING: this patch instantly flips LO
    to importing/exporting most xlsx documents with the Excel 2010 filter.
    Prior to this, everything used Excel 2007 filter for import or export.
    
    xl/workbook.xml contains a fileVersion element
    that has a lowestEdited value (similar to DOCX's compatibilityMode).
    
    Although undocumented, lowestEdited in practice seems to mean:
    - 4 is Excel 2007
    - 5 is Excel 2010
    - 6 is (probably) Excel 2013
    - 7 is Excel 2019 (probably also 2016)
    
    My Excel 2024 produced this:
    <fileVersion appName="xl" lastEdited="7" lowestEdited="7"
                 rupBuild="27928"/>
    
    If there is no lowestEdited, then just use lastEdited.
    There apparently is no default value for lowestEdited or lastEdited
    (unlike compatibilityMode - which is treated as 12 when not specified).
    
    make CppunitTest_sc_subsequent_export_test2 \
        CPPUNIT_TEST_NAME=testGroupShape
    
    Change-Id: I83b093279949214cbf819d0597cb923347cfb04d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195118
    Reviewed-by: Justin Luth <[email protected]>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195523

diff --git a/include/oox/core/filterdetect.hxx 
b/include/oox/core/filterdetect.hxx
index 89b71c603f09..2ce6f030a700 100644
--- a/include/oox/core/filterdetect.hxx
+++ b/include/oox/core/filterdetect.hxx
@@ -77,6 +77,7 @@ public:
 
 private:
     void parseSettings(const AttributeList& rAttribs);
+    void parseWorkbook(const AttributeList& rAttribs);
     void                parseRelationship( const AttributeList& rAttribs );
 
     OUString            getFilterNameFromContentType( std::u16string_view 
rContentType, std::u16string_view rFileName );
diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index b48df147673b..cc75b51ee088 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -98,6 +98,14 @@ void SAL_CALL FilterDetectDocHandler::startFastElement(
                 parseSettings(aAttribs);
             break;
 
+        // cases for xl/workbook.xml
+        case XLS_TOKEN(workbook):
+            break;
+        case XLS_TOKEN(fileVersion):
+            if (!maContextStack.empty() && (maContextStack.back() == 
XLS_TOKEN(workbook)))
+                parseWorkbook(aAttribs);
+            break;
+
         // cases for _rels/.rels
         case PR_TOKEN( Relationships ):
         break;
@@ -164,6 +172,19 @@ void FilterDetectDocHandler::parseSettings(const 
AttributeList& rAttribs)
     }
 }
 
+void FilterDetectDocHandler::parseWorkbook(const AttributeList& rAttribs)
+{
+    if (maOOXMLVariant != OOXMLVariant::ECMA_Transitional)
+        return;
+
+    // tdf#165180 Remember filter when opening file as 'Office Open XML 
Spreadsheet'
+    // (fileVersion can only exist once, and lowestEdited can only be defined 
once - else corrupt)
+    // lowestEdited: 4 is 2007, 5 is 2010, 6 is 201?, 7 is 201?-2024
+    const sal_Int32 nDefaultValue = rAttribs.getInteger(XML_lastEdited, 99);
+    if (rAttribs.getInteger(XML_lowestEdited, nDefaultValue) > 4)
+        maOOXMLVariant = OOXMLVariant::ISO_Transitional; // Excel 2010+
+}
+
 void FilterDetectDocHandler::parseRelationship( const AttributeList& rAttribs )
 {
     OUString aType = rAttribs.getStringDefaulted( XML_Type);
@@ -230,14 +251,32 @@ OUString 
FilterDetectDocHandler::getFilterNameFromContentType( std::u16string_vi
     }
 
     if( rContentType == 
u"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")
-        return u"MS Excel 2007 XML"_ustr;
+    {
+        switch (maOOXMLVariant)
+        {
+            case OOXMLVariant::ISO_Transitional:
+            case OOXMLVariant::ISO_Strict: // Not supported, map to ISO 
transitional
+                return u"Office Open XML Spreadsheet"_ustr; // Excel 2010+
+            case OOXMLVariant::ECMA_Transitional:
+                return u"MS Excel 2007 XML"_ustr;
+        }
+    }
 
     if (rContentType == 
u"application/vnd.ms-excel.sheet.macroEnabled.main+xml")
         return u"MS Excel 2007 VBA XML"_ustr;
 
     if( rContentType == 
u"application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml"
 ||
         rContentType == 
u"application/vnd.ms-excel.template.macroEnabled.main+xml" )
-        return u"MS Excel 2007 XML Template"_ustr;
+    {
+        switch (maOOXMLVariant)
+        {
+            case OOXMLVariant::ISO_Transitional:
+            case OOXMLVariant::ISO_Strict: // Not supported, map to ISO 
transitional
+                return u"Office Open XML Spreadsheet Template"_ustr; // Excel 
2010+
+            case OOXMLVariant::ECMA_Transitional:
+                return u"MS Excel 2007 XML Template"_ustr;
+        }
+    }
 
     if ( rContentType == 
u"application/vnd.ms-excel.sheet.binary.macroEnabled.main" )
         return u"MS Excel 2007 Binary"_ustr;
@@ -457,6 +496,7 @@ OUString SAL_CALL FilterDetect::detect( Sequence< 
PropertyValue >& rMediaDescSeq
             aParser.registerNamespace( NMSP_officeRel );
             aParser.registerNamespace( NMSP_packageContentTypes );
             aParser.registerNamespace(NMSP_doc); // for W_TOKEN
+            aParser.registerNamespace(NMSP_xls); // for XLS_TOKEN
 
             OUString aFileName;
             aMediaDescriptor[utl::MediaDescriptor::PROP_URL] >>= aFileName;
@@ -469,11 +509,20 @@ OUString SAL_CALL FilterDetect::detect( Sequence< 
PropertyValue >& rMediaDescSeq
             try
             {
                 // Text documents can't use .rels to determine maOOXMLVariant. 
Use compatibilityMode
-                 aParser.parseStream(aZipStorage, u"word/settings.xml"_ustr);
+                aParser.parseStream(aZipStorage, u"word/settings.xml"_ustr);
             }
             catch(const Exception&)
             {
                 // not a MS Word text document, or file might not exist
+                try
+                {
+                    // Spreadsheets distinguish maOOXMLVariant using 
fileVersion lowestEdited
+                    aParser.parseStream(aZipStorage, u"xl/workbook.xml"_ustr);
+                }
+                catch(const Exception&)
+                {
+                    // not a MS Excel spreadsheet document, or file might not 
exist
+                }
             }
             // Order is critical: .rels and then settings.xml must be parsed 
before [Content_Types]
             aParser.parseStream( aZipStorage, u"[Content_Types].xml"_ustr );
diff --git a/sc/qa/unit/subsequent_export_test2.cxx 
b/sc/qa/unit/subsequent_export_test2.cxx
index eec405eaa66d..1e7f7a0ce920 100644
--- a/sc/qa/unit/subsequent_export_test2.cxx
+++ b/sc/qa/unit/subsequent_export_test2.cxx
@@ -21,6 +21,8 @@
 #include <comphelper/propertyvalue.hxx>
 #include <unotools/syslocaleoptions.hxx>
 #include <formula/grammar.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
 #include <svl/numformat.hxx>
 #include <svl/zformat.hxx>
 #include <svx/svdograf.hxx>
@@ -45,8 +47,15 @@ ScExportTest2::ScExportTest2()
 CPPUNIT_TEST_FIXTURE(ScExportTest2, testGroupShape)
 {
     createScDoc("xlsx/groupShape.xlsx");
-    save(TestFilter::XLSX);
 
+    // tdf#165180: should be recognized as a 2010+ XLSX format when loaded 
(and resaved...)
+    SfxMedium* pMedium = getScDocShell()->GetMedium();
+    SfxFilterMatcher aMatcher(u"com.sun.star.sheet.SpreadsheetDocument"_ustr);
+    std::shared_ptr<const SfxFilter> pFilter;
+    aMatcher.DetectFilter(*pMedium, pFilter);
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("import", u"Calc Office Open XML"_ustr, 
pFilter->GetFilterName());
+
+    save(TestFilter::XLSX);
     xmlDocUniquePtr pDoc = parseExport(u"xl/drawings/drawing1.xml"_ustr);
     CPPUNIT_ASSERT(pDoc);
     assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor/xdr:grpSp/xdr:grpSpPr");

Reply via email to