关于UPCE条码的校验
关于UPC E条码的知识可以参照BlueSky⽼师的空间,⾮常感谢BlueSky⽼师的耐⼼讲解。
下⾯这篇⽂章是BlueSky对条码的讲解,其中第四部分是关于UPC E的。
从BlueSky⽼师的讲述来看,UPC E条码应该是8位的,只不过UPC E的第⼀位⼀定是0,并且校验位⽤A,B⼦集的排列来表⽰(这跟EAN13的第⼀位的形成⽅式是⼀样的),所以条码的条空只表⽰6位数字,但是加上系统位0和A,B⼦集排列代表的校验位,条码本⾝代表的数字含义⼀定是8位的。所以我不太明⽩AX⾥在做条码设置的时候UPC E为什么规定成6位的?⽤扫描枪扫描出来的是8位的数字。。。
基本设置->设置->条码设置
这样给商品添加UPC-E条码的时候,就只能输⼊6位了,否则会报错说位数不对,问题是即便把0和校验位去掉了,输⼊6位数字,还是会报错说校验位不对。
postgraduate
BlueSky⽼师的⼀篇⽂章介绍了校验位的⽣成算法:
在AX中UPC和EAN类型的编码的校验位算法在类BarcodeEAN_UPC的validateCheckDigit
代码
birdprotected boolean validateCheckDigit(BarCodeString barCodeString)
{
boolean ret =true;
str tmp;
;
if (strlen(barCodeString) !=this.strlen())
return true; // Actually an error, but has already been reported.
barcodeStr =deString(substr(barCodeString,1,this.strlen()));
tmp = Barcode::inrtModulo10CheckDigit(barCodeString, this.strlen());
if (tmp != barCodeString)
ret = checkFailed(strfmt("@SYS76957", substr(barCodeString, this.strlen(), 1), substr(tmp, this.strlen(), 1)));
return ret;explains
}
AX的代码就是实现了BlueSky⽼师介绍的校验位⽣成算法,类BarCode的静态⽅法inrtModulo10CheckDigit:
代码
public client rver static str inrtModulo10CheckDigit(str s_in, Integer stringLength)
{
Integer checkDigit =0;
Integer counter;
Integer temp;
Integer digit(Integer position)
data是什么意思{
return any2int(substr(s_in,stringLength +1- position,1));
}
;
counter =2;
while (counter <= stringLength)
{
checkDigit += digit(counter);
counter +=2;
}
checkDigit =3* checkDigit;
counter =3;
while (counter <= stringLength)
{
checkDigit += digit(counter);
counter +=2;
}
temp = checkDigit mod 10;
if (temp)
checkDigit =10- temp;
el
checkDigit =0;
return substr(s_in,1,stringLength -1) + num2str(checkDigit,1,0,0,0);
}
EAN8,EAN13以及UPC-A⽤这个算法⽣成校验位都没有问题,UPC-E直接⽤这个算法就有问题了,如果按照AX的要求输⼊去掉⾸位和校验位的六位数字,⽣成的校验位显然不符合要求。
UPC-E要⽣成校验位必须⾸先还原成UPC-A,然后再⽤上⾯的算法才能⽣成正确的校验位,还原的算法很简单,按照前⾯提到的BlueSky ⽼师的⽂章⾥介绍UPC-A到UPC-E的压缩算法反过程回去就可以
了,X++代码如下:
代码
private BarCodeString upce2UPCA(BarCodeString _barCodeString)
{
BarCodeString barCodeString;
;
switch(str2int(substr(_barCodeString,strlen(_barCodeString)-1,1)))
{
ca0:
ca1:
ca2:
{小学二年级英语下册
barCodeString = substr(_barCodeString,1,3)
+substr(_barCodeString,strlen(_barCodeString)-1,1)
大学英语三级考试+'0000'
+substr(_barCodeString,4,3)
+substr(_barCodeString,strlen(_barCodeString),1);
break;
}
ca3:
{
barCodeString = substr(_barCodeString,1,4)
+'00000'
+substr(_barCodeString,5,2)
+substr(_barCodeString,strlen(_barCodeString),1);
break;
}
ca4:
{
barCodeString = substr(_barCodeString,1,5)
+'00000'
+substr(_barCodeString,6,1)
+substr(_barCodeString,strlen(_barCodeString),1);
break;
}
ca5:
ca6:
传闻中的七公主主题曲
ca7:
ca8:
ca9:
bigbigworld下载{
barCodeString = substr(_barCodeString,1,6)
+'0000'
+substr(_barCodeString,7,2);
break;
}
default:
throw error("");
}
return barCodeString;
}
然后在类BarcodeUPCEvalidateCheckDigit
代码
protected boolean validateCheckDigit(BarCodeString barCodeString)
{
boolean ret;
str tmp;
str barCodeStringLocal;
;
barcodeStr =deString(substr(barCodeString,2,this.strlen()));
nuts是什么意思英语barCodeStringLocal =this.upce2UPCA(barCodeString);
tmp = Barcode::inrtModulo10CheckDigit(barCodeStringLocal, 12);
if (substr(tmp,strlen(tmp),1) != substr(barCodeString,strlen(barCodeString),1))
ret = checkFailed(strfmt("@SYS76957", substr(barCodeString, this.strlen(), 1), substr(tmp, strlen(tmp), 1)));
return ret;
}
其实在类BarcodeEAN_UPC的encodeStr的前半部部分就是⽤来计算校验位的,算法⼤同⼩异,⾸先还原成UPC-A,然后再计算得到校验位,根据校验位得到各个数字对应的打印的字符。这个⽅法是按照UPC-E为六位计算得到打印字符的,所以也需要改⼀下,把传⼊的字符去头舍尾变成六位。
if (len !=this.strlen())
return'';
_stringIn = subStr(_stringIn,2,6);
修改⼀下表BarcodeSetup的fieldModifiedBarcodeType⽅法,让其当类型为UPCE时,最⼤和最⼩长度设置为8。
代码
public void fieldModifiedBarcodeType()
{
Barcode barcode;
;
switch(this.BarcodeType)
{
ca BarcodeType::UPCA :
this.MinimumLength =12;
this.MaximumLength =12;
break;
ca BarcodeType::UPCE :
this.MinimumLength =8;
this.MaximumLength =8;
蓝精灵字幕break;
ca BarcodeType::EAN13 :
this.MinimumLength =13;
this.MaximumLength =13;
break;
ca BarcodeType::EAN8 :
this.MinimumLength =8;
this.MaximumLength =8;
break;
}
barcode =this.barcode();
if (this.FontName &&!barcode.validateFontName(this.FontName))
this.FontName ='';
if (!this.FontName)
this.FontName = barcode.defaultFont();
}
UPCE条码应该还是有很多地⽅⽤的,AX在全世界也有很多⽤户,如果这是个bug的话,应该早就发现了,所以我觉得可能是我某个地⽅理解错了,但是⼜实在找不到相关⽂档,也只能这么从代码上这么改了,还望知道其中原委的⾼⼈指点。