- Home
- Forum
- ASP.NET Core
- Export Chart to png and excel
Export Chart to png and excel
Hi,
I have created a 3D pie chart inside a ejDialog control. I am trying to add functionality so that the user can do a server side export it to png or excel. I cannot find documentation on how to do this specifically for ASP.Net Core EJ1. (All the other types have lots of documentation....)
I tried following this older forum post (to save as png), https://www.syncfusion.com/forums/128915/how-to-render-chart-image-run-time-and-save-it-to-a-file. However I get an "FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters." error on Convert.FromBase64String().
Here is some code from my view:
// the dialog that contains the pie chart
List<string> stageAvgButtons = new List<string>() { "close", "print", "save", "excel" };
<ej-dialog id="StageAveragesDialog" show-on-init="false" title="Stage Averages" width="1000" is-responsive="true" action-buttons="@stageAvgButtons" action-button-click="stageAvgButtonsClick">
<e-dialog-position x-value="441px" y-value="153.6px" />
<e-content-template>
<div id="chartStageAvg"></div>
</e-content-template>
</ej-dialog>
<ej-dialog id="StageAveragesDialog" show-on-init="false" title="Stage Averages" width="1000" is-responsive="true" action-buttons="@stageAvgButtons" action-button-click="stageAvgButtonsClick">
<e-dialog-position x-value="441px" y-value="153.6px" />
<e-content-template>
<div id="chartStageAvg"></div>
</e-content-template>
</ej-dialog>
// opens the dialog and creates the chart
function openStageAverages() {
var popupobj = $("#customWaiting").data("ejWaitingPopup");
popupobj.show();
var avgDialog = $("#StageAveragesDialog").ejDialog("instance");
//avgDialog.width = 1000;
avgDialog.open();
$.ajax({
url: "/Telecom/StageAverageDataSource",
type: "GET",
data: { "projId": @ProjId },
success: function (dataPoints) {
if (dataPoints.length > 0) {
$("#chartStageAvg").ejChart({
commonSeriesOptions:
{
labelPosition: 'outside',
tooltip: { visible: true, format: "#point.x# : #point.y# Days" },
marker:
{
dataLabel:
{
shape: 'none',
visible: true,
textPosition: 'top',
border: { width: 1 },
connectorLine: { height: 70, stroke: "black" }
}
}
},
series: [{
points: dataPoints,
explodeIndex: 0,
border: { width: 2, color: 'white' },
type: 'pie',
labelPosition: 'outside',
startAngle: 145
}],
//Enabling 3D Chart
enable3D: true,
enableRotation: true,
depth: 30,
tilt: -30,
rotation: -30,
perspectiveAngle: 90,
isResponsive: true,
load: "onchartload",
title: { text: "" },
size: { height: "600", width: "970" },
legend: { visible: false }
});
} else {
$("#chartStageAvg").html("There is not enough data to create the pie chart.");
}
var popupobj = $("#customWaiting").data("ejWaitingPopup");
popupobj.hide();
}
});
}
var popupobj = $("#customWaiting").data("ejWaitingPopup");
popupobj.show();
var avgDialog = $("#StageAveragesDialog").ejDialog("instance");
//avgDialog.width = 1000;
avgDialog.open();
$.ajax({
url: "/Telecom/StageAverageDataSource",
type: "GET",
data: { "projId": @ProjId },
success: function (dataPoints) {
if (dataPoints.length > 0) {
$("#chartStageAvg").ejChart({
commonSeriesOptions:
{
labelPosition: 'outside',
tooltip: { visible: true, format: "#point.x# : #point.y# Days" },
marker:
{
dataLabel:
{
shape: 'none',
visible: true,
textPosition: 'top',
border: { width: 1 },
connectorLine: { height: 70, stroke: "black" }
}
}
},
series: [{
points: dataPoints,
explodeIndex: 0,
border: { width: 2, color: 'white' },
type: 'pie',
labelPosition: 'outside',
startAngle: 145
}],
//Enabling 3D Chart
enable3D: true,
enableRotation: true,
depth: 30,
tilt: -30,
rotation: -30,
perspectiveAngle: 90,
isResponsive: true,
load: "onchartload",
title: { text: "" },
size: { height: "600", width: "970" },
legend: { visible: false }
});
} else {
$("#chartStageAvg").html("There is not enough data to create the pie chart.");
}
var popupobj = $("#customWaiting").data("ejWaitingPopup");
popupobj.hide();
}
});
}
function stageAvgButtonsClick(args) {
switch (args.currentTarget.toUpperCase()) {
case "PRINT":
try {
var chartObj = $("#chartStageAvg").ejChart("instance");
chartObj.print("chartStageAvg");
} catch {
alert("There is not enough data to create the pie chart.");
}
break;
case "SAVE":
try {
var chartObj = $("#chartStageAvg").ejChart("instance");
exporting = chartObj.model.exportSettings;
exporting.mode = "server";
exporting.type = "png";
exporting.action = "/Telecom/ExportStageAverages";
chartObj.export();
} catch {
alert("There is not enough data to create the pie chart.");
}
break;
switch (args.currentTarget.toUpperCase()) {
case "PRINT":
try {
var chartObj = $("#chartStageAvg").ejChart("instance");
chartObj.print("chartStageAvg");
} catch {
alert("There is not enough data to create the pie chart.");
}
break;
case "SAVE":
try {
var chartObj = $("#chartStageAvg").ejChart("instance");
exporting = chartObj.model.exportSettings;
exporting.mode = "server";
exporting.type = "png";
exporting.action = "/Telecom/ExportStageAverages";
chartObj.export();
} catch {
alert("There is not enough data to create the pie chart.");
}
break;
case "EXCEL":
// will add code here for excel
default:
alert("Action " + args.currentTarget + " not defined.");
break;
}
}
alert("Action " + args.currentTarget + " not defined.");
break;
}
}
From the controller:
public void ExportStageAverages(string Data, string ChartModel)
{
ChartProperties propObj = ConvertChartObject(ChartModel);
string type = propObj.ExportSettings.Type.ToString().ToLower();
if (type == "png")
{
//Data = Data.Remove(0, Data.IndexOf(',') + 1);
//MemoryStream stream = new MemoryStream(Convert.FromBase64String(Data));
string fullPath = _hostingEnvironment.WebRootPath + @"\XlsIO\Telecom\Download\";
using (FileStream fs = new FileStream(fullPath + "Averages.png", FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(Data);
//byte[] data = Convert.
bw.Write(data);
bw.Dispose();
}
}
} else
{
// code for export to excel will go here
}
}
private ChartProperties ConvertChartObject(string ChartModel)
{
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
};
ChartProperties chartProp = new ChartProperties();
chartProp = JsonConvert.DeserializeObject<ChartProperties>(ChartModel, settings);
return chartProp;
}
{
ChartProperties propObj = ConvertChartObject(ChartModel);
string type = propObj.ExportSettings.Type.ToString().ToLower();
if (type == "png")
{
//Data = Data.Remove(0, Data.IndexOf(',') + 1);
//MemoryStream stream = new MemoryStream(Convert.FromBase64String(Data));
string fullPath = _hostingEnvironment.WebRootPath + @"\XlsIO\Telecom\Download\";
using (FileStream fs = new FileStream(fullPath + "Averages.png", FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(Data);
//byte[] data = Convert.
bw.Write(data);
bw.Dispose();
}
}
} else
{
// code for export to excel will go here
}
}
private ChartProperties ConvertChartObject(string ChartModel)
{
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
};
ChartProperties chartProp = new ChartProperties();
chartProp = JsonConvert.DeserializeObject<ChartProperties>(ChartModel, settings);
return chartProp;
}
Thanks,
Chris
SIGN IN To post a reply.
6 Replies
CH
Chris
November 5, 2018 11:15 PM UTC
I have a couple other questions that wouldn't fit in the original post.
1) How can I change the icon for "print" in the ejdialog?
2) For exporting the chart to excel is it possible to pass an extra parameter to the controller method? I need to know the "projectId" so it can get the right data.
Thanks,
Chris
DD
Dharanidharan Dharmasivam
Syncfusion Team
November 7, 2018 11:50 AM UTC
Hi Chris,
Greetings from Syncfusion.
Chart Component:
We have analyzed our query. We would like to let you know that, as of now we have provided support or 3D chart in SVG mode only, so 3D chart can’t be exported as image. And for 3D chart export to Excel in server side, we have logged feature request for this requirement. While the feature itself important, we are afraid we can’t provide you an accurate timeline on when this feature will be available in our site. So, based on the priority the feature will be available in any of our upcoming release.
Dialog Component:
By default, svg icons are used for EJ1 dialog action buttons. If you wish to change this svg print icon, you can remove the svg icon and add your customized icons. Please find the below css code for your reference.
|
<style class="cssStyles">
.e-icon.e-print:before{ // Remove default print icon
content: "";
}
.e-icon.e-print{ // Add your customized image
background-image:url("http://cdn.syncfusion.com/16.3.0.29/js/mobile/images/scrollpanel/pullarrow.png");
}
.e-icon.e-print:hover{ // Add your customized image when you hovering element
background-image:url("http://cdn.syncfusion.com/16.3.0.29/js/mobile/images/scrollpanel/pullarrow.png");
}
</style> |
Please find the below JS playground link.
Thanks,
Dharani.
CH
Chris
November 7, 2018 03:39 PM UTC
Hi,
Thanks for the reply. In ASP.net Core EJ1 are we able to save a pie chart as image and export to excel if it is NOT 3d? If so, could I have an example?
Thanks,
Chris
CH
Chris
November 7, 2018 04:10 PM UTC
Sorry, I thought of another question...
Can you save a 3d chart as an SVG file? If so, how would you do that?
I just realized there is way you could export a 3d chart to excel. You could do it yourself using XlsIO instead of the built in export to excel functionality in the chart.
Chris
CH
Chris
November 7, 2018 11:44 PM UTC
Hi,
I figured out how to save the 3d pie chart as SVG and how to export to excel using XlsIO. I even got the chart in the excel file looking reasonably close to the one created in the view. Here is my controller method:
public ActionResult ExportStageAverages(string Data, string ChartModel)
{
ChartProperties propObj = ConvertChartObject(ChartModel);
string type = propObj.ExportSettings.Type.ToString().ToLower();
if (type == "svg")
{
// to svg
string data = System.Uri.UnescapeDataString(Data);
MemoryStream ms = new MemoryStream();
TextWriter tw = new StreamWriter(ms);
tw.WriteLine(data);
tw.Flush();
ms.Position = 0;
return File(ms, "application/force-download", "Averages.svg");
} else
{
if (type == "xlsx")
{
ExcelEngine excelEngine = new ExcelEngine();
IApplication application = excelEngine.Excel;
// create new workbook
IWorkbook workbook = application.Workbooks.Create();
IWorksheet sheet = workbook.Worksheets[0];
sheet.Name = "Averages";
string stageText = propObj.Legend.Title.Text;
sheet.Range["A1"].ColumnWidth = 14.43;
sheet.Range["B1"].ColumnWidth = 14.29;
sheet.Range["A1"].Text = stageText + " Averages";
sheet.Range["A1"].CellStyle.Font.Bold = true;
sheet.Range["A1"].CellStyle.Font.Size = 16;
sheet.Range["A3"].Text = stageText;
sheet.Range["B3"].Text = "Length (Days)";
sheet.Range["A3:B3"].CellStyle.Font.Bold = true;
sheet.Range["A3:B3"].CellStyle.Font.Underline = ExcelUnderline.Single;
// the data points are already in the chart properties, no need to recalculate
int curRowIdx = 3;
foreach (var point in propObj.Series[0].Points)
{
curRowIdx++;
sheet.Range["A" + curRowIdx.ToString()].Text = point.X;
sheet.Range["B" + curRowIdx.ToString()].Number = point.Y;
}
IChartShape chart = sheet.Charts.Add();
chart.ChartType = ExcelChartType.Pie_Exploded_3D;
chart.DataRange = sheet.Range["A3:B" + curRowIdx.ToString()];
chart.IsSeriesInRows = false;
chart.ChartTitle = "";
chart.TopRow = curRowIdx + 1;
chart.BottomRow = curRowIdx + 35;
chart.RightColumn = 9;
chart.HasLegend = false;
IChartSerie serie = chart.Series[0];
chart.ChartArea.LineProperties.LinePattern = ExcelChartLinePattern.None;
// can't use DefaultDataPoint as I want to add a "suffix" to each one
//serie.DataPoints.DefaultDataPoint.DataLabels.IsValue = true;
//serie.DataPoints.DefaultDataPoint.DataLabels.IsCategoryName = true;
//serie.DataPoints.DefaultDataPoint.DataLabels.ShowLeaderLines = true;
//serie.DataPoints.DefaultDataPoint.DataLabels.Position = ExcelDataLabelPosition.Outside;
//serie.DataPoints.DefaultDataPoint.DataLabels.Delimiter = ": ";
//serie.DataPoints.DefaultDataPoint.DataLabels.Text = serie.DataPoints.DefaultDataPoint.DataLabels.Text + " Days";
int curIdx = 0;
foreach (var point in propObj.Series[0].Points) {
serie.DataPoints[curIdx].DataFormat.Fill.ForeColor = Syncfusion.Drawing.ColorTranslator.FromHtml(point.Fill);
serie.DataPoints[curIdx].DataLabels.Text = point.X + ": " + point.Y.ToString() + " days";
serie.DataPoints[curIdx].DataLabels.Position = ExcelDataLabelPosition.Outside;
serie.DataPoints[curIdx].DataLabels.ShowLeaderLines = true;
curIdx++;
}
chart.Elevation = 50;
chart.Rotation = 90;
chart.Series[0].SerieFormat.Percent = 40;
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
workbook.Version = ExcelVersion.Excel2016;
string fileName = "Averages.xlsx";
try
{
MemoryStream ms = new MemoryStream();
workbook.SaveAs(ms);
ms.Position = 0;
workbook.Close();
excelEngine.Dispose();
return File(ms, contentType, fileName);
}
catch
{
return View();
}
}
}
// should never get here
return View();
}
{
ChartProperties propObj = ConvertChartObject(ChartModel);
string type = propObj.ExportSettings.Type.ToString().ToLower();
if (type == "svg")
{
// to svg
string data = System.Uri.UnescapeDataString(Data);
MemoryStream ms = new MemoryStream();
TextWriter tw = new StreamWriter(ms);
tw.WriteLine(data);
tw.Flush();
ms.Position = 0;
return File(ms, "application/force-download", "Averages.svg");
} else
{
if (type == "xlsx")
{
ExcelEngine excelEngine = new ExcelEngine();
IApplication application = excelEngine.Excel;
// create new workbook
IWorkbook workbook = application.Workbooks.Create();
IWorksheet sheet = workbook.Worksheets[0];
sheet.Name = "Averages";
string stageText = propObj.Legend.Title.Text;
sheet.Range["A1"].ColumnWidth = 14.43;
sheet.Range["B1"].ColumnWidth = 14.29;
sheet.Range["A1"].Text = stageText + " Averages";
sheet.Range["A1"].CellStyle.Font.Bold = true;
sheet.Range["A1"].CellStyle.Font.Size = 16;
sheet.Range["A3"].Text = stageText;
sheet.Range["B3"].Text = "Length (Days)";
sheet.Range["A3:B3"].CellStyle.Font.Bold = true;
sheet.Range["A3:B3"].CellStyle.Font.Underline = ExcelUnderline.Single;
// the data points are already in the chart properties, no need to recalculate
int curRowIdx = 3;
foreach (var point in propObj.Series[0].Points)
{
curRowIdx++;
sheet.Range["A" + curRowIdx.ToString()].Text = point.X;
sheet.Range["B" + curRowIdx.ToString()].Number = point.Y;
}
IChartShape chart = sheet.Charts.Add();
chart.ChartType = ExcelChartType.Pie_Exploded_3D;
chart.DataRange = sheet.Range["A3:B" + curRowIdx.ToString()];
chart.IsSeriesInRows = false;
chart.ChartTitle = "";
chart.TopRow = curRowIdx + 1;
chart.BottomRow = curRowIdx + 35;
chart.RightColumn = 9;
chart.HasLegend = false;
IChartSerie serie = chart.Series[0];
chart.ChartArea.LineProperties.LinePattern = ExcelChartLinePattern.None;
// can't use DefaultDataPoint as I want to add a "suffix" to each one
//serie.DataPoints.DefaultDataPoint.DataLabels.IsValue = true;
//serie.DataPoints.DefaultDataPoint.DataLabels.IsCategoryName = true;
//serie.DataPoints.DefaultDataPoint.DataLabels.ShowLeaderLines = true;
//serie.DataPoints.DefaultDataPoint.DataLabels.Position = ExcelDataLabelPosition.Outside;
//serie.DataPoints.DefaultDataPoint.DataLabels.Delimiter = ": ";
//serie.DataPoints.DefaultDataPoint.DataLabels.Text = serie.DataPoints.DefaultDataPoint.DataLabels.Text + " Days";
int curIdx = 0;
foreach (var point in propObj.Series[0].Points) {
serie.DataPoints[curIdx].DataFormat.Fill.ForeColor = Syncfusion.Drawing.ColorTranslator.FromHtml(point.Fill);
serie.DataPoints[curIdx].DataLabels.Text = point.X + ": " + point.Y.ToString() + " days";
serie.DataPoints[curIdx].DataLabels.Position = ExcelDataLabelPosition.Outside;
serie.DataPoints[curIdx].DataLabels.ShowLeaderLines = true;
curIdx++;
}
chart.Elevation = 50;
chart.Rotation = 90;
chart.Series[0].SerieFormat.Percent = 40;
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
workbook.Version = ExcelVersion.Excel2016;
string fileName = "Averages.xlsx";
try
{
MemoryStream ms = new MemoryStream();
workbook.SaveAs(ms);
ms.Position = 0;
workbook.Close();
excelEngine.Dispose();
return File(ms, contentType, fileName);
}
catch
{
return View();
}
}
}
// should never get here
return View();
}
DD
Dharanidharan Dharmasivam
Syncfusion Team
November 8, 2018 07:34 AM UTC
Hi Chris,
Thanks for the information. As stated earlier we will provide support for exporting 3d chart to excel in any of our upcoming release. Kindly revert us, if you need any further assistance.
Thanks,
Dharani.
SIGN IN To post a reply.
- 6 Replies
- 2 Participants
-
CH Chris
- Nov 5, 2018 11:11 PM UTC
- Nov 8, 2018 07:34 AM UTC