一、文章引言:近段时间,由于工作的需要,需要以报表和图形的形式对数据进行统计分析,由于手头没有相关的开发组件,于是自己利用GDI+函数进行地层的图形绘制,配合中间层的数据统计及组合,表层嵌入HTML文件中,形成了一整套生成饼状图、柱状图和折线图的应用,现在把设计思路及部分源代码提供出来,和大家相互交流。
二、设计思路:
用户请求 ——》数据采集 ——》逻辑组织——》调用自定义底层函数——》调用.Net GDI+图形函数——》生成JPG文件——》返回指向JPG图形的HTML文件 ——》完成
二、部分代码:
1. 自定义底层图形函数
///
1<summary>
2/// JpgProxy 的摘要说明。
3/// </summary>
public class JpgProxy
{
#region 饼状图
///
1<summary>
2/// 绘制饼状图
3/// </summary>
///
1<param name="height"/>
画布高度
///
1<param name="width"/>
画布宽度
///
1<param name="title"/>
图形标题
///
1<param name="partName"/>
图形组成元素名称
///
1<param name="partPoint"/>
图形组成元素坐标
///
1<param name="partCount"/>
图形组成元素总数
///
1<param name="partColor"/>
图形组成元素颜色
///
1<param name="imgName"/>
输出图形文件名称
///
1<param name="unit"/>
统计单位
///
1<param name="bgColor"/>
图形背景颜色
///
1<param name="strErr"/>
功能调用返回信息
///
1<param name="debug"/>
功能调用测试
///
1<returns>功能调用是否成功</returns>
public static bool DrawPie(int height,int width,string title,string[] partName,float[,] partPoint,int[]partCount,Color[] partColor,string imgName,string unit,Color bgColor,out string strErr,bool debug)
{
#region 分离参数
//参数检测
if( partPoint.GetLength(0) != partColor.Length)
{
strErr = "坐标参数与颜色参数不对称,拒绝功能调用";
return false;
}
else if(partPoint.GetLength(0) != 2)
{
strErr = "坐标参数数组定义与约定不符,拒绝功能调用";
}
else if(partPoint.GetLength(0) != partName.Length)
{
strErr = "坐标参数与组成名称参数不对称,拒绝功能调用";
return false;
}
string outPutName = imgName.Split('\')[imgName.Split('\').Length - 1].Split('.')[0].ToString();
string outPutParth = "";
for( int i = 0 ; i < imgName.Split('\').Length - 1; i ++)
{
outPutParth = outPutParth + imgName.Split('\')[i].ToString() + "\";
}
#endregion
#region 基本图形
//功能调用
Bitmap bmp = new Bitmap(width,height);
Graphics g = Graphics.FromImage(bmp);
Pen pen = new Pen(Color.Black);
Rectangle outline = new Rectangle(0,0,height - 5,width -5);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(bgColor);
g.DrawEllipse(pen,outline);
//输出图形区域
for(int i = 0 ; i < partName.Length; i ++)
{
g.FillPie(new SolidBrush(partColor[i]),outline,partPoint[i,0],partPoint[i,1]);
}
//输出到图片
bmp.Save(imgName,ImageFormat.Jpeg);
#endregion
#region 图形标题
if(debug)
{
bmp = new Bitmap(200 , 30);
g = Graphics.FromImage(bmp);
g.Clear(bgColor);
g.DrawString(title,new Font("Arail",14,FontStyle.Regular),SystemBrushes.WindowText,new PointF(0,0));
bmp.Save(outPutParth + outPutName + "" + "Title" + ".jpg",ImageFormat.Jpeg);
}
#endregion
#region 描述图形
//输出颜色方块
for(int i = 0; i < partName.Length ; i++)
{
bmp = new Bitmap(15 , 15);
g = Graphics.FromImage(bmp);
pen = new Pen(Color.Black);
g.Clear(bgColor);
outline = new Rectangle(0,0,10,10);
g.DrawRectangle(pen,outline);
g.FillRectangle(new SolidBrush(partColor[i]),0,0,10,10);
bmp.Save(outPutParth + outPutName + "" + "DesColor" + "" + i.ToString() +".jpg",ImageFormat.Jpeg);
}
#endregion
#region 描述文字
if(debug)
{
for(int i = 0; i < partName.Length ; i++)
{
bmp = new Bitmap(120 , 15);
g = Graphics.FromImage(bmp);
g.Clear(bgColor);
g.DrawString(partName[i].ToString() + ": " + Convert.ToString( partCount[i]) + " " + unit,new Font("Arail",9,FontStyle.Regular),SystemBrushes.WindowText,new PointF(0,0));
bmp.Save(outPutParth + outPutName + "" + "DesText" + "_" + i.ToString() +".jpg",ImageFormat.Jpeg);
}
}
#endregion
#region 释放资源
g.Dispose();
bmp.Dispose();
strErr = imgName + "绘制成功";
return true;
#endregion
}
#endregion
2. 中间逻辑组织函数
#region 构建饼状图
///
1<summary>
2/// 构建饼状图
3/// </summary>
///
1<param name="pie"/>
图形参数
///
1<param name="JpgName"/>
图形名称
///
1<returns>目标文件地址</returns>
private static string CreatePie(JPGPie pie,string JpgName)
{
//计算总和
int Count = 0;
for(int i = 0 ; i < pie.ElementValue.Length; i ++)
{
Count = Count + pie.ElementValue[i];
}
string strContent = "";
if(Count != 0)
{
#region 组织图形参数
//图形组成元素坐标
float[,]partPoint = new float[pie.ElementCount,2];
for(int i = 0 ; i < partPoint.GetLength(0); i ++)
{
for(int j = 0 ; j < partPoint.GetLength(1); j ++)
{
if( i == 0 && j == 0) //第一个扇形的第一条边
{
partPoint[i,j] = 0.0F;
}
else if( j == 0) //中间扇形的第一条边
{
partPoint[i,j] = partPoint[i-1,0] + partPoint[i -1,1];
}
else if( j == 1 && i == partPoint.GetLength(0) - 1)//最后一个扇型
{
partPoint[i,j] = Convert.ToSingle( pie.ElementValue[i] * 360 / Count + 2 );
}
else if( j == 1)//中间扇形的第二条边
{
partPoint[i,j] = Convert.ToSingle( pie.ElementValue[i] * 360 / Count );
}
}
}
#endregion
string strErr = "";
string strImgName = JPGReportManage.JpgPath("Pie\"+ JpgName +".jpg");
#region 调用图形函数
JpgProxy.DrawPie(pie.BgHeight,pie.BgWidth,pie.BgTitle,pie.ElementName,partPoint,pie.ElementValue,pie.ElementColor,strImgName,pie.Unit,pie.BgColor,out strErr,false);
#endregion
#region 组织HTML代码
#region 格式控制
//换算值长度
int vir_max_lenth = 0;
//实际数值长度
int val_max_lenth = 0;
//最大元素下标
int flag = 0;
#region 求出最大元素下标
int k = 0;
int max_Value = pie.ElementValue[0];
for(int i = 0 ; i < pie.ElementValue.Length; i ++)
{
if(k < pie.ElementValue.Length -1)
{
k = i + 1;
}
else
{
break;
}
if( max_Value < pie.ElementValue[k] )
{
max_Value = pie.ElementValue[k];
flag = k;
}
}
#endregion
//长度标准
vir_max_lenth = Convert.ToString(pie.ElementValue[flag] * 100 / Count).Length;
val_max_lenth = pie.ElementValue[flag].ToString().Length;
#endregion
string strDynamic = "";
for(int i = 0 ; i < pie.ElementCount; i ++)
{
strDynamic = strDynamic +
"
1<tr>" +
2"<td>" +
3"<img src='../jpg/pie/"+ JpgName +"_DesColor_"+ i.ToString() +".jpg'/>" +
4"</td>" +
5"<td>" +
6"<font size="2">" +
7pie.ElementName[i].ToString() + " : " + Convert.ToString(pie.ElementValue[i] * 100 / Count) + JPGReportManage.HTMLSpaceGenerator(vir_max_lenth - Convert.ToString(pie.ElementValue[i] * 100 / Count).Length) + pie.Unit + "[" + pie.ElementValue[i].ToString() + JPGReportManage.HTMLSpaceGenerator(val_max_lenth - pie.ElementValue[i].ToString().Length) +"]" +
8"</font>" +
9"</td>" +
10"</tr>
" ;
}
strContent = "
1<html><head></head><body>" +
2"<table align="center" height="100%" width="100%">" +
3"<tr>" +
4"<td>" +
5"<table align="center">" +
6"<tr>" +
7"<td>" +
8"<img src='../jpg/pie/"+ JpgName +".jpg'/>" +
9"<td>" +
10"<td>" +
11"<table align="center">" +
12strDynamic +
13"</table>" +
14"<td>" +
15"</td></td></td></td></tr>" +
16"</table>" +
17"</td>" +
18"<tr>" +
19"</tr></tr></table>" +
20"</body></html>
";
#endregion
}
else
{
#region 组织HTML代码
strContent = "
1<html><head></head><body>" +
2"<table align="center" height="100%" width="100%">" +
3"<tr>" +
4"<td>" +
5"<table align="center">" +
6"<tr>" +
7"<td>" +
8"没有数据可以显示" +
9"</td>" +
10"</tr>" +
11"</table>" +
12"</td>" +
13"<tr>" +
14"</tr></tr></table>" +
15"</body></html>
";
#endregion
}
#region 生成HTML文件
JPGReportManage.CreateHtmFile(JPGReportManage.HtmlPath(JpgName + ".htm"),strContent);
#endregion
return "../Html/"+ JpgName +".htm";
}
#endregion
3. 特定应用调用
#region 各区办件数量同比柱状图
///
1<summary>
2/// 各区办件数量同比柱状图
3/// </summary>
///
1<param name="param"/>
///
1<returns></returns>
private static string Create_Cit_Case_Amount_Pos_Column(PosContrastParam param)
{
#region 逻辑处理
#region 参数处理
LiLongDataReport.JPGColumn column = new JPGColumn();
//图片颜色
column.BgColor = System.Drawing.Color.White;
//图片高度
column.BgHeight = 860;
//图片标题
column.BgTitle = "";
//图片宽度
column.BgWidth = 860;
//柱状颜色
System.Drawing.Color[]color = {System.Drawing.Color.Blue};
column.ElementColor = color;
//柱状总数
column.ElementCount = 1;
//柱状描述
string[]name = new string[PosNameDataBag.NameList.Length];
for(int i = 0 ; i < name.Length ; i ++)
{
name[i] = PosNameDataBag.NameList[i].Substring(0,2);
}
column.ElementName = name;
//统计单位
column.XUnit = "区";
//统计单位
column.YUnit = "件";
//柱状高度
int[]position = new int[PosNameDataBag.NameList.Length];
string Begin = "";
string End = "";
for(int i = 0 ; i < param.StartDate.Split('-').Length; i ++)
{
Begin = Begin + param.StartDate.Split('-')[i];
}
for(int i = 0 ; i < param.EndDate.Split('-').Length; i ++)
{
End = End + param.EndDate.Split('-')[i];
}
#endregion
#region 提交查询
string strErr = "";
string Result = "";
string strSql = "";
for(int i = 0; i < position.Length ; i ++)
{
XMLProxy.SetNodeValue(System.Web.HttpContext.Current.Server.MapPath("..") + "\" + "state.xml","综合查询","正在处理"+ PosNameDataBag.NameList[i] +"区数据 任务数["+ PosNameDataBag.NameList.Length.ToString() +"] 已处理["+ i.ToString() +"] 未处理["+ Convert.ToString(PosNameDataBag.NameList.Length - i) +"]");
strSql = "SELECT count(*) as col from 办件表 where Cast(受理日期 as datetime) >= '"+ Begin + "' and Cast(受理日期 as datetime) <= '"+ End + "'";
DataBaseProxy.ExceuteSql(ConfigManage.ConnectionStringProxy(PosNameDataBag.NameList[i]),strSql,out Result,out strErr);
position[i] = int.Parse(Result);
}
#endregion
#region 绑定到参数
column.ElementValue = position;
#endregion
#endregion
#region 内核调用
string strReturn = null;
strReturn = JPGReportManage.CreateColumn(column,"Cit_Case_Amount_Pos_Column");
#endregion
return strReturn;
}
#endregion
4. 表层调用函数
#region 构造区级统计类图形
///
1<summary>
2/// 构造区级统计类图形
3/// </summary>
///
1<param name="jpgType"/>
图形类型
///
1<param name="param"/>
统计参数
///
1<returns>目标文件地址</returns>
public static string BuildPosAmountJPG(EJpgReportType jpgType,PosAmountParam param)
{
string strReturn = null;
switch(jpgType)
{
case EJpgReportType.Pos_Case_Amount_Type_Pie:
{
strReturn = JPGReportManage.Create_Pos_Case_Amount_Type_Pie(param);
break;
}
case EJpgReportType.Pos_Case_Amount_Year_Curve:
{
strReturn = JPGReportManage.Create_Pos_Case_Amount_Year_Curve(param);
break;
}
default:
{
strReturn = "";
break;
}
}
return strReturn;
}
#endregion
5. 相关参数列举
///
1<summary>
2/// 图形报表类型
3/// </summary>
public enum EJpgReportType
{
///
1<summary>
2/// 区级年度办件数量走势折线图
3/// </summary>
Pos_Case_Amount_Year_Curve = 0,
///
1<summary>
2/// 区级办件数量中各办件类型所占比例饼状图
3/// </summary>
Pos_Case_Amount_Type_Pie =1,
///
1<summary>
2/// 各区办件数量同比柱状图
3/// </summary>
Cit_Case_Amount_Pos_Column = 2,
///
1<summary>
2/// 各区办件数量排名饼状图
3/// </summary>
Cit_Case_Amount_Pos_Pie = 3,
///
1<summary>
2/// 市级年度办件数量走势折线图
3/// </summary>
Cit_Case_Amount_Year_Curve = 4,
///
1<summary>
2/// 各区所有办件中各办件类型所占比例饼状图
3/// </summary>
Cit_Case_Type_Pie = 5,
///
1<summary>
2/// 委办局年度办件数量走势折线图
3/// </summary>
Adm_Case_Amount_Year_Curve = 6,
///
1<summary>
2/// 委办局办件数量同比柱状图
3/// </summary>
Adm_Case_Amount_Adm_Column = 7,
///
1<summary>
2/// 委办局各分局办件数量同比柱状图
3/// </summary>
Adm_Case_Amount_Sub_Column = 8,
///
1<summary>
2/// 区级年度办件办结效率评估分析饼状图
3/// </summary>
Pos_Case_End_Efficiency_Year_Pie = 9
}
#region 饼状图数据结构
///
1<summary>
2/// 饼状图数据结构
3/// </summary>
public class JPGPie
{
//饼状组成元素个数
private int elementCount;
//饼状组成元素名称
private string[]elementName;
//饼状组成元素颜色
private Color[]elementColor;
//饼状组成元素大小
private int[]elementValue;
//饼装图形背景颜色
private Color bgColor;
//饼状图形高度
private int bgHeight;
//饼状图形宽度
private int bgWidth;
//饼状图形标题
private string bgTitle;
//饼状图统计单位
private string unit;
///
1<summary>
2/// 饼状图统计单位
3/// </summary>
public string Unit
{
get
{
return unit;
}
set
{
unit = value;
}
}
///
1<summary>
2/// 饼状组成元素个数
3/// </summary>
public int ElementCount
{
get
{
return elementCount;
}
set
{
elementCount = value;
}
}
///
1<summary>
2/// 饼状组成元素名称
3/// </summary>
public string[]ElementName
{
get
{
return elementName;
}
set
{
elementName = value;
}
}
///
1<summary>
2/// 饼状组成元素颜色
3/// </summary>
public Color[]ElementColor
{
get
{
return elementColor;
}
set
{
elementColor = value;
}
}
///
1<summary>
2/// 饼状组成元素大小
3/// </summary>
public int[]ElementValue
{
get
{
return elementValue;
}
set
{
elementValue = value;
}
}
///
1<summary>
2/// 饼装图形背景颜色
3/// </summary>
public Color BgColor
{
set
{
bgColor = value;
}
get
{
return bgColor;
}
}
///
1<summary>
2/// 饼状图形高度
3/// </summary>
public int BgHeight
{
get
{
return bgHeight;
}
set
{
bgHeight = value;
}
}
///
1<summary>
2/// 饼状图形宽度
3/// </summary>
public int BgWidth
{
get
{
return bgWidth;
}
set
{
bgWidth = value;
}
}
///
1<summary>
2/// 饼状图形标题
3/// </summary>
public string BgTitle
{
get
{
return bgTitle;
}
set
{
bgTitle = value;
}
}
}
#endregion
6. 效果展示
希望能够有更多的知识与大家分享,共同进步!