При выгрузке данных из 1С в Microsoft Excel через механизм COM-автоматизации разработчики и пользователи часто сталкиваются со сбоями после обновления версии офисного пакета. Типичный сценарий: внешняя обработка годами функционировала без нареканий, но после перехода на MS Office 2016, 2019 или 365 при попытке записать данные на второй или третий лист программа выдает критическую ошибку:
Ошибка при вызове метода контекста (Sheets): Произошла исключительная ситуация (0x8002000b)
Рассмотрим подробно причины возникновения этой проблемы, проанализируем устройство коллекции листов в COM-модели Excel и разберем сразу несколько способов исправления кода внешней обработки.
Код ошибки 0x8002000b в спецификации COM/OLE расшифровывается как DISP_E_BADINDEX — «Недопустимый индекс» или «Выход за пределы допустимого диапазона». Ошибка происходит в тот момент, когда 1С пытается обратиться к элементу коллекции Sheets по индексу, которого не существует в открытой книге.
Проанализируем, почему код перестает работать именно после обновления Excel:
Workbooks.Add() программа по умолчанию формировала документ с 3 листами («Лист1», «Лист2», «Лист3»). Код вида ExcelWB.Sheets(2) успешно получал ссылку на второй лист.ExcelWB.Sheets(2) система пытается извлечь несуществующий элемент и генерирует исключение 0x8002000b.Разберем практические варианты устранения данной проблемы в коде 1С:Предприятие.
Самое чистое и лаконичное решение, не требующее усложнения циклов в коде выгрузки, — явно указать приложению Excel, сколько листов должно создаваться в новых книгах. У объекта Excel.Application присутствует свойство SheetsInNewWorkbook.
Рассмотрим пример правильной инициализации объекта Excel и создания книги с тремя листами:
// Инициализируем приложение Excel
ExcelПриложение = Новый COMОбъект("Excel.Application");
ExcelПриложение.Visible = Ложь;
// Задаем количество листов, создаваемых по умолчанию
ExcelПриложение.SheetsInNewWorkbook = 3;
// Создаем новую книгу - она сразу будет содержать 3 листа
ExcelWB = ExcelПриложение.Workbooks.Add();
// Теперь обращение к первым трем листам пройдет без ошибок
Лист1 = ExcelWB.Sheets(1);
Лист1.Name = "Главная";
Лист2 = ExcelWB.Sheets(2);
Лист2.Name = "Товар - движение по складу";
Лист3 = ExcelWB.Sheets(3);
Лист3.Name = "Товар - остатки товара";
Этот способ позволяет сохранить исходную логику работы обработки без масштабных переделок основного алгоритма заполнения таблиц.
Если книга открывается из существующего файла-шаблона или количество требуемых листов заранее неизвестно, рационально использовать динамическую проверку размера коллекции Sheets перед обращением к элементам.
Однако при добавлении листов через метод Sheets.Add() важно учитывать порядок их вставки. По умолчанию Excel вставляет новый лист перед текущим активным листом, из-за чего листы могут выстроиться в обратном порядке. Чтобы новые листы добавлялись строго в конец документа, следует передавать параметр позиционирования.
Проанализируем программный код динамического добавления листов:
// Создаем или открываем книгу
ExcelWB = ExcelПриложение.Workbooks.Add();
// Проверяем количество листов и добавляем недостающие в конец книги
ТребуемоеКоличествоЛистов = 3;
Пока ExcelWB.Sheets.Count < ТребуемоеКоличествоЛистов Цикл
// Вставляем новый лист после последнего существующего
ПоследнийЛист = ExcelWB.Sheets(ExcelWB.Sheets.Count);
ExcelWB.Sheets.Add(, ПоследнийЛист);
КонецЦикла;
// Настройка первого листа
Лист = ExcelWB.Sheets(1);
Лист.Name = "Главная";
Лист.Columns("A").NumberFormat = "0";
Лист.Columns("B").NumberFormat = "@";
Лист.Columns("C").NumberFormat = "ДД.ММ.ГГГГ";
// Настройка второго листа
Лист = ExcelWB.Sheets(2);
Лист.Name = "Товар - движение по складу";
Лист.Columns("A").NumberFormat = "0";
Лист.Columns("B").NumberFormat = "@";
При переработке кода часто возникают синтаксические ошибки платформы 1С. Разберем типичные ошибки и способы их предотвращения:
Возникает, если переменной присвоили коллекцию (например, Листы = ExcelWB.Sheets;), а затем попытались обратиться к ней с круглыми скобками: Лист = Листы(1);. Платформа 1С воспринимает эту запись как вызов функции языка 1С Листы(). Для обращения к элементам COM-коллекции из отдельной переменной следует использовать метод Item():
Листы = ExcelWB.Sheets;
Лист = Листы.Item(1); // Корректное обращение через метод Item()
Либо обращаться непосредственно через родительский объект: Лист = ExcelWB.Sheets(1);.
Происходит при попытке присвоить имя всей коллекции листов вместо конкретного листа. Например, код Лист = ExcelWB.Sheets; Лист.Name = "Главная"; некорректен, так как Sheets — это коллекция, не имеющая свойства Name.
Select:
Вызовы вида ExcelWB.Sheets(2).Select; или присвоение результата метода Select переменной приводят к непредсказуемым ошибкам. Для настройки параметров и записи данных в ячейки делать лист активным (выделенным) не требуется.
Для предотвращения «зависания» процессов EXCEL.EXE в операционной системе и исчерпания оперативной памяти всю работу с внешней связкой необходимо оборачивать в конструкцию безопасного выполнения Попытка ... Исключение с гарантированным закрытием приложения.
ExcelПриложение = Неопределено;
ExcelWB = Неопределено;
Попытка
ExcelПриложение = Новый COMОбъект("Excel.Application");
ExcelПриложение.Visible = Ложь;
ExcelПриложение.DisplayAlerts = Ложь; // Отключаем системные предупреждения
ExcelПриложение.SheetsInNewWorkbook = 3;
ExcelWB = ExcelПриложение.Workbooks.Add();
// ... Логика заполнения листов и ячеек ...
// Сохраняем результат
ExcelWB.SaveAs("C:\Export\Report.xlsx");
Исключение
Сообщить("Ошибка при работе с Excel: " + ОшибкаОписание());
КонецПопытки;
// Обязательный блок очистки ресурсов
Если ExcelWB <> Неопределено Тогда
ExcelWB.Close(Ложь);
КонецЕсли;
Если ExcelПриложение <> Неопределено Тогда
ExcelПриложение.Quit();
ExcelПриложение = Неопределено;
КонецЕсли;
Подводя итог: при обновлении MS Office основной причиной ошибок выгрузки является изменение числа листов по умолчанию. Использование свойства SheetsInNewWorkbook или явный контроль количества листов методом Sheets.Add() с корректным синтаксисом обращения к COM-объектам полностью решает проблему совместимости внешней обработки.