Custom USING function (thousand separators)

(and a bit more)

There was a request at JB forum:
All of the numbers for my output are supposed to be formatted. We have been taught to use
USING("####.##", VariableName)
(...)
Is there a way to add things like commas to this so that when I reach larger totals they come out as
###,###.##
instead of just
######.##

Well, as you know, JB only supports masks of type ######.##

So first I tried to take result of USING then add (,) into every 3rd place... counting leftwards from decimal point (brrr)
Then it occurred that number of commas added depends on actual number - so formatted number could end up longer when mask, or have different width. Not what you would expect from USING. I could be kludged more - but resulting code just not pretty.
So first attempt went to a dustbin. ;)

Here is second one.

Idea is as follows:
1) We supply a mask
  • consisting of normal USING mask characters (# and a dot (.))
  • and comma (,) as a thousand separator
  • and any other symbol;
2) program filter it, producing realMask$ for build-in USING
3) program gets formatted number with build-in USING
4) program combine mask and formated number:
  • parts with (# and a dot (.)) got replaced from formatted number;
  • thousand separator added if the number is big enough, else space printed (only difference from other character)
  • any other characters goes out as is.
Everything else is details.
(: you already can use spaces as separators, you can change delim1000$ variable,
and it doesn't have to delimit thousands - you can put them anywhere and in any quantity )

Since in JB USING function actually return string but lacks $ at the end, we could name our function using$.
That is, using$(mask$, x)

Demo and a function:
randomize .5
 
print "String";tab(15);"Val";tab(30);"Using";tab(50);"using$"
for i = 1 to 20
    n = int(rnd(1)*10)
    a$=""
    for j = 1 to n
        a$=a$;int(rnd(1)*10)
    next
        a$=a$;"."
    for j = 1 to 3
        a$=a$;int(rnd(1)*10)
    next
    if rnd(1)<0.5 then a$="-";a$
    a=val(a$)
    print a$;tab(15);a;tab(30);using("############.##", a);tab(50);using$("###,###,###,###.##", a)
next
 
print
print "Also can do:"
x=1234567.8901
mask$ = "###,###,###.##"
print x, ">";mask$;"<", ">";using$(mask$, x);"<"
mask$ = "x=###,###,###.##$"
print x, ">";mask$;"<", ">";using$(mask$, x);"<"
mask$ = "any text ###,###,###.## more"
print x, ">";mask$;"<", ">";using$(mask$, x);"<"
mask$ = "### ###,###.##"
print x, ">";mask$;"<", ">";using$(mask$, x);"<"
mask$ = "### ### ###.##"
print x, ">";mask$;"<", ">";using$(mask$, x);"<"
 
 
function using$(mask$, x)
    delim1000$ = "," 'the point is, we do not print them (print " ") if there are no digit in this place
 
    realMask$ = ""
    for i = 1 to len(mask$)
        c$=mid$(mask$,i,1)
        if instr("#.", c$) then realMask$ = realMask$ + c$ 
    next
 
    x$=using(realMask$, x)
    'print x$
 
    xx$=""
    j = 1
    digitStarted=0
    for i = 1 to len(mask$)
        c$=mid$(mask$,i,1)
        if instr("#.", c$) then
            cc$=mid$(x$,j,1)
            xx$ = xx$ + cc$ 
            j=j+1
            digitStarted = (instr(" -", cc$)=0)
        else
            if instr(delim1000$, c$) then
                if digitStarted = 0 then
                    if cc$="-" then 'if we have "  -," we should convert it to "   -"
                        xx$ = left$(xx$, len(xx$)-1) + " "
                        c$="-"
                    else
                        c$=" "   'skip thousand delimiter if digits not started yet
                    end if
                end if
            end if
            xx$ = xx$ + c$ 
        end if
    next
    using$ = xx$
end function

Result:

String        Val            Using               using$
22193343.186  22193343.2         22193343.19          22,193,343.19
-.962         -0.962                   -0.96                  -0.96
6366418.671   6366418.67          6366418.67           6,366,418.67
-0.616        -0.616                   -0.62                  -0.62
-77427.055    -77427.055           -77427.06             -77,427.06
-5.624        -5.624                   -5.62                  -5.62
39878.106     39878.106             39878.11              39,878.11
3570.227      3570.227               3570.23               3,570.23
-27081012.166 -27081012.2       -27081012.17         -27,081,012.17
-3.274        -3.274                   -3.27                  -3.27
-28636.087    -28636.087           -28636.09             -28,636.09
3798.929      3798.929               3798.93               3,798.93
2904.410      2904.41                2904.41               2,904.41
238509325.295 2.38509325e8      238509325.29         238,509,325.29
47940310.161  47940310.2         47940310.16          47,940,310.16
4.340         4.34                      4.34                   4.34
-58181972.435 -58181972.4       -58181972.44         -58,181,972.44
636227.597    636227.597           636227.60             636,227.60
-0937027.468  -937027.468         -937027.47            -937,027.47
.248          0.248                     0.25                   0.25
 
Also can do:
1234567.89    >###,###,###.##<            >  1,234,567.89<
1234567.89    >x=###,###,###.##$<         >x=  1,234,567.89$<
1234567.89    >any text ###,###,###.## more<            >any text   1,234,567.89 more<
1234567.89    >### ###,###.##<            >  1 234,567.89<
1234567.89    >### ### ###.##<            >  1 234 567.89<