|
Post by turtleman on Mar 4, 2022 5:03:43 GMT -5
One of my display windows consists of around 70 graphic boxes arranged in 2 columns. All boxes, to the right of short static labels, display only numbers. Some are only 1 or 2 digits, while others can go up to 8 digits. A dozen or so also display percentages to 2 decimal places. (Decimals aren't used for all displays.) Stylebits hides the boxes and displays only the numbers in green, red, blue, or black. And thanks to most helpful desegment/flush suggestions in another thread, everything is working great! However, the displays would look a lot better if the numbers could be aligned vertically over decimal points. (Decimals aren't shown on all displays.) I'm not sure if going to textboxes might be an alternative, but don't think that would help with decimal point alignment. Can anyone point me to some examples that I might be able to adopt? I'm also still searching for a way to insert commas between every 3 digits. Thanks in advance!
|
|
|
Post by tsh73 on Mar 4, 2022 5:37:30 GMT -5
You should (could?) use monospaced font (courier, andale mono, consolas - whatever) so all characters take same space and format your numbers so decimal point happen to be on same position (padding with spaces from the left if needed)
I found this code of 2013, have a look
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
|
|
|
Post by turtleman on Mar 4, 2022 6:01:40 GMT -5
tsh73: Thanks a bunch! It's going to take some time (if ever) for me to totally understand the code, but the "using$" column appears to be exactly what I'm looking for. Now if I can only figure out how to adopt my code to do the same thing.
|
|
|
Post by turtleman on Mar 4, 2022 6:14:57 GMT -5
PS: About half the boxes don't need to display decimal points, but I'll worry about that later.
|
|
|
Post by tsh73 on Mar 4, 2022 7:07:51 GMT -5
>>About half the boxes don't need to display decimal points Just edit the mask as needed
print mask$ = "###,###,###.##" print x, ">";mask$;"<", ">";using$(mask$, x);"<" mask$ = "###,###,###" print x, ">";mask$;"<", ">";using$(mask$, x);"<"
1234567.89 >###,###,###.##< > 1,234,567.89< 1234567.89 >###,###,###< > 1,234,568<
|
|
|
Post by turtleman on Mar 4, 2022 9:58:18 GMT -5
Anatoly: Thanks again, but so far I've been unable to implement the changes. In a nutshell, I'm probably in over my head!
The following lines are just 2 of 70-some graphic boxes that I'm trying to align. Unfortunately, I don't understand all of the example code, particularly "<" and ">. Oh well, I've been confused lots of times, so maybe I'll eventually figure this out too.
statictext #stats, "Wins", 20,160, 70, 20 graphicbox #stats.wins, 100,160, 75, 18 stylebits #stats.wins, 0,_WS_BORDER,0,0
statictext #stats, "Losses", 20,180, 70, 20 graphicbox #stats.losses, 100,180, 75, 18 stylebits #stats.losses, 0,_WS_BORDER,0,0 .........
#stats.wins, "down; fill lightgray; color darkgreen; backcolor lightgray; place 2 13" #stats.wins, "\" ;statswins #stats.wins, "delsegment stats.wins" #stats.wins, "flush stats.wins"
#stats.losses, "down; fill lightgray; color red; backcolor lightgray; place 2 13" #stats.losses, "\" ;statslosses #stats.losses, "delsegment stats.losses" #stats.losses, "flush stats.losses"
|
|
|
Post by tsh73 on Mar 4, 2022 11:08:21 GMT -5
Just insert that function in lines where you printing. So
#stats.wins, "\" ;statswins should became
#stats.wins, "\" ;using$(mask$, statswins)
You can define first, use mask$ for several lines - so if you need to add a decimal you'll change it in one place only.
Or put it right into function
#stats.wins, "\" ;using$("###,###,###.##", statswins)
|
|
|
Post by turtleman on Mar 4, 2022 11:51:49 GMT -5
I don't know what's going on! "using$" prevents the program from loading, and "using" without the "$" doesn't add the commas. However, it does insert a "%" on left side of the digits.
Sorry, but I'm too worn out and confused to be more detailed at the moment.
|
|
|
Post by tsh73 on Mar 4, 2022 12:04:37 GMT -5
It is user-defined function. For it to work you should add that function at the bottom of your program. This part
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
|
|
bplus
Full Member
Posts: 127
|
Post by bplus on Mar 4, 2022 12:25:31 GMT -5
Hey nice function! My test code:
for i = 1 to 20 print using$("###,###.##", rnd(0)*10000) next
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
|
|
|
Post by turtleman on Mar 4, 2022 12:49:39 GMT -5
Adding the function at the program's end got it working! (Don't know what was wrong before, but I'd be lying if I said I understood how it works.) While the commas now show up, the decimal position shifts as the number of digits changes. It will probably suffice for the smaller percentage graphic boxes, but I have some more changes to make first and will report back.
I wonder if there might be some "simpler" or alternate code that might be easier for me to understand.
|
|
|
Post by tsh73 on Mar 4, 2022 13:03:31 GMT -5
!!! use monospaced font (courier, andale mono, consolas) It should look like this
monospaced font example 1234567890.1234 MMMM is same width as iiii !!!
|
|
|
Post by turtleman on Mar 5, 2022 8:37:19 GMT -5
False alarm – still not working correctly, probably because the data isn't being properly formatted to the graphic boxes. Of course, not understanding "function using$(mask$, x)" isn't helping. I'm afraid I still don't completely understand how it works, particularly the ">";mask$;"<", ">" The example I shared earlier now looks like: mask$ = "###,###,###.##" x = statswins #stats.wins, "down; fill lightgray; color darkgreen; backcolor lightgray; place 2 13; font andale mono 10 bold" #stats.wins, "\" ; using$(mask$, x) #stats.wins, "delsegment stats.wins" #stats.wins, "flush stats.wins" For additional "fun," and because some static labels are on the left, I'd like the numbers to increment to the right of the most significant digit, while still inserting the commas. Is that even possible? Other graphic boxes display percentages ranging from 0% to 100% to 2 decimal places, but at least the decimal is in a fixed position. And I was so happy to finally have things working … until deciding to make "cosmetic" improvements. I hate to admit it, but I didn't even know what "monospaced" was until the other day! What I really need is someone to translate my 18K lines of spaghetti code into a semi-sane program … or maybe find another hobby!
|
|
|
Post by Walt Decker on Mar 6, 2022 12:05:05 GMT -5
Try this. It may be easier to follow and adapt to your particular needs.
PS: I will work on it with you.
' '<----------- EDIT CONTROL STYLES -------------> WS.HSCROLL = HEXDEC("&H00100000") WS.VSCROLL = HEXDEC("&H00200000")
ES.MULTILINE = HEXDEC("&H0004") ES.AUTOHSCROLL = HEXDEC("&H0080") ES.AUTOVSCROLL = HEXDEC("&H0040") ES.WANTRETURN = HEXDEC("&H1000")
A = 0 I = 0
DIM NumAry$(9)
B$ = "" FNmask$ = "" CRLF$ = CHR$(13) + CHR$(10)
WindowWidth = DisplayWidth * 0.5 WindowHeight = DisplayHeight * 0.5
STYLEBITS #USING.EDC, WS.VSCROLL OR WS.AUTOVSCROLL OR ES.MULTILINE OR _ ES.WANTRETURN, WS.AUTOHSCROLL, 0, 0 TEXTBOX #USING.EDC, 5, 5, WindowWidth - 28, WindowHeight - 50
UpperLeftX = 200 UpperLeftY = 175
OPEN "USING" FOR WINDOW AS #USING PRINT #USING.EDC, "!FONT COURIER_NEW 10"
'<---------------- FIND MINIMUM AND MAXIMUM STRING LENGTH ----------> Nmin = 1000 FOR I = 0 TO 9 B$ = STR$(INT(RND(0) * 10000000)) C$ = STR$(RND(0)) J = INSTR(C$, "e") IF J THEN C$ = LEFT$(C$, J - 1) B$ = B$ + C$ B$ = FN.PRound$(B$, 2) NumAry$(I) = B$ Nmax = MAX(Nmax, LEN(NumAry$(I))) Nmin = MIN(Nmin, LEN(NumAry$(I))) NEXT I
Pad = Nmax - Nmin '<--- front padding so decimals will align C$ = "" FOR I = 0 TO 9 IF LEN(NumAry$(I)) < Nmax THEN '<--- add padding if less than max length B$ = FN.REPEAT$("0", Pad) NumAry$(I) = B$ + NumAry$(I) END IF
B$ = NumAry$(I) FNmask$ = FN.Mask$(B$, 2) '<--- create the mask to fill FNmask$ = FN.FILLMASK$(B$, FNmask$) '<--- replace "#" with values IF I MOD 2 = 0 THEN '<--- if "I" evenly divisible by 2, negate the value FNmask$ = "-" + FNmask$ + CRLF$ ELSE FNmask$ = " " + FNmask$ + CRLF$ '<--- space to keep decimals aligned END IF
C$ = C$ + FNmask$ '<--- print values to edit control (textbox)
NEXT I PRINT #USING.EDC, C$
WAIT
FUNCTION FN.Mask$(C$, NumDecimals)
I = 0 '<--- counter LftLen = 0 '<--- length of intger part RgtLnn = 0 NumGroup = 0 '<--- groups of 3 in integer part Remainder = 0 '<--- what is left over in integer part
Lft$ = "" '<--- left side of decimal point Rgt$ = "" '<--- right side of decimal point Mask$ = "" '<--- return string LftMask$ = "" '<--- left (integer) formatting mask RgtMask$ = "" '<--- right (decimal) formatting mask
I = INSTR(C$, ".") '<--- find decimal point
Lft$ = LEFT$(C$, I - 1) '<--- split into integer and decimal Rgt$ = MID$(C$, I + 1)
'<--- change or truncate decimal portion to fit -----> RgtLen = LEN(Rgt$) IF RgtLen < NumDecimals THEN NumDecimals = RgtLen IF RgtLen > NumDecimals THEN Rgt$ = LEFT$(Rgt$, NumDecimals) END IF
RgtMask$ = FN.REPEAT$("#", NumDecimals) '<--- create the 'decimaol format
LftLen = LEN(Lft$) '<--- how many characters in intger part NumGroup = INT(LftLen / 3) '<--- how many groups of three 'in intger part Remainder = INT(LftLen - NumGroup * 3) '<--- how many 'left over characters 'in integer part
'<-------------------------------------------------> ' if left side (integer part) of number is not ' evenly divisible by 3 create a mask for the ' part not evenly divisible by 3 '<--------------------------------------------------> IF Remainder THEN LftMask$ = FN.REPEAT$("#", Remainder) + "," '<--- left over END IF
'<--- create the groups divisible by 3 -----------> 'characters FOR I = 1 TO NumGroup - 1 '<--- make into groups of three LftMask$ = LftMask$ + FN.REPEAT$("#", 3) + "," NEXT I
LftMask$ = LftMask$ + FN.REPEAT$("#", 3) '<--- last group of 'three Mask$ = LftMask$ + "." + RgtMask$ '<--- put 'em together
FN.Mask$ = Mask$ '<--- return result END FUNCTION
'---------------------------------------- '----------------------------------------
FUNCTION FN.REPEAT$(StrIn$, Ntimes) '############################################ ' CREATE A STRING Ntimes '############################################
I = 0 StrOut$ = ""
FOR I = 1 TO ABS(Ntimes) StrOut$ = StrOut$ + StrIn$ NEXT I
FN.REPEAT$ = StrOut$ END FUNCTION
'---------------------------------------- '----------------------------------------
FUNCTION FN.FILLMASK$(MainStr$, Mask$)
I = 0 J = 0 LenMain = 0 LenMask = 0
Char$ = "" LenMain = LEN(MainStr$) LenMask = LEN(Mask$) J = LenMask
FOR I = LenMain TO 1 STEP -1 Char$ = MID$(MainStr$, I, 1) IF Char$ = "." THEN GOTO [NXT.CHAR] '<--- skip decimal point
[CHK.MASK] IF MID$(Mask$, J, 1) = "#" THEN Mask$ = FN.INSERTSTR$(Mask$, Char$, J) '<--- replace "#" with value ELSE J = J - 1 '<--- character in mask is a comma so look at next character GOTO [CHK.MASK] END IF
[NXT.CHAR] NEXT I
FN.FILLMASK$ = Mask$ END FUNCTION
'---------------------------------------------- '----------------------------------------------
FUNCTION FN.INSERTSTR$(MainStr$, StrIn$, Posn)
Lft$ = "" Rgt$ = ""
Lft$ = LEFT$(MainStr$, Posn - 1) Rgt$ = MID$(MainStr$, Posn + 1) Lft$ = Lft$ + StrIn$ MainStr$ = Lft$ + Rgt$
FN.INSERTSTR$ = MainStr$ END FUNCTION
'------------------------------------------------------------ '------------------------------------------------------------
FUNCTION FN.PRound$(StrIn$, NumDec)
I = 0
LenIn = 0 Value = 0 Carry = 0 DivVal = 5 NewVal = 0 DecPos = 0
Rgt$ = "" Lft$ = "" Char$ = "" DecPos = INSTR(StrIn$, ".") Rgt$ = MID$(StrIn$, DecPos + 1) Lft$ = LEFT$(StrIn$, DecPos)
LenIn = LEN(Rgt$) FOR I = LenIn TO NumDec + 1 STEP -1 Value = VAL(MID$(Rgt$, I, 1)) Carry = INT(Value / DivVal) Value = VAL(MID$(Rgt$, I - 1, 1)) NewVal = Value + Carry
[CHK.CARRY] IF NewVal <> Value THEN IF NewVal > 9 THEN Char$ = "0" Rgt$ = FN.INSERTSTR$(Rgt$, Char$, I)' - 1) I = I - 1 ' IF I = NumDec THEN EXIT FOR Value = VAL(MID$(Rgt$, I, 1)) + Carry NewVal = Value / DivVal IF I = NumDec THEN EXIT FOR GOTO [CHK.CARRY] END IF Char$ = STR$(NewVal) Rgt$ = FN.INSERTSTR$(Rgt$, Char$, I - 1) END IF NEXT I
Rgt$ = LEFT$(Rgt$, NumDec) Char$ = Lft$ + Rgt$ FN.PRound$ = Char$ END FUNCTION
|
|
|
Post by turtleman on Mar 8, 2022 9:56:48 GMT -5
Walt: Thanks a lot for your code example and offering to help. Right now, however, I "discovered" some other bugs in my program that I'm attempting to exterminate. I'll be back here as soon as that's accomplished.
|
|