[SalesForce] Generate Barcode dynamically in Email Body/Attachment

I need to send emails to multiple contacts with a bar code based on Customer ID in a pdf attachment.
The requirement was to add the bar code in the attachment but due to salesforce limitation of accessing external images when rendered as pdf , made me modify the code to put the bar code in html email body.

I am using a third party freeware to generate the bar code , but still not able to generate barcode in the attachment.

Here is my vfpage mail template

<messaging:emailTemplate subject="Account Info" recipientType="Contact" relatedToType="Account">
<messaging:htmlEmailBody >
Hi

Welcome to Stackexchange <br/>
Congratulations!
This is your Sample Email Template. <br/>
We are happy to provide you with the gift card <br/>
Kindly open the attachment for more details<br/>
<img id="theImage" src="http://www.barcodesinc.com/generator/image.php?code={!relatedTo.Cust_ID__c}&style=325&type=C128B&width=200&height=50&xres=1&font=3" />   
</messaging:htmlEmailBody>
<messaging:attachment renderAs="PDF">
    <html>
    <head/>
    <body>
   <td> Hi {!relatedTo.name} </td><br/>
   {!relatedTo.Phone} <br/>
   {!relatedTo.Email_Address__c} <br/>
   {!relatedTo.Cust_ID__c} <br/>

    We are happy to provide you with the gift card
   </body>
    </html>
</messaging:attachment>
</messaging:emailTemplate>

Note: I have added barcodesinc.com in Remoe Site Settings.

My query is how can we make the image available in the attachment

Currently its coming as a broken image.

Best Answer

The remote site setting has nothing to do with the barcode appearing/not appearing.

Try the following:

<apex:image value="{!URLFOR('http://www.barcodesinc.com/generator/image.php', null, [code=relatedTo.Cust_Id__c, style=325, type='C128B', width=200, height=50, xres=1, font=3])}" />

I just tested this in my dev org with a standard field, and it works.

I suspect that your URL is getting confused because of unescaped characters, so this should fix it. You could also use URLENCODE.


I threw together some code that works in a PDF attachment, if you're really stuck. I've included the code as a Gist, but I'll also reproduce it here.


public class Code39Controller {
    // Determines if the check digit should be generated
    // If true, scanners must be enabled to use it
    public Boolean shouldCheckDigit { get; set; }
    // The source string to use. Currently only supports
    // the characters in the "keys" string. Do not use '*'.
    public String sourceCodeValue   { get; set; }

    // The index for supported characters.
    static String keys = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*';

    // The binary representation of each character, 16 bits each.
    static String[] values = new String[] {
        '1010001110111010', '1110100010101110', '1011100010101110', '1110111000101010',
        '1010001110101110', '1110100011101010', '1011100011101010', '1010001011101110',
        '1110100010111010', '1011100010111010', '1110101000101110', '1011101000101110',
        '1110111010001010', '1010111000101110', '1110101110001010', '1011101110001010',
        '1010100011101110', '1110101000111010', '1011101000111010', '1010111000111010',
        '1110101010001110', '1011101010001110', '1110111010100010', '1010111010001110',
        '1110101110100010', '1011101110100010', '1010101110001110', '1110101011100010',
        '1011101011100010', '1010111011100010', '1110001010101110', '1000111010101110',
        '1110001110101010', '1000101110101110', '1110001011101010', '1000111011101010',
        '1000101011101110', '1110001010111010', '1000111010111010', '1000100010001010',
        '1000100010100010', '1000101000100010', '1010001000100010', '1000101110111010' };

    // Renders the barcode on the screen
    public String[] getBarCodeBars() {
        return generateCode39(sourceCodeValue, shouldCheckDigit).split('');
    }

    // Returns a string in case we also want to debug the output.
    String generateCode39(String source, Boolean checkDigit) {
        // Output
        String[] result = new String[0];

        Integer index,      // Temp variable
                total = 0;  // Checksum calculation

        // Avoid System.NullPointerException
        source = source == null? '': source;
        // Start character is *
        result.add(values[keys.indexOf('*')]);
        // For each character in source
        for(String sourceChar: source.toUpperCase().split('')) {
            // Valid character, add to checksum and output bits
            if((index = keys.indexOf(sourceChar)) > -1) {
                result.add(values[index]);
                total += index;
            }
        }
        // Add the check digit
        if(checkDigit) {
            result.add(values[Math.mod(total, 43)]);
        }
        // Add the stop character
        result.add(values[keys.indexOf('*')]);
        // Join as string
        return String.join(result,'');
    }
}

.blackbar, .whitebar {
    display: inline-block;
    overflow: hidden;
    padding: 0;
    width: 1px;
    height: 1cm;
}
.blackbar {
    background-color: black;
}
.whitebar {
    background-color: white;
}

<apex:component controller="code39" access="global">
    <!-- global required to use in templates -->

    <apex:attribute assignTo="{!shouldCheckDigit}" type="boolean" name="checkDigit" default="false" description="True if should append additional check character." />

    <!-- codeValue must be supplied, but cannot be required because of global attribute -->
    <apex:attribute assignTo="{!sourceCodeValue}" type="string" name="codeValue" description="The string to encode." />

    <!-- style sheet must be included to work properly -->
    <apex:stylesheet value="{!URLFOR($Resource.barcodeCSS)}"/>

    <!-- leave some space on the side for scanners -->
    <div style="display: inline-block; border: 1px solid black; min-width: 1in; padding: 0.25in 1in;" >
        <div>
            <apex:repeat value="{!barCodeBars}" var="bar">
                <apex:outputText value="" styleClass="{!if(bar='1','blackbar','whitebar')}" />
            </apex:repeat>
        </div>
        <div style="text-align: center">
            <!-- we'll show the output text on the bottom, too -->
            {!sourceCodeValue}
        </div>
    </div>
</apex:component>

I used it in an email as follows:

<messaging:emailTemplate subject="Account Info" recipientType="User" relatedToType="Account">
<messaging:htmlEmailBody >
Hi

Welcome to Stackexchange <br/>
Congratulations!
This is your Sample Email Template. <br/>
We are happy to provide you with the gift card <br/>
Kindly open the attachment for more details<br/>

</messaging:htmlEmailBody>
<messaging:attachment renderAs="PDF">
    <html>
    <head/>
    <body>
   <td> Hi {!relatedTo.name} </td><br/>
   {!relatedTo.Phone} <br/>

    We are happy to provide you with the gift card<br /><br />
    <c:barcode39 codeValue="{!relatedTo.AccountNumber}" />
   </body>
    </html>
</messaging:attachment>
</messaging:emailTemplate>
Related Topic