幾種實現統計表的方法

 作者:郭斌 時間:2003年10月
作者手機:13571878390
作者項目:Syn-Data
負責人名稱: 韋敏宗
負責人Email: [email protected]

Syn-Data基於Internet數據協同會議系統是利用最新流媒體通信技術實現的一個具有實時多點語音、視頻、數據通訊綜合應用能力的系統。它不僅實現基於Internet的具有多人音頻、多人視頻、共享電子白板、共享文檔等交流手段的實時數據協同、實時討論的功能,而且實現單機的課件錄製,全程錄製回放等功能,具有對帶寬要求低,高質量音頻視頻,與Web無縫集成,強的抗網絡擁塞丟包能力和支持防火牆和應用代理等能力。它使用戶可以利用普通的PC機、標準的視頻採集設備、耳機和麥克風,實現基於Internet的實時數據協同、實時討論。Syn-Data致力於有效地節約時間和經費,提高了用戶的工作效率,使任何人不受時間、地點的限制,可充分享受網絡時代給大家帶來的實時交互式多媒體通信服務。使用Syn-Data,終端用戶可以實現共享演示文檔、應用程序、網頁及桌面等,同時提供音、視頻的無縫嵌入。

BlastTeam:該文爲Blast Tean技術原創文章之一。因爲是一系列文章,故文章描述是以章節來描述的。BlastTeam最終將把所有的技術原創文章彙編成冊。
概述
在Web程序開發中,圖形和圖表是很好的數據表現形式。往往是表格中的大量數據讓用戶產生無法處理,無從獲取所需要的信息。而以圖表方式提供數據的話就可以達到簡單清爽,簡單易懂並且一目瞭然的效果。利用圖表,管理人員可以方便的掌握銷售與生產數據,從而做出相應的判斷。
ASP.NET Web程序中,生成圖表有以下的選擇:
ASP.NET內建的圖形庫(GDI+,位於System.Drawing 命名空間)
使用簡單的圖形,GDI+能夠創建餅圖、柱狀圖、線性圖。但是這種方法過於底層,不適於創建複雜的圖形。
● 各種ASP.NET圖表控件
網上有一些ASP.NET的圖表控件,但許多控件非常昂貴,而且與最常用的圖表應用Excel差別很大。
● Office Web Components
Microsoft Office Web Components 包含在 Microsoft Office 2000 中。它們是用於向 Web 頁添加電子表格、圖表和數據處理功能的 ActiveX 控件的集合。可以直接在瀏覽器中處理數據,並以圖表的形式顯示數據。由於其基於Office的強大功能,以及與Office相同的用戶界面,無疑是ASP.NET中圖表生成的明智選擇。
本章主要包括以下幾個方面內容:
● 基於GDI+的圖表生成。
● 基於Office Web Components的圖表生成。
● 基於Office Web Components的報表生成。
經過本章的學習,將掌握ASP.NET中統計圖表的實現,利用圖表將網站的數據完美呈現給用戶。
方案設計
本節分別介紹GDI+與Office Web Components的具體使用,爲後面的章節打下基礎。
使用GDI+
GDI+ 是 GDI(Windows XP之前版本提供的圖形設備接口)的後續版本。GDI+ 是一種應用程序編程接口 (API),負責在屏幕和打印機上顯示信息。
ASP.NET中,利用GDI+可以創建簡單的柱狀圖和餅圖。
ASP.NET頁面GDI+圖像使用
在完整的生成柱狀圖和餅圖之前,先從簡單的ASP.NET頁面圖像使用開始。
在System.Draw命名空間中包含了創建、編輯圖像的所有類。創建圖像時,主要使用Bitmap類和Graphics類。爲了便於理解,可以把Bitmap類想象成畫板,Graphics類想象成畫筆。Bitmap類主要用於創建畫板以及在完成後圖像的保存。Graphics類主要用來繪製圖像、圖形和線條。
首先使用下面的代碼創建畫板。(本小節所有代碼需要添加System.Drawing命名空間與System.Drawing.Image命名空間)
Bitmap myPalette = new Bitmap(600, 400); //創建600*400的畫板
有了畫板,還需要創建Graphics類的實例來創建畫筆,指定畫板。代碼如下
Graphics myGraphics = Graphics.FromImage(myPalette);
有了畫筆和畫板,只要使用Graphics類中的各種方法在畫板上繪製圖像、圖形和線條就可以了。
Graphics類中的方法分爲兩類:繪製方法與填充方法。例如,DrawRectangle方法與FillRectangle方法。繪製方法僅僅繪製出圖形的輪廓,而填充方法繪製出圖形的輪廓同時填充圖形的內部。
下面的代碼繪製了簡單的圖形:
int width=150,height=50;
// 創建黑色背景橢圓
myGraphics.FillEllipse(new SolidBrush(Color.Black), 300, 150, width, height);
// 創建藍色背景橢圓
myGraphics.FillEllipse(new SolidBrush(Color.LightBlue), 300, 150, width - 10, height - 10);
// 創建輸出文本
string textOut = "ASP.NET";
//指定字體
Font fontOut = new Font("Times New Roman", 16, FontStyle.Bold|FontStyle.Italic);
//指定文本居中
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.LineAlignment = StringAlignment.Center;
// 繪製文本
myGraphics.DrawString(textOut,fontOut,new SolidBrush(Color.Black),new Rectangle(0,0,width,height),stringFormat);
圖已經畫好了,只剩下將圖保存下來。要將保存的圖在網頁中顯示,可以在下面兩種方式中任選其一:
● 將圖像保存在服務器的文件系統中,使用HTML的<img>標記來顯示。
● 直接將圖像的二進制流輸出到Response對象的輸出流。
兩種方式各有千秋。第一種方式適合於創建不需要變動的圖片(例如網站廣告圖片),能夠創建一次,滿足今後的所有要求。但會在服務器端保留下臨時文件。第二種方式適用於動態的創建圖片供頁面顯示,不能滿足今後的需要,卻也不會留下臨時文件。
下面分別寫出這兩種方式的代碼:
● 保存文件方式代碼:
保存文件方式首先需要在Aspx文件中添加<Img>標記
<!-- 指定顯示文件爲tmpFile.jpg -->
<img src = “tmpFile.jpg”>
然後在代碼中保存文件即可:
//將文件保存爲當前頁面所在目錄下的tmpFile.jpg
myPalette.Save(Server.MapPath("")+@"/tmpFile.jpg",ImageFormat.Jpeg);
● 直接輸出方式代碼:
//直接將圖片以二進制流的方式輸出到Response對象的輸出流。
myPalette.Save(Response.OutputStream, ImageFormat.Jpeg);
將代碼加入頁面的PageLoad事件中即可得到如圖18-1效果。
      
       圖18-1 GDI+圖像使用效果
創建柱狀圖
在知道了如何使用GDI+創建簡單圖像並顯示到頁面後,創建複雜一些的柱狀圖就非常自然了。
使用簡單的FillRectangle,DrawRectangle,DrawString方法,即可實現基本的柱狀圖。代碼如下:
//初始化Bitmap類實例與Graphics類實例準備畫圖
const int width = 600, height = 400;
Bitmap myPalette = new Bitmap(width,height);
Graphics myGraphics = Graphics.FromImage(myPalette);
// 繪製白色背景
myGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height);
// 設定顯示數據
string [] DataName = {"Jan","Feb","Mar","Apr","May","Jun"};
int [] Data = {100,20,50,60,240,20};
//設定顯示顏色
Color [] myColors = {
Color.Blue,
Color.Red,
Color.Yellow,
Color.Purple,
Color.Orange,
Color.Brown
};
//繪製柱圖
for(int i = 0;i<DataName.Length;i++)
{
//填充柱圖
myGraphics.FillRectangle(new SolidBrush(myColors[i]),(i*40)+30,300 - Data[i],20,Data[i]+5);
//繪製柱圖邊界
myGraphics.DrawRectangle(new Pen(Color.Black),(i*40)+30,300 - Data[i],20,Data[i]+5);
//繪製柱圖上方數據
myGraphics.DrawString(Data[i].ToString(), new Font("宋體", 9), Brushes.Black, new PointF((i*40)+30,300-Data[i]-20));
//繪製柱圖下標
myGraphics.DrawString(DataName[i], new Font("宋體", 9), Brushes.Black, new PointF((i*40)+30,320));
}
//輸出圖像
myPalette.Save(Response.OutputStream, ImageFormat.Jpeg);
// 清除所用繪圖對象
myGraphics.Dispose();
myPalette.Dispose();
將上述代碼寫入頁面CodeBehind文件的PageLoad事件中即可看到如圖18-2效果:
       
          圖18-2 GDI+柱狀圖效果
