Delphi表单验证异常:条件未满足仍触发数据库上传且报无效整数错误
Delphi表单数据上传验证逻辑问题分析与修复
问题根源
你的代码存在两个核心问题,导致空值检查不通过时仍触发数据库上传并报错:
- 空值检查后未终止流程:即使空值验证失败(弹出"Complete All Fields!"),后续代码仍会继续执行,包括对
vidn的字符串截取和strtoint转换——当vidn为空时,copy(vidn,1,2)返回空字符串,strtoint就会抛出"is not a valid integer"错误。 - 验证顺序不合理:依赖
vidn的年龄计算逻辑,放在了空值检查之后但没有阻断,导致无效数据进入转换流程。
关键修复点
- 空值验证失败时,立即调用
Exit终止整个按钮点击事件流程,避免后续无效代码执行。 - 在对
vidn执行strtoint前,先检查其是否为纯数字,防止非数字字符触发转换错误。 - 调整验证顺序,先完成所有基础格式验证,再执行业务逻辑检查(如年龄、重复ID)。
修正后的代码
unit Unit6; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Spin, ExtCtrls,unit7,unit5,unit4, DB, ADODB, Grids, DBGrids, pngimage; type Tfrmupload = class(TForm) Panel1: TPanel; edtname: TEdit; edtsurn: TEdit; edtidn: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label5: TLabel; Label6: TLabel; Panel2: TPanel; btnupload: TButton; edtmail: TEdit; cbprov: TComboBox; Image1: TImage; cbdiv: TComboBox; Label4: TLabel; procedure btnuploadClick(Sender: TObject); procedure Label7Click(Sender: TObject); private { Private declarations } function IsStringNumeric(const S: string): Boolean; public { Public declarations } end; var frmupload: Tfrmupload; implementation {$R *.dfm} // 辅助函数:检查字符串是否为纯数字 function Tfrmupload.IsStringNumeric(const S: string): Boolean; var I: Integer; begin Result := True; for I := 1 to Length(S) do if not (S[I] in ['0'..'9']) then begin Result := False; Break; end; end; procedure Tfrmupload.btnuploadClick(Sender: TObject); var vname, vsurname, c, vidn, vprov, vmail, vdiv: string; year, i, age: Integer; bnotnull, bidl, bmail, byoung, valid, idrepeated: Boolean; dt: TDateTime; begin vname := edtname.Text; vsurname := edtsurn.Text; vidn := edtidn.Text; vdiv := cbdiv.Text; vprov := cbprov.Text; vmail := edtmail.Text; // 初始化验证标记 bnotnull := False; bidl := False; bmail := False; byoung := False; idrepeated := False; valid := False; // 1. 空值检查:不通过直接终止流程 if (vname = '') or (vsurname = '') or (vidn = '') or (vprov = '') or (vmail = '') or (vdiv = '') then begin ShowMessage('Complete All Fields!'); Exit; // 终止后续代码执行 end; bnotnull := True; // 2. ID格式检查:长度+纯数字验证 if Length(vidn) <> 13 then begin ShowMessage('ID Number must be 13 characters'); Exit; end; bidl := True; if not IsStringNumeric(vidn) then begin ShowMessage('ID Number must contain only digits'); Exit; end; // 3. 重复ID检查 if unit5.frmadmin.ADODetails.Locate('ID number', vidn, []) then begin ShowMessage('ID Number already exists'); idrepeated := True; Exit; end; // 4. 年龄计算与合法性检查 dt := Now; year := StrToInt(FormatDateTime('yyyy', dt)); c := Copy(vidn, 1, 2); if (StrToInt(c) >= 0) and (StrToInt(c) <= 22) then age := year - (2000 + StrToInt(c)) else age := year - (1900 + StrToInt(c)); if age < 6 then begin ShowMessage('Contestant too young, cannot compete'); byoung := True; Exit; end; // 5. 邮箱格式检查(基础版,可扩展更严格规则) bmail := Pos('@', vmail) > 1; // @不能在开头,且至少存在一个 if not bmail then begin ShowMessage('Incorrect Email Format'); Exit; end; // 所有验证通过,执行数据库上传 valid := True; if valid then begin unit5.frmadmin.ADODetails.Append; unit5.frmadmin.ADODetails['Name(s)'] := vname; unit5.frmadmin.ADODetails['Surname'] := vsurname; unit5.frmadmin.ADODetails['ID Number'] := vidn; unit5.frmadmin.ADODetails['Age'] := age; unit5.frmadmin.ADODetails['Province'] := vprov; unit5.frmadmin.ADODetails['Email'] := vmail; unit5.frmadmin.ADODetails.Post; unit4.frmcontest.ADOLead.Insert; unit4.frmcontest.ADOLead['ID Number'] := unit4.frmcontest.DBComboID.Text; unit4.frmcontest.ADOLead['Name(s)'] := unit4.frmcontest.DBCombonme.Text; unit4.frmcontest.ADOLead['Division'] := vdiv; unit4.frmcontest.ADOLead.Post; ShowMessage('Details Uploaded'); frmupload.Hide; end; // 清空输入 edtname.Clear; edtsurn.Clear; edtidn.Clear; cbdiv.Text := ''; cbprov.Text := ''; edtmail.Clear; end; procedure Tfrmupload.Label7Click(Sender: TObject); begin frmupload.Hide; end; end.
额外说明
- 添加了
IsStringNumeric辅助函数,确保vidn是纯数字后再执行转换,避免类型错误。 - 每个验证步骤不通过时都立即
Exit,彻底阻断后续无效代码,包括数据库上传逻辑。 - 邮箱验证做了简单优化,确保
@不在字符串开头,你可以根据需求扩展为更严格的正则验证。
内容的提问来源于stack exchange,提问作者Mr Engine
相关产品推荐
相关产品推荐

