sc ooxml: don't write empty dxf border sides

A dxf holds only incremental formatting that is layered on top of an
object's existing format. So an absent border side is left as-is, while
an empty side element (e.g. <left/>) defaults to style="none" and clears
that border. Writing every side unconditionally made a headerRow that
only defines a bottom border also clear the left/right/top borders it
should inherit from the wholeTable element (based on ooxml standard).
(only visible after re-importing into Excel)

Change-Id: Idb703badb7649f7f91d57324295b39f68ec234c1
Signed-off-by: Balazs Varga <balazs.varga@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5591
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit cc0181aec07f66847b9c5a06cd047d50abc5a70c)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207623
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Balazs Varga
2026-07-05 10:40:10 +02:00
committed by Xisco Fauli
parent 6fc72bf737
commit 007cc77f29
3 changed files with 30 additions and 11 deletions
+14
View File
@@ -224,6 +224,20 @@ CPPUNIT_TEST_FIXTURE(ScExportTest6, testTableStyleInnerBordersExportXLSX)
assertXPath(pStyles, sBorder + "/x:vertical/x:color", "theme", u"8");
assertXPath(pStyles, sBorder + "/x:horizontal", "style", u"thin");
assertXPath(pStyles, sBorder + "/x:horizontal/x:color", "theme", u"8");
sal_Int32 nHeaderRowDxfId
= getXPath(
pStyles,
"/x:styleSheet/x:tableStyles/x:tableStyle/x:tableStyleElement[@type='headerRow']",
"dxfId")
.toInt32();
CPPUNIT_ASSERT(nHeaderRowDxfId >= 0);
OString sHdrBorder
= "/x:styleSheet/x:dxfs/x:dxf[" + OString::number(nHeaderRowDxfId + 1) + "]/x:border";
assertXPath(pStyles, sHdrBorder + "/x:bottom", "style", u"medium");
assertXPath(pStyles, sHdrBorder + "/x:left", 0);
assertXPath(pStyles, sHdrBorder + "/x:right", 0);
assertXPath(pStyles, sHdrBorder + "/x:top", 0);
}
CPPUNIT_TEST_FIXTURE(ScExportTest6, testTableStyleCustomRoundtripXLSX)
+14 -10
View File
@@ -1869,12 +1869,16 @@ static const char* ToLineStyle( sal_uInt8 nLineStyle )
namespace
{
void lcl_WriteBorder(XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor, model::ComplexColor const& rComplexColor)
void lcl_WriteBorder(XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLineStyle, const Color& rColor, model::ComplexColor const& rComplexColor, bool bWriteEmpty = true)
{
sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream();
if( nLineStyle == EXC_LINE_NONE )
{
rStyleSheet->singleElement(nElement);
// In a differential format (dxf) an empty side element (e.g. <left/>) means
// "no border" and overrides the underlying table style, so omit it there and
// let the side be inherited. The cell border list still writes it.
if (bWriteEmpty)
rStyleSheet->singleElement(nElement);
return;
}
else if (rColor == Color(0, 0, 0) && !rComplexColor.isValidThemeType())
@@ -1889,7 +1893,7 @@ void lcl_WriteBorder(XclExpXmlStream& rStrm, sal_Int32 nElement, sal_uInt8 nLine
}
} // end anonymous namespace
void XclExpCellBorder::SaveXml(XclExpXmlStream& rStream) const
void XclExpCellBorder::SaveXml(XclExpXmlStream& rStream, bool bDxf) const
{
sax_fastparser::FSHelperPtr& rStyleSheet = rStream.GetCurrentStream();
@@ -1901,11 +1905,11 @@ void XclExpCellBorder::SaveXml(XclExpXmlStream& rStream) const
// OOXTODO: XML_outline
);
lcl_WriteBorder(rStream, XML_left, mnLeftLine, rPalette.GetColor(mnLeftColor), maComplexColorLeft);
lcl_WriteBorder(rStream, XML_right, mnRightLine, rPalette.GetColor(mnRightColor), maComplexColorRight);
lcl_WriteBorder(rStream, XML_top, mnTopLine, rPalette.GetColor(mnTopColor), maComplexColorTop);
lcl_WriteBorder(rStream, XML_bottom, mnBottomLine, rPalette.GetColor(mnBottomColor), maComplexColorBottom);
lcl_WriteBorder(rStream, XML_diagonal, mnDiagLine, rPalette.GetColor(mnDiagColor), maComplexColorDiagonal);
lcl_WriteBorder(rStream, XML_left, mnLeftLine, rPalette.GetColor(mnLeftColor), maComplexColorLeft, !bDxf);
lcl_WriteBorder(rStream, XML_right, mnRightLine, rPalette.GetColor(mnRightColor), maComplexColorRight, !bDxf);
lcl_WriteBorder(rStream, XML_top, mnTopLine, rPalette.GetColor(mnTopColor), maComplexColorTop, !bDxf);
lcl_WriteBorder(rStream, XML_bottom, mnBottomLine, rPalette.GetColor(mnBottomColor), maComplexColorBottom, !bDxf);
lcl_WriteBorder(rStream, XML_diagonal, mnDiagLine, rPalette.GetColor(mnDiagColor), maComplexColorDiagonal, !bDxf);
// Inner borders (vertical/horizontal). Only emitted when actually set, so
// ordinary cell borders keep their previous output.
@@ -3350,7 +3354,7 @@ void XclExpDxf::SaveXml( XclExpXmlStream& rStrm )
if (mpAlign)
mpAlign->SaveXml(rStrm);
if (mpBorder)
mpBorder->SaveXml(rStrm);
mpBorder->SaveXml(rStrm, /*bDxf*/true);
if (mpProt)
mpProt->SaveXml(rStrm);
if (mpCellArea)
@@ -3372,7 +3376,7 @@ void XclExpDxf::SaveXmlExt( XclExpXmlStream& rStrm )
if (mpAlign)
mpAlign->SaveXml(rStrm);
if (mpBorder)
mpBorder->SaveXml(rStrm);
mpBorder->SaveXml(rStrm, /*bDxf*/true);
if (mpProt)
mpProt->SaveXml(rStrm);
rStyleSheet->endElementNS( XML_x14, XML_dxf );
+2 -1
View File
@@ -382,7 +382,8 @@ struct XclExpCellBorder : public XclCellBorder
/** Fills the data to the passed fields of a BIFF8 CF (conditional format) record. */
void FillToCF8( sal_uInt16& rnLine, sal_uInt32& rnColor ) const;
void SaveXml( XclExpXmlStream& rStrm ) const;
/// bDxf: omit unset border sides (dxf) instead of writing them as empty elements.
void SaveXml( XclExpXmlStream& rStrm, bool bDxf = false ) const;
};
/** Extends the XclCellArea struct for export.