我在做的一个项目里,要求对物料进行编码管理,物料是多级管理的,自然编码里也会有字母和数字,A3B2003之后肯定就是A3B2004了,人是很容易理解的,但程序语言就难说了。我以前只做过纯数字的,带字母的一下子还真找不到对应的函数,所以只有自己做了。
我们知道在Excel里,带字母的数字是可以自动加1的,比如A3B2001,A3B2002, A3B2003,这在Excel里的操作相信很多人都会,但如何在Delphi里实现呢?
从逻辑上分析,我觉得应该从最后一位开始算起,把后面几位是数字的字串截取出来转换成数字后+1,然后再合并回去,就实现要求了,按照这个逻辑,我用2种方法来实现,1种是程序实现,1种是SQL语言实现,下面来分别解释,先上代码。
一、程序实现
function GetStrAddOne(NumStr:string):string;
var
i,iStart,iEnd,iTmp:Integer;
sTmp,sFormat:string;
begin
Result:='';
sTmp:=NumStr;
iEnd:=Length(sTmp);
iStart:=Length(sTmp);//当前位是最后一位
while TryStrToInt(Copy(sTmp, iStart, Length(sTmp)),iTmp) do //当前位如果不是数字就结束
begin
iStart:=iStart -1; //如果是数字就往前移1位
end;
iTmp:=StrToInt(Copy(sTmp, iStart+1, Length(sTmp)))+1;截取后面是数字的那几位转换成数字并加1
sFormat:=Format('%%.%dd',[iEnd-iStart]);//生成数字按位数补0的格式串,这步可不要,看具体情况
sTmp:=Format(sFormat,[iTmp]); //将加1后的数值按格式生成字串
Result:= Copy(NumStr, 1,iStart) + sTmp;//将原字串与新生成的字串合并
end;
以A3B2002为例,从最后1位第7 位 开始循环往前判断,只要是数字就往前移,到了第3位遇到了非数字的字符,我们得出4-7位是数字。
退出循环后将4-7位的字符转换成数字2002,加1后得到2003
新的数字要转换成什么格式的字串呢,就要根据2003的长度来定义格式字符串,由于2003是4位,我们得到格式字符串是'%.4d',对Format不熟悉的同学可以上网查一下Format的用法。
接下来最后一步,就是把前3位的字串加上新数字2003转换成的字串,最终得到A3B2003。
二、SQL语句实现
Create function [dbo].[GetStrAddOne](@Var nvarchar(50))
returns nvarchar(50)
begin
declare @Tmp nvarchar(50)=reverse(Upper(@var)) --将转入的字符串反转作为临时变量
DECLARE @var1 INT
set @var1=PATINDEX('%[A-Z]%',@Tmp)-1 --用正式表达式,求出是数字字符的长度
set @var=LEFT(@var,LEN(@var)-@var1) + right(CAST(power(10,@var1)+ cast(RIGHT(@var,@Var1) as bigint)+1 as bigint),@var1) --这个是转换的重点
return @var
还是以A3B2002为例,先将A3B2002反转,得到2002B3A
用正则表达式求2002B3A前面是数字的字串的长度,2002B3A前面是数字的就是2002,长度就是4。
先将原字串A3B2002截取左边的部分A3B
将10的4次方加上2002得到12002,加1后,再从右边截取长度4的字串得到2003。有人会问为什么这里要这么复杂,这里主要是解决数字前面是不是要补0的问题。比如A3002002,如果只是单纯将后面的数字加1再合并的话,就会变成A32003了。
将A3B与2003合并得到A3B2003
说的有点啰嗦,希望大家能看的明白。有了这个功能,以后在定义新编码时只需要给出第1个编码,后面系统就可以自动算出第2个,第3个编码了,方便很多。