基于 WeihanLi.Npoi 實現excel導入時純漢字的日期轉換
Intro
前段時間有位小伙伴在 Github 上提了一個 “不能識別純漢字的日期格式” issue
二〇二二年一月一日
格式的日期單元格識別不出來會變成,0001/1/1 0:00:00
如何讓它能夠識別出來呢,基于 InputFormatter
的強大擴展性支持,我們只需要實現一個從純漢字的日期轉換成標準日期的一個轉換即可,詳細參考后面的實現
Implement
首先去網上找了一個將支持將漢字日期轉換的方法,實現來自于 http://luoma.pro/Content/Detail/671?parentId=1,(代碼有點長,這里只是截出來一部分只是作為示例,有需要的小伙伴也可以自己寫一個
//?http://luoma.pro/Content/Detail/671?parentId=1
public?static?class?DateTimeUtils
{public?static?bool?TransStrToDateTime(string??str,?out?DateTime?dt){dt?=?default;if?(str.IsNullOrEmpty())return?false;//第一次轉換if?(DateTime.TryParse(str,?out?dt)){return?true;}//第二次轉換string[]?format?=?new?string[]{"yyyyMMdd","yyyyMdHHmmss","yyyyMMddHHmmss","yyyy-M-d","yyyy-MM-dd","yyyy-MM-dd?HH:mm:ss","yyyy/M/d","yyyy/MM/dd","yyyy/MM/dd?HH:mm:ss","yyyy.M.d","yyyy.MM.dd","yyyy.MM.dd?HH:mm:ss","yyyy年M月d日","yyyy年MM月dd日","yyyy年MM月dd日HH:mm:ss","yyyy年MM月dd日?HH時mm分ss秒"};if?(DateTime.TryParseExact(str,?format,?CultureInfo.InvariantCulture,?DateTimeStyles.None,?out?dt)){return?true;}//第三次轉換try{if?(Regex.IsMatch(str,?"^(零|〇|一|二|三|四|五|六|七|八|九|十){2,4}年((正|一|二|三|四|五|六|七|八|九|十|十一|十二)月((一|二|三|四|五|六|七|八|九|十){1,3}(日)?)?)?$")){var?match?=?Regex.Match(str,?@"^(.+)年(.+)月(.+)日$");if?(match.Success){int?year?=?GetYear(match.Groups[1].Value);int?month?=?GetMonth(match.Groups[2].Value);long?dayL?=?ParseCnToInt(match.Groups[3].Value);dt?=?new?DateTime(year,?month,?int.Parse(dayL.ToString()));return?true;}}}catch{return?false;}return?false;}
}
接下來來準備一個測試方法和 model:
private?sealed?class?ChineseDateFormatter
{public?sealed?class?ChineDateTestModel{public?DateTime?Date?{?get;?set;?}}public?static?DateTime?FormatInput(string??input){if?(DateTimeUtils.TransStrToDateTime(input,?out?var?dt)){return?dt;}throw?new?ArgumentException("Invalid?date?input");}
}
最終配置和導入實現代碼如下:
FluentSettings.For<ChineseDateFormatter.ChineDateTestModel>().Property(x?=>?x.Date).HasColumnInputFormatter(ChineseDateFormatter.FormatInput);var?excelPath?=?"<excelPath>";?
var?list?=?ExcelHelper.ToEntityList<ChineseDateFormatter.ChineDateTestModel>(excelPath);
var?item?=?list[0];
Guard.NotNull(item);
Assert.Equal(DateTime.Parse("2022-01-01"),?item.Date);
這里我們導入一個純漢字的日期來測試一下,excel 內容示例如下:
導入結果如下:
可以看到我們導入的時間此時已經不再是默認值了,可以正常讀取出來了
More
其他類似的需求也可以通過這種方式來實現,InputFormatter
主要是針對導入的處理,OutputFormatter
主要針對導出的處理,更多示例可以參考介紹:https://weihanli.github.io/WeihanLi.Npoi/docs/articles/zh/InputOutputFormatter.html(也支持 CSV 的處理)
目前覺得這種純漢字的日期比較少,我們基本不會用到,也不建議使用,因為大部分庫應該都是不支持的
所以目前建議自己實現一個 formatter
如果用到的朋友比較多的話,也可以考慮集成在 package 里這樣大家使用起來會更方便,歡迎需要的朋友進行反饋
References
https://github.com/WeihanLi/WeihanLi.Npoi/commit/f98f624dfc2b2adf56ccd34a7f8964dde53ec291
https://github.com/WeihanLi/WeihanLi.Npoi
https://www.nuget.org/packages/WeihanLi.Npoi/