Dec 082015
 

We are proud to announce the release of DYMO Label software version 8.5.3 for Windows.

UPDATE: The newest version is available in the following post: DLS 8.5.3 Patch Release

This release includes:

  • Support for Microsoft Windows 10
  • Support for Microsoft Office 2016
  • DYMO Label Web Service is installed for use by the DYMO Label Framework.

You can now download: DYMO Label software 8.5.3
You can also download the Javascript Library : DYMO Label Framework 2.0

Reference the following posts for additional set up information.  Keep in mind that the Web Service is build into this version of DYMO Label so the standalone install is no longer required.

We also know that you are interested in the Mac version.  We have had a lot of issues getting the design to work on Mac OSX, we have hit a major milestone this week and we now have a release candidate for DLS 8.5.3 for the Mac.  If everything passes, we should be able to release it within a work week.

As a note to all our patient customers, we really appreciate you and your patience.  This has been a more difficult release than we had thought but it is finally happening.  All we have now is the imminent MacOSX release.   Thank you!

Update: Added link to new Javascript library version and added links to older posts for references

Jul 282011
 

We are proud to announce the release of DYMO Label software version 8.3.1 for Mac. This release adds support for Mac OS X 10.7 (Lion). This release is mandatory, earlier releases will NOT work on 10.7. The release is available from here.

Here is some technical information describing the underlying changes in DLS and the printer drivers:

  1. In 10.7 Apple discontinued the Tioga printer driver architecture which had been in use since the initial release of Mac OS X 10.0. The only driver architecture supported in 10.7 is CUPS. DLS prior to 8.3.1. includes Tioga drivers, while DLS 8.3.1 includes both Tioga (for Mac OS X 10.5 and 10.6) and CUPS (for 10.7) drivers.
  2. Apple discontinued WebKit-style Safari plugins. This does not affect DLS itself, but does affect DYMO SDK users. There are two scenarios where SDK users are affected:
    • If a SDK web application uses DYMO Safari plugin directly. In this case the only solution is to switch to DYMO Label Framework JavaScript library. This should be done NOT by DYMO but by the application developer.
    • If a SDK web application uses DYMO Label Framework JavaScript library. In this case the application developer should update their app to use the just released version 1.2  of the library.

So, if you are a developer integrating DYMO printers on Mac platform, here are the steps to make sure your application works on 10.7:

  • tell users to update to DLS 8.3.1
  • if your application is a web application:
    • switch code from using DYMO Safari plugin to using DYMO Label Framework JavaScript Library
    • make sure to use the latest version of the library available (1.2)

Update:

If you are experiencing problems with installing or using the printer try these steps:

  • Unplug printer’s USB cable
  • (Re)Install DLS 8.3.1
  • Reboot Mac
  • Replug printer’s USB cable

If the problem persists, please contact DYMO Tech Support, http://sites.dymo.com/Support/Pages/ContactForm.aspx.

Update Regarding LabelWriter 3xx Series Printers on Mac OS 10.7

DYMO LabelWriter 3xx series printers are not supported on Mac OS X 10.7.  We dropped support for technical reasons – starting with 10.7 the Tioga driver system that DYMO drivers have always used is no longer supported by Apple. So we switched to CUPS drivers, and these do not work with the older 300 series hardware.

Please contact DYMO customer service for assistance – 1-877-724-8324. Sorry for the inconvenience.

 

Jul 192011
 

We are proud to announce a BETA release of the DYMO Label Mobile SDK for Android. The DYMO Label Mobile SDK for Android is a complete toolset containing libraries, documentation, and samples that make it easy to add label printing to any Android app. All DYMO LabelWriter and DYMO LabelManager printers are supported. Using the DYMO Label Mobile SDK in combination with DYMO Label Web SDK allows creating both native and web-based apps for Android.

Please Note

This release is a BETA and is not supported by DYMO. It has not been extensively tested outside DYMO and should be used for developer testing only, NOT for production software releases.

Architecture Overview

It is essentially the same as the architecture of DYMO Label Mobile SDK for iOS.

DYMOLabelMobileSDKforAndroid

The major piece here is a computer that has a DYMO printer plugged-in and DYMO Label software installed. DYMO Label software contains a service called DYMO Label Proxy that allows communication between an Android device and the printer.

Notes:

  • right now DYMO Label Proxy is available for Windows only. So, a printer must be connected to a Windows machine, or be available from Windows machine that has DYMO Label Proxy installed (see below).
  • the printer itself does not have to be connected directly to the computer running DYMO Label Proxy. The printer has to be ACCESSIBLE from that machine. This means that the printer might be really connected to a different machine and be a “shared” network printer. Or the printer might be connected to a DYMO Print Server and be “installed” on the computer using a RAW TCP/IP port. This setup might be used to simplify installation (see below).
  • the local network is used for communications between the proxy service and the mobile device. That means that on the mobile device the Wi-Fi should be turned on and the device should be connected to the network. Using just 3G is not enough.

Installation

SDK Installation

SDK is available here. It is a zip file, just extract it to any folder. Inside there are following folders:

  • docs – SDK documentation. Contains API reference documentation in JavaDoc format.
  • libs – jars to be included with an application.
  • Samples – sample apps.

Samples were tested with Eclipse Helios and Android SDK r11. The SDK supports Android API level 8 (2.2) and later.

DYMO Label Proxy Installation

The installation is fairly simple. Just install DYMO Label software, that’s it. DYMO Label Proxy service will be installed and run as a part of the installation. DYMO Label Proxy is a Windows service running on port 8631 by default. Because of that there are couple of considerations that must be taken into account:

  • DYMO Label Software will configure Windows Firewall to open the port 8631 for inbound requests. If a different firewall software is installed, you have to configure it manually.
  • The port number may be changed from the default one. Either use the configuration utility included or specify the port manually in the service’s application .config file. In any case don’t forget to update the firewall rules to open the port. Otherwise clients will not be able to connect to the service.
  • The final release to the public will add the ability to select the port number and autostart options for the service during installation.

Note: This version of DYMO Label Proxy contains enchantments and bug fixes over the version released for Web and iOS SDKs. To be able to use with Android SDK you must update it to the latest version.

DYMO Label Proxy Configuration

To configure the service use DYMOLabelProxyServiceConfiguration.exe utility. It lets you change the port number the service is listening to as well as stop/start/restart the service. In addition the utility displays a list of urls that might be used to connect to the service.

image_thumb

Changing Port Number

To change the port number enter a new value into “Port Number” field and click “Apply” button. Right now the service is not restarted automatically, so don’t forget to restart it.

Service Control

You can start/stop/restart the service from within the configuration utility. Alternatively the standard “Services” panel of the  “Computer Management” tool can be used.

Service ip-address

Usually the SDK is able to discover the service on the network automatically using Bonjour. But sometimes Bonjour does not work. One common case is when the service and the Android device are on different subnets, e.g. the mobile device is connected to a “wireless” subnet and the service to a “wired” subnet. This is not a problem with the DYMO service, it is how Bonjour works in its default configuration. There are solutions for this problem, but the detailed descriptions are beyond the scope of this post. Some ideas:

In this case it is necessary to know the service’s ip-address to be able to connect to it from the Android device (see below). The configuration utility can help here as well. Service’s ip-address(es) is displayed in Service URIs list.

API Overview

The SDK contains two complete samples those demonstrate most of the functionality the SDK provides. Here we will look at the API from the point of tasks that are necessary to perform to print a label. To print a label the following tasks usually have to be performed:

  1. framework initialization
  2. discover a printer to print the label on
  3. load label layout
  4. set label data
  5. perform actual printing
  6. Monitor printing progress

Note: these tasks might be performed in a different order, e.g. printer discovery might be performed after the label is prepared for the printing. Though usually printer discovery should be performed first, because it can take some time.

Framework Initialization

