Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Embedding Microsoft Word as a control into Desktop Forms


:P
On this page:

 

I’ve spent quite a bit of time today with a cool feature – integrating MS Word directly into Help Builder as an edit control. By this I mean, using Word as an embedded control into my application and using it for basic editing and more importantly for its spell checking support.

 

The normal editing environment in Help Builder is entirely text based and using Word too leaves the actual editing as text based with all mark up handled through Help Builder’s menus, rather than through Word.

Here’s what this looks like in Help Builder:

 

 

Although the editing doesn’t take advantage of Words layout capabilities or even its markup it does provide a smoother text typing environment and of course inline spell checking.

 

This feature is optional and not the default edit mode – you basically have to select this option from the Edit toolbar when you are in a specific control. As soon as you move off the field, the editor reverts to a default textbox. You could say that Word is used in this scenario merely as an overlay on the stock textbox.

 

Of course, the customer must have Word installed in order for this to work at all, and as this interface uses the Web Browser control to host a Word document, must have security settings to allow editing Word documents locally.

How it works

Embedding Word into a FoxPro (or any other ActiveX container) is not easily done. Although Word is an Activedocument host, it doesn’t provide a direct interface to embed itself into a host application.

 

You can make this happen however, by using the Microsoft Web Browser ActiveX control and hosting a Word document inside of it. You can simply navigate the WebBrowser to a Word Document and Word will load into the browser control in place and expose the Word object model via the Document property.

 

If you’re not familiar with the Web Browser control you can look here for more information:

http://www.west-wind.com/presentations/shellapi/shellapi.asp

 

The following function loads a Word document into the browser control hosted on a form (or in this case a Container control in Visual FoxPro):

 

FUNCTION LoadDocument

LPARAMETERS lcDocument, lcText

 

IF !FILE(lcDocument)

   this.oBrowser.Navigate("about:blank")

   MESSAGEBOX("Can't find document: " + lcDocument,48,"Word Editing")

   RETURN .F.

ENDIF

 

this.cinternaldocument = lcDocument

 

DOEVENTS

 

THIS.oBrowser.Navigate( lcDocument )

DOEVENTS

 

IF !this.oBrowser.WaitForReadyState()

   DOEVENTS

   IF !this.oBrowser.WaitForReadyState()

      RETURN .F.

   ENDIF

ENDIF     

 

IF this.oBrowser.ReadyState # 4

   WAIT WINDOW TIMEOUT .2

ENDIF

 

LOCAL loDoc as Word.Document, loApp as Word.Application

loDoc = this.oBrowser.Document

THIS.oDoc = loDoc

this.oWord = loDoc.Application

 

*** Put document into 'Web View' mode

loWord.ActiveWindow.View = 6

 

*** Match document fonts to current font

IF !EMPTY(this.cfontinfo)

   lnCount = ALINES(laWords,this.cfontinfo,",")

   IF lnCount = 3

      loDoc.Styles.Item("Normal").Font.Name = this.oEdit.Fontname

      loDoc.Styles.Item("Normal").Font.Size = this.oEdit.Fontsize

   ENDIF

ENDIF  

 

*** Manage display of toolbars

loDoc.CommandBars("Reviewing").visible = .f.

loDoc.CommandBars("Standard").Visible = .t.

 

*** Load up the text into the Word doc

IF !EMPTY(lcText)

   this.oBrowser.Document.Content.Text = lcText

ENDIF

 

*** Try to select the same selection in the Word doc

this.oWord.Selection.Start = this.oEdit.SelStart

this.oWord.Selection.End = this.oEdit.SelStart + this.oEdit.SelLength

this.oWord.Selection.Range.Select

DOEVENTS

 

THIS.oBrowser.Visible = .t.

 

RETURN .t.

 

This code is part of a class that essentially handles two way editing and data exchange with a textbox. The control (a Container)  receives an EditBox and the container then overlays this Editbox with the Web Browser control hosting Word. When focus is lost the the control writes the output back into the textbox, matching the selections and cursor locations etc.

 

The code above requires that you pass a document. Word loaded into the browser needs a Word document to start with, even if you’re only interested in the text typed into Word (as I am in Help Builder). This means no matter what, you need to load some sort of document and I have an empty template document that I use for this purpose. I copy this document to a temporary location and then load the document with this method. I can optionally pass in a second parameter which is the text that gets loaded into the editing document. lcText gets set at the very end.

 

Note the code to load the document: It navigates the browser to the temporary document, then waits for the document to become ready. This is tricky and you need to make sure that you use DOEVENTS extensively while polling for the Browser’s ReadyState property to get to 4. The WaitForReadyState() method provides this functionality and is outlined in the article mentioned earlier.

 

Once the document is loaded you can get a reference to the active document which is an instance of the Word.Document COM interface. From there you can Word.Application with Document.Application, which gives you access to the entire Word document model. The code that follows customizes the look and feel of Word a bit to match what I need in Help Builder.

 

Specifically I want to run in Web View which is most similar to an EditBox control. You also want to hide some toolbars – the Reviewing bar always pops up by default, but this toolbar is not used for editing. You can hide all toolbars if you choose, but be aware that resizing the browser can cause some of the toolbars to pop back up…

 

Finally I go and set the text of the control and match it to the text in the Edit box. I also pick up the selection of the EditBox and map it over into the Word document so the doc pops up in the same cursor position.

 

Once that’s done you’re ready to start editing text…

 

To do data exchange you can now call the SaveText() method manually:

 

FUNCTION SaveText()

 

IF TYPE("THIS.oDoc") = "O"

   this.Value = THIS.oDoc.Content.Text

   IF !ISNULL(THIS.oEdit )

      this.oEdit.Value = this.Value

      DOEVENTS

      this.oEdit.SelStart = this.SelStart

      this.oEdit.SelLength = this.SelLength

   ENDIF

ENDIF

 

this.Value = ""

 

The control exposes a value property which contains the value from the Word document. At any point you can call SaveText to retrieve the Word documents content and also update the selection points in the edit control.

 

This behavior can also be Auto-Triggered when the control looses focus. By default in Help Builder the control is set up to ExitOnLostFocus() so that when you click on another control or the form the control releases and updates the underlying edit control.

 

FUNCTION LostFocus()

 

IF this.lExitOnLostfocus

  *** Switch back to EditControl view

  THIS.SetViewMode(1)

ELSE

   *** Otherwise just save the text

   THIS.SaveText()

ENDIF

 

 

To make life easier when switching Views there’s SetViewMode() method that handles swapping the EditBox and Word interfaces:

 

FUCNTION SetViewMode(lnViewMode)

 

IF lnViewMode = 2

   LOCAL loBrowser

   THIS.AddObject("oBrowser","wwbrowser_4")

 

   loBrowser = this.oBrowser

 

   *** Resize into the container control

   loBrowser.Left = 0

   loBrowser.Top = 0

   loBrowser.Height = this.Height

   loBrowser.Width = this.Width

   loBrowser.Anchor = 15

   DOEVENTS

 

   *** Force a resize to occur

   THIS.Width = this.Width

   DOEVENTS

 

   this.oEdit.Visible = .f.  && Hide the EditBox

  

   loBrowser.Visible = .t.  && Make the browser visible

   this.Visible = .t.

   this.SetFocus()

 

   IF !EMPTY(this.cInternaldocument)

       this.Loaddocument(this.cInternalDocument,;

             IIF(!ISNULL(this.oEdit),this.oEdit.Value,""))

   ENDIF

  

    IF TYPE("THISFORM.nWordEditMode") = "N"

      THISFORM.nWordEditMode = 1  && Into Word Mode

   ENDIF

ELSE

    IF TYPE("THISFORM.nWordEditMode") = "N"

      THISFORM.nWordEditMode = 0  && No Word/Text Mode

   ENDIF

   THIS.Savetext()

 

   this.RemoveBrowser()

   this.Visible = .f.

  

   DOEVENTS

   this.oEdit.Visible = .t.

ENDIF

 

Notice that this code actually adds and deletes an instance of the browser. It does this because the Web Browser control is finicky in some ways and I had some problems from keeping the UI working properly when the Web Browser control was hidden. From time to time it would simply pop up ontop of the text box, or would cause the textbox to not be editable. The workaround was to remove the control completely.

 

Removing the browser or exiting the document is also a bit tricky. The problem is that Word hosted in the browser uses the underlying document for editing. Since you’ve essentially made changes to the document when you try to move off the document or close /remove the browser, Word wants to prompt you to save. So rather than the prompt, we can fake out Word by saving our document first, then navigating to a blank page, before actually removing the browser. The process looks like this:

 

FUNCTION RemoveBrowser()

THIS.Visible =.t.

 

IF TYPE("this.oBrowser") = "O"

   *** Must save so we get no dialog

   IF !ISNULL(this.oDoc)

      this.oDoc.Save()

   ENDIF

   *** Must navigate off

   this.oBrowser.Navigate("about:blank")

   this.oBrowser.WaitForReadyState()

ENDIF  

 

IF !ISNULL(this.oDoc)

   THIS.oDoc = .null.

