如何使用Microsoft.Office.Interop.Word.Document.PrintOut()将docx打印到特定打印机 [英] How to print a docx to a specific printer using Microsoft.Office.Interop.Word.Document.PrintOut()

查看:208
本文介绍了如何使用Microsoft.Office.Interop.Word.Document.PrintOut()将docx打印到特定打印机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一个简单的需求,但是由于某种原因,我无法找到实现该目标的方法.我有这样的代码:

This seems like such a simple need, but for some reason I cannot find how I can accomplish this. I have code like this:

Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
MemoryStream documentStream = getDocStream();
FileInfo wordFile = new FileInfo("c:\\test.docx");
object fileObject = wordFile.FullName;
object oMissing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Word.Document doc = wordInstance.Documents.Open(ref fileObject, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);
doc.Activate();
doc.PrintOut(oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);

我需要一个配置设置驱动器,使用哪个打印机和纸盘.搜索后,我发现了Microsoft.Office.Interop.Word.Application.ActivePrinter,这是一个可设置的字符串属性,文档说它使用活动打印机的名称",但是我不知道对于打印机来说这意味着什么. 活动打印机",尤其是当我有两个的时候.如何做到这一点?

I need to have a config setting drive which printer and tray are used. After searching around I found Microsoft.Office.Interop.Word.Application.ActivePrinter which is a settable string property that the documentation says takes "the name of the active printer", but I don't know what it means for a printer to the the "Active Printer", especially when I have two of them. How can this be accomplished?

推荐答案

TL; DR 您不能使用特定的打印机进行打印.您必须将默认打印机更改为要使用的打印机.然后照常打印.

TL;DR You can't print to a specific printer. You have to change the default printer to what you want to use. Then print as normal.

自从我们在这一领域开始工作以来,情况可能发生了巨大变化,但是我们找不到任何方法可以打印到特定打印机.因此,我们要做的就是将系统的默认打印机更改为所需的打印机,在该计算机上打印所需的所有文档,然后将其更改回原来的状态. (实际上,我们放弃将其改回,因为没有别的期望任何特定的默认打印机,所以没关系).

It may be that things have changed dramatically since we first did our work in this area, but we were unable to find any way to print to a specific printer. So what we did in place of that was change the system's default printer to what we wanted, print all the documents that we wanted on that computer, then change it back to what it was before. (actually, we quit changing it back because nothing else was expecting any particular default printer, so it didn't matter).

简短答案:

Microsoft.Office.Interop.Word._Application _app = [some valid COM instance];
Microsoft.Office.Interop.Word.Document doc = _app.Documents.Open(ref fileName, ...);
doc.Application.ActivePrinter = "name of printer";
doc.PrintOut(/* ref options */);

但是,我们发现这非常不可靠!继续阅读以获取更多详细信息:

But, we found this highly unreliable! Read on for more details:

如果您还没有这样做,我强烈建议您构建自己的包装器类,以处理_Document_Application的所有普通工作.现在可能还没有现在那么糟(dynamic对我们来说不是一个选择),但这仍然是一个好主意.您会注意到,此代码中缺少某些美味的代码...我试图着重于与您所要求的代码有关的代码.同样,此DocWrapper类是代码的许多独立部分的合并-避免混乱.最后,如果您认为异常处理很奇怪(或者抛出Exception导致设计不佳),请记住,我试图将许多地方的代码部分放在一起(同时也保留了我们自己的自定义类型).阅读代码中的注释很重要.

If you haven't done so already, I heavily suggest building your own wrapper classes to deal with all the mundane work bits of _Document and _Application. It may not be as bad now as it was then (dynamic was not an option for us), but it's still a good idea. You'll note that certain delicious bits of code are absent from this ... I tried to focus on the code that is related to what you are asking. Also, this DocWrapper class is a merging of many separate parts of the code - forgive the disorder. Lastly, if you consider the exception handling odd (or just poor design by throwing Exception) -- remember I'm trying to put together parts of code from many places (while also leaving out our own custom types). Read the comments in the code, they matter.

class DocWrapper
{
  private const int _exceptionLimit = 4;

  // should be a singleton instance of wrapper for Word
  // the code below assumes this was set beforehand
  // (e.g. from another helper method)
  private static Microsoft.Office.Interop.Word._Application _app;

  public virtual void PrintToSpecificPrinter(string fileName, string printer)
  {
    // Sometimes Word fails, so needs to be restarted.
    // Sometimes it's not Word's fault.
    // Either way, having this in a retry-loop is more robust.
    for (int retry = 0; retry < _exceptionLimit; retry++)
    {
      if (TryOncePrintToSpecificPrinter(fileName, printer))
        break;

      if (retry == _exceptionLimit - 1) // this was our last chance
      {
        // if it didn't have actual exceptions, but was not able to change the printer, we should notify somebody:
        throw new Exception("Failed to change printer.");
      }
    }
  }

  private bool TryOncePrintToSpecificPrinter(string fileName, string printer)
  {
    Microsoft.Office.Interop.Word.Document doc = null;

    try
    {
      doc = OpenDocument(fileName);

      if (!SetActivePrinter(doc, printer))
        return false;

      Print(doc);

      return true; // we did what we wanted to do here
    }
    catch (Exception e)
    {
      if (retry == _exceptionLimit)
      {
        throw new Exception("Word printing failed.", e);
      }
      // restart Word, remembering to keep an appropriate delay between Quit and Start.
      // this should really be handled by wrapper classes
    }
    finally
    {
      if (doc != null)
      {
        // release your doc (COM) object and do whatever other cleanup you need
      }
    }

    return false;
  }

  private void Print(Microsoft.Office.Interop.Word.Document doc)
  {
    // do the actual printing:
    doc.Activate();
    Thread.Sleep(TimeSpan.FromSeconds(1)); // emperical testing found this to be sufficient for our system
    // (a delay may not be required for you if you are printing only one document at a time)
    doc.PrintOut(/* ref objects */);
  }

  private bool SetActivePrinter(Microsoft.Office.Interop.Word.Document doc, string printer)
  {
    string oldPrinter = GetActivePrinter(doc); // save this if you want to preserve the existing "default"

    if (printer == null)
      return false;

    if (oldPrinter != printer)
    {
      // conditionally change the default printer ...
      // we found it inefficient to change the default printer if we don't have to. YMMV.
      doc.Application.ActivePrinter = printer;
      Thread.Sleep(TimeSpan.FromSeconds(5)); // emperical testing found this to be sufficient for our system
      if (GetActivePrinter(doc) != printer)
      {
        // don't quit-and-restart Word, this one actually isn't Word's fault -- just try again
        return false;
      }

      // successful printer switch! (as near as anyone can tell)
    }

    return true;
  }

  private Microsoft.Office.Interop.Word.Document OpenDocument(string fileName)
  {
    return _app.Documents.Open(ref fileName, /* other refs */);
  }

  private string GetActivePrinter(Microsoft.Office.Interop.Word._Document doc)
  {
    string activePrinter = doc.Application.ActivePrinter;
    int onIndex = activePrinter.LastIndexOf(" on ");
    if (onIndex >= 0)
    {
      activePrinter = activePrinter.Substring(0, onIndex);
    }
    return activePrinter;
  }
}

这篇关于如何使用Microsoft.Office.Interop.Word.Document.PrintOut()将docx打印到特定打印机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