All SDK classes and interfaces are accessed from a top label Framework object. A constructor of Framework class accept Context as a parameter. The context might be either an activity/service or be the application context. The Framework instance can be created inside activity’s onCreate()  handler. Note, that Framework initialization might take some time; so if the activity ca be frequently recreated or if the Framework should be accessed from different activities, it make sense to use some sort of singleton to make sure only one instance of the Framework exists.

import android.content.Context;
import com.dymo.label.framework.Framework;

class PrintLabelManager
{
    static private PrintLabelManager instance_;

    static PrintLabelManager instance(Context context)
    {
        if (instance_ == null)
            instance_ = new PrintLabelManager(context);

        return instance_;
    }

    private Framework framework_;

    private PrintLabelManager(Context context)
    {
        framework_ = new Framework(context.getApplicationContext());
    }

    Framework getFramework()
    {
        return framework_;
    }
}
import com.dymo.label.framework.Framework;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity
{
    private Framework framework_; 

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        setupFramework();
    }

    private void setupFramework()
    {
        framework_ = PrintLabelManager.instance(this).getFramework();
    }
}

 

Discover Printers

Before something can be printed it is necessary to know on which printer it will be printed. Printer discovery is an asynchronous operation. The reason is that it requires network communications and various delays and timeouts might happen during the process. To handle async notifications of the discovering progress a PrintersListener object should be assigned to the Framework object. PrintersListener defines two methods, one called when a new printer or printers are discovered, another when some sort of failure happened. To assign the listener use setPrintersListeners() method. To start discovering call startRefreshPrinters() method. This method is asynchronous and returns almost immediately. When a printer is found the listener’s method newPrintersFound() will be called. The list of available printers can be obtained by the Framework.getPrinters() or by  NewPrintersFoundEvent.getPrinters() methods. If the Proxy service could not be contacted during the discovering, e.g. it went offline, the printerLookupFailure() method will be called. Here is a code snippet to demonstrate that:

public class MainActivity extends Activity
{
    private void setupFramework()
    {
        framework_ = PrintLabelManager.instance(this).getFramework();
        framework_.setPrintersListener(new PrintersListener()
        {
            @Override
            public void printerLookupFailure(PrinterLookupFailureEvent event)
            {
                final String message = String.format("Unable to contact '%s' (%s)", event.getPrinterUri(),
                    event.getLocation());
                Log.e("Print Label", message);

                MainActivity.this.runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
                    }
                });
            }

            @Override
            public void newPrintersFound(final NewPrintersFoundEvent event)
            {
                runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        // output all discovered printers to the log
                        Iterable<Printer> printers = event.getPrinters();
                        for (Printer p : printers)
                            Log.i("Print Label", p.getName());
                    }
                });
            }
        });
    }
}

Please note, the listener’s methods are called from a non-UI thread. So, if you need to perform any UI related operations that must be called from the UI thread, don’t forget to use Activity.runOnUiThread() or View.postDelayed() methods.

Unlike iOS API there is no way to automatically determine when printer discovering should be stopped. It is important to stop it manually by calling stopRefreshPrinters()method. If stopRefreshPrinters() is not called this may lead to an extensive battery drain (underneath implementation uses Bonjour, that uses multicast network requests, and the requests use a lot of power). Call stopRefreshPrinters() after a timeout and when the activity is been stopped.

    // refreshes printers and update currently selected one
    private void refreshPrinters()
    {

        framework_.startRefreshPrinters();

        // / stop refreshing in 5 seconds
        labelContentEditText_.postDelayed(new CheckedRunnable()
        {
            @Override
            public void run2()
            {
                Log.i("PrintLabel", "----------- Stopping printers lookup after 5 seconds");
                framework_.stopRefreshPrinters();

                // usually this is called from newPrintersFound() handler
                // newPrintersFound will not be called if all printers are gone 
                updateCurrentPrinter(framework_.getPrinters());
            }
        }, 5000);
    }

 

Load Label Layout

A label layout specifies what will printed on a label. The layout contains ‘label objects’ – text, address, barcode, image, etc. Each object has a ‘reference name’, so the object can be referenced programmatically from the SDK. Usually DYMO Label software is used to create a layout and save it as xml file. Because the layout is serialized as a xml document, the layout can be created or modified using any xml editor or even programmatically. This and that blog posts describe label format in great details. To load label layout use one of Framework.openLabel() methods. Usually we will load the layout from an asset. Something like this:

    Label label = framework_.openLabel(this, "Address.label");

This assumes, that the Android project  has “Address.label” file in the assets folder.

image

Set Label Data

Label Layout can already contain data to be printed, e.g. an address. this might be a case when a label is generated dynamically on the server. But usually we will need to set data programmatically based on user’s input. This can be done using two different methods.

The first method allows printing of one label only. Use Label.setObjectText(String objectName, String objectText) method to set text data of Address, Text, Barcode, and CircularText objects. Use setObjectImage(String objectName, Bitmap image) to set image data for Image objects.

The second method is more universal, and it allows printing multiple labels at once. It is implemented using a “label set” concept. Label set is similar to a recordset, a database table. Label set consist of a set of “label records”. Each label record represents data to be printed on one label. Label record itself is conceptually is a dictionary (associative array), where dictionary keys are label object names, and dictionary values are label object data. To manipulate a label set use LabelSet interface. Use addRecord method to add a record into a label set. To set object data in the record, use LabelSetRecord methods. There are methods to add text and image data similar to ones above. Also, there is way to specify formatted/styled text data where each character or line can have different formatting (font size and style). To create a LabelSet use Framework.createLabelSet() method.

public class MainActivity extends Activity
{
    void printWithLabelSet(Printer printer)
    {
        // open a label
        Label label = framework_.openLabel(this, "Address.label");

        // create a label set
        LabelSet labelSet = framework_.createLabelSet();

        // label #1
        LabelSetRecord record = labelSet.addRecord();
        record.setText("TEXT", "6x7=42");

        //label #2
        record = labelSet.addRecord();
        record.setTextMarkup("TEXT", "font family='Arial' size='36'>6x7=<b>42</b></font>");

        // print label
        label.print(printer, labelSet);
    }
}

Actual Printing

To start printing call Label.print() methods. There are several  overrides, the most generic one is print(Printer printer, PrintParams printParams, LabelSet labelSet)

We have to provide three parameters:

  • printer – printer to print the label on. The printer instance can be obtained from a list of available printers populated during printer discovering process described above. This is the only required parameter, all other can be omitted.
  • printParams – printing parameters, like number of copies, print quality, etc. This parameter can be null, in witch case defaults will be used.
  • labelSet – a label set contains data to be printed. If omitted, the data contained by label instance will be printed.

This method call is asynchronous as well. Right after all necessary data are assembled the method returns. Printing progress monitoring can be done using PrintJob instance returned by the print() method (see below).

Print Progress Monitoring

PrintJob instance returned by the Label.print() call can be used to monitor print progress. Periodically call getStatus() method to retrieve current status information. Note: currently only this “polling” schema is supported; in the future we might add “pushing” data from the printer when it status has changed. getStatus() is an async call as well; when the status data has been retrieved from the printer, the PrintJobListener method statusReceived(PrintJobStatusReceivedEvent event) is called. Here is an example:

public class MainActivity extends Activity
{
    private void printButtonClick()
    {
        try
        {
            //... open label, assemble print data, etc 

            // print with default parameters
            final PrintJob job = label.print(currentPrinter);

            final Runnable getStatus = new CheckedRunnable()
            {
                @Override
                public void run2()
                {
                    job.getStatus();
                }
            };

            // an executor service to ask for the status in the background 
            final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

            // set the listener to be called when the status received
            job.setOnStatusListener(new PrintJobListener()
            {

                @Override
                public void statusReceived(PrintJobStatusReceivedEvent event)
                {
                    try
                    {
                        final PrintJobStatus jobStatus = event.getPrintJobStatus();
                        final JobStatusId statusId = jobStatus.getStatusId();
                        final String statusMessage = jobStatus.getStatusMessage();
                        Log.i("job status", statusMessage);

                        switch (statusId)
                        {
                        case ProcessingError:
                            // bad - unrecoverable printing error, do not ask status again
                            break;

                        case Finished:
                            // done - printing is done, do not ask status again
                            break;

                        default:
                            // OK - printing is in progress, ask the status after one second delay
                            scheduler.schedule(getStatus, 1, TimeUnit.SECONDS);
                            break;
                        }

                    }
                    catch (Exception e)
                    {
                        handleException(e);
                    }
                }
            });

            // schedule first status request in a second
            scheduler.schedule(getStatus, 1, TimeUnit.SECONDS);

        } catch (Exception e)
        {
            handleException(e);
        }
    }
}

Setup an Eclipse Project to Use SDK

Add Jars into a classpath

To use classes from the SDK two jars must be added to a class path (both can be found in the libs folder). The first one is DymoLabelFramework.jar – it contains the SDK classes. The second one is jmdns.jar. It contains Bonjour implementation used for printer discovering. JmDNS is an open source implementation of Bonjour/multicast-DNS for Java. The version bundled with the SDK is JmDNS 3.4.0 and can be downloaded from http://sourceforge.net/projects/jmdns/

Check Android SDK Target Version

The DymoLabelFramework internally uses some classes available only starting from Android SDK API level 8 (Android 2.2, Froyo). Make sure the project targets Android 2.2 or later.

Set Proper Permissions

The SDK requires two permissions to be set in AndroidManifest.xml. The first is android.permission.INTERNET, so the SDK be communicate with the Proxy service. The second is android.permission.CHANGE_WIFI_MULTICAST_STATE that is required to be able to use Bonjour for printer discovering.

Note: samples applications use another one, android.permission.ACCESS_NETWORK_STATE. It is uses to determine Wi-Fi status and ask a user to turn Wi-Fi on if necessary because otherwise no printers can be discovered. It is strictly to be a little bit more user-friendly, and is NOT required.

Setup an Ant Build Script to Use SDK

Use Android SDK tools to generate/update initial build.xml file.

Check Android SDK target version in default.properties file, so target=android-8 (or later).

Specify path where the jars are located in build.properties by using jar.libs.dir  property. E.g. for the sample projects jar.libs.dir=../../libs.

Note: to compile sample projects from the command line you have to specify path to the Android SDK in the local.properties file by using sdk.dir property.

Conclusion

DYMO Label Mobile SDK for Android provides a simple way to add label printing capabilities to any Android app. Along with DYMO Label Web SDK developers can use DYMO printers from their web-based applications or  from native apps.

Apr 222011
 

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:

pic01

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:

  1. Pick one of your contacts (using the Contacts tab).
  2. Create a new URL that enables you to create a new Visualforce page.
  3. 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.

pic02

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:

  1. Create the resource by selecting App Setup > Develop > Static Resource from Salesforce.com.
  2. Provide a name, for example: DymoFramework.
  3. Browse to the folder where the DYMO Label SDK is installed (or where DYMO Framework JavaScript library is downloaded).
  4. 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.

  1. Select Setup > Customize > Contacts > Buttons and Links.
  2. Click the New button in the Custom Buttons and Links section.

A page similar to the following example appears.

pic03

  1. 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.

Apr 032010
 

So you’ve read somewhere that DYMO LabelWriter printers come with a software developer’s kit, commonly referred to as the DLS SDK. But you might be wondering how DLS SDK can help you and how much time you have to spend learning this SDK before you can start using it. Hopefully this blog entry gives you an idea on how easy it is to get started and also help answer some commonly asked questions by developers.

Before we get too far, let me first explain what the DLS SDK is: it is a programming interface designed specifically for label printing. Using the programming interface (API), one can build a label printing application with minimum amount of work.

Create a label printing application

The following section walks you through the steps of creating a label printing application using the DLS SDK. At the end of the section, you should have an understanding of the basic concepts and the working parts of the DLS SDK.

