This post guides you through the simple steps needed to add your DYMO LabelWriter printer(s) to the Salesforce.com environment so that you can print a contact’s mailing address on a DYMO address label.
The post assumes that you are familiar with Salesforce.com’s CRM software and have a developer account with the company. Consult Salesforce.com user documentation if you have never created a Visualforce page.
The major tasks are:
- Download and install the appropriate DYMO Label software and SDK
- Create the Visualforce page that enables you to:
- · Enumerate a list of client-side printer names
- · Generate and preview an image for the label
- · Create an editable multi-line text box with the mailing address for a selected contact
- · Print the label
- · Create a Print Label button
When these tasks are completed, your Salesforce.com page will resemble the following example:
Introduction
Salesforce.com is a Web-based service. As such, Salesforce.com stores and manipulates data on the server side without the need to know much about the client side – your computer. The Salesforce.com server has no knowledge of the peripherals that are connected to your computer. The DYMO Label Framework JavaScript Library fills the gap between your Salesforce.com data and your DYMO LabelWriter printer.
Salesforce.com may be customized for individual customer needs. This post provides JavaScript code examples and describes the Visualforce customization that is required for the CRM software- LabelWriter printer integration.
Download and Install DYMO Label Software
You need to download and install the following software:
DYMO Label v.8.3 (DLS). The latest updates are available for Windows and Mac
· Windows DYMO Label v.8.3 Installer
· Mac DYMO Label v.8.3 Installer
DYMO Label Framework JavaScript library which supports the most popular browsers for Windows and Mac
· DYMO Label Framework JavaScript Library
Creating the Visualforce Page
This post uses the standard Visualforce controller extension to provide access to a current contact’s data. To work with an existing contact’s data, you must specify the contact’s ID in the URL as an input parameter.
To begin, you have to:
- Pick one of your contacts (using the Contacts tab).
- Create a new URL that enables you to create a new Visualforce page.
- Type a page name in the URL, specifying the contact’s ID as an input parameter.
With Salesforce.com running, go to a contact’s Detail page and copy the ID from the browser’s address bar. The following screenshot shows the contact ID for Mr. Sean Forbes.
Paste the ID into your new URL. The new page URL will resemble the following:
https://c.na5.visual.force.com/apex/PrintAddress?id=0037000000TG8xR’
where PrintAddress is the name of your Visualforce page.
After this URL is typed into the browser’s address bar, the system displays the message:
Page PrintAddress does not exist
To create a page, click the Create Page link beneath this message.
An empty page is created and you can begin to construct the Visualforce page elements described in this post.
Specifying the Controller Extension and Linking the DYMO Label Framework JavaScript Library
Begin by specifying the controller extension and linking the page with the DYMO Label Framework JavaScript Library. Here is the code that does this:
<apex:page id="printAddressPage" standardController="Contact" extensions="PrintAddressExtension">
<apex:includeScript value="{!$Resource.DymoFramework}"/>
<div style="padding-bottom:6px">
<apex:outputLink value="{!URLFOR($Action.Contact.View, $CurrentPage.parameters.id)}">
Back to {!paObject.Contact.FirstName} {!paObject.Contact.LastName} detail page
</apex:outputLink>
</div>
<apex:form >
</apex:form>
</apex:page>
Before including the library in your page, you must add the DYMO Label Framework JavaScript Library as a static resource. Here are the steps:
- Create the resource by selecting App Setup > Develop > Static Resource from Salesforce.com.
- Provide a name, for example: DymoFramework.
- Browse to the folder where the DYMO Label SDK is installed (or where DYMO Framework JavaScript library is downloaded).
- Select the DYMO.Label.Framework.js file.
Now the framework library can be referenced on the page as:
<apex:includeScript value="{!$Resource.DymoFramework}"/>
The next part of the code is used as a page controller. You create a singleton:
paObject
to get access to the current contact’s properties as well as to accommodate other methods that the Visualforce page may require.
public class PrintAddressExtension
{
public PrintAddressExtension(ApexPages.StandardController controller)
{
}
public class PaObject
{
private Contact m_contact;
public PaObject()
{
Id id = System.currentPageReference().getParameters().get('id');
m_contact = id == null ? new Contact() :
[Select Id, FirstName, LastName, MailingStreet, MailingCity, MailingState, MailingCountry,
MailingPostalCode FROM Contact WHERE Id = :id];
}
public Contact getContact()
{
return m_contact;
}
// contact full name
public String getContactFullName()
{
if (m_contact == null)
{
system.Debug(logginglevel.ERROR, 'PaObject.m_contact is null');
return '';
}
return m_contact.LastName + ', ' + m_contact.FirstName;
}
}
private paObject m_paObject;
public PaObject getPaObject()
{
if (m_paObject == null)
{
m_paObject = new PaObject();
System.debug(logginglevel.INFO, 'singleton PaObject is created');
}
return m_paObject;
}
}
Save the Visualforce page and controller.
The system displays a page with a link:
Back to <Contact> detail page.
Enumerating Printer Names
As mentioned previously, the Salesforce.com server does not know what peripherals are connected to your computer. You must generate a list of the printer names separately on the client side and provide this information to Salesforce.com. You do this by coding a JavaScript routine that enumerates the available printers.
The Visualforce page contains an <apex:selectList> control (selection drop-down combo-box). You leave this control empty when the Visualforce page is first created. The control is created in such a way that you can add items to it later. You will have a global variable, <apex:selectList>, reference to this control.
Here is the piece of code that shows all these elements:
<apex:form >
<apex:pageBlock id="PrintersBlock" title="Select Printer">
<apex:selectList id="Printers" size="1" />
</apex:pageBlock>
<script>
var PrintersCtrl = document.getElementById("{!$Component.PrintersBlock.Printers}");
</script>
</apex:form>
To get access to the generated HTML element, you declare a PrintersCtrl variable and reference it using the full path of nested page blocks. The Salesforce.com syntax is:
{!$Component.PrintersBlock.Printers}
The JavaScript code shown below populates the list. The code uses the onload page event to hook to the procedure of enumerating LabelWriter printers. The enumPrinters function returns a list of available printers. From this function, you call the DYMO Label Framework JavaScript Library method declared as getPrinters(). You reference this method by the namespaces declared in the Library.
dymo.label.framework.getPrinters();
The method returns a list of the names of all available DYMO label printers installed on the client. Since you are going to print an address label, you can only use LabelWriter printers because these printers use die-cut address labels.
The DYMO Label Framework JavaScript Library returns the complete list of printers. You must iterate through the list again and dynamically create OPTION elements filled with only the LabelWriter printer names.
At this point, the reference to the HTML-rendered control becomes handy because you can access to the element (PrintersCtrl ) from JavaScript as:
PrintersCtrl.options.add(option);
Now, find the </apex:form> tag in the previous code example, and add the following code below the tag.
<script type="text/javascript">
function enumPrinters() {
var plist = new Array();
var printers = dymo.label.framework.getPrinters();
if (printers.length == 0) {
alert("No DYMO printers are installed. Install DYMO printers.");
}
else {
for (var i = 0; i < printers.length; i++) {
if (printers[i].printerType == "LabelWriterPrinter")
plist[i] = printers[i].name;
}
}
return plist;
}
window.onload = new function () {
var plist = enumPrinters();
if (plist.length > 0) {
// populate combo-box control with a list of printers
for (var i = 0; i < plist.length; i++) {
var option = document.createElement("OPTION");
option.text = plist[i];
option.value = plist[i];
PrintersCtrl.options.add(option);
}
}
}
</script>
The Salesforce.com page now includes a SELECT control that is populated with the names of DYMO LabelWriter printers.
Updating the Label Preview
Next, you generate an image for the label preview. Some of the work, such as rendering the actual image, needs to be done on the client since only the DYMO Label Framework knows how to do this. The idea is that prior to submitting the page for a redraw, the client side needs to generate an image and save the result in the Visualforce page’s hidden field. When the Visualforce page is redrawn, it will contain the updated image taken from the controller’s member associated with the hidden field. To implement this approach, you introduce other Visualforce UI elements and global variables. Here is the code for this work:
<apex:form>
<apex:inputhidden id="PreviewImageSrc" value="{!paObject.imageSrc}"/>
<apex:pageBlock id="EditorBlock" title="{!paObject.contactFullName}">
<div>
<apex:inputTextarea id="AddressEditor"
value="{!paObject.formattedAddress}" rows="4" cols="52"/>
</div>
<div>
<apex:inputCheckbox id="BarcodeCheckbox" selected="{!paObject.printBarcode}"
style="vertical-align:middle"/> Print Intelligent Mail Barcode
</div>
<hr/>
<apex:commandButton id="ButtonUpdate" value="Update" rerender="PreviewPanel"
onclick="updatePreview('{!paObject.addressLabelXml}')"/>
</apex:pageBlock>
<apex:pageBlock id="PrintersBlock" title="Select Printer">
<apex:selectList id="Printers" size="1" />
</apex:pageBlock>
<script>
var PrintersCtrl = document.getElementById("{!$Component.PrintersBlock.Printers}");
var AddressEditor = document.getElementById("{!$Component.EditorBlock.AddressEditor}");
var BarcodeCheckbox = document.getElementById("{!$Component.EditorBlock.BarcodeCheckbox}");
var PreviewImageSrc = document.getElementById("{!$Component.PreviewImageSrc}");
var ButtonUpdate = document.getElementById("{!$Component.EditorBlock.ButtonUpdate}");
</script>
</apex:form>
<apex:outputpanel id="PreviewPanel">
<div>
<apex:image id="previewImage" url="{!paObject.imageSrc}"/>
</div>
</apex:outputpanel>
The added UI controls are:
- A multi-line text editor for modifying the address (if desired).
- A checkbox that triggers the inclusion of the Intelligent Mail Barcode on the label.
- An Update button.
The Update button contains the rerender="PreviewPanel" attribute, which refreshes only the preview part of the page. When the Update button is clicked, only <apex:outputpanel> within the Visualforce page is redrawn. (See the Salesforce.com ’s user documentation for more information regarding the partial page refresh.)
Another element this code creates is a hidden field that stores the image preview’s raw data between the time when the update action is invoked and the time when the preview panel is redrawn. The code also contains a reference to the Update button itself because an update action must be invoked when the page is loaded for the first time.
The code hooks to the updatePreview JavaScript function when the Update button is clicked. Similar to the enumPrinters function, this updatePreview JavaScript function calls the DYMO Label Framework Library to open a label template and set the address data in the template’s address object. If you need to make additional modification to the label’s appearance—because of a user request or the data itself—it can be done in this updatePreview function.
In the example shown below, the code prevents the address barcode from appearing in the address.
function updatePreview(template) {
try {
var address = AddressEditor.value;
var label = dymo.label.framework.openLabelXml(template);
label.setAddressText(0, address);
// barcode - show it or not
if (!BarcodeCheckbox.checked)
label.setAddressBarcodePosition(0, dymo.label.framework.AddressBarcodePosition.Suppress);
var pngData = label.render();
PreviewImageSrc.value = "data:image/png;base64," + pngData;
}
catch (e) {
alert(e.message);
}
}
The updatePreview function takes one parameter: an xml string that represents the label template. For simplicity, the example includes the xml template definition as a read-only property in the controller. Alternately, this string could be a static resource.
The call to the DYMO Label Framework Library’s label.render() method returns an image’s raw data as a string. The code assigns this string to the hidden text field (accessible as PreviewImageSrc).
An important thing to remember is that the Visualforce <apex:inputhidden> element requires a corresponding property in the controller. The controller should have a string property called imageSrc.
When the Update button is clicked, the updatePreview function:
- Gathers all the data from the page controls.
- Generates the label’s image.
- Saves the image in the hidden field associated with the controller’s property.
- Submits a request to redraw part of the page.
When the page is rendered, the Visualforce control <apex:image url="{!paObject.imageSrc}"/> contains an updated image.
To have a preview shown when the page is loaded for the first time, you have to add the next line into the page initialization routine:
ButtonUpdate.click();
Printing the Label
The Visualforce page requires a Print button that is linked to a corresponding JavaScript function attached to an onclick event. The printing function is not much different from the updating the preview function. However, instead of getting the label preview from the label.render() method, the function invokes label.print to print at the desired printer.
Here is the JavaScript print function code:
function printAddress(template) {
try {
var label = dymo.label.framework.openLabelXml(template);
label.setAddressText(0, AddressEditor.value);
if (!BarcodeCheckbox.checked)
label.setAddressBarcodePosition(0, dymo.label.framework.AddressBarcodePosition.Suppress);
var printer = PrintersCtrl.value;
label.print(printer);
}
catch (e) {
alert(e.message);
}
}
Creating a Print Label Button
Here is the link to the code examples:
http://www.labelwriter.com/software/dls/sdk/blog_resources/Salesforce.PrintAddress.zip
To make them work, you must add a custom button to the contact’s Detail page.
- Select Setup > Customize > Contacts > Buttons and Links.
- Click the New button in the Custom Buttons and Links section.
A page similar to the following example appears.
- Provide the requested parameters.
- · Button Label and Name
- · Description
- · Display Type (the type of UI link or button)
- · Behavior (select Display in existing window with sidebar)
- · Content Source (select Visualforce Page)
When you have completed and saved this customization work, a Print Label button appears on the Detail page for each of your contacts.
Conclusion
That is all there is to it. I hope this post has demonstrated how easy it is to integrate DYMO LabelWriter printers into a Salesforce.com application.