使用Office Web Components
Office Web Components是用於向 Web 頁添加電子表格、圖表和數據處理功能的 ActiveX控件的集合。
利用Office Web Components可以方便的來繪製簡單的柱狀圖與餅圖。不必像在GDI+中需要考慮畫圖的細節。
使用Office Web Components要求
使用Office Web Components需要系統中裝有Office2000以上版本。在工程的引用中添加Office Web Components即可。
具體步驟如下:
在解決方案資源管理器的引用文件夾上單擊鼠標右鍵選擇添加引用,在出現的添加引用對話框中選擇COM標籤,選擇Microsoft Office Web Components,雙擊選中,點擊確定即可。圖18-3、18-4顯示了該過程。
       
            圖18-3 添加引用           圖18-4 添加Office Web Components引用

使用Office Web Components繪製柱狀圖
使用Office Web Components繪製圖表不同於直接使用GDI+,主要的工作從繪圖的細節轉移到對於圖表的設置。步驟如下:
● Step1 創建ChartSpace對象來放置圖表
ChartSpace是用來放置圖表的類,圖表完成後用它來輸出。
OWC.ChartSpace objCSpace = new OWC.ChartSpaceClass ();
● Step2 使用ChartSpace對象的Add方法創建圖表
ChartSpace的Add方法創建圖表,參數表示所創建圖表的索引。
OWC.WCChart objChart = objCSpace.Charts.Add (0);
● Step3 指定圖表的類型
通過設定Chart類對象的Type屬性來指定圖表的類型。
objChart.Type = OWC.ChartChartTypeEnum.chChartTypeColumnClustered;
本例創建柱狀圖,選擇了chChartTypeColunmClustered類型。
其他的類型包括:chChartTypeArea 面積圖、chChartTypeBarClustered 條形圖、chChartTypePie 餅圖、chChartType RadarLine 雷達線圖、chChartTypeSmoothLine 平滑曲線圖、chChartTypeDoughnut 環形圖等等。
圖18-5至18-10顯示了部分圖表的簡單實例。
       
         圖18-5 曲線圖          圖18-6 條形圖          圖18-7 面積圖
       
         圖18-8 環形圖           圖18-9 餅圖          圖18-10 雷達圖
● Step4 設定圖示說明
圖示說明主要包括圖例(用顏色表示數據類型)、圖題(圖表的標題)、XY軸的數據說明(一般用來說明各軸上的數據單位)。設定代碼如下:
//指定圖表是否需要圖例
objChart.HasLegend = true;

//給定標題
objChart.HasTitle = true;
objChart.Title.Caption= "上半年月收入圖";

//給定x,y軸的圖示說明
objChart.Axes[0].HasTitle = true;
objChart.Axes[0].Title.Caption = "萬元";
objChart.Axes[1].HasTitle = true;
objChart.Axes[1].Title.Caption = "月份";
● Step5 添加數據
添加數據主要設定Chart類對象的SeriesCollection屬性。首先使用SeriesCollection的Add方法創建一組數據。然後使用SetData方法具體添加數據。代碼如下:
(注意:數據的格式是以'/t'間隔的字符串)
//添加一組圖表數據
objChart.SeriesCollection.Add(0);
//給定該組數據的名字
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimSeriesNames,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,”上半年收入”);
//給定數據分類
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,
"Jan"+'/t'+"Feb"+'/t'+"Mar"+'/t'+"Apr"+'/t'+"May"+'/t'+"Jun"+'/t' );
//給定數據值
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues,
(int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,
"100"+'/t'+"20"+'/t'+"50"+'/t'+"60"+'/t'+"240"+'/t'+"20"+'/t');
● Step6 顯示數據
顯示數據是使用Chart類對象的ExportPicture方法將生成的圖表創建爲圖片,然後顯示的。代碼如下:
//輸出成GIF文件,參數爲文件名、格式、圖片大小
objCSpace.ExportPicture(Server.MapPath("")+@"/tmpFile.gif", "GIF", 400, 300);
//從生成的圖片創建Bitmap對象,輸出到Response輸出流
Bitmap myPalette = new Bitmap(Server.MapPath("")+@"/tmpFile.gif",true);
myPalette.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Gif);
經過了以上的步驟,將代碼輸入頁面的PageLoad事件代碼段中,運行程序就可以得到如圖18-11效果。
        
        圖18-11 Office Web Components柱狀圖示例
