最近バーコード絡みの案件があるのでちょくちょくバーコードネタが出てきます
今日は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 ); }
で、問題はここから
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; }
さきほどの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