Announcement

Collapse
No announcement yet.

MLG Column Total & MLG_Put() Function

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    As single Macro.
    Code:
    [COLOR=#0000C0]MACRO[/COLOR] string2money3(s) = [COLOR=#0000C0]USING$[/COLOR]([COLOR=#C020C0]".##"[/COLOR],[COLOR=#0000C0]VAL[/COLOR]([COLOR=#0000C0]IIF$[/COLOR]([COLOR=#0000C0]TALLY[/COLOR](s,[COLOR=#C020C0]"-"[/COLOR]),[COLOR=#C020C0]"-"[/COLOR],[COLOR=#C020C0]""[/COLOR])+[COLOR=#0000C0]RETAIN$[/COLOR](s, [COLOR=#0000C0]ANY[/COLOR] [COLOR=#C020C0]"0123456789"[/COLOR]))/[COLOR=#000000]100[/COLOR])

    Comment


    • #22
      String2Money3 does not require any code other than the 1-line macro!

      Excellent code worth going into the source code forum by Rod Macia.

      Code:
      MACRO string2money(s) = USING$(".##",string2long(s)/100)
      MACRO string2money3(s) = USING$(".##",VAL(IIF$(TALLY(s,"-"),"-","")+RETAIN$(s, ANY "0123456789"))/100) 'by Rod Macia 3/19/21
      
      [COLOR=#2980b9]'[B]Test 1-line String2Money3 macro vs String2Money (String2Money also requires string2long function)[/B][/COLOR]
      FUNCTION PBMAIN( )
      
       LOCAL s,s1,s2 AS STRING
      
       s = "You owe 1, dollar and 50 cents"
      
       s1= string2money(s)
       s2= string2money3(s)
      
       ? CHR$(s1,$CR,s2,$CR,SWITCH$(s1=s2,"success",s1<> s2,"wrong"))
      
      END FUNCTION
      
      FUNCTION string2long(snum AS STRING) AS LONG
       IF LEN(sNum) = 0 THEN EXIT FUNCTION
       'use "012345679-" at any position to create long value
       'does not terminate on invalid characters
       'credits to: john gleason, paul dixon, mike trader, mike doty (me)
       'http://www.powerbasic.com/support/pbforums/showthread.php?t=14373i]
      '--------------------------------------------------------------------------------------------
      '3/29/08 Correction: These 2 lines were somehow missing in previous posting and the code GPF'ed
      '3/17/21 Added IF LEN(sNum) = 0 check
      !mov edi,sNum ;get the pointer to the string information (not the string)
      !mov edi,[edi] ;get the point to the string contents (added this)
      '--------------------------------------------------------------------------------------------
      
      !xor edx,edx ;the sum =0
      !xor ecx,ecx ;the neg flag =0
      !movzx eax,byte ptr [edi] ;get the first character
      lp:
      !cmp eax,"0" ;is character < a "0"?
      !jl lessthan0 ;yes, skip to the non-digit check
      !cmp eax,"9" ;is it greater than a "9"?
      !jg nextcharacter ;yes, get next char.
      'to get here it must be a digit
      !imul edx,10 ;sum=sum*10 ..
      !add edx,eax ; + digit
      !sub edx,48 ; - 48
      !jmp nextcharacter
      lessthan0:
      REM !cmp eax,"." ;is it a "." 'rem to terminate on decimal
      REM !je done ;yes, then exit loop 'rem to terminate on decimal
      !cmp eax,"-" ;is it a "-"
      !jne nextcharacter ;no, get next character
      !mov ecx,1 ;set the neg flag
      nextcharacter:
      !inc edi ;increment the string pointer
      !movzx eax,byte ptr [edi] ;get next character
      !or eax,eax ;test if zero
      !jnz lp ;not zero, go back and do next character
      done:
      !cmp ecx,0 ;is neg flag set?
      !je skip ;no, skip next instruction
      !neg edx ;yes, negate answer
      skip:
      !mov function,edx ;write answer to function
      END FUNCTION'
      The world is full of apathy, but who cares?

      Comment


      • #23
        Thank you Sirs Macia and Doty, this post #22 solves a lot of my problems with my accounting programs which I started to program

        Comment


        • #24
          Wait , still has a problem with s = "1234567890" as it returns 12,345,678.90 instead of 1,234,567,890.00 ?

          maybe caused by /100 in the macros ?

          It needs to be able to check if the decimal point exist or not if it doesn't exist then ensure that there is no division by 100

          Comment


          • #25
            Routines are for calculator-style entry where operator never uses period. 1 = .01, 100 = a dollar.
            The world is full of apathy, but who cares?

            Comment


            • #26
              maybe caused by /100 in the macros ?
              not maybe, for sure!

              Use CUX.
              Dale

              Comment


              • #27
                This will crash.
                Code:
                MACRO string2money3(s) = USING$(".##",VAL(IIF$(TALLY(s,"-"),"-","")+RETAIN$(s, ANY "0123456789"))/100)
                
                FUNCTION PBMAIN( )
                 LOCAL s AS STRING
                 s = "1"
                 ? USING$("&",string2money3(s)),,"Won't make it here"
                END FUNCTION
                Last edited by Mike Doty; 19 Mar 2021, 12:06 PM.
                The world is full of apathy, but who cares?

                Comment


                • #28
                  Code:
                  MACRO string2money3(s) = USING$(".##",VAL(IIF$(TALLY(s,"-"),"-","")+RETAIN$(s, ANY "0123456789"))/100)
                  
                  FUNCTION PBMAIN( )
                   LOCAL s AS STRING
                   s = "1"
                   ? USING$("&",string2moneyfunc(s)),,"works as a function"
                   ? USING$("&",string2money3(s)) ,,  "crash"
                  END FUNCTION
                  
                  FUNCTION string2moneyfunc(s AS STRING) AS STRING 'works
                   FUNCTION = USING$(".##",VAL(IIF$(TALLY(s,"-"),"-","")+RETAIN$(s, ANY "0123456789"))/100)
                  END FUNCTION
                  Note: ? USING$("&",string2money(s)) ,, "does not crash"
                  Restrictions A macro definition may contain replacement text up to approximately 4000 characters. Macros may specify up to 240 parameters, which may occupy up to approximately 2000 bytes total expanded space per macro.
                  Macro Function substitutions are limited to an expanded total of approximately 16000 characters per line of original source code.
                  Macro parameters are substituted directly, so whitespace characters in the passed macro parameters may cause unexpected problems if the expanded code is syntactically incorrect with the additional whitespace. For example, this can be important when specifying UDT variables as macro parameters. Consider the following code:
                  Do not know why the program will crash with ? USING$("&",string2money3(s))
                  The world is full of apathy, but who cares?

                  Comment


                  • #29
                    Not Sure it's the Macro this does not work either.

                    Code:
                    [COLOR=#0000C0]? USING$[/COLOR]([COLOR=#C020C0]"&"[/COLOR],[COLOR=#0000C0]USING$[/COLOR]([COLOR=#C020C0]".##"[/COLOR],[COLOR=#0000C0]VAL[/COLOR]([COLOR=#0000C0]IIF$[/COLOR]([COLOR=#0000C0]TALLY[/COLOR](s,[COLOR=#C020C0]"-"[/COLOR]),[COLOR=#C020C0]"-"[/COLOR],[COLOR=#C020C0]""[/COLOR])+[COLOR=#0000C0]RETAIN$[/COLOR](s, [COLOR=#0000C0]ANY[/COLOR] [COLOR=#C020C0]"0123456789"[/COLOR]))/[COLOR=#000000]100[/COLOR]))

                    Comment


                    • #30
                      Too much for a single-line macro?
                      This works:
                      Code:
                      FUNCTION PBMAIN AS LONG
                       LOCAL sInput,sOutput AS STRING
                       sInput = "1"
                       sOutput = USING$(".##",VAL(IIF$(TALLY(sInput,"-"),"-","")+RETAIN$(sInput, ANY "0123456789"))/100)
                       ? USING$("&",sOutput)
                      END FUNCTION
                      The world is full of apathy, but who cares?

                      Comment


                      • #31
                        Originally posted by Tim Lakinir View Post
                        Wait , still has a problem with s = "1234567890" as it returns 12,345,678.90 instead of 1,234,567,890.00 ?

                        maybe caused by /100 in the macros ?

                        It needs to be able to check if the decimal point exist or not if it doesn't exist then ensure that there is no division by 100
                        No problem, it's by design. all values are assumed to be cents.
                        It would also give a wrong value if you give it "123.456" or "12345.6" it would become "1234.56"

                        If you need it to do something else feel free to contribute.

                        Comment


                        • #32
                          Originally posted by Mike Doty View Post
                          Too much for a single-line macro?
                          This works:
                          Code:
                          FUNCTION PBMAIN AS LONG
                          LOCAL sInput,sOutput AS STRING
                          sInput = "1"
                          sOutput = USING$(".##",VAL(IIF$(TALLY(sInput,"-"),"-","")+RETAIN$(sInput, ANY "0123456789"))/100)
                          ? USING$("&",sOutput)
                          END FUNCTION
                          I don't think it's the macro per say, but too complex as an embedded Using$ inside another Using$
                          when we perform as a function, or put it in a variable we simplify what the last Using$ gets.

                          Man I hope that was clear!
                          In any case I can live with the Function.

                          Comment


                          • #33
                            Maybe using a new function instead of a macro

                            Code:
                            '================================
                            ' Convert a string and round to 2 decimal places
                            ' as in money
                            ' by Rod Macia
                            FUNCTION Mstring2money3(GivenSt AS STRING) AS STRING
                               LOCAL gsLen , posDot , numDecpl AS LONG
                               GivenSt = TRIM$(GivenSt)
                               gsLen   = LEN(GivenSt)
                               IF gsLen = 0 THEN
                                   FUNCTION = ""
                                   EXIT FUNCTION
                               END IF
                               posDot   = INSTR(1,GivenSt,".")
                             ' number of original decimal places
                               numDecpl =  gsLen - posDot
                            
                               SELECT CASE numDecpl
                                   CASE 1
                               '   1 decimal place
                                   FUNCTION = USING$(",.##",VAL(IIF$(TALLY(GivenSt,"-"),"-","")+ _
                                      RETAIN$(GivenSt, ANY "0123456789"))/10)
                            
                                   CASE 2
                               '   2 decimal places
                                   FUNCTION = USING$(",.##",VAL(IIF$(TALLY(GivenSt,"-"),"-","")+ _
                                      RETAIN$(GivenSt, ANY "0123456789"))/100)
                            
                                   CASE 3
                               '   3 decimal places
                                   FUNCTION = USING$(",.##",VAL(IIF$(TALLY(GivenSt,"-"),"-","")+ _
                                      RETAIN$(GivenSt, ANY "0123456789"))/1000)
                            
                                   CASE 4
                               '   4 decimal places
                                   FUNCTION = USING$(",.##",VAL(IIF$(TALLY(GivenSt,"-"),"-","")+ _
                                      RETAIN$(GivenSt, ANY "0123456789"))/10000)
                            
                                   CASE 5
                               '   5 decimal places
                                   FUNCTION = USING$(",.##",VAL(IIF$(TALLY(GivenSt,"-"),"-","")+ _
                                      RETAIN$(GivenSt, ANY "0123456789"))/100000)
                            
                                   CASE <= 0
                               '    decimal point does NOT exist
                                    FUNCTION =  USING$(",.##",VAL(IIF$(TALLY(GivenSt,"-"),"-","")+ _
                                           RETAIN$(GivenSt, ANY "0123456789")))
                               END SELECT
                            
                            END FUNCTION

                            Comment


                            • #34
                              Code:
                              [COLOR=#3498db]posDot [/COLOR]= INSTR(1,GivenSt,".")
                              ' number of original decimal places
                              [COLOR=#e74c3c]numDecpl[/COLOR] = gsLen - posDot
                              posDot for a no decimal value will be 0
                              gsLen - 0 will = gslen
                              numDecpl will never be 0 so your CASE <= 0 will never happen.

                              You should use CASE gsLen instead

                              and you don't deal with a decimal a first position.

                              of course using CASE for each position means you would need to have one for all possible cases of the max number.

                              I would probably do something like this.

                              Code:
                              [COLOR=#0000C0]FUNCTION[/COLOR] Mstring2money4(GivenSt [COLOR=#0000C0]AS STRING[/COLOR]) [COLOR=#0000C0]AS STRING[/COLOR]
                                 [COLOR=#0000C0]LOCAL[/COLOR] gsLen , posDot , numDecpl [COLOR=#0000C0]AS LONG[/COLOR]
                                 GivenSt = [COLOR=#0000C0]TRIM$[/COLOR](GivenSt)
                                 gsLen   = [COLOR=#0000C0]LEN[/COLOR](GivenSt)
                                 [COLOR=#0000C0]IF[/COLOR] gsLen = [COLOR=#000000]0[/COLOR] [COLOR=#0000C0]THEN[/COLOR]
                                     [COLOR=#0000C0]FUNCTION[/COLOR] = [COLOR=#C020C0]""[/COLOR]
                                     [COLOR=#0000C0]EXIT FUNCTION[/COLOR]
                                 [COLOR=#0000C0]END IF[/COLOR]
                               
                                 posDot   = [COLOR=#0000C0]INSTR[/COLOR]([COLOR=#000000]1[/COLOR],GivenSt,[COLOR=#C020C0]"."[/COLOR])
                               [COLOR=#007F00]' 10 exponent number of original decimal places[/COLOR]
                                 numDecpl =  [COLOR=#000000]10[/COLOR] ^ (gsLen - posDot)   [COLOR=#007F00]' calculate divisor[/COLOR]
                               
                                  [COLOR=#0000C0]IF[/COLOR] PosDot > [COLOR=#000000]0[/COLOR] [COLOR=#0000C0]THEN[/COLOR]   [COLOR=#007F00]'   1 or more decimal place[/COLOR]
                                         [COLOR=#0000C0]FUNCTION[/COLOR] = [COLOR=#0000C0]USING$[/COLOR]([COLOR=#C020C0]",.##"[/COLOR],[COLOR=#0000C0]VAL[/COLOR]([COLOR=#0000C0]IIF$[/COLOR]([COLOR=#0000C0]TALLY[/COLOR](GivenSt,[COLOR=#C020C0]"-"[/COLOR]),[COLOR=#C020C0]"-"[/COLOR],[COLOR=#C020C0]""[/COLOR])+ _
                                            [COLOR=#0000C0]RETAIN$[/COLOR](GivenSt, [COLOR=#0000C0]ANY[/COLOR] [COLOR=#C020C0]"0123456789"[/COLOR]))/numDecpl)
                                  [COLOR=#0000C0]ELSE[/COLOR]
                                     [COLOR=#007F00]'    decimal point does NOT exist[/COLOR]
                                          [COLOR=#0000C0]FUNCTION[/COLOR] =  [COLOR=#0000C0]USING$[/COLOR]([COLOR=#C020C0]",.##"[/COLOR],[COLOR=#0000C0]VAL[/COLOR]([COLOR=#0000C0]IIF$[/COLOR]([COLOR=#0000C0]TALLY[/COLOR](GivenSt,[COLOR=#C020C0]"-"[/COLOR]),[COLOR=#C020C0]"-"[/COLOR],[COLOR=#C020C0]""[/COLOR])+ _
                                                 [COLOR=#0000C0]RETAIN$[/COLOR](GivenSt, [COLOR=#0000C0]ANY[/COLOR] [COLOR=#C020C0]"0123456789"[/COLOR])))
                                  [COLOR=#0000C0]END IF[/COLOR]
                              [COLOR=#0000C0]END FUNCTION[/COLOR]

                              Comment


                              • #35
                                Thank you Sir Macia, very concise way

                                Comment

                                Working...
                                X