tdf#118812 DOCX import: fix table style preference – part 2

Apply table styles according to OOXML and – in
the case of font sizes – MSO exception
"overrideTableStyleFontSizeAndJustification".

Fix temporary regression in styles of paragraph
portions, table cell regions and nested tables from
commit f15d67442972c5f69c71925a6bfa5aa1a39d54eb
(tdf#129575 DOCX import: fix table style preference).

Unit test document was created by Justin Luth.

Change-Id: I7b076ac27f5b44d44934b7efb18ac4a878f8b596
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88869
Tested-by: Jenkins
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/ooxmlexport/data/calendar5.docx b/sw/qa/extras/ooxmlexport/data/calendar5.docx
new file mode 100644
index 0000000..a276346
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/calendar5.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx b/sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx
new file mode 100644
index 0000000..e2cbffc
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf118812_tableStyles-comprehensive.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx
index 5533789..d1e62fb 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx
@@ -316,8 +316,12 @@ DECLARE_OOXMLEXPORT_TEST(testCalendar3, "calendar3.docx")
    // TableStyle:firstRow (for header rows 1 and 2) color and size overrides document rPrDefault
    uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
    uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A2"), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0x5B9BD5), getProperty<sal_Int32>(getRun(xCell,1), "CharColor"));
    CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(xCell,1), "CharHeight"));
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0x5B9BD5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 1), "CharColor"));
    CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),1), "CharHeight"));
    // direct formatting in A1
    uno::Reference<text::XTextRange> xCell2(xTable->getCellByName("A1"), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0x2E74B5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell2->getText()), 1), "CharColor"));
    CPPUNIT_ASSERT_EQUAL(20.f, getProperty<float>(getRun(getParagraphOfText(1, xCell2->getText()),1), "CharHeight"));
}

DECLARE_OOXMLEXPORT_TEST(testCalendar4, "calendar4.docx")
@@ -329,6 +333,23 @@ DECLARE_OOXMLEXPORT_TEST(testCalendar4, "calendar4.docx")
    CPPUNIT_ASSERT_EQUAL(14.f, getProperty<float>(getRun(xCell,1), "CharHeight"));
}

DECLARE_OOXMLEXPORT_TEST(testCalendar5, "calendar5.docx")
{
    // check text portions with and without direct formatting
    uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
    uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
    // text portions with direct formatting
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0x2E74B5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 1), "CharColor"));
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xFF0000), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 2), "CharColor"));
    // default paragraph text color
    CPPUNIT_ASSERT_EQUAL(sal_Int32(0x5B9BD5), getProperty<sal_Int32>(getRun(getParagraphOfText(1, xCell->getText()), 3), "CharColor"));
    // text portions with direct formatting
    CPPUNIT_ASSERT_EQUAL(20.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),1), "CharHeight"));
    CPPUNIT_ASSERT_EQUAL(10.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),2), "CharHeight"));
    // default paragraph text size
    CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()),3), "CharHeight"));
}

DECLARE_OOXMLEXPORT_TEST(testTcBorders, "testTcBorders.docx")
{
    //fdo#76635 : Table borders are not getting preserved.
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
index 45bcc9a..3b5726d 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx
@@ -459,9 +459,9 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf128752, "tdf128752.docx")
DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf119054, "tdf119054.docx")
{
    xmlDocPtr pXmlDoc = parseExport();
    // Overwrite applied table style with before and after spacing of Heading2
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before", "0");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after", "360");
    // Don't overwrite before and after spacing of Heading2 by table style
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "before");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "after");
    // Use table style based single line spacing instead of the docDefaults' 254
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:p[1]/w:pPr/w:spacing", "line", "240");
}
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index b7f6852..991916e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -30,7 +30,6 @@
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/style/LineSpacing.hpp>
#include <com/sun/star/style/LineSpacingMode.hpp>
//#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp>
@@ -249,6 +248,82 @@ DECLARE_OOXMLEXPORT_TEST(testTdf129575_docDefault, "tdf129575-docDefault.docx")

}

DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf118812, "tdf118812_tableStyles-comprehensive.docx")
{
    xmlDocPtr pXmlDoc = parseExport("word/document.xml");
    // cell A1
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "lineRule");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "line");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "before", "480");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:pPr/w:spacing", "after", "20");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "CharSubStyleDefaults");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[1]/w:tc/w:p/w:r[2]/w:rPr/w:sz", "val", "16");
    // cell A2
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "lineRule");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "line");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "before", "480");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:pPr/w:spacing", "after", "20");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "ParaSubStyleDefaultsChar");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[2]/w:rPr/w:sz", "val", "16");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[3]/w:rPr/w:rStyle", "val", "CharSubStyleNormal");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[3]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[2]/w:tc/w:p/w:r[3]/w:rPr/w:sz", "val", "16");
    // cell A3
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:pStyle", "val", "ParaSubStyleNormal");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "lineRule");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "line");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "before", "480");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:pPr/w:spacing", "after", "280");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[1]/w:rPr/w:sz", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "CharSubStyleNormal");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:rPr/w:sz", 0);
    // cell A4
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:pStyle", "val", "ParaSubStyleDefaults");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "lineRule");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "line");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "before", "480");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:pPr/w:spacing", "after", "200");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[1]/w:rPr/w:sz", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:rPr/w:rStyle", "val", "CharSubStyleDefaults");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:rPr/w:sz", 0);
    // cell A5
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "lineRule");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "line");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:rPr", "color");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:rPr", "sz");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "before", "480");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:pPr/w:spacing", "after", "20");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:r[1]/w:rPr/w:color", 1);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:r[1]/w:rPr/w:color", "val", "AAAA00"); // all text in color
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16");
    // cell A6
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:pStyle", "val", "Normal");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "lineRule");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "line");
    assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:rPr", "color");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:rPr/w:sz", "val", "16");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "before", "480");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:pPr/w:spacing", "after", "20");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[1]/w:rPr/w:color", 0);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[1]/w:rPr/w:sz", "val", "16");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[2]/w:rPr/w:color", 1);
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[2]/w:rPr/w:color", "val", "AAAA00");
    assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc/w:p/w:r[2]/w:rPr/w:sz", "val", "16");
}

