程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 實現標記datagridview標題並導出Excel的功能,datagridviewexcel

實現標記datagridview標題並導出Excel的功能,datagridviewexcel

編輯:關於.NET

實現標記datagridview標題並導出Excel的功能,datagridviewexcel


最近在學習winform,國慶前被布置了一個小任務,好不容易大致做出來了,決定記錄下來,以此加深印象。

先說下需求:這是一個導入話單標記後並導出的功能

1. 選擇excel文件

2. 定義字段
   日期 時間 對方號碼 通話時長 呼叫類型
3. 點擊datagridview 標題 出現下拉菜單 顯示定義的字段
4. 標記定義字段列
5. 保存定義字段數據 到 datatable
6  導出datatable

按照需求一步一步來,先設計界面,需要一個DataGridView和兩個Button,一個導入,一個導出,我加了個Label和TextBox來提示文件路徑。

先在類裡面定義幾個全局變量,下面的代碼中會用到。

1 int colIndex;//點擊的單元格列索引 2 int rowIndex;//點擊的單元格行索引 3 Dictionary<int, string> dic = new Dictionary<int, string>();//存放excel標題 4 List<string> list = new List<string>(); //存放標記後的標題 5 DataTable dt;//導入的table 6 string filename = "";//Excel文件名 View Code

第一步:導入Excel預覽,我從網上找了一段excel導入datagridview的代碼,具體如下:

1 private DataTable ExcelToDataTable(string path) 2 { 3 4 FileStream fs = File.OpenRead(path); //打開.xls文件 5 6 HSSFWorkbook wk = new HSSFWorkbook(fs); //把xls文件中的數據寫入wk中 7 8 var sheet = wk.GetSheetAt(0); //提取第一個sheet 9 var headerRow = sheet.GetRow(0);//提取sheet第一行 10 var cellCount = headerRow.LastCellNum;//提取行的最後一列 11 DataTable table = new DataTable(); 12 //給table添加一個列 13 for (int i = headerRow.FirstCellNum; i < cellCount; i++) 14 { 15 DataColumn col = new DataColumn(headerRow.GetCell(i).StringCellValue); 16 table.Columns.Add(col); 17 } 18 //獲取sheet的行數 19 var rowCount = sheet.LastRowNum; 20 //循環逐行將sheet中數據寫入table 21 for (int i = (sheet.FirstRowNum + 1); i < rowCount; i++) 22 { 23 var row = sheet.GetRow(i); 24 DataRow datarow = table.NewRow(); 25 for (int j = row.FirstCellNum; j < cellCount; j++) 26 { 27 if (row.GetCell(j) != null) 28 { 29 datarow[j] = row.GetCell(j).ToString(); 30 } 31 } 32 table.Rows.Add(datarow); 33 } 34 wk = null; 35 sheet = null; 36 return table; 37 } 導入方法

這是個導入的方法,雙擊導入按鈕,在事件裡添加如下代碼:

1 private void btnImport_Click(object sender, EventArgs e) 2 { 3 OpenFileDialog ofd = new OpenFileDialog(); 4 ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 5 ofd.Filter = "Excel Files(*.xls)|*.xls"; 6 if (ofd.ShowDialog() != DialogResult.OK) 7 { return; } 8 filename = ofd.FileName; 9 textBox1.Text = ofd.FileName; 10 dt = ExcelToDataTable(filename); 11 dataGridView1.DataSource = dt;//ExcelToDataTable(ofd.FileName); 12 13 int ColCount = dataGridView1.Columns.Count; 14 //將Excel所有標題存入dic中 15 for (int i = 0; i < ColCount; i++) 16 { 17 dic.Add(i, dataGridView1.Columns[i].HeaderText); 18 } 19 } 導入預覽

為了方便我將測試的Excel文檔放到桌面,Excel的標題我存到了字典裡,下面會用到。

到這裡基本實現了第一步,點擊導入按鈕,選中excel文件,顯示在datagridview上預覽。

 

第二步、第三步:要求的樣式大概是這樣:

點擊datagridview的標題,彈出下拉菜單,顯示定義的字段。因此添加一個ContextMenuStrip控件,將字段一個個添加進去。

要求點擊標題彈出下拉菜單,我用到了datagridview的CellCilck事件,這個事件裡代碼非常簡單,只要彈出contexmenustrip就行了,然後加一個對是否為標題行的判斷。

View Code

第四步比較復雜,大概思路是,下拉菜單的選項是固定的,通過contextMenuStrip1_ItemClicked事件裡的e.ItemClicked.Text可以獲取到你選擇的菜單,因此我用了switch case語句來進行判斷。

首先是點擊datagridview一列的標題,然後選中一個菜單,這一列的標題要變成e.itemClicked,並且標記這一列,所以我寫了一個標記的方法表示標記後操作和樣式。

1 private void Mark(string item) 2 { 3 dt.Columns[colIndex].ColumnName = item; 4 dataGridView1.Columns[colIndex].HeaderText = item; 5 dataGridView1.Columns[colIndex].DefaultCellStyle.BackColor = Color.LightSteelBlue; 6 dataGridView1.EnableHeadersVisualStyles = false; 7 dataGridView1.Columns[colIndex].HeaderCell.Style.BackColor = Color.LightSlateGray; 8 } Mark

因為涉及到匹配的問題,例如日期格式的列無法標記成“呼叫類型”,“通話時間”等,所以加了一些正則判斷,正則表達式以前從沒用過,也是網上現學的,寫得比較差。

又寫了一個判斷後的方法:

1 private void MatchItem(string match, string str, string item) 2 { 3 Match m = Regex.Match(match, str); 4 if (m.Success) 5 { 6 Mark(item); 7 //如果該列已標記,則不添加item到list 8 foreach (var i in list) 9 { 10 if (item == i) 11 return; 12 } 13 list.Add(item); 14 } 15 else 16 { 17 contextMenuStrip1.Hide(); 18 MessageBox.Show("該列不為" + item + "!"); 19 } 20 } 判斷格式

至於contextmenustrip_itemClicked事件裡只要在每個case裡調用MatchItem方法就可以了。

1 private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e) 2 { 3 //dt = ExcelToDataTable(filename); 4 //獲取想要標記的的標題 5 string item = e.ClickedItem.Text; 6 //獲取用於判斷的內容 7 var BeMatch = dataGridView1.Rows[rowIndex + 1].Cells[colIndex].Value.ToString(); 8 //當前列在table是否已經存在 9 int i = 0; 10 foreach (DataColumn dataCol in dt.Columns) 11 { 12 if (i != colIndex && dataCol.ColumnName == item) 13 { 14 contextMenuStrip1.Hide(); 15 var index = i + 1; 16 MessageBox.Show("該表第" + index + "列為" + dataCol.ColumnName + ",無法標記"); 17 return; 18 } 19 i++; 20 } 21 22 switch (item) 23 { 24 case "呼叫類型": 25 { 26 string strType = @"[\u4e00-\u9fbb]"; 27 MatchItem(BeMatch, strType, item); 28 } 29 break; 30 case "對方號碼": 31 { 32 string strNum = @"0?[1]+[358]+\d{9}"; 33 MatchItem(BeMatch, strNum, item); 34 } 35 break; 36 case "日期": 37 { 38 string strDate = @"^2\d{7}$"; 39 MatchItem(BeMatch, strDate, item); 40 } 41 break; 42 case "時間": 43 { 44 string strTime = @"^[0-2]\d{1}[0-5]\d{1}[0-5]\d{1}$"; 45 MatchItem(BeMatch, strTime, item); 46 } 47 break; 48 case "通話時長": 49 { 50 string strOften = @"\d"; 51 MatchItem(BeMatch, strOften, item); 52 } 53 break; 54 case "取消設置": 55 { 56 //遍歷原標題,獲取取消設置的列,移出dt 57 foreach (var kv in dic) 58 { 59 if (kv.Key == colIndex) 60 { 61 list.Remove(dataGridView1.Columns[colIndex].HeaderText); 62 //list.Insert(colIndex,kv.Value); 63 item = kv.Value; 64 dt.Columns[colIndex].ColumnName = item; 65 } 66 } 67 //還原標題和樣式 68 dataGridView1.Columns[colIndex].DefaultCellStyle.BackColor = Color.White; 69 dataGridView1.Columns[colIndex].HeaderCell.Style.BackColor = DefaultBackColor; 70 } 71 break; 72 } 73 } 標記列

第五步 :保存標記後的字段數據到datatable裡,我在網上找了一個方法,附上鏈接:http://www.jb51.net/article/80620.htm

1 private void btnExport_Click(object sender, EventArgs e) 2 { 3 //添加標記的列到table 4 DataTable table = dt.DefaultView.ToTable(false, list.ToArray()); 5 6 try 7 { 8 SaveFileDialog sfd = new SaveFileDialog(); 9 //sfd.FileName = "測試導出.xls"; 10 sfd.Filter = "Excel Files(*.xls)|*.xls"; 11 sfd.FileName = "測試導出"; 12 if (sfd.ShowDialog() == DialogResult.OK) 13 { 14 filename = sfd.FileName; 15 DataToExcel(table, filename, "話單", false); 16 } 17 } 18 catch (Exception ex) 19 { 20 MessageBox.Show(ex.Message); 21 } 導出標記後的列

做完運行的效果是這樣的:


 

到這裡基本結束了,運行後沒什麼大問題,可能有的bug還沒有測出來。第一次寫博客,寫的不好大家見諒,歡迎提出各種意見和建議。謝謝支持!

                                                               

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved