需求:選擇一個Excel文件,而後對該Excel文件進行處理,再導出一個處理後的Excel文件。sql
效果圖app
聲明:我對winform開發不熟,可是我看到許多開發人員作東西只管交差,從不考慮用戶體驗,也不考慮容錯處理,我就在想,難道就不能作得專業一點嗎?當你用別人作的東西,滿口吐槽的時候有沒有想過別人用你作的東西的時候,會不會同樣的狂噴呢?異步
這裏對Excel的操做使用了NPOI.dll組件,可自行去網上如今或者使用NuGet下載。ide
IrisSkin4.dll包括(73皮膚+vs2012兼容) 綠色版下載地址:http://pan.baidu.com/s/1eQ1sAUA工具
這裏使用到了IrisSkin4.dll皮膚控件this
使用方法:spa
一、添加IrisSkin4.dll引用線程
一、工具箱,添加此程序集3d
二、複製皮膚文件日誌
設置皮膚文件的屬性
三、代碼調用
public frmMain() { InitializeComponent(); //加載皮膚 skinEngine1.SkinFile ="Skins/Warm.ssk"; skinEngine1.Active = true; skinEngine1.SkinDialogs = false;
//若是要讓某個控件不使用皮膚,則設置此屬性,這樣,就能夠單獨爲此控件設置屬性了,不然爲此控件設置的屬性將會被皮膚屬性覆蓋 lblShow.Tag = skinEngine1.DisableTag; lblMsg.Tag = skinEngine1.DisableTag; this.lblShow.ForeColor = Color.Red; this.lblMsg.ForeColor = Color.Green; }
關於excel的操做,這裏仍是使用NPOI.dll,能夠本身從網上下載,也能夠直接從vs的NuGet中下載。
須要注意的是,對於一些比較耗時的界面操做,建議使用一個進度條,而後以異步調用的形式進行操做。異步調用能夠開啓一個線程,若是在線程調用的代碼中須要修改窗體控件,也就是要修改主線程的內容,可使用以下代碼:
Invoke(new MethodInvoker(delegate { progressBar.Maximum = sheet.LastRowNum; }));}
代碼很簡單,這裏我不作過多的說明,詳情請參見代碼。
using Dapper; using NExtensions; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using System.ComponentModel; using System.Configuration; using System.Data.SqlClient; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Windows.Forms; using System.Drawing; using System.Collections.Generic; using NPOI.HSSF.Util; namespace uuch.CustomsCheckPrint { //modify by:Zouqj 2015/4/9 public partial class frmMain : Form { public frmMain() { InitializeComponent(); //加載皮膚 skinEngine1.SkinFile ="Skins/"+ConfigurationManager.AppSettings["themeName"]; skinEngine1.Active = true; skinEngine1.SkinDialogs = false; lblShow.Tag = skinEngine1.DisableTag; lblMsg.Tag = skinEngine1.DisableTag; this.lblShow.ForeColor = Color.Red; this.lblMsg.ForeColor = Color.Green; } public bool IsCalculating { get; set; } /// <summary> /// 設置單元格樣式 /// </summary> /// <param name="workbook"></param> /// <param name="cell"></param> private void setCellStyle(IWorkbook workbook, ICell cell) { HSSFCellStyle fCellStyle = (HSSFCellStyle)workbook.CreateCellStyle(); HSSFFont ffont = (HSSFFont)workbook.CreateFont(); //ffont.FontHeight = 20 * 20; //ffont.FontName = "宋體"; ffont.Color = HSSFColor.Red.Index; fCellStyle.SetFont(ffont); //fCellStyle.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;//垂直對齊 //fCellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;//水平對齊 cell.CellStyle = fCellStyle; } public void EditAndSave(string filePath, ProgressBar progressBar, Label label) { // 0 , 1 , 2 , 3, 4, 5, 6 // 收寄日期, 郵件號, 寄達地, 類, 重量, 郵費, 省份 //序號 提單號 快件單號 發件人 收件人 收件人地址 內件名稱 數量 價值(USD) 重量(KG) 省份 首重費用 續重費用 OVS運費 操做費 OVS稅費 var sc = new SqlConnection(ConfigurationManager.AppSettings["connectionString"]); sc.Open(); IWorkbook workbook = null; var fileExten = Path.GetExtension(filePath); var fsRead = File.OpenRead(filePath); if (fileExten == ".xls"||fileExten == ".xlsx") { workbook = new HSSFWorkbook(fsRead); } else { MessageBox.Show("文件不是有效的Excel文件!"); return; } string proviceNameA = ConfigurationManager.AppSettings["proviceNameA"]; string proviceNameB = ConfigurationManager.AppSettings["proviceNameB"]; string[] economicProvince =null; string channelE = string.Empty; //經濟渠道 string channelS = string.Empty; //標準渠道 if (rbtnA.Checked) { channelE = ConfigurationManager.AppSettings["channelAE"]; channelS = ConfigurationManager.AppSettings["channelAS"]; economicProvince = string.IsNullOrEmpty(proviceNameA) ? null : proviceNameA.Split(','); } else if (rbtnB.Checked) { channelE = ConfigurationManager.AppSettings["channelBE"]; channelS = ConfigurationManager.AppSettings["channelBS"]; economicProvince = string.IsNullOrEmpty(proviceNameB) ? null : proviceNameB.Split(','); } string pWeighFee = string.Empty; //首重費 string yWeighFee = string.Empty; //續重費用 string orderFee = string.Empty; //訂單費 操做費 fsRead.Close(); //ISheet sheet = workbook.GetSheetAt(0); var lackProvinceCount = 1; var sheetCount = workbook.NumberOfSheets; int successCounts = 0; for (int sheetIndex = 0; sheetIndex < sheetCount; sheetIndex++) { var sheetIndexShow = sheetIndex + 1; var sheet = workbook.GetSheetAt(sheetIndex); //progressBar.Maximum = sheet.LastRowNum; if (sheetIndex == 0) { Invoke(new MethodInvoker(delegate { progressBar.Maximum = sheet.LastRowNum; })); } IsCalculating = true; for (int i = 1; i <= sheet.LastRowNum; i++) { var row = sheet.GetRow(i); var weight = row.GetCell(9) == null ? 0D : row.GetCell(9).NumericCellValue; //重量 var targetProvince = row.GetCell(10) == null ? "" : row.GetCell(10).StringCellValue.ToString().Trim(); //省份 if (targetProvince.IsNullOrEmpty()) { Invoke(new MethodInvoker(delegate { lblShow.Text += String.Format("{0} 郵件號: {1} 缺乏目標地省份!\r\n", lackProvinceCount.ToString("00000"), row.GetCell(1).StringCellValue); })); lackProvinceCount++; continue; } if (targetProvince.Contains("省")) { targetProvince = targetProvince.Replace("省", ""); } var channelCode = economicProvince.Contains(targetProvince) == true ? channelE : channelS; //根據省份獲取渠道代碼 var sSelectProvince = String.Format("SELECT Base_PlaceID FROM Base_Place WHERE CnName LIKE '%{0}%' ", targetProvince); var resultContry = sc.Query(sSelectProvince, null).FirstOrDefault(); if (resultContry == null) { setCellStyle(workbook, row.GetCell(10)); continue; } var countryID = resultContry["Base_PlaceID"].ToString(); var sSelectChannel = String.Format("SELECT Base_ChannelInfoID FROM Base_ChannelInfo WHERE ChannelCode = '{0}' ", channelCode); var resultChannel= sc.Query(sSelectChannel, null).FirstOrDefault(); if (resultChannel == null) { setCellStyle(workbook, row.GetCell(10)); continue; } var channelID = resultChannel["Base_ChannelInfoID"].ToString(); string sql = string.Format(@"select SalesPrice, CalStyle from v_Price_PriceInfo where SubChannelCode='{0}' and charindex ('{1}',AreaCountry)>0", channelCode, countryID); // 銷售價 計算方式 P:首重 Y:續重 var result = sc.Query(sql, null).ToList(); if (result != null && result.Count() > 0) { foreach (var v in result) { if (v["CalStyle"].ToString() == "Y") { yWeighFee = v["SalesPrice"].ToString(); } else if (v["CalStyle"].ToString() == "P") { pWeighFee = result[0]["SalesPrice"].ToString(); } } } else { setCellStyle(workbook, row.GetCell(10)); continue; } successCounts++; // 執行運費計算 " EXEC p_CalculatePriceByCH CountryID, Weight, ChannelID, CalFlag "; var sExecProc = String.Format(" EXEC p_CalculatePriceByCH {0}, {1}, {2}, {3} ", countryID, weight, channelID, 1); var query = sc.Query(sExecProc, null).FirstOrDefault(); var shipFeeRs = query["BaseFee"].ToString(); orderFee = query["OrderFee"].ToString(); //Trace.WriteLine(String.Format("{0} - {1}, {2} - {3}, {4} ", targetProvince, countryID, channelCode, channelID, sExecProc)); //首重費用 11 var cellpWeighFee = row.GetCell(11); cellpWeighFee.SetCellType(CellType.Numeric); cellpWeighFee.SetCellValue(pWeighFee.ToDouble()); //續重費用 12 var cellyWeighFee = row.GetCell(12); cellyWeighFee.SetCellType(CellType.Numeric); cellyWeighFee.SetCellValue(yWeighFee.ToDouble()); //OVS運費 13 var cellShipFee = row.GetCell(13); cellShipFee.SetCellType(CellType.Numeric); cellShipFee.SetCellValue(shipFeeRs.ToDouble()); //操做費 14 var cellOrderFee = row.GetCell(14); cellOrderFee.SetCellType(CellType.Numeric); cellOrderFee.SetCellValue(orderFee.ToDouble()); //progressBar.Value = i; Invoke(new MethodInvoker(delegate { lblMsg.Text = String.Format("工做表: {0}/{1} | 行: {2}/{3}", sheetIndexShow, sheetCount, i, sheet.LastRowNum); progressBar1.Value = i; })); //異步顯示進度條 System.Windows.Forms.Application.DoEvents(); } Invoke(new MethodInvoker(delegate { lblShow.Text = string.Format("計算成功!成功數:{0}", successCounts); })); if (sheet.LastRowNum != successCounts) { Invoke(new MethodInvoker(delegate { lblShow.Text += string.Format(" 有計算不出的數據{0}條,請覈對數據或格式是否有誤!", sheet.LastRowNum - successCounts); })); } } var fsSave = File.Create(textBoxOutputPath.Text); workbook.Write(fsSave); fsSave.Close(); sc.Close(); IsCalculating = false; } protected override void OnClosing(CancelEventArgs e) { if (IsCalculating) { var rs = MessageBox.Show("計算還沒結束, 肯定退出?", "肯定退出?", MessageBoxButtons.YesNoCancel); if (rs == DialogResult.Yes) { this.Dispose(); this.Close(); Environment.Exit(0); } else { e.Cancel = true; } } } private void btnSave_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(textBoxInputFilePath.Text)) { lblShow.Text = "請先選擇要計算的文件!\r\n"; return; } if (string.IsNullOrEmpty(textBoxOutputPath.Text)) { lblShow.Text = "必須制定輸出文件路徑和名稱!\r\n"; return; } lblShow.Text = ""; //兩種結算方式 try { Thread t = new Thread(new ThreadStart(Single)); t.IsBackground = true; t.Start(); } catch (Exception ex) { LogAPI.WriteLog(ex.Message); lblShow.Text=ex.Message;//"計算錯誤,詳情請查看日誌!" return; } Trace.WriteLine("OK"); } //適配器 void Single() { EditAndSave(textBoxInputFilePath.Text, progressBar1, lblMsg); } private void buttonChooseInputFile_Click(object sender, EventArgs e) { var fileDialog = new OpenFileDialog(); fileDialog.Multiselect = true; fileDialog.Title = "選擇文件"; fileDialog.Filter = "Excel files|*.xls; *.xlsx"; if (fileDialog.ShowDialog() == DialogResult.OK) { textBoxInputFilePath.Text = fileDialog.FileName; } } private void buttonChooseOutputFolder_Click(object sender, EventArgs e) { var saveFileDialog = new SaveFileDialog(); saveFileDialog.Title = "保存文件"; saveFileDialog.Filter = "Excel files|*.xls; *.xlsx"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { textBoxOutputPath.Text = saveFileDialog.FileName; } } } }
App.config
<?xml version="1.0"?> <configuration> <appSettings> <add key="connectionString" value="Data Source=192.xx.2.xxx;Initial Catalog=xxx;Persist Security Info=True;User ID=xx;Password=xxxx"/> <add key="EnbleLog" value="false"/><!--是否開啓日誌:true,false--> <add key="LogUrl" value="D:/"/> <add key="LogName" value="計費日誌.txt"/> <add key="themeName" value="Warm.ssk"/> <!--結算方式A一--> <!--渠道--> <add key="proviceNameA" value="上海,江蘇,浙江,北京,安徽"/><!--這些省走經濟快遞渠道--> <add key="channelAE" value="GZExpress_E"/> <!--經濟快遞渠道代碼--> <add key="channelAS" value="GZExpress_S"/> <!--標準快遞渠道代碼--> <!--結算方式B 帝途一--> <add key="proviceNameB" value="北京,上海,江蘇,浙江,天津"/><!--這些省走經濟快遞渠道--> <add key="channelBE" value="GZExpress_E1"/> <!--經濟快遞渠道代碼--> <add key="channelBS" value="GZExpress_S1"/> <!--標準快遞渠道代碼--> </appSettings> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> </startup> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="NPOI" publicKeyToken="0df73ec7942b34e1" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-2.1.3.1" newVersion="2.1.3.1"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="NPOI.OOXML" publicKeyToken="0df73ec7942b34e1" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-2.1.3.1" newVersion="2.1.3.1"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>