Can't export IncludeHtml to NativeExcel, wraps HTML in SPAN tag
I have a sample report below. I need to be able to export an SVG to PDF and NativeExcel. I am able to use the IncludeHtml element for the SVG and export to PDF without any issues. However, when I export to NativeExcel, I get no image (and corruption in the View Export HTML in the debugger).
I found that the IncludeHtml element wraps the contents in a SPAN tag which breaks the NativeExcel for some reason. To resolve this, I am grabbing my IncludeHtml's innerHTML and base64 encoding it to try to pass an HTML IMG tag to NativeExcel instead of the IncludeHtml. Here is the Action.PreActionJavascript I'm using (svgElement is my IncludeHtml and hdnXml is the Input.Hidden element I'm placing in my IMG tag's src attribute):
var svg = document.getElementById('svgElement').innerHTML; //get SVG from IncludeHtml element
console.log(svg); //check innerHTML for valid SVG as XML
var xmlval = btoa(svg); //base64 encode innerHTML for IncludeHtml element
document.getElementById('hdnXml').value = "data:image/svg+xml;base64,"+xmlval; //assign img string to hidden input
This isn't working for some reason... the js is sound and the console.log shows me the correct var values. Any ideas on how to make this work?
Here is my full reproducer with some other code that didn't work remarked:
<?xml version="1.0" encoding="utf-8"?>
<Report
ID="TestGetSvgExcel"
>
<Body>
<Division
HtmlDiv="True"
ID="divExport"
ShowModes="rdBrowser"
>
<Label
Caption="To Excel"
>
<Action
ID="expExcel"
Type="NativeExcel"
>
<Target
ExcelOutputFormat="Excel2007"
FrameID="NewWindow"
ID="tgtExcel"
ShowGridlines="True"
Type="NativeExcel"
/>
<Action
Javascript="//var svg = document.getElementById('svgElement');
//var xmlval = new XMLSerializer().serializeToString(svg);
//document.getElementById('hdnXml').value = "data:image/svg+xml;base64,"+xmlval;
//this picks up the span tags, need to strip that off of svgElement or use innerHTML
var svg = document.getElementById('svgElement').innerHTML; //get SVG from IncludeHtml element
console.log(svg); //check innerHTML for valid SVG as XML
var xmlval = btoa(svg); //base64 encode innerHTML for IncludeHtml element
document.getElementById('hdnXml').value = "data:image/svg+xml;base64,"+xmlval; //assign img string to hidden input
return true;"
Type="PreActionJavascript"
/>
</Action>
</Label>
</Division>
<Division
HtmlDiv="True"
ID="divBrowser"
ShowModes="rdBrowser"
>
<IncludeHtml
Html="<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" class="highcharts-root" style="font-family:arial, helvetica, sans-serif;font-size:12px;" xmlns="http://www.w3.org/2000/svg" width="800" height="540" viewBox="0 0 800 540"><desc>Created with Highcharts 9.0.1</desc><defs><clipPath id="highcharts-sv8taes-16-"><rect x="0" y="0" width="651" height="492" fill="none"></rect></clipPath></defs><rect fill="#FFFFFF" class="highcharts-background" stroke="rgba(255,255,255,0)" stroke-width="1" x="0.5" y="0.5" width="798" height="538" rx="0" ry="0"></rect><rect fill="#FFFFFF" class="highcharts-plot-background" x="48" y="10" width="651" height="492"></rect><g class="highcharts-pane-group" data-z-index="0"></g><g class="highcharts-grid highcharts-xaxis-grid" data-z-index="1"><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 264.5 10 L 264.5 502" opacity="1"></path><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 481.5 10 L 481.5 502" opacity="1"></path><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 698.5 10 L 698.5 502" opacity="1"></path><path fill="none" data-z-index="1" class="highcharts-grid-line" d="M 47.5 10 L 47.5 502" opacity="1"></path></g><g class="highcharts-grid highcharts-yaxis-grid" data-z-index="1"><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 502.5 L 699 502.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 432.5 L 699 432.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 361.5 L 699 361.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 291.5 L 699 291.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 221.5 L 699 221.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 151.5 L 699 151.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 80.5 L 699 80.5" opacity="1"></path><path fill="none" stroke="#C0C0C0" stroke-width="1" data-z-index="1" class="highcharts-grid-line" d="M 48 9.5 L 699 9.5" opacity="1"></path></g><rect fill="none" class="highcharts-plot-border" data-z-index="1" x="48" y="10" width="651" height="492"></rect><g class="highcharts-axis highcharts-xaxis" data-z-index="2"><path fill="none" class="highcharts-tick" stroke="#ccd6eb" stroke-width="1" d="M 264.5 502 L 264.5 512" opacity="1"></path><path fill="none" class="highcharts-tick" stroke="#ccd6eb" stroke-width="1" d="M 481.5 502 L 481.5 512" opacity="1"></path><path fill="none" class="highcharts-tick" stroke="#ccd6eb" stroke-width="1" d="M 699.5 502 L 699.5 512" opacity="1"></path><path fill="none" class="highcharts-tick" stroke="#ccd6eb" stroke-width="1" d="M 47.5 502 L 47.5 512" opacity="1"></path><path fill="none" class="highcharts-axis-line" stroke="#ccd6eb" stroke-width="1" data-z-index="7" d="M 48 502.5 L 699 502.5"></path></g><g class="highcharts-axis highcharts-yaxis" data-z-index="2"><path fill="none" class="highcharts-axis-line" data-z-index="7" d="M 48 10 L 48 502"></path></g><g class="highcharts-series-group" data-z-index="3"><g class="highcharts-series highcharts-series-0 highcharts-line-series" data-z-index="0.1" opacity="1" transform="translate(48,10) scale(1 1)" clip-path="url(#highcharts-sv8taes-16-)"><path fill="none" d="M 108.5 351.42857142857144 L 325.5 210.8571428571429 L 542.5 70.28571428571428" class="highcharts-graph" data-z-index="1" stroke="rgba(36,159,218,0.8)" stroke-width="2" stroke-linejoin="round" stroke-linecap="round"></path></g><g class="highcharts-markers highcharts-series-0 highcharts-line-series" data-z-index="0.1" opacity="1" transform="translate(48,10) scale(1 1)" clip-path="none"></g><g class="highcharts-series highcharts-series-1 highcharts-column-series" data-z-index="0.1" opacity="1" transform="translate(48,10) scale(1 1)" clip-path="url(#highcharts-sv8taes-16-)"><rect x="56" y="492" width="105" height="1" fill="rgba(138,192,66,0.8)" opacity="1" class="highcharts-point"></rect><rect x="273" y="490" width="105" height="3" fill="rgba(138,192,66,0.8)" opacity="1" class="highcharts-point"></rect><rect x="490" y="489" width="105" height="4" fill="rgba(138,192,66,0.8)" opacity="1" class="highcharts-point"></rect></g><g class="highcharts-markers highcharts-series-1 highcharts-column-series" data-z-index="0.1" opacity="1" transform="translate(48,10) scale(1 1)" clip-path="none"></g></g><text x="400" text-anchor="middle" class="highcharts-title" data-z-index="4" style="color:#274b6d;font-size:16px;fill:#274b6d;" y="23"></text><text x="400" text-anchor="middle" class="highcharts-subtitle" data-z-index="4" style="color:#4d759e;fill:#4d759e;" y="25"></text><text x="10" text-anchor="start" class="highcharts-caption" data-z-index="4" style="color:#666666;fill:#666666;" y="538"></text><g class="highcharts-legend" data-z-index="7" transform="translate(711,10)"><rect fill="none" class="highcharts-legend-box" rx="0" ry="0" x="0" y="0" width="78" height="45" visibility="visible"></rect><g data-z-index="1"><g><g class="highcharts-legend-item highcharts-line-series highcharts-color-undefined highcharts-series-0" data-z-index="1" transform="translate(8,3)"><path fill="none" d="M 0 13 L 16 13" class="highcharts-graph" stroke="rgba(36,159,218,0.8)" stroke-width="2"></path><text x="21" style="color:#000000;cursor:pointer;font-size:14px;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="start" data-z-index="2" y="17">Count</text></g><g class="highcharts-legend-item highcharts-column-series highcharts-color-undefined highcharts-series-1" data-z-index="1" transform="translate(8,20)"><text x="21" y="17" style="color:#000000;cursor:pointer;font-size:14px;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="start" data-z-index="2">id</text><rect x="0" y="6" width="16" height="12" fill="rgba(138,192,66,0.8)" class="highcharts-point" data-z-index="3"></rect></g></g></g></g><g class="highcharts-axis-labels highcharts-xaxis-labels" data-z-index="7"><text x="156.5" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="middle" transform="translate(0,0)" y="523" opacity="1">Johnny</text><text x="373.5" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="middle" transform="translate(0,0)" y="523" opacity="1">Sallie</text><text x="590.5" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="middle" transform="translate(0,0)" y="523" opacity="1">Emily</text></g><g class="highcharts-axis-labels highcharts-yaxis-labels" data-z-index="7"><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="508" opacity="1">0</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="437" opacity="1">50</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="367" opacity="1">100</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="297" opacity="1">150</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="226" opacity="1">200</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="156" opacity="1">250</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="86" opacity="1">300</text><text x="33" style="color:#000000;cursor:default;font-size:12px;white-space:nowrap;font-weight:normal;font-family:verdana;fill:#000000;" text-anchor="end" transform="translate(0,0)" y="16" opacity="1">350</text></g></svg>"
ID="svgElement"
/>
</Division>
<Division
HtmlDiv="True"
ID="divImage"
ShowModes="rdExport"
>
<Remark>
<Image
Caption="@Request.hdnXml~"
ID="img"
/>
</Remark>
<HtmlTag
HtmlTagName="img"
>
<HtmlAttributeParams
src="@Request.hdnXml~"
/>
</HtmlTag>
</Division>
<InputHidden
ID="hdnXml"
/>
</Body>
<ideTestParams
hdnXml=""
/>
</Report>
-
After reviewing with Logi Engineering, we found that Logi's NativeExcel exporter/renderer doesn't accept SVG code. I solved this requirement by using the following process:
- Generate the Chart in Info
- Use HighCharts' getSVG API to get the SVG for the chart
- --stop here and pass the SVG as Hidden Input if you want PDF export--
- Write the SVG to a hidden (in CSS) IMG element
- When the img loads, copy its contents to an HTML CANVAS element
- Use the Canvas element's toDataURL API
- Store the resulting DataURL (minus the prefix) in a Hidden Input
- Pass that Hidden Input as a Request Token (POST) to a new report definition
- In the new definition, use a DataLayer.Static to grab the Token value
- Add a FileColumn element to write the Token to the file server as a PNG
- Present the PNG on the page as the Caption in an Image Element
- Export this page/report to Excel
This feels convoluted but it works, and it is typically much faster than using the Action.NativeExcel which re-runs the entire report to generate the Excel. I'll create a separate forum post with a full reproducer so the option isn't hidden under this specific topic.
0
Please sign in to leave a comment.
Comments
1 comment