0

I've tried multiple solutions I've found here, but none are quite what I'm dealing with and thus my guesses at how to slice & dice the format inputs are failing. Below I have a VF email template that runs down a list of child rows to populate a table. It's come to my attention that the formatting is goofy - we need all the "currency" columns to display 000,000.00 format (notice I already have dynamic currency code) and the last column for Quantity to just display commas.

Currently there are no commas, and only a SINGLE place after the decimal - which even by itself is a weird default. Any help greatly appreciated!!

            <table border="0" >
              <tr >
                 <th>Action</th>
                 <th>Product Code</th>
                 <th>Product Name</th>
                 <th>End User Price</th>
                 <th>List Price</th>
                 <th>Target Price</th>
                 <th>Max Discount Price</th>                                  
                 <th>Annual Kit Qty / Units</th>
              </tr>
              <apex:repeat var="cx" value="{!relatedTo.Quote_to_Contract_Product__r}">
                <tr>
                  <td><a href="{!LEFT($CurrentPage.URL,FIND('/',$CurrentPage.URL,9))}{!cx.id}">View</a></td> 
                  <td> {!cx.Product_Code__c}</td>
                  <td> {!cx.Product__r.Name}</td>
                  <td> {!cx.CurrencyIsoCode} {!cx.End_User_Price_per_Kit__c}</td>
                  <td> {!cx.CurrencyIsoCode} {!cx.SYS_List_Price__c}</td>
                  <td> {!cx.CurrencyIsoCode} {!cx.SYS_Price_Floor_AE__c}</td>
                  <td> {!cx.CurrencyIsoCode} {!cx.SYS_Price_Floor_RD__c}</td>
                  <td> {!cx.Quantity__c}</td>
                </tr>
              </apex:repeat>                
            </table>

The current output: enter image description here

2 Answers 2

3

Visualforce has a way to specify formatting using <apex:outputText>.

You specify a format in the <apex:outputText> tag, and then include an <apex:param> tag between the start and end tags (instead of using <apex:outputText />)

<apex:repeat var="cx" value="{!relatedTo.Quote_to_Contract_Product__r}">
    <tr>
        <td><a href="{!LEFT($CurrentPage.URL,FIND('/',$CurrentPage.URL,9))}{!cx.id}">View</a></td> 
        <td> {!cx.Product_Code__c}</td>
        <td> {!cx.Product__r.Name}</td>
        <td> {!cx.CurrencyIsoCode} {!cx.End_User_Price_per_Kit__c}</td>
        <td> {!cx.CurrencyIsoCode} {!cx.SYS_List_Price__c}</td>
        <td> {!cx.CurrencyIsoCode} {!cx.SYS_Price_Floor_AE__c}</td>
        <td> {!cx.CurrencyIsoCode} {!cx.SYS_Price_Floor_RD__c}</td>
        <td> {!cx.Quantity__c}</td>
    </tr>
</apex:repeat>

becomes

<apex:repeat var="cx" value="{!relatedTo.Quote_to_Contract_Product__r}">
    <tr>
        <td><a href="{!LEFT($CurrentPage.URL,FIND('/',$CurrentPage.URL,9))}{!cx.id}">View</a></td> 
        <td> {!cx.Product_Code__c}</td>
        <td> {!cx.Product__r.Name}</td>
        <td> 
            <apex:outputText value="{!cx.CurrencyIsoCode} {0, number, ###,###.00}">
                <apex:param value="{!cx.End_User_Price_per_Kit__c}"/>
            </apex:outputText>
        </td>
        <td> 
            <apex:outputText value="{!cx.CurrencyIsoCode} {0, number, ###,###.00}">
                <apex:param value="{!cx.SYS_List_Price__c}"/>
            </apex:outputText>
        </td>
        <td> 
            <apex:outputText value="{!cx.CurrencyIsoCode} {0, number, ###,###.00}">
                <apex:param value="{!cx.Price_Floor_AE__c}"/>
            </apex:outputText>
        </td>
        <td> 
            <apex:outputText value="{!cx.CurrencyIsoCode} {0, number, ###,###.00}">
                <apex:param value="{!cx.Price_Floor_RD__c}"/>
            </apex:outputText>
        </td>
        <td> 
            <apex:outputText value="{!cx.CurrencyIsoCode} {0, number, ###,###}">
                <apex:param value="{!cx.Quantity}"/>
            </apex:outputText>
        </td>
    </tr>
</apex:repeat>

The {0, number, ###,###.##} bit is the formatting string, and it follows the Java MessageFormat syntax.

  • 0 = the argument index number (if you had multiple <apex:param>, the first would be index 0, the second index 1, etc...
  • number = the format type (one of number, date, time, choice)
  • ###,###.## = the subformat pattern (or format style)

You might be able to get away with {0, number, currency} (except for the quantity, which would be {0, number, integer}), but using a subformat pattern gives you more control.

Took a little bit of digging to unearth the characters you can use in a decimal subformat pattern, reproducing here...

Symbol Location Localized? Meaning
0 Number Yes Digit (always present)
# Number Yes Digit, zero shows as absent
. Number Yes Decimal separator or monetary decimal separator
- Number Yes Minus sign
, Number Yes Grouping separator
E Number Yes Separates mantissa and exponent in scientific notation. Need not be quoted in prefix or suffix.
; Subpattern boundary Yes Separates positive and negative subpatterns
% Prefix or suffix Yes Multiply by 100 and show as percentage
\u2030 Prefix or suffix Yes Multiply by 1000 and show as per mille value
¤ (\u00A4) Prefix or suffix No Currency sign, replaced by currency symbol. If doubled, replaced by international currency symbol. If present in a pattern, the monetary decimal separator is used instead of the decimal separator.
' Prefix or suffix No Used to quote special characters in a prefix or suffix, for example, "'#'#" formats 123 to "#123". To create a single quote itself, use two in a row: "# o''clock".

The difference between {0, number, ###,###.##} and {0, number, 000,000.00} would be that given an input of 1234.50

  • the first would display as "1,234.5"
  • the second would display as "001,234.50"

A "0" in the subpattern format causes that digit/decimal to always be displayed.
A "#" in the subpattern format removes leading and trailing 0s.

So following that, {0, number, ###,###.00} would display "1,234.50"

For reference, here is the VFP I used to test/confirm this behavior

<apex:page standardController="Account">
    <apex:outputText value="{!account.Name} {0, number, ###,###.##}">
        <apex:param value="{!1234.50}"/>
    </apex:outputText>
    <apex:outputText value="{!account.Name} {0, number, 000,000.00}">
        <apex:param value="{!1234.50}"/>
    </apex:outputText>
    <apex:outputText value="{!account.Name} {0, number, ###,###.00}">
        <apex:param value="{!1234.50}"/>
    </apex:outputText>
    <apex:outputText value="{!account.Name} {0, number, currency}">
        <apex:param value="{!1234.50}"/>
    </apex:outputText>
    <apex:outputText value="{!account.Name} {0, number, integer}">
        <apex:param value="{!1234.50}"/>
    </apex:outputText>
</apex:page>
2
  • Note: I haven't tested this with a Visualforce Email Template, just visualforce rendered on-platform in a Visualforce page.
    – Derek F
    Commented Apr 4, 2022 at 22:56
  • Thanks so much, yeah I eventually figured out that the formatting needed to be repeated, and inside each TD, and wrapped around the specific field.
    – Chris High
    Commented Apr 14, 2022 at 20:28
0

Thought I would come back and share in case it was ever useful for anyone else - this includes currency formatted columns along other columns that are just text or numbers, and the last column is also right-justified.

    <table border="0" >
          <tr >
             <th>Action</th>
             <th>Product Code</th>
             <th>Product Name</th>
             <th>End User Price</th>
             <th>List Price</th>
             <th>Target Price</th>
             <th>Max Discount Price</th>                                  
             <th> <div align="right"> Annual Kit Qty / Units </div> </th>
          </tr>
          <apex:repeat var="cx" value="{!relatedTo.Quote_to_Contract_Product__r}">

            <tr>
              <td><a href="{!LEFT($CurrentPage.URL,FIND('/',$CurrentPage.URL,9))}{!cx.id}">View</a></td>                                     
              <td> {!cx.Product_Code__c}</td>
              <td> {!cx.Product__r.Name}</td>
              <td> {!cx.CurrencyIsoCode}&nbsp; <apex:outputText value="{0,number,#,##0.00}"><apex:param value="{!cx.End_User_Price_per_Kit__c}"/> </apex:outputtext> </td>
              <td> {!cx.CurrencyIsoCode}&nbsp; <apex:outputText value="{0,number,#,##0.00}"><apex:param value="{!cx.SYS_List_Price__c}"/> </apex:outputtext> </td>
              <td> {!cx.CurrencyIsoCode}&nbsp; <apex:outputText value="{0,number,#,##0.00}"><apex:param value="{!cx.SYS_Price_Floor_AE__c}"/> </apex:outputtext> </td>
              <td> {!cx.CurrencyIsoCode}&nbsp; <apex:outputText value="{0,number,#,##0.00}"><apex:param value="{!cx.SYS_Price_Floor_RD__c}"/> </apex:outputtext> </td>
              <td> <div align="right"> <apex:outputText value=" {0,number,#,##0}"><apex:param value="{!cx.Quantity__c}"/> </apex:outputtext> </div> </td>                
            </tr>
            
          </apex:repeat>         
        </table>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .