Post

Format Code to HTML within a VS.NET 2K3 Macro (leveraging Microsoft Word)

Brad Abrams pointed out that he uses copy and paste into Word from Visual Studio 2005 Express Edition. Mike Parsons commented that he uses a VS.NET macro to help automate the same task. I really liked the idea of doing this directly within VS.NET.

After looking through it, I found what I thought were some flaws in the implementation; not removing the file upon finishing the task being one of them causing a lot of temporary files being created and the fact that he wasn’t leveraging some System.IO methods to handle the creation of the temporary file. In addition, you still had to switch to another task (your system default browser) in order to select the text, yet again, to paste it in your blogging software. In addition, the final HTML was still pretty ugly. I decided to fix some of these deficiencies.

I think this macro pretty solid, however, I’ve not really done a whole lot of dogfooding just yet. If you find any problems, please let me know.

Here is the final product.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Option Explicit On 
Option Strict Off ' Using late binding.

Imports System
Imports EnvDTE
Imports System.Diagnostics
 
Public Module Module1
 
  Private Const WdPasteDefault As Integer = 0
  Private Const WdFormatFilteredHTML As Integer = 10
  Private Const WdWebView As Integer = 6
  
  Sub FormatSourceCode()
  
    ' Get the currently selected code snippet.
    Dim selection As TextSelection = CType(DTE.ActiveDocument.Selection(), TextSelection)
  
    ' Check that something is selected.
    If selection.Text = "" Then
      MsgBox("No code selected!", MsgBoxStyle.Critical Or MsgBoxStyle.OKOnly, "Format Code")
      Return
    End If
  
    ' Create a temporary file.
    Dim path As String = System.IO.Path.GetTempFileName()
  
    ' Copy the selected code to clipboard (using VS.NET).
    selection.Copy()
  
    ' Instantiate a new Word document to achieve HTML code formatting.
    Dim oleDocument As Type = Type.GetTypeFromProgID("Word.Document")
    Dim document As Object = Activator.CreateInstance(oleDocument)
    document.ActiveWindow.Selection.PasteAndFormat(WdPasteDefault)
    document.SaveAs(path, WdFormatFilteredHTML, False, "", True, "", False, False, False, False, False)
    document.Close()
    document = Nothing
    oleDocument = Nothing
  
    ' Open a new instance of Word.
    Dim oleApplication As Type = Type.GetTypeFromProgID("Word.Application")
    Dim application As Object = Activator.CreateInstance(oleApplication)
    ' Open the temporary document.
    document = application.Documents.Open(path)
    ' Switch to the WebView mode within Word.
    document.ActiveWindow.View.Type = WdWebView
    ' Select the whole document.
    document.ActiveWindow.Selection.WholeStory()
    ' Copy it to the clipboard.
    document.ActiveWindow.Selection.Copy()
    ' Close the document.
    document.Close()
    document = Nothing
    application.Quit()
    application = Nothing
    oleApplication = Nothing
  
    ' Cleanup after ourselves.
    IO.File.Delete(path)

  End Sub

End Module

And yes, I did use this macro to format the code within here ;-)

Note: I tried a couple of methods to get the final result saved within the clipboard… the one I settled on produced the best result. However, because it has to launch a new instance of Word; it takes a second or two. Still faster than doing everything by hand :-D

UPDATE: Josh Ledgard pointed out a nice step by step process for adding macros in Visual Studio. Also, I’m not an expert in the Microsoft Word object model. I should point out that I’ve only tested this with Microsoft Word 2003. What other versions of Microsoft Word this macro works with (or doesn’t) is anyones guess. If your using other versions of Microsoft Word, please let me (and others) know whether it’s working or not by leaving a comment.

UPDATE: Modified the code listing to include the application.Quit() call.

UPDATE: Modified the code to conform to the VB.NET Coding Guidelines, add it to the code samples / articles document and created a text file version of the macro for download.

This post is licensed under CC BY 4.0 by the author.