ENDIF

 

DOEVENTS

 

IF !ISNULL(this.oWord)

   THIS.oWord = .NULL.

ENDIF

 

IF TYPE("this.oBrowser") = "O"

   this.RemoveObject("obrowser")

ENDIF

 

 

FUNCTION Destroy()

 

IF !ISNULL(THIS.oEdit)

   THIS.oEdit.visible = .t.

   THIS.oEdit = .null.  && Clear the reference

ENDIF

 

this.RemoveBrowser()

 

DOEVENTS

 

IF THIS.ldeletedocument

   LOCAL llError, lnX

   llError = .T.

   lnX=0

   DO while llError AND lnX < 10

      TRY

         ERASE (this.cinternaldocument)

         llError = .f.

      CATCH

         llError = .t.

      ENDTRY

      DOEVENTS

      WAIT WINDOW "" TIMEOUT .3

      lnX = lnX + 1

   ENDDO

ENDIF

 

This code makes very sure that all object reference are released. This is important or else Word may not completely shut down.

 

The control also has a property for lDeleteDocument which when true deletes the document that was created when done editing. The idea being that you want to have a temporary file on disk for editing using a unique name (in case you have more than a single instance of the control on a form editing documents at the same time). If true Destroy code deletes the temporary file.

 

Although this code is full of a few odd ‘hacks’ to make the browser and Word behave properly I find that this works actually really well. The process of managing this ‘hot swapping’ of controls in the UI is a bit of work, but quite doable. In fact, Help Builder already supports this overlay mechanism for the HTML Edit control and this interface works of the same concepts.

 

Help Builder had similar Word integration in previous versions for spell checking. Previously the Spell checker would bring up Word.Application as a COM object externally and then manipulate the document the same way. While that’s much easier than this integration into a form, the in-form approach is much more intuitive and provides access to all the of the editing features that Help Builder provides such as image capture/embedding and easy cross linking. This only makes sense in a form based interface and wouldn’t really work in an external interface.

 

While the solution I show above is a bit implementation specific and focused on exchanging data with an EditBox you can use the same logic for direct access or for simply embedding and editing/managing saving a Word document in your own applications. Check it out…


The Voices of Reason


 

Gabe
January 13, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Really cool. Good hack!

# RE: Embedding Microsoft Word as a control into Desktop Forms

