Hier een unit met daarin functies voor het checken van BTW nummers van verschillende EU landen. Niet alle landen geven hun formule voor de controle zomaar vrij en dus kan het lastig zijn om hier achter te komen. Daarom deze thread.

Mijn voorganger heeft enkele functies geschreven (indent = 3) en ik de rest (indent = 1).

Mocht iemand nog de formules hebben voor andere landen dan zou ik dat heel graag horen.

[ ik weet het, excuses voor de rommelige code]


Code:
unit VAT_CheckFuncs;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ComCtrls,
  Menus, DBCtrls, StdCtrls, Mask, Db, DBTables, Grids, DBGrids, FileCtrl, jpeg;


Function ATcheck(VATnr: string): Boolean;
Function BEcheck(VATnr: string): Boolean;
Function DEcheck(VATnr: string): Boolean;
Function DKcheck(VATnr: string): Boolean;
Function FIcheck(VATnr: string): Boolean;
Function FRcheck(VATnr: string): Boolean;
Function GBcheck(VATnr: string): Boolean;
Function ITcheck(VATnr: string): Boolean;
Function LUcheck(VATnr: string): Boolean;
Function NLcheck(VATnr: string): Boolean;
Function NOcheck(VATnr: string): Boolean;
Function SEcheck(VATnr: string): Boolean;
Function EScheck(VATnr: string): Boolean;
Function GRcheck(VATnr: string): Boolean;
Function IRcheck(VATnr: string): Boolean;
Function PTcheck(VATnr: string): Boolean;

implementation

////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  VAT CALCULUS HELPER FUNCTIONS
//
////////////////////////////////////////////////////////////////////////////////////////////////////


//
Function MultiplyAdd(Digit1,Digit2 : string) : integer;
var s : string;
begin
 s := IntToStr(StrToInt(Digit1) * StrToInt(Digit2));
 if(Length(s) > 1) then
  result := StrToInt(s[1]) + StrToInt(s[2])
 else
  result := StrToInt(s);
end;

//Trek een nummer uit een string beginnend op start pos tot eind pos.///////////////////////////////
Function ExtractNumFromStr(Str: String;iStart,iEnd : integer) : Integer;
var s : string;
    i : integer;
begin
 i := iStart;
 s := '';
 while i <= iEnd do begin
  s := s + Str[i];
  i := i + 1;
 end;
 result := StrToInt(s);
end;


////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  VAT CALCULUS FUNCTIONS
//
////////////////////////////////////////////////////////////////////////////////////////////////////


//Oosterijk.////////////////////////////////////////////////////////////////////////////////////////
Function ATcheck(VATnr: string): Boolean;
var i : integer;
begin
 try
  if VATnr[1] <> 'U' then begin
   result := false;
   EXIT;
  end;
  i := StrToInt(VATnr[2])
     + MultiplyAdd('2',VATnr[3])
     + StrToInt(VATnr[4])
     + MultiplyAdd('2',VATnr[5])
     + StrToInt(VATnr[6])
     + MultiplyAdd('2',VATnr[7])
     + StrToInt(VATnr[8]);
  i := 10 - ((i+4) mod 10);
  if (i = 10) then i := 0;
  result := (StrToInt(VATnr[9]) = i);
 except
  result := false;
 end;
End;

//Belgie.///////////////////////////////////////////////////////////////////////////////////////////
Function BEcheck(VATnr: string): Boolean;
var deelwaarde, rechts2: Integer;
begin
     If Length(vatnr) <> 9 Then              //Controle op de lengte
        Result := false
     else
         begin
              If (strtoint(copy(vatnr,1,1))=0) Or
                 (strtoint(copy(vatnr,1,1))=1) Or
                 (strtoint(copy(vatnr,1,1))=8) Then
                 Result := false                //Controle op eerste cijfer
              else
                  begin
                       deelwaarde:=(97-(strtoint(copy(vatnr,1,7)) Mod 97));  //Bepaal de rest bij deling en haal dat getal van 97 af
                       rechts2:=strtoint(copy(vatnr,8,2));                    //Bepaal het controlegetal
                       If deelwaarde <> rechts2 Then
                          Result := false
                       else
                          Result := true;
                  end;
         end;
End;

//Duitsland.////////////////////////////////////////////////////////////////////////////////////////
Function DEcheck(VATnr: string): Boolean;
var a, s, k, b, rechts1, teller: Integer;
begin
     If Length(vatnr) <> 9 Then
        Result := false
     else
         begin
              a:=10;
              s:=(strtoint(copy(vatnr, 1, 1)) + a) Mod 10;
              If s=0 Then
                 s:=10;
              For teller:=2 To 8 do
              begin
                  k:=strtoint(copy(vatnr, teller, 1));
                  a:=(2 * s) Mod 11;
                  If a=0 Then
                     a:=11;
                  s:=(k + a) Mod 10;
                  If s=0 Then
                     s:=10;
              end;
              a:=(2 * s) Mod 11;
              If a=0 Then
                 a:=11;
              b:=11-a;
              If b=10 Then
                 b:=0;
              rechts1:=strtoint(copy(vatnr,9, 1));
              if b=rechts1 then
                  Result := true
              else
                  Result := false;
         end;

end;

//Denemarken.///////////////////////////////////////////////////////////////////////////////////////
Function DKcheck(VATnr: string): Boolean;
begin
     If Length(vatnr)<>8 Then               //Controleer op lengte
        Result := false
     else
         If strtoint(copy(vatnr,1,1))=0 Then
            Result := false        //Controleer op eerste nr <> 0
         else
             If (((strtoint(copy(vatnr,1,1))) * 2 +
                (strtoint(copy(vatnr, 2, 1))) * 7 +
                (strtoint(copy(vatnr, 3, 1))) * 6 +
                (strtoint(copy(vatnr, 4, 1))) * 5 +
                (strtoint(copy(vatnr, 5, 1))) * 4 +
                (strtoint(copy(vatnr, 6, 1))) * 3 +
                (strtoint(copy(vatnr, 7, 1))) * 2 +
                (strtoint(copy(vatnr,8,1)))) Mod 11)=0 Then
                Result := true
             else Result := false;
End;

//Finland.//////////////////////////////////////////////////////////////////////////////////////////
Function FIcheck(VATnr: string): Boolean;
var c: Integer;
begin
 c := 0;
 if Length(VATnr) = 8 Then
  c := (((StrtoInt(copy(VATnr,1,1)) * 7) +
         (StrtoInt(copy(VATnr,2,1)) * 9) +
         (StrtoInt(copy(VATnr,3,1)) * 10) +
         (StrtoInt(copy(VATnr,4,1)) * 5) +
         (StrtoInt(copy(VATnr,5,1)) * 8) +
         (StrtoInt(copy(VATnr,6,1)) * 4) +
         (StrtoInt(copy(VATnr,7,1)) * 2) ) Mod 11);
 if (c = 0) and (StrToInt(copy(vatnr,8,1))=0) Then
  Result := true
 else
  If(c > 2) Then c := 11 - c;

 if not Result then If c = strtoint(copy(vatnr,8,1)) Then
  Result := true
 else
  Result := false;
End;

//Frankrijk.////////////////////////////////////////////////////////////////////////////////////////
Function  FRcheck(VATnr: string): Boolean;
const FRCharTable : Array[0..33] of char =
      ('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','L','M','N',
       'P','Q','R','S','T','U','V','W','X','Y','Z');
var i,ic,ic1,ic2,x,y : integer;

    Function FindCharInTable(ch : char) : Integer;
    var i_ : integer;
    begin
     i_ := 0;
     while i <= 33 do begin
      if(FRCharTable[i] = ch) then begin
       result := i;
       EXIT;
      end;
      i := i + 1;
     end;
     i := -1;
    end;

begin
 try
  //Old or new system??  Use a hack method
  try
   ic := StrToInt(Copy(VATnr,1,2));
   //if we get here then its the old system..
   result := ic = (((StrToInt64(Copy(VATnr,3,9)) * 100) + 12) mod 97)
  except
   //The new system...
   ic1 := FindCharInTable(VATnr[1]);
   ic2 := FindCharInTable(VATnr[2]);
   if(ic1 < 10) then begin
    i := (ic1 * 24) + ic2 - 10;
   end else begin
    i := (ic1 * 34) + ic2 - 100;
   end;
   X := i mod 11;
   i := i div 2 + 1;
   Y := (StrToInt(Copy(VATnr,3,9)) + i) mod 11;
   result := X = Y;
  end;
 except
  result := false;
 end;
end;

//Engeland./////////////////////////////////////////////////////////////////////////////////////////
Function GBcheck(VATnr:string): Boolean;
var i : integer;
begin
 try
  //What type of VAT number??
  if(copy(VATnr,1,2) = 'GD') then begin
   //Goverment department//////////////////////////////////////////////////////
   result := StrToInt(Copy(VATnr,3,3)) < 500;
  end else
  if(copy(VATnr,1,2) = 'HA') then begin
   //Health Authority//////////////////////////////////////////////////////////
   result := StrToInt(Copy(VATnr,3,3)) > 499;
  end else
  if(Length(VATnr) = 9) then begin
   //Standard//////////////////////////////////////////////////////////////////
   i := StrToInt(Copy(VATnr,1,7));
   if not(((i > 1) and (i < 19999)) or ((i > 1000000) and (i < 9999999))) then begin
    result := false;
    EXIT;
   end;
   if StrToInt(Copy(VATnr,8,2)) >= 97 then begin
    result := false;
    EXIT;
   end;
   i := 0
      + (8  * StrToInt(VATnr[1]))
      + (7  * StrToInt(VATnr[2]))
      + (6  * StrToInt(VATnr[3]))
      + (5  * StrToInt(VATnr[4]))
      + (4  * StrToInt(VATnr[5]))
      + (3  * StrToInt(VATnr[6]))
      + (2  * StrToInt(VATnr[7]))
      + (10 * StrToInt(VATnr[8]))
      +       StrToInt(VATnr[9]);
   result := (i mod 97) = 0;
  end else
  if(Length(VATnr) = 10) then begin
   //Group registred traders////////////////////////////////////////////////////
   i := StrToInt(Copy(VATnr,1,7));
   if not(((i > 1) and (i < 19999)) or ((i > 1000000) and (i < 9999999))) then begin
    result := false;
    EXIT;
   end;
   if StrToInt(Copy(VATnr,8,2)) >= 97 then begin
    result := false;
    EXIT;
   end;
   if VATnr[10] <> '3' then begin
    result := false;
    EXIT;
   end;
   i := 0
      + (8  * StrToInt(VATnr[1]))
      + (7  * StrToInt(VATnr[2]))
      + (6  * StrToInt(VATnr[3]))
      + (5  * StrToInt(VATnr[4]))
      + (4  * StrToInt(VATnr[5]))
      + (3  * StrToInt(VATnr[6]))
      + (2  * StrToInt(VATnr[7]))
      + (10 * StrToInt(VATnr[8]))
      +       StrToInt(VATnr[9]);
   result := (i mod 97) = 0;
  end else
  if(Length(VATnr) = 12) then begin
   //Isle of man////////////////////////////////////////////////////////////////
   i := StrToInt(Copy(VATnr,4,7));
   if not(((i > 1) and (i < 19999)) or ((i > 1000000) and (i < 9999999))) then begin
    result := false;
    EXIT;
   end;
   if StrToInt(Copy(VATnr,11,2)) >= 97 then begin
    result := false;
    EXIT;
   end;
   if not((Copy(VATnr,1,3) = '000') or (Copy(VATnr,1,3) = '001')) then begin
    result := false;
    EXIT;
   end;
   i := 0
      + (8  * StrToInt(VATnr[4 ]))
      + (7  * StrToInt(VATnr[5 ]))
      + (6  * StrToInt(VATnr[6 ]))
      + (5  * StrToInt(VATnr[7 ]))
      + (4  * StrToInt(VATnr[8 ]))
      + (3  * StrToInt(VATnr[9 ]))
      + (2  * StrToInt(VATnr[10]))
      + (10 * StrToInt(VATnr[11]))
      +       StrToInt(VATnr[12]);
   result := (i mod 97) = 0;
  end else
  if(Length(VATnr) = 13) then begin
   //Isle of man, group registred traders.//////////////////////////////////////
   i := StrToInt(Copy(VATnr,4,7));
   if not(((i > 1) and (i < 19999)) or ((i > 1000000) and (i < 9999999))) then begin
    result := false;
    EXIT;
   end;
   if StrToInt(Copy(VATnr,11,2)) >= 97 then begin
    result := false;
    EXIT;
   end;
   if not((Copy(VATnr,1,3) = '000') or (Copy(VATnr,1,3) = '001')) then begin
    result := false;
    EXIT;
   end;
   if VATnr[13] <> '3' then begin
    result := false;
    EXIT;
   end;
   i := 0
      + (8  * StrToInt(VATnr[4 ]))
      + (7  * StrToInt(VATnr[5 ]))
      + (6  * StrToInt(VATnr[6 ]))
      + (5  * StrToInt(VATnr[7 ]))
      + (4  * StrToInt(VATnr[8 ]))
      + (3  * StrToInt(VATnr[9 ]))
      + (2  * StrToInt(VATnr[10]))
      + (10 * StrToInt(VATnr[11]))
      +       StrToInt(VATnr[12]);
   result := (i mod 97) = 0;
  end else
   //invalid
   result := false;
 except
  Result := false;
  EXIT;
 end;
End;

//Italie.///////////////////////////////////////////////////////////////////////////////////////////
Function ITcheck(VATnr: string): Boolean;
var code,som,somoneven,k,temp,l,r: Integer;
begin
     If copy(vatnr,1,7)='0000000' Then    //Eerste 7 posities ongelijk aan 0000000
        Result := false
     else
     begin
          code:=strtoint(copy(vatnr,8,3)); //De eenheidscode die in het nummer verwerkt is filteren en controleren op geldigheid
          If inttostr(code)='' Then code:=0;
          If (code>=1) And (code<=100) Or
                            (code=120) Or
                            (code=121) Then
          begin
               k:=2;
               som:=0;
               while k<11 do
               begin
                    temp:=strtoint(copy(vatnr,k,1))*2;  //Het nummer vanaf positie 2 tot 10 doornemen, even posities berekenen
                    If inttostr(temp)='' Then code:= 0;
                    If temp > 9 Then
                    begin
                         l:=strtoint(copy(inttostr(temp),1,1));        //Getal groter dan 10 => tientallen en eenheden bij elkaar optellen
                         r:=strtoint(copy(inttostr(temp),length(inttostr(temp)), 1));
                         temp:=l + r;
                    End;
                    som:=som + temp;              //Som bijwerken
                    k:=k + 2;
               end;
               k:=1;                       //Initialiseren variabelen
               somoneven:=0;
               while k<10 do    //Oneven posities tussen positie 1 en 9
               begin
                   somoneven:=somoneven + strtoint(copy(vatnr,k,1));
                   k:=k+2;
               end;
               som:=som + somoneven;     //Oneven posities bij de even posities optellen
               If ((strtoint(copy(inttostr(som),length(inttostr(som)),1))=0) And
                  (strtoint(copy(vatnr,length(vatnr),1))=0)) Then  //controle op tientallen
                       Result := true;
               r:=strtoint(copy(inttostr(som),length(inttostr(som)),1));      //Tientallen en eenheden optellen
               l:=strtoint(copy(vatnr,length(vatnr),1));
               If ((10-r) = l) Then
                  Result := true
               else Result := false;
          end;
     End;
End;


//Luxemburg.////////////////////////////////////////////////////////////////////////////////////////
Function LUcheck(VATnr: string): Boolean;
var control: Integer;
begin
     If Length(vatnr) = 8 Then //Controleer lengte = 8
        begin
             control:=strtoint(copy(vatnr,1,6)) Mod 89;  //rest bij deling eerste 6 cijfers door 87
             If control = strtoint(copy(vatnr,7,2)) Then
                Result := true
             else Result := false;
        end
     else Result := false;
End;

//Nederland.////////////////////////////////////////////////////////////////////////////////////////
Function NLcheck(VATnr: string): Boolean;
var i: integer;
begin
 try
  if(VATnr[10] <> 'B') then begin
   result := false;
   EXIT;
  end;
  i := 0
     + 9 * StrToInt(VATnr[1])
     + 8 * StrToInt(VATnr[2])
     + 7 * StrToInt(VATnr[3])
     + 6 * StrToInt(VATnr[4])
     + 5 * StrToInt(VATnr[5])
     + 4 * StrToInt(VATnr[6])
     + 3 * StrToInt(VATnr[7])
     + 2 * StrToInt(VATnr[8]);
  i := i mod 11;
  if(i = 10) then result := false
  else            result := StrToInt(VATnr[9]) = i;
 except
  result := true;
  EXIT;
 end;
End;

//Noorwegen.////////////////////////////////////////////////////////////////////////////////////////
Function NOcheck(VATnr: string) : Boolean;
var nummer: integer;
begin
     if length(vatnr)=9 then
        begin
             nummer:=(strtoint(copy(vatnr,1,1))*3)+
                     (strtoint(copy(vatnr,2,1))*2)+
                     (strtoint(copy(vatnr,3,1))*7)+
                     (strtoint(copy(vatnr,4,1))*6)+
                     (strtoint(copy(vatnr,5,1))*5)+
                     (strtoint(copy(vatnr,6,1))*4)+
                     (strtoint(copy(vatnr,7,1))*3)+
                     (strtoint(copy(vatnr,8,1))*2);
             if (11-(nummer mod 11))=(strtoint(copy(vatnr,9,1))) then
                Result := true
             else Result := false;
        end
     else Result := false;
end;


//Sweden.///////////////////////////////////////////////////////////////////////////////////////////
Function SEcheck(VATnr: string): Boolean;
var k,som,temp,l,r: Integer;
begin
     If (Length(vatnr)=12) And (strtoint(copy(vatnr,11,2))<>0) Then
        begin
             k:=1;
             som:=0;
             temp:=0;
             while k< 10 do
             begin
                  temp:=strtoint(copy(vatnr,k,1)) * 2;
                  If temp > 9 Then
                  begin
                     l:=strtoint(copy(inttostr(temp),1,1));
                     r:=strtoint(copy(inttostr(temp),length(inttostr(temp)),1));
                     temp:=l+r;
                  end;
                  som:=som+temp;
                  k:=k+2;
             end;
             k:=2;
             while k<9 do
             begin
                 temp:=strtoint(copy(vatnr,k,1));
                 som:=som+temp;
                 k:=k+2;
             end;
             If ((strtoint((copy(inttostr(som),length(inttostr(som)),1)))=0) And ((strtoint(copy(vatnr,10,1)))=0)) Then
                 Result := true
             else
                 begin
                      r:=som Mod 10;
                      l:=strtoint(copy(vatnr,10,1));
                      If ((10-r) = l) Then
                         Result := true
                      else Result := false;
                 end;
        end
     else Result := false;
End;


//Spanje.///////////////////////////////////////////////////////////////////////////////////////////
Function EScheck(VATnr: string): Boolean;
const ESCharTable : Array[1..23] of Char =
      ('T','R','W','A','G','M','Y','F','P','D','X','B','N','J','Z','S','Q','V','H','L','C','K','E');
var ch : char;
    i  : integer;
begin
 try
  if(Length(vatnr) <> 9) then begin
   Result := false;
   EXIT;
  end;
  ch := vatnr[1];

  case ch of
   //Juridical person with profit purpose:
   'A' .. 'H' : begin
                 i := 0 + MultiplyAdd(VATnr[2],'2');
                 i := i + strToInt(VATnr[3]);
                 i := i + MultiplyAdd(VATnr[4],'2');
                 i := i + StrToInt(VATnr[5]);
                 i := i + MultiplyAdd(VATnr[6],'2');
                 i := i + StrToInt(VATnr[7]);
                 i := i + MultiplyAdd(VATnr[8],'2');
                 i := 10 - (i mod 10);
                 if(i = 10) then i := 0;
                 result := StrToInt(VATnr[9]) = i;
                end;

   //Juridical persons without profit purpose
   'N','P','Q','S' : begin
                      i := 0 + MultiplyAdd(VATnr[2],'2');
                      i := i + strToInt(VATnr[3]);
                      i := i + MultiplyAdd(VATnr[4],'2');
                      i := i + StrToInt(VATnr[5]);
                      i := i + MultiplyAdd(VATnr[6],'2');
                      i := i + StrToInt(VATnr[7]);
                      i := i + MultiplyAdd(VATnr[8],'2');
                      i := 10 - (i mod 10);
                      if(i = 10) then i := 0;
                      result := (i - 1 + Ord('A')) = ord(VATnr[9]);
                     end;

   //Foreigner physical persons smaller than 14 years old or non residents
   'K','L','M','X' : begin
                      i := 1 +(ExtractNumFromStr(VATnr,2,8) mod 23);
                      Result := ESCharTable[i] = VATnr[9];
                     end;

   //Spanish Physical persons
   '0' .. '9' : begin
                 i := 1 +(ExtractNumFromStr(VATnr,1,8) mod 23);
                 Result := ESCharTable[i] = VATnr[9];
                end;

   else begin
    Result := false;
   end;
  end; //end case
 except
  Result := false;
 end;
end;


//Greece VAT calculus.//////////////////////////////////////////////////////////////////////////////
Function GRcheck(VATnr: string): Boolean;
var i,il,ipos,imul: integer;
begin
 try
  il := Length(VATnr) - 1;
  if(il >= 7) and (il <= 8) then begin
   //calculus
   i    := 0;
   ipos := 1;
   if(il = 7) then
    imul := 128
   else
    iMul := 256;
   while ipos <= il do begin
    i    := i + (iMul * StrToInt(VATnr[ipos]));
    iMul := iMul shr 1;
    ipos := ipos + 1;
   end;
   i := i mod 11;
   if(i = 10) then i := 0;
   //check control
   result := i = StrToInt(VATnr[il + 1]);
  end else
   //invalid
   Result := false;
 except
  result := false;
 end;
end;


//Ireland.//////////////////////////////////////////////////////////////////////////////////////////
Function IRcheck(VATnr: string): Boolean;
const IRCharTable : Array[0..22] of char =
      ('W','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V');
var i : integer;
begin
 try
  //Old or new system??
  if(VATnr[2] in ['A'..'Z','+','*']) then begin
   //Old System
   if(StrToInt(VATnr[1]) <= 6) then Begin
    Result := false;
    EXIT;
   end;
   i := 0
      + 7 * StrToInt(VATnr[3])
      + 6 * StrToInt(VATnr[4])
      + 5 * StrToInt(VATnr[5])
      + 4 * StrToInt(VATnr[6])
      + 3 * StrToInt(VATnr[7])
      + 2 * StrToInt(VATnr[1]);
   i := i mod 23;
   //Check control
   result := IRCharTable[i] = VATnr[8];
  end else begin
   //New System
   i := 0
      + 8 * StrToInt(VATnr[1])
      + 7 * StrToInt(VATnr[2])
      + 6 * StrToInt(VATnr[3])
      + 5 * StrToInt(VATnr[4])
      + 4 * StrToInt(VATnr[5])
      + 3 * StrToInt(VATnr[6])
      + 2 * StrToInt(VATnr[7]);
   i := i mod 23;
   //Check control
   result := IRCharTable[i] = VATnr[8];
  end;
 except
  result := false;
 end;
end;

//Portugal./////////////////////////////////////////////////////////////////////////////////////////
Function PTcheck(VATnr: string): Boolean;
var i : integer;
begin
 try
  if(StrToInt(VATnr[1]) <= 0) then begin
   result := false;
   EXIT;
  end;
  i := 0
     + 9 * StrToInt(VATnr[1])
     + 8 * StrToInt(VATnr[2])
     + 7 * StrToInt(VATnr[3])
     + 6 * StrToInt(VATnr[4])
     + 5 * StrToInt(VATnr[5])
     + 4 * StrToInt(VATnr[6])
     + 3 * StrToInt(VATnr[7])
     + 2 * StrToInt(VATnr[8]);
  i := 11 - (i mod 11);
  if(i >= 10) then i := 0;
  result := i = StrToInt(VATnr[9]);
 except
  result := false;
 end;
end;

end.