简体   繁体   English

从 Delphi 操作 MS Word 打开对话框

[英]Manipulating MS Word Open Dialog from Delphi

Every time I run this code, I manually confirm that I want to convert "PDF Files".每次运行此代码时,我都会手动确认我要转换“PDF 文件”。

Is there any way to automate it?有没有办法让它自动化?

procedure TFWordAnalyzer.Button1Click(Sender: TObject);
var
  Clipboard:TClipboard;
  WordApp,WordDocument: OleVariant;
begin
  try
    WordApp := GetActiveOleObject('Word.Application');
  except
    WordApp := CreateOleObject('Word.Application') ;
 end;

  WordApp.visible := true;
  WordApp.DisplayAlerts := False;

  WordDocument := WordApp.Documents.Open('D:\Corpus\Adyg\Hudmir.pdf', true, false);

  WordDocument.range.copy;

          sleep(1000);//Otherwise it fails
          RichEdit1.Clear;
          RichEdit1.PasteFromClipboard;

  WordDocument.close;
  WordApp.Quit;
  WordApp := Unassigned;
end;

在此处输入图片说明

Both of the problems you have mentioned namely how to avoid the Convert File dialog and the pop-up prompt about saving data copied to the Clipboard can by avoided by specifiying the correct values in calls to Word's automation.您提到的两个问题,即如何避免“转换文件”对话框和有关保存复制到剪贴板的数据的弹出提示,都可以通过在对 Word 自动化的调用中指定正确的值来避免。

1. Avoiding the Convert File dialog 1. 避免转换文件对话框

Update the line of your code which opens the document to更新打开文档的代码行

WordDocument := WordApp.Documents.Open('D:\Corpus\Adyg\Hudmir.pdf', ConfirmConversions := False);

This should open the document without the Confirm Conversion dialog being invoked.这应该会在没有调用确认转换对话框的情况下打开文档。

Assuming that works, you should be able to reinstate your second and third arguments, so that you have假设有效,您应该能够恢复您的第二个和第三个参数,以便您有

WordDocument := WordApp.Documents.Open('D:\Corpus\Adyg\Hudmir.pdf', true, false, ConfirmConversions := False);

Note that the syntax注意语法

WordApp.Documents.Open([...], ConfirmConversions := False)

was added at the same time (in D2) at the same time as OLE automation via OleVariants, to support optional arguments being passed to automation calls.通过 OleVariants 与 OLE 自动化同时(在 D2 中)添加,以支持传递给自动化调用的可选参数。

PS: With this change, you may find that your call to Sleep in unnecessary. PS:有了这个变化,你可能会发现你对 Sleep 的调用是不必要的。 I say "may" because my test code did not need it in the first place.我说“可能”是因为我的测试代码一开始就不需要它。

2. Avoiding the prompt to save the contents of the Clipboard. 2. 避免提示保存剪贴板的内容。

This prompt pops if you attempt to close Word using automation when you have copied a large amount of data to the Clipboard.如果您在将大量数据复制到剪贴板后尝试使用自动化关闭 Word,则会弹出此提示。

To avoid it, simply replace为了避免它,只需更换

WordApp.Quit;

by经过

WordApp.Quit(SaveChanges := False);

That should be all you need.这应该就是你所需要的。 The fact that this works is slightly counter-intuitive: As you saved the data from your WordDocument, you might expect that using WordDocument is the way to clear the Clipboard data (see the now-superfluous update below).这样做有点违反直觉:当您从 WordDocument 保存数据时,您可能希望使用 WordDocument 是清除剪贴板数据的方法(请参阅下面现在多余的更新)。 However, by setting up a test app with a number of checkboxes which control the parameter values for WordDocument.Close and WordApp.Close, and testing the various permutations of their settings, I established that only the value of SaveChanges passed to WordApp.Quit influences this behaviour and avoids the dialog (if it would otherwise have been displayed).但是,通过设置带有多个复选框的测试应用程序,这些复选框控制 WordDocument.Close 和 WordApp.Close 的参数值,并测试其设置的各种排列,我确定只有传递给 WordApp.Quit 的 SaveChanges 值会影响这种行为并避免对话框(如果它本来会被显示)。

The remainder of this answer can be disregarded but I have let it remain aas it may help future readers with similar problems.这个答案的其余部分可以忽略,但我让它保留下来,因为它可能会帮助未来遇到类似问题的读者。 I have also added the VBA tag to the q, as I found numerous questions about how to avoid the Clipboard-save prompt in VBA questions, but none with a definitive solution which worked with the code here.我还在 q 中添加了VBA标签,因为我发现了许多关于如何避免 VBA 问题中的剪贴板保存提示的问题,但没有一个明确的解决方案可以与此处的代码一起使用。

+++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++

Update The OP reported that the above code can result in a prompt from Word as it closes down saying that there is a large amount of data on the Clipboard, and queried whether it was possible to automate responding to the prompt.更新OP 报告说,上述代码可能会导致 Word 在关闭时提示剪贴板上有大量数据,并询问是否可以自动响应提示。

Google found several suggestions for avoiding the prompt, but I found that none of them worked reliably working with a 17Mb .Pdf file. Google 找到了一些避免提示的建议,但我发现它们中没有一个可以可靠地处理 17Mb .Pdf 文件。 The method shown below, which I arrived at by experiment, does seem to work reliably but is not as simple as I would like it to be.如下图所示的方法,我在通过实验来了,似乎可靠地工作,但不是那么简单,因为我想它是。

The reason the prompt occurs is that Word evidently sets up internal pointers to the contents provided to the Clipboard, so I wondered if setting the text of the Range to something much smaller and then discarding it before closing the document would work.出现提示的原因是 Word 显然设置了指向提供给剪贴板的内容的内部指针,所以我想知道将 Range 的文本设置为小得多的内容,然后在关闭文档之前将其丢弃是否可行。 I ran into 2 problems:我遇到了两个问题:

  • calling vRange.End := 1 had no effect调用 vRange.End := 1 没有效果

  • trying to call vRange.Set_Text := ' ' provoked an exception claiming that vRange does not support the Set_Text method despite the fact that the Range interface in the Word2000.Pas import unit for MS Word clearly does.试图调用 vRange.Set_Text := ' ' 引发了一个异常,声称 vRange 不支持 Set_Text 方法,尽管事实上 MS Word 的 Word2000.Pas 导入单元中的 Range 接口显然支持。 So, the code below picks up the Range object contained in the vRange variant and calls Set_Text on that.因此,下面的代码选取包含在 vRange 变体中的 Range 对象,并在其上调用 Set_Text。 This works but means that you need to add Word2000.Pas (or one of the more recent Word import units) to the Uses clause.这有效,但意味着您需要将 Word2000.Pas(或较新的 Word 导入单元之一)添加到 Uses 子句。

Note that I removed the call to GetActiveOle object to avoid an exception being raised when it failed, which disrupted debugging.请注意,我删除了对 GetActiveOle 对象的调用,以避免在失败时引发异常,从而中断调试。

procedure TForm1.Button1Click(Sender: TObject);
var
  Clipboard:TClipboard;
  WordApp,
  WordDocument: OleVariant;
  vRange : OleVariant;
  iRange : Range;  //  or WordRange for D10.3.1+
begin
  try
    WordApp := CreateOleObject('Word.Application') ;
    WordApp.visible := true;
    WordApp.DisplayAlerts := False;

    try
      WordDocument := WordApp.Documents.Open('D:\aaad7\aaaofficeauto\test.pdf', ConfirmConversions := False); //, true, false);

      vRange := WordDocument.range;
      Label1.Caption := IntToStr(vRange.Start) + ':' + IntToStr(vRange.End);
      vRange.copy;

      sleep(1000);//Otherwise it fails
      RichEdit1.Clear;
      RichEdit1.PasteFromClipboard;

      //  vRange.Set_Text(' ');  // This provokes a "Method Set_Text not supported by automation object" exception
      //  SO ...
      //  Pick up the Range interface contained in the vRange variant
      iRange := IDispatch(WordDocument.range) as Range;
      // and call Set_Text on it to set the Range's text to a single space
      iRange.Set_Text(' ');
      //  Clear the iRange interface
      iRange := Nil;

      finally
        //   beware that the following discards and changes to the .Pdf
        //   so if you want to save any changes, you should do it
        //   before calling iRange.Set_Text
        WordDocument.close(False, False, False);
        WordDocument := UnAssigned;
      end;
  finally
    WordApp.Quit(False, False, False);
    WordApp := Unassigned;
  end;
end;

Tested with MS Word 2010 on Windows 10 64-bit/在 Windows 10 64 位/上用 MS Word 2010 测试

Here is the working code:这是工作代码:

procedure TFWordAnalyzer.Button5Click(Sender: TObject);
var
  Clipboard:TClipboard;
WordApp,
WordDocument: OleVariant;
vRange : OleVariant;
iRange : WordRange;

begin

try
WordApp := CreateOleObject('Word.Application') ;
WordApp.visible := true;
WordApp.DisplayAlerts := False;

try
  WordDocument := WordApp.Documents.Open('D:\Corpus\Adyg\Hudmir.pdf', ConfirmConversions := False); //, true, false);

  vRange := WordDocument.range;
  Label1.Caption := IntToStr(vRange.Start) + ':' + IntToStr(vRange.End);
  vRange.copy;

  sleep(1000);//Otherwise it fails
  RichEdit1.Clear;
  RichEdit1.PasteFromClipboard;
  iRange := IDispatch(WordDocument.range) as WordRange;
  iRange.Set_Text(' ');
  iRange := Nil;

  finally

    WordDocument.close(False, False, False);
    WordDocument := UnAssigned;
  end;
 finally
   WordApp.Quit(False, False, False);
   WordApp := Unassigned;

 end;

  end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在文件打开时禁止MS Word中的对话框警告 - suppress dialog warnings in MS Word on file open 使用VBA MS-Word打开包含所选单词的搜索对话框 - Open search dialog with a selected word with VBA MS-Word 如何使用 VBA 或 AppleScript 在 MS Word 中打开显示 SharePoint 在线位置的“另存为”对话框? - How to open a Save As dialog in MS Word showing SharePoint Online Locations by using VBA or AppleScript? 使用VBA从MS Word打开Excel文档 - Open an Excel document from MS Word Using VBA 我应该如何从 MS Word VBA 打开 Excel 工作簿 - How should I open an Excel Workbook from MS Word VBA Delphi 7.0 DBGrid Ms-Word 超链接 - Delphi 7.0 DBGrid Ms-Word Hyperlink MS Word:基于复选框值处理书签文本值 - MS Word: Manipulating bookmark text values based on checkbox values 带有过滤器的MS Word SaveAs File对话框 - MS Word SaveAs File Dialog with filters MS Word VBA 选择要从文件夹路径打开的任何单词文件进行复制/粘贴 - MS Word VBA to select any word file to open from folder path for copy/paste 使用 Office 自动化从 Delphi 打开文档时,为什么 Document_Open 宏不在 Word 中运行 - Why does the Document_Open Macro not run in Word when opening the document from Delphi using Office Automation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM