Почему не удается установить листинг объекта из Microsoft Excel?

Попытка получить ссылку на рабочие листы (с помощью Excel interop):

Excel.Application xl = new Excel.ApplicationClass();
Excel.Workbooks xlWorkBooks = xl.Workbooks;
Excel.Workbook xlWorkBook = xlWorkBooks.Open(fileName, 0, false, 5, "", 
                      "", true, Excel.XlPlatform.xlWindows, "\t",
                      false, false, 0, true, 1, 0);

// Next line crashes
Excel.Worksheets xlWorkSheets = (Excel.Worksheets) xlWorkBook.Worksheets; 

Ошибка заключается в том, что он не может ее использовать:

Невозможно передать COM-объект типа "System.__ ComObject" в тип интерфейса "Microsoft.Office.Interop.Excel.Worksheets". Эта операция завершилась неудачно, потому что вызов QueryInterface для COM-компонента для интерфейса с IID '{000208B1-0000-0000-C000-000000000046} завершился неудачно из-за следующей ошибки: такой интерфейс не поддерживается (исключение из HRESULT: 0x80004002 (E_NOINTERFACE)).

Является ли мой листинг неправильным?

Ответ 1

Да, ваш трюк неверен.

_Workbook.Sheets дает вам Sheets экземпляр. Этот интерфейс предоставляет вам все типы листов, а не только рабочие листы; главным образом, он включает в себя диаграммы, макролисты и т.д.

С другой стороны, интерфейс Worksheets дает вам только рабочие таблицы - не диаграммы.

Интерфейсы не назначаются друг другу; поэтому вы получаете ошибку COM. Это запутанно - я даже не уверен, возможно ли получить экземпляр интерфейса Worksheets через PIA, но этот Office Interop для ya.

Пока вы используете свойство _Workbook.Worksheets вместо свойства _Workbook.Sheets, вы должны получить экземпляр Sheets, который возвращает только объекты Worksheet - несмотря на то, что интерфейс способен обеспечить другие типы листов.

Ответ 2

Согласно MSDN, Workbook.Worksheets возвращает Microsoft.Office.Interop.Excel.Sheets.

Итак, вы должны сделать это следующим образом:

Microsoft.Office.Interop.Excel.Sheets sheets = 
    (Microsoft.Office.Interop.Excel.Sheets)xlWorkBook.Worksheets

Или предполагая, что Excel отображается на Microsoft.Office.Interop.Excel (как видно из вашего вопроса)

Excel.Sheets sheets = (Excel.Sheets)xlWorkBook.Worksheets

Ответ 3

Если он работает в одной среде, но не в другом, проверьте ключи реестра HK Classes Root/TypeLib.

Возможно, вы пытаетесь запустить HKCR\TypeLib {00020813-0000-0000-C000-000000000046}\1,6 но то, что пользователь установил, добавил ключ: HKCR\TypeLib {00020813-0000-0000-C000-000000000046}\1,7 в результате чего вызов Interop генерирует исключение.

Или, если это не так, это может быть что-то в GAC из-за разных версий ОС.

У меня была эта проблема, когда она работала на наших машинах разработчика под управлением Windows 7 и вызвала эту ошибку на пользовательской машине с XP.

Ответ 4

Нечетный. Согласно эта страница, она должна быть типа Sheets not Worksheets. Не тестировали - дайте ему вихрь?

Ответ 5

Если вы имеете дело с Excel 2007+, я бы предложил использовать System.IO.Packaging + System.Xml.Linq(LINQ to XML) для управления листами Excel. Это намного чище и не требует, чтобы на самом деле было установлено, что на вашем компьютере установлено приложение.

Вы также столкнетесь с меньшими COM-конфликтами (например, выше в своем сообщении).

Если вы пытаетесь редактировать Excel 2003 или ранее, то, к сожалению, я не могу вам помочь.

Ответ 6

Возможно, это произошло после обновления до последней версии Office. Попробуйте перейти в "Программы и функции", найти установку и "восстановить" ее. По-видимому, он обновил и/или повторно зарегистрировал dll interop, используемый для создания этих объектов.

Это может потребоваться в сочетании с исправлением реестра, описанным в @codesforcoffee.