⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f_idcard.pas

📁 用Delphi 开发的一个 户籍管理系统
💻 PAS
📖 第 1 页 / 共 2 页
字号:
////////////////////////////////////////////////////////////////////////////////
//                                                                            //  
//  单元用途:身份证号码相关处理                                              //
//  单元作者:池龙                                                            //
//  电子邮件:poolord@2ndhometown.net                                         //
//  个人主页:http://www.2ndhometown.net                                      //
//  开发平台:MS Windows 2000 Profrssional / Delphi 6                         //
//  最后更新:2005.01.16                                                      //
//                                                                            //  
////////////////////////////////////////////////////////////////////////////////
//                                                                            //  
//  许    可:                                                                //
//                                                                            //
//      您可以不受任何限制的使用、修改、分发这个单元,但请不要删除此说明。    //
//                                                                            //
//      作者对本单元不作任何显式或隐含的安全性和适用性的担保。                //
//                                                                            //
//      如果您对本单元进行了修改,请花几分钟发送一份拷贝给我,非常感谢。      //
//                                                                            //  
////////////////////////////////////////////////////////////////////////////////
//                                                                            //  
//  版本历史:                                                                //
//                                                                            //
//      2005.01.16  完成本单元                                                //
//                  基本功能: 1. 从身份证号码中取信息                        //
//                             2. 判断身份证号码的有效性                      //
//                             3. 将15位号码转换成18位号码                    //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //  
//  备    注:                                                                //
//                                                                            //
//      区划代码转换为名称的部分,需要从外部文件中读取区划定义的数据(如随单  //
//  元发布的文件 regioncode.dat )。                                          //
//                                                                            //
//      该文件为纯文本文件,每行是一个代码和名称的对应关系。代码和名称之间以  //
//  逗号作分隔。以#开头的行作为注释行,空行不处理。程序中作了一定的容错处理, //
//  通常情况下,不正确的数据会被略过。但在重新编排时,还是请尽量保证数据的正  //
//  确性。                                                                    //
//                                                                            //
//   另外,为了保证查找的效率,所以要求文件中的记录按区划代码由小到大的顺  //
// 序排列。                                                                 //
//                                                                            //  
////////////////////////////////////////////////////////////////////////////////

unit f_IDCard;

interface

uses
  Controls,
  Classes,
  SysUtils;

type
//性别
  TSex = (sexUnknown,   //未知
          sexMale,      //男性
          sexFemale);   //女性

//身份证号码的类型
  TIDNumType = (idnum15,   //15位
                idnum18);  //18位

//校验结果
  TChecksumRst = (csNoChecksum,       //无校验(15位)
                  csChecksumError,    //错误
                  csChecksumCorrect); //正确

//个人信息
  TIDNumInfo = record
    IDNumType   : TIDNumType;   //身份证号码类型
    RegionCode  : string;       //区划代码
    RegionStr   : string;       //区划名称
    BirthDay    : TDate;        //生日
    Sex         : TSex;         //性别
    ChecksumRst : TChecksumRst; //校验结果
  end;

//区划代码对应关系
  TRegionCodeTransRec = record
    RegionCode: string;     //代码
    RegionStr : string;     //名称
  end;

  TRegionCodeTransArray = array of TRegionCodeTransRec;

//分离过的区域代码
  TSepRegionCode = record
    ProvinceCode : string; //省级代码
    CityCode     : string; //市级代码
    CountyCode   : string; //区县级代码   
  end;

  TStrArray = array of string;

const
//18位身份证号码的校验方式中使用的常量
//从左向右,除了末尾的校验位之外,每位的权值
  cPosPowerArray : array[1..17] of integer = (7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);

//得到的校验值对应的第18位字符
  cCheckSumValueArray : array[0..10] of char = ('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');

//取身份证号码中的信息
//为了加快速度,不将区划代码进行转换
//需要取得确切的区划名称,用GetRegionStr函数
function GetIDNumInfo(IDNum: string; var IDNumInfo: TIDNumInfo): boolean;

//检查身份证号码的有效性
//内部仍然是利用GetIDNumInfo函数
function IsIDNumValid(IDNum: string): boolean;

//将15位身份证号码扩展为18位
function ExpandIDNum(IDNum15: string; var IDNum18: string): boolean;

//根据区划代码取相应的字符串
function GetRegionStr(RegionCode: string; FromFileName: string): string; overload;

function GetRegionStr(RegionCode: string): string; overload;

function GetRegionStr(var IDNumInfo: TIDNumInfo; FromFileName: string): boolean; overload;

function GetRegionStr(var IDNumInfo: TIDNumInfo): boolean; overload;

