繁体   English   中英

从 Delphi 操作 MS Word 打开对话框

[英]Manipulating MS Word Open Dialog from Delphi

每次运行此代码时,我都会手动确认我要转换“PDF 文件”。

有没有办法让它自动化?

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;

在此处输入图片说明

您提到的两个问题,即如何避免“转换文件”对话框和有关保存复制到剪贴板的数据的弹出提示,都可以通过在对 Word 自动化的调用中指定正确的值来避免。

1. 避免转换文件对话框

更新打开文档的代码行

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

这应该会在没有调用确认转换对话框的情况下打开文档。

假设有效,您应该能够恢复您的第二个和第三个参数,以便您有

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

注意语法

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

通过 OleVariants 与 OLE 自动化同时(在 D2 中)添加,以支持传递给自动化调用的可选参数。

PS:有了这个变化,你可能会发现你对 Sleep 的调用是不必要的。 我说“可能”是因为我的测试代码一开始就不需要它。

2. 避免提示保存剪贴板的内容。

如果您在将大量数据复制到剪贴板后尝试使用自动化关闭 Word,则会弹出此提示。

为了避免它,只需更换

WordApp.Quit;

经过

WordApp.Quit(SaveChanges := False);

这应该就是你所需要的。 这样做有点违反直觉:当您从 WordDocument 保存数据时,您可能希望使用 WordDocument 是清除剪贴板数据的方法(请参阅下面现在多余的更新)。 但是,通过设置带有多个复选框的测试应用程序,这些复选框控制 WordDocument.Close 和 WordApp.Close 的参数值,并测试其设置的各种排列,我确定只有传递给 WordApp.Quit 的 SaveChanges 值会影响这种行为并避免对话框(如果它本来会被显示)。

这个答案的其余部分可以忽略,但我让它保留下来,因为它可能会帮助未来遇到类似问题的读者。 我还在 q 中添加了VBA标签,因为我发现了许多关于如何避免 VBA 问题中的剪贴板保存提示的问题,但没有一个明确的解决方案可以与此处的代码一起使用。

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

更新OP 报告说,上述代码可能会导致 Word 在关闭时提示剪贴板上有大量数据,并询问是否可以自动响应提示。

Google 找到了一些避免提示的建议,但我发现它们中没有一个可以可靠地处理 17Mb .Pdf 文件。 如下图所示的方法,我在通过实验来了,似乎可靠地工作,但不是那么简单,因为我想它是。

出现提示的原因是 Word 显然设置了指向提供给剪贴板的内容的内部指针,所以我想知道将 Range 的文本设置为小得多的内容,然后在关闭文档之前将其丢弃是否可行。 我遇到了两个问题:

  • 调用 vRange.End := 1 没有效果

  • 试图调用 vRange.Set_Text := ' ' 引发了一个异常,声称 vRange 不支持 Set_Text 方法,尽管事实上 MS Word 的 Word2000.Pas 导入单元中的 Range 接口显然支持。 因此,下面的代码选取包含在 vRange 变体中的 Range 对象,并在其上调用 Set_Text。 这有效,但意味着您需要将 Word2000.Pas(或较新的 Word 导入单元之一)添加到 Uses 子句。

请注意,我删除了对 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;

在 Windows 10 64 位/上用 MS Word 2010 测试

这是工作代码:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM