【基於WinForm+Access區域網共享資料庫的專案總結】之篇二:WinForm開發扇形圖統計和Excel資料匯出
【小記】:最近基於WinForm+Access資料庫完成一個法律諮詢管理系統。本系統要求類似網頁後臺管理效果,並且基於區域網內,完成多客戶端操作同一資料庫,根據許可權不同分別執行不同功能模組。核心模組為級聯統計型別管理、資料庫諮詢資料扇形統計、樹的操作、諮詢資料的管理、手寫分頁、Excel資料的匯出、多使用者操作伺服器資料等。並支援多使用者同時操作,遠端連線資料庫且對資料IP資訊的修改。開發過程中特別對介面的要求和事後多使用者操作顯得略為麻煩。自此,本專案得以完善交付,然後對其進行小結。依舊採用整個框架認識,核心知識逐個梳理分析,以便於二次開發和需要之程式設計師共享。
篇二:WinForm開發扇形圖統計和Excel資料匯出
【開篇】本章概述
開發過程簡介:應客戶需求,在法律諮詢系統中以扇形圖形式進行資料統計。需求如下:(圖表需要統計的資料 各諮詢型別小類的數量、以及佔大類的百分比,可隨意組合生成。例如,(以民事 - 婚姻家庭 - 撫養為例)所有民事的佔總案件的比例,婚姻家庭佔所有民事的比例,撫養佔所有婚姻家庭的比例。)現在核心問題在於兩點,第一、如果單級易於把握,但是多級無限組合似乎有難度;第二、web和wpf等開發都有現成的控制元件或者元件應用經驗,而winfrom的相關控制元件不熟悉;第三、只能通過網上查詢相關資料,具體查詢結果我做個總結,以供需要之人,免得浪費時間。
一、扇形統計圖解決思路:(以下資料中包含扇形圖、餅狀圖、折線圖)
1 下個MSChart控制元件,裡面可以直接用
2 C#編寫的影象:http://www.cnblogs.com/ziyiFly/archive/2008/09/24/1297841.html
3 比較簡潔:http://netdz.blog.163.com/blog/static/2106990252012725104054804/
4 參考:http://jingyan.baidu.com/article/e75aca858b6630142edac6de.html
但是,最終以上思路還沒有解決問題。因為我採用的直接C#程式碼繪製圖片顯示方式,然後圖片pictureBox控制元件中顯示。這樣會出現至上而下流形式的輸出。使得頁面佈局效果很差。最終自己改進後,採用兩個pictureBox控制元件,一個用於輸出圖片流,另一個用於輸出文字流。實現效果如下(三級實現,下面顯示2級的效果,因為後臺核心程式碼基本一致)
程式編寫思路:
1、窗體頁面放置兩個pictureBox控制元件顯示圖片和資料資訊.
2、構造Cartogram統計圖類,然後構造方法,最後講控制元件名和查詢資料文字傳參。Cartogram.CreateTestImage(pictureBox1, pictureBox2, comboBox1.Text);
3、在統計方法中首先模糊查詢獲取總的條目,然後將型別表中所有那列型別資料儲存在陣列中,以便下面遍歷。
public static ArrayList BindB(string type) { ArrayList al = new ArrayList(); string sql = "select * from B_type where aname='" + type + "'"; DataSet ds = MYHelper.SQLHelper.GetSetData(sql); if (ds.Tables[0].Rows.Count > 0) { for (int j = 0; j < ds.Tables[0].Rows.Count; j++) { al.Add(ds.Tables[0].Rows[j]["bname"].ToString()); } } return al; }
4、再進行遍歷陣列,查到每個型別的條目,然後比總數獲取百分比進行在圓圖上比例顯示。到此每個型別所佔比例的統計圖構造完成,那麼怎麼列印數目和百分比?
int childtype = 0; ArrayList coun = new ArrayList(); for (int i = 0; i < a.Count; i++) { //子事件總數 childtype = MYHelper.SQLHelper.ExecuteScalar("Select count(*) From L_consult Where type Like '" + "%" + a[i].ToString() + "%" + "'"); //畫佔扇形圖的比例 objgraphics.FillPie((SolidBrush)colors[i], pierect, currentdegree, Convert.ToSingle(childtype) / Total * 360); currentdegree += Convert.ToSingle(childtype) / Total * 360; coun.Add(childtype); }
5、依舊採用遍歷方式,將上面遍歷的每個型別條目輸出,然後除總數目轉化成百分比。最後例項化兩個圖片物件進行輸出
for (int i = 0; i < a.Count; i++) { kuandu += 20; y += 20; objgraphics1.DrawString(a[i] + "事件: " + (coun[i]), fontlegend, blackbrush, x, kuandu); objgraphics1.FillRectangle((SolidBrush)colors[i], 20, y, 10, 10); objgraphics1.DrawString("所佔比率: " + Convert.ToString((Convert.ToSingle(coun[i]) / Total) * 100) + " %", fontlegend, blackbrush, 200, kuandu); }
6、網頁輸出和窗體輸出的區別?即本程式碼適應於網頁和窗體
網頁輸出圖片流:
Response.ContentType = "image/Jpeg"; objbitmap.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg); objgraphics.Dispose(); objbitmap.Dispose();
窗體輸出圖片流:
pictureBox1.Image = objbitmap;
pictureBox2.Image = objbitmap1;
完整統計圖原始碼:
static string date = DateTime.Now.ToString("yyyy-MM-dd"); public static ArrayList BindA() { ArrayList al = new ArrayList(); string sql = "select * from A_type"; DataSet ds = MYHelper.SQLHelper.GetSetData(sql); if (ds.Tables[0].Rows.Count > 0) { for (int j = 0; j < ds.Tables[0].Rows.Count; j++) { al.Add(ds.Tables[0].Rows[j]["name"].ToString()); } } return al; } public static ArrayList BindB(string type) { ArrayList al = new ArrayList(); string sql = "select * from B_type where aname='" + type + "'"; DataSet ds = MYHelper.SQLHelper.GetSetData(sql); if (ds.Tables[0].Rows.Count > 0) { for (int j = 0; j < ds.Tables[0].Rows.Count; j++) { al.Add(ds.Tables[0].Rows[j]["bname"].ToString()); } } return al; } public static ArrayList BindC(string type) { ArrayList al = new ArrayList(); string sql = "select * from C_type where bname='" + type + "'"; DataSet ds = MYHelper.SQLHelper.GetSetData(sql); if (ds.Tables[0].Rows.Count > 0) { for (int j = 0; j < ds.Tables[0].Rows.Count; j++) { al.Add(ds.Tables[0].Rows[j]["cname"].ToString()); } } return al; } //一級統計圖 public static void CreateTestImage(PictureBox pictureBox1, PictureBox pictureBox2) { ArrayList a = BindA(); //把連線字串指定為一個常量 float Total = MYHelper.SQLHelper.ExecuteScalar("select count(*) from L_consult");//獲取總的條目數 #region //設定字型,fonttitle為主標題的字型 Font fontlegend = new Font("verdana", 9); Font fonttitle = new Font("verdana", 10, FontStyle.Bold); //背景寬 int width = 350; int bufferspace = 15; int legendheight = fontlegend.Height * 12 + bufferspace; //高度 int titleheight = fonttitle.Height + bufferspace; int height = width + legendheight + titleheight + bufferspace;//白色背景高 int pieheight = width; Rectangle pierect = new Rectangle(0, titleheight, width, pieheight); //加上各種隨機色 ArrayList colors = new ArrayList(); Random rnd = new Random(); for (int i = 0; i < 50; i++) colors.Add(new SolidBrush(Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255)))); //建立一個bitmap例項 Bitmap objbitmap = new Bitmap(width, height); Graphics objgraphics = Graphics.FromImage(objbitmap); Bitmap objbitmap1 = new Bitmap(width, height); Graphics objgraphics1 = Graphics.FromImage(objbitmap1); //畫一個白色背景 objgraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height); //畫一個亮黃色背景 objgraphics.FillRectangle(new SolidBrush(Color.Beige), pierect); //以下為畫餅圖(有幾行row畫幾個) float currentdegree = 0.0f; #endregion int childtype = 0; ArrayList coun = new ArrayList(); for (int i = 0; i < a.Count; i++) { //子事件總數 childtype = MYHelper.SQLHelper.ExecuteScalar("Select count(*) From L_consult Where type Like '" + "%" + a[i].ToString() + "%" + "'"); //畫子事件總數 objgraphics.FillPie((SolidBrush)colors[i], pierect, currentdegree, Convert.ToSingle(childtype) / Total * 360); currentdegree += Convert.ToSingle(childtype) / Total * 360; coun.Add(childtype); } //以下為生成主標題 SolidBrush blackbrush = new SolidBrush(Color.Black); SolidBrush bluebrush = new SolidBrush(Color.Blue); string title = " 律師事務所統計餅狀圖: " + "\n \n\n"; StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; objgraphics.DrawString(title, fonttitle, blackbrush, new Rectangle(0, 10, width, titleheight), stringFormat); //列出各欄位與得數目 objgraphics1.DrawRectangle(new Pen(Color.White, 2), 0, 0, 400, 400); objgraphics1.DrawString("---------------諮詢事件統計資訊---------------------", fontlegend, bluebrush, 0, 10); objgraphics1.DrawString("統計單位: " + "律師事務所", fontlegend, blackbrush, 40, 40); objgraphics1.DrawString("統計年份: " + date, fontlegend, blackbrush, 40, 70); objgraphics1.DrawString("事件諮詢總數: " + Convert.ToString(Total), fontlegend, blackbrush, 40, 100); int kuandu = 100; int y = 100; int x = 40; for (int i = 0; i < a.Count; i++) { kuandu += 30; y += 30; objgraphics1.DrawString(a[i] + "事件: " + (coun[i]), fontlegend, blackbrush, x, kuandu); objgraphics1.FillRectangle((SolidBrush)colors[i], 20, y, 10, 10); objgraphics1.DrawString("所佔比率: " + Convert.ToString((Convert.ToSingle(coun[i]) / Total) * 100) + " %", fontlegend, blackbrush, 160, kuandu); } pictureBox1.Image = objbitmap; pictureBox2.Image = objbitmap1; } //二級統計圖 public static void CreateTestImage(PictureBox pictureBox1, PictureBox pictureBox2, string type) { ArrayList a = BindB(type); //把連線字串指定為一個常量 float Total = MYHelper.SQLHelper.ExecuteScalar("Select count(*) From L_consult Where type Like '" + "%" + type + "%" + "'");//獲取總的條目數 #region //設定字型,fonttitle為主標題的字型 Font fontlegend = new Font("verdana", 9); Font fonttitle = new Font("verdana", 10, FontStyle.Bold); //背景寬 int width = 350; int bufferspace = 15; int legendheight = fontlegend.Height * 12 + bufferspace; //高度 int titleheight = fonttitle.Height + bufferspace; int height = width + legendheight + titleheight + bufferspace;//白色背景高 int pieheight = width; Rectangle pierect = new Rectangle(0, titleheight, width, pieheight); //加上各種隨機色 ArrayList colors = new ArrayList(); Random rnd = new Random(); for (int i = 0; i < 50; i++) colors.Add(new SolidBrush(Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255)))); //建立一個bitmap例項 Bitmap objbitmap = new Bitmap(width, height); Graphics objgraphics = Graphics.FromImage(objbitmap); Bitmap objbitmap1 = new Bitmap(width, height); Graphics objgraphics1 = Graphics.FromImage(objbitmap1); //畫一個白色背景 objgraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height); //畫一個亮黃色背景 objgraphics.FillRectangle(new SolidBrush(Color.Beige), pierect); //以下為畫餅圖(有幾行row畫幾個) float currentdegree = 0.0f; #endregion int childtype = 0; ArrayList coun = new ArrayList(); for (int i = 0; i < a.Count; i++) { //子事件總數 childtype = MYHelper.SQLHelper.ExecuteScalar("Select count(*) From L_consult Where type Like '" + "%" + a[i].ToString() + "%" + "'"); //畫佔扇形圖的比例 objgraphics.FillPie((SolidBrush)colors[i], pierect, currentdegree, Convert.ToSingle(childtype) / Total * 360); currentdegree += Convert.ToSingle(childtype) / Total * 360; coun.Add(childtype); } //以下為生成主標題 SolidBrush blackbrush = new SolidBrush(Color.Black); SolidBrush bluebrush = new SolidBrush(Color.Blue); string title = " 律師事務所統計餅狀圖: " + "\n \n\n"; StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; objgraphics.DrawString(title, fonttitle, blackbrush, new Rectangle(0, 10, width, titleheight), stringFormat); //列出各欄位與得數目 objgraphics1.DrawRectangle(new Pen(Color.White, 2), 0, 0, 500, 500); objgraphics1.DrawString("---------------諮詢事件統計資訊---------------------", fontlegend, bluebrush, 0, 10); objgraphics1.DrawString("統計單位: " + "律師事務所", fontlegend, blackbrush, 40, 40); // objgraphics1.DrawString("【統計時間:】" + date, fontlegend, blackbrush, 40, 40); objgraphics1.DrawString("事件諮詢總數: " + Convert.ToString(Total), fontlegend, blackbrush, 40, 60); int kuandu = 60; int y = 60; int x = 40; for (int i = 0; i < a.Count; i++) { kuandu += 20; y += 20; objgraphics1.DrawString(a[i] + "事件: " + (coun[i]), fontlegend, blackbrush, x, kuandu); objgraphics1.FillRectangle((SolidBrush)colors[i], 20, y, 10, 10); objgraphics1.DrawString("所佔比率: " + Convert.ToString((Convert.ToSingle(coun[i]) / Total) * 100) + " %", fontlegend, blackbrush, 200, kuandu); } pictureBox1.Image = objbitmap; pictureBox2.Image = objbitmap1; } //三級統計圖 public static void CreateThreeImage(PictureBox pictureBox1, PictureBox pictureBox2, string bname) { ArrayList a = BindC(bname); //把連線字串指定為一個常量 float Total = MYHelper.SQLHelper.ExecuteScalar("Select count(*) From L_consult Where type Like '" + "%" + bname + "%" + "'");//獲取總的條目數 #region //設定字型,fonttitle為主標題的字型 Font fontlegend = new Font("verdana", 9); Font fonttitle = new Font("verdana", 10, FontStyle.Bold); //背景寬 int width = 350; int bufferspace = 15; int legendheight = fontlegend.Height * 12 + bufferspace; //高度 int titleheight = fonttitle.Height + bufferspace; int height = width + legendheight + titleheight + bufferspace;//白色背景高 int pieheight = width; Rectangle pierect = new Rectangle(0, titleheight, width, pieheight); //加上各種隨機色 ArrayList colors = new ArrayList(); Random rnd = new Random(); for (int i = 0; i < 80; i++) colors.Add(new SolidBrush(Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255)))); //建立一個bitmap例項 Bitmap objbitmap = new Bitmap(width, height); Graphics objgraphics = Graphics.FromImage(objbitmap); Bitmap objbitmap1 = new Bitmap(width, height); Graphics objgraphics1 = Graphics.FromImage(objbitmap1); //畫一個白色背景 objgraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, width, height); //畫一個亮黃色背景 objgraphics.FillRectangle(new SolidBrush(Color.Beige), pierect); //以下為畫餅圖(有幾行row畫幾個) float currentdegree = 0.0f; #endregion int childtype = 0; ArrayList coun = new ArrayList(); for (int i = 0; i < a.Count; i++) { //子事件總數 childtype = MYHelper.SQLHelper.ExecuteScalar("Select count(*) From L_consult Where type Like '" + "%" + a[i].ToString() + "%" + "'"); //畫通過人數 objgraphics.FillPie((SolidBrush)colors[i], pierect, currentdegree, Convert.ToSingle(childtype) / Total * 360); currentdegree += Convert.ToSingle(childtype) / Total * 360; coun.Add(childtype); } //以下為生成主標題 SolidBrush blackbrush = new SolidBrush(Color.Black); SolidBrush bluebrush = new SolidBrush(Color.Blue); string title = " 律師事務所統計餅狀圖: " + "\n \n\n"; StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Center; stringFormat.LineAlignment = StringAlignment.Center; objgraphics.DrawString(title, fonttitle, blackbrush, new Rectangle(0, 10, width, titleheight), stringFormat); //列出各欄位與得數目 objgraphics1.DrawRectangle(new Pen(Color.White, 2), 0, 0, 400, 500); objgraphics1.DrawString("---------------諮詢事件統計資訊---------------------", fontlegend, bluebrush, 0, 10); objgraphics1.DrawString("統計單位: " + "律師事務所", fontlegend, blackbrush, 40, 40); // objgraphics1.DrawString("【統計時間:】" + date, fontlegend, blackbrush, 40, 40); objgraphics1.DrawString("事件諮詢總數: " + Convert.ToString(Total), fontlegend, blackbrush, 40, 60); int kuandu = 60; int y = 60; int x = 40; for (int i = 0; i < a.Count; i++) { kuandu += 20; y += 20; objgraphics1.DrawString(a[i] + "事件: " + (coun[i]), fontlegend, blackbrush, x, kuandu); objgraphics1.FillRectangle((SolidBrush)colors[i], 20, y, 10, 10); objgraphics1.DrawString("所佔比率: " + Convert.ToString((Convert.ToSingle(coun[i]) / Total) * 100) + " %", fontlegend, blackbrush, 220, kuandu); } pictureBox1.Image = objbitmap; pictureBox2.Image = objbitmap1; }View Code
二、對當前頁資料和全部資料匯出的功能實現
首先咱們還是看看效果,然後我說下思路,最後檢視原始碼:
註釋:當用戶點選匯出當前頁,則以Excel形式匯出當前頁資訊,當用戶關閉時候,提示是否儲存。這樣既可以達到查詢效果,也可以根據需求進行儲存。當然匯出所有頁效果一樣。
思路:在方法中傳入兩個引數(資料來源控制元件名DataGridView,布林值flag),在方法中對DataGridView進行遍歷打印出標頭,然後在對各列資料進行填充。最後通過控制元件器flag控制,如果flag==true,則進行資料儲存關閉Excel,如果false直接關閉
補充:有時候,在匯出Excel時候,不希望直接顯示關閉時儲存,即如上方法。希望直接彈窗,提示儲存物理路徑進行儲存。在如下程式碼,將兩種形式實現方法都進行粘貼出來。
方法一、關閉時儲存
#region DataGridView資料顯示到Excel /// <summary> /// 開啟Excel並將DataGridView控制元件中資料匯出到Excel /// </summary> /// <param name="dgv">DataGridView物件 </param> /// <param name="isShowExcle">是否顯示Excel介面 </param> /// <remarks> /// add com "Microsoft Excel 11.0 Object Library" /// using Excel=Microsoft.Office.Interop.Excel; /// </remarks> /// <returns> </returns> public bool DataGridviewShowToExcel(DataGridView dgv, bool isShowExcle) { try { if (dgv.Rows.Count == 0) return false; //建立Excel物件 Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application(); excel.Application.Workbooks.Add(true); excel.Visible = isShowExcle; //生成欄位名稱 for (int i = 0; i < dgv.ColumnCount; i++) { excel.Cells[1, i + 1] = dgv.Columns[i].HeaderText; } //填充資料 for (int i = 0; i < dgv.RowCount; i++) { for (int j = 0; j < dgv.ColumnCount; j++) { if (dgv[j, i].ValueType == typeof(string)) { excel.Cells[i + 2, j + 1] = "'" + dgv[j, i].Value.ToString(); } else { excel.Cells[i + 2, j + 1] = dgv[j, i].Value.ToString(); } } } return true; } catch { return false; } } #endregionView Code
方法二、直接提示儲存
#region DateGridView匯出到csv格式的Excel /// <summary> /// 常用方法,列之間加\t,一行一行輸出,此檔案其實是csv檔案,不過預設可以當成Excel開啟。 /// </summary> /// <remarks> /// using System.IO; /// </remarks> /// <param name="dgv"></param> public void DataGridViewToExcel(DataGridView dgv) { SaveFileDialog dlg = new SaveFileDialog(); dlg.Filter = "Execl files (*.xls)|*.xls"; dlg.FilterIndex = 0; dlg.RestoreDirectory = true; dlg.CreatePrompt = true; dlg.Title = "儲存為Excel檔案"; if (dlg.ShowDialog() == DialogResult.OK) { Stream myStream; myStream = dlg.OpenFile(); StreamWriter sw = new StreamWriter(myStream, System.Text.Encoding.GetEncoding(-0)); string columnTitle = ""; try { //寫入列標題 for (int i = 0; i < dgv.ColumnCount; i++) { if (i > 0) { columnTitle += "\t"; } columnTitle += dgv.Columns[i].HeaderText; } sw.WriteLine(columnTitle); //寫入列內容 for (int j = 0; j < dgv.Rows.Count; j++) { string columnValue = ""; for (int k = 0; k < dgv.Columns.Count; k++) { if (k > 0)