Step 1. Get the tools you need.

  1. The latest DLS 8 Installer (build 996). It’s important to install the latest version.
  2. The latest DLS SDK Samples. The samples installers installs documentation and technical references to the DLS SDK along with samples to give you an idea of the types of application you can create using the SDK.
  3. Visual Studio 2005 or 2008. I will be using VS2008, but what I do there can easily be done in VS2005.
  4. A PC with a LabelWriter printer connected to it and the latest DLS 8 software installed.

Step 2. Understanding the basic concepts in the DLS SDK

  1. Label File: A label file is a document that contains address, text, barcode, and/or images that you want to print on a label. You can perform various operations on a label file, like Open, Print, SaveAs, etc.
  2. Label Objects: The address, text, and barcode data that are stored inside a label file are logically separated into different label objects. Each object has its own set of properties that control how the object is printed on the label, and the DLS SDK provides access to programmatically create label objects and change label object properties.
  3. Data: The data is a general term for data (i.e. text, address, or image) that you would like to print on a label. The data source can be from user input, a file, or a database.

The DLS SDK ties these three concepts together to enable you to start printing labels in your application with a few lines of code.

Step 3. Defining your application.

To keep the blog short, I will define a simple application that lets users type in a list of to-dos for the day, and print out the list on a label to take with them for the day.

Step 4. Designing a label the application will print (download it here).

  1. start DLS 8, select a shipping label, then change the label orientation to portrait
  2. add a date-time label object on the label
  3. add a text object as header on the label
  4. add a text object as the area to list to-do’s on the label
  5. name the to-do’s text object “todos”
  6. save the label

This video shows you the steps to create the above label.

Step 5. Create an SDK application project in VS2008 (download it here). The important things to note are:

  • make sure the project is targeted for x86 platform. The reason is because the current DSL SDK works only in 32-bit mode (i.e. x86), so if your application is targeted for x64 or AnyCPU, you will not be able to use the DLS SDK.
  • Add a reference to the “DLS 7 Compatibility COM Type Library” in the project. Doing so allows you to use the COM objects that are available in the DLS SDK.

This video shows you the steps to setup the above project.

Step 6. Adding code to take in a list of to-do items from the user, then printing it on label (see listing below).

DymoAddinClass and DymoLabelsClass are the two main objects available from the High-Level COM interface in the DLS SDK. Combined, they provide methods and properties for you to open a label file, set data on label objects in the label file, and print the label. Keep in mind that the DLS SDK is much more extensive than just these two objects, and we will take time to explore them in future blog entries.

1 private void printBtn_Click(object sender, EventArgs e)
2 {
3     DymoAddInClass _dymoAddin = new DymoAddInClass();
4     DymoLabelsClass _dymoLabel = new DymoLabelsClass();
5 
6     // open the to-do-list label we created earlier
7     if (_dymoAddin.Open(@"......To-Do's List.label"))
8     {
9         // this call returns a list of objects on the label
10         string[] objNames = _dymoLabel.GetObjectNames(false).Split(new Char [] {'|'});
11 
12         // verify that our text object is on the label
13         if (objNames.Contains("todos"))
14         {
15             // take the to-do's list entered by the user
16             // and put in on the label
17             if (_dymoLabel.SetField("todos", todoEdit.Text))
18             {
19                 // let's print to the first LabelWriter available
20                 // on the pc, if the printer is a TwiTurbo, print
21                 // to the left tray
22                 string[] printers = _dymoAddin.GetDymoPrinters().Split(new char[] { '|' });
23                 if (printers.Count() > 0)
24                 {
25                     if (_dymoAddin.SelectPrinter(printers[0]))
26                     {
27                         if (_dymoAddin.IsTwinTurboPrinter(printers[0]))
28                         {
29                             _dymoAddin.Print2(1, false, 0);
30                         }
31                         else
32                         {
33                             _dymoAddin.Print(1, false);
34                         }
35                     }
36                 }
37             }
38         }
39     }
40 }
41 
(you can download the complete project here).

Done! As you can see, it didn’t take much to create a simple application that prints labels using the DLS SDK