循序漸進開發(fā)WinForm項目(5)--Excel數(shù)據(jù)的導(dǎo)入導(dǎo)出操作

隨筆背景:在很多時候,很多入門不久的朋友都會問我:我是從其他語言轉(zhuǎn)到C#開發(fā)的,有沒有一些基礎(chǔ)性的資料給我們學(xué)習(xí)學(xué)習(xí)呢,你的框架感覺一下太大了,希望有個循序漸進的教程或者視頻來學(xué)習(xí)就好了。
其實也許我們每天面對的太多東西了,覺得很多都稀松平常了,即使很細微的地方,可能我們都已經(jīng)形成習(xí)慣了。反過來,如果我們切換到其他領(lǐng)域,如IOS、android,那么開始我們可能對里面很多設(shè)計的規(guī)則不甚了解,開始可能也是一頭霧水。
本篇繼續(xù)上一篇《循序漸進開發(fā)WinForm項目(4)--Winform界面模塊的集成使用》,繼續(xù)介紹如何循序漸進開發(fā)Winform項目,介紹業(yè)務(wù)模塊常見的導(dǎo)入導(dǎo)出操作的功能實現(xiàn),使得我們能夠快速,高效開發(fā)常見的模塊功能。
上篇隨筆我們介紹到自動代碼生成的界面如下所示,具備了導(dǎo)入、導(dǎo)出操作,這個操作是針對Excel進行的。


下面我們來介紹這個在很多模塊里面常見的Excel導(dǎo)入、Excel導(dǎo)出操作是如何實現(xiàn)的。

1、Excel數(shù)據(jù)的導(dǎo)出操作

由于我為了演示的目的,我在客戶信息表里面只是設(shè)計了幾個代表性的字段,下面我們來看看代碼生成工具自動生成的界面后臺代碼是如何的。

/// <summary>
/// 導(dǎo)出Excel的操作
/// </summary>
private void btnExport_Click(object sender, EventArgs e)
{
    string file = FileDialogHelper.SaveExcel(string.Format("{0}.xls", moduleName));
    if (!string.IsNullOrEmpty(file))
    {
        string where = GetConditionSql();
        List<CustomerInfo> list = BLLFactory<Customer>.Instance.Find(where);
        DataTable dtNew = DataTableHelper.CreateTable("序號|int,姓名,年齡,創(chuàng)建人,創(chuàng)建時間");
        DataRow dr;
        int j = 1;
        for (int i = 0; i < list.Count; i++)
        {
            dr = dtNew.NewRow();
            dr["序號"] = j++;
             dr["姓名"] = list[i].Name;
             dr["年齡"] = list[i].Age;
             dr["創(chuàng)建人"] = list[i].Creator;
             dr["創(chuàng)建時間"] = list[i].CreateTime;
             dtNew.Rows.Add(dr);
        }

        try
        {
            string error = "";
            AsposeExcelTools.DataTableToExcel2(dtNew, file, out error);
            if (!string.IsNullOrEmpty(error))
            {
                MessageDxUtil.ShowError(string.Format("導(dǎo)出Excel出現(xiàn)錯誤:{0}", error));
            }
            else
            {
                if (MessageDxUtil.ShowYesNoAndTips("導(dǎo)出成功,是否打開文件?") == System.Windows.Forms.DialogResult.Yes)
                {
                    System.Diagnostics.Process.Start(file);
                }
            }
        }
        catch (Exception ex)
        {
            LogTextHelper.Error(ex);
            MessageDxUtil.ShowError(ex.Message);
        }
    }
 }

上面的代碼中,FileDialogHelper.SaveExcel 函數(shù)是調(diào)用公用類庫模塊,彈出一個選擇保存文件的對話框,如果你沒有這個類,你可以自己添加代碼實現(xiàn)這個操作(這就是公用類庫的好處,在使用的時候能夠快速調(diào)用,減少代碼,提高效率)。
然后根據(jù)客戶錄入的條件檢索需要的數(shù)據(jù)內(nèi)容:
string where = GetConditionSql()
;
接著就是構(gòu)建一個相關(guān)字段的表格對象:DataTableHelper.CreateTable,這里面也是使用公用類庫來方便創(chuàng)建各種字段的表格,默認字段為字符串格式,如果需要如整形格式的,可以通過|進行分割,如“序號|int” 。
創(chuàng)建DataTable對象后,我們遍歷對象集合,把它里面的數(shù)據(jù)一行行的賦值給DataRow對象就可以了。

for (int i = 0; i < list.Count; i++)
{
    dr = dtNew.NewRow();
    dr["序號"] = j++;
     dr["姓名"] = list[i].Name;
     dr["年齡"] = list[i].Age;
     dr["創(chuàng)建人"] = list[i].Creator;
     dr["創(chuàng)建時間"] = list[i].CreateTime;
     dtNew.Rows.Add(dr);
}

賦值后,就是需要把DataTable對象轉(zhuǎn)換為Excel的操作過程了,這里操作分為兩步,第一是創(chuàng)建Excel文檔,第二個是寫數(shù)據(jù)的表頭和數(shù)據(jù)行信息,也就是數(shù)據(jù)的寫入操作,這里面我們把它封裝在公用類庫里面,方便模塊之間的調(diào)用。
導(dǎo)出Excel模塊采用了基于Aspose.Cell的組件進行數(shù)據(jù)的寫入操作:AsposeExcelTools.DataTableToExcel2
導(dǎo)出完成后,我們提示用戶是否打開Excel文件。

if (MessageDxUtil.ShowYesNoAndTips("導(dǎo)出成功,是否打開文件?") == System.Windows.Forms.DialogResult.Yes)
{
        System.Diagnostics.Process.Start(file);
}

最終,完成功能后,我們運行程序,導(dǎo)出Excel數(shù)據(jù)的效果如下所示。


2、Excel數(shù)據(jù)的導(dǎo)入操作

相對于數(shù)據(jù)的導(dǎo)出操作,Excel數(shù)據(jù)的導(dǎo)入操作會稍微麻煩一點,你至少需要選擇一個文件,文件最好以固定的模板進行導(dǎo)入,因此為了讓用戶確認數(shù)據(jù)的有效性,我們最好能提供了一個把Excel數(shù)據(jù)顯示出來再確認導(dǎo)入的過程,這樣可以減少導(dǎo)入錯誤數(shù)據(jù)的可能。
我們知道,這種常見的導(dǎo)入操作,很多業(yè)務(wù)模塊可能都需要,因此有必要考慮把它抽象出來,作為一個通用的導(dǎo)入模塊,這樣我們可以多次利用,非常方便,因此我們提煉這個通用導(dǎo)入的模塊特性如下所示。



Excel數(shù)據(jù)的導(dǎo)入模塊,默認生成界面的時候,也已經(jīng)一并生成了,我們來看看其中的代碼。

private string moduleName = "客戶信息";
/// <summary>
/// 導(dǎo)入Excel的操作
/// </summary>          
private void btnImport_Click(object sender, EventArgs e)
{
    string templateFile = string.Format("{0}-模板.xls", moduleName);
    FrmImportExcelData dlg = new FrmImportExcelData();
    dlg.SetTemplate(templateFile, System.IO.Path.Combine(Application.StartupPath, templateFile));
    dlg.OnDataSave += new FrmImportExcelData.SaveDataHandler(ExcelData_OnDataSave);
    dlg.OnRefreshData += new EventHandler(ExcelData_OnRefreshData);
    dlg.ShowDialog();
}

其中FrmImportExcelData 是一個界面基礎(chǔ)模塊中定義的一個通用導(dǎo)入模塊,里面實現(xiàn)了一些如顯示Excel數(shù)據(jù),模板信息關(guān)聯(lián),保存數(shù)據(jù)的接口等操作。我們來看看它的程序運行的效果。


其中我們通過代碼 dlg.SetTemplate 指定模板就是用來關(guān)聯(lián)Excel模板信息的,我們讓可以盡可能的選擇正確的模板進行錄入數(shù)據(jù)。
用戶通過第2的標識,指定要導(dǎo)入的Excel數(shù)據(jù)文件,選擇文件后,數(shù)據(jù)會自動顯示出來方便確認。
但我們選擇保存數(shù)據(jù)的操作的時候,這個通用模塊會執(zhí)行保存的邏輯代碼,并調(diào)用由創(chuàng)建者實現(xiàn)的代碼邏輯,如上面代碼的dlg.OnDataSave就是在執(zhí)行保存的時候,執(zhí)行的代碼邏輯,我們來看看生成的一些代碼實現(xiàn)。

bool ExcelData_OnDataSave(DataRow dr)
{
    bool success = false;
    bool converted = false;
    DateTime dtDefault = Convert.ToDateTime("1900-01-01");
    DateTime dt;
    CustomerInfo info = new CustomerInfo();
    info.Name = dr["姓名"].ToString();
    info.Age = dr["年齡"].ToString().ToInt32();
    info.Creator = dr["創(chuàng)建人"].ToString();
    converted = DateTime.TryParse(dr["創(chuàng)建時間"].ToString(), out dt);
    if (converted && dt > dtDefault)
    {
        info.CreateTime = dt;
    }

    success = BLLFactory<Customer>.Instance.Insert(info);
     return success;
}

我們知道,導(dǎo)入的時候,是遍歷每行Excel進行數(shù)據(jù)保存操作的,因此我們這里給出了一個一行的操作代碼即可:bool ExcelData_OnDataSave(DataRow dr),里面的邏輯,在數(shù)據(jù)保存的時候會被模塊進行調(diào)用。
上面的操作,是一條條的進行操作,如果累計超過3條記錄出錯,模塊提示是否繼續(xù)還是退出。
這里面并沒有采用事務(wù)的操作,對于一些如Sqlite的大批量的數(shù)據(jù)操作(速度提升很快),建議采用事務(wù)進行處理,關(guān)于這個可以參考《Winform開發(fā)框架之通用數(shù)據(jù)導(dǎo)入導(dǎo)出操作的事務(wù)性操作完善》進行修改調(diào)整。
最后,我們的Excel數(shù)據(jù)導(dǎo)入完成后,為了及時更新主界面的數(shù)據(jù),我們也定義了一個事件作為回調(diào),如下所示。

dlg.OnRefreshData += new EventHandler(ExcelData_OnRefreshData);

這個事件的實現(xiàn)代碼就是在主界面的數(shù)據(jù)綁定更新。

void ExcelData_OnRefreshData(object sender, EventArgs e) { BindData(); }

循序漸進開發(fā)WInform項目--系列文章導(dǎo)引:
循序漸進開發(fā)WinForm項目(6)--開發(fā)使用混合式Winform模塊
循序漸進開發(fā)WinForm項目(5)--Excel數(shù)據(jù)的導(dǎo)入導(dǎo)出操作
循序漸進開發(fā)WinForm項目(4)--Winform界面模塊的集成使用
循序漸進開發(fā)WinForm項目(3)--Winform界面層的項目設(shè)計
循序漸進開發(fā)WinForm項目(2)--項目代碼的分析
循序漸進開發(fā)WinForm項目(1) --數(shù)據(jù)庫設(shè)計和項目框架的生成

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容