Consulting

Results 1 to 15 of 15

Thread: Convert percentage into words

  1. #1
    VBAX Regular
    Joined
    Jul 2014
    Posts
    54
    Location

    Convert percentage into words

    It seems like I have nothing but questions these days - thank goodness for this forum!

    I have a Userform with a field for the user to insert a percentage rate, i.e. "1.0", "3.5", "0.47" etc which is then displayed in the document as:-

    "ONE (1.0) PER CENTUM PER ANNUM"
    "THREE POINT FIVE (3.5) PER CENTUM PER ANNUM"
    "ZERO POINT FOUR SEVEN (0.47) PER CENTUM PER ANNUM"

    I've just realised that using my usual method of CardText to convert the number into words isn't going to work for percentages as "0.47" for example will read "forty-seven" instead of "four seven".

    Is there a format that I can use to make this change?

    Thanks for all the assistance.

    Dav

  2. #2
    See http://www.gmayor.com/formatting_word_fields.htm and you may have to resort to more lateral thinking, as this time I don't think Paul will have a silver bullet - though no doubt he will be along later to confirm ... or not

    In the meantime you will undoubtedly find his work at http://www.gmayor.com/Zips/Word%20Field%20Maths.zip and http://www.gmayor.com/Zips/DateCalc.zip useful
    Last edited by gmayor; 04-26-2017 at 02:30 AM.
    Graham Mayor - MS MVP (Word) 2002-2019
    Visit my web site for more programming tips and ready made processes
    http://www.gmayor.com

  3. #3
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    Here's a stand-alone field code for a proof-of-concept. As coded it will handle up to three decimal places.
    {QUOTE{ASK Percent}{=INT(Percent) \* CardText}{SET Rmndr {=MOD(Percent,1)}}{IF{Rmndr}> 0 " point {=INT(Rmndr*10) \* CardText}{SET Rmndr {=MOD(Rmndr*10,1)}}{IF{Rmndr}> 0 " {=INT(Rmndr*10) \* CardText}"}{SET Rmndr {=MOD(Rmndr*10,1)}}{IF{Rmndr}> 0 " {=INT(Rmndr*10) \* CardText}"}"}}
    To extend the precision, you could simply keep adding more sets of the highlighted:
    {SET Rmndr {=MOD(Rmndr*10,1)}}{IF{Rmndr}> 0 " {=INT(Rmndr*10) \* CardText}"}
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  4. #4
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,335
    Location
    Since you are writing a userform text field input to the document, perhaps you could jus use a function:

    Sub ScratchMacro()
    'A basic Word macro coded by Greg Maxey
      MsgBox UCase(fcnSpellOut("0.47")) & " (0.47) PERCENT PER ANNUM"
    lbl_Exit:
      Exit Sub
    End Sub
    Function fcnSpellOut(strIn As String) As String
    Dim lngIndex As Long
      fcnSpellOut = vbNullString
      For lngIndex = 1 To Len(strIn)
        Select Case Mid(strIn, lngIndex, 1)
          Case ".": fcnSpellOut = fcnSpellOut & " point"
          Case "0": fcnSpellOut = fcnSpellOut & " Zero"
          Case "4": fcnSpellOut = fcnSpellOut & " Four"
          Case "7": fcnSpellOut = fcnSpellOut & " Seven"
        End Select
        fcnSpellOut = Trim(fcnSpellOut)
      Next
    End Function
    Greg

    Visit my website: http://gregmaxey.com

  5. #5
    VBAX Regular
    Joined
    Jul 2014
    Posts
    54
    Location
    Hi Paul

    Thanks very much for your suggestion. Before I play around with functions which I've never tried to use before I thought I'd try your field code.

    In my document I had two fields, one for balance and one for interest rate. I've already had assistance in splitting the balance and turning this from a numeric string into words as below:-

    Dim iSumOne As String 
    iSumOne = Me.ComboBox11.Value
    oVars("SumOnePounds") = Split(iSumOne, Chr(46))(0)
    If InStr(1, iSumOne, Chr(46)) > 0 Then
        oVars("SumOnePence") = Split(iSumOne, Chr(46))(1)
          Else
        oVars("SumOnePence") = vbNullString
           End If
    If Me.ComboBox11.Value = vbNullString And Me.ComboBox12.Value = vbNullString Then
    iSumOne = vbNullString
    oVars("SumOnePounds") = vbNullString
    oVars("SumOnePence") = vbNullString
    End If
    End If
    So what I tried was just doing the same with the interest figure but it was at that point I realised I was stuck:-

    Dim iSumOne As String, iIntOne As StringiSumOne = Me.ComboBox11.Value
    iIntOne = Me.ComboBox12.Value 'The number to be processed
    oVars("SumOnePounds") = Split(iSumOne, Chr(46))(0)
    oVars("IntOnePounds") = Split(iIntOne, Chr(46))(0)
    If InStr(1, iSumOne, Chr(46)) > 0 Then
        oVars("SumOnePence") = Split(iSumOne, Chr(46))(1)
        oVars("IntSumPence") = Split(iIntOne, Chr(46))(1)
       Else
        oVars("SumOnePence") = vbNullString
        oVars("IntOnePence") = vbNullString
       End If
    If Me.ComboBox11.Value = vbNullString And Me.ComboBox12.Value = vbNullString Then
    iSumOne = vbNullString
    iIntOne = vbNullString
    oVars("SumOnePounds") = vbNullString
    oVars("SumOnePence") = vbNullString
    oVars("IntOnePounds") = vbNullString
    oVars("IntOnePence") = vbNullString
    End If
    End If
    Am I right in thinking that in your example I can just have one DocVariable for interest without having to mess about splitting it and the formatting itself will do the heavy lifting?

    Sorry for all the questions, I'm getting into deeper water here than I've done previously.

    Thanks

    Dav

  6. #6
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,335
    Location
    I'm Greg. Paul is the smart guy.

    If you want to use DocVariables fields (why?) then you can still use the function (which you will need to complete out):

    Private Sub CommandButton1_Click()
      With ActiveDocument
        .Variables("Interest").Value = fcnSpellOut(ComboBox1.Value)
        .Fields.Update
      End With
    End Sub
    Function fcnSpellOut(strIn As String) As String
    Dim strTemp As String
    Dim lngIndex As Long
        strTemp = vbNullString
        For lngIndex = 1 To Len(strIn)
            Select Case Mid(strIn, lngIndex, 1)
            Case ".": strTemp = strTemp & " point"
            Case "0": strTemp = strTemp & " Zero"
            Case "4": strTemp = strTemp & " Four"
            Case "7": strTemp = strTemp & " Seven"
            End Select
            fcnSpellOut = UCase(Trim(strTemp) & " (" & strIn & ") PERCENT PER ANNUM")
        Next
    End Function
    In the document put { DocVariable Interest }
    Greg

    Visit my website: http://gregmaxey.com

  7. #7
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    Quote Originally Posted by DavG63 View Post
    Hi Paul

    Thanks very much for your suggestion. Before I play around with functions which I've never tried to use before I thought I'd try your field code.

    ...

    Am I right in thinking that in your example I can just have one DocVariable for interest without having to mess about splitting it and the formatting itself will do the heavy lifting?
    You could indeed do that. Suppose you have a DocVariable named 'Percent'. The field code for that would be:

    {QUOTE{=INT({DOCVARIABLE Percent}) \* CardText}
    {SET Rmndr {=MOD({DOCVARIABLE Percent},1)}}
    {IF{Rmndr}> 0 " point {=INT(Rmndr*10) \* CardText}
    {SET Rmndr {=MOD(Rmndr*10,1)}}
    {IF{Rmndr}> 0 " {=INT(Rmndr*10) \* CardText}"}
    {SET Rmndr {=MOD(Rmndr*10,1)}}
    {IF{Rmndr}> 0 " {=INT(Rmndr*10) \* CardText}"}"}}
    Your VBA code could then simply update the DocVariable, then issue 'ActiveDocument.Fields.Update' to update the content in the body.

    Note: I've laid out the field code with line breaks for clarity, but you don't need/want them in practice.
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  8. #8
    VBAX Regular
    Joined
    Jul 2014
    Posts
    54
    Location
    Hi Greg/Paul

    I'm pleased to say that after a little bit of work I was able to get the conditional format to work. Oh and to answer your question Greg, DocVariables were the first thing I learned how to use in VBA. I'm entirely self taught so it's just a case of my using what I know rather than trying to reinvent the wheel.

    Thanks so much to you both for your help, I really do appreciate it.

    Dav

  9. #9
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,335
    Location
    Ok. Say you wanted to use a content control titled "Interest" instead of a DocVariable field:

    Private Sub CommandButton1_Click() 
        ActiveDocument.SelectContentControlsByTitle("Interest").Item(1).Range.Text = fcnSpellOut(ComboBox1.Value) 
    End Sub
    Greg

    Visit my website: http://gregmaxey.com

  10. #10
    VBAX Regular
    Joined
    Jul 2014
    Posts
    54
    Location
    I've managed to get it working so that it now works when there's an interest rate.

    If you remember my prior question about deleting out rows in tables however you'll probably know where this question is going. If the interest field is left blank because that row of the table isn't going to be displayed, it now won't delete because that field leaves behind text.

    My usual

    {IF {DocVariable IntOne }="Error!* ""
    Isn't doing the trick this time and instead just makes the whole thing disappear.

    One step forward, two steps back!

    Any ideas of a way to get round it?

  11. #11
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    The fairly obvious answer is to not rely on the cell's content to determine whether to delete the row - rely on the value of whatever you're using to populate (or not) the Document Variable instead. Of course, field coding can be used to suppress the error message, but why bother with that if the row is destined for the bin?
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  12. #12
    VBAX Regular
    Joined
    Jul 2014
    Posts
    54
    Location
    Yeah I get what you're saying. Is there a simple code then that I could use that would delete row two if a variable is blank and row three if another is also blank?

  13. #13
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    That's pretty basic. For example:
    If ComboBox1.Value = "" Then ActiveDocument.Tables(1).Rows(5).Delete
    where 1 is the table # and 5 is the row #.
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  14. #14
    VBAX Regular
    Joined
    Jul 2014
    Posts
    54
    Location
    Thanks Paul, I'll give that a try.

  15. #15
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    Of course, you could just output 0 to IntOne, and have 'zero' (plus whatever other text you want) output via the DOCVARIABLE field, thereby obviating the problem...
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •