PageRenderTime 30ms CodeModel.GetById 23ms app.highlight 5ms RepoModel.GetById 0ms app.codeStats 0ms

/Visual Studio 2008/VBAutomateWord/ReadMe.txt

#
Plain Text | 226 lines | 171 code | 55 blank | 0 comment | 0 complexity | c43f681330bd27a6cdc91f4d25aa2dfe MD5 | raw file
  1========================================================================
  2    CONSOLE APPLICATION : VBAutomateWord Project Overview
  3========================================================================
  4
  5/////////////////////////////////////////////////////////////////////////////
  6Summary:
  7
  8The VBAutomateWord example demonstrates the use of Visual Basic.NET codes to 
  9create a Microsoft Word instance, create a new document, insert a paragraph 
 10and a table, save the document, close the Microsoft Word application and then 
 11clean up unmanaged COM resources.
 12
 13Office automation is based on Component Object Model (COM). When you call a 
 14COM object of Office from managed code, a Runtime Callable Wrapper (RCW) is 
 15automatically created. The RCW marshals calls between the .NET application 
 16and the COM object. The RCW keeps a reference count on the COM object. If 
 17all references have not been released on the RCW, the COM object of Office 
 18does not quit and may cause the Office application not to quit after your 
 19automation. In order to make sure that the Office application quits cleanly, 
 20the sample demonstrates two solutions.
 21
 22Solution1.AutomateWord demonstrates automating Microsoft Word application by 
 23using Microsoft Word Primary Interop Assembly (PIA) and explicitly assigning 
 24each COM accessor object to a new varaible that you would explicitly call 
 25Marshal.FinalReleaseComObject to release it at the end.
 26
 27Solution2.AutomateWord demonstrates automating Microsoft Word application by 
 28using Microsoft Word PIA and forcing a garbage collection as soon as the 
 29automation function is off the stack (at which point the RCW objects are no 
 30longer rooted) to clean up RCWs and release COM objects.
 31
 32
 33/////////////////////////////////////////////////////////////////////////////
 34Prerequisite:
 35
 36You must run this code sample on a computer that has Microsoft Word 2007 
 37installed.
 38
 39
 40/////////////////////////////////////////////////////////////////////////////
 41Demo:
 42
 43The following steps walk through a demonstration of the Word automation 
 44sample that starts a Microsoft Word instance, creates a new document, 
 45inserts a paragraph and a table, saves the document, and quits the Microsoft 
 46Word application cleanly.
 47
 48Step1. After you successfully build the sample project in Visual Studio 2008, 
 49you will get the application: VBAutomateWord.exe.
 50
 51Step2. Open Windows Task Manager (Ctrl+Shift+Esc) to confirm that no 
 52winword.exe is running. 
 53
 54Step3. Run the application. It should print the following content in the 
 55console window if no error is thrown.
 56
 57  Word.Application is started
 58  A new document is created
 59  Insert a paragraph
 60  Save and close the document
 61  Quit the Word application
 62
 63  Word.Application is started
 64  Insert a paragraph
 65  Insert a table
 66  Save and close the document
 67  Quit the Word application
 68
 69Then, you will see two new documents in the directory of the application: 
 70Sample1.docx and Sample2.docx. Both documents have the following content.
 71
 72  Heading 1
 73
 74Sample2.docx additionally has this table in the document.
 75
 76  r1c1	r1c2
 77  r2c1	r2c2
 78  r3c1	r3c2
 79  r4c1	r4c2
 80  r5c1	r5c2
 81
 82Step4. In Windows Task Manager, confirm that the winword.exe process does not 
 83exist, i.e. the Microsoft Word intance was closed and cleaned up properly.
 84
 85
 86/////////////////////////////////////////////////////////////////////////////
 87Project Relation:
 88
 89VBAutomateWord - CSAutomateWord - CppAutomateWord
 90
 91These examples automate Microsoft Word to do the same thing in different 
 92programming languages.
 93
 94
 95/////////////////////////////////////////////////////////////////////////////
 96Creation:
 97
 98Step1. Create a Console application and reference the Word Primary Interop 
 99Assembly (PIA). To reference the Word PIA, right-click the project file