使用Office Web Components繪製餅圖
繪製餅圖與繪製柱狀圖的區別不是很大,需要注意的是餅圖沒有XY軸,所以不能設置XY軸的圖示說明。在繪製柱狀圖的代碼上去掉關於XY軸圖示說明的代碼即可。
完整代碼如下:
//初始化圖表數據
string [] DataName = {"Jan","Feb","Mar","Apr","May","Jun"};
int [] Data = {100,20,50,60,240,20};
//聲明存儲數據分類和數據值的字符串
string strDataName = "";
string strData = "";
//循環按格式生成存儲數據分類與數據值的字符串
for(int i=0;i< Data.Length;i++)
{
strCategory += DataName[i]+'/t';
strValue += Data[i].ToString()+'/t';
}
//創建ChartSpace對象來放置圖表
OWC.ChartSpace objCSpace = new OWC.ChartSpaceClass ();

//在ChartSpace對象中添加圖表,Add方法返回chart對象
OWC.WCChart objChart = objCSpace.Charts.Add (0);

//指定圖表的類型爲餅圖
objChart.Type = OWC.ChartChartTypeEnum.chChartTypePie;
//指定圖表是否需要圖例
objChart.HasLegend = true;
//給定標題
objChart.HasTitle = true;
objChart.Title.Caption= "上半年月收入圖";

//添加一個series
objChart.SeriesCollection.Add(0);

//給定數據分類
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,strDataName);

//給定數據值
objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues,
(int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,strData);
//輸出成GIF文件.
objCSpace.ExportPicture(Server.MapPath("")+@"/tmpFile.gif", "GIF", 400, 300);
Bitmap myPalette = new Bitmap(Server.MapPath("")+@"/tmpFile.gif",true);
myPalette.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Gif);
將上述代碼寫入頁面文件的PageLoad事件處理代碼中,運行得到如圖18-12效果。
         
        圖18-12 Office Web Components餅圖示例
公司盈利狀況統計
前面介紹了Office Web Components的情況,本節將通過公司盈利狀況統計來介紹Office Web Components柱狀圖在具體實例中的使用。
數據庫設計
爲了實現公司盈利狀況統計。首先,需要設計相關的數據庫表。在實際情況中,公司的盈利就是收入的總和與支出的總和之差。而每筆收入與支出都是在一次交易中完成的。基於以上考慮,同時爲了實現簡單。設計數據庫表單如下:
表名 T_Deal 別名 交易表
表項      說明   類型     是否可空
DealTime   交易時間  DateTime     否
DealIncome  交易金額  int       否
DealContent  交易內容  Varchar(50)   否
DealObject  交易對象  Varchar(20)   是
Comment    備註    Varchar(50)   是
注意:爲了簡單起見,用交易金額統一表示收入與支出。用正數的交易金額表示收入,負數的交易金額表示支出。這樣計算盈利時只需將交易金額求和即可。
按照上表的格式在SqlServer中創建表。添加樣例數據供程序使用。
然後創建下面的存儲過程來實現公司盈利狀況的統計。
CREATE PROCEDURE sp_SelectIncome
@year int
AS

Select sum(DealCount),Datepart(mm,DealTime) From T_Deal
where DATEPART(yy,DealTime)=@year
Group By Datepart(mm,DealTime)
GO
該存儲過程選擇交易時間的年份與輸入參數@year相等的數據,並將選擇得到的數據按交易時間的月份分組。返回每組交易金額的總和以及該組的交易月份。
界面設計
新建Web工程WebChart。將WebForm1.aspx改名爲OWCChart.aspx。同時,將其代碼文件中的類名改爲OWCChart。
界面如圖18-13所示:
      
          圖18-13 公司盈利統計界面
該界面主要包括兩部分:一個PlaceHolder控件用來放置生成的圖表構成顯示圖表部分。一個用來選擇統計年份的DropDownList控件,一個用來確定生成圖表的Button控件,一個用來顯示錯誤信息的Label控件構成了圖表的生成部分。
同樣爲了界面整潔使用Table將所用控件放在表格中。按照圖18-13安排好界面後就可以爲控件設置屬性了,主要包括以下幾個方面的設置:
● PlaceHolder控件的設置
PlaceHolder控件在本程序中用於放置生成的圖表,只需設置其Id屬性爲ChartPlaceHolder即可。
● DropDownList控件的設置
DropDownList控件在本程序中用於選擇統計年份,設置其Id屬性爲ddlYear。併爲其添加ListItem 2000,2001,2002,2003。
<asp:ListItem Value="2000">2000</asp:ListItem>
<asp:ListItem Value="2001">2001</asp:ListItem>
<asp:ListItem Value="2002">2002</asp:ListItem>
<asp:ListItem Value="2003">2003</asp:ListItem>
● Button控件的設置
Button控件設置Id屬性爲btnSumbit,Text屬性爲“確定”即可。
● Label控件的設置
Label控件設置Id屬性爲Info即可。
代碼實現
在完成了上面的界面設計後,就要進入後臺代碼的編寫了。下面就將分模塊介紹各部分功能的代碼實現。
數據讀入
爲了顯示公司盈利狀況統計,首先需要將統計的結果從數據庫中讀入。讀入數據的代碼包括以下兩部分。
● 創建數據庫聯接
爲了方便程序的配置,將數據庫聯接字段保存在Web.Config文件中。如此一來,在需要修改數據庫聯接字段時只需要修改Web.Config文件即可,不需要修改程序代碼,重新編譯。
在Web.Config文件中的<configuration>字段中加入如下代碼:
<appSettings>
<add key="ConnectStr"
value="server=localhost;uid=yourid;pwd=yourpas;database=Info;"/>
</appSettings>
其中localhost要改爲自己的數據庫服務器名,uid,pwd分別爲數據庫用戶id和密碼,database爲數據庫名。
設置好聯接字段後就可在代碼中對其進行引用了。
主要使用AppSettingReader對象的GetValue方法獲取”ConnectStr”字段信息,該方法需要兩個參數,第一個指定要引用的字段,第二個參數指定需要的類型。返回一個Object類型的變量。需要使用Convert的ToString方法將其轉換爲字符串類型
引用代碼如下:
//全局數據庫聯接
System.Data.SqlClient.SqlConnection MyConnection;
private void Page_Load(object sender, System.EventArgs e)
{
// 在此處放置用戶代碼以初始化頁面
if(Page.IsPostBack==false) // 頁面首次加載時
{

//創建Web.Config文件應用程序設置字段讀取對象
System.Configuration.AppSettingsReader ConnectionString = new System.Configuration.AppSettingsReader();
//創建數據庫聯接
MyConnection = new System.Data.SqlClient.SqlConnection();
//設置數據庫聯接的連接字段
MyConnection.ConnectionString = Convert.ToString(ConnectionString.GetValue("ConnectStr",System.Type.GetType("System.String")));
}
}
● 利用數據庫聯接讀取數據
有了前面創建的數據庫聯接就可以從數據庫中讀取數據了。
讀取數據代碼如下:
//讀取數據函數,參數爲需要統計的年份,返回DataSet
DataSet ReadData(string Year)
{
//創建DataSet
DataSet dsIncome = new DataSet();
//設置存儲過程名
string SpName = "sp_SelectIncome";
//創建Sql命令
SqlCommand IncomeCmd = new SqlCommand(SpName,MyConnection);
//設定數據庫命令類型爲存儲過程
IncomeCmd.CommandType = CommandType.StoredProcedure;
//打開數據庫聯接
MyConnection.Open();
//創建並設定存儲過程參數
SqlParameter IncomeYear = new SqlParameter("@year",SqlDbType.Int,4);
IncomeYear.Value=Convert.ToInt16(Year);
//爲Sql命令添加參數
IncomeCmd.Parameters.Add(IncomeYear);
//創建Sql數據橋接器
SqlDataAdapter adapter = new SqlDataAdapter(SpName,MyConnection);
//指定橋接器Sql命令
adapter.SelectCommand = IncomeCmd;
//填充DataSet
adapter.Fill(dsIncome,"Income");
//關閉數據庫聯接
MyConnection.Close();
}
數據顯示
使用ReadData方法讀出數據,接下來就是顯示數據了。顯示數據同樣需要兩個步驟。
● 處理數據庫讀出的數據
由於從數據庫讀出的數據不能完全滿足顯示的要求,有可能某個月份沒有交易,那麼返回的DataSet中就不會包含該月的數據。但顯示時需要所有月份的數據。所以直接顯示數據之前先要對數據進行加工。代碼如下:
//創建存儲數據的數組,MyMonthIncome存放每月數據,MyMonthName存放月份縮寫
int[] MyMonthIncome = new int[12];
string[] MyMonthName = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

