and*_*rew 9 c# ms-word office-interop
这似乎是一个简单的需求,但由于某种原因,我无法找到如何实现这一目标.我有这样的代码:
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);
Run Code Online (Sandbox Code Playgroud)
我需要一个配置设置驱动器,使用哪个打印机和托盘.在搜索之后我发现了Microsoft.Office.Interop.Word.Application.ActivePrinter这是一个可设置的字符串属性,文档中说的是"活动打印机的名称",但我不知道这对打印机来说意味着什么"活动打印机",特别是当我有两个时.如何实现这一目标?
pay*_*ayo 16
TL; DR您无法打印到特定的打印机.您必须将默认打印机更改为您要使用的打印机.然后正常打印.
自从我们第一次在这个领域开展工作以来,情况可能发生了巨大的变化,但我们无法找到任何打印到特定打印机的方法.因此,我们所做的就是将系统的默认打印机更改为我们想要的,打印我们想要的那台计算机上的所有文档,然后将其更改回之前的版本.(实际上,我们退出了更改它,因为没有其他任何东西期待任何特定的默认打印机,所以它没关系).
简短回答:
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 */);
Run Code Online (Sandbox Code Playgroud)
但是,我们发现这非常不可靠!请阅读以获得更多详情:
如果你还没有这样做的话,我建议巨资建立自己的包装类来处理所有的平凡工作位_Document和_Application.它现在可能没有那么糟糕(dynamic不是我们的选择),但它仍然是一个好主意.你会注意到这里没有一些美味的代码......我试着把注意力集中在与你所要求的相关的代码上.此外,这个DocWrapper类是代码的许多独立部分的合并 - 原谅这种障碍.最后,如果你认为异常处理是奇怪的(或者通过抛出异常只是糟糕的设计) - 记住我正在尝试将来自许多地方的部分代码放在一起(同时也省略了我们自己的自定义类型).阅读代码中的注释,它们很重要.
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;
}
}
Run Code Online (Sandbox Code Playgroud)