100and click the "Add Reference..." button. In the Add Reference dialog, 
101navigate to the .NET tab, find Microsoft.Office.Interop.Word 12.0.0.0 and 
102click OK.
103
104Step2. Import and rename the Excel interop namepace:
105
106	Imports Word = Microsoft.Office.Interop.Word
107
108Step3. Start up a Word application by creating a Word.Application object.
109
110	oWord = New Word.Application()
111
112Step4. Get the Documents collection from Application.Documents and call its 
113Add function to create a new document. The Add function returns a Document 
114object.
115
116Step5. Insert a paragraph.
117
118	oParas = oDoc.Paragraphs
119	oPara = oParas.Add()
120	oParaRng = oPara.Range
121	oParaRng.Text = "Heading 1"
122	oFont = oParaRng.Font
123	oFont.Bold = 1
124	oParaRng.InsertParagraphAfter()
125
126Step6. Insert a table.
127
128The following code has the problem that it invokes accessors which will also 
129create RCWs and reference them. For example, calling Document.Bookmarks.Item 
130creates an RCW for the Bookmarks object. If you invoke these accessors via 
131tunneling as this code does, the RCWs are created on the GC heap, but the 
132references are created under the hood on the stack and are then discarded. As 
133such, there is no way to call MarshalFinalReleaseComObject on those RCWs. To 
134get them to release, you would either need to force a garbage collection as 
135soon as the calling function is off the stack (at which point these objects 
136are no longer rooted) and then call GC.WaitForPendingFinalizers, or you would 
137need to change the syntax to explicitly assign these accessor objects to a 
138variable that you would then explicitly call Marshal.FinalReleaseComObject on. 
139
140	oBookmarkRng = oDoc.Bookmarks.Item("\endofdoc").Range
141
142	oTable = oDoc.Tables.Add(oBookmarkRng, 5, 2)
143	oTable.Range.ParagraphFormat.SpaceAfter = 6
144
145	For r As Integer = 1 To 5
146		For c As Integer = 1 To 2
147			oTable.Cell(r, c).Range.Text = "r" & r & "c" & c
148		Next
149	Next
150
151	' Change width of columns 1 & 2
152	oTable.Columns(1).Width = oWord.InchesToPoints(2)
153	oTable.Columns(2).Width = oWord.InchesToPoints(3)
154
155Step7. Save the document as a docx file and close it.
156
157	Dim fileName As String = Path.GetDirectoryName( _
158	Assembly.GetExecutingAssembly().Location) & "\Sample1.docx"
159	oDoc.SaveAs(fileName, Word.WdSaveFormat.wdFormatXMLDocument)
160	oDoc.Close()
161
162Step8. Quit the Word application.
163
164	oWord.Quit(False)
165
166Step9. Clean up the unmanaged COM resource. To get Word terminated rightly, 
167we need to call Marshal.FinalReleaseComObject() on each COM object we used.
168We can either explicitly call Marshal.FinalReleaseComObject on all accessor 
169objects:
170
171	' See Solution1.AutomateWord
172	If Not oFont Is Nothing Then
173		Marshal.FinalReleaseComObject(oFont)
174		oFont = Nothing
175	End If
176	If Not oParaRng Is Nothing Then
177		Marshal.FinalReleaseComObject(oParaRng)
178		oParaRng = Nothing
179	End If
180	If Not oPara Is Nothing Then
181		Marshal.FinalReleaseComObject(oPara)
182		oPara = Nothing
183	End If
184	If Not oParas Is Nothing Then
185		Marshal.FinalReleaseComObject(oParas)
186		oParas = Nothing
187	End If
188	If Not oDoc Is Nothing Then
189		Marshal.FinalReleaseComObject(oDoc)
190		oDoc = Nothing
191	End If
192	If Not oDocs Is Nothing Then
193		Marshal.FinalReleaseComObject(oDocs)
194		oDocs = Nothing
195	End If
196	If Not oWord Is Nothing Then
197		Marshal.FinalReleaseComObject(oWord)
198		oWord = Nothing
199	End If
200
201and/or force a garbage collection as soon as the calling function is off the 
202stack (at which point these objects are no longer rooted) and then call 
203GC.WaitForPendingFinalizers.
204
205	' See Solution2.AutomateWord
206	GC.Collect()
207	GC.WaitForPendingFinalizers()
208	' GC needs to be called twice in order to get the Finalizers called 
209	' - the first time in, it simply makes a list of what is to be 
210	' finalized, the second time in, it actually is finalizing. Only 
211	' then will the object do its automatic ReleaseComObject.
212	GC.Collect()
213	GC.WaitForPendingFinalizers()
214
215
216/////////////////////////////////////////////////////////////////////////////
217References:
218
219MSDN: Word 2007 Developer Reference
220http://msdn.microsoft.com/en-us/library/bb244391.aspx
221
222How to automate Word from Visual Basic .NET to create a new document
223http://support.microsoft.com/kb/316383/
224
225
226/////////////////////////////////////////////////////////////////////////////