Since you are embedding the browser control, why don't you just use the WYSIWYG edit feature of the browser? It's very easy to do and allows you full access to the source of the document as HTML (run it through SGML reader and you've got XHTML transitional).

This is good stuff!

Rick Strahl
January 13, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Mike, I already have support for HTML editing in there, but it's flakey at best. There are two issues with it: IE's edit support is difficult to implement if you do anything beyond what the browser natively supports (namely injecting your own markup and dealing with document containership) and the fact that Help Builder essentially works with a interpreted HTML implementation for editing to make it easy to work with text (so rather than pure HTML, Help Builder deals with things like line breaks displaying markup text as text etc. Converting back and forth is not really possible especially since IE thrashes the source when it goes into edit mode (if it didn't - that would fix all of my problems!).

IE's support for editing (either in the DOM or via the DHTML edit control) is very spotty at best too. The main problem is that it's really difficult to handle markup containership. For example, if you're in a cell in a table, doing the UI to continue outside of the table if the table is the last thing on the page is very difficult through the Html Edit interface, unless you hand edit the HTML. Heck it doesn't even work in the VS editor and is difficult even in FrontPage.

I have the basics working well, but to go beyond that some SERIOUS work is required and I fear even if I did do that it would never work perfectly.

So the support is in there with a disclaimer in the docs <g>. It's one way - once you edit HTML WYSIWYG it converts to plain HTML and stays that way - it doesn't go back to the 'formatted HTML' Help Builder uses.

I may look at this again shortly because this Word embedding has given me a few ideas how to switch into the rich edit mode more reliably which has been one of the issues with it as well.

jeffp
January 15, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Awesome Rick.

What you have done has given me a solution on a problem I have been fiddling around with for awhile.

In addition to Word, I want to try something similar for Visio HTML output.

Bernard Bout
January 25, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

As usual, clear, informative and really practical.

The Best.

Thanks Rick.

Rick Strahl's WebLog
January 28, 2005

# Integrating Word Spell Checking for Text and HTML

Here's a quick tip on how to use Word for Spell checking Text and HTML in your apps.

Scott
February 04, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Excellent article! I'm writing a C# app to analyze Word docs and this is exactly what I needed to get started. Thanks!

Jenny Garcia
March 03, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms


hello,

I need to apply the code that you gave but in javascript

it is possible?

it's urgent

thanks!!!!

Rick Strahl
March 03, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Given the right security in IE, yes you can do this with JavaScript in the browser. But remember Word is required on the client and the user must allow ActiveX usage.

A. de Vos
March 03, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Hello,
Really a create article also i was looking for a solution. I've now only one other problem: I want to display de menu bar of word in the browser but it don't show it self when I set the visible property of the menu bar to True.

Is there also a workaround for?

Arco

sisank
April 05, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Hello,

I am newbie to Asp.Net technology.
I like to know, is it possible to create ASP.Net Server contorl using your example above, so that I can host on IE.


WayneL
June 02, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Did anyone figure out how to do this using Javascript and are there any examples?

Thanks!

WayneL
June 02, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Rick,

Below is the Javascript code in my html to launch MS Word. My only problem is that Word is running externally and not within my browser application.

Is there any way you or anyone could help?

<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
// Your Code Here
var wdApp = new ActiveXObject("Word.Application");

wdApp.CommandBars("Standard").Visible = true;
wdApp.CommandBars("Formatting").Visible = true;
wdApp.CommandBars("Reviewing").Visible = false;
wdApp.Visible = true;


-->
</SCRIPT>

Thanks,
Wayne

Mishel
June 19, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

hi i couldnt call Microsoft Word into Html How can Call it with Menu?

James
June 21, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms - Hiding/Showing toolbars

Great article.

Only problem is the hiding and showing of Word toolbars. I just can not do it programmatically. If anyone has a work around please email me.

Thanks

Dave
July 27, 2005

# how to make display Microsoft Word in no-editable

hi, if a word doc is loaded in to webbrowser control, how to make the doc not to be editable?
thanks!

Andy
September 20, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

I just wondered if you could get word to open with a zoom set to 80%?

suresh
November 07, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

How Can i write data from a jsp page in to new word document?

i am using the below code. but i need to insert data in to new document.pls suggest me.

var Fname=window.document.wrd.fname.value;
var Lname=window.document.wrd.lname.value;

if ((Fname!="")&&(Lname!=""))
{
var word = new ActiveXObject("Word.Document");

var doc = word.documents.open("C/Tc.doc");


doc.BookMarks("FName").range.InsertBefore(Fname);
doc.BookMarks("LName").range.InsertBefore(Lname);
word.visible=true;
}

Val Wolinski
November 14, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Rick,
Do you think your code could be adapted for use in a Access VBA or VisualBasic.NET form? My wife is a teacher and I'm trying to develop a database memory bank application with her chosen word doc in a subform or suchlike placed in the middle of the screen. Cant find much in MS knowledge base and so far have only found your articles. thanks
Val

Dev
November 24, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Hey Rick

I have been trying to work with Office applications in IE. Although I have achieved the same through ActiveX Control, I want to be able to opent he document normally within the browser and show the office document toolbar embedded with IE toolbar. Havent had a luck with this so far. I am using asp.net with vb as code behind. Any help would be greatly appreciated

Thanks
Dev

Scott
November 29, 2005

# re: Embedding Microsoft Word as a control into Desktop Forms

Hey Rick,

This looks great. I'm in the group that is trying to get this to work with a JSP. Have you or anybody else been able to get it to work? If so, can you please forward the example to me.

Thanks,

Scott

mishel
January 30, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

Hi
How can i control word ( edit ) in Html or Php ?


thanks.

SONU
February 08, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

IS THIS SAME THING IS POSSIBLE USING ASP.NET

Brianlala
February 19, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

Hi, Rick. I'm using this method to open word document in VFP 8.0. I embedded the webbrowser control to a pageframe. When the page is changed to another, the toolbar of the word doc inside the webbrowser control reset to the original setting. And also, when I set the webbrowser's visible to False, it hides normally. The problem is when I set it's visible to true again, it still hides. Is there any workaround for this problem???

Brianlala
February 20, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

Hi, Rick

I fixed the previous problem by setting the initial visible property to false.

I would like to know how can I avoid the download prompt to be shown when navigate to the word file?

Anyone can help?

Rick Strahl
February 20, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

You can't automate the download dialog. It's a security setting that the user has to approve.

User has to click on the 'always open in browserload' checkbox once - after that Word displays without prompting.

Dirk Brocker
February 22, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

Hello,

is it possible to integrate Microsoft Word as Control in a Windows Forms Aplication.

Ideas, examples, hints etc. to this address:
cottonface@t-online.de

Best Regards,
Dirk

Pragati
April 24, 2006

# re: Embedding Microsoft Word as a control into ASP.net

Is this possible that we can Embedded Microsoft Word as a control into ASP.net...?

Rick Strahl
April 24, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

Maybe - you'd have to load the Word doc into a separate frame or IFRAME and then automate it with JavaScript. Somehow I think this isn't going to go well due to security concerns. Certainly you won't be able to save documents to disk which is partially what the code above is based upon.


Afzal
July 27, 2006

# re: Embedding Microsoft Word as a control into Desktop Forms

Interesting. Any comments on the "Browse in Same Window" problem? When unchecked, navigating to a word doc pops up word from the WebBrowser control rather than showing it in-place.

Rakesh N. Bhavsar
February 19, 2008

# re: Embedding Microsoft Word as a control into Desktop Forms

Hi Sir,
we want a to insert a particular text(key) into the word doc which is read only through ASP.NET. This is a unique key for that file(only msdoc file).
So, Can i make that key read only. Any one can add some data into it but can'not edit this key(or text).

hope you reply!
Rakesh
Mechsoft, Pune

Brady
April 01, 2008

# re: Embedding Microsoft Word as a control into Desktop Forms

Way cool.... I noticed that this is from 2005 is this still the best way to handle word in a form? Have you found any other method that works better?

thanks
Brady

Brady
April 02, 2008

# re: Embedding Microsoft Word as a control into Desktop Forms

FYI

I was adopting this to a VB.NET forms based applicatin and ran into a problem. The webControl.document as not returning a reference to the document.

I discovered that the problem is that this does not appear to work with the system.windows.forms.webbroswer control. Which is the default webcontrol in my vs 2008 control box. I added the IE control AxSHDocVw.AxWebBrowswer which comes from the dll shdocvw.dll which I believe is an IE dll. And all seems to work as expected.

SMine
September 16, 2008

# re: Embedding Microsoft Word as a control into Desktop Forms

Pls help everyone!
There are:
1. frame in IE, at this point load Word doc. Frame in html have object and metod window, document, body, etc (by DOM).
2. I can call Word in html by javascript - use 'oDoc = new ActiveXObject("Word.Document");' - in any case in NEW window of MS Word. And in the case in question I have control on all word-object (Document, Range, etc).
I want have control of doc-file load in frame. (now I cannot - i.e. html-frame without control of word-document or word-doc (out of frame) in NEW - not for me - window with control of him, )
Do you can help me?

gordana
April 04, 2009

# re: Embedding Microsoft Word as a control into Desktop Forms

could you help me?
I developed by VB Studio .Net (framework 2.0) page using Word document (COM object).So, everything works fine on my development machine (XP - IIS 6.0 - Office 2003) using VB Studio net, but when I published to website on my local II Server (localhost), the code executes without raising any error and the winword.exe is loaded in the task manager but the GUI or the word document (where by bookmarks I added data from SQL Server) does not show up. I added high access to Word but not helps.
Thank you in advance

Anonymous
September 05, 2009

# re: Embedding Microsoft Word as a control into Desktop Forms

Really appreciate the idea. When looking for similar behavior, came across the link http://support.microsoft.com/kb/311765. This could too.

Sam
December 03, 2009

# javascript code Needed -Word activex not loading inside the page

Rick,

Somebody got same issue . Do you have solution for this problem?

Below is the Javascript code in my html to launch MS Word. My only problem is that Word is running externally and not within my browser application.



<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
// Your Code Here
var wdApp = new ActiveXObject("Word.Application");

wdApp.CommandBars("Standard").Visible = true;
wdApp.CommandBars("Formatting").Visible = true;
wdApp.CommandBars("Reviewing").Visible = false;
wdApp.Visible = true;


-->
</SCRIPT>

Thanks,
Sam

Shakeel
January 28, 2010

# Re: Directly Open particular section marked by Bookmark in Word Document upon opening

Hi Strahl,

I want to open a word document and upon opening, it should navigate directly to a bookmark. How can I do so?

Clay Takaya
March 16, 2010

# re: Embedding Microsoft Word as a control into Desktop Forms

Using this technique works pretty well although it seems like a lot of code is spent dealing with squirrelly behavior in the webbrowser object.

One problem I can't seem to lick is that the commandbars disappear when another object like a textbox or even a command button is activated. Then the commandbars can't be recovered.

Does anyone have a workaround for this?

Thanks.

Joe Holt
August 25, 2010

# re: Embedding Microsoft Word as a control into Desktop Forms

Id also like to know if theres a way to open an MS Word file with auto 70% zoom.

Thanks

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024