NiceLabel.Blog Everything you wanted to know about NiceLabel

17May/11Off

Formatting numbers and date/time using current locale in NiceForm and NiceLabel Portal

Locale is a set of parameters that defines the user's language, country and any special variant preferences that the user wants to see in their user interface. Usually a locale identifier consists of at least a language identifier and a region identifier.

General settings usually include the following display format settings:

  • Number format setting
  • Character classification, case conversion settings
  • Date/Time format setting
  • String collation setting
  • Currency format setting
  • Paper size setting
  • Other minor settings

The locale settings are about formatting output given a locale. For example you can see some of the settings for the Slovenian locales on my machine in the screenshot below.

Region and Language

Even more options are available if you click the “Additional settings…” button.

Customize Number, Currency, Time and Date Format

To view or modify these changes  in Windows 7 you have to follow these steps:

  1. Click Start > Control Panel.
  2. Double-click the Region and Language icon. The Region and Language dialog box appears.

Please note that you have to be logged in with an account with Administrative Privileges in order for this to work.

Working with Locales in Python Scripts

To work with locales in Python scripts in NiceForm you have to use the locale module. Your script would typically start with something like this:

import locale
locale.setlocale(locale.LC_ALL, '')

This sets the locale for all categories (number format settings, currency format settings, date/time settings, etc.) to the user’s default setting.

You can also set the locale to a specific one. For example to change current locale in your Python script to German, you could use the following code:

locale.setlocale(locale.LC_ALL, 'deu_deu')

or to French

locale.setlocale(locale.LC_ALL, 'fra_fra')

Unfortunately locale module is not supported in IronPython (that is used to implement scripting in NiceLabel Portal) so you have to write a little different code. To obtain information about current locale (or current culture as it is called in Silverlight) you have to use the following code:

import System
culture = System.Threading.Thread.CurrentThread.CurrentCulture


And to set the culture you would do this:

from System.Globalization import *
culture = CultureInfo("de-DE");
System.Threading.Thread.CurrentThread.CurrentCulture = culture

Formatting Numbers Using Current Locale

The following code converts values of two NiceForm (or NiceLabel Portal) variables (that are represented as strings) into floating point numbers using the current locales, calculates the difference between them and assigns this new value to the third variable value (again as a string value).

import sys
if sys.platform == 'silverlight':
    import System
    culture = System.Threading.Thread.CurrentThread.CurrentCulture
    number1 = System.Single.Parse(originalSellingPrice.Value, culture.NumberFormat)
    number2 = System.Single.Parse(sellingPrice.Value, culture.NumberFormat)
    diff = number1 - number2
    subtract_price.Value = diff.ToString("F")
else:
    import locale
    locale.setlocale(locale.LC_ALL, '')
    number1 = locale.atof(originalSellingPrice.Value)
    number2 = locale.atof(sellingPrice.Value)
    diff = number1 - number2
    subtract_price.Value = locale.format("%.2f", diff)


Script should work in both NiceLabel Portal (code block after the if statement) and NiceForm (code block after the else statement).

Formatting Date/Time Using Current Locale

Again code for NiceLabel Portal and NiceForm is a little different. It does however in both cases display date and time in different formats using user’s current locale settings.

import sys
if sys.platform == 'silverlight':
    import System
    dt = System.DateTime.Now
    d1.Value = "Long time: " + dt.ToLongTimeString()
    d2.Value = "Long date: " + dt.ToLongDateString()
    d3.Value = "Short time: " + dt.ToShortTimeString()
    d4.Value = "Short date: " + dt.ToShortDateString()
    d5.Value = "Day of the week: " + dt.ToString("ddd") + " (abbreviated), " + dt.ToString("dddd") + " (full)"
    d6.Value = "Month name: " + dt.ToString("MMM") + " (abbreviated), " + dt.ToString("MMMM") + " (full)"
else:
    from datetime import date
    import time
    import locale
    locale.setlocale(locale.LC_ALL, '')   

    date1 = date.today();
    d1.Value = time.strftime("Long time: %H:%M:%S");
    d2.Value = date1.strftime("Long date: %d.%B %Y");
    d3.Value = time.strftime("Short time: %X");
    d4.Value = date1.strftime("Short date: %x");
    d5.Value = date1.strftime("Day of the week: %a (abbreviated), %A (full)");
    d6.Value = date1.strftime("Month name: %b (abbreviated), %B (full)");

To use a specific locale (French in this case) you would do this:

import sys
if sys.platform == 'silverlight':
    import System
    from System.Globalization import *
    culture = CultureInfo("fr-FR");
    System.Threading.Thread.CurrentThread.CurrentCulture = culture
    dt = System.DateTime.Now
    d1.Value = "Long time: " + dt.ToLongTimeString()
    d2.Value = "Long date: " + dt.ToLongDateString()
    d3.Value = "Short time: " + dt.ToShortTimeString()
    d4.Value = "Short date: " + dt.ToShortDateString()
    d5.Value = "Day of the week: " + dt.ToString("ddd", culture) + " (abbreviated), " + dt.ToString("dddd", culture) + " (full)"
    d6.Value = "Month name: " + dt.ToString("MMM", culture) + " (abbreviated), " + dt.ToString("MMMM", culture) + " (full)"
else:
    from datetime import date
    import time
    import locale
    locale.setlocale(locale.LC_ALL, 'fra_fra')   

    date1 = date.today();
    d1.Value = time.strftime("Long time: %H:%M:%S");
    d2.Value = date1.strftime("Long date: %d.%B %Y");
    d3.Value = time.strftime("Short time: %H:%M");
    d4.Value = date1.strftime("Short date: %d.%b.%Y");
    d5.Value = date1.strftime("Day of the week: %a (abbreviated), %A (full)");
    d6.Value = date1.strftime("Month name: %b (abbreviated), %B (full)");


Related posts:

http://www.primozic.net/nl/manipulating-date-and-time-using-python-in-niceform-and-nicelabel-portal/

http://www.primozic.net/nl/working-with-modules-in-python-scripts-in-niceform-and-nicelabel-portal/

http://www.primozic.net/nl/working-with-strings-in-python-scripts-in-niceform/

http://www.primozic.net/nl/python-scripting-in-niceform-and-nicelabel-portal/

11May/11Off

How can I work with files in NiceLabel Portal?

NiceLabel Portal uses Microsoft Silverlight as its underlying technology. Because Silverlight is a browser-based plug-in, it has by default the lowest security privileges to ensure a safe browsing experience. This restriction introduces a number of challenges, especially when it comes to working with files. For example you do not have direct access to files on your drive from NiceLabel Portal. There is a solution though that might solve most of the problems.

Isolated storage is a great way to store data on the end user’s local computer. It’s flexible in that it works in all modes of Silverlight operation (in-browser, out-of-browser, elevated out-of-browser) and works as a virtual file system. Isolated storage is tied to individual user and lies outside of the browser cache. This means that even if a user clears browser history, files within isolated storage will remain intact.

To work with Isolated Storage in NiceLabel Portal you will have to use Python scripts. Here are scripts for some of the most common scenarios you might encounter when working with Isolated Storage.

Basics of Isolated Storage

The System.IO.IsolatedStorage namespace provides the functionality to work with a user’s isolated storage area. This area can be accessed through the IsolatedStorageFile class, which exposes two methods that retrieve an IsolatedStorageFile. These methods are GetUserStoreForApplication and GetUserStoreForSite. The GetUserStoreForApplication can be used to retrieve a user’s isolated storage for a specific Silverlight application, defined by the full URL to the .xap. The GetUserStoreForSite method gets a user’s isolated storage for the entire domain.

from System.IO.IsolatedStorage import *
store = IsolatedStorageFile.GetUserStoreForApplication()

Once you’ve retrieved an IsolatedStorageFile, you can use it to manage a virtual file system, which gives you the ability to work with files and directories.

Checking if Isolated Storage is enabled

Before using Isolated Storage you should check if it is enabled because user can disable it in the “Microsoft Silverlight Configuration” dialog box under the “Application Storage” page). To configure the Silverlight plug-in (not just the Application Storage) a user can right-click the opened solution in the NiceLabel Portal or simply find Microsoft Silverlight in the Windows Start menu.

image

To programmatically check if Isolated Storage is enabled you can use the following code:

from System.IO.IsolatedStorage import *

isEnabled = IsolatedStorageFile.IsEnabled
if (isEnabled):
    # do something
else:
    # display error message

Checking the Available Space

By default in-browser application gets 1 MB of free space. The IsolatedStorageFile class exposes two read-only properties that inform you of an isolated storage area’s memory situation. The first property, Quota, holds the total number of bytes allocated to the storage area. The other property,  AvailableFreeSpace, represents the number of bytes remaining in the Isolated Storage.

from System.IO.IsolatedStorage import *

store = IsolatedStorageFile.GetUserStoreForApplication()
usedSize.Value = "Used size: " + str(store.UsedSize) + " bytes"
quota.Value = "Quota: " + str(store.Quota) + " bytes"
availableFreeSpace.Value = "Available free space: " + str(store.AvailableFreeSpace) + " bytes"

Requesting more space

To increase the Isolated Storage quota, you must call the IncreaseQuotaTo method from a user-initiated event, such as in an event handler for a button-click event. Unfortunately because of the way action execution is implemented in NiceLabel Portal you will not be able to increase the quota by a Python script even if you have the script defined on the “On click” event of the button object. You will have to write your own application that calls the above mentioned method or contact NiceLabel support for help.

Listing the contents of the virtual file system

The IsolatedStorageFile class provides two methods that enable you to retrieve the items within a storage area. The first method, GetDirectoryNames,  enables you to get the names of the directories that match a certain pattern; the GetFileNames method allows you to search for files that match a particular filter. To perform the search just provide the path to the file or directory. If the directory or file name is found an array with one element will be returned. Otherwise, an empty set will be returned. Wildcard characters can also be used to match file names (the * character matches any number of characters, and the ? character matcher any single character.

from System.IO.IsolatedStorage import *

store = IsolatedStorageFile.GetUserStoreForApplication()
results1 = store.GetFileNames("*.txt");
results2 = store.GetFileNames("Folder/*");
results3 = store.GetFileNames("configfile*"); 

results4 = store.GetDirectoryNames("*");

# convert array of directory names into a string separated by commas
if len(results4) > 0:
    all = ",".join(results)

Creating directories within Isolated Storage

The IsolatedStorageFile class has a method called CreateDirectory that enables you to create a directory within the isolated storage space.

from System.IO.IsolatedStorage import *

store = IsolatedStorageFile.GetUserStoreForApplication()
store.CreateDirectory("Folder1")
store.CreateDirectory("Folder1/Sub/Leaf")

 

The first call to CreateDirectory is pretty simple; it creates a subdirectory under an existing

directory. The second call shows an additional feature. If you provide an absolute path to a subdirectory further down the line, all missing directories along the way will automatically be added. Once a directory exists, you can create files in it.

Checking if an item exists

from System.IO.IsolatedStorage import *

store = IsolatedStorageFile.GetUserStoreForApplication()

msg2.Value = str(store.FileExists(fileName.Value))
if store.FileExists(fileName.Value):
    msg.Value = "File already exists."
else:
    msg.Value = "File does not exist!"

 

Removing items from Isolated Storage

from System.IO.IsolatedStorage import *

store = IsolatedStorageFile.GetUserStoreForApplication()

if store.FileExists(fileName.Value):
    store.DeleteFile(fileName.Value)

if store.DirectoryExists(directoryName.Value):
    store.DeleteDirectory(directoryName.Value)

Possible problems

There are a few problems that you should be aware of when working with Isolated Storage.

  1. Administrators can set disk quota per user and assembly which means there is no guarantee on space available. So it is very important to add exception handling to your code.
  2. Computer can be locked down by administrative security policies preventing applications from writing to the Isolated Storage.
  3. Even though Isolated Storage is placed in a hidden folder it is possible, with a bit of effort, to find the folder. Therefore the data stored is not completely secure as users can change or remove files.

Isolated Storage Best Practices

When you use isolated storage, following these guidelines will help you avoid problems and make the most of the protection isolated storage provides.

  • Wrap all calls to isolated storage within try/catch blocks to be resilient to potential IsolatedStorageExceptions, which can be thrown if isolated storage is disabled or if the store has been deleted.
  • Keep isolated storage paths as small as possible to prevent the internal full path from reaching the 260-character limit.
  • Encrypt sensitive data stored in isolated storage.
  • Use IsolatedStorageSettings to store objects and simple settings in isolated storage.
from System.IO.IsolatedStorage import *

# Write to application settings
settings = IsolatedStorageSettings.ApplicationSettings
settings.Add("FirstName", FirstName.Value)
settings.Add("LastName", LastName.Value)

# Read from application settings
FirstName.Value = settings["FirstName"]
LastName.Value = settings["LastName"]

# Remove just first name from application settings
settings.Remove("FirstName")

# Clear all settings
settings.Clear()

Please note that all code samples in this post will only work in NiceLabel Portal. Even though you will write them in NiceForm you will only be able to test them in NiceLabel Portal.

You can find all the samples in one sample NiceForm file (it is in a .zip file so you will have to uncompress it first).

3May/11Off

How can I fix the “The ‘Microsoft.Jet.OLEDB.4.0′ provider is not registered on the local machine.” error in NiceLabel Portal?

Usually you get this error when you try to use Microsoft Excel file in NiceLabel Portal solution – in a form or in a label file when NiceLabel Portal is installed on a 64-bit operating system. Although I would not suggest using Excel files as a database for anything else but a demo, you can get around this particular problem.

What you have to do is to set “Enable 32-Bit Applications” property of the “EPWebPrintingAppPool” application pool in IIS (Internet Information Services) to “True”.

In IIS 7 you have to open the list of Application Pools, right click the selected application pool and select “Advanced Settings” in the pop up menu.

IIS - List of application pools

When “Advanced Settings” dialog box is shown change the “Enable 32-Bit Applications” property to “True”.

IIS - Advanced settings for application pool

Now all you have to do is reload your solution file in the browser.

13Mar/11Off

Actions in NiceForm and NiceLabel Portal

One of the main strengths of NiceForm and NiceLabel Portal are actions that let you build workflows that accomplish manual chores quickly, efficiently and effortlessly. You don’t have to know any scripting languages or write any code (unless you want to). Instead, you create and execute workflows simply by dragging and dropping actions. Currently there are 29 actions available in NiceForm. They are grouped in 6 groups: Labeling, Variables, Batch Printing, Database, Connectivity and Other.

Labeling actions: “Open label”, “Print label”, “Set printer”, “Send custom commands”, “Run command file”, “Close label”, “Define printer settings”.

Variables actions: “Set variable”, “Save variable data”, “Load variable data”.

Batch printing actions: “For every label”, “For every record in a table”, “For loop”.

Database actions: “Refresh database”, “Execute SQL statement”, “Import data into database”.

Connectivity actions: “Read data from serial port”, “Write data to serial port”, “Send data to TCP/IP port”, “Acquire image”.

Other actions: “Open another form”, “Open document/program”, “Refresh previews”, “Quit”, “Execute script”, “Move focus to object”, “View log file”, “Browse for file or folder”, “Verify license”.

Where can actions be used in the form?

Actions are executed on certain events that happen on the form. Form itself has three events - On Form Load, On Form Close and On Timer – that can be used to execute actions when form is loaded, closed or when a specified time interval elapses. Also almost all objects (with the exception of the Frame object) have one or more events that trigger action execution (check the “Events” page of the object properties dialogs). Usually these are: On Click (when object like Button is clicked), On Focus (when object becomes active), On Exit (when input focus shifts away from the object) or On Change. Even variable can execute actions when its value changes.

NiceForm - Edit field events

Defining actions

You define actions and their properties in the “Actions Editor” dialog box. This dialog is the same in both NiceForm and NiceWatch so everything that works in NiceForm should also work in NiceWatch (there are some differences in the action types supported).

“Actions Editor” has three sections. On the left you can see a list of all available actions grouped together by functionality (or action type) in several groups. To define action workflows you just have to drag and drop the action to the area on the right or select one and click “Insert” button at the top of the window.

There is a small toolbar at the top of the right section.  “Properties” button opens the properties of the currently selected action in the right pane(you get the same effect by double clicking the action). By clicking the “Delete” you will delete the selected action. Click on the arrow buttons to change the order and hierarchy of the actions in the right pane. Some of the actions like “Open label”, “For every label”, “For every record in a table” and “For loop” work on their “sub” actions – actions that are essentially their child actions. See the picture below for some samples.

Actions editor

The two remaining buttons in the top toolbar are the “Copy” and “Paste” buttons. You can copy/paste actions between different parts of NiceForm, between different instances of NiceForm and even between NiceForm and NiceWatch (if action is available in both applications).

At the bottom of the dialog you can find buttons to close the window, open help file and switch between Basic and Advanced views of the window. You can see the “Actions Editor” in the (default) Basic mode below. The difference between them is that the Basic view shows only the basic, most used actions, while the Advance view shows all available actions.

Actions editor - Basic

Protecting your know-how

If you do not want the end-user to modify forms you have created or to see how you implemented a very complicated script, you can lock (protect) the form with a password. In this case all the actions will be encrypted. Of course you have to make sure you do not forget the password because in that case you will have to design the forms from the start.

To lock the form, do the following:

  1. Open your form.
  2. Select the “Form Properties” option in the “File” menu or double click the form to open “Form Properties” dialog box.
  3. Go to the Advanced tab.
  4. Tick the “Form locked” option.
  5. Tick the “Password protection” and click on the “Set password” button.
  6. Provide the password and click on the “OK” button to close the “Set Password” dialog.
  7. Click on the “OK” button to close the “Form Properties” dialog box.
  8. Select the command Save in the File menu.
  9. Close the form.

Actions that are not supported in NiceLabel Portal

Some of the actions are currently not yet supported in NiceLabel Portal. These are: “Close label”, “For every label”, “Move focus”, “Refresh previews”, “Read data from serial port”, “Write data to serial port”, “Acquire image”, “Browse for file or folder”, “Define printer settings” and “Verify license”. “Import data into database” action is available only in NiceLabel Portal. We plan to support all actions that make sense in the browser environment in the future releases.

3Mar/11Off

Manipulating date and time using Python in NiceForm and NiceLabel Portal

Time values are represented with the time class. Times have attributes for hour, minute, second, and microsecond. They can also include time zone information. A time instance only holds values of time, and not a date associated with the time.

from datetime import datetime;

time1 = datetime.time(datetime.now()); # Get current time
h = time1.hour;
m = time1.minute;
s = time1.second;
ms = time1.microsecond;
tz = time1.tzinfo;
min = time1.min;
max = time1.max;

d1.Value = "Hour: " + str(h);
d2.Value = "Minute: " + str(m);
d3.Value = "Second: " + str(s);
d4.Value = "Microsecond: " + str(ms);
d5.Value = "Time zone: " + str(tz);
d6.Value = "Earliest: " + str(min);
d7.Value = "Latest: " + str(max);

Calendar date values are represented with the date class. Instances have attributes for year, month, and day. It is easy to create a date representing current date using the today() class method. As with time, the range of date values supported can be determined using the min and max attributes.

from datetime import date;

date1 = date.today(); # Get current date
year = date1.year;
month = date1.month;
day = date1.day;
ordinal = date1.toordinal();
min = date1.min;
max = date1.max;

d1.Value = "Day: " + str(day);
d2.Value = "Month: " + str(month);
d3.Value = "Year: " + str(year);
d4.Value = "Ordinal: " + str(ordinal);
d5.Value = "Earliest: " + str(min);
d6.Value = "Latest: " + str(max);

How can I add or subtract from a date?

To add or subtract from a date use the datetime.timedelta object.

from datetime import datetime, timedelta, time;

time1 = datetime.now();
diff = timedelta(weeks=52);  # 1 year
time2 = time1 + diff;
diff = timedelta(days=730);  # 2 years
time3 = time1 + diff;
diff = timedelta(hours=240);  # 10 days
time4 = time1 + diff;
diff = timedelta(weeks=40, days=84, hours=23, minutes=50, seconds=600);  # Adds up to 365 days
time5 = time1 - diff;

d1.Value = "Current date and time: " + str(time1);
d2.Value = "Added 52 weeks (1 year): " + str(time2);
d3.Value = "Added 730 days (2 years): " + str(time3);
d4.Value = "Added 10 days: " + str(time4);
d5.Value = "Subtracted 365 days: " + str(time5);

How can I calculate difference of two dates?

When two dates are subtracted they produce timedeltas.

from datetime import date;

date1 = date.today();
date2 = date(1973, 7, 6);
diff = date1 - date2;

d1.Value = "Current date: " + str(date1);
d2.Value = "My birthday: " + str(date2);
d3.Value = "I am : " + str(diff.days) + " days old.";

Can I compare date or time values?

Both time and date values can be compared using standard operators to determine which one is earlier or later.

from datetime import date, time;

date1 = date.today();
date2 = date(1973, 7, 6);
time1 = time(12, 0, 0);
time2 = time(13, 5, 0);

d1.Value = "Date 1: " + str(date1);
d2.Value = "Date 2: " + str(date2);
d3.Value = "Date 1 < Date 2: " + str(date1 < date2);
d4.Value = "Time 1: " + str(time1);
d5.Value = "Time 2: " + str(time2);

d6.Value = "Time 1 > Time 2: " + str(time1 < time2);

How can I replace just part of date?

from datetime import datetime;

date1 = datetime.now();            # Use current date and time
date2 = date1.replace(year=2012);  # Change year to 2012
date3 = date1.replace(month=12);   # Change month to December
date4 = date1.replace(day=31);     # Change day to 31
date5 = date1.replace(day=31, month=12, year=2012); # Change day, month and year all at once.

d1.Value = str(date1);
d2.Value = str(date2);
d3.Value = str(date3);
d4.Value = str(date4);
d5.Value = str(date5);

Formatting time and date

Default string representation of a datetime object uses the ISO 8601 format (YYYY-MM-DDHH:MM:SS.mmmmmm). Other formats can be generated using strftime() method. The following directives can be embedded in the format string:

Directive Meaning
%a Locale’s abbreviated weekday name.
%A Locale’s full weekday name.
%b Locale’s abbreviated month name.
%B Locale’s full month name.
%c Locale’s appropriate date and time representation.
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%I Hour (12-hour clock) as a decimal number [01,12].
%j Day of the year as a decimal number [001,366].
%m Month as a decimal number [01,12].
%M Minute as a decimal number [00,59].
%p Locale’s equivalent of either AM or PM.
%S Second as a decimal number [00,61].
%U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.
%w Weekday as a decimal number [0(Sunday),6].
%W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0.
%x Locale’s appropriate date representation.
%X Locale’s appropriate time representation.
%y Year without century as a decimal number [00,99].
%Y Year with century as a decimal number.
%Z Time zone name (no characters if no time zone exists).
%% A literal '%' character.

Here are some examples of using different directives:

from datetime import date;

format1 = "%A,  %B %d, %Y";
format2 = "Today is day %j of the year.";
format3 = "Short month name: %b; Short weekday name: %a";

date1 = date.today();
d1.Value = date1.strftime(format1);
d2.Value = date1.strftime(format2);
d3.Value = date1.strftime(format3);

How can I get a week number from a date?

from datetime import date;

format = "Today is day %w of the %W week of the year.";

date1 = date.today();
d1.Value = date1.strftime(format);

All code samples above should work in NiceForm and NiceLabel Portal. You can find all samples in sample form file (PyDateTime.xff).

20Jan/11Off

How can I show a message box using Python script in NiceForm or NiceLabel Portal?

import sys

if sys.platform == 'silverlight':
    from System.Windows import *
    result = MessageBox.Show("Would you like to see the simple version?", "MessageBox Example", MessageBoxButton.OKCancel);
    if result == MessageBoxResult.OK:
        MessageBox.Show("No caption, one button.");
else:
    import win32gui
    import win32con
    result = win32gui.MessageBox(0, "Would you like to see the simple version?", "MessageBox Example", win32con.MB_YESNO);
    if result == win32con.IDYES:
        win32gui.MessageBox(0, "No caption, one button.", "", win32con.MB_OK);

There is no single way to display message box both in NiceForm and in NiceLabel Portal. So the previous code snippet shows how you can do it on both platforms.

20Jan/11Off

Working with Modules in Python Scripts in NiceForm and NiceLabel Portal

A module is a Python source file (a text file) whose name ends in .py. Objects (names) defined in a module can be imported and used elsewhere.

The import statement has several different forms:

import module
from module import name1, name2
from module import name as anotherName
from module import *

 

If you use the first form, you receive a reference to the module object. If a module defines a class SomeClass then you can access it using module.SomeClass. If you need access to only a few objects from the module, you can use the second form. It imports only the names you have specified from the module. If a name you wish to import would clash with a name in your current namespace, you can use the third form. The fourth form imports all the names from the module into your namespace. In Python this is something you would not normally do.

Exploring Modules

To find out what a module contains you can use the dir() function, which lists all the attributes of an object and therefore all functions, classes, variables of a module. Several of these names begin with an underscore which means that they are not meant to be used outside the module.

For example:

import math
print dir(math)

 

would return the following:

['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']

Very useful command that can help you while exploring modules, classes, variables and methods is help(). help() is a built-in function that provides information like what method does and what arguments that method takes.

import math
help(math.sin)

 

would return:

sin(...)
    sin(x)

    Return the sine of x (measured in radians).

Finding modules

To import a module, the Python interpreter needs to find it. With a module, the Python interpreter first looks for a file named module.py, where module is the name of the module you pass to the import statement. The Python interpreter looks for modules in the directories that are part of the module search path. These directories are listed in the sys.path variable from the sys module.

import sys
print sys.path

 

There are some differences between NiceForm and NiceLabel Portal here. In NiceForm you would get something like this:

['C:\Windows\system32\python27.zip','C:\Ln\Python27\Lib', 'C:\Ln\Python27\DLLs', 'C:\Ln\Python27\Lib\lib-tk','C:\PROGRA~2\EuroPlus\NICELA~1\bin','C:\Ln\Python27', 'C:\Ln\Python27\lib\site-packages', 'C:\Ln\Python27\lib\site-packages\win32', 'C:\Ln\Python27\lib\site-packages\win32\lib', 'C:\Ln\Python27\lib\site-packages\Pythonwin']

while in NiceLabel Portal sys.path would return just ‘.’. The reason for this is that NiceLabel Portal runs in the web browser and does not have access to the local files and directories. As a consequence in NiceLabel Portal you can use only built-in modules. You have on other hand have access to a rich functionality of .NET Framework Class Library for Silverlight.

17Jan/11Off

Working with Strings in Python Scripts in NiceForm and NiceLabel Portal

Strings are the basic unit of text in Python. Either single or double quotes can be used to quote strings. This can be useful in some cases:

s1 = "Let's go!"
s2 = '"NiceLabel is the best!", she said.'

 

Special characters need to be escaped. Likely the most common special character you will encounter is the newline '\n'. Some of other special characters are:

\\    Backslash (\)
\"    Double quote (")
\'    Single quote (')
\n    ASCII linefeed (LF)
\r    ASCII Carriage Return (CR)
\t    ASCII Horizontal Tab (TAB)

 

In NiceForm version 5.2.3 (that uses Python 2.7) Python string constants are by default ASCII (single byte) strings. Basically this means that they are just a sequence of bytes. If you want to use define Unicode string literal you need to use the ‘u’ or ‘U’ prefix:

s1 = u"čćšđž"
s2 = U"НИГЕЛАБЕЛ"

 

NiceForm variable values are already Unicode enabled so you do not have to do anything. The same goes for scripts running in NiceLabel Portal. Because NiceLabel Portal uses IronPython (that is implemented on .NET Framework) it means that all strings are Unicode strings.

Basic Operations

Strings can be concatenated (glued together) with the + operator, and repeated with *:

s = ""NiceLabel" + " " + "is the best!" # "NiceLabel is the best!"

s2 = "Nice" * 3 # "NiceNiceNice"


To see if two strings are equal use the "==" operator. Other comparison operations are useful for putting words in alphabetical order. You should be aware though that Python does not handle uppercase and lowercase letters the same way people do. All the uppercase letters come before all the lowercase letters.

word = variable.Value
if word == "NiceLabel":
    result.Value = "Your word is NiceLabel."
elif (word < "NiceLabel"):
    result.Value = "Your word comes before NiceLabel."
elif (word > "NiceLabel"):
    result.Value = "Your word comes after NiceLabel."     

 

Sometimes it might be tempting to use the [] operator on the left side of an assignment, with the intention of changing a character in a string. For example:

s = "NiceLabel"
s[0] = 'M'

 

This code will not work because the strings in Python are immutable, which means that you cannot change an existing string. The best you can do is create a new string that is a variation of the original one:

s = "NiceLabel"
s2 = 'M' + s[1:]

 

If you need to count the number of characters in a string use the len() function:

len("NiceForm")  # Returns 8.

 

To convert any data type to string use the str() function:

f = 123.56
result.Value = str(f)

String Slices

A segment of a string is called a slice. Selecting a slice is similar to selecting a character:

s = "NiceLabel, NiceForm and NiceLabel Portal"

print s[0:9]     # NiceLabel
print s[11:19]   # NiceForm
print s[24:41]   # NiceLabel Portal

 

The operator [n:m] returns the part of the string from the "n-eth" character to "m-eth" character, including the first but excluding the last. If you omit the first index (before the colon), the slice starts at the beginning of the string. If you omit the second index, the slice goes to the end of the string.

s[:9]  # NiceLabel
s[24:] # NiceLabel Portal

 

Working with cases

There are several functions that allow you to work with character case.

s = "NiceLabel Portal"

# String converted to lower case.
lowercase = s.lower() # "nicelabel portal" 

# String converted to upper case.
uppercase = s.upper() # "NICELABEL PORTAL" 

# String converted to title case.
titlecase = s.title() # "Nicelabel Portal"

# Make all lowercase letters uppercase and vice versa.
swapcase = s.swapcase() # "nICElABEL pORTAL" 

# The capitalize method is like title except that it considers the
# entire string  to be a word. (i.e. it makes the first character
# upper case and the rest lower case).
capitalcase = s.capitalize() # "Nicelabel portal"

Searching for substrings

The find() method finds a substring within a larger string. It returns the leftmost index where the substring is found. If it is not found, –1 is returned. For searching in strings you can also use startswith(), endswith(), rfind(), count() and replace() methods. See attached files for more details.

 

Stripping

strip(), lstrip() and rstrip() methods can be used to remove characters you do not want in the string:

word = "999aaa999"
stripped = word.strip('9')    # returns "aaa"
lstripped = word.lstrip('9')  # returns "aaa999"
rstripped = word.rstrip('9')  # returns "999aaa"

 

Checking Character Types

To check if a string contains a certain type of characters, use the following methods:

  • isalnum(): Returns true if string has at least 1 character and all characters are alphanumeric and false otherwise. 
  • isalpha(): Returns true if string has at least 1 character and all characters are alphabetic and false otherwise. 
  • isdigit(): Returns true if string contains only digits and false otherwise.
  • islower(): Returns true if string has at least 1 cased character and all cased characters are in lowercase and false otherwise. 
  • isspace(): Returns true if string contains only whitespace characters and false otherwise.
  • istitle(): Returns true if string is properly "title cased" and false otherwise.
  • isupper(): Returns true if string has at least one cased character and all cased characters are in uppercase and false otherwise.
  • isnumeric(): Returns true if string contains only numeric characters and false otherwise.

     

Padding strings

center() method returns a string that is centered in a string of a defined length. Padding is done using the specified fill character.  ljust() returns the string left justified in a string of specified length. Similarly goes for rjust().

word = "abcd"

# "   abcd   "
centered = '"' + word.center(10, ' ') + '"'

# "abcd      "
l = '"' + word.ljust(10, ' ') + '"'

# "      abcd"
r = '"' + word.rjust(10, ' ') + '"'

 

String Substitution

There are a few different ways to produce a string with information that is only available at run-time. The most obvious way is to concatenate multiple strings together using the + operator, but that only works if all the values are strings. As an alternative, Python also supports a way to inject objects into a string. This uses placeholders inside a string to denote where objects should go, along with a list of objects that should fill them in. This is called string substitution, and is performed using the % operator.

Placeholders consist of a percent sign and a conversion format. This allows the string to specify how objects should get converted, rather than having to call separate function explicitly. The most common of these formats is %s, which is equivalent to the str() function.

'This object is %s' % 1  # is equivalent to 'This object is 1'

 

Formatting

For a more powerful alternative to the simple string substitution described in the previous section, Python also includes a robust formatting system for strings. Rather than relying on a less obvious operator, string formatting uses an explicit format() method on strings. In addition, the syntax used for the formatting string is considerably different from what was used in simple substitution previously.

Instead of using a percent sign and a format code, format() expects its placeholders to be

surrounded by curly braces. What goes inside those braces depends on how you plan to pass in the values and how they should be formatted. The first portion of the placeholder determines whether it should look for a positional argument or a keyword argument. For positional arguments, the content is a number, indicating the index of the value to work with, while for keyword arguments, you supply the key that references the appropriate value.

s = "{0} and {1} are the best!"
s = s.format("NiceLabel", "NiceForm")

# NiceLabel and NiceForm are the best!

You can find all the samples here

10Dec/10Off

Python scripting in NiceForm and NiceLabel Portal

When you buy NiceLabel Portal you also get the new version of NiceLabel Suite (5.2.3.4020). This version includes NiceForm that besides Visual Basic Script now also supports Python as a scripting language. This gives NiceForm and NiceLabel Portal great opportunities to create very powerful and versatile solutions.

Prerequisites

NiceForm uses Python 2.7 and PyWin32 extensions for Python that allow Python to be used in the same way VBScript is used. However these two components are not automatically installed when you install NiceLabel Suite as most users will not need them. You will have to manually install first Python 2.7 and then PyWin32 extensions. You can find them on the NiceLabel Portal CD or download them from the internet:

Python 2.7 
PyWin32 for Python 2.7

How to enable Python as scripting language in NiceForm?

You can now choose between VBScript or Python language as the scripting language that can be used in "Execute script" ("VB Script" action was renamed to "Execute script") action or as an expression for action condition. This is a new form property that you can change by double clicking the form and opening "Scripting" page in the “Form Properties” dialog box and it will be used for all actions on the form. Only one language can be used at a time.

NiceForm - Form Properties

Other changes in NiceForm 5.2.3 regarding Python scripting

Some other changes were also implemented in NiceForm in connection with Python scripting:

  • “Action Properties [Execute Script]” dialog box is now resizable.
  • Syntax highlighting for both VBScript and Python is supported.
  • “Build script …” button is not available if you use Python as a scripting language.

NiceForm - Execute Script Action Properties

Some of the differences between VBScript and Python

Variable names

If you want to use variables in scripts you have to follow some rules regarding variable names:

  • Name cannot contain spaces.
  • Name can contain lowercase or uppercase letters and digits.
  • Case is significant.
  • The following reserved words cannot be used as variable names: and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, with, yield.

This means that if you were allowed to use variable with name “Last Name” in a VBScript you will no longer be able to do that and you will have to rename it to “LastName” to use it in Python script. Please also note that Python is case sensitive and that “variable” and “Variable” are no longer the same thing (as they were in VBScript). In your Python script you have to use exactly the same name for a variable you used when you defined it.

Getting and setting variable values

One of the differences between VBScript and Python is also the way NiceForm variables are set. This is best shown on a sample code. Below you can find a piece of code that does the same thing in both VBScript and Python.

VBScript
error = ""
if Len(keypress) <> 8 then
  keypress = keypress & 8
else
  error = "You can use max 8 digits"
end if
Display = keypress
Python
error.Value = ""
if len(keypress.Value) < 8:
  keypress.Value = keypress.Value + "8"
else:
  error.Value = "You can use max 8 digits"
Display.Value = keypress.Value

 

If you want to get or set variable value you can no longer just its name, but have to use its “Value” property.

Python scripts in NiceLabel Portal

Because NiceLabel Portal runs in the browser and Python as such cannot be used there we used IronPython for running scripts in forms that are used in NiceLabel Portal. Because of this there are some differences between scripts that run on the desktop (in NiceForm) and those that run in NiceLabel Portal. Syntax of the scripts is the same you just cannot use all of the modules Python provides.

How can I tell on which platform my Python script is running?


import sys

if sys.platform == 'silverlight':
    # Form runs in NiceLabel Portal
else:
    # Form runs in NiceForm on the desktop

 

Resources

I find the following resources very useful for learning Python:

www.python.org/ (Python Home)

diveintopython.org/ (Dive into Python)

openbookproject.net//thinkCSpy/ (How to Think Like a Computer Scientist)

ironpython.net/ (IronPython Home)

www.trypython.org/ (Excellent resource for trying out what can be done via scripting in NiceLabel Portal)

20Oct/10Off

NiceLabel Portal

We have announced NiceLabel Portal today. I am very excited about this product because it brings powers of NiceLabel and NiceForm to the web. NiceLabel Portal allows running complex (or simple) labeling applications created by NiceLabel and NiceForm.

Here are two samples of such applications. First video shows a simple form where user can select a record from a database, set date, define whether she wants to print a logo on the label, select a printer and print the one of two label designs.

 

 

Second sample shows that even applications that do not print can be created.

 

For the client side of NiceLabel Portal you will have to have the latest version of Silverlight 4, Internet Explorer 7 or newer (32-bit version) and you also have to install a small ActiveX component that allows communication with printers. For installing ActiveX component on Windows XP you will have to have administrator privileges.

Since this is version 1 of the product not full functionality of NiceLabel and NiceForm was implemented.On the label you can use Text, Text Box, Bar code, Picture, Rectangle and Line objects. The following barcode symbologies can be used: EAN-8, EAN-13, UPC-A, UPC-E, UPC-E(1), GS1-128 (EAN-UCC 128), Code 39, CODE-128 (A, B and C subsets), PDF 417, DataMatrix and QR. For pictures you can use .JPG or .PNG files.”Concatenate”, “Subset”, “Linear”, “GS1-128”, “Date addition”, “ASC (FACT)”, “Link to file” functions can also be used. To make label designs flexible prompt variables, counters, date and time variables and global variables can be used. Properties like prefix, suffix, padding character can also be used.

For designing forms all objects except Button Group can be used: Frame, Text, Picture, Edit Field, Memo Field, Button, List Box, Combo Box, Check Box, Radio Group, Variable Prompt, Database Search, Database Navigator, Table and Preview. Also almost all actions were implemented: “Open label”, “Print label”, “Set printer”, “Set variable”, “Load variable data”, “Save variable data”, “For every record in a table”, “For loop”, “Refresh database”, “Execute SQL statement”, “Import data into database”, “Send data to TCP/IP” port, “Open another form”, “Open document/program” (with limitations), “Quit” and “Execute script”. Since Visual Basic script is not supported in Silverlight, Python is now used as a scripting language in forms.

All printers with Windows drivers can be used for printing.

NiceLabel Portal supports Unicode encoding so you can create multi-lingual form and label designs. You can also use any Windows font during label or form design but you have to make sure that all used fonts are also installed on client computers. If a font cannot be found, Arial font will be used.

Of course databases can also be used (see the first video). We recommend using “real” databases like Microsoft SQL server or Oracle, although text (CSV) files and databases that have OLE DB drivers (like Microsoft Excel, Microsoft Access, Microsoft SQL Server, Oracle, etc.) are also supported.

For the end I would like once again repeat that I am very proud and excited about NiceLabel Portal because it is very solid, stable product that can solve lots of problems that our existing and future customers have.