Živě.cz o počítačích a internetu

Tipy a triky v Delphi, díl 187. – IBAN

Jan Šindelář 1.6.2005

Dnešní tip bude opět směřovat více do praxe a tentokrát do praxe bankovní. Ukážeme si, jak ověřovat platnost čísla bankovního účtu zadaného v mezinárodním formátu. Toto ověřování pak můžete použít v účetních programech či libovolných informačních systémech, kam se tento údaj zadává.

Co je IBAN?

Nejprve si povíme něco málo teorie. Odborníkům z bankovního sektoru se předem omlouvám za případné nepřesnosti, je to přeci jen hlavně programátorský článek a případné doplňující komentáře rád uvítám pod článkem.

IBAN, tedy International Bank Account Number, je formát pro zápis bankovního čísla účtu, který umožňuje mezinárodně identifikovat konkrétní účet, finanční instituci a zemi původu. I vy byste jej měli nalézt na svém výpisu z účtu, neboť po našem vstupu do EU jsou banky povinny tento údaj na výpisu uvádět. Má přesně stanovený formát a pomocí určitých kontrolních součtů (což je tématem dnešního článku) lze ověřit platnost takového účtu. Jedná se samozřejmě o platnost "syntaktickou", nelze prověřit programem existenci účtu jako takového. Zajímají-li vás další podrobnosti, navštivte odkazy uvedené ve zdrojích na konci článku.

Pro nás je tedy důležitý právě zmiňovaný formát IBANu, jehož splnění budeme kontrolovat. Tak tedy, IBAN je tvořen minimálně 5 a maximálně 34 znaky. Tyto znaky mohou být jednak číslice a pak rovněž velká písmena latinky A až Z. V psané formě mohou být některé "sekce" IBANu odděleny mezerou, ale v elektronické verzi se nesmí mezery použít a IBAN s mezerami nebude tím pádem naším programem vyhodnocen jako validní.

První dva znaky celého řetězce jsou vždy písmena a tvoří ISO kód země (tj. pro Českou republiku je to CZ). Další dva znaky jsou naopak vždy číslice a využívají se právě pro kontrolní součet. Zbylých maximálně 30 znaků pak tvoří kód dané banky a konkrétní číslo účtu.

Kontrolní algoritmus

Postup pro ověřování je sice možná na první poslech poněkud krkolomný, ale čistě programátorsky to není úloha příliš obtížná. Nejprve vezmeme první čtyři znaky (tedy kód země a dvě kontrolní číslice) a přesuneme je na konec řetězce. Tedy např.:

CZ6508000000192000145399 - > 08000000192000145399CZ65

Dalším krokem je převod všech znaků na čísla od 0 do 35. Původní číslice tedy zůstanou stejné, písmeno A bude převedeno na číslo 10, B na 11 atd.. až Z je rovno 35. Náš ukázkový účet se tedy změní na:

08000000192000145399123565

A nyní přichází hlavní finta celé operace. Vydělíme-li toto velké číslo číslem 97, musíme dostat zbytek 1. V tom případě je číslo účtu správné. Jiný výsledek značí, že je účet špatný. Zbývá nám tedy zjistit zbytek po dělení získaného čísla a 97. To může být obtížné i pro počítač (resp. můžeme narazit na omezení ve funkcích daného programovacího jazyka) a tak lze použít menší "trik". Původní velké číslo si rozkouskujeme na menší části. Ty poté dělíme každou zvlášť číslem 97 tím způsobem, že zbytek po prvním dělení přidáme k následujícímu číslu (tedy nepřičteme, ale napíšeme "před něj"). Takto pokračujeme až do konce. Názorně to ukazuje opět příklad s naším fiktivním číslem účtu:

původní číslo rozdělíme na tyto části:

08000000 19200014 53991235 65

a poté dělíme:

08000000 dělíme 97, zbytek je 22

2219200014 dělíme 97, zbytek 64

6453991235 dělíme 97, zbytek 11

1165 dělíme 97, zbytek 1

Náš ukázkový účet je tedy platný. Když už tedy známe teorii, pustíme se do programu. Formulář bude obsahovat jen Edit, do kterého vyplníme IBAN, a tlačítko, které spustí ověřování.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function CheckIBAN(iban: string): boolean;
var
  a: char;
  v, l, rest: Integer;
  alpha: string;
  number: Longint;
begin
  iban := iban + Copy(iban, 1, 4);
  Delete(iban, 1, 4);
  for a := `A` to `Z` do iban := StringReplace(iban, a, IntToStr(Ord(a) - 55), [rfReplaceAll]);
  v := 1;
  l := 9;
  rest := 0;
  alpha := ``;
  try
    while v <= Length(iban) do
    begin
      if l > Length(iban) then l := Length(iban);
      alpha := alpha + Copy(iban, v, l);
      number := StrToInt(alpha);
      rest := number mod 97;
      v := v + l;
      alpha := IntToStr(rest);
      l := 9 - Length(alpha);
    end;
  except
    rest := 0;
  end;
  if rest <> 1 then Result := false
              else Result := true;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if CheckIBAN(Edit1.Text) then ShowMessage(`IBAN je validní`)
                          else ShowMessage(`IBAN NENÍ validní`);
end;

end.

Kód počítá s tím, že vložíme IBAN formálně ve správném formátu, takže nesmí obsahovat mezery ani jiné znaky než číslice a velká písmena. Není kontrolována ani délka řetězce. Případnou kontrolu vstupu si jistě snadno doprogramujete sami. A tím pro dnešek končíme. Ukázkový projekt najdete zde.

Zdroje