include/oox/export/chartexport.hxx | 3 ++ include/oox/export/drawingml.hxx | 10 ++++++++ include/oox/export/shapes.hxx | 10 -------- oox/source/export/chartexport.cxx | 26 +++++++++++++++++++++- oox/source/export/drawingml.cxx | 14 ++++++++++++ oox/source/export/shapes.cxx | 24 ++++---------------- sc/qa/unit/data/xlsx/chart_hyperlink.xlsx |binary sc/qa/unit/subsequent_export-test.cxx | 24 ++++++++++++++++++++ sc/source/filter/excel/xeescher.cxx | 7 ++++-- sc/source/filter/inc/xcl97rec.hxx | 14 ++++++++++++ sc/source/filter/inc/xeescher.hxx | 4 ++- sc/source/filter/xcl97/xcl97esc.cxx | 2 - sc/source/filter/xcl97/xcl97rec.cxx | 35 ++++++++++++------------------ 13 files changed, 118 insertions(+), 55 deletions(-)
New commits: commit dc091e7fd952b0530db8583247c2f910d627700a Author: tundet <tund...@gmail.com> AuthorDate: Fri Apr 12 10:21:42 2019 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Wed Apr 17 10:17:47 2019 +0200 tdf#123645 XLSX export: fix hyperlink inserted to chart Hyperlink inserted to chart lost after export. chart_hyperlink.xlsx: Test file from Excel 2016. Change-Id: Ideca10e544193ba43d7c2ef6e9dd8e393383edc1 Reviewed-on: https://gerrit.libreoffice.org/70648 Tested-by: Jenkins Reviewed-by: László Németh <nem...@numbertext.org> diff --git a/include/oox/export/chartexport.hxx b/include/oox/export/chartexport.hxx index c5f9e6ebd188..b39b3f52b455 100644 --- a/include/oox/export/chartexport.hxx +++ b/include/oox/export/chartexport.hxx @@ -101,6 +101,7 @@ private: css::uno::Reference< css::frame::XModel > mxChartModel; css::uno::Reference< css::chart::XDiagram > mxDiagram; css::uno::Reference< css::chart2::XDiagram > mxNewDiagram; + std::shared_ptr<URLTransformer> mpURLTransformer; // members filled by InitRangeSegmentationProperties (retrieved from DataProvider) bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false @@ -214,6 +215,8 @@ public: ::oox::core::XmlFilterBase* pFB, DocumentType eDocumentType ); virtual ~ChartExport() {} + void SetURLTranslator(const std::shared_ptr<URLTransformer>& pTransformer); + const css::uno::Reference< css::frame::XModel >& getModel(){ return mxChartModel; } void WriteChartObj( const css::uno::Reference< css::drawing::XShape >& xShape, sal_Int32 nID, sal_Int32 nChartCount ); diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index b3cdbb3600ba..8ed1aaf0d702 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -96,6 +96,16 @@ namespace core { namespace drawingml { +class OOX_DLLPUBLIC URLTransformer +{ +public: + virtual ~URLTransformer(); + + virtual OUString getTransformedString(const OUString& rURL) const; + + virtual bool isExternalURL(const OUString& rURL) const; +}; + // Our rotation is counter-clockwise and is in 100ths of a degree. // drawingML rotation is clockwise and is in 60000ths of a degree. template <typename T> T ExportRotateClockwisify(T input) diff --git a/include/oox/export/shapes.hxx b/include/oox/export/shapes.hxx index aa0ca2cd1a62..b7755ccee9d2 100644 --- a/include/oox/export/shapes.hxx +++ b/include/oox/export/shapes.hxx @@ -78,16 +78,6 @@ OOX_DLLPUBLIC css::uno::Reference<css::io::XInputStream> GetOLEObjectStream( namespace oox { namespace drawingml { -class OOX_DLLPUBLIC URLTransformer -{ -public: - virtual ~URLTransformer(); - - virtual OUString getTransformedString(const OUString& rURL) const; - - virtual bool isExternalURL(const OUString& rURL) const; -}; - class OOX_DLLPUBLIC ShapeExport : public DrawingML { private: diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index 15e9bca1c1c9..672ae2579d99 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -376,6 +376,7 @@ ChartExport::ChartExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, Reference< f , mnXmlNamespace( nXmlNamespace ) , mnSeriesCount(0) , mxChartModel( xModel ) + , mpURLTransformer(new URLTransformer) , mbHasCategoryLabels( false ) , mbHasZAxis( false ) , mbIs3DChart( false ) @@ -384,6 +385,11 @@ ChartExport::ChartExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, Reference< f { } +void ChartExport::SetURLTranslator(const std::shared_ptr<URLTransformer>& pTransformer) +{ + mpURLTransformer = pTransformer; +} + sal_Int32 ChartExport::getChartType( ) { OUString sChartType = mxDiagram->getDiagramType(); @@ -445,6 +451,8 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI { FSHelperPtr pFS = GetFS(); + Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY ); + pFS->startElementNS( mnXmlNamespace, XML_graphicFrame, FSEND ); pFS->startElementNS( mnXmlNamespace, XML_nvGraphicFramePr, FSEND ); @@ -455,11 +463,27 @@ void ChartExport::WriteChartObj( const Reference< XShape >& xShape, sal_Int32 nI if (xNamed.is()) sName = xNamed->getName(); - pFS->singleElementNS( mnXmlNamespace, XML_cNvPr, + pFS->startElementNS( mnXmlNamespace, XML_cNvPr, XML_id, I32S( nID ), XML_name, sName.toUtf8(), FSEND ); + OUString sURL; + if ( GetProperty( xShapeProps, "URL" ) ) + mAny >>= sURL; + if( !sURL.isEmpty() ) + { + OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(), + oox::getRelationship(Relationship::HYPERLINK), + mpURLTransformer->getTransformedString(sURL), + mpURLTransformer->isExternalURL(sURL)); + + mpFS->singleElementNS( XML_a, XML_hlinkClick, + FSNS( XML_r,XML_id ), sRelId.toUtf8(), + FSEND ); + } + pFS->endElementNS(mnXmlNamespace, XML_cNvPr); + pFS->singleElementNS( mnXmlNamespace, XML_cNvGraphicFramePr, FSEND ); diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index a5e8f48f6dff..15eeda16f4c6 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -133,6 +133,20 @@ using ::sax_fastparser::FastSerializerHelper; namespace oox { namespace drawingml { +URLTransformer::~URLTransformer() +{ +} + +OUString URLTransformer::getTransformedString(const OUString& rString) const +{ + return rString; +} + +bool URLTransformer::isExternalURL(const OUString& /*rURL*/) const +{ + return true; +} + static css::uno::Any getLineDash( const css::uno::Reference<css::frame::XModel>& xModel, const OUString& rDashName ) { css::uno::Reference<css::lang::XMultiServiceFactory> xFact(xModel, css::uno::UNO_QUERY); diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index ecc14705a75b..b89f1d966868 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -338,20 +338,6 @@ uno::Reference<io::XInputStream> GetOLEObjectStream( namespace oox { namespace drawingml { -URLTransformer::~URLTransformer() -{ -} - -OUString URLTransformer::getTransformedString(const OUString& rString) const -{ - return rString; -} - -bool URLTransformer::isExternalURL(const OUString& /*rURL*/) const -{ - return true; -} - #define GETA(propName) \ GetProperty( rXPropSet, #propName) @@ -1160,13 +1146,13 @@ void ShapeExport::WriteGraphicObjectShapePart( const Reference< XShape >& xShape if( !sURL.isEmpty() ) { OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(), - oox::getRelationship(Relationship::HYPERLINK), - mpURLTransformer->getTransformedString(sURL), - mpURLTransformer->isExternalURL(sURL)); + oox::getRelationship(Relationship::HYPERLINK), + mpURLTransformer->getTransformedString(sURL), + mpURLTransformer->isExternalURL(sURL)); mpFS->singleElementNS( XML_a, XML_hlinkClick, - FSNS( XML_r,XML_id ), sRelId.toUtf8(), - FSEND ); + FSNS( XML_r,XML_id ), sRelId.toUtf8(), + FSEND ); } pFS->endElementNS(mnXmlNamespace, XML_cNvPr); diff --git a/sc/qa/unit/data/xlsx/chart_hyperlink.xlsx b/sc/qa/unit/data/xlsx/chart_hyperlink.xlsx new file mode 100644 index 000000000000..95d48266f0fb Binary files /dev/null and b/sc/qa/unit/data/xlsx/chart_hyperlink.xlsx differ diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index 17158933ec34..57c4469355f7 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -214,6 +214,7 @@ public: void testTdf115192XLSX(); void testTdf91634XLSX(); void testTdf115159(); + void testTdf123645XLSX(); void testXltxExport(); @@ -335,6 +336,7 @@ public: CPPUNIT_TEST(testTdf115192XLSX); CPPUNIT_TEST(testTdf91634XLSX); CPPUNIT_TEST(testTdf115159); + CPPUNIT_TEST(testTdf123645XLSX); CPPUNIT_TEST(testXltxExport); @@ -4225,6 +4227,28 @@ void ScExportTest::testTdf115159() xDocSh->DoClose(); } +void ScExportTest::testTdf123645XLSX() +{ + ScDocShellRef xDocSh = loadDoc("chart_hyperlink.", FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xDocSh), FORMAT_XLSX); + + xmlDocPtr pDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/drawing1.xml"); + CPPUNIT_ASSERT(pDoc); + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[1]/xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/a:hlinkClick", 1); + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[2]/xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/a:hlinkClick", 1); + assertXPath(pDoc, "/xdr:wsDr/xdr:twoCellAnchor[3]/xdr:graphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr/a:hlinkClick", 1); + + xmlDocPtr pXmlRels = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/drawings/_rels/drawing1.xml.rels"); + CPPUNIT_ASSERT(pXmlRels); + assertXPath(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId1']", "TargetMode", "External"); + assertXPathNoAttribute(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId3']", "TargetMode"); + assertXPath(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId5']", "TargetMode", "External"); + assertXPath(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId1']", "Target", "file:///C:/TEMP/test.xlsx"); + assertXPath(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId3']", "Target", "#Sheet2!A1"); + assertXPath(pXmlRels, "/r:Relationships/r:Relationship[@Id='rId5']", "Target", "https://bugs.documentfoundation.org/show_bug.cgi?id=123645"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 1780e00efc9e..f1d41f7a7f7e 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -1059,9 +1059,10 @@ void XclExpTbxControlObj::WriteSbs( XclExpStream& rStrm ) //#endif -XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > const & xShape, const tools::Rectangle* pChildAnchor ) : +XclExpChartObj::XclExpChartObj( XclExpObjectManager& rObjMgr, Reference< XShape > const & xShape, const tools::Rectangle* pChildAnchor, ScDocument* pDoc ) : XclObj( rObjMgr, EXC_OBJTYPE_CHART ), - XclExpRoot( rObjMgr.GetRoot() ), mxShape( xShape ) + XclExpRoot( rObjMgr.GetRoot() ), mxShape( xShape ), + mpDoc(pDoc) { // create the MSODRAWING record contents for the chart object mrEscherEx.OpenContainer( ESCHER_SpContainer ); @@ -1128,6 +1129,8 @@ void XclExpChartObj::SaveXml( XclExpXmlStream& rStrm ) XclObjAny::WriteFromTo( rStrm, mxShape, GetTab() ); Reference< XModel > xModel( mxChartDoc, UNO_QUERY ); ChartExport aChartExport(XML_xdr, pDrawing, xModel, &rStrm, drawingml::DOCUMENT_XLSX); + std::shared_ptr<oox::drawingml::URLTransformer> pURLTransformer(new ScURLTransformer(*mpDoc)); + aChartExport.SetURLTranslator(pURLTransformer); static sal_Int32 nChartCount = 0; nChartCount++; sal_Int32 nID = rStrm.GetUniqueId(); diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx index 1c8fa1903e33..0999f0ea3dd2 100644 --- a/sc/source/filter/inc/xcl97rec.hxx +++ b/sc/source/filter/inc/xcl97rec.hxx @@ -26,6 +26,7 @@ #include "xestring.hxx" #include <tabprotection.hxx> #include <svx/svdobj.hxx> +#include <oox/export/drawingml.hxx> class XclObj; class XclExpMsoDrawing; @@ -34,6 +35,19 @@ class SdrTextObj; class XclTxo; class XclEscherEx; +class ScURLTransformer : public oox::drawingml::URLTransformer +{ +public: + explicit ScURLTransformer(ScDocument& rDoc); + + virtual OUString getTransformedString(const OUString& rURL) const override; + + virtual bool isExternalURL(const OUString& rURL) const override; + +private: + ScDocument& mrDoc; +}; + class XclExpObjList : public ExcEmptyRec, protected XclExpRoot { public: diff --git a/sc/source/filter/inc/xeescher.hxx b/sc/source/filter/inc/xeescher.hxx index f45ebbf79bcf..05491a3b2127 100644 --- a/sc/source/filter/inc/xeescher.hxx +++ b/sc/source/filter/inc/xeescher.hxx @@ -294,7 +294,8 @@ public: explicit XclExpChartObj( XclExpObjectManager& rObjMgr, css::uno::Reference< css::drawing::XShape > const & xShape, - const tools::Rectangle* pChildAnchor ); + const tools::Rectangle* pChildAnchor, + ScDocument* pDoc ); virtual ~XclExpChartObj() override; /** Writes the OBJ record and the entire chart substream. */ @@ -308,6 +309,7 @@ private: XclExpChartRef mxChart; /// The chart itself (BOF/EOF substream data). css::uno::Reference< css::drawing::XShape > mxShape; css::uno::Reference< css::chart::XChartDocument > mxChartDoc; + ScDocument* mpDoc; }; /** Represents a NOTE record containing the relevant data of a cell note. diff --git a/sc/source/filter/xcl97/xcl97esc.cxx b/sc/source/filter/xcl97/xcl97esc.cxx index f987d336e1b4..9ca76ae49c58 100644 --- a/sc/source/filter/xcl97/xcl97esc.cxx +++ b/sc/source/filter/xcl97/xcl97esc.cxx @@ -215,7 +215,7 @@ EscherExHostAppData* XclEscherEx::StartShape( const Reference< XShape >& rxShape SvGlobalName aObjClsId( xObj->getClassID() ); if ( SotExchange::IsChart( aObjClsId ) ) { // yes, it's a chart diagram - mrObjMgr.AddObj( std::make_unique<XclExpChartObj>( mrObjMgr, rxShape, pChildAnchor ) ); + mrObjMgr.AddObj( std::make_unique<XclExpChartObj>( mrObjMgr, rxShape, pChildAnchor, &GetDocRef() ) ); pCurrXclObj = nullptr; // no metafile or whatsoever } else // metafile and OLE object diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx index 38fd9c27103e..4c55ed88ec03 100644 --- a/sc/source/filter/xcl97/xcl97rec.cxx +++ b/sc/source/filter/xcl97/xcl97rec.cxx @@ -1129,30 +1129,23 @@ void transformURL(const OUString& rOldURL, OUString& rNewURL, const ScDocument* rNewURL = rOldURL; } -class ScURLTransformer : public oox::drawingml::URLTransformer -{ -public: - explicit ScURLTransformer(ScDocument& rDoc) - : mrDoc(rDoc) - { - } - - virtual OUString getTransformedString(const OUString& rURL) const override - { - OUString aNewURL; - transformURL(rURL, aNewURL, &mrDoc); - return aNewURL; - } +} - virtual bool isExternalURL(const OUString& rURL) const override - { - return !rURL.startsWith("#"); - } +ScURLTransformer::ScURLTransformer(ScDocument& rDoc) + : mrDoc(rDoc) +{ +} -private: - ScDocument& mrDoc; -}; +OUString ScURLTransformer::getTransformedString(const OUString& rURL) const +{ + OUString aNewURL; + transformURL(rURL, aNewURL, &mrDoc); + return aNewURL; +} +bool ScURLTransformer::isExternalURL(const OUString& rURL) const +{ + return !rURL.startsWith("#"); } void XclObjAny::SaveXml( XclExpXmlStream& rStrm ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits