Nov 292011
 

This blog post will demonstrate how it is easy to print a label with a QR-code barcode from any .NET application. Even more, it will show how to do that in two different ways. The sample VS 2008 project is available here.

Prerequisites

First, make sure the latest DYMO Label software is installed. It is always available on DYMO web-site, at the time of writing it is version 8.3.1. Next, in Visual Studio create a new .NET project and add a reference to DYMO.Label.Framework assembly. This will make possible to use DYMO Label Framework API in the project.

Use Barcode Object

The easiest way to print QR-code is to use built-in support for QR-code in DYMO Label Framework. First, design your label using DYMO Label software. Unfortunately, DYMO Label itself does not have ability to specify QR-code barcode type in the UI yet. So, add the Barcode object to the label and put it into desired position. Don’t specify the barcode symbology, use the default Code39. Save the label in to a file, open the file in any XML editor and change the <Type> tag to “QRCode”.

<BarcodeObject>
    <Name>Barcode</Name>
    <ForeColor Alpha="255" Red="0" Green="0" Blue="0" />
    <BackColor Alpha="0" Red="255" Green="255" Blue="255" />
    <LinkedObjectName></LinkedObjectName>
    <Rotation>Rotation0</Rotation>
    <IsMirrored>False</IsMirrored>
    <IsVariable>False</IsVariable>
    <Text></Text>
    <Type>QRCode</Type>
    <Size>Large</Size>
    <TextPosition>None</TextPosition>
    <TextFont Family="Arial" Size="8" Bold="False" Italic="False" Underline="False" Strikeout="False" />
    <CheckSumFont Family="Arial" Size="8" Bold="False" Italic="False" Underline="False" Strikeout="False" />
    <TextEmbedding>None</TextEmbedding>
    <ECLevel>0</ECLevel>
    <HorizontalAlignment>Left</HorizontalAlignment>
    <QuietZonesPadding Left="0" Top="0" Right="0" Bottom="0" />
</BarcodeObject>

See Barcode.label file in the sample project. After the label is ready, the actual steps to print it is quite easy: open the label, set desired data, print. Here is a snippet from the sample:

private void PrintBarcodeButton_Click(object sender, RoutedEventArgs e)
{
    // load label template
    var label = DYMO.Label.Framework.Label.Open(
        Application.GetResourceStream(
            new Uri("Barcode.label", UriKind.Relative)).Stream);

    // set barcode data
    label.SetObjectText("Barcode", "http://developers.dymo.com");

    // print
    label.Print(PrintersComboBox.Text);
}

First, label is loaded from a file, stored as a resource in the application assembly. Next, the barcode data is set to be the blog’s URL. And finally, the label is printed on the printer selected in the UI.

Use Image Object

Printing QR-code by using Barcode object is easy. The only drawback, it is hard to control the actual barcode size. <Size> tag can be used for that but it support only three predefined sizes Small/Medium/Large, but still the overall size will depend on the actual barcode data. The longer the data string, the larger is the barcode. So, the idea is to use some library to generate QR-code image of desired size, and then print it using the Image object. As before, design a label using DYMO Label software. Put an Image object on the label where the barcode should be printed. Set the Image’s Scale Mode to None to avoid image scaling and possible problems with the scanning/reading of the printed barcode. See BarcodeAsImage.label from the sample project. Then use selected library to generate the QR-code image. When specifying the barcode image size in pixels calculate it based on the printer resolution, that is 300 dpi for LabelWriter printers and 180 dpi for Tape printers. For example, if you want the barcode to be 1” in size, specify the barcode image size as 300×300 pixels. Actuals API calls are very similar to the first case.

private void PrintBarcodeAsImageButton_Click(object sender, RoutedEventArgs e)
{
    // load label template
    var label = DYMO.Label.Framework.Label.Open(
        Application.GetResourceStream(
            new Uri("BarcodeAsImage.label", UriKind.Relative)).Stream);

    // set data as a barcode image
    var imageStream = Application.GetResourceStream(
            new Uri("qr.png", UriKind.Relative)).Stream;

    label.SetImagePngData("Image", imageStream);

    // print
    label.Print(PrintersComboBox.Text);
}

First, label is loaded from a file, stored as a resource in the application assembly. Next, the barcode image is “generated”; for the simplicity, already created png file is used instead of library calls. Next, the image data is assigned to the Image object. And finally, the label is printed on the printer selected in the UI.

Conclusion

It is quite simple to print QR-code barcode even if built-in support is somewhat limited. The next post will show how to do the same thing by using DYMO Label JavaScript library.

Apr 052011
 

We are proud to announce a BETA release of the DYMO Label Web SDK. The DYMO Label Web SDK contains enhancements to DYMO Label software and the DYMO Label Framework JavaScript library to allow printing from a web browser running on any modern computing platform. This includes any desktop browser running on Windows, Mac, or Linux; mobile browsers on iPhone, iPod, iPad, Android, BlackBerry and even on Kindle :)

Please Note

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

Architecture Overview

Before going into details let first look at the high level architecture for the Web SDK to understand how it works.

For the current SDK the architecture looks like this:

SDK1

So, only PC and Mac are supported. DYMO Label software has to be installed on each machine that uses the JavaScript library.

The architecture for the Web SDK is like this:

SDK2

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 a web browser and the printer. Nothing should be installed on any other computing device that accesses the printer. That is the biggest difference from the current SDK where DYMO Label software must be installed on any client computer that needs label printing functionality.

Notes:

  • right now DYMO Label Proxy is available for Windows only. So, a printer should be connected to a Windows machine, or be available from Windows machine 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 RAW TCP/IP port. This might be used to simplify installation (see below).
  • a local network is used for communications between the proxy service and a 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.
  • browsers that use an internal “proxy” servers to fetch internet content, e.g. Opera Mini, are not supported. The reason? It is impossible to contact “local network” servers like DYMO Label Proxy from such browsers.

Usage Scenarios

The first scenario is printing from a computing device that DYMO Label cannot be installed on. This includes a mobile device like an iPad or Android as well as a desktop PC running e.g. Linux.

The second scenario is to simplify installation on Windows. Before now DYMO Label has to be installed on a PC you wanted to print from. Not any more :) Let say you want to be able to print to a “shared” printer connected to a different machine. E.g. the printer can be connected to a “server” or someone’s workstation in a common location, like a "front desk". In this case DYMO Label has to be installed only on the "server" and nothing should be installed on your local PC, even drivers.

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

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

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 standard “Services” panel of the  “Computer Management" tool can be used.

Service URIs

To be able to access the service, the service’s URI should be known on the mobile device. From a programmatic side it is done by calling a framework function addPrinterUri(); we will look at addPrinterUri() later when analyzing a sample application. But what URI to use? Well, it depends on various of factors, like network configuration, a mobile device type, etc.

Bonjour Name

If your device supports Bonjour protocol, i.e. it is a iPhone or iPad, then most likely you can use the first URI in the list, that has a form http://.local:. Here “.local” represents a default Bonjour domain. Even if Bonjour is supported on the mobile device there might be problem if your mobile device and the service are connected to different subnets, e.g. the mobile device is connected to a “wireless” subnet and the service to a “wired” subnet. It is not a problem with the DYMO service, it is how Bonjour works in default configuration. There are solutions for this problem, but the details descriptions are beyond the scope of this post. Some ideas:

DNS Name

If you have a DNS server running on your network, e.g. the PC running the service is in a domain, then most likely you can use a second URI contains just a PC name, like http://.

IP Address

As the last resort you can specify an ip-address. The configuration utility tries to apply some intelligence here and filters ip-addresses. It will show ip-address for active network interfaces only. It will filter VMWare interfaces as well. So, the URI in this case is like http://:

Changes in DYMO Label Framework JavaScript Library

The goal was to modify API in a such way, so existing web applications that use the library should not require major changes. In many cases the only change that needs to be done to an application is to call dymo.label.framework.addPrinterUri() function to “register” the proxy service’s URI, so the framework knows how to communicate with the printer. Below is a short list of changes.

Checking for the Framework Installation

Previously dymo.label.framework.checkEnvironment() function could be used for checking if the library can be used or not. E.g. it checked if the browser is one of the  supported browsers, is DYMO Label software installed or not, etc. Now, because any browser can be used and DYMO Label software is not required to be installed this function is kind of obsolete. It is still a part of the library but it will return a correct result only if running on Windows or Mac assuming you are going to use a Framework dependent parts of the library (see below).

Framework Dependent Functions

Some functions depend on a browser plugin and DYMO Label software being installed to operate. These functions access a local file system to load a label or an image file. If these functions are called when running on a mobile device  an exception will be thrown. It is a good idea to call checkEnviromnent() first to make sure the functions can be called. The functions are dymo.label.framework.openLabelFile() and dymo.label.framework.loadImageAsPngBase64().

Printer Registration

To be able to communicate with the printer , the library needs to know the DYMO Label Proxy service URI. To “register” a printer with the library, use dymo.label.framework.addPrinterUri() function. To “deregester” a printer use dymo.label.framework.removePrinterUri() function. Multiple printers/proxy services can be registered. To register a different service just call addPrinterUri() with a different URI. To deregister all printers use dymo.label.framework.removeAllPrinterUri() function.

Printing Status Checking

When printing from a desktop it might be not necessary to know the print status because the status can be easily accessed from the spooler UI. When printing from a mobile device it is not so easy. So, we added some functions for monitoring print job progress. dymo.label.framework.printLabel2() and label.print2() can be used to create a print job. An object representing a print job is returned by these calls and can be used to monitor  the job progress by calling printJob.getStatus(). There is an utility function to combine both operations into one. It is dymo.label.framework.printLabelAndPollStatus() (and the correspondent label.printAndPollStatus()). Status checking function can be called for any printer, even if the application is running on Windows and  printer is locally connected printer. Status checking for a printer locally connected to a Mac is not implemented in this BETA release.

Sample

Now the fun part Smile Let see how it works in practice. The sample is http://labelwriter.com/software/dls/sdk/samples/js/PrintMeThatLabel/pl.html. When manually typing the url, make sure to use it as-is, because it is case-sensitive. The JavaScript code for the sample is http://labelwriter.com/software/dls/sdk/samples/js/PrintMeThatLabel/PrintMeThatLabel.js

Adding Printer URI

The first thing that has to be done is to add/register printer URI. Type one of the URIs displayed in the configuration utility into the “Printer location(url) field. Make sure to use the full URI, including the protocol scheme. Then click the “Add” button. A list of printers installed on the proxy’s machine should be displayed in the printers drop down list. The click event handler for the “Add” button is as following:

addPrinterUriButton.onclick = function()
{
    try
    {
        var printerUri = printerUriTextBox.value;
        if (!printerUri)
            throw new Error("Specify printer Url");

        dymo.label.framework.addPrinterUri(printerUri, '',
            function()
            {
                settings.printerUris.push(printerUri);
                saveSettings();
                updatePrinters();
            },
            function()
            {
                alert('Unable to connect to "' + printerUri + '"');
            }
        );

    }
    catch(e)
    {
        alert(e.message || e);
    }
}


It checks that something is entered into printer URI field and then calls dymo.label.framework.addPrinterUri() function that does the main job. The signature for addPrinterUri() is

/**
    @param {string} printerUri
    @param {string=} opt_location
    @param {Function=} opt_successCallback
    @param {Function=} opt_errorCallback

    @return {undefined}
*/
dymo.label.framework.addPrinterUri = function(printerUri, opt_location, opt_successCallback, opt_errorCallback)

addPrinterUri() accepts four parameters:

  • printerUri – string URI of the proxy service. It is a required parameter
  • opt_location – optional string representing the printer location. A value passed in this parameter will be used as a part of printer name. If nothing is passed, then the host part of the URI will be used as the location.
  • opt_successCallback – optional callback function called when the service has returned information about available printers. One parameter is passed to the callback – the printerUri of the service.
  • opt_errorCallback – optional callback called when the service cannot be contacted, e.g. the service is down, or the printerURI is invalid. One parameter is passed to the callback – the printerUri of the service.

When addPrinterUri() is called it remembers the printerUri in an internal structures and tries to make a request to the proxy service to obtain information about available printers – model name, printer name, printer type, etc. This request is made asynchronously, so addPrinterUri() returns almost immediately, and callbacks, if provided, are called later when the request is completed. You know, the usual Ajax stuff Smile

For the sample, the printerUri parameter is taken from the printer url field. The opt_location is an empty string, so the host part of the uri will be used as a location. opt_errorCallback displays a simple message box telling the user about connection problem. opt_successCallback remembers the uri, so next time you opens the sample there is no need to reenter the uri (see below for more discussion). After that a printers drop down list is updated by updatePrinters().

function updatePrinters()
{
    // clear first
    removeChildren(printersComboBox);

    printers = dymo.label.framework.getPrinters();

    for (var i = 0; i < printers.length; i++)
    {
        var printerName = printers[i].name;

        // add combo box item
        var option = document.createElement('option');
        option.value = printerName;
        option.appendChild(document.createTextNode(printerName));
        printersComboBox.appendChild(option);

        // select current printer
        if (printerName == settings.currentPrinterName)
            printersComboBox.selectedIndex = i;
    }

    // hide 'add printer url' controls if there are printers to use
    printerSettingsDiv.style.display= printers.length == 0 ? 'block' : 'none';
};


The main item here is a call to dymo.label.framework.getPrinters(). getPrinters() is a synchronous call that uses “cached” printer information returned by the proxy service. Because it is called from a opt_successCallback we are sure that information is really available. It would be a mistake to call  dymo.label.framework.getPrinters() right after dymo.label.framework.addPrinterUri() like this

// Don't do that, will not work
dymo.label.framework.addPrinterUri('http://myservice:8631');
var printers = dymo.label.framework.getPrinters();
// process printers...

In this case the ‘printers’ variable most likely will contain an empty array (or array with local printers only).

Multiple proxy services can be added/registers at the same time. Just type a new service uri and click “Add” button.

To remove/unregester all proxy services, click on “Clear” button

clearPrinterUriButton.onclick = function()
{
    dymo.label.framework.removeAllPrinterUri();
    settings.printerUris = [];
    saveSettings();
    updatePrinters();
}

dymo.label.framework.removeAllPrinterUri() does the main job and the rest updates the UI.

If you want to unregister one proxy service you can call dymo.label.framework.removePrinterUri() with the service uri as a parameter.

/**
    @param {string} printerUri 
    @return {undefined}
*/
dymo.label.framework.removePrinterUri = function(printerUri)

Settings

An utility Settings class is used to store proxy Uris and the last used printer between sessions. In this sample, cookies are used as a persistent storage. In a real application other more reliable mechanisms should be used instead.

// app settings stored between sessions
var Settings = function()
{
    this.currentPrinterName = "";
    this.printerUris = [];
}

// loads settings
Settings.prototype.load = function()
{
    var currentPrinterName = Cookie.get('currentPrinterName');
    var printerUris = Cookie.get('printerUris');

    if (currentPrinterName)
        this.currentPrinterName = currentPrinterName;

    if (printerUris)
        this.printerUris = printerUris.split('|');
}

Settings.prototype.save = function()
{
    Cookie.set('currentPrinterName', this.currentPrinterName, 24*365);
    Cookie.set('printerUris', this.printerUris.join('|'), 24*365);
}

Loading Labels

DYMO Web SDK supports printing on both die-cut labels and tape labels. Label files for these two labels type are similar but different. So, the sample needs two label files for printing depending upon what printer is selected.

// load labels from the server
function loadLabels()
{
    $.get("Address.label", function(labelXml)
    {
        addressLabel = dymo.label.framework.openLabelXml(labelXml);
    }, "text");

    $.get("12mm.label", function(labelXml)
    {
        tapeLabel = dymo.label.framework.openLabelXml(labelXml);
    }, "text");
}

Labels are fetched from files “Address.label” and “12mm.label”. This  files are located on the server in the same folder as other files for the sample. The files are loaded using jQuery’s get() method. After label files are loaded, they are “opened” by using  dymo.label.framework.openLabelXml() function; the resulting “label” objects are stored in addressLabel variable and tapeLabel variable.

Printing and Status Checking

Type some data into the label text box and click “Print” button. The following is the function that does printing. It is a little bit long, but we will look at it part by part.

printButton.onclick = function()
{
    try
    {
        printButton.disabled = true;

        settings.currentPrinterName = printersComboBox.value;

        var text = document.getElementById('labelTextArea').value;

        var printer = printers[settings.currentPrinterName];
        if (!printer)
            throw new Error("Select printer");

        // determine what label to print based on printer type
        var label = null;
        var objName = "";
        if (printer.printerType == "LabelWriterPrinter")
        {
            label = addressLabel;
            objName = "Address";
        }
        else
        {
            label = tapeLabel;
            objName = "Text";
        }

        if (!label)
            throw new Error("Label is not loaded. Wait until is loaded or reload the page");

        // set data
        var labelSet = new dymo.label.framework.LabelSetBuilder();
        labelSet.addRecord().setText(objName, text);

        // print and get status
        var printJob = label.printAndPollStatus(printer.name, null, labelSet.toString(), function(printJob,
        printJobStatus)
        {
            // output status
            var statusStr = 'Job Status: ' + printJobStatus.statusMessage;

            var result = (printJobStatus.status != dymo.label.framework.PrintJobStatus.ProcessingError
                && printJobStatus.status != dymo.label.framework.PrintJobStatus.Finished);

            // reenable when the job is done (either success or fail)
            printButton.disabled = result;

            setTextContent(jobStatusMessageSpan, statusStr);

            return result;

        }, 1000);

        saveSettings();
    }
    catch(e)
    {
        printButton.disabled = false;
        alert(e.message || e);
    }
}

First, the Print button is disabled during printing, just to make things easier. The printer name and text to print is taken from UI elements and saved in printer and text variables correspondingly. If no printer is selected, e.g. no proxy uri has been added, a error saying “Select printer” is displayed.

Depending on the selected printer type a label to print is selected. Also a label object to put data into is selected.

// determine what label to print based on printer type
var label = null;
var objName = "";
if (printer.printerType == "LabelWriterPrinter")
{
    label = addressLabel;
    objName = "Address";
}
else
{
    label = tapeLabel;
    objName = "Text";
}


Then data to be printed is put into a label set object. Usually label sets are used to print multiple labels, but it is perfectly fine to use them to print a single label as well.  In this case the same objects are used regardless of number of labels printed, so the code is easier to adjust.

// set data
var labelSet = new dymo.label.framework.LabelSetBuilder();
labelSet.addRecord().setText(objName, text);


And finally the actual printing

// print and get status
var printJob = label.printAndPollStatus(printer.name, null, labelSet.toString(), function(printJob, printJobStatus)
{
    // output status
    var statusStr = 'Job Status: ' + printJobStatus.statusMessage;

    var result = (printJobStatus.status != dymo.label.framework.PrintJobStatus.ProcessingError
        && printJobStatus.status != dymo.label.framework.PrintJobStatus.Finished);

    // reenable when the job is done (either success or fail)
    printButton.disabled = result;

    setTextContent(jobStatusMessageSpan, statusStr);

    return result;

}, 1000);


The  job is done by the printAndPollStatus() method. This method sends a label and label data to be printed to the selected proxy service, and then periodically checks for the print job status. When a status is available a callback is called with new status information, so the application code can update the UI. printAndPollstatus() has following signature:

/** Prints a label and runs status checking in a loop

    @param {string} printerName
    @param {string} printParamsXml
    @param {string} labelSetXml 
    @param {function(PrintJob, PrintJobStatusInfo): boolean} statusCallback
    @param {number} pollInterval 
    @return {PrintJob}
*/
printAndPollStatus = function(printerName, printParamsXml, labelSetXml, statusCallback, pollInterval)

