问题
I have a program written in Delphi-7 which opens a new Word document which is based on a template.
Once the document is open, the automation jumps to a bookmark (predefined in the template) and adds some text there.
The following code works fine in Word 2003 but causes a invalid variant operation
error message in Word 2010 (I have omitted try/except
blocks for the sake of clarity).
wrdapp:= CreateOleObject ('Word.Application');
wrdDoc:= wrdapp.documents.add (wrdApp.Options.DefaultFilePath[wdUserTemplatesPath] + '1.dot'
wrdApp.selection.goto (wdGotoBookmark, unassigned, unassigned, 'B1')
If I replace the third line with
wrdDoc.bookmarks.item ('B1').select
the program works fine in Word 2003 but still crashes in Word 2010.
What is the correct code for Word 2010 to 'go to' the bookmark?
回答1:
Word 2010 has a bug that is related to loading Normal.dotm (and maybe plugins too, who knows?). When you start Word 2010 as you would normally do, you see a splashscreen and Word performs some initialization, including loading Normal.dotm. When you start Word via automation - CreateOleObject('Word.Application')
- it doesn't wait till Normal.dotm is loaded and returns immediatly. But performing operations when Normal.dotm is still being loaded seems to crash Word. What I did to solve this problem is to make a loop that just waits for the template to load. You can also choose for a delay to give Word the time to initialize, but so far, the loop works.
Something like this:
wrdapp := CreateOleObject('Word.Application');
//loop that waits for the normal template to load
while wrdapp.Templates.Count = 0 do
Sleep(200);
//continue operations
PS: I don't have Delphi available here, so the code may contain errors, but you get the idea
回答2:
I think you should replace the constants in the "GoTo_" call with variables. Like that:
...
var
vWhat, vBookmark:OleVariant;
begin
...
vWhat:=wdGoToBookmark;
vBookmark:='B1';
wrdApp.Selection.GoTo_(vWhat,emptyParam,emptyParam,vBookmark);
...
end;
回答3:
Hi I hope this help you. I am using D2010 and Office 2010
What I am doing: If I found a Bookmark name, I insert a word Document in this point
Part of my code:
try
Template := EmptyParam;
NewTemplate := true;
ItemIndex := 1;
try
Wdapplication.Connect;
except
Screen.Cursor := crDefault;
MessageDlg('No se detecta Word Puede no estar instalado(1) o versi?n incorrecta de Word', mtError, [mbOK], 0);
Abort;
result := False;
end;
Wdapplication.Visible := true; // False;
WdApplication.Caption := 'Kalemat automation';
{Turn Spell checking of because it takes a long time if enabled and slows down Winword}
WdApplication.Options.CheckSpellingAsYouType := false;
WdApplication.Options.CheckGrammarAsYouType := false;
lbInfo.Lines.Add('Word connected');
except
on E: Exception do begin
ShowMessage(E.Message);
WdApplication.Disconnect;
result := False;
Exit;
end;
end;
//-
if wdapplication.Documents.Count > 0 then begin
Screen.Cursor := crDefault;
MessageDlg(
'Por Favor cierre todos sus Word-documentos antes de proseguir...', mtWarning,
[mbRetry], 0);
wdApplication.Visible := true;
WdApplication.Disconnect;
result := False;
exit;
end
else begin
with WdApplication do begin
// OnQuit := WordAppQuit;
// OnChangeDocument := WordDocChange;
// OnOpenDocument := WordDocOpen;
// OnPreCloseDocument := WordPreClose;
// OnCloseDocument := WordDocClose;
// DisableSystemCloseBox;
end
end;
{Create new document}
Template := EmptyParam;
NewTemplate := false;
oNewDocument := ModEsc;
// abre documento
lbInfo.Lines.Add('Abriendo escritura '+ModEsc);
WdApplication.Documents.AddOld(oNewDocument, NewTemplate);
// Conecta con al instancia de Word
WdDocument.ConnectTo(WdApplication.Documents.Item(ItemIndex));
sBookMarkName := 'FPROEMIO';
lbInfo.Lines.Add('Busca marcador Proemio');
if WdDocument.Bookmarks.Exists(sBookMarkName) then begin
// ShowMessage(' -Existe: '+sBookMarkName);
owhat := wdGotoBookMark;
owhich := unAssigned;
ocount := unAssigned;
//-->>> // ShowMessage(' -Ve a..: '+sBookMarkName);
//-->>> // Ve a ese marcados addendum
wdDocument.GoTo_(oWhat, oWhich, OCount, sBookMarkName);
// ShowMessage(' GoTo_.. ya estoy en: '+sBookMarkName);
// Lo encontre
oRange := '';
oConformConv := false;
oLink := false;
oattachment := false;
fl_Name := proemi;
lbInfo.Lines.Add('Insertando Proemio '+Proemi);
if not FileExists(fl_name) then begin
Screen.Cursor := crDefault;
lbInfo.Lines.Add('No Existe Documento PROEMIO ');
MessageDlg('Documento FPROEMIO NO EXISTE, Revise el modelo de escritura', mtError, [mbRetry], 0);
end
else
wdDocument.Bookmarks.Item(sBookMarkName).Range.InsertFile(Fl_Name, oRange, oConformConv, oLink, oattachment);
// ShowMessage(' -.. inserte el addendum');
end
else begin
lbInfo.Lines.Add('No Existe Marcador PROEMIO ');
end;
来源:https://stackoverflow.com/questions/5913665/word-2010-automation-goto-bookmark