Saturday, November 06, 2021

Opening Word from a thread and displaying a file

I wrote eight and a half years ago (!) the following:  As I have noted, I have spent no small amount of time updating and expanding the use of email in the Occupational Psychologist's management program. Email is now sent via GMail and works very nicely ... except for one not so small problem: when one is sending an email with an attached file, the program apparently stops working for a minute or so. The solution to this problem is to send the email via a separate thread but until now I have lacked the programming knowledge to implement this.

Today I can rephrase this statement as follows:  As I have noted, output from the Occupational Psychologist's management program is frequently sent to Microsoft Word (and even more frequently to Microsoft Excel). There is one not so small problem with this: when one is running a report whose output is displayed by Word, the program apparently stops working for a minute or so. The solution to this problem is to open Word in a separate thread but until now I have lacked the programming knowledge to implement this.

I have tried this in the past but not succeeded. As it was so long ago, I have no idea what I did then, but now it was fairly simple to write the necessary code that worked the first time that I tried it! I think that I missed using CoInitialise/CoUnInitialise in the Execute procedure. The next step is to write similar code that will open Excel in a thread: there are many more places that call Excel to display data.

Here is the code:

unit Manage08at; interface uses Windows, SysUtils, Classes, MyOffice, ComObj, ActiveX, Variants; Procedure ThreadWord (const AFileName: string); implementation type TWordThread = class (TThread) private FFilename: string; procedure Execute; override; public constructor Create (const AFileName: string); reintroduce; end; constructor TWordThread.Create (const AFileName: string); begin inherited Create (False); FreeOnTerminate:= True; FFilename:= afilename; end; procedure TWordThread.Execute; var wrdApp, wrdDoc, wrdSel: variant; begin CoInitialize (nil); wrdApp:= GetWordObject; wrdDoc:= wrdApp.Documents.Add (wrdApp.Options.DefaultFilePath[wdUserTemplatesPath] + '\q400.dot'); wrdDoc.Select; wrdSel:= wrdApp.Selection; wrdSel.InsertFile (ffilename); deletefile (ffilename); wrdSel.WholeStory; wrdSel.Font.Name:= 'Arial'; wrdSel.Font.Size:= 11; wrdSel.homekey (wdStory); wrdapp.visible:= true; wrdSel:= unassigned; wrdDoc:= unassigned; wrdApp:= unassigned; CoUnInitialize; end; Procedure ThreadWord (const AFileName: string); begin TWordThread.Create (AFileName); end; end.
The only thing that is personal development in this code is the MyOffice unit that includes a procedure called GetWordObject that opens an instance of Word.

No comments: