2010-04-19

Notes on Developing Outlook 2003 Forms

I just finished developing a simple e-mail workflow system implemented using Outlook forms and VBScript and thought I should jot down some things that made development easier:

Configuring Your Development Environment

  • Disable Outlook Autosignature, otherwise your signature is inserted into the message object each time you create a new form and you cannot clear the text in the message object using the Form Designer. While you can clear the message object using VBScript using Item.Body = "", it's annoying to have so much noise during development.
  • If you use VBScript in your form definition, don't send the form definition in each item, otherwise you cannot run VBScript in your item. In the Form Designer's Properties tab, ensure that Send form definition with item is unchecked.
  • Each form definition has a unique Message Class. To ensure that you are opening items based on your form definition in Outlook, add the Message Class field into your Outlook View using the following steps:
    1. Select menu item View, Arrange By, Current View, Customize Current View. Outlook should open the Customize View dialog.
    2. In Customize View: dialog, select Fields... button. Outlook should open the Show Fields dialog.
    3. In Show Fields dialog, select All Mail Fields in the drop down list of available fields.
    4. Select and add Message Class to your view.
  • Create a desktop shortcut to use your form. Using the shortcut is faster than the alternative of using the menu item Tools, Forms, Choose Form and then picking your form from the Choose Form dialog. Plus, when you finish development and publish your form, you can send the shortcut file to your users.

One-Off Forms

If you have VBScript in your form definition, you must avoid making a one-off forms (i.e. an item which no longer references its form definition) because Outlook security does not allow VBScript to run in one-off forms. A one-off form can be identified if its Message Class is not the same as the form definition's and / or its size is much larger than expected. For instance, if you define a form named IPM.Note.Test, instances of this form should have the same message class and a size of about 5 to 6 Kbytes, while a one-off form may be called IPM.Note and / or have a size of in tens of Kbytes. If you think the rules for identify one-off items are a bit vague, read this.

There's a fair bit of documentation and discussion about one-off items online because that's how Outlook forms were first deployed before they were regarded as a security risk. I ignored one-off items (which seemed quite useless nowadays) and treated my form definition as my 'program'. During development, my form definition is published in Personal Folders and I always use that definition to create an item. I also found that using the form designer's Tools, Run This Form menu item creates one-off items.

VBScript Development

When writing VBScript for Outlook forms, you are stuck with the minimal Script Editor which doesn't have features such as highlighting syntax, auto-completion or a debugger; it's so minimal that it doesn't have a Save button or allow you to choose another font! At least changes in the Script Editor are always saved when you publish, so you can leave the Script Editor window open during a coding session.

Script Editor doesn't have a debugger, so you have to use the Outlook Script Debugger, which is the Web Debugger in read-only mode (!) that doesn't allow you to modify Outlook VBScript. The only silver lining that you can inspect objects and find out what properties they have in the script debugger.

Final Thoughts

Developing Outlook Forms with VBSCript was somewhat painful because of the lack of tool support. I hope the tips in this article would be useful for others starting on a similar project.

References

2010-03-01

Visio Shape Positioning Annoyance

In technical diagrams, I align the positions and dimensions of shapes with a grid so that the spacing and sizes are consistent. Using Visio 2007, after I resize a page using File, Page Setup, Page Size, Size to fit drawing contents, every shape's position is slightly modified. For example, if I position a shape at x = 40mm, y = 30mm, the shape's position becomes something like x = 40.0847mm, y = 30.1051mm.

My workaround is to manually resize the page size by holding the Ctrl key and using the pointer to move the horizontal or vertical edge of a page; then the shapes' positions aren't altered.

2010-02-23

Vista Ctrl+Space IME Toggle Workaround

If you start using Windows Vista Input Method Editor (IME) for Chinese, you may find that you can no longer use Ctrl+Space in some applications (e.g. to select a column in Excel, to activate autocomplete in IDEs such as VBA, Netbeans or Visual Studio, or to activate Firefox Ubiquity). One workaround is to define a different hotkey, such as Ctrl+Shift+F12, to toggle the IME.

If you have only one keyboard service and find that Ctrl+Space mysteriously starts to act as a toggle for an unselected IME (in my case, Chinese (Traditional, Taiwan)), the workaround is to add a keyboard service and define a different IME hotkey. You must define a hotkey for toggling the IME, otherwise the IME is activated using the default Ctrl+Space.

Reference

2010-02-21

VBA Is*() Functions Only Apply To Variant Types

VBA has several informational functions prefixed with "Is", such as IsNull(), IsMissing() and IsEmpty(), that only work with Variant types. I didn't realise it until I tried to apply them to non-Variant variables and noticed that they didn't work as I expected or always returned the same result.

For instance, if you define optional parameters for a procedure, you can only test if they are used in the procedure call using IsMissing() if the parameter is a Variant type. Using any other type of parameter with IsMissing() always returns False because all other parameter types have a default value supplied by the compiler or by the programmer.

Similarly, only Variant variables can have a Null value so that they can be tested by the IsNull() function. Object types can have a Nothing value, not Null, and can only be tested using the Is operator.

In the same vein, only Variant variables can be uninitialised and tested with IsEmpty(). All other variable types are initialised to some value (e.g. Objects are initialised to Nothing, Integers are initialised to 0).