📄 ole.htm
字号:
<!-- This document was created with HomeSite v2.5 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>UDDF - OLE</TITLE>
<META NAME="Description" CONTENT="OLE section of the Delphi Developers FAQ" >
<META NAME="Keywords" CONTENT=" ">
</HEAD>
<BODY bgcolor="#FFFFFF">
<CENTER>
<IMG SRC="../images/uddf.jpg"> </CENTER>
<HR SIZE="6" color="#00FF00">
<CENTER><FONT SIZE="7" FACE="Arial Black" COLOR="#FF0000">Object Linking Embeded</FONT></CENTER>
<P><H1><A NAME="ole0">Delphi 2.01 / MS Office 97 / OLE / VB for Applications</P></A></H1>
<P><I>From: "Jill Marquiss"</I></P>
This answers those really interesting questions of
<LI> How do you know whether word8 is installed?
<LI> Where are the templates?
<LI> Why do I keep getting a new instance when I didn't want one?
<LI> Where the heck is the document the user was typing on?
<LI> Why does word end when my procedure ends?
<LI> How about that Outlook - how do I get to the folders?
<LI> How to make a simple contact and how to fish for an existing contact?
<HR><PRE>{--------------------Straight from the type library--------------- WORDDEC.INC}
Const
// OlAttachmentType
olByValue = 1;
olByReference = 4;
olEmbeddedItem = 5;
olOLE = 6;
// OlDefaultFolders
olFolderDeletedItems = 3;
olFolderOutbox = 4;
olFolderSentMail = 5;
olFolderInbox = 6;
olFolderCalendar = 9;
olFolderContacts = 10;
olFolderJournal = 11;
olFolderNotes = 12;
olFolderTasks = 13;
// OlFolderDisplayMode
olFolderDisplayNormal = 0;
olFolderDisplayFolderOnly = 1;
olFolderDisplayNoNavigation = 2;
// OlInspectorClose
olSave = 0;
olDiscard = 1;
olPromptForSave = 2;
// OlImportance
olImportanceLow = 0;
olImportanceNormal = 1;
olImportanceHigh = 2;
// OlItems
olMailItem = 0;
olAppointmentItem = 1;
olContactItem = 2;
olTaskItem = 3;
olJournalItem = 4;
olNoteItem = 5;
olPostItem = 6;
// OlSensitivity
olNormal = 0;
olPersonal = 1;
olPrivate = 2;
olConfidential = 3;
// OlJournalRecipientType;
olAssociatedContact = 1;
// OlMailRecipientType;
olOriginator = 0;
olTo = 1;
olCC = 2;
olBCC = 3 ;
Const
wdGoToBookmark = -1;
wdGoToSection = 0;
wdGoToPage = 1;
wdGoToTable = 2;
wdGoToLine = 3;
wdGoToFootnote = 4;
wdGoToEndnote = 5;
wdGoToComment = 6;
wdGoToField = 7;
wdGoToGraphic = 8;
wdGoToObject = 9;
wdGoToEquation = 10;
wdGoToHeading = 11;
wdGoToPercent = 12;
wdGoToSpellingError = 13;
wdGoToGrammaticalError = 14;
wdGoToProofreadingError = 15;
wdGoToFirst = 1;
wdGoToLast = -1;
wdGoToNext = 2; //this is interesting
wdGoToRelative = 2; //how can these two be the same
wdGoToPrevious = 3;
wdGoToAbsolute = 1;
</PRE><HR>
These are basic functions <p>
<HR><PRE>Function GetWordUp(StartType : string):Boolean;
Function InsertPicture(AFileName : String) : Boolean;
Function InsertContactInfo(MyId : TMyId; MyContId : TMyContId): Boolean;
Function GetOutlookUp(ItemType : Integer): Boolean;
Function MakeOutLookContact(MyId : TMyId; MyContId : TMyContId) : Boolean;
Function ImportOutlookContact : Boolean;
Function GetOutlookFolderItemCount : Integer;
Function GetThisOutlookItem(AnIndex : Integer) : Variant;
Function FindMyOutlookItem(AFilter : String; var AItem : Variant) :Boolean;
Function FindNextMyOutlookItem(var AItem : Variant) : Boolean;
Function CloseOutlook : Boolean;
Type TTreeData = class(TObject)
Public
ItemId : String;
end;
</PRE><HR>
<HR><PRE>{$I worddec.inc} {literal crap translated from type libraries}
Var
myRegistry : TRegistry;
GotWord : Boolean;
WhereIsWord : String;
WordDoneMessage : Integer;
Basically : variant;
Wordy: Variant;
MyDocument : Variant;
MyOutlook : Variant;
MyNameSpace : Variant;
MyFolder : Variant;
MyAppointment : Variant;
Function GetWordUp(StartType : string):Boolean;
// to start word the "right" way for me
// if you start word, you own word and I wanted it to remain after I closed
var i : integer;
AHwnd : Hwnd;
AnAnswer : Integer;
temp : string;
MyDocumentsCol : Variant;
TemplatesDir : Variant;
OpenDialog1 : TopenDialog;
begin
result := false;
myRegistry := Tregistry.Create;
myRegistry.RootKey := HKEY_LOCAL_MACHINE;
// no word 8, no function
If myRegistry.KeyExists('SOFTWARE\Microsoft\Office\8.0\Word')
then
GotWord := true
Else
GotWord := false;
If GotWord then
//where the heck is it?
If myRegistry.OpenKey('SOFTWARE\Microsoft\Office\8.0', false) then
begin
WhereisWord := myRegistry.ReadString('BinDirPath');
MyRegistry.CloseKey;
end
else
GotWord := false;
If GotWord then
//where are those pesky templates?
Begin
MyRegistry.RootKey := HKEY_CURRENT_USER;
If
myRegistry.OpenKey('SOFTWARE\Microsoft\Office\8.0\Common\FileNew\SharedTemplates', false) then
Begin
TemplatesDir := myRegistry.ReadString(Nothing);
MyRegistry.CloseKey;
end
Else
Begin
Warning('Ole setup','The workgroup templates have not been setup');
GotWord := false;
end;
End;
myRegistry.free;
If not gotword then
Begin
Warning('Ole Handler', 'Word is not installed');
exit;
end;
//this is the class name for the last two versions of word's main window
temp := 'OpusApp';
AHwnd := FindWindow(pchar(temp),nil);
If (AHwnd = 0) then
//it isn't running and I don't wanna start it by automation
Begin
Temp := WhereisWord + '\winword.exe /n';
AnAnswer := WinExec(pchar(temp), 1);
If (AnAnswer < 32) then
Begin
Warning('Ole Handler', 'Unable to find WinWord.exe');
Exit;
End;
End;
Application.ProcessMessages;
{If you use Word.Application, you get your own instance}
{If you use Word.Document, you get the running instance}
{this makes a trash document (for me, anyway) and I chuck it out later}
try {and make a new document}
Basically := CreateOleObject('Word.Document.8');
except
Warning('Ole Handler', 'Could not start Microsoft Word.');
Result := False;
Exit;
end;
Try {get the app variant from that new document}
Wordy := Basically.Application;
Except
Begin
Warning('Ole Handler', 'Could not access Microsoft Word.');
Wordy := UnAssigned;
Basically := UnAssigned;
Exit;
end;
end;
Application.ProcessMessages;
Wordy.visible := false;
MyDocumentsCol := Wordy.Documents;
{If its just my throw away document or I wanted a brand new one}
If (MyDocumentsCol.Count = 1) or
(StartType = 'New') then
Begin
OpenDialog1 := TOpenDialog.Create(Application);
OpenDialog1.filter := 'WordTemplates|*.dot|Word Documents|*.doc';
OpenDialog1.DefaultExt := '*.dot';
OpenDialog1.Title := 'Select your template';
OpenDialog1.InitialDir := TemplatesDir;
If OpenDialog1.execute then
Begin
Wordy.ScreenUpdating:= false;
MyDocumentsCol := wordy.Documents;
MyDocumentsCol.Add(OpenDialog1.Filename, False);
OpenDialog1.free;
end
Else
begin
OpenDialog1.Free;
Wordy.visible := true;
Wordy := Unassigned;
Basically := Unassigned;
Exit;
end;
end
Else
{get rid of my throwaway}
MyDocument.close(wdDoNotSaveChanges);
{now I either have a new document based on a template the user selected
or I have their current document}
MyDocument := Wordy.ActiveDocument;
Result := true;
Application.ProcessMessages;
end;
Function InsertPicture(AFileName : String) : Boolean;
var
MyShapes : Variant;
MyRange : variant;
begin
Result := True;
If GetWordUp('Current')then
Try
Begin
MyRange := MyDocument.Goto(wdgotoline, wdgotolast);
MyRange.EndOf(wdParagraph, wdMove);
MyRange.InsertBreak(wdPageBreak);
MyShapes := MyDocument.InlineShapes;
MyShapes.AddPicture(afilename, false, true, MyRange);
end;
Finally
begin
Wordy.ScreenUpdating:= true;
Wordy.visible := true;
Wordy := Unassigned;
Basically := UnAssigned;
Application.ProcessMessages;
end;
end
else
Result := False;
end;
Function InsertContactInfo(MyId : TMyId; MyContId : TMyContId) : Boolean;
var
MyCustomProps : Variant;
begin
{ personally, I store stuff in document properties and then give out a
toolbar macro to allow the user to "set" the properties in their template or current
document.
this has three advantages that I know of (and no defects that I'm aware of)
1. The user can place the location of the info in the document either
before or after this function runs
2. A custom property can be placed any number of times inside the same
document
3. A user can map the properties in their Outlook or search on them using
that abismal file open in Word}
Result := true;
If GetWordUp('New')then
Try
Begin
MyCustomProps := MyDocument.CustomDocumentProperties;
MyCustomProps.add(cpId, false, msoPropertyTypeString, MyId.Id);
MyCustomProps.add(cpOrganizationName, false,
msoPropertyTypeString, MyId.OrganizationName);
MyCustomProps.add(cpAddress1, false,
msoPropertyTypeString,MyId.Address1);
MyCustomProps.add(cpAddress2, false, msoPropertyTypeString,
MyId.Address2);
MyCustomProps.add(cpCity, false, msoPropertyTypeString,
MyId.City);
MyCustomProps.add(cpStProv, false, msoPropertyTypeString,
MyId.StProv);
MyCustomProps.add(cpCountry, false,
msoPropertyTypeString,MyId.City);
MyCustomProps.add(cpPostal, false, msoPropertyTypeString,
MyId.Country);
MyCustomProps.add(cpAccountId, false, msoPropertyTypeString,
MyId.AccountId);
MyCustomProps.add(cpFullName, false, msoPropertyTypeString,
MyContId.FullName);
MyCustomProps.add(cpSalutation, false, msoPropertyTypeString,
MyContId.Salutation);
MyCustomProps.add(cpTitle, false,
msoPropertyTypeString,MyContId.Title);
If (MyContId.workPhone = Nothing) or (MycontId.WorkPhone =
ASpace) then
MyCustomProps.add(cpPhone, false, msoPropertyTypeString,
MyId.Phone )
else
MyCustomProps.add(cpPhone, false, msoPropertyTypeString,
MyContId.WorkPhone );
If (MyContId.Fax = Nothing) or (MycontId.Fax = ASpace) then
MyCustomProps.add(cpFax, false, msoPropertyTypeString,
MyId.Fax)
else
MyCustomProps.add(cpFax, false,
msoPropertyTypeString,MyContId.Fax);
If (MyContId.EMail = Nothing) or (MycontId.Email = ASpace) then
MyCustomProps.add(cpEmail, false, msoPropertyTypeString,
MyId.Email)
else
MyCustomProps.add(cpEmail, false, msoPropertyTypeString,
MyContId.Email);
MyCustomProps.add(cpFirstName, false,
msoPropertyTypeString,MyContId.FirstName);
MyCustomProps.add( cpLastName, false, msoPropertyTypeString,
MyContId.LastName);
MyDocument.Fields.Update;
end;
Finally
begin
Wordy.ScreenUpdating:= true;
Wordy.visible := true;
Wordy := Unassigned;
Basically := UnAssigned;
Application.ProcessMessages;
end;
end
Else
Result := false;
end;
Function GetOutlookUp(ItemType : Integer): Boolean;
Const
AppointmentItem = 'Calendar';
TaskItem = 'Tasks';
ContactItem = 'Contacts';
JournalItem = 'Journal';
NoteItem = 'Notes';
var
MyFolders : Variant;
MyFolders2 : variant;
MyFolders3 : variant;
MyFolder2 : Variant;
MyFolder3 : variant;
MyUser : Variant;
MyFolderItems : Variant;
MyFolderItems2 : Variant;
MyFolderItems3 : Variant;
MyContact : Variant;
i, i2, i3 : Integer;
MyTree : TCreateCont;
MyTreeData : TTreeData;
RootNode, MyNode, MyNode2 : ttreeNode;
ThisName : String;
Begin
{this is really ugly........
There is some really wierd thing going on in the object model for outlook
so excuse this folder.folder.folder stuff cause the "right way" doesn't work
for folders and this does}
{user picks folder from treeview}
Result := False;
Case ItemType of
olAppointmentItem : ThisName := AppointmentItem;
olContactItem : ThisName := ContactItem;
olTaskItem : ThisName := TaskItem;
olJournalItem : ThisName := JournalItem;
olNoteItem : ThisName := NoteItem;
Else
ThisName := 'Unknown';
End;
try
MyOutlook := CreateOleObject('Outlook.Application');
except
warning('Ole Interface','Could not start Outlook.');
Exit;
end;
{this is the root folder}
MyNameSpace := MyOutlook.GetNamespace('MAPI');
MyFolderItems := MyNameSpace.Folders;
MyTree := TCreateCont.create(Application);
{Really unfortunate, but a user can create something other than the default
folder for the kind of thing you're interested in - so this goes down a coupla
levels in the folder chain}
MyTree.Caption := 'Select ' + ThisName + ' Folder';
With MyTree do
If MyFolderItems.Count > 0 then
For i := 1 to MyFolderItems.Count do begin
MyFolder := MyNameSpace.Folders(i);
MyTreeData := TTreeData.create;
MyTreeData.ItemId := MyFolder.EntryId;
RootNode := TreeView1.Items.AddObject(nil, MyFolder.Name, MyTreeData);
MyFolders2 := MyNameSpace.folders(i).Folders;
If MyFolders2.Count > 0 then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -