2013-02-13 4 views
1

У меня есть функция, в которую я передаю экземпляр Microsoft.Office.Interop.Excel.Application. Функция использует встроенный факсимильный принтер Windows или Microsoft XPS Document Writer для сохранения файла в виде tiff-изображения.COMException при назначении Excel.Application.ActivePrinter

Однако, когда я пытаюсь присвоить свойству 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, и у меня такое чувство, что это может быть просто мое невежество, связанное с игрой, но я не могу найти почти ничего, что связано с этим при поиске google/stackoverflow, за исключением одного или двух старых, неотвеченные темы. Есть несколько, которые связаны с большими объемами данных/больших диапазонов, но не свойство ActivePrinter

EDIT - краткое резюме ответа, подробно описано в ссылке M Патель:

Excel придирчив о настройке это ActivePrinter имущество; вместо имени принтера, он требует как принтера, так и порта, например. «Факс на Ne01:». Этот порт должен быть доступен из реестра, либо по адресу:

HKEY_CURRENT_USER \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Устройства

или

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

Используя метод, подробно описанный в ссылке, o r в моем случае с использованием Microsoft.Win32.Registry.GetValue(). Последний вернет что-то по линии «winspool, Ne01:». Объединение последней части этой строки с именем принтера в порядке «Факс на Ne01:» позволяет устанавливать свойство ActivePrinter без исключения.

Я хотел бы также отметить, что моя проблема происходила в Excel 2010

+0

проблема все еще существует в Excel 2013. И конкатенация переводится с языка пользователя в Excel. Я добавил свое решение по адресу http://stackoverflow.com/questions/29921150/c-sharp-setting-a-printer/32862651#32862651 –

ответ

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

+1

Это билет, отлично работает! И чтобы подумать, я прорычал эту точную часть реестра, но по причинам, совершенно не связанным с этой проблемой! Огромное спасибо. – dbr

2

У меня было такое же исключение при печати документ Excel с помощью первенствовать Interop.

С MS Word: -

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

Но с MS Excel: -

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

Ниже приводится общая функция для печати любого офиса (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) (Печать в файл) Проверьте, предназначена опция печати в PDF/XPS Для/FAX и т.д.

Смежные вопросы