‘printerName’ is the name of the printer to print on. Usually obtained by calling dymo.label.framework.getPrinters(). printParamsXml – printing parameters, in our case we pass null, so default parameters are used. ‘labelSetXml’ – label data to print. ‘pollInterval’ – interval in milliseconds to ask the proxy service for the job status information. In our case we use an one second interval. ‘statusCallback’ – status callback function called when the service returned status information. the callback takes two parameters; the first is PrintJob object. It can be used to get the status information on demand, without using polling. Also, it might be extended in the future to provide more control over the print job, e.g. an ability to cancel it. The second parameter to the callback is PrintJobStatusInfo class. PrintJobStatusInfo has two properties: statusMessage that contains a status message string; and status that contains status code. The callback has to return a boolean value. If true is returned, than pritnAndPollStatus() will poll the serivce again after the pollInterval passed. If false is returned, then printAndPollStatus() finishes processing. printandPollstatus() returns PrintJob object for the created print job. It has a little of use right now, but may be useful in the future if PrintJob is extended to support more operations.

So, in our sample the callback does the following:

  • a string representing the printing status is assembled by using ‘Job status:’ prefix followed by real status string obtained from statusMessage property.
  • determine if we should continue polling the service for the status or not. We stop polling the service when the status is either dymo.label.framework.PrintJobStatus.ProcessingError, that means something really bad happened and print job has not been even created (e.g. the label has an invalid format, or Windows spooler is not running , or DYMO Label is not installed correctly); or the status is dymo.label.framework.PrintJobStatus.Finished, that means the print job is completed.
  • If no more polling is going to be done, then the “Print” button is enabled again, so another label can be printed
  • and finally the UI is updated to display the status string

The library provides different functions to do printing and status checking. For printing use print2() method of Label object. It has the same parameters as the print() method and returns a PrintJob object. The PrintJob object then can be used to get the status by calling getStatus() method, which has following signature:

/** 
    Gets a status of the print job
    @param {function(PrintJobStatusInfo)} replyCallback a function called when the status is available
    @return {undefined}
*/
getStatus = function(replyCallback)

In addition to Label class methods, similar functions are defined in dymo.label.framework namespace.

One similar to label.print2()

/** Prints a label and returns a print job object

    @param {string} printerName the printer to print on. A list of printers can be obtained by getPrinters()
    @param {string} printParamsXml printing parameters, like number of copies, print quality, etc. See PrintParams.xsd
    @param {string} labelXml label to print
    @param {string} labelSetXml 
        LabelSet to print. LabelSet is used to print multiple labels with same layout but different data, e.g. multiple 
        addresses. 
        Use LabelSetBuilder to create a LabelSet or construct xml manualy according to LabelSet.xsd
    @return {dymo.label.framework.PrintJob} print job
*/
dymo.label.framework.printLabel2 = function(printerName, printParamsXml, labelXml, labelSetXml)


Another, similar to label.printAndPollStatus()

/** Prints a label and runs status checking in a loop

    @param {string} printerName the printer to print on. A list of printers can be obtained by getPrinters()
    @param {string} printParamsXml printing parameters, like number of copies, print quality, etc. See PrintParams.xsd
    @param {string} labelXml label to print
    @param {string} labelSetXml 
        LabelSet to print. LabelSet is used to print multiple labels with same layout but different data, e.g. multiple 
        addresses. 
        Use LabelSetBuilder to create a LabelSet or construct xml manualy according to LabelSet.xsd
    @param {function(PrintJob, PrintJobStatusInfo): boolean} statusCallback
        Function to be called when a print job status is available.
        To continue polling the status the function should return true, false otherwise 
    @param {number} pollInterval poll interval in milliseconds
    @return {dymo.label.framework.PrintJob}
*/
dymo.label.framework.printLabelAndPollStatus = function(printerName, printParamsXml, labelXml, labelSetXml,
statusCallback, pollInterval)

Conclusion

We are really exited about the Web SDK and hope you can find it useful. Any thoughts, feedback, critics are welcome Smile

Jun 022010
 

This blog post will show how easy is to add label printing capabilities to your web application. This is possible because of the JavaScript library that is a part of new DYMO Label Framework.

Prerequisites

To be able to use the library DYMO Label software should be installed on the client machines. On Windows version 8.3 or later is required.  Version 8.3.1.1332 is available on http://download.dymo.com/download/Win/DLS8Setup.8.3.1.1332.exe On Mac version 8.2.2.1173 or later is required. Version 8.2.2.1173 is available on http://www.labelwriter.com/software/dls/mac/DLS8Setup.8.2.2.1173.dmg

The Sample

The complete sample is available on http://www.labelwriter.com/software/dls/sdk/samples/js/PrintLabel/PrintLabel.html

The code in the sample is in http://www.labelwriter.com/software/dls/sdk/samples/js/PrintLabel/PrintLabel.js

The sample is minimalistic. It just contains a text area element to specify a text to be printed on a label and a button that triggers printing.

DYMOLabelFramework.js

The first thing should be done for any web project that uses the Framework is to include the library’s code, so it is available for scripts on the page. It is done like this:

<script src="http://labelwriter.com/software/dls/sdk/js/DYMO.Label.Framework.latest.js"
        type="text/javascript" charset="UTF-8"> </script>

This will include the latest version of the library. The only other hosted version for now is http://labelwriter.com/software/dls/sdk/js/DYMO.Label.Framework.1.0.beta.js

In the future other versions will be available as well. It is OK to host the file on your own web-server.

Print a Label

All printing code is in the printButton.onclick event handler assigned in PrintLabel.js. The print task contains three major steps: specifying label layout to print, setting data to print, selecting printer to print on, and actual printing.

Specify Label Layout to Print

Before a label can be printed we should specify what is the label, what objects it contains, what are their positions, etc. It is done by “opening” a label. The easiest way is to put the xml string describing the label right into openLabelXml() function. The easiest way to obtain the xml is to design the label using DYMO Label software, saving it into a file, then pasting file content into the js code.

var labelXml = '
 <DieCutLabel Version="8.0" Units="twips">
 <PaperOrientation>Landscape</PaperOrientation>
 <Id>Address</Id>
 <PaperName>30252 Address</PaperName>
 <DrawCommands/>
 <ObjectInfo>
 <TextObject>
 <Name>Text</Name>
 <ForeColor Alpha="255" Red="0" Green="0" Blue="0" />
 <BackColor Alpha="0" Red="255" Green="255" Blue="255" />
 <LinkedObjectName></LinkedObjectName>
 <Rotation>Rotation0</Rotation>
 <IsMirrored>False</IsMirrored>
 <IsVariable>True</IsVariable>
 <HorizontalAlignment>Left</HorizontalAlignment>
 <VerticalAlignment>Middle</VerticalAlignment>
 <TextFitMode>ShrinkToFit</TextFitMode>
 <UseFullFontHeight>True</UseFullFontHeight>
 <Verticalized>False</Verticalized>
 <StyledText/>
 </TextObject>
 <Bounds X="332" Y="150" Width="4455" Height="1260" />
 </ObjectInfo>
 </DieCutLabel>';
var label = dymo.label.framework.openLabelXml(labelXml);

In a real web application you would probably load the label definition xml from the server using some AJAX library instead of specifying it directly in a js file.

Setting Data to Print

The next step is to specify data to print on the label. This is easy:

label.setObjectText("Text", textTextArea.value);

The code sets the content for the object named “Text” to whatever is typed in the text area field on the page. Note: the library supports setting formatted/styled text as well. This ability will be reviewed in a different blog post.

Selecting the Printer to Print on

The printer should be selected from a list of installed printers. For this sample we choose the first LabelWriter printer:

var printers = dymo.label.framework.getPrinters();
if (printers.length == 0)
    throw "No DYMO printers are installed. Install DYMO printers.";

var printerName = "";
for (var i = 0; i < printers.length; ++i)
{
    var printer = printers[i];
    if (printer.printerType == "LabelWriterPrinter")
    {
        printerName = printer.name;
        break;
    }
}

Actual Printing

If the printer name is known the printing is simple:

label.print(printerName);

Conclusion

As you can see, label printing is not hard if DYMO Label Framework is being used. The Framework has a lot of other useful features, like multiple label printing, specifying image data for a label, specifying text styles, etc. These features will be reviewed in later posts.

Jun 022010
 

DYMO has just released a beta version of DYMO Label Framework – a new set of APIs to work with DYMO LabelWriter and LabelMANAGER printers. In this post we will briefly look at different parts of the Framework.

Installation

All needed libraries and binaries are installed by DYMO Label v.8 installer. On Windows you will need to install version 8.2.3.1026 or later available on http://download.dymo.com/download/Win/DLS8Setup.8.3.1.1332.exe http://www.labelwriter.com/software/dls/win/DLS8Setup.8.2.3.1026-BETA.exe. Note: THIS IS A BETA VERSION for developers only. Please don’t install it on customer’s machines.  On Mac DYMO Label version 8.2.2.1173 or later should be installed. It is available on http://www.labelwriter.com/software/dls/mac/DLS8Setup.8.2.2.1173.dmg. Documentation and samples are installed by DYMO Label SDK installer available on http://www.labelwriter.com/software/dls/win/DYMO_Label_v.8_SDK_Installer.exe.

APIs

The Framework supports the following environments: .NET, COM, and JavaScript. The .NET and COM APIs are similar to high-level and low-level SDK APIs in the current API. JavaScript is a new API to be used from a web-browser.

.NET

The Framework itself is almost completely written in C#, so .NET is “natively” supported. To start using it just reference DYMO.Label.Framework assembly. Below is a simple example shows how to print an address label.

var label = DYMO.Label.Framework.Label.Open(@“c:Address.label”);
label.SetObjectText(“Address”, “DYMOn828 San Pablo AvenAlbany CA 94706”);
label.Print(“DYMO LabelWriter 450 Turbo”);

A compete C# sample is available on DYMO Label Framework/samples/C# Sample subfolder of the SDK installation folder. A VB.NET sample is available on DYMO Label Framework/samples/VB Sample subfolder.

COM

Thanks to .NET-to-COM-interop, Framework can be used from any language/platform that supports COM, e.g. Visual C++, Delphi, or VB6. The API is similar to the .NET one. E.G. the above example in C++ will look like this:

#import “DYMOLabelFramework.tlb”
using namespace DYMO_Label_Framework;
IFrameworkPtr framework (__uuidof(Framework));
ILabelPtr label = framework->OpenLabel(L“c:\Address.label”);
label->SetObjectText(L”Address”, L“DYMOn828 San Pablo AvenAlbany CA 94706”);
IPrintParamsPtr printParams = abelWriterPrintParams(__uuidof(LabelWriterPrintParams));
label->Print(framework->GetPrinterByName(L”DYMO LabelWriter 450 Turbo”), printParams); 

JavaScript

Prior to the the introduction of the Framework API DYMO had limited support for accessing printers from web-browsers. Although major browsers (IE, Firefox, Safari on Mac) were supported, the burden of browsers’ incompatibility was on the developers side. That has changed now. Not only more browsers are supported now (IE, IE 64-bit, Firefox, Chrome, Opera, Safari on Windows, Safari on Mac) but the Framework provides a cross-browser and cross-platform pure JavaScript API. The above samples will look like this (in any supported browser):

$.get(http://myserver.com/Address.label, function(labelXml)
{
    var label = dymo.label.framework.openLabelXml(labelXml);
    label.setObjectText(“Address”, “DYMOn828 San Pablo AvenAlbany CA 94706”);
    label.print(“DYMO LabelWriter 450 Turbo”);
});

Note 1: using of jQuery library ($.get function) is just for this sample only. The Framework JavaScript library itself does not have dependencies on any other libraries.

Conclusion

DYMO Label Framework allows easy label printing in many different environments. The APIs provided by the Framework will be explored in more detail in upcoming posts.