[PHP] calcurate UPC-E check digit

最近バーコード絡みの案件があるのでちょくちょくバーコードネタが出てきます
今日はUPC-E(8桁短縮タイプ)のチェックデジットを計算する関数を作ってみました

そんなライブラリどこかに転がってるだろ、と思っていたのですが、これが意外に見つからない・・・
UPC-A対応ならあるのですが、8桁短縮コードは考慮されていない事が多かったです
探し方が悪かったのかな?
とにかく、見つけられなかった以上、自作します

基本的にはJAN(=EAN)であろうとUPCであろうとModulus10/Weight3と呼ばれる方法でチェックデジットは計算されています
これはざっくり言うと、奇数桁の合計×3 + 偶数桁の合計 を10で割った余りを10から引いたもの、です

日本語で書くよりソースコードのほうがわかりやすそうです

function calc_checkdigit($code)
{
if( !ctype_digit($code) ) return false;
$code = (string)$code;
$odd_total = 0;
$even_total = 0;
for($i=0; $i<strlen($code); $i++)
{
if((($i+1)%2) == 0) {
// 偶数行合計
$even_total += $code[$i];
} else {
// 奇数行合計
$odd_total += $code[$i];
}
}
// 奇数桁の合計×3 + 偶数桁の合計
$sum = (3*$odd_total) + $even_total;
// 10で割った余りを求める
$remainder = $sum%10;
// 求められた余りを10から引いた値がチェックデジット(10の場合は0)
return( (10-$remainder)%10 );
}
function calc_checkdigit($code) { if( !ctype_digit($code) ) return false; $code = (string)$code; $odd_total = 0; $even_total = 0; for($i=0; $i<strlen($code); $i++) { if((($i+1)%2) == 0) { // 偶数行合計 $even_total += $code[$i]; } else { // 奇数行合計 $odd_total += $code[$i]; } } // 奇数桁の合計×3 + 偶数桁の合計 $sum = (3*$odd_total) + $even_total; // 10で割った余りを求める $remainder = $sum%10; // 求められた余りを10から引いた値がチェックデジット(10の場合は0) return( (10-$remainder)%10 ); }
function calc_checkdigit($code)
{
    if( !ctype_digit($code) ) return false;
    $code = (string)$code;
    $odd_total  = 0;
    $even_total = 0;
    
    for($i=0; $i<strlen($code); $i++)
    {
        if((($i+1)%2) == 0) {
            // 偶数行合計
            $even_total += $code[$i];
        } else {
            // 奇数行合計
            $odd_total += $code[$i];
        }
    }
 
    // 奇数桁の合計×3 + 偶数桁の合計
    $sum = (3*$odd_total) + $even_total;
    // 10で割った余りを求める
    $remainder = $sum%10;
    // 求められた余りを10から引いた値がチェックデジット(10の場合は0)
    return( (10-$remainder)%10 );
}

で、問題はここから

UPC-Eの場合は一度UPC-A(12桁の通常タイプ)に変換してから計算するという仕様なのですが、この変換がちょっとややこしい
UPC-Eの8桁のうち先頭の1桁は0で固定されており、また末尾1桁はチェックデジットなので、意味のある文字列は2桁目から7桁目までの6文字になるのですが、その末尾(全体の7桁目)によって変換の方法が変わるという仕様です

まとめた資料がcanonさんにありました
UPC短縮バーコードチェックデジット計算方法

よく見るとそこまで複雑な話ではないのですが、ぱっと見じゃ理解できないですよね…

PHPで処理を書くとこうなります

function upce2upca($code)
{
if( !ctype_digit($code) ) return false;
$code = (string)$code;
$len = strlen($code);
if( $len != 7) return false;
switch($code[6])
{
case '0':
case '1':
case '2':
$ret = substr($code,0,3).$code[6].'0000'.substr($code,3,3);
break;
case '3':
$ret = substr($code,0,4).'00000'.substr($code,4,2);
break;
case '4':
$ret = substr($code,0,5).'00000'.$code[5];
break;
default:
$ret = substr($code,0,6).'0000'.$code[6];
break;
}
return $ret;
}
function upce2upca($code) { if( !ctype_digit($code) ) return false; $code = (string)$code; $len = strlen($code); if( $len != 7) return false; switch($code[6]) { case '0': case '1': case '2': $ret = substr($code,0,3).$code[6].'0000'.substr($code,3,3); break; case '3': $ret = substr($code,0,4).'00000'.substr($code,4,2); break; case '4': $ret = substr($code,0,5).'00000'.$code[5]; break; default: $ret = substr($code,0,6).'0000'.$code[6]; break; } return $ret; }
function upce2upca($code)
{
    if( !ctype_digit($code) ) return false;
    $code = (string)$code;
    $len = strlen($code);
    if( $len != 7) return false;
    
    switch($code[6])
    {
        case '0':
        case '1':
        case '2':
            $ret = substr($code,0,3).$code[6].'0000'.substr($code,3,3);
            break;
        case '3':
            $ret = substr($code,0,4).'00000'.substr($code,4,2);
            break;
        case '4':
            $ret = substr($code,0,5).'00000'.$code[5];
            break;
        default:
            $ret = substr($code,0,6).'0000'.$code[6];
            break;
    }
    return $ret;
}

さきほどのModulus10/Weight3の計算と合わせて使うことでUPC-Eのチェックデジット計算ができます

// チェックデジット計算前の7桁
$raw_upce = '0123456';
// UPC-A(チェックデジット加える前の11桁)に変換
$raw_upca = upce2upca($raw_upce );
// チェックデジットを計算
$cd = calc_checkdigit($raw_upca); // 5
// 有効な8桁UPC-Eを作る
$valid_upce = $raw_upce.$cd; // 01234565
// チェックデジット計算前の7桁 $raw_upce = '0123456'; // UPC-A(チェックデジット加える前の11桁)に変換 $raw_upca = upce2upca($raw_upce ); // チェックデジットを計算 $cd = calc_checkdigit($raw_upca); // 5 // 有効な8桁UPC-Eを作る $valid_upce = $raw_upce.$cd; // 01234565
// チェックデジット計算前の7桁
$raw_upce = '0123456'; 

// UPC-A(チェックデジット加える前の11桁)に変換
$raw_upca = upce2upca($raw_upce );

// チェックデジットを計算
$cd = calc_checkdigit($raw_upca); // 5

// 有効な8桁UPC-Eを作る
$valid_upce = $raw_upce.$cd; // 01234565

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です