利用GDI+函数构造图形报表

一、文章引言:近段时间,由于工作的需要,需要以报表和图形的形式对数据进行统计分析,由于手头没有相关的开发组件,于是自己利用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. 效果展示

希望能够有更多的知识与大家分享,共同进步!

Published At
Categories with Web编程
Tagged with
comments powered by Disqus