在Web程序開(kāi)發(fā)中,,圖形和圖表是很好的數(shù)據(jù)表現(xiàn)形式,。往往是表格中的大量數(shù)據(jù)讓用戶(hù)產(chǎn)生無(wú)法處理,無(wú)從獲取所需要的信息,。而以圖表方式提供數(shù)據(jù)的話(huà)就可以達(dá)到簡(jiǎn)單清爽,,簡(jiǎn)單易懂并且一目了然的效果。利用圖表,,管理人員可以方便的掌握銷(xiāo)售與生產(chǎn)數(shù)據(jù),,從而做出相應(yīng)的判斷。 在ASP.NET Web程序中,,生成圖表有以下的選擇: ● ASP.Net內(nèi)建的圖形庫(kù)(GDI+,位于System.Drawing 命名空間) 使用簡(jiǎn)單的圖形,,GDI+能夠創(chuàng)建餅圖、柱狀圖、線性圖,。但是這種方法過(guò)于底層,,不適于創(chuàng)建復(fù)雜的圖形。 ● 各種ASP.NET圖表控件 網(wǎng)上有一些ASP.NET的圖表控件,,但許多控件非常昂貴,,而且與最常用的圖表應(yīng)用Excel差別很大。 ● Office Web Components Microsoft Office Web Components 包含在 Microsoft Office 2000 中,。它們是用于向 Web 頁(yè)添加電子表格,、圖表和數(shù)據(jù)處理功能的 ActiveX 控件的集合??梢灾苯釉跒g覽器中處理數(shù)據(jù),,并以圖表的形式顯示數(shù)據(jù)。由于其基于Office的強(qiáng)大功能,,以及與Office相同的用戶(hù)界面,,無(wú)疑是ASP.NET中圖表生成的明智選擇。 本章主要包括以下幾個(gè)方面內(nèi)容: ● 基于GDI+的圖表生成,。 ● 基于Office Web Components的圖表生成,。 ● 基于Office Web Components的報(bào)表生成。 經(jīng)過(guò)本章的學(xué)習(xí),,將掌握ASP.NET中統(tǒng)計(jì)圖表的實(shí)現(xiàn),,利用圖表將網(wǎng)站的數(shù)據(jù)完美呈現(xiàn)給用戶(hù)。 方案設(shè)計(jì) 本節(jié)分別介紹GDI+與Office Web Components的具體使用,,為后面的章節(jié)打下基礎(chǔ),。 使用GDI+ GDI+ 是 GDI(Windows XP之前版本提供的圖形設(shè)備接口)的后續(xù)版本。GDI+ 是一種應(yīng)用程序編程接口 (API),,負(fù)責(zé)在屏幕和打印機(jī)上顯示信息,。 在ASP.NET中,利用GDI+可以創(chuàng)建簡(jiǎn)單的柱狀圖和餅圖,。 ASP.NET頁(yè)面GDI+圖像使用 在完整的生成柱狀圖和餅圖之前,,先從簡(jiǎn)單的ASP.NET頁(yè)面圖像使用開(kāi)始。 在System.Draw命名空間中包含了創(chuàng)建,、編輯圖像的所有類(lèi),。創(chuàng)建圖像時(shí),主要使用Bitmap類(lèi)和Graphics類(lèi),。為了便于理解,,可以把Bitmap類(lèi)想象成畫(huà)板,Graphics類(lèi)想象成畫(huà)筆,。Bitmap類(lèi)主要用于創(chuàng)建畫(huà)板以及在完成后圖像的保存,。Graphics類(lèi)主要用來(lái)繪制圖像,、圖形和線條。 首先使用下面的代碼創(chuàng)建畫(huà)板,。(本小節(jié)所有代碼需要添加System.Drawing命名空間與System.Drawing.Image命名空間) Bitmap myPalette = new Bitmap(600, 400); //創(chuàng)建600*400的畫(huà)板 有了畫(huà)板,,還需要?jiǎng)?chuàng)建Graphics類(lèi)的實(shí)例來(lái)創(chuàng)建畫(huà)筆,指定畫(huà)板,。代碼如下 Graphics myGraphics = Graphics.FromImage(myPalette); 有了畫(huà)筆和畫(huà)板,,只要使用Graphics類(lèi)中的各種方法在畫(huà)板上繪制圖像、圖形和線條就可以了,。 Graphics類(lèi)中的方法分為兩類(lèi):繪制方法與填充方法,。例如,DrawRectangle方法與FillRectangle方法,。繪制方法僅僅繪制出圖形的輪廓,,而填充方法繪制出圖形的輪廓同時(shí)填充圖形的內(nèi)部。 下面的代碼繪制了簡(jiǎn)單的圖形: int width=150,height=50; // 創(chuàng)建黑色背景橢圓 myGraphics.FillEllipse(new SolidBrush(Color.Black), 300, 150, width, height); // 創(chuàng)建藍(lán)色背景橢圓 myGraphics.FillEllipse(new SolidBrush(Color.LightBlue), 300, 150, width - 10, height - 10); // 創(chuàng)建輸出文本 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); 圖已經(jīng)畫(huà)好了,,只剩下將圖保存下來(lái),。要將保存的圖在網(wǎng)頁(yè)中顯示,可以在下面兩種方式中任選其一: ● 將圖像保存在服務(wù)器的文件系統(tǒng)中,,使用HTML的<img>標(biāo)記來(lái)顯示。 ● 直接將圖像的二進(jìn)制流輸出到Response對(duì)象的輸出流,。 兩種方式各有千秋,。第一種方式適合于創(chuàng)建不需要變動(dòng)的圖片(例如網(wǎng)站廣告圖片),能夠創(chuàng)建一次,,滿(mǎn)足今后的所有要求,。但會(huì)在服務(wù)器端保留下臨時(shí)文件。第二種方式適用于動(dòng)態(tài)的創(chuàng)建圖片供頁(yè)面顯示,,不能滿(mǎn)足今后的需要,,卻也不會(huì)留下臨時(shí)文件。 下面分別寫(xiě)出這兩種方式的代碼: ● 保存文件方式代碼: 保存文件方式首先需要在Aspx文件中添加<Img>標(biāo)記 <!-- 指定顯示文件為tmpFile.jpg --> <img src = “tmpFile.jpg”> 然后在代碼中保存文件即可: //將文件保存為當(dāng)前頁(yè)面所在目錄下的tmpFile.jpg myPalette.Save(Server.MapPath("")+@"/tmpFile.jpg",ImageFormat.Jpeg); ● 直接輸出方式代碼: //直接將圖片以二進(jìn)制流的方式輸出到Response對(duì)象的輸出流,。 myPalette.Save(Response.OutputStream, ImageFormat.Jpeg); 將代碼加入頁(yè)面的PageLoad事件中即可得到如圖18-1效果,。
圖18-1 GDI+圖像使用效果 創(chuàng)建柱狀圖 在知道了如何使用GDI+創(chuàng)建簡(jiǎn)單圖像并顯示到頁(yè)面后,創(chuàng)建復(fù)雜一些的柱狀圖就非常自然了,。 使用簡(jiǎn)單的FillRectangle,,DrawRectangle,DrawString方法,,即可實(shí)現(xiàn)基本的柱狀圖,。代碼如下: //初始化Bitmap類(lèi)實(shí)例與Graphics類(lèi)實(shí)例準(zhǔn)備畫(huà)圖 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); // 設(shè)定顯示數(shù)據(jù) string [] DataName = {"Jan","Feb","Mar","Apr","May","Jun"}; int [] Data = {100,20,50,60,240,20}; //設(shè)定顯示顏色 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); //繪制柱圖上方數(shù)據(jù) myGraphics.DrawString(Data[i].ToString(), new Font("宋體", 9), Brushes.Black, new PointF((i*40)+30,300-Data[i]-20)); //繪制柱圖下標(biāo) myGraphics.DrawString(DataName[i], new Font("宋體", 9), Brushes.Black, new PointF((i*40)+30,320)); } //輸出圖像 myPalette.Save(Response.OutputStream, ImageFormat.Jpeg); // 清除所用繪圖對(duì)象 myGraphics.Dispose(); myPalette.Dispose(); 將上述代碼寫(xiě)入頁(yè)面CodeBehind文件的PageLoad事件中即可看到如圖18-2效果:
圖18-2 GDI+柱狀圖效果 使用Office Web Components Office Web Components是用于向 Web 頁(yè)添加電子表格、圖表和數(shù)據(jù)處理功能的 ActiveX控件的集合,。 利用Office Web Components可以方便的來(lái)繪制簡(jiǎn)單的柱狀圖與餅圖,。不必像在GDI+中需要考慮畫(huà)圖的細(xì)節(jié),。 使用Office Web Components要求 使用Office Web Components需要系統(tǒng)中裝有Office2000以上版本。在工程的引用中添加Office Web Components即可,。 具體步驟如下: 在解決方案資源管理器的引用文件夾上單擊鼠標(biāo)右鍵選擇添加引用,,在出現(xiàn)的添加引用對(duì)話(huà)框中選擇COM標(biāo)簽,選擇Microsoft Office Web Components,,雙擊選中,,點(diǎn)擊確定即可。圖18-3,、18-4顯示了該過(guò)程,。
圖18-3 添加引用 圖18-4 添加Office Web Components引用 使用Office Web Components繪制柱狀圖 使用Office Web Components繪制圖表不同于直接使用GDI+,主要的工作從繪圖的細(xì)節(jié)轉(zhuǎn)移到對(duì)于圖表的設(shè)置,。步驟如下: ● Step1 創(chuàng)建ChartSpace對(duì)象來(lái)放置圖表 ChartSpace是用來(lái)放置圖表的類(lèi),,圖表完成后用它來(lái)輸出。 OWC.ChartSpace objCSpace = new OWC.ChartSpaceClass (); ● Step2 使用ChartSpace對(duì)象的Add方法創(chuàng)建圖表 ChartSpace的Add方法創(chuàng)建圖表,,參數(shù)表示所創(chuàng)建圖表的索引,。 OWC.WCChart objChart = objCSpace.Charts.Add (0); ● Step3 指定圖表的類(lèi)型 通過(guò)設(shè)定Chart類(lèi)對(duì)象的Type屬性來(lái)指定圖表的類(lèi)型。 objChart.Type = OWC.ChartChartTypeEnum.chChartTypeColumnClustered; 本例創(chuàng)建柱狀圖,,選擇了chChartTypeColunmClustered類(lèi)型,。 其他的類(lèi)型包括:chChartTypeArea 面積圖、chChartTypeBarClustered 條形圖,、chChartTypePie 餅圖,、chChartType RadarLine 雷達(dá)線圖、chChartTypeSmoothLine 平滑曲線圖,、chChartTypeDoughnut 環(huán)形圖等等,。 圖18-5至18-10顯示了部分圖表的簡(jiǎn)單實(shí)例。
圖18-5 曲線圖 圖18-6 條形圖 圖18-7 面積圖
圖18-8 環(huán)形圖 圖18-9 餅圖 圖18-10 雷達(dá)圖 ● Step4 設(shè)定圖示說(shuō)明 圖示說(shuō)明主要包括圖例(用顏色表示數(shù)據(jù)類(lèi)型),、圖題(圖表的標(biāo)題),、XY軸的數(shù)據(jù)說(shuō)明(一般用來(lái)說(shuō)明各軸上的數(shù)據(jù)單位)。設(shè)定代碼如下: //指定圖表是否需要圖例 objChart.HasLegend = true;
//給定標(biāo)題 objChart.HasTitle = true; objChart.Title.Caption= "上半年月收入圖";
//給定x,y軸的圖示說(shuō)明 objChart.Axes[0].HasTitle = true; objChart.Axes[0].Title.Caption = "萬(wàn)元"; objChart.Axes[1].HasTitle = true; objChart.Axes[1].Title.Caption = "月份"; ● Step5 添加數(shù)據(jù) 添加數(shù)據(jù)主要設(shè)定Chart類(lèi)對(duì)象的SeriesCollection屬性,。首先使用SeriesCollection的Add方法創(chuàng)建一組數(shù)據(jù),。然后使用SetData方法具體添加數(shù)據(jù)。代碼如下: (注意:數(shù)據(jù)的格式是以'/t'間隔的字符串) //添加一組圖表數(shù)據(jù) objChart.SeriesCollection.Add(0); //給定該組數(shù)據(jù)的名字 objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimSeriesNames, + (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,”上半年收入”); //給定數(shù)據(jù)分類(lèi) objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories, + (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, "Jan"+'/t'+"Feb"+'/t'+"Mar"+'/t'+"Apr"+'/t'+"May"+'/t'+"Jun"+'/t' ); //給定數(shù)據(jù)值 objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimValues, (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, "100"+'/t'+"20"+'/t'+"50"+'/t'+"60"+'/t'+"240"+'/t'+"20"+'/t'); ● Step6 顯示數(shù)據(jù) 顯示數(shù)據(jù)是使用Chart類(lèi)對(duì)象的ExportPicture方法將生成的圖表創(chuàng)建為圖片,,然后顯示的,。代碼如下: //輸出成GIF文件,參數(shù)為文件名,、格式,、圖片大小 objCSpace.ExportPicture(Server.MapPath("")+@"/tmpFile.gif", "GIF", 400, 300); //從生成的圖片創(chuàng)建Bitmap對(duì)象,輸出到Response輸出流 Bitmap myPalette = new Bitmap(Server.MapPath("")+@"/tmpFile.gif",true); myPalette.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Gif); 經(jīng)過(guò)了以上的步驟,,將代碼輸入頁(yè)面的PageLoad事件代碼段 中,,運(yùn)行程序就可以得到如圖18-11效果,。
圖18-11 Office Web Components柱狀圖示例 使用Office Web Components繪制餅圖 繪制餅圖與繪制柱狀圖的區(qū)別不是很大,需要注意的是餅圖沒(méi)有XY軸,,所以不能設(shè)置XY軸的圖示說(shuō)明,。在繪制柱狀圖的代碼上去掉關(guān)于XY軸圖示說(shuō)明的代碼即可。 完整代碼如下: //初始化圖表數(shù)據(jù) string [] DataName = {"Jan","Feb","Mar","Apr","May","Jun"}; int [] Data = {100,20,50,60,240,20}; //聲明存儲(chǔ)數(shù)據(jù)分類(lèi)和數(shù)據(jù)值的字符串 string strDataName = ""; string strData = ""; //循環(huán)按格式生成存儲(chǔ)數(shù)據(jù)分類(lèi)與數(shù)據(jù)值的字符串 for(int i=0;i< Data.Length;i++) { strCategory += DataName[i]+'/t'; strValue += Data[i].ToString()+'/t'; } //創(chuàng)建ChartSpace對(duì)象來(lái)放置圖表 OWC.ChartSpace objCSpace = new OWC.ChartSpaceClass ();
//在ChartSpace對(duì)象中添加圖表,,Add方法返回chart對(duì)象 OWC.WCChart objChart = objCSpace.Charts.Add (0);
//指定圖表的類(lèi)型為餅圖 objChart.Type = OWC.ChartChartTypeEnum.chChartTypePie; //指定圖表是否需要圖例 objChart.HasLegend = true; //給定標(biāo)題 objChart.HasTitle = true; objChart.Title.Caption= "上半年月收入圖";
//添加一個(gè)series objChart.SeriesCollection.Add(0);
//給定數(shù)據(jù)分類(lèi) objChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimCategories, + (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral,strDataName);
//給定數(shù)據(jù)值 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); 將上述代碼寫(xiě)入頁(yè)面文件的PageLoad事件處理代碼中,,運(yùn)行得到如圖18-12效果。
圖18-12 Office Web Components餅圖示例 公司盈利狀況統(tǒng)計(jì) 前面介紹了Office Web Components的情況,,本節(jié)將通過(guò)公司盈利狀況統(tǒng)計(jì)來(lái)介紹Office Web Components柱狀圖在具體實(shí)例中的使用,。 數(shù)據(jù)庫(kù)設(shè)計(jì) 為了實(shí)現(xiàn)公司盈利狀況統(tǒng)計(jì)。首先,,需要設(shè)計(jì)相關(guān)的數(shù)據(jù)庫(kù)表,。在實(shí)際情況中,公司的盈利就是收入的總和與支出的總和之差,。而每筆收入與支出都是在一次交易中完成的,。基于以上考慮,,同時(shí)為了實(shí)現(xiàn)簡(jiǎn)單,。設(shè)計(jì)數(shù)據(jù)庫(kù)表單如下: 表名 T_Deal 別名 交易表 表項(xiàng) 說(shuō)明 類(lèi)型 是否可空 DealTime 交易時(shí)間 DateTime 否 DealIncome 交易金額 int 否 DealContent 交易內(nèi)容 Varchar(50) 否 DealObject 交易對(duì)象 Varchar(20) 是 Comment 備注 Varchar(50) 是 注意:為了簡(jiǎn)單起見(jiàn),用交易金額統(tǒng)一表示收入與支出,。用正數(shù)的交易金額表示收入,,負(fù)數(shù)的交易金額表示支出。這樣計(jì)算盈利時(shí)只需將交易金額求和即可,。 按照上表的格式在SqlServer中創(chuàng)建表。添加樣例數(shù)據(jù)供程序使用,。 然后創(chuàng)建下面的存儲(chǔ)過(guò)程來(lái)實(shí)現(xiàn)公司盈利狀況的統(tǒng)計(jì),。 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 該存儲(chǔ)過(guò)程選擇交易時(shí)間的年份與輸入?yún)?shù)@year相等的數(shù)據(jù),并將選擇得到的數(shù)據(jù)按交易時(shí)間的月份分組,。返回每組交易金額的總和以及該組的交易月份,。 界面設(shè)計(jì) 新建Web工程WebChart。將WebForm1.aspx改名為OWCChart.aspx,。同時(shí),,將其代碼文件中的類(lèi)名改為OWCChart。 界面如圖18-13所示:
圖18-13 公司盈利統(tǒng)計(jì)界面 該界面主要包括兩部分:一個(gè)PlaceHolder控件用來(lái)放置生成的圖表構(gòu)成顯示圖表部分,。一個(gè)用來(lái)選擇統(tǒng)計(jì)年份的DropDownList控件,,一個(gè)用來(lái)確定生成圖表的Button控件,一個(gè)用來(lái)顯示錯(cuò)誤信息的Label控件構(gòu)成了圖表的生成部分,。 同樣為了界面整潔使用Table將所用控件放在表格中,。按照?qǐng)D18-13安排好界面后就可以為控件設(shè)置屬性了,,主要包括以下幾個(gè)方面的設(shè)置: ● PlaceHolder控件的設(shè)置 PlaceHolder控件在本程序中用于放置生成的圖表,只需設(shè)置其Id屬性為ChartPlaceHolder即可,。 ● DropDownList控件的設(shè)置 DropDownList控件在本程序中用于選擇統(tǒng)計(jì)年份,,設(shè)置其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控件的設(shè)置 Button控件設(shè)置Id屬性為btnSumbit,Text屬性為“確定”即可,。 ● Label控件的設(shè)置 Label控件設(shè)置Id屬性為Info即可。 代碼實(shí)現(xiàn) 在完成了上面的界面設(shè)計(jì)后,,就要進(jìn)入后臺(tái)代碼的編寫(xiě)了,。下面就將分模塊介紹各部分功能的代碼實(shí)現(xiàn)。 數(shù)據(jù)讀入 為了顯示公司盈利狀況統(tǒng)計(jì),,首先需要將統(tǒng)計(jì)的結(jié)果從數(shù)據(jù)庫(kù)中讀入,。讀入數(shù)據(jù)的代碼包括以下兩部分。 ● 創(chuàng)建數(shù)據(jù)庫(kù)聯(lián)接 為了方便程序的配置,,將數(shù)據(jù)庫(kù)聯(lián)接字段保存在Web.Config文件中,。如此一來(lái),在需要修改數(shù)據(jù)庫(kù)聯(lián)接字段時(shí)只需要修改Web.Config文件即可,,不需要修改程序代碼,,重新編譯。 在Web.Config文件中的<configuration>字段中加入如下代碼: <appSettings> <add key="ConnectStr" value="server=localhost;uid=yourid;pwd=yourpas;database=Info;"/> </appSettings> 其中l(wèi)ocalhost要改為自己的數(shù)據(jù)庫(kù)服務(wù)器名,,uid,pwd分別為數(shù)據(jù)庫(kù)用戶(hù)id和密碼,,database為數(shù)據(jù)庫(kù)名。 設(shè)置好聯(lián)接字段后就可在代碼中對(duì)其進(jìn)行引用了,。 主要使用AppSettingReader對(duì)象的GetValue方法獲取”ConnectStr”字段信息,,該方法需要兩個(gè)參數(shù),第一個(gè)指定要引用的字段,,第二個(gè)參數(shù)指定需要的類(lèi)型,。返回一個(gè)Object類(lèi)型的變量。需要使用Convert的ToString方法將其轉(zhuǎn)換為字符串類(lèi)型 引用代碼如下: //全局?jǐn)?shù)據(jù)庫(kù)聯(lián)接 System.Data.SqlClient.SqlConnection MyConnection; private void Page_Load(object sender, System.EventArgs e) { // 在此處放置用戶(hù)代碼以初始化頁(yè)面 if(Page.IsPostBack==false) // 頁(yè)面首次加載時(shí) {
//創(chuàng)建Web.Config文件應(yīng)用程序設(shè)置字段讀取對(duì)象 System.Configuration.AppSettingsReader ConnectionString = new System.Configuration.AppSettingsReader(); //創(chuàng)建數(shù)據(jù)庫(kù)聯(lián)接 MyConnection = new System.Data.SqlClient.SqlConnection(); //設(shè)置數(shù)據(jù)庫(kù)聯(lián)接的連接字段 MyConnection.ConnectionString = Convert.ToString(ConnectionString.GetValue("ConnectStr",System.Type.GetType("System.String"))); } } ● 利用數(shù)據(jù)庫(kù)聯(lián)接讀取數(shù)據(jù) 有了前面創(chuàng)建的數(shù)據(jù)庫(kù)聯(lián)接就可以從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)了,。 讀取數(shù)據(jù)代碼如下: //讀取數(shù)據(jù)函數(shù),,參數(shù)為需要統(tǒng)計(jì)的年份,返回DataSet DataSet ReadData(string Year) { //創(chuàng)建DataSet DataSet dsIncome = new DataSet(); //設(shè)置存儲(chǔ)過(guò)程名 string SpName = "sp_SelectIncome"; //創(chuàng)建Sql命令 SqlCommand IncomeCmd = new SqlCommand(SpName,MyConnection); //設(shè)定數(shù)據(jù)庫(kù)命令類(lèi)型為存儲(chǔ)過(guò)程 IncomeCmd.CommandType = CommandType.StoredProcedure; //打開(kāi)數(shù)據(jù)庫(kù)聯(lián)接 MyConnection.Open(); //創(chuàng)建并設(shè)定存儲(chǔ)過(guò)程參數(shù) SqlParameter IncomeYear = new SqlParameter("@year",SqlDbType.Int,4); IncomeYear.Value=Convert.ToInt16(Year); //為Sql命令添加參數(shù) IncomeCmd.Parameters.Add(IncomeYear); //創(chuàng)建Sql數(shù)據(jù)橋接器 SqlDataAdapter adapter = new SqlDataAdapter(SpName,MyConnection); //指定橋接器Sql命令 adapter.SelectCommand = IncomeCmd; //填充DataSet adapter.Fill(dsIncome,"Income"); //關(guān)閉數(shù)據(jù)庫(kù)聯(lián)接 MyConnection.Close(); } 數(shù)據(jù)顯示 使用ReadData方法讀出數(shù)據(jù),,接下來(lái)就是顯示數(shù)據(jù)了,。顯示數(shù)據(jù)同樣需要兩個(gè)步驟。 ● 處理數(shù)據(jù)庫(kù)讀出的數(shù)據(jù) 由于從數(shù)據(jù)庫(kù)讀出的數(shù)據(jù)不能完全滿(mǎn)足顯示的要求,,有可能某個(gè)月份沒(méi)有交易,,那么返回的DataSet中就不會(huì)包含該月的數(shù)據(jù),。但顯示時(shí)需要所有月份的數(shù)據(jù)。所以直接顯示數(shù)據(jù)之前先要對(duì)數(shù)據(jù)進(jìn)行加工,。代碼如下: //創(chuàng)建存儲(chǔ)數(shù)據(jù)的數(shù)組,,MyMonthIncome存放每月數(shù)據(jù),MyMonthName存放月份縮寫(xiě) int[] MyMonthIncome = new int[12]; string[] MyMonthName = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
//聲明存放顯示用字符串的變量,,strMonthName存放月份信息,,strMonthIncome存放數(shù)據(jù) string strMonthName = ""; string strMonthIncome = ""; //對(duì)存在數(shù)據(jù)的月份將數(shù)據(jù)保存在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]); } //用已有的數(shù)據(jù)來(lái)生成圖表顯示所需的字符串 for(int i=0;i< 12;i++) { strMonthName += MyMonthName[i]+'/t'; strMonthIncome += MyMonthIncome[i].ToString()+'/t'; } ● 使用Office Web Components顯示數(shù)據(jù) 經(jīng)過(guò)上一步驟,圖表顯示所需的字符串已經(jīng)放入了strMonthName和strMonthIncome中,,下面使用18.2節(jié)中關(guān)于Office Web Components的知識(shí)就可以大功告成了,。需要注意的是在生成圖片后使用了PlaceHolder的.Controls屬性的Add方法將動(dòng)態(tài)生成的<img>標(biāo)簽放入頁(yè)面。為了方便后面的使用,,將顯示數(shù)據(jù)的代碼寫(xiě)為函數(shù),。代碼如下: private void MakeLineChart(string Year) { //使用ReadData函數(shù)讀出數(shù)據(jù) DataSet dsIncome = ReadData(Year); //以下插入處理數(shù)據(jù)庫(kù)讀出的數(shù)據(jù)部分的代碼,不再重復(fù) //….上一步驟中處理數(shù)據(jù)庫(kù)讀出數(shù)據(jù)代碼
//創(chuàng)建ChartSpace對(duì)象來(lái)放置圖表 OWC.ChartSpace mySpace = new OWC.ChartSpaceClass (); //在ChartSpace對(duì)象中添加圖表,,Add方法返回chart對(duì)象 OWC.WCChart myChart = mySpace.Charts.Add (0);
//指定圖表的類(lèi)型為線性圖 myChart.Type = OWC.ChartChartTypeEnum.chChartTypeLine; //指定圖表是否需要圖例 myChart.HasLegend = true; //給定標(biāo)題 myChart.HasTitle = true; myChart.Title.Caption= ddlYear.SelectedItem.Text + "月收入圖"; //給定x,y軸的圖示說(shuō)明 myChart.Axes[0].HasTitle = true; myChart.Axes[0].Title.Caption = "萬(wàn)元"; myChart.Axes[1].HasTitle = true; myChart.Axes[1].Title.Caption = "月份"; //添加一個(gè)series myChart.SeriesCollection.Add(0); //給定series的名字 myChart.SeriesCollection[0].SetData (OWC.ChartDimensionsEnum.chDimSeriesNames, + (int)OWC.ChartSpecialDataSourcesEnum.chDataLiteral, strSeriesName); //給定分類(lèi) 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); //創(chuàng)建GIF文件的相對(duì)路徑. string strRelativePath = "./images/tempFile.gif” //生成顯示圖片的<img>標(biāo)簽 string strImageTag = "<IMG SRC='" + strRelativePath + "'/>"; //把圖片添加到placeholder. ChartPlaceHolder.Controls.Add(new LiteralControl(strImageTag)); 18.3.3.3 按鈕點(diǎn)擊事件 有了前面的MakeLineChart函數(shù),,在aspx頁(yè)面的設(shè)計(jì)模式下雙擊btnSumbit創(chuàng)建按鈕點(diǎn)擊事件。修改代碼如下: private void btnSubmit_Click(object sender, System.EventArgs e) { MakeLineChart(ddlYear.SelectedItem.Text); } 至此,,公司盈利狀況統(tǒng)計(jì)功能完全實(shí)現(xiàn),,運(yùn)行結(jié)果如圖18-16:
圖18-16 公司盈利狀況統(tǒng)計(jì)效果 公司收入分塊圖 上一節(jié)介紹了Office Web Components的柱狀圖的使用,實(shí)現(xiàn)了對(duì)公司盈利狀況統(tǒng)計(jì),。本節(jié)將通過(guò)公司收入分塊圖的實(shí)現(xiàn)來(lái)介紹Office Web Components中餅裝圖的使用,。 數(shù)據(jù)庫(kù)設(shè)計(jì) 為了實(shí)現(xiàn)公司收入分塊圖,為T(mén)_Deal表增添交易類(lèi)別字段,。擴(kuò)充后的T_Deal表如下: 表名 T_Deal 別名 交易表 表項(xiàng) 說(shuō)明 類(lèi)型 是否可空 DealTime 交易時(shí)間 DateTime 否 DealIncome 交易金額 int 否 DealContent 交易內(nèi)容 Varchar(50) 否 DealObject 交易對(duì)象 Varchar(20) 是 DealCategory 交易類(lèi)別 Varchar(20) 否 Comment 備注 Varchar(50) 是 按照新表的格式重新在SqlServer中創(chuàng)建表,。添加樣例數(shù)據(jù)供程序使用。并且創(chuàng)建如下存儲(chǔ)過(guò)程實(shí)現(xiàn)公司收入分塊統(tǒng)計(jì),。 Create PROCEDURE sp_SelectCategory @year int AS
Select sum(DealCount),DealCategory From T_Deal where DATEPART(yy,DealTime)=@year Group By DealCategory GO 該存儲(chǔ)過(guò)程選擇交易時(shí)間的年份與輸入?yún)?shù)@year相等的數(shù)據(jù),,并將選擇得到的數(shù)據(jù)按交易類(lèi)別分組。返回每組交易金額的總和以及該組的交易類(lèi)別,。 界面設(shè)計(jì) 為了簡(jiǎn)便同時(shí)利用已有成果,在現(xiàn)有的基礎(chǔ)上修改無(wú)疑是最好的選擇,。因此,,本節(jié)的程序直接在上一節(jié)的程序上修改。在原有界面上添加一個(gè)DropDownList來(lái)選擇不同的圖表內(nèi)容,。新的界面如圖18-17:
圖18-17 公司收入分布界面 新增的DropDownList屬性設(shè)置為Id=ddlChartType,,并為其添加Item <asp:ListItem Value="Income">公司盈利狀況</asp:ListItem> <asp:ListItem Value="Category">公司收入分塊圖</asp:ListItem> 代碼實(shí)現(xiàn) 在完成了上面的界面設(shè)計(jì)后,就要進(jìn)入后臺(tái)代碼的編寫(xiě)了,。由于是在上一節(jié)的基礎(chǔ)上,,所以只需增加新功能,。 數(shù)據(jù)讀入 由于已經(jīng)有了創(chuàng)建數(shù)據(jù)庫(kù)聯(lián)接部分,下面只需要讀出數(shù)據(jù)即可,。數(shù)據(jù)讀入部分代碼與上一節(jié)的代碼相似,,不同之處只是所調(diào)用的存儲(chǔ)過(guò)程不同,為了簡(jiǎn)化代碼,,修改ReadData函數(shù),,為其增加參數(shù)SpName 指定調(diào)用的存儲(chǔ)過(guò)程。將原有程序中聲明SpName的語(yǔ)句刪除即可,。 //讀取數(shù)據(jù)函數(shù),,參數(shù)Yesr為需要統(tǒng)計(jì)的年份SpName為調(diào)用存儲(chǔ)過(guò)程名,返回DataSet DataSet ReadData(string Year,,string SpName) { //創(chuàng)建DataSet DataSet dsIncome = new DataSet(); //設(shè)置存儲(chǔ)過(guò)程名,,通過(guò)新增參數(shù)完成,將此句去除 //string SpName = "sp_SelectIncome"; //以下部分不做修改,,不再重復(fù) … } 注意:修改ReadData函數(shù)后,,在上一節(jié)MakeLineChart函數(shù)中調(diào)用ReadData的代碼需要為其增加參數(shù)。 private void MakeLineChart(string Year) { //使用ReadData函數(shù)讀出數(shù)據(jù) DataSet dsIncome = ReadData(Year,,“sp_SelectIncome”); //以下部分不做修改 … } 數(shù)據(jù)顯示 使用ReadData方法讀出數(shù)據(jù),,接下來(lái)就是顯示數(shù)據(jù)了。顯示數(shù)據(jù)的代碼也只需對(duì)上一節(jié)代碼做部分修改即可,。聲明繪制分類(lèi)收入的函數(shù),將MakeLineChart函數(shù)內(nèi)容復(fù)制并修改如下: private void MakePieChart(string Year) { //使用ReadData函數(shù)讀出數(shù)據(jù) DataSet dsCategory = ReadData(Year); //創(chuàng)建存儲(chǔ)數(shù)據(jù)的數(shù)組,,MyCategory存放類(lèi)別數(shù)據(jù),MyMonthName存放類(lèi)別名稱(chēng) int[] MyCategory = new int[dsIncome.Tables["Income"].Rows.Count]; string[] MyCategoryName = new string[dsIncome.Tables["Income"].Rows.Count];
//聲明存放顯示用字符串的變量,,strMonthName存放月份信息,,strMonthIncome存放數(shù)據(jù) string strCategoryName = ""; string strCategory = ""; //聲明總收入,用來(lái)計(jì)算各分類(lèi)收入百分比 int IncomeSum = 0; //將數(shù)據(jù)放入數(shù)組,,同時(shí)計(jì)算總收入 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]; } //用已有的數(shù)據(jù)來(lái)生成圖表顯示所需的字符串 for(int i=0;i< dsIncome.Tables["Income"].Rows.Count;i++) { //計(jì)算出各分類(lèi)所占百分比 int PercentCategory= 100*MyCategory[i]/IncomeSum; strCategory += MyCategoryName[i]+" "+PercentCategory.ToString()+ "%"+'/t'; strValue += MyCategory[i].ToString()+'/t'; } //下面代碼與上一節(jié)基本相同不再重復(fù) //僅給出需要修改的部分 … //指定圖表的類(lèi)型為線性圖 改為餅圖 myChart.Type = OWC.ChartChartTypeEnum.chChartTypePie; //指定圖表是否需要圖例 myChart.HasLegend = true; //給定標(biāo)題 myChart.HasTitle = true; myChart.Title.Caption= ddlYear.SelectedItem.Text + "收入圖"; //給定x,y軸的圖示說(shuō)明 ,,去掉XY軸圖示說(shuō)明部分 /* myChart.Axes[0].HasTitle = true; myChart.Axes[0].Title.Caption = "萬(wàn)元"; myChart.Axes[1].HasTitle = true; myChart.Axes[1].Title.Caption = "月份"; */ … } 18.3.3.3 按鈕點(diǎn)擊事件 由于增加了新功能,按鈕點(diǎn)擊的代碼修改如下: private void btnSubmit_Click(object sender, System.EventArgs e) { //根據(jù)ddlChartType的選項(xiàng)判斷執(zhí)行的內(nèi)容 if(ddlChartType.SelectedItem.Value=="Income") MakeLineChart(ddlYear.SelectedItem.Text); //顯示公司盈利統(tǒng)計(jì) else if(ddlChartType.SelectedItem.Value=="Category") MakePieChart(ddlYear.SelectedItem.Text);//顯示收入分布 } 至此,,公司盈利狀況統(tǒng)計(jì)功能完全實(shí)現(xiàn),,運(yùn)行后選擇收入分布點(diǎn)擊確定按鈕。結(jié)果如圖18-18:
圖18-18 公司收入分塊圖效果 報(bào)表產(chǎn)出 前面的幾個(gè)小節(jié)完成了對(duì)數(shù)據(jù)的統(tǒng)計(jì)并以圖表的形式呈現(xiàn)給用戶(hù),,使用戶(hù)能夠一目了然的獲取所需信息,。這一節(jié)將把統(tǒng)計(jì)結(jié)果以Excel報(bào)表的形式輸出,以免用戶(hù)提交報(bào)表時(shí)手工輸入的麻煩,,提高工作效率,。 報(bào)表產(chǎn)出主要使用了Office Web Components的Spreadsheet控件。利用該控件創(chuàng)建并編輯數(shù)據(jù)表格,并將最終結(jié)果輸出到Excel報(bào)表,。步驟如下: ● Step1創(chuàng)建SpreadsheetClass對(duì)象,,用來(lái)放置數(shù)據(jù)表格 類(lèi)似于Chart控件中的ChartSpace,Spread控件中也需要?jiǎng)?chuàng)建一個(gè)放置SpreadsheetClass的對(duì)象作為單個(gè)表的容器,。 SpreadsheetClass exl = new SpreadsheetClass(); ● Step2利用SpreadsheetClass的ActiveSheet獲得當(dāng)前處于活動(dòng)狀態(tài)的表格 一個(gè)SpreadsheetClass對(duì)象就相當(dāng)于一個(gè)運(yùn)行中的Excel,,通過(guò)其ActiveSheet屬性能夠得到當(dāng)前處于活動(dòng)狀態(tài)的表格。一個(gè)Worksheet對(duì)象就相當(dāng)于Excel中的一張表格,。將SpreadsheetClass對(duì)象的ActiveSheet屬性賦值給Worksheet對(duì)象,。就可以在后面的代碼中對(duì)表格進(jìn)行操作了。 OWC.Worksheet ws = exl.ActiveSheet; ● Step3 編輯表格 編輯表格使用的是Worksheet對(duì)象的Cells屬性,。Cells屬性就代表著表格中的每個(gè)單元格,。使用Cells[row,col]的格式引用,row表示行號(hào),,col表示列號(hào),。需要注意的是行號(hào)和列號(hào)都是從1開(kāi)始的,而不是像C#的數(shù)組是從0開(kāi)始,。例如Cells[2,,2]就表示表格的第二行,第二列的單元格,。下面是產(chǎn)生盈利狀況統(tǒng)計(jì)報(bào)表的編輯表格代碼(該段代碼添加在MakePieChart函數(shù)末尾,,其中的變量延用之前的聲明): //為表格設(shè)定標(biāo)題 ws.Cells[1, 1] = "收入(萬(wàn)元)"; ws.Cells[1,2] = "類(lèi)別"; ws.Cells[1,3] = "所占比重"; //將數(shù)據(jù)寫(xiě)入表格 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() + "%"; } //將總收入寫(xiě)入表格 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 導(dǎo)出表格 導(dǎo)出表格使用Worksheet對(duì)象的Export方法,將表格導(dǎo)出為Excel文件即可,??紤]到可能出現(xiàn)異常,使用了try,catch來(lái)捕獲可能出現(xiàn)的異常,,輸出錯(cuò)誤信息,。 try { //輸出Excel報(bào)表到服務(wù)器文件系統(tǒng) ws.Export(Server.MapPath(" ") + @"/Excel/report.xls", OWC.SheetExportActionEnum.ssExportActionNone); } catch { //錯(cuò)誤時(shí)輸出錯(cuò)誤提示 Info.Text = "保存報(bào)表錯(cuò)誤,請(qǐng)與管理員聯(lián)系"; } 將上述代碼添加到MakePieChart函數(shù)的末尾,,重新運(yùn)行,,在工程所在文件夾下的子Excel目錄中就會(huì)有report.xls文件。其結(jié)果如圖18-19,。
圖18-19 生成報(bào)表結(jié)果圖 小結(jié) 這一章先對(duì)ASP.NET中生成統(tǒng)計(jì)圖表進(jìn)行了介紹,,然后對(duì)GDI+與Office Web Components的使用進(jìn)行了詳細(xì)說(shuō)明,為后面做好了知識(shí)儲(chǔ)備,。隨后利用公司盈利狀況統(tǒng)計(jì)和公司收入分塊圖兩個(gè)實(shí)例詳細(xì)的介紹了如何利用Office Web Components與數(shù)據(jù)庫(kù)結(jié)合繪制統(tǒng)計(jì)圖表以及生成報(bào)表,。
|