在Console上使用Entity Framework將Excel及Word匯入至資料庫
用Visual Studio 2017做的,使用LINQ開發速度快很多很多很多!
1.首先,當然是建立Console專案...
檔案 => 新增 =>專案/方案 => 主控台應用程式 => 先命名「MyConsole」
2.利用NuGet加入Entity Framework套件至專案參考
工具 => NuGet封裝管理員 => 管理方案的NuGet套件 => 選「EntityFramework」
3.加入Microsoft Excel及Word的參考
專案 => 加入參考 => COM => 「Microsoft Word 12.0 Object Library」、「Microsoft Excel 12.0 Object Library」
4.加入Database模型
方案總管建立一個名為「Model」的資料夾 => 右鍵加入參考 => 新增項目 => Visual C# 項目 => 資料 => 選擇「ADO.NET」 => 命名「EntityDB」
ps. 連接完成後會自動將Database資訊加入App.config
5.寫程式看是匯入Word還是Excel
6.處理完的檔案成功的話就直接刪除,失敗的話移到特定資料夾
程式參考如下:
標頭
using System.Data.Entity;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
using MyConsole.Model; //連接Database的東東都在「Model」箱子唷,要記得加上!
資料夾構造樹狀分支Word、Excel
\\ServerName\e$\FileFolder\1.Word\xxxxxxxx.docx
\\ServerName\e$\FileFolder\2.Excel\xxxxxxxx.xlsx
主程式
static void Main(string[] args)
{
//連接EntityFramework DB
EntityDB db = new EntityDB();
//根路徑
string FilePathRoot = @"\\server\e$\FileFolder";
//事件名稱
string Event = null;
//跑迴圈抓根路徑底下資料夾的路徑
foreach(string EventsPath in Directory.GetDirectories(FilePathRoot))
{
//擷取資料夾名稱,分辨檔案類別
Event = EventsPath.Split('.').Last();
if (Event == "Word")
{
Word匯入(EventsPath);
}
if (Event == "Excel")
{
Excel匯入(EventsPath);
}
}
}
匯入Word:
static public void Word匯入(string EventsPath, string Event)
{
//連接Entity Framework
EntityDB db = new EntityDB();
//開啟Word應用程式
Word.Application wordApp = new Word.Application
{
DisplayAlerts = Word.WdAlertLevel.wdAlertsNone, //關閉警告
Visible = false, //背景執行
};
//讀取資料夾檔案,但排除開啟時產生的"~$"開頭的隱藏暫存檔
foreach(string MemberPath in Directory.GetFiles(EventsPath, @"*.*").Where(x => !x.Contains("~")))
{
//開啟路徑檔案
Word.Document wordDoc = wordApp.Documents.Open(MemberPath, ReadOnly:true, Visible:false);
Word.Table wordTable = wordDoc.Tables[1];
//初始宣告
string ErrorMessage = null;
bool 是否成功匯入 = true;
string FileName = xlWorkbooks.Name;
string SheetName = null;
try
{
//事前檢查
if (db.員工.Any(x => x.員工編號 == FileName))
{
員工 emp = db.員工.FirstOrDefault(x => x.員工編號 == FileName);
db.Configuration.ValidateOnSaveEnabled = false;
//設定狀態為可編輯
db.Entry(emp).State = EntityState.Modified;
員工 xl員工 = new 員工
{
員工編號 = FileName,
員工姓名 = wordTable.Cell(1,2).Range.Text.Trim().Replace("\r\a", string.Empty),
生日 = wordTable.Cell(2,2).Range.Text.Trim().Replace("\r\a", string.Empty)
};
//匯入DB
if (emp != null)
{
//更新, 此法無法用在啟用自動編號的表,新的Class會給該屬性null,卡到主鍵無法更新
//改成一個一個更新,如下
//emp.員工編號 = xl員工.員工編號;
//emp.員工姓名 = xl員工.員工姓名;
//emp.員工生日 = xl員工.員工生日;
db.Entry(emp).CurrentValues.SetValues(xl員工);
}
else
{
//新增
db.員工.Add(xl員工);
}
}
else
{
throw new Exception(FileName + " 無此人資料!")
}
}
catch (Exception ex)
{
ErrorMessage = "[" + SheetName + "] " + ex.Message;
是否成功匯入 = false;
}
finally
{
//寫Log紀錄
db.資料匯入紀錄.Add(new 資料匯入紀錄
{
員工編號 = FileName,
員工姓名 = emp.員工姓名,
資料類型 = Event,
匯入時間 = DateTime.Now,
是否成功 = 是否成功匯入,
失敗原因 = ErrorMessage
});
//最後一次執行儲存指令,刷新DB資料
db.SaveChanges();
//關閉工作簿
wordDoc.Close();
//讀完檔案後處理
移動檔案(MemberPath, Event, 是否成功匯入)
}
}
//所有檔案讀完後,關閉Excel應用程式
wordApp.Quit();
}
匯入Excel:
static public void Excel匯入(string EventsPath, string Event)
{
//連接Entity Framework
EntityDB db = new EntityDB();
//開啟Excel應用程式
Excel.Application xlApp = new Excel.Application
{
DisplayAlerts = false, //關閉警告
Visible = false, //背景執行
};
//讀取資料夾檔案,但排除開啟時產生的"~$"開頭的隱藏暫存檔
foreach(string MemberPath in Directory.GetFiles(EventsPath, @"*.*").Where(x => !x.Contains("~")))
{
//開啟路徑檔案
Excel.Workboos xlWorkbook = xlApp.Workbooks.Open(MemberPath);
//初始宣告
string ErrorMessage = null;
bool 是否成功匯入 = true;
string FileName = xlWorkbooks.Name;
string SheetName = null;
try
{
//事前檢查
if (db.員工.Any(x => x.員工編號 == FileName))
{
員工 emp = db.員工.FirstOrDefault(x => x.員工編號 == FileName);
db.Configuration.ValidateOnSaveEnabled = false;
//設定狀態為可編輯
db.Entry(emp).State = EntityState.Modified;
}
else
{
throw new Exception(FileName + " 無此人資料!")
}
//將每個sheet資料分別匯入
//只有一個sheet時,直接Excel.Worksheet xlWorksheet = xlWorkbook.Sheets[1];
//註:Excel的Sheet編號是從1開始,不是0
foreach (Excel.Worksheet xlWorksheet in xlWorkbook.Sheets)
{
switch (SheetName = xlWorksheet.Name)
{
case "SheetName1":
//先將Excel資料放入目標表的新class
//讀取Excel須數格子,讀取方式分Text, Value, Value2
//可上網查詢讀出來的差異在哪
員工 xl員工 = new 員工
{
員工編號 = FileName,
員工姓名 = xlWorksheet.Cells[1, 2].Text,
生日 = xlWorksheet.Cells[2, 2].Value,
//一併用列舉的方式變成編號抓值
層級 = (int)Enum.Parse(typeof(Enum層級), xlWorksheet.Cells[4, 2].Value2)
};
//匯入DB
if (emp != null)
{
//更新, 此法無法用在啟用自動編號的表,新的Class會給該屬性null,卡到主鍵無法更新
//改成一個一個更新,如下
//emp.員工編號 = xl員工.員工編號;
//emp.員工姓名 = xl員工.員工姓名;
//emp.員工生日 = xl員工.員工生日;
db.Entry(emp).CurrentValues.SetValues(xl員工);
}
else
{
//新增
db.員工.Add(xl員工);
}
break;
case "SheetName2":
//todo somethings
break;
case "SheetName3":
//todo somethings
break;
}
}
}
catch (Exception ex)
{
ErrorMessage = "[" + SheetName + "] " + ex.Message;
是否成功匯入 = false;
}
finally
{
//寫Log紀錄
db.資料匯入紀錄.Add(new 資料匯入紀錄
{
員工編號 = FileName,
員工姓名 = emp.員工姓名,
資料類型 = Event,
匯入時間 = DateTime.Now,
是否成功 = 是否成功匯入,
失敗原因 = ErrorMessage
});
//最後一次執行儲存指令,刷新DB資料
db.SaveChanges();
//關閉工作簿
xlWorkbook.Close();
//讀完檔案後處理
移動檔案(MemberPath, Event, 是否成功匯入)
}
}
//所有檔案讀完後,關閉Excel應用程式
xlApp.Quit();
}
後處理:移動檔案
static public void 移動檔案(string FilePath, string Event, bool 是否成功匯入)
{
//連接Entity Framework
EntityDB db = new EntityDB();
//初始宣告
string ErrorMessage = "[移動檔案]" + FilePath;
bool 是否成功移動檔案 = true;
try
{
//失敗檔案移動至目標資料夾,資料夾插入位置可用IndexOf(檔案名稱)或其他方式自己數
string DestinationPath = FilePath.Insert(40, @"\失敗的檔案");
if (!是否成功匯入)
{
File.Move(FilePath, DestinationPath);
}
//刪除原檔案
FileInfo fi = new FileInfo(FilePath);
fi.Delete;
}
catch (Exception ex)
{
ErrorMessage = ErrorMessage + " → " + ex.Message;
是否成功移動檔案 = false;
}
finally
{
//寫Log紀錄
db.資料匯入紀錄.Add(new 資料匯入紀錄
{
員工編號 = 0,
員工姓名 = "MyConsole",
資料類型 = Event,
匯入時間 = DateTime.Now,
是否成功 = 是否成功移動檔案,
失敗原因 = ErrorMessage
});
//最後一次執行儲存指令,刷新DB資料
db.SaveChanges();
}
}