Excel 身份證號碼合法性校驗函數說明及其代碼邏輯


安裝與使用

工具是一個ExcelDNA的 xll 加載項,如下圖,32位Excel裝前者,64位裝后者。

 

 64位Excel加載如圖(還可以配合ExcelDNA的函數參數提示支持xll,這里不做說明)

 

 在【公式】—【函數】可以找到IDCardFuns類下的IDNumCheck函數,用法是=IDNumCheck(身份證號碼,性別)

 

 

實現邏輯與代碼

身份證號碼合法性校驗的一般邏輯有:

①位數

18位沒得商量;

②性別

一般校驗時會有先期錄入的性別(“男” or “女”),與通過身份證號碼計算出來的性別等於比較;

③出生年月日

a.年齡 是當前計算機系統的年份與身份證年份的差值,大於100判斷為錯誤(這是一個懷疑錯誤),身份證年份大於系統年份也判斷為錯誤;

b.月份 必須在[1,12]區間內,多了 少了都不對;

c.日期 1.3.5.7.8.10.12這幾個31天沒得跑,不在[1,31]是不對的,4.6.9.11是[1,30],2月的更復雜了,還得去分平閏年,區間為[1,28]或[1,29]。

④校驗碼

這個東西應該不多見,但必要。

二代身份證號碼的前17位數字是可以通過一個算法,算出第18位的,第18位就叫做校驗碼。

這個馬的邏輯在這兒 

整個代碼貼到下面

  public class IDCardFuncs { [ExcelFunction(Name = "GetGenderFromIDNum", Description = "18位身份證號碼提取性別,號碼不是18位返回錯誤提示。", Category = "IDCardFuncs", IsMacroType = true)] public static string GetGenderFromIDNum(string idNumber) { if (idNumber.Length == 18) { int num; if (int.TryParse(idNumber.Substring(16, 1), out num)) { return (num % 2) switch { 1 => "", 0 => "", _ => "" }; } else { return "身份證號碼第16位不是數值"; } } else { return "身份證號碼不為18位"; } } [ExcelFunction(Name = "IDNumCheck", Description = "18位身份證號碼合法性檢查", Category = "IDCardFuncs", IsMacroType = true)] public static string IDNumCheck(string idNum, string gender) { if (idNum.Length != 18) return "身份證號碼應為18位"; else if (!GenderCheck(idNum, gender)) return "性別與身份證號碼不匹配"; else if (!DateCheck(idNum)) return "身份證號碼出生日期有誤"; else if (CodeCheck(idNum) != idNum.Substring(17, 1).ToUpper()) return $"校驗碼不正確,最后一位是{CodeCheck(idNum)}"; else
                return "True"; } private static bool GenderCheck(string idNum, string gender) { return IDCardFuncs.GetGenderFromIDNum(idNum) == gender; } private static bool DateCheck(string idNum) { bool dateBool = true; int year = int.Parse(idNum.Substring(6, 4)); int month = int.Parse(idNum.Substring(10, 2)); int date = int.Parse(idNum.Substring(12, 2)); //年份大於系統時間或者小於當前年份的前100年(大於100歲)判為錯
            if (year > System.DateTime.Now.Year || year < System.DateTime.Now.Year - 100 || month < 1 || month > 12) dateBool = false; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: if (date == 0 || date > 31) dateBool = false; break; case 2: if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { if (date == 0 || date > 29) dateBool = false; } else { if (date == 0 || date > 28) dateBool = false; } break; default: if (date == 0 || date > 30) dateBool = false; break; } return dateBool; } private static string CodeCheck(string idNum) {
//變量名懶得想,用了奇葩命名法。
int[] 數字 = new int[idNum.Length]; for (int i = 0; i < idNum.Length - 1; i++) //轉身份證號碼字符串前17位為int型數組 { 數字[i] = int.Parse(idNum.Substring(i, 1)); } int[] 系數 = new int[] { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; int 前17位與系數乘積之和 = 0; for (int i = 0; i < 17; i++) { 前17位與系數乘積之和 = 前17位與系數乘積之和 + 數字[i] * 系數[i]; } int 余數 = 前17位與系數乘積之和 % 11; return 余數 switch { 0 => "1", 1 => "0", 2 => "X", 3 => "9", 4 => "8", 5 => "7", 6 => "6", 7 => "5", 8 => "4", 9 => "3", 10 => "2", _ => "" }; } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM