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

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


下面我們來(lái)介紹這個(gè)在很多模塊里面常見(jiàn)的Excel導(dǎo)入亥啦、Excel導(dǎo)出操作是如何實(shí)現(xiàn)的。

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

由于我為了演示的目的翔脱,我在客戶(hù)信息表里面只是設(shè)計(jì)了幾個(gè)代表性的字段,下面我們來(lái)看看代碼生成工具自動(dòng)生成的界面后臺(tái)代碼是如何的媒鼓。

/// <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("序號(hào)|int,姓名,年齡,創(chuàng)建人,創(chuàng)建時(shí)間");
        DataRow dr;
        int j = 1;
        for (int i = 0; i < list.Count; i++)
        {
            dr = dtNew.NewRow();
            dr["序號(hào)"] = j++;
             dr["姓名"] = list[i].Name;
             dr["年齡"] = list[i].Age;
             dr["創(chuàng)建人"] = list[i].Creator;
             dr["創(chuàng)建時(shí)間"] = 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)錯(cuò)誤:{0}", error));
            }
            else
            {
                if (MessageDxUtil.ShowYesNoAndTips("導(dǎo)出成功届吁,是否打開(kāi)文件?") == 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)用公用類(lèi)庫(kù)模塊疚沐,彈出一個(gè)選擇保存文件的對(duì)話(huà)框,如果你沒(méi)有這個(gè)類(lèi)潮模,你可以自己添加代碼實(shí)現(xiàn)這個(gè)操作(這就是公用類(lèi)庫(kù)的好處亮蛔,在使用的時(shí)候能夠快速調(diào)用,減少代碼擎厢,提高效率)究流。
然后根據(jù)客戶(hù)錄入的條件檢索需要的數(shù)據(jù)內(nèi)容:
string where = GetConditionSql()
;
接著就是構(gòu)建一個(gè)相關(guān)字段的表格對(duì)象:DataTableHelper.CreateTable,這里面也是使用公用類(lèi)庫(kù)來(lái)方便創(chuàng)建各種字段的表格锉矢,默認(rèn)字段為字符串格式梯嗽,如果需要如整形格式的,可以通過(guò)|進(jìn)行分割沽损,如“序號(hào)|int” 灯节。
創(chuàng)建DataTable對(duì)象后,我們遍歷對(duì)象集合绵估,把它里面的數(shù)據(jù)一行行的賦值給DataRow對(duì)象就可以了炎疆。

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

賦值后,就是需要把DataTable對(duì)象轉(zhuǎn)換為Excel的操作過(guò)程了国裳,這里操作分為兩步形入,第一是創(chuàng)建Excel文檔,第二個(gè)是寫(xiě)數(shù)據(jù)的表頭和數(shù)據(jù)行信息缝左,也就是數(shù)據(jù)的寫(xiě)入操作亿遂,這里面我們把它封裝在公用類(lèi)庫(kù)里面浓若,方便模塊之間的調(diào)用。
導(dǎo)出Excel模塊采用了基于Aspose.Cell的組件進(jìn)行數(shù)據(jù)的寫(xiě)入操作:AsposeExcelTools.DataTableToExcel2
導(dǎo)出完成后蛇数,我們提示用戶(hù)是否打開(kāi)Excel文件挪钓。

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

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


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

相對(duì)于數(shù)據(jù)的導(dǎo)出操作盔性,Excel數(shù)據(jù)的導(dǎo)入操作會(huì)稍微麻煩一點(diǎn)霞丧,你至少需要選擇一個(gè)文件,文件最好以固定的模板進(jìn)行導(dǎo)入纯出,因此為了讓用戶(hù)確認(rèn)數(shù)據(jù)的有效性蚯妇,我們最好能提供了一個(gè)把Excel數(shù)據(jù)顯示出來(lái)再確認(rèn)導(dǎo)入的過(guò)程,這樣可以減少導(dǎo)入錯(cuò)誤數(shù)據(jù)的可能暂筝。
我們知道,這種常見(jiàn)的導(dǎo)入操作硬贯,很多業(yè)務(wù)模塊可能都需要焕襟,因此有必要考慮把它抽象出來(lái),作為一個(gè)通用的導(dǎo)入模塊饭豹,這樣我們可以多次利用鸵赖,非常方便,因此我們提煉這個(gè)通用導(dǎo)入的模塊特性如下所示拄衰。



Excel數(shù)據(jù)的導(dǎo)入模塊它褪,默認(rèn)生成界面的時(shí)候,也已經(jīng)一并生成了翘悉,我們來(lái)看看其中的代碼茫打。

private string moduleName = "客戶(hù)信息";
/// <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 是一個(gè)界面基礎(chǔ)模塊中定義的一個(gè)通用導(dǎo)入模塊,里面實(shí)現(xiàn)了一些如顯示Excel數(shù)據(jù)妖混,模板信息關(guān)聯(lián)老赤,保存數(shù)據(jù)的接口等操作。我們來(lái)看看它的程序運(yùn)行的效果制市。


其中我們通過(guò)代碼 dlg.SetTemplate 指定模板就是用來(lái)關(guān)聯(lián)Excel模板信息的抬旺,我們讓可以盡可能的選擇正確的模板進(jìn)行錄入數(shù)據(jù)。
用戶(hù)通過(guò)第2的標(biāo)識(shí)祥楣,指定要導(dǎo)入的Excel數(shù)據(jù)文件开财,選擇文件后汉柒,數(shù)據(jù)會(huì)自動(dòng)顯示出來(lái)方便確認(rèn)。
但我們選擇保存數(shù)據(jù)的操作的時(shí)候责鳍,這個(gè)通用模塊會(huì)執(zhí)行保存的邏輯代碼碾褂,并調(diào)用由創(chuàng)建者實(shí)現(xiàn)的代碼邏輯,如上面代碼的dlg.OnDataSave就是在執(zhí)行保存的時(shí)候薇搁,執(zhí)行的代碼邏輯斋扰,我們來(lái)看看生成的一些代碼實(shí)現(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)建時(shí)間"].ToString(), out dt);
    if (converted && dt > dtDefault)
    {
        info.CreateTime = dt;
    }

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

我們知道啃洋,導(dǎo)入的時(shí)候传货,是遍歷每行Excel進(jìn)行數(shù)據(jù)保存操作的,因此我們這里給出了一個(gè)一行的操作代碼即可:bool ExcelData_OnDataSave(DataRow dr)宏娄,里面的邏輯问裕,在數(shù)據(jù)保存的時(shí)候會(huì)被模塊進(jìn)行調(diào)用。
上面的操作孵坚,是一條條的進(jìn)行操作粮宛,如果累計(jì)超過(guò)3條記錄出錯(cuò),模塊提示是否繼續(xù)還是退出卖宠。
這里面并沒(méi)有采用事務(wù)的操作巍杈,對(duì)于一些如Sqlite的大批量的數(shù)據(jù)操作(速度提升很快),建議采用事務(wù)進(jìn)行處理扛伍,關(guān)于這個(gè)可以參考《Winform開(kāi)發(fā)框架之通用數(shù)據(jù)導(dǎo)入導(dǎo)出操作的事務(wù)性操作完善》進(jìn)行修改調(diào)整筷畦。
最后,我們的Excel數(shù)據(jù)導(dǎo)入完成后刺洒,為了及時(shí)更新主界面的數(shù)據(jù)鳖宾,我們也定義了一個(gè)事件作為回調(diào),如下所示逆航。

dlg.OnRefreshData += new EventHandler(ExcelData_OnRefreshData);

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市因俐,隨后出現(xiàn)的幾起案子拇惋,更是在濱河造成了極大的恐慌,老刑警劉巖女揭,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚤假,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吧兔,警方通過(guò)查閱死者的電腦和手機(jī)磷仰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)境蔼,“玉大人灶平,你說(shuō)我怎么就攤上這事伺通。” “怎么了逢享?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵罐监,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瞒爬,道長(zhǎng)弓柱,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任侧但,我火速辦了婚禮矢空,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘禀横。我一直安慰自己屁药,他們只是感情好伍茄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布题山。 她就那樣靜靜地躺著弧关,像睡著了一般蟹腾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扔水,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天蛉加,我揣著相機(jī)與錄音惜颇,去河邊找鬼抬闷。 笑死械巡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饶氏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼有勾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼疹启!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蔼卡,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤喊崖,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后雇逞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體荤懂,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年塘砸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了节仿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掉蔬,死狀恐怖廊宪,靈堂內(nèi)的尸體忽然破棺而出矾瘾,到底是詐尸還是另有隱情,我是刑警寧澤箭启,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布壕翩,位于F島的核電站,受9級(jí)特大地震影響傅寡,放射性物質(zhì)發(fā)生泄漏放妈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一荐操、第九天 我趴在偏房一處隱蔽的房頂上張望芜抒。 院中可真熱鬧,春花似錦淀零、人聲如沸挽绩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)唉堪。三九已至,卻和暖如春肩民,著一層夾襖步出監(jiān)牢的瞬間唠亚,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工持痰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灶搜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓工窍,卻偏偏與公主長(zhǎng)得像割卖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子患雏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容