• 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", _ => "" }; } }
  • 相关阅读:
    MFiX做增量编译的时候不要删掉*.mod和*.inc文件
    Paraview教程
    origin生成直方图
    DEM轨迹后处理
    Zotero导入Markdown here插件
    origin把点图和线图放在一起
    mfix中输出DEM颗粒的固相速度到网格
    一个好用的ssh终端:MobaXterm
    GDB:从单线程调试到多线程调试(MFiX单步调试)
    操作系统概论-06
  • 原文地址:https://www.cnblogs.com/yzhyingcool/p/14069588.html
Copyright © 2020-2023  润新知