分配给Excel.Application.ActivePrinter时发生COMException

我有一个函数,我通过一个Microsoft.Office.Interop.Excel.Application实例。 该function使用Windows内置的传真打印机或Microsoft XPS Document Writer将文件保存为tiff图像。

但是,当我尝试分配给应用程序的ActivePrinter属性时,会引发一个COMException,并显示以下消息:

来自HRESULT的exception:0x800A03EC

代码如下:

'Save the current default printer Dim strDefaultPrinter As String = excelApp.ActivePrinter 'Assign printer string constant to ActivePrinter - throws exception excelApp.ActivePrinter = FAX_PRINTER excelApp.ActiveWorkbook.PrintOutEx(, , , , , True, "c:\RestOfFilePath...") ' Print to file = true 'Reset the default printer excelApp.ActivePrinter = strDefaultPrinter 

所使用的打印机都被确认为安装在registry中。 一个类似的function,需要一个Word应用程序类工作正常。 我相当新的COM相关的东西,我有一种感觉,这可能只是我玩的相关的愚蠢无知,但我可以find几乎没有任何关于此search谷歌/ stackoverflow,除了一个或两个旧的,未答复线程。 有一些涉及到大量的数据/大范围,但不是ActivePrinter属性

编辑 – 答案的简短摘要,详见M Patel的链接:

Excel是挑剔关于设置它的ActivePrinter财产; 而不是打印机名称,它需要打印机和端口,例如“Ne01传真:”。 这个端口应该从registry中可用,

HKEY_CURRENT_USER \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Devices

要么

HKEY_LOCAL_MACHINE \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Devices

使用链接中详细的方法,或在我的情况下使用Microsoft.Win32.Registry.GetValue()。 后者将按照“winspool,Ne01:”的方式返回。 以“传真Ne01:”的方式将该string的最后部分连接到打印机名称上,允许设置ActivePrinter属性,而不会出现exception。

我也应该注意到我的问题发生在Excel 2010中

在使用excel interop打印excel文档时,我遇到了同样的exception。

用MS Word: –

 document.Application.ActivePrinter = "Brother MFC.. Printer"; // Works without exception 

但与MS Excel: –

 document.Application.ActivePrinter = "Brother MFC.. Printer"; // throws COM exception 

以下是使用Office Interop打印任何办公室(MS Word,MS Excel,PS Powerpoint)文件的一般function。

  void PrintToPrinter(dynamic app, dynamic document, string printer, int numberOfCopies) { bool PrintToFile = false; // Trying to print document without activation throws print exception document.Activate(); // The only way to change printer is to set the default printer of document or of application // Remember the active printer name to reset after printing document with intended printer oldPrinterName = document.Application.ActivePrinter; for (int retry = 0; retry < retryLimit; retry++) { try { if (!GetActivePrinter(document).Contains(printer)) { try { document.Application.ActivePrinter = printer; docPrinterChanged = true; } catch (Exception) { try { app.ActivePrinter = printer; appPrinterChanged = true; } catch (Exception) { continue; } } } object oMissing = System.Reflection.Missing.Value; document.PrintOut( true, // Background false, // Append overwrite oMissing, // Page Range oMissing, // Print To File - OutputFileName oMissing, // From page oMissing, // To page oMissing, // Item numberOfCopies, // Number of copies to be printed oMissing, // oMissing, // PrintToFile, // Print To file true // Collate ); break; } catch (Exception) { continue; } } try { if(docPrinterChanged) document.Application.ActivePrinter = oldPrinterName; else if(appPrinterChanged) app.ActivePrinter = oldPrinterName; } catch (Exception) { } } private static string GetActivePrinter(dynamic document) { string activePrinter = document.Application.ActivePrinter; if (activePrinter.Length >= 0) return activePrinter; return null; } 

在MS Excel中使用上述function时,如下所示更新打印机名称。 在从MS Excel实例将打印机名称传递给上述function时,我使用

  bool IFilePrint.PrintFile(string fullFileName, string printerName, int numberOfCopies) { // ....... Excel.Workbook document = null; try { document = this.Application.Workbooks.Open(fullFileName); } catch { document = null; } string portNumber = null; // Find correct printerport using (RegistryKey key = Registry.CurrentUser.OpenSubKey(fullFileName)) { if (key != null) { object value = key.GetValue(printerName); if (value != null) { string[] values = value.ToString().Split(','); if (values.Length >= 2) port = values[1]; } } } // Get current concatenation string ('on' in en, 'auf' in de, etc..) var split = this.Application.ActivePrinter.Split(' '); if (split.Length >= 3) printerName = String.Format("{0} {1} {2}", printerName, split[split.Length - 2], port); PrintToPrinter(this.Application, document, printerName, numberOfCopies); // ........... } catch (Exception) { } result = true; return result; } 

进一步检查可以做到这一点:

1)使用PrinterSettings类检查打印机是否存在。

2)(打印到文件)检查打印选项是否为PDF /到XPS / FAX等