//从文件中区划代码信息
function LoadRegionDat(FromFileName: string; var RegionCodeArray: TRegionCodeTransArray): boolean; overload;
//下面这个函数的作用是直接将区划代码信息读入到本单元的公用变量里
function LoadRegionDat(FromFileName: string): boolean; overload;

implementation

var
  RegionCodeTransArray : TRegionCodeTransArray;

//判断这个字符是否为数字
function IsDigiChar(TestChar: Char): boolean;
begin
//直接判断文字
  Result := TestChar in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
//当然这里也可以使用判断字符ASCII值所在区间的方法,如:
//  Result := ord(TestChar) in [ord('0')..ord('9')];
end;

//判断一个字符串是否全部由数字组成
function IsDigiStr(TestStr: string): boolean;
var
  Count0 : integer;
begin
  if Length(TestStr) > 0 then
  begin
    Result := true;
    for Count0 := 1 to Length(TestStr) do
      if not IsDigiChar(TestStr[Count0]) then
      begin
        Result := false;
        Break;
      end;
  end else
    Result := false;
end;

//用于生成18位身份证号码中的校验字符
//注意:此函数不检查前17位的有效性以及其是否为数字
function GenIDNumCheckSumChar(IDNum18: string): char;
var
  DataSum : integer;
  Count0 : integer;
begin
  if length(IDNum18) = 18 then
  begin
    DataSum := 0;
//将前17位上的各个数字加权累加
    for Count0 := 1 to 17 do
      Inc(DataSum, StrtoInt(IDNum18[Count0]) * cPosPowerArray[Count0]);
//结果取模,再从字典中得到对应的字符
    Result := cCheckSumValueArray[DataSum mod 11];
  end else
    Result := ' ';
end;

//将15位身份证号码扩展为18位
function ExpandIDNum(IDNum15: string; var IDNum18: string): boolean;
var
  IDNumInfo: TIDNumInfo;
  TmpIDNum : string;
begin
  Result := false;
  IDNum18 := '';
//先检察原有的号码是否正确
  if (length(IDNum15) = 15) and GetIDNumInfo(IDNum15, IDNumInfo) then
  begin
//行政区划代码 + 生日 + 顺序码 + 校验
    TmpIDNum := IDNumInfo.RegionCode + formatdatetime('yyyymmdd', IDNumInfo.BirthDay) + Copy(IDNum15, 13, 3) + ' ';
//生成校验码,补到末位
    TmpIDNum[18] := GenIDNumCheckSumChar(TmpIDNum);
    IDNum18      := TmpIDNum;
    Result       := true;
  end;
end;

function GetIDNumInfo(IDNum: string; var IDNumInfo: TIDNumInfo): boolean;
var
  ToProcess : boolean;
  IDNumLen,
  Year, Month, Day : word;
  SexMark          : char;
begin
  Result := false;
  FillChar(IDNumInfo, sizeof(IDNumInfo), #0);

  IDNumLen := length(IDNum);
  if IDNumLen in [15, 18] then
  begin
    ToProcess := false;
//检查字符串是否符合要求
    case IDNumLen of
//15位身份证号码,全部要求为数字
      15  : begin
              ToProcess := IsDigiStr(IDNum);
              IDNumInfo.IDNumType := idnum15;
              IDNumInfo.ChecksumRst := csNoChecksum;
            end;
//18位身份证号码,前17位必须是数字,最后一位除数字外,可能是"X"
      18  : begin
              ToProcess := IsDigiStr(Copy(IDNum, 1, 17)) and (IsDigiChar(IDNum[18]) or (IDNum[18] in ['x', 'X']));
              IDNumInfo.IDNumType := idnum18;
            end;
    end;

    if ToProcess then
    begin
//取区划代码
      IDNumInfo.RegionCode := Copy(IDNum, 1, 6);
      
//取生日信息
      case IDNumInfo.IDNumType of
        idnum15 : begin
                    Year  := strtoint('19' + Copy(IDNum, 7, 2));
                    Month := strtoint(Copy(IDNum, 9, 2));
                    Day   := strtoint(Copy(IDNum, 11, 2));
                  end;
        idnum18 : begin
                    Year  := strtoint(Copy(IDNum, 7, 4));
                    Month := strtoint(Copy(IDNum, 11, 2));
                    Day   := strtoint(Copy(IDNum, 13, 2));
                  end;
        else
        begin
          Year  := 0;
          Month := 0;
          Day   := 0;
        end;
      end;
//尝试将生日信息转换成日期
      try
        IDNumInfo.BirthDay := EncodeDate(Year, Month, Day);
      except
        ToProcess := false;
      end;

      if ToProcess then

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -