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