summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortundet <tundeth@gmail.com>2019-04-12 10:21:42 +0200
committerLászló Németh <nemeth@numbertext.org>2019-04-17 10:17:47 +0200
commitdc091e7fd952b0530db8583247c2f910d627700a (patch)
treeb9f9e791329be94147fb932806a98ec897fa57b6
parent185e01c015528cafbddcda5dfdabf816ce8be20e (diff)
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 <nemeth@numbertext.org>
-rw-r--r--include/oox/export/chartexport.hxx3
-rw-r--r--include/oox/export/drawingml.hxx10
-rw-r--r--include/oox/export/shapes.hxx10
-rw-r--r--oox/source/export/chartexport.cxx26
-rw-r--r--oox/source/export/drawingml.cxx14
-rw-r--r--oox/source/export/shapes.cxx24
-rw-r--r--sc/qa/unit/data/xlsx/chart_hyperlink.xlsxbin0 -> 21564 bytes
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx24
-rw-r--r--sc/source/filter/excel/xeescher.cxx7
-rw-r--r--sc/source/filter/inc/xcl97rec.hxx14
-rw-r--r--sc/source/filter/inc/xeescher.hxx4
-rw-r--r--sc/source/filter/xcl97/xcl97esc.cxx2
-rw-r--r--sc/source/filter/xcl97/xcl97rec.cxx35
13 files changed, 118 insertions, 55 deletions
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
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/chart_hyperlink.xlsx
Binary files 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 )