文章目錄
匯出 Excel 時使用多國語系 Resource 當做欄位名稱
之前筆記 使用 C# 將資料匯出成 Excel (.xlsx) 紀錄到使用 ClosedXML 搭配 generic 與 reflection 匯出 excel,方便使用者自行調整資料報表
剛好有個系統需要支援多國語系,連帶地使用者對要求 excel 也需要有多國語系,雖然資料內容無法隨意改變,但 excel 的欄位名稱就有調整的空間,就來看看可以如何處理吧
使用 Resource
加入 Resource
專案上按右鍵 –> Add –> New Item…
Visual C# Items –> Resource File –> 指定 .resx 名稱
使用 ResXManager 來管理多國語系文字
搜尋並安裝
ResXManager
VS 主選單 Tools –> ResX Manager
加入新語言
加入新字串
第一次填寫不同語言時會提示建立 Resource 檔案
將多國語系 Resource 加入 Excel 匯出
excel helper 直接取用 resource 內容
範本
Resource.ResourceManager.GetString({resource key}, {target CultureInfo};
實例
Resource.ResourceManager.GetString("Name", new CultureInfo("zh-TW"));
將 resource 相關資訊傳入 excel helper
調整 excel helper
允許可傳入 ResourceManager 及 CultureInfo
ResourceManager _rm; CultureInfo _ci; public XSLXHelper() : this(null, null) { } public XSLXHelper(ResourceManager rm, CultureInfo ci) { _rm = rm; _ci = ci; }
調整取欄位邏輯
if (_rm != null) { //依 resource key 及 CultureInfo 取得 resource 內容 string resourceName = _ci == null ? _rm.GetString(item.Name) : _rm.GetString(item.Name, _ci); //如 resource key 取不到資料則使用屬性名稱 sheet.Cell(1, colIdx++).Value = string.IsNullOrWhiteSpace(resourceName) ? item.Name : resourceName; } else sheet.Cell(1, colIdx++).Value = item.Name;
程式呼叫
XSLXHelper helper = new XSLXHelper(new System.Resources.ResourceManager(typeof(Resource)), new CultureInfo("zh-TW"));
完整程式碼
using ClosedXML.Excel; using System; using System.Collections.Generic; using System.Globalization; using System.Resources; namespace TestHelper { public class XSLXHelper { ResourceManager _rm; CultureInfo _ci; public XSLXHelper() : this(null, null) { } public XSLXHelper(ResourceManager rm, CultureInfo ci) { _rm = rm; _ci = ci; } /// <summary> /// 產生 excel /// </summary> /// <typeparam name="T">傳入的物件型別</typeparam> /// <param name="data">物件資料集</param> /// <returns></returns> public XLWorkbook Export<T>(List<T> data) { //建立 excel 物件 XLWorkbook workbook = new XLWorkbook(); //加入 excel 工作表名為 `Report` var sheet = workbook.Worksheets.Add("Report"); //欄位起啟位置 int colIdx = 1; //使用 reflection 將物件屬性取出當作工作表欄位名稱 foreach (var item in typeof(T).GetProperties()) { #region - 直接使用物件屬性名稱 - if (_rm != null) { //依 resource key 及 CultureInfo 取得 resource 內容 string resourceName = _ci == null ? _rm.GetString(item.Name) : _rm.GetString(item.Name, _ci); //如 resource key 取不得資料則使用屬性名稱 sheet.Cell(1, colIdx++).Value = string.IsNullOrWhiteSpace(resourceName) ? item.Name : resourceName; } else sheet.Cell(1, colIdx++).Value = item.Name; #endregion } //資料起始列位置 int rowIdx = 2; foreach (var item in data) { //每筆資料欄位起始位置 int conlumnIndex = 1; foreach (var jtem in item.GetType().GetProperties()) { //將資料內容加上 "'" 避免受到 excel 預設格式影響,並依 row 及 column 填入 sheet.Cell(rowIdx, conlumnIndex).Value = string.Concat("'", Convert.ToString(jtem.GetValue(item, null))); conlumnIndex++; } rowIdx++; } return workbook; } } }
//想要匯出的資料集 var users = new List<User>() { new User(){Name="Yowko",Salary=10,Address="Taipei",Birthday=new DateTime(1983,7,29) }, new User(){Name="Test",Salary=20,Address="USA",Birthday=new DateTime(1993,7,29) }, }; //xlsx 檔案位置 string filepath = $@"./{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"; //建立 xlxs 轉換物件 XSLXHelper helper = new XSLXHelper(new System.Resources.ResourceManager(typeof(Resource)), new CultureInfo("zh-TW")); //取得轉為 xlsx 的物件 var xlsx=helper.Export(users); //存檔至指定位置 xlsx.SaveAs(filepath);
心得
在 excel helper 中直接依 CultureInfo 取得 resource 內容適用於 excel helper 與 Resource 在同個專案中,如果像同事遇到的狀況: excel helper 獨立存在於 library 專案中沒有 resource 概念時,就可以透過將 ResourceManager 與 CultureInfo 傳入來處理
重新 review 程式碼,實際的程式碼並不多,概念與難度也不難,但卻花好幾個小時才找到真正的做法,我想主要原因是過往工作缺乏多國語系需求的關係,明顯經驗與相關知識都不足,而這就是做專案的趣味所在,常常有意外的需求來增加工作樂趣跟自我挑戰
參考資訊
文章作者 Yowko Tsai
上次更新 2021-10-28
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。