6
votes

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?

3
Just curious, if you put a 10 second wait (Sleep(10000);) between the first and second line, do you still get the error?The_Fox
Unbelievable but true! Make your comment an answer because the sleep is what made the code work. I cut the time to 5 seconds but that also worked.No'am Newman
Wait a minute... There has to be a better way than a fixed sleep interval. Of course, this approach may work in almost every instance, but there is probably a way that is guaranteed to work in every instance. One would expect something like wrdApp.WaitUntilReady...Andreas Rejbrand

3 Answers

5
votes

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

0
votes

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;
0
votes

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;