//聲明存放顯示用字符串的變量,strMonthName存放月份信息,strMonthIncome存放數據
string strMonthName = "";
string strMonthIncome = "";
//對存在數據的月份將數據保存在MyMonthName
for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++)
{
MyMonthIncome[Convert.ToInt16(dsIncome.Tables["Income"].Rows[i][1])-1] = Convert.ToInt16(dsIncome.Tables["Income"].Rows[i][0]);
}
//用已有的數據來生成圖表顯示所需的字符串
for(int i=0;i< 12;i++)
{
strMonthName += MyMonthName[i]+'/t';
strMonthIncome += MyMonthIncome[i].ToString()+'/t';
}
● 使用Office Web Components顯示數據
經過上一步驟,圖表顯示所需的字符串已經放入了strMonthName和strMonthIncome中,下面使用18.2節中關於Office Web Components的知識就可以大功告成了。需要注意的是在生成圖片後使用了PlaceHolder的.Controls屬性的Add方法將動態生成的<img>標籤放入頁面。爲了方便後面的使用,將顯示數據的代碼寫爲函數。代碼如下:
private void MakeLineChart(string Year)
{
//使用ReadData函數讀出數據
DataSet dsIncome = ReadData(Year);
//以下插入處理數據庫讀出的數據部分的代碼,不再重複
//….上一步驟中處理數據庫讀出數據代碼

//創建ChartSpace對象來放置圖表
OWC.ChartSpace mySpace = new OWC.ChartSpaceClass ();
//在ChartSpace對象中添加圖表,Add方法返回chart對象
OWC.WCChart myChart = mySpace.Charts.Add (0);

//指定圖表的類型爲線性圖
myChart.Type = OWC.ChartChartTypeEnum.chChartTypeLine;
//指定圖表是否需要圖例
myChart.HasLegend = true;
//給定標題
myChart.HasTitle = true;
myChart.Title.Caption= ddlYear.SelectedItem.Text + "月收入圖";
//給定x,y軸的圖示說明
myChart.Axes[0].HasTitle = true;
myChart.Axes[0].Title.Caption = "萬元";
myChart.Axes[1].HasTitle = true;
myChart.Axes[1].Title.Caption = "月份";
//添加一個series
myChart.SeriesCollection.Add(0);
//給定series的名字
myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimSeriesNames,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strSeriesName);
//給定分類
myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories,
+ (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strCategory);
//給定值
myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues,
(int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strValue);
//輸出成GIF文件.
string strAbsolutePath = (Server.MapPath(".")) + @"/images/tempFile.gif";
mySpace.ExportPicture(strAbsolutePath, "GIF", 700, 350);
//創建GIF文件的相對路徑.
string strRelativePath = "./images/tempFile.gif”
//生成顯示圖片的<img>標籤
string strImageTag = "<IMG SRC='" + strRelativePath + "'/>";
//把圖片添加到placeholder.
ChartPlaceHolder.Controls.Add(new LiteralControl(strImageTag));
18.3.3.3 按鈕點擊事件
有了前面的MakeLineChart函數,在aspx頁面的設計模式下雙擊btnSumbit創建按鈕點擊事件。修改代碼如下:
private void btnSubmit_Click(object sender, System.EventArgs e)
{
MakeLineChart(ddlYear.SelectedItem.Text);
}
至此,公司盈利狀況統計功能完全實現,運行結果如圖18-16:
        
         圖18-16 公司盈利狀況統計效果
公司收入分塊圖
上一節介紹了Office Web Components的柱狀圖的使用,實現了對公司盈利狀況統計。本節將通過公司收入分塊圖的實現來介紹Office Web Components中餅裝圖的使用。
數據庫設計
爲了實現公司收入分塊圖,爲T_Deal表增添交易類別字段。擴充後的T_Deal表如下:
表名 T_Deal 別名 交易表
表項      說明   類型     是否可空
DealTime   交易時間  DateTime     否
DealIncome  交易金額  int       否
DealContent  交易內容  Varchar(50)   否
DealObject  交易對象  Varchar(20)   是
DealCategory 交易類別  Varchar(20)   否
Comment     備註   Varchar(50)   是
按照新表的格式重新在SqlServer中創建表。添加樣例數據供程序使用。並且創建如下存儲過程實現公司收入分塊統計。
CREATE PROCEDURE sp_SelectCategory
@year int
AS

