Kenny Hill · Oct 23, 2018

Add Leading Zeros

I'm trying to format a filed, and I need to add leading zeros infront with a length of 4.


Before: 1

After: 0001

0 2,213
Discussion (30)14
Log in or sign up to continue


 Eg: w ##class(Ens.Rule.FunctionSet).Pad(1,-4,0)    


This returns with "0000".

I need it to keep the value and add 0's infront.

This is the way I do it when I need to

I think that is my preferred method as well, but it depends to some extent what you are going to do with the result, and what you want to happen if the input number is too big. This $J solution will always return all the characters input, which may be the safest thing. (Though any space characters inside the input will get converted to zeros.)

When the fail mode needs to still return the same length string, e.g. to avoid messing up some fixed length message format, it might be best to use $E(), e.g.

W $E("0000"_number,$L(a)+1,*)

I've also seen the following used, but I'm not sure I recommend it. So many interesting ways it could go wrong!

w $E(number+10000,2,999)

This does work. I think the only downside is if you were to apply this to longer numbers. For example, an invoice number with 9 digits you'd have to write "000000000". As far as readability, you'd have to count those zeroes every time. For this reason, I'd say the combination of $TRIM and $JUSTIFY would be more appropriate since you'd alleviate how to count the zeroes.

$P is how I do it as well and due to a quirk of $P you don't even have to set the variable first although if it is possible a value might already exist it is reccommended.

If in an alternate namespace, this would require the namespace to contain the %qarfunc, or have a routine mapping to the USER namespace.


USER>d $system.SQL.Shell()
SQL Command Line Shell
The command prefix is currently set to: >.
Enter q to quit, ? for help.
USER>>select lpad('1',4,'0'n
1.      select lpad('1',4,'0'n
1 Rows(s) Affected

I think this is normally called right-justify-zero-fill:

I usually define a local function, such as:

rjzf(num,wid) Quit $Translate($Justify(num,wid)," ","0")

USER> w $$rjzf(1,4)


Thanks, Larry,
Adding your variant to the "code base".
As most of others, your solution needs *  length correction  * which I'm putting aside from Xecute to improve readability.

  new code,i,z,sign
  set number=+number
  set sign="" set:number<0 sign="-",number=-number
  set code($increment(code))="w sign_$tr($j(number,length),"" "",""0"")"
  set:length<$l(number) length=$l( number) ;* length correction *
  set code($increment(code))="w sign_$e(1E"_length_"+number,2,*)"
  set code($increment(code))="w sign_$e(10**length+number,2,*)"
  set code($increment(code))="w sign_$e($tr($j("""",length),"" "",0)_number,*-length+1,*)"
  set code($increment(code))="s $P(z,""0"",length)=number w sign_$E(z,*-(length-1),*)"
  for i=1:1:code write code(i),"  => ",?60 xecute code(i) write !

Here's one way, which uses $JUSTIFY to add leading spaces, then $TRANSLATE to convert these to zeroes:

USER>s number=1

USER>w $tr($j(number,4)," ","0")

For the record, the $TR abbreviation in my answer stands for $TRANSLATE

There is no $TRIM function in ObjectScript.

The functions from %qarfunc are actively used in system classes, so I don't think ^%qarfunc will be removed in the near future, otherwise everything will stop working.

Please, never ever rely on undocumented APIs. They may be taken out or change semantics without further notice. The best you get is "use at your own risk" if you think you have to.
There is a plethora of one-liner suggestions here you can use for the same purpose. No need to walk into undocumented InterSystems system code for an LPAD function.

I was looking at the generated INT code for &sql(select lpad('1',4,'0'n)

Unfortunately, for COS at the moment I have not found an analogue LPADSQL.
Can you offer a documented LPADCOS ?

No, according to my tests the %qarfunc routine is available in all namespaces. It comes from the CACHELIB / IRISLIB database. But I think it's a remnant of an ancient InterSystems tool called M/SQL, so I wouldn't recommend starting to rely on it in new code you're writing.

Ben, thanks, I use the same approach.

Nothing to add to the "code base" as this solution is already here by #1 (John was the first).

While adding the length check is valid for a pure coding solution, the most practical reason where leading zero's are necessary is for values that are required to be a fixed length such as SSN's.

If a value initially  exceeded that fixed length, it most likely would have been trapped out as an invalid entry before it reached the length adjustment code.

That's a good point and the code base example is useful but the question was specifically for leading zero's and the code base version might be overkill for this.

$string = 9;
echo str_pad($string5'0', STR_PAD_LEFT); // Resultado: 00009

Another way:

set number="",$p(number,0,4)=1 w number 


If you do universal LPAD, it is best $$lpad^%qarfunc, because for certain arguments may produce an incorrect result, for example:

#define lpad(%s,%len,%pad) $tr($j(%s,%len)," ",%pad)
s s="a b",len=8,pad="0"
w $$$lpad(s,len,pad),!


00000a b
a ba a b

If we are looking for more generic solution, e.g. pad <number> by zeroes yielding to the field of given <length>, let's try:

  new code
  set code($increment(code))="w $tr($j(number,length),"" "",""0"")"
  set code($increment(code))="w $e(1E"_length_"+number,2,*)"
  set code($increment(code))="w $e(10**length+number,2,*)"
  set code($increment(code))="w $e($tr($j("""",length),"" "",0)_number,*-length+1,*)"
  for i=1:1:code write code(i)," => " xecute code(i) write !

Some  results are:

for n=999,9999,99999 d lpad^ztest(n,4) w !
w $tr($j(number,length)," ","0") => 0999
w $e(1E4+number,2,*) => 0999
w $e(10**length+number,2,*) => 0999
w $e($tr($j("",length)," ",0)_number,*-length+1,*) => 0999
w $tr($j(number,length)," ","0") => 9999
w $e(1E4+number,2,*) => 9999
w $e(10**length+number,2,*) => 9999
w $e($tr($j("",length)," ",0)_number,*-length+1,*) => 9999
w $tr($j(number,length)," ","0") => 99999
w $e(1E4+number,2,*) => 09999
w $e(10**length+number,2,*) => 09999
w $e($tr($j("",length)," ",0)_number,*-length+1,*) => 9999

Only the first solution (John's one) provides valid result even with "bad" input data ($length(99999) > 4). Others can't be amended this way without extra efforts irrelevant to this tiny task. Just to complete it:

 new code,i
 set code($i(code))="w $tr($j(number,length),"" "",""0"")"
 set code($i(code))="w $e(1E"_$s(length>$l(number):length,1:$l(number))_"+number,2,*)"
 set code($i(code))="w $e(10**$s(length>$l(number):length,1:$l(number))+number,2,*)"
 set code($i(code))="w $e($tr($j("""",$s(length>$l(number):length,1:$l(number))),"" "",0)_number,*-$s(length>$l(number):length,1:$l(number))+1,*)"
 for i=1:1:code write code(i)," => ",?60 xecute code(i) write !

Now all solutions become correct even with the <number> >= 99999, but only the first one keeps its simplicity.

Try this:

ROU>s val="sd123X"             ; value to be justified

ROU>s len=9                             ; length of the total string

ROU>k z                                      ; make sure z is undefined

ROU>s $P(z,"0",len)=val        ; set z to value with leading zeros

ROU>s val=$E(z,*-(len-1),*)   ; trim value to required length

ROU>w !,val



The solution is to use the 2 methods:

  •  $JUSTIFY($J) - For Adding leading spaces (" ") 
  •  $REPLACE - For Replasing the spaces to zeros.

so in that case:

set Num=1

set NumWithLeadingZeros= $REPLACE($J(Num,9)," ","0")