1

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

但是,当我尝试分配给应用程序的 ActivePrinter 属性时,会抛出带有以下消息的 COMException:

HRESULT 异常: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

使用的打印机都被确认为已安装/在注册表中。采用 Word 应用程序类的类似函数可以正常工作。我对 COM 相关的东西还很陌生,我觉得这可能只是我与 excel 相关的无知在起作用,但是在搜索 google/stackoverflow 时我几乎找不到任何与此相关的东西,除了一两个旧的、未回答的线程。有一些与大量数据/大范围有关,但与 ActivePrinter 属性无关

编辑 - 答案的简要总结,在 M Patel 的链接中有详细说明:

Excel 对设置它的 ActivePrinter 属性很挑剔。它不仅需要打印机名称,还需要打印机和端口,例如“Fax on Ne01:”。这个端口应该可以从注册表中获得,或者在:

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

或者

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

使用链接中详述的方法,或者在我的情况下使用 Microsoft.Win32.Registry.GetValue()。后者将返回类似于“winspool,Ne01:”的内容。以“Fax on Ne01:”的方式将该字符串的最后一部分连接到打印机名称上,可以毫无例外地设置 ActivePrinter 属性。

我还应该注意到我的问题发生在 excel 2010

4

2 回答 2

2

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

使用 MS Word:-

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

但是使用 MS Excel :-

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

以下是使用 office interop 打印任何 office(MS Word、MS Excel、PS Powerpoint)文档的通用功能。

    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 时,我会更新打印机名称,如下所示。从 MS Excel 实例将打印机名称传递给上述函数时,我使用

    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) (打印到文件)检查预期的打印选项是否是 To PDF/ To XPS / FAX 等。

于 2016-02-01T15:19:58.280 回答
1

也许下面的链接会有所帮助?看起来您分配给 ActivePrinter 属性的名称的格式很重要。

http://netindonesia.net/blogs/jimmy/archive/2011/02/25/how-to-change-the-active-printer-to-specific-printer-in-excel-using-net-and-how- the-heck-can-i-find-the-right-printer-name-and-port-combination-that-excel-wants.aspx

于 2013-02-13T23:45:17.740 回答