How to clear the Clipboard when exiting Microsoft Word

This week a colleague approached me to consult about a problem he had encountered, where it was necessary to ensure that the Clipboard was empty when Microsoft Word exits. It was part of a legacy Word automation solution that he wasn’t in a position to change just yet, and it would crash if there was anything left on the clipboard.

Two approaches came to mind, one using a Word VBA Macro, the other using a VSTO add-in. Here is an attempt at a solution for the first approach – let’s hope it fixes the problem.

You can hook into events using Word VBA quite easily, either by creating a macro with a special name (reference: http://msdn.microsoft.com/en-us/library/bb208800.aspx), or by setting up event handlers. In this case, we will use a macro called AutoExit which is invoked “when you exit Word or unload a global template”. We’ll save the macro in a template file and have it loaded as a global template, so this event should be ideal for our purposes.

The first step is to load Word and get to the Visual Basic editor (press Alt-F11). Here, double-click on the ThisDocument entry in the project explorer to open up a code window:

Then, copy and paste the following code (which I will explain soon) into the code window you just opened:

'Events: http://msdn.microsoft.com/en-us/library/bb208800.aspx
Sub AutoExit()
    ClearClipboard
End Sub

Sub ClearClipboard()
    Dim MyData As Object
    ' source: http://akihitoyamashiro.com/en/VBA/LateBindingDataObject.htm
    Set MyData = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    MyData.SetText ""
    MyData.PutInClipboard
    Set MyData = Nothing
End Sub

Now save the document as a Word Macro-Enabled Document Template (.dotm) with a name such as ClearClipboardOnWordExit.dotm:

Place this document in the Word Startup folder. By default, it should be %appdata%\Microsoft\Word\Startup, but you can find out where it really is by going to Word Options, Advanced, scrolling to the bottom and clicking on File Locations:

Word will load any templates in this folder as global templates when it starts.

That’s about it! Now to test it, open Word afresh, type something and copy it to the clipboard. Then exit Word and check to confirm that the clipboard no longer has the text you just copied.

Explanation of the code

  • The name of the macro, AutoExit, makes it get called when Word is closing:
    Sub AutoExit()
        ClearClipboard
    End Sub
    
  • Then we create a DataObject, which is part of the Microsoft Forms 2.0 Object Library. However, instead of adding a reference to it, I prefer using late binding so I found this page that describes how to do it using the clsid: http://akihitoyamashiro.com/en/VBA/LateBindingDataObject.htm

        Dim MyData As Object
        Set MyData = CreateObject("new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    
  • Using this object, we set a blank string to the clipboard, effectively clearing it:
        MyData.SetText ""
        MyData.PutInClipboard
    
Posted in Technology | Tagged , , , | 1 Response

Get email Headers from an Outlook MailItem

While working on a VSTO add-in for Microsoft Outlook, I came across the need to access the headers of an email, to parse out X-CustomProperty tags that were put in by an application that sent the emails. However, I couldn’t find a Headers property in the Outlook object model, so below is an attempt to create one.

The Regex used is courtesy of John Gietzen’s answer on this stackoverflow question.

using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Office.Interop.Outlook;

public static class MailItemExtensions
{
    private const string HeaderRegex =
        @"^(?<header_key>[-A-Za-z0-9]+)(?<seperator>:[ \t]*)" +
            "(?<header_value>([^\r\n]|\r\n[ \t]+)*)(?<terminator>\r\n)";
    private const string TransportMessageHeadersSchema =
        "http://schemas.microsoft.com/mapi/proptag/0x007D001E";

    public static string[] Headers(this MailItem mailItem, string name)
    {
        var headers = mailItem.HeaderLookup();
        if (headers.Contains(name))
            return headers[name].ToArray();
        return new string[0];
    }

    public static ILookup<string, string> HeaderLookup(this MailItem mailItem)
    {
        var headerString = mailItem.HeaderString();
        var headerMatches = Regex.Matches
            (headerString, HeaderRegex, RegexOptions.Multiline).Cast<Match>();
        return headerMatches.ToLookup(
            h => h.Groups["header_key"].Value,
            h => h.Groups["header_value"].Value);
    }

    public static string HeaderString(this MailItem mailItem)
    {
        return (string)mailItem.PropertyAccessor
            .GetProperty(TransportMessageHeadersSchema);
    }
}

Sample usage:

string[] preparedByArray = mailItem.Headers("X-PreparedBy");
string preparedBy;
if (preparedByArray.Length == 1)
    preparedBy = preparedByArray[0];
else 
    preparedBy = "";

string allHeaders = mailItem.HeaderString();

Edit 2011/08/05:
Thanks to Rob for the heads-up. I updated the code to return a Lookup instead of a Dictionary – this handles the case of multiple headers with the same name.

Posted in Technology | Tagged , , , , , , | 4 Responses

How to filter select list options

Here’s a jQuery extension method to filter the elements of a select list (option tags). It binds to a textbox, and as you type in the textbox the select list gets filtered to match what you are typing.

jQuery.fn.filterByText = function(textbox, selectSingleMatch) {
  return this.each(function() {
    var select = this;
    var options = [];
    $(select).find('option').each(function() {
      options.push({value: $(this).val(), text: $(this).text()});
    });
    $(select).data('options', options);
    $(textbox).bind('change keyup', function() {
      var options = $(select).empty().scrollTop(0).data('options');
      var search = $.trim($(this).val());
      var regex = new RegExp(search,'gi');

      $.each(options, function(i) {
        var option = options[i];
        if(option.text.match(regex) !== null) {
          $(select).append(
             $('<option>').text(option.text).val(option.value)
          );
        }
      });
      if (selectSingleMatch === true && 
          $(select).children().length === 1) {
        $(select).children().get(0).selected = true;
      }
    });
  });
};

Parameters:

  • textbox
    This could be a jQuery selector, a jQuery object, or a DOM object.
  • selectSingleMatch
    This is optional, if you set it to true, when the filtered list includes only one item, that item will be automatically selected.

For example:

$(function() {
  $('#select').filterByText($('#textbox'), true);
});  

Live example (or in a new window):

You can play around with it on jsbin: http://jsbin.com/egogeh/edit

What it does:

When you invoke the function on a select object, it finds all child option tags and saves their text and values into an array. This array is saved to the select object itself as a HTML5 custom data attribute, called data-options. Then, when a change or keyup event fires on the associated textbox, the select list is emptied, and for any entries in the array that match the search text a new option element is created.

Edit 2012-10-15: Added ScrollTop(0) to improve the way it works with long lists, thanks to a comment by xarel below.

Posted in Technology | Tagged | 55 Responses

Using Open XML SDK to get Custom Properties from a Word document

I stumbled across a library that I didn’t realize was out there, for working with Microsoft Office documents. It only works with the newer Office 2007 and 2010 files (and 2003 with a compatibility pack), i.e. those using the Open XML standard.

Download and install the Open XML SDK 2.0 for Microsoft Office: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=5124.

I got the second, smaller file:

Open XML SDK 2.0 for Microsoft Office

Add a reference to DocumentFormat.OpenXml and WindowsBase to your project:

You can now programmatically access Office documents, without the need to have Microsoft Office installed or any Interop DLLs. This works with Word, Excel and PowerPoint (using the OpenXML WordprocessingML, SpreadsheetML and PresentationML).

For example, to get the custom properties of a Word document:

public static Dictionary<string, string> GetCustomPropertiesOfWordDocument
                                                  (string filename)
{
    using (var package = WordprocessingDocument.Open(filename, false))
    {
        var properties = new Dictionary<string, string>();
        foreach (var property in package.CustomFilePropertiesPart
            .Properties.Elements<CustomDocumentProperty>())
        {
            properties.Add(property.Name, property.VTLPWSTR.Text);
        }
        return properties;
    }
}

In this example, you would need to add some error handling around line 9 (property.VTLPWSTR.Text) as your property may be a different type or null.

When deploying your solution, you need to include DocumentFormat.OpenXml.dll with your application. You can set Copy Local to True in the properties for the reference, and it will be copied to your output folder when you compile the project:

Download a sample project here.

Posted in Technology | Tagged , , | Leave a comment

How to hide the dotted border outline on focused elements in HTML, using CSS

While working on a web application for data entry, I had to scour the net for a way to hide the dotted border that appears when an element is focused on a web page. Here are my findings.

First, the obligatory disclaimer – I do understand that the dotted border is for accessibility purposes and should be left in place under normal circumstances. However, in this case we already had a replacement in place – when an element receives focus it is styled differently, using a very distinct background color. And this applies to all elements, regardless of whether they were selected by mouse or keyboard. So the dotted border is redundant, and somewhat distracting.

To further clarify the question, these are the dotted borders I refer to:
save-outline and cancel-outline

While the solution needed to be usable across browsers, the target browsers where well defined – modern versions of Firefox and Chrome, and IE 7 or newer. I first came across this question on stackoverflow.com which pointed me to using outline:none. Then this one helped with Firefox compatibility. And then I saw this post which provides a number of different techniques.

I ended up using the following CSS, which seems to cover most bases. As I didn’t see this combination on other sites I thought I would post it myself. It doesn’t apply to the select element in Firefox and IE7. Testing was done on Windows XP.

/* hide the dotted lines around an element when it receives focus */
* { _noFocusLine: expression(this.hideFocus=true); } /* ie7 */
::-moz-focus-inner {border:0;}	                     /* firefox */
:focus {outline:none;}                               /* ie8, chrome, etc */
Posted in Technology | Tagged , , , | 4 Responses

Context is Hindi when printing line numbers in Word 2007

[This post accompanies a question posted here: http://superuser.com/questions/90665/context-is-hindi-when-printing-line-numbers-in-word-2007]

I’m trying to print a Word 2007 document with Line Numbering turned on, and in Word the document looks fine but when I print the document, the line numbers appear in Hindi script.

On screen:
Printed:

I tried deleting my Normal template and allowing Word to create a new one, and testing using that, with no change. I also tried different printers.

The problem goes away if I choose Arabic instead of Context under Word Options -> Advanced -> Show Document Content / Numeral:

However, I would like to keep the setting as Context. The question is, why is the default context of my document Hindi script?

Posted in Technology | Tagged , , | 2 Responses

Registry settings to add Uninstall as a shell option for VSTO manifest files

vsto logo

Visual Studio Tools for the Microsoft Office System (VSTO)

I have been working on some VSTO add-ins and on deploying them, and have something to share that I didn’t find anywhere else.

First of all, let me just say that despite certain hurdles, deploying using ClickOnce has been a very pleasant experience. After following some tutorials on making an MSI, we eventually ended up simply deploying the few needed registry entries to all users, which take care of installing and trusting each add-in. Then, once the add-in is installed, it takes care of updating itself every so often.

Unfortunately, during the period of figuring this out a few users got an older version then a newer version with a new signing certificate, which is I suspect the reason why they get the following error message:

Specified argument was out of the range of valid values.
Parameter name: entryValue

Exception Text
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: entryValue
  at Microsoft.VisualStudio.Tools.Applications.Deployment.RegistryStore.Retrieve(String entryName, Object entryValue, CompareDelegate compareMethod)
  at Microsoft.VisualStudio.Tools.Applications.Deployment.MetadataStore.UpdateLastCheckedTime(String subscriptionID, DateTime newLastCheckedTime)
  at Microsoft.VisualStudio.Tools.Applications.Deployment.ClickOnceAddInDeploymentManager.InstallAddIn()

There is some discussion of this error here.

Anyway, I tried removing the folder: C:\Documents and Settings\%username%\Local Settings\Apps\2.0 which causes the add-ins to re-install themselves, but that didn’t fix the problem.

The second solution I tried worked, which was to uninstall the add-in and then re-install it again. One way to uninstall is to do so via Add/Remove programs (still using XP lingo), but I came across another way from this blog post at ChristophDotNet: simply run this command:

C:\Program Files\Common Files\Microsoft Shared\VSTO\9.0\VSTOinstaller.exe
     /uninstall &lt;name-of-manifest-file.vsto&gt;

I find this way much easier than waiting for the Add/Remove dialog to populate (takes a while on my bloated box). You can read more about the VSTOInstaller on MSDN.

After using this technique for a while, I realized one thing – to install an MSI file, you right-click on it and choose Install, and you can also right-click to Uninstall. However, with .vsto files, you can only install. Why not add the uninstall capability right there using a shell command? And now that I knew what the command was, it was trivial. First, to find out where in the registry the open command is defined, I came across this post on Nikhil’s blog. Then, I simply added an uninstall component to it:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\bootstrap.vsto.1\shell\uninstall]
@="Uninstall"

[HKEY_CLASSES_ROOT\bootstrap.vsto.1\shell\uninstall\command]
@="\"C:\\Program Files\\Common Files\\microsoft shared\\VSTO\\9.0\\VSTOInstaller.exe\" /uninstall \"%1\""

Put that in a .reg file and run it, and you’ll be able to uninstall VSTO add-ins with ease!

This post applies to VSTO version 3.0.

Posted in Technology | Tagged , , , , | 6 Responses

Recursive Active Directory group membership using System.DirectoryServices in .NET 3.5

When coding for an organization that uses Active Directory, you will eventually come across the business case for using groups within groups, i.e. a  user is part of say, the HR-Administration group, and that group is itself a member of the HR-Department group. You may then need to secure your application to only allow members of HR-Department to access certain functionality within it,  and so you need an IsUserInGroup function, but one that looks recursively at groups that are members of the requested group.

Over the years I’ve had to come up with such a function in various technologies: VB6 using ADSI, PHP using the php_ldap extension, and System.DirectoryServices in .NET 2.0 with a custom function for recursing.

A few weeks ago I was using .NET 3.5 and decided to look around again to see if there was an easy alternative. It seems the 3.5 release comes with a revamped System.DirectoryServices which makes things much easier for common use cases. And although there is no function to achieve what we need, there is one that helps us do it: group.GetMembers(true).  The parameter when set to true triggers a recursive search of all groups that are members of the current group, and grabs their members too. So it becomes trivial to achieve an IsUserInGroup function:

using System.DirectoryServices.AccountManagement;

...

public static bool IsUserInGroup(string username, string groupname)
{
    var foundUser = false;
    using (var context = new PrincipalContext(ContextType.Domain, "microsoft.com"))
    using (var group = GroupPrincipal.FindByIdentity(context, groupname))
    {
        if (group == null)
        {
            throw new ArgumentException("Group could not be found: " + groupname);
        }

        // GetMembers(true) is recursive (groups-within-groups)
        foreach (var member in group.GetMembers(true))
        {
            if (member.SamAccountName.Equals(username))
            {
                foundUser = true;
                break;
            }
        }
    }
    return foundUser;
}
Posted in Technology | Comments closed

Now using Windows 7 Release Candidate

I recently installed Windows 7 – which is currently being developed and will be released in the next few months – on my home computer. I had heard good things about it, and was keen to test out this latest preview version. It replaced my 6-month old XP installation. Here are some screenshots of things that stood out to me in the new Windows.

windows7

The installation went very smoothly, took somewhere around 30 minutes (had to go away from the computer and come back so couldn’t tell exactly how long it took). The first thing I noticed, it installed drivers for my video card, then detected the monitors connected and figured out their maximum resolutions, and set Windows to those resolutions as well as the side-by-side layout of the monitors. Everything worked perfectly! Quite impressed. To change these settings further, the interface looks like this:

display

Another change was with themes. They now seem more well integrated, with sound schemes and lists of wallpapers to go along with each theme. When you click on the theme it changes to it there and then, and very quickly. You also hear a preview sound from that theme, which makes for a great choosing experience:

themes

The quick launch area next to the Start menu has gotten a revamp – mouse over also shows a preview of all the windows of that type that are open:

quick-launch

One of the new features is Libraries, which are special folders that show files from different sources. You get to define which paths these files come from, but they all show together in one convenient view:

librariesOf course, the icons themselves are new, and rendered very beautifully – I just noticed the Control Panel icon which looks very nice:

iconsStarting to test out other features – the desktop Gadgets are there just like Vista, but worked really well and fast for me:

gadgets

There is a new item in the Control Panel called Devices and Printers. This seems to provide a much more convenient location to see your installed hardware and configure them. Each icon represents a type of device, and they all have their own context menus of actions:

devices

Thats about it for what I noticed in the first few minutes. Microsoft Paint also got an interface lift:

paint

So far the experience has been quite pleasant – very responsive and fast, sleek polished UI, high availability of drivers and installation seems very well automated, and stable – haven’t had any crashes yet.

If you would like to try it out for yourself, here’s the link:

win7_subhero_downloadrc
Posted in Technology | Tagged , | Leave a comment

Prezi for stunning presentations

Prezi logoSome days ago I was introduced to this website: prezi.com, for creating presentations online. The editor uses Flash and is entirely online, and you can upload pictures, videos and other flash animations to it.

Anyway, I had signed up for their closed beta and earlier today I received a login. The timing was quite fortuitous as I had a presentation scheduled for later in the day and decided to re-do the PowerPoint slides on Prezi. It was quite quick to do, and I exported some of the elements from the PowerPoint presentation and uploaded them to Prezi – took maybe two or three hours in total.

Here’s the resulting creation:

Prezi screenshot - Windows Workflow Foundation

Click through to open and view it. When viewing, use the arrows in the bottom right corner to navigate:

Prezi - Navigation

Or you can simply click on an object to zoom in on it.

 

The editor is also quite neat – there is a round menu system:

Prezi menu

And when you click on a shape you can move/scale/rotate it with this round control:

Prezi - Round menu

Very innovative interface! This promises to be a popular online resource. Visit their site and sign up, and you can play around with the demos.

Posted in Technology | Tagged , , , , , | 2 Responses