Select sum(DealCount),DealCategory From T_Deal
where DATEPART(yy,DealTime)=@year
Group By DealCategory
GO
該存儲過程選擇交易時間的年份與輸入參數@year相等的數據,並將選擇得到的數據按交易類別分組。返回每組交易金額的總和以及該組的交易類別。
界面設計
爲了簡便同時利用已有成果,在現有的基礎上修改無疑是最好的選擇。因此,本節的程序直接在上一節的程序上修改。在原有界面上添加一個DropDownList來選擇不同的圖表內容。新的界面如圖18-17:
      
         圖18-17 公司收入分佈界面
新增的DropDownList屬性設置爲Id=ddlChartType,併爲其添加Item
<asp:ListItem Value="Income">公司盈利狀況</asp:ListItem>
<asp:ListItem Value="Category">公司收入分塊圖</asp:ListItem>
代碼實現
在完成了上面的界面設計後,就要進入後臺代碼的編寫了。由於是在上一節的基礎上,所以只需增加新功能。
數據讀入
由於已經有了創建數據庫聯接部分,下面只需要讀出數據即可。數據讀入部分代碼與上一節的代碼相似,不同之處只是所調用的存儲過程不同,爲了簡化代碼,修改ReadData函數,爲其增加參數SpName 指定調用的存儲過程。將原有程序中聲明SpName的語句刪除即可。
//讀取數據函數,參數Yesr爲需要統計的年份SpName爲調用存儲過程名,返回DataSet
DataSet ReadData(string Year,string SpName)
{
//創建DataSet
DataSet dsIncome = new DataSet();
//設置存儲過程名,通過新增參數完成,將此句去除
//string SpName = "sp_SelectIncome";
//以下部分不做修改,不再重複

}
注意:修改ReadData函數後,在上一節MakeLineChart函數中調用ReadData的代碼需要爲其增加參數。
private void MakeLineChart(string Year)
{
//使用ReadData函數讀出數據
DataSet dsIncome = ReadData(Year,“sp_SelectIncome”);
//以下部分不做修改

}
數據顯示
使用ReadData方法讀出數據,接下來就是顯示數據了。顯示數據的代碼也只需對上一節代碼做部分修改即可。聲明繪製分類收入的函數,將MakeLineChart函數內容複製並修改如下:
private void MakePieChart(string Year)
{
//使用ReadData函數讀出數據
DataSet dsCategory = ReadData(Year);
//創建存儲數據的數組,MyCategory存放類別數據,MyMonthName存放類別名稱
int[] MyCategory = new int[dsIncome.Tables["Income"].Rows.Count];
string[] MyCategoryName = new string[dsIncome.Tables["Income"].Rows.Count];

//聲明存放顯示用字符串的變量,strMonthName存放月份信息,strMonthIncome存放數據
string strCategoryName = "";
string strCategory = "";
//聲明總收入,用來計算各分類收入百分比
int IncomeSum = 0;
//將數據放入數組,同時計算總收入
for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++)
{
MyCategory[i] = Convert.ToInt16(dsIncome.Tables["Income"].Rows[i][0]);
MyCategoryName[i] = Convert.ToString(dsIncome.Tables["Income"].Rows[i][1]);
IncomeSum += MyCategory[i];
}
//用已有的數據來生成圖表顯示所需的字符串
for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++)
{
//計算出各分類所佔百分比
int PercentCategory= 100*MyCategory[i]/IncomeSum;
strCategory += MyCategoryName[i]+" "+PercentCategory.ToString()+ "%"+'/t';
strValue += MyCategory[i].ToString()+'/t';
}
//下面代碼與上一節基本相同不再重複
//僅給出需要修改的部分

//指定圖表的類型爲線性圖 改爲餅圖
myChart.Type = OWC.ChartChartTypeEnum.chChartTypePie;
//指定圖表是否需要圖例
myChart.HasLegend = true;
//給定標題
myChart.HasTitle = true;
myChart.Title.Caption= ddlYear.SelectedItem.Text + "收入圖";
//給定x,y軸的圖示說明 ,去掉XY軸圖示說明部分
/*
myChart.Axes[0].HasTitle = true;
myChart.Axes[0].Title.Caption = "萬元";
myChart.Axes[1].HasTitle = true;
myChart.Axes[1].Title.Caption = "月份";
*/

}
18.3.3.3 按鈕點擊事件
由於增加了新功能,按鈕點擊的代碼修改如下:
private void btnSubmit_Click(object sender, System.EventArgs e)
{
//根據ddlChartType的選項判斷執行的內容
if(ddlChartType.SelectedItem.Value=="Income")
MakeLineChart(ddlYear.SelectedItem.Text); //顯示公司盈利統計
else if(ddlChartType.SelectedItem.Value=="Category")
MakePieChart(ddlYear.SelectedItem.Text);//顯示收入分佈
}
至此,公司盈利狀況統計功能完全實現,運行後選擇收入分佈點擊確定按鈕。結果如圖18-18:
       
        圖18-18 公司收入分塊圖效果
報表產出
前面的幾個小節完成了對數據的統計並以圖表的形式呈現給用戶,使用戶能夠一目瞭然的獲取所需信息。這一節將把統計結果以Excel報表的形式輸出,以免用戶提交報表時手工輸入的麻煩,提高工作效率。
報表產出主要使用了Office Web Components的Spreadsheet控件。利用該控件創建並編輯數據表格,並將最終結果輸出到Excel報表。步驟如下:
● Step1創建SpreadsheetClass對象,用來放置數據表格
類似於Chart控件中的ChartSpace,Spread控件中也需要創建一個放置SpreadsheetClass的對象作爲單個表的容器。
SpreadsheetClass exl = new SpreadsheetClass();
● Step2利用SpreadsheetClass的ActiveSheet獲得當前處於活動狀態的表格
一個SpreadsheetClass對象就相當於一個運行中的Excel,通過其ActiveSheet屬性能夠得到當前處於活動狀態的表格。一個Worksheet對象就相當於Excel中的一張表格。將SpreadsheetClass對象的ActiveSheet屬性賦值給Worksheet對象。就可以在後面的代碼中對錶格進行操作了。
OWC.Worksheet ws = exl.ActiveSheet;
● Step3 編輯表格
編輯表格使用的是Worksheet對象的Cells屬性。Cells屬性就代表着表格中的每個單元格。使用Cells[row,col]的格式引用,row表示行號,col表示列號。需要注意的是行號和列號都是從1開始的,而不是像C#的數組是從0開始。例如Cells[2,2]就表示表格的第二行,第二列的單元格。下面是產生盈利狀況統計報表的編輯表格代碼(該段代碼添加在MakePieChart函數末尾,其中的變量延用之前的聲明):
//爲表格設定標題
ws.Cells[1, 1] = "收入(萬元)";
ws.Cells[1,2] = "類別";
ws.Cells[1,3] = "所佔比重";
//將數據寫入表格
for(int i=0;i<dsIncome.Tables[0].Rows.Count;i++)
{
ws.Cells[i+2,1] = MyCategory[i].ToString();
ws.Cells[i+2,2] = MyCategoryName[i];
int Percent = MyMonthIncome[i]*100/IncomeSum;
ws.Cells[i+2,3] = Percent.ToString() + "%";
}
//將總收入寫入表格
ws.Cells[dsIncome.Tables[0].Rows.Count + 2,1] = IncomeSum.ToString();
ws.Cells[dsIncome.Tables[0].Rows.Count + 2,2] = "總和";
ws.Cells[dsIncome.Tables[0].Rows.Count + 2,3] = "100%";
Step4 導出表格
導出表格使用Worksheet對象的Export方法,將表格導出爲Excel文件即可。考慮到可能出現異常,使用了try,catch來捕獲可能出現的異常,輸出錯誤信息。
try
{
//輸出Excel報表到服務器文件系統
ws.Export(Server.MapPath(" ") + @"/Excel/report.xls", OWC.SheetExportActionEnum.ssExportActionNone);
}
catch
{
//錯誤時輸出錯誤提示
Info.Text = "保存報表錯誤,請與管理員聯繫";
}
將上述代碼添加到MakePieChart函數的末尾,重新運行,在工程所在文件夾下的子Excel目錄中就會有report.xls文件。其結果如圖18-19。
       
        圖18-19 生成報表結果圖
小結
這一章先對ASP.NET中生成統計圖表進行了介紹,然後對GDI+與Office Web Components的使用進行了詳細說明,爲後面做好了知識儲備。隨後利用公司盈利狀況統計和公司收入分塊圖兩個實例詳細的介紹瞭如何利用Office Web Components與數據庫結合繪製統計圖表以及生成報表。
通過本章的學習,讀者對於.NET中統計報表的生成有了深刻的理解,相信精美、清晰的報表一定會爲成爲Web程序的亮點。

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章