DECLARE_OOXMLEXPORT_TEST(testTdf106970, "tdf106970.docx")
{
    // The second paragraph (first numbered one) had 0 bottom margin:
diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx
index 79cb240..b51efa9 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -1003,40 +1003,12 @@ void SwXCell::setPropertyValue(const OUString& rPropertyName, const uno::Any& aV
        auto pEntry(m_pPropSet->getPropertyMap().getByName(rPropertyName));
        if ( !pEntry )
        {
            // not a table property: if it is a paragraph/character property, consider applying it to the underlying text.
            // not a table property: ignore it, if it is a paragraph/character property
            const SfxItemPropertySet& rParaPropSet = *aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH);
            pEntry = rParaPropSet.getPropertyMap().getByName(rPropertyName);

            if ( pEntry )
            {
                SwNodeIndex aIdx( *GetStartNode(), 1 );
                const SwNode* pEndNd = aIdx.GetNode().EndOfSectionNode();
                while ( &aIdx.GetNode() != pEndNd )
                {
                    const SwTextNode* pNd = aIdx.GetNode().GetTextNode();
                    if ( pNd )
                    {
                        //point and mark selecting the whole paragraph
                        SwPaM aPaM(*pNd, 0, *pNd, pNd->GetText().getLength());
                        const bool bHasAttrSet = pNd->HasSwAttrSet();
                        const SfxItemSet& aSet = pNd->GetSwAttrSet();
                        // isPARATR: replace DEFAULT_VALUE properties only
                        // Require that the property is default in the paragraph style as well,
                        // unless the style is the default style.
                        // isCHRATR: change the base/auto SwAttr property, but don't remove the DIRECT hints
                        bool bCustomParent = false;
                        if (const SwFormatColl* pFormatColl = pNd->GetFormatColl())
                        {
                            bCustomParent = pFormatColl->GetPoolFormatId() != RES_POOLCOLL_STANDARD;
                        }
                        bool bSearchInParent = bCustomParent && !pNd->GetNumRule();
                        if ( !bHasAttrSet || SfxItemState::DEFAULT == aSet.GetItemState(pEntry->nWID, bSearchInParent) )
                            SwUnoCursorHelper::SetPropertyValue(aPaM, rParaPropSet, rPropertyName, aValue, SetAttrMode::DONTREPLACE);
                    }
                    ++aIdx;
                }
                return;
            }
        }

        if(!pEntry)
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index ab51d4f..d02e26a 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -28,6 +28,10 @@
#include <com/sun/star/text/RelOrientation.hpp>
#include <com/sun/star/text/SizeType.hpp>
#include <com/sun/star/text/XTextRangeCompare.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include "TablePositionHandler.hxx"
#include "ConversionHelper.hxx"
#include "util.hxx"
@@ -1066,58 +1070,64 @@ css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTabl

// table style has got bigger precedence than docDefault style,
// but lower precedence than the paragraph styles and direct paragraph formatting
void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo)
void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableParaProperties, css::beans::PropertyValues rCellProperties)
{
    for( auto const& eId : rInfo.aTablePropertyIds )
    for( auto const& eId : aAllTableParaProperties )
    {
        // apply paragraph and character properties of the table style on table paragraphs
        if ( isParagraphProperty(eId) || isCharacterProperty(eId) )
        // if there is no direct paragraph formatting
        if ( !rParaProp.m_pPropertyMap->isSet(eId) )
        {
            // check all paragraphs of the table
            for (const auto& rParaProp : m_rDMapper_Impl.m_aParagraphsToEndTable)
            OUString sPropertyName = getPropertyName(eId);
            auto pCellProp = std::find_if(rCellProperties.begin(), rCellProperties.end(),
                [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
            // this cell applies the table style property
            if (pCellProp != rCellProperties.end())
            {
                // there is no direct paragraph formatting
                if (!rParaProp.m_pPropertyMap->isSet(eId))
                bool bDocDefault;
                OUString sParaStyleName;
                rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
                StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
                uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
                // use table style when no paragraph style setting or a docDefault value is applied instead of it
                if ( aParaStyle == uno::Any() || bDocDefault ||
                   // set default behaviour of MSO ("overrideTableStyleFontSizeAndJustification" exception):
                   // if Normal style defines 11 pt or 12 pt font heights, table style overrides its font size
                   (eId == PROP_CHAR_HEIGHT && sParaStyleName == "Standard" && (aParaStyle == uno::Any(double(11)) || aParaStyle == uno::Any(double(12))))) try
                {
                    bool bDocDefault;
                    OUString sParaStyleName;
                    rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
                    StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
                    uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
                    // use table style when a docDefault value is applied instead of it,
                    // and there is no associated TableStyleSheetEntry
                    // TODO: replace CNF_ALL with the actual mask
                    if ( (aParaStyle == uno::Any() || bDocDefault) && !rInfo.pTableStyle->GetProperties(CNF_ALL)->getProperty(eId) )
                    // check property state of paragraph
                    uno::Reference<text::XParagraphCursor> xParagraph(
                        rParaProp.m_rEndParagraph->getText()->createTextCursorByRange(rParaProp.m_rEndParagraph), uno::UNO_QUERY_THROW );
                    // select paragraph
                    xParagraph->gotoStartOfParagraph( true );
                    uno::Reference< beans::XPropertyState > xParaProperties( xParagraph, uno::UNO_QUERY_THROW );
                    if ( xParaProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE )
                    {
                        OUString sPropertyName = getPropertyName(eId);
                        auto pTableProp = std::find_if(rInfo.aTableProperties.begin(), rInfo.aTableProperties.end(),
                            [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
                        if (pTableProp != rInfo.aTableProperties.end())
                        // apply style setting when the paragraph doesn't modify it
                        rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pCellProp->Value );
                    }
                    else
                    {
                        // apply style setting only on text portions without direct modification of it
                        uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xParagraph, uno::UNO_QUERY);
                        uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
                        uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
                        uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
                        while ( xRunEnum->hasMoreElements() )
                        {
                            try
                            uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
                            uno::Reference< beans::XPropertyState > xRunProperties( xRun, uno::UNO_QUERY_THROW );
                            if ( xRunProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE )
                            {
                                rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pTableProp->Value );
                            }
                            catch ( const uno::Exception & )
                            {
                                TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
                                 uno::Reference< beans::XPropertySet > xRunPropertySet( xRun, uno::UNO_QUERY_THROW );
                                 xRunPropertySet->setPropertyValue( sPropertyName, pCellProp->Value );
                            }
                        }
                    }
                    // table style can overwrite paragraph style, when the paragraph style property has a default value, restore it
                    // TODO remove the associated TableStyleSheetEntry styles, if needed
                    else if ( aParaStyle != uno::Any() && !bDocDefault )
                    {
                        OUString sPropertyName = getPropertyName(eId);
                        try
                        {
                            rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, aParaStyle );
                        }
                        catch ( const uno::Exception & )
                        {
                            TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
                        }
                    }
                }
                catch ( const uno::Exception & )
                {
                    TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
                }
            }
        }
@@ -1153,6 +1163,60 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
        uno::Reference<text::XTextRange> xEnd;

        bool bFloating = !aFrameProperties.empty();

        // OOXML table style may contain paragraph properties, apply these on cell paragraphs
        if ( m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements() )
        {
            // collect all paragraph properties used in table styles
            PropertyMapPtr pAllTableProps( new PropertyMap );
            pAllTableProps->InsertProps(aTableInfo.pTableDefaults);
            if ( aTableInfo.pTableStyle )
                pAllTableProps->InsertProps(aTableInfo.pTableStyle->GetProperties( CNF_ALL ));
            for (const auto& eId : pAllTableProps->GetPropertyIds())
            {
                if ( !isParagraphProperty(eId) && !isCharacterProperty(eId) )
                    pAllTableProps->Erase(eId);
            }
            std::vector< PropertyIds > aAllTableParaProperties = pAllTableProps->GetPropertyIds();

            if ( !aAllTableParaProperties.empty() )
            {
                for (size_t nRow = 0; nRow < m_aTableRanges.size(); ++nRow)
                {
                    for (size_t nCell = 0; nCell < m_aTableRanges[nRow].size(); ++nCell)
                    {
                        auto rStartPara = m_aTableRanges[nRow][nCell][0];
                        auto rEndPara = m_aTableRanges[nRow][nCell][1];
                        uno::Reference<text::XTextRangeCompare> xTextRangeCompare(rStartPara->getText(), uno::UNO_QUERY);
                        bool bApply = false;
                        // search paragraphs of the cell
                        std::vector<TableParagraph>::iterator aIt = m_rDMapper_Impl.m_aParagraphsToEndTable.begin();
                        while ( aIt != m_rDMapper_Impl.m_aParagraphsToEndTable.end() ) try
                        {
                            if (!bApply && xTextRangeCompare->compareRegionStarts(rStartPara, aIt->m_rStartParagraph) == 0)
                                bApply = true;
                            if (bApply)
                            {
                                bool bEndOfApply = (xTextRangeCompare->compareRegionEnds(rEndPara, aIt->m_rEndParagraph) == 0);
                                ApplyParagraphPropertiesFromTableStyle(*aIt, aAllTableParaProperties, aCellProperties[nRow][nCell]);
                                // erase processed paragraph from list of pending paragraphs
                                aIt = m_rDMapper_Impl.m_aParagraphsToEndTable.erase(aIt);
                                if (bEndOfApply)
                                    break;
                            }
                            else
                                ++aIt;
                        }
                        catch( const lang::IllegalArgumentException & )
                        {
                            // skip compareRegion with nested tables
                            ++aIt;
                        }
                    }
                }
            }
        }

        // Additional checks: if we can do this.
        if (bFloating && m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements())
        {
@@ -1221,9 +1285,6 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
                        }
                    }
                }

                // OOXML table style may contain paragraph properties, apply these now.
                ApplyParagraphPropertiesFromTableStyle(aTableInfo);
            }
        }
        catch ( const lang::IllegalArgumentException & )
@@ -1301,7 +1362,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTab
    m_aCellProperties.clear();
    m_aRowProperties.clear();
    m_bHadFootOrEndnote = false;
    m_rDMapper_Impl.m_aParagraphsToEndTable.clear();
    if (nestedTableLevel <= 1)
        m_rDMapper_Impl.m_aParagraphsToEndTable.clear();

#ifdef DBG_UTIL
    TagLogger::getInstance().endElement();
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
index b454be9..bb0ea2e 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.hxx
@@ -56,6 +56,15 @@ struct HorizontallyMergedCell
    }
};

/// Information about a paragraph to be finished after a table end.
struct TableParagraph
{
    css::uno::Reference<css::text::XTextRange> m_rStartParagraph;
    css::uno::Reference<css::text::XTextRange> m_rEndParagraph;
    PropertyMapPtr m_pPropertyMap;
    css::uno::Reference<css::beans::XPropertySet> m_rPropertySet;
};

/// Class to handle events generated by TableManager::resolveCurrentTable().
class DomainMapperTableHandler final : public virtual SvRefBase
{
@@ -91,7 +100,7 @@ public:
     */
    void startTable(const TablePropertyMapPtr& pProps);

    void ApplyParagraphPropertiesFromTableStyle(TableInfo & rInfo);
    void ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableProperties, css::beans::PropertyValues rCellProperties);

    /// Handle end of table.
    void endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart);
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 259e1eb..0ee4c6d 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1759,7 +1759,13 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
                // collect these pending paragraph properties to process in endTable()
                if (xParaProps && m_nTableDepth > 0)
                {
                    TableParagraph aPending{pParaContext, xParaProps};
                    uno::Reference<text::XTextCursor> xCur = xTextRange->getText( )->createTextCursor( );
                    xCur->gotoEnd(false);
                    xCur->goLeft(1, false);
                    uno::Reference<text::XTextCursor> xCur2 =  xTextRange->getText()->createTextCursorByRange(xCur);
                    uno::Reference<text::XParagraphCursor> xParaCursor(xCur2, uno::UNO_QUERY_THROW);
                    xParaCursor->gotoStartOfParagraph(false);
                    TableParagraph aPending{xParaCursor, xCur, pParaContext, xParaProps};
                    m_aParagraphsToEndTable.push_back(aPending);
                }

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 0fd51ab..6138bb7 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -430,13 +430,6 @@ struct SymbolData
    { }
};

/// Information about a paragraph to be finished after a table end.
struct TableParagraph
{
    PropertyMapPtr m_pPropertyMap;
    css::uno::Reference<css::beans::XPropertySet> m_rPropertySet;
};

class DomainMapper;
class DomainMapper_Impl final
{