需求:数据统计报表使用到HighCharts显示各种图形:柱状图,饼图,点阵图等等,需要将数据表以及对应的图像导入到Excel中,方便打印。

解决方法: Excel导出采用NPOI,HighChart图像利用svg将图片写入到Excel中。

遇到的问题:图片模糊,图片清晰度与web页面相比差距很大。

        

 
明显可以看出,差别很大,无法达到要求,
实现此所采用的代码:

 var doc = new SvgDocument();
XmlDocument xml = new XmlDocument();
xml.LoadXml(this.chart_Hidden.Value);
doc = SvgDocument.Open(xml);
Bitmap mapImage = doc.Draw();
byte[] buffer = NPOIExportExcelHelp.BitmapToBytes(mapImage);
int pictureIdx = workBook.AddPicture(buffer, PictureType.JPEG);
HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(, , , , , , , );
HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
pict.Resize();

优化方案:

1 下载开源的.net导出文件: https://github.com/imclem/Highcharts-export-module-asp.net

利用此项目中的dll文件:itextsharp.dll,sharpPDF.dll,Svg.dll

2   借鉴文章:https://jucelin.com/highcharts_esport_net.html  中针对于CreateSvgDocument()方法的优化改造,优化图片的格式,
 /// <summary>
/// Creates an SvgDocument from the SVG text string.
/// </summary>
/// <returns>An SvgDocument object.</returns>
private SvgDocument CreateSvgDocument()
{
SvgDocument svgDoc;
XmlDocument xml = new XmlDocument();
xml.LoadXml(this.Svg);
XmlNodeList nodeListAllg = xml.GetElementsByTagName("g");
Dictionary<int, XmlNode[,]> dic = new Dictionary<int, XmlNode[,]>();
int i = ;
foreach (XmlNode xNod in nodeListAllg)
{
i++;
XmlNode xmlvisibility = xNod.Attributes.GetNamedItem("class");
if (xmlvisibility != null && xmlvisibility.Value == "highcharts-series-group")
{
foreach (XmlNode xNod2 in xNod.ChildNodes)
{
i++;
XmlNode xmlvisibility1 = xNod2.Attributes.GetNamedItem("visibility");
if (xmlvisibility1 != null && xmlvisibility1.Value == "hidden")
{
XmlNode[,] xmln = new XmlNode[, ];
xmln[, ] = xNod;
xmln[, ] = xNod2;
dic.Add(i, xmln);
}
}
}
else if (xmlvisibility != null && xmlvisibility.Value == "highcharts-tooltip")
{
XmlNode[,] xmln = new XmlNode[, ];
xmln[, ] = xml.FirstChild;
xmln[, ] = xNod;
dic.Add(i, xmln);
}
}
foreach (KeyValuePair<int, XmlNode[,]> a in dic)
{
a.Value[, ].RemoveChild(a.Value[, ]);
}
this.Svg = xml.OuterXml;
// Create a MemoryStream from SVG string.
using (MemoryStream streamSvg = new MemoryStream(
Encoding.UTF8.GetBytes(this.Svg)))
{
// Create and return SvgDocument from stream.
svgDoc = SvgDocument.Open(streamSvg);
}
// Scale SVG document to requested width.
svgDoc.Transforms = new SvgTransformCollection();
float scalar = (float)this.Width / (float)svgDoc.Width;
svgDoc.Transforms.Add(new SvgScale(scalar, scalar));
svgDoc.Width = new SvgUnit(svgDoc.Width.Type, svgDoc.Width * scalar);
svgDoc.Height = new SvgUnit(svgDoc.Height.Type, svgDoc.Height * scalar);
return svgDoc;
}
 
3 利用第二步的方法,基本可以满足要求,生成的Exce图片效果如下
4 将以上方法整理封装成类库
 public class HightChartExport
{
/// <summary>
/// 获取svg图片buffer,用于excel
/// </summary>
/// <param name="svgHtml"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
public static byte[] GetSvgDocumentByte(string svgHtml, int width, int height)
{
try
{
if (string.IsNullOrEmpty(svgHtml))
{
return new byte[];
}
if (width == || height == )
{
return new byte[];
}
SvgDocument svgDocument = CreateSvgDocument(svgHtml, width, height);
return BitmapToBytes(svgDocument.Draw());
}
catch
{
throw new Exception();
}
}
private static SvgDocument CreateSvgDocument(string svgHtml, int width, int height)
{
SvgDocument svgDoc;
XmlDocument xml = new XmlDocument();
xml.LoadXml(svgHtml);
XmlNodeList nodeListAllg = xml.GetElementsByTagName("g");
Dictionary<int, XmlNode[,]> dic = new Dictionary<int, XmlNode[,]>();
int i = ;
foreach (XmlNode xNod in nodeListAllg)
{
i++;
XmlNode xmlvisibility = xNod.Attributes.GetNamedItem("class");
if (xmlvisibility != null && xmlvisibility.Value == "highcharts-series-group")
{
foreach (XmlNode xNod2 in xNod.ChildNodes)
{
i++;
XmlNode xmlvisibility1 = xNod2.Attributes.GetNamedItem("visibility");
if (xmlvisibility1 != null && xmlvisibility1.Value == "hidden")
{
XmlNode[,] xmln = new XmlNode[, ];
xmln[, ] = xNod;
xmln[, ] = xNod2;
dic.Add(i, xmln);
}
}
}
else if (xmlvisibility != null && xmlvisibility.Value == "highcharts-tooltip")
{
XmlNode[,] xmln = new XmlNode[, ];
xmln[, ] = xml.FirstChild;
xmln[, ] = xNod;
dic.Add(i, xmln);
}
}
foreach (KeyValuePair<int, XmlNode[,]> a in dic)
{
a.Value[, ].RemoveChild(a.Value[, ]);
}
svgHtml = xml.OuterXml;
// Create a MemoryStream from SVG string.
using (MemoryStream streamSvg = new MemoryStream(
Encoding.UTF8.GetBytes(svgHtml)))
{
// Create and return SvgDocument from stream.
svgDoc = SvgDocument.Open<SvgDocument>(streamSvg);
}
// Scale SVG document to requested width.
svgDoc.Transforms = new SvgTransformCollection();
float scalar = (float)width / (float)svgDoc.Width;
svgDoc.Transforms.Add(new SvgScale(scalar, scalar));
svgDoc.Width = new SvgUnit(svgDoc.Width.Type, svgDoc.Width * scalar);
svgDoc.Height = new SvgUnit(svgDoc.Height.Type, svgDoc.Height * scalar);
return svgDoc;
}
/// <summary>
/// 读取图片
/// </summary>
/// <param name="Bitmap"></param>
/// <returns></returns>
private static byte[] BitmapToBytes(Bitmap Bitmap)
{
MemoryStream ms = null;
try
{
ms = new MemoryStream();
Bitmap.Save(ms, ImageFormat.Png);
byte[] byteImage = new Byte[ms.Length];
byteImage = ms.ToArray();
return byteImage;
}
catch (ArgumentNullException ex)
{
throw ex;
}
finally
{
ms.Close();
}
}
}

5 调用方法如下:

 byte[] buffer = HightChartExport.GetSvgDocumentByte(this.chart_Pie.Value, Convert.ToInt32(chart_width.Value), Convert.ToInt32(chart_height.Value));
int pictureIdx = workBook.AddPicture(buffer, PictureType.PNG);
HSSFPatriarch patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(, , , , , rowIndex + , , );
HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx);
pict.Resize();

参考文章

https://github.com/imclem/Highcharts-export-module-asp.net

https://jucelin.com/highcharts_esport_net.html

 

.Net 使用HighCharts 导入图片到Excel的更多相关文章

  1. FastStone+ImageReady+Kutools plus导入图片到Excel单元格

    先前打算自己做一个也附带训练下,发现有下面方法也好. 1)做帮助文档时需要一种格式(需要将图片导入到Excel中时,假如是按此法归类汇总) 2)FastStone滚动截图       粘贴到Photo ...

  2. 分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility (续2篇-模板导出综合示例)

    自ExcelUtility类推出以来,经过项目中的实际使用与不断完善,现在又做了许多的优化并增加了许多的功能,本篇不再讲述原理,直接贴出示例代码以及相关的模板.结果图,以便大家快速掌握,另外这些示例说 ...

  3. [转]Java中导入、导出Excel

    原文地址:http://blog.csdn.net/jerehedu/article/details/45195359 一.介绍 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样 ...

  4. 分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility (续3篇-导出时动态生成多Sheet EXCEL)

    ExcelUtility 类库经过我(梦在旅途)近期不断的优化与新增功能,现已基本趋向稳定,功能上也基本可以满足绝大部份的EXCEL导出需求,该类库已在我们公司大型ERP系统全面使用,效果不错,今天应 ...

  5. 分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility (续篇)

    上周六我发表的文章<分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility>受到了大家的热烈支持与推荐,再此表示感谢,该ExcelUtility ...

  6. 用javascript协助导入图片

    用javascript协助导入图片 需求 先说说需求.春节回家见爸妈,老爸迷上了摄影.他把平时的照片都上传到了 成都图片网, 这个成都图片网专门有一个 "快拍成都" 的版块,用于大 ...

  7. Java的导入与导出Excel

    使用Jakarta POI导入.导出Excel Jakarta POI 是一套用于访问微软格式文档的Java API.Jakarta POI有很多组件组成,其中有用于操作Excel格式文件的HSSF和 ...

  8. (转载)SQL中导入图片

    SQL中导入图片 分类: 论坛精贴 2006-05-10 12:07 398人阅读 评论(0) 收藏 举报 sqlimage服务器insertlogingo 1.建立过程CREATE PROCEDUR ...

  9. 有关ios中images.xcassets的导入图片等命名问题

    最近遇到一个问题,就是在设置启动图片的时候,把启动图片命名设置为了xxx@2x.png, 然后应用死活没有显示启动图片,调试了很久,才发现是因为文件命名的原因. 1. 如果在图片的下方有2x或3x的标 ...

随机推荐

  1. CentOS7入门到精通实战课程课后习题

    Linux自动化运维系列①: CentOS7入门到精通实战--->传送门 http://edu.51cto.com/course/13055.html 01.系统入门课后习题 1.口述一个命令执 ...

  2. 温故而知新-面向对象的PHP

    1 类的多态 不同的类对同一操作可以有不同的行为. 比如自行车和汽车都有移动这个成员函数行为, 那么自行车类可以移动,行为和汽车的移动行为肯定不同. 2 析构函数不能有参数 3 __set和__get ...

  3. MPI 并行奇偶交换排序 + 集合通信函数 Sendrecv() Sendvecv_replace()

    ▶ <并行程序设计导论>第三章的例子程序 ● 代码 #include <stdio.h> #include <mpi.h> #include <stdlib. ...

  4. <form> 表单提交 return 阻止内容为空事件

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 重新设定McAfee Agent的菜单语言

    默认安装的McAfee Agent,语言会根据系统中的设置,自动选择了语言. 有时想更换语言,却又不想重装McAfee Agent (以前叫 ePO Agent) 其实可以直接运行下面的命令进行重新设 ...

  6. js 判断空数组,空对象!

    var attr1 = [ ]; var obj1 = { }; console.log(isEmpty(attr1)); console.log(isEmpty(obj1)); function i ...

  7. 创建maven版的java工程

    步骤如下: 1.第一步 2.第二步: 3.第三步:

  8. Work-Stealing in .NET 4.0

    [Work-Stealing in .NET 4.0] 1.线程按LIFO取Task,因为最后一个Task很可能还在Cache中,提高命中率. 2.Stealer从FIFO取Task,最先加入的Tas ...

  9. 使用C#进行基于PI的开发

    首先欲基于PI-SDK开发PI数据库,必须先安装PI-SDK,然后再VS中新建了一个aspnet网站,添加引用:PI-SDK 1.2 Type Library 和 PISDKCommon 1.2 Ty ...

  10. Laravel 5.4 实现无限级分类

    最近在工作中遇到一个需求,是要在laravel 5.4中实现无限级分类,但发现网上这个的资料较少,所以只能自己来实现了,下面这篇文章主要给大家介绍了关于在laravel 5.4中实现无限级分类的方法示 ...