Как исправить ошибку «Ссылка на объект не указывает на экземпляр объекта» при загрузке данных из Excel?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации бизнес-процессов разработчики 1С часто сталкиваются с необходимостью импорта данных из файлов Excel. Традиционный и наиболее популярный метод реализации этой задачи — использование COM-соединения через объект Excel.Application. Однако этот подход таит в себе скрытые угрозы, связанные со спецификой локального окружения пользователя.

Довольно распространенной является ситуация, когда отточенный и стабильно работавший годами код загрузки внезапно начинает выдавать ошибку: «Ссылка на объект не указывает на экземпляр объекта» (в англоязычной среде — NullReferenceException). При этом сам импорт данных может даже завершаться успешно, но раздражающее окно с ошибкой прерывает сессию пользователя или ломает логику пакетной обработки. Давайте подробно разберем, почему возникает эта проблема и как ее эффективно решить.

В этой статье мы проанализируем техническую природу сбоя и рассмотрим несколько практических вариантов обхода проблемы — от простой настройки операционной системы до перевода механизмов загрузки на современные кроссплатформенные рельсы без использования COM.

Выясняем техническую причину сбоя

Для того чтобы понять, откуда берется ошибка «Ссылка на объект не указывает на экземпляр объекта», заглянем во внутренние процессы Windows при вызове COM-объекта из 1С.

Когда в коде 1С выполняется инициализация объекта через команду Новый COMОбъект("Excel.Application"), операционная система запускает процесс EXCEL.EXE в так называемом фоновом (скрытом) режиме. В этот момент визуальное окно программы отсутствует, а в самом приложении по умолчанию еще не открыто ни одной книги (до тех пор, пока мы явно не вызовем метод Open).

Параллельно с этим, если у пользователя установлены какие-либо глобальные макросы или сторонние COM-надстройки (например, популярный пакет XLTools, надстройки для связи с базами данных SAP, инструменты бизнес-анализа PowerPivot и др.), они автоматически инициализируются вместе с запуском Excel. Код этих надстроек (часто написанный на .NET / C# или VBA) жестко запрограммирован на интеграцию в интерфейс Excel сразу при его старте.

Проблема заключается в том, что при фоновом COM-запуске из 1С интерфейсные элементы отсутствуют. Программа надстройки пытается обратиться к свойствам активного окна (ActiveWindow), активной книги (ActiveWorkbook) или активного листа (ActiveSheet). Так как ни одной книги еще не открыто, эти системные свойства возвращают пустое значение (null или Nothing). Не найдя ожидаемого объекта, код надстройки аварийно завершается с ошибкой обращения к пустой ссылке, которая мгновенно транслируется обратно в 1С в виде системного сбоя.

Рассмотрим по шагам все возможные способы борьбы с этой напастью, начиная с самых простых и заканчивая наиболее надежными.

Способ 1. Чтение файлов без использования Excel.Application (Рекомендуемый метод)

Самый надежный и современный способ раз и навсегда избавиться от подобных ошибок — полностью отказаться от использования COM-соединения для чтения файлов Excel. Чтение через COM медленное, требует обязательной установки лицензионного MS Office на клиентский компьютер (или сервер) и полностью привязано к операционной системе Windows.

Платформа 1С:Предприятие 8.3 обладает мощным встроенным функционалом для работы с файлами .xlsx и .xls напрямую через объект ТабличныйДокумент. Этот метод работает на любой операционной системе (включая Linux), не требует установленного Microsoft Office и полностью игнорирует любые макросы и надстройки.

Давайте рассмотрим пример кода, который позволяет прочитать данные из файла Excel без обращения к COM:


// Создаем объект табличного документа
ТабДок = Новый ТабличныйДокумент;

Попытка
    // Читаем файл Excel напрямую в память 1С
    ТабДок.Прочитать(ПутьКФайлу, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
    ЗаписатьЛогСобытий("Ошибка чтения файла: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

// Теперь мы можем обойти строки табличного документа, как обычную таблицу
ВсегоСтрок = ТабДок.ВысотаТаблицы;
ВсегоКолонок = ТабДок.ШиринаТаблицы;

Для НомерСтроки = 1 По ВсегоСтрок Цикл
    // Пример получения значения из конкретной ячейки
    КодТовара = ТабДок.Область(НомерСтроки, 1).Текст;
    Количество = ТабДок.Область(НомерСтроки, 2).Значение;
    
    // Обработка полученных данных...
КонецЦикла;

Перевод загрузок на чтение через ТабличныйДокумент не только защитит вас от ошибок стороннего софта, но и существенно ускорит работу алгоритмов импорта данных.

Способ 2. Изменение режима загрузки надстроек в реестре Windows

Если у вас настроено множество различных загрузок через COM и оперативно переписать их код под ТабличныйДокумент не представляется возможным, проблему можно решить на уровне администрирования операционной системы.

Мы можем указать проблемной надстройке (например, XLTools) не загружаться при фоновом старте Excel через сторонние программы, но при этом она продолжит нормально работать, когда пользователь запускает Excel вручную для своей повседневной работы. Для этого настроим поведение надстройки через реестр Windows.

  1. Нажмите сочетание клавиш Win + R, введите regedit и нажмите Enter для запуска Редактора реестра.
  2. Перейдите по следующему пути (для текущего пользователя):
    HKEY_CURRENT_USER\Software\Microsoft\Office\Excel\Addins\[Имя_Вашей_Надстройки]
    (Здесь вместо [Имя_Вашей_Надстройки] выберите ветку, соответствующую проблемному плагину, например, XLTools).
  3. В правой части окна найдите параметр с именем LoadBehavior (тип DWORD).
  4. Дважды кликните по нему и измените его значение. По умолчанию там установлена цифра 3 (загружать всегда при старте). Измените это значение на 2 (загружать по требованию / load on demand).

При значении параметра равным 2 надстройка не будет пытаться инициализироваться при фоновом COM-вызове из 1С. Однако, как только пользователь лично откроет Excel и кликнет на панель надстройки на ленте инструментов, она мгновенно активируется. Это элегантное решение, позволяющее избежать конфликта систем.

Способ 3. Программное отключение COM-надстроек в коде 1С

Если у вас есть возможность внести небольшие правки в код инициализации Excel в 1С (особенно если создание объекта вынесено в общую функцию или общий модуль), вы можете программно отключать все установленные COM-надстройки перед началом чтения файла.

Для этого мы можем обойти коллекцию COMAddIns объекта Excel и временно деактивировать их только для текущей запущенной сессии. Это никак не повлияет на настройки Excel самого пользователя в будущем.

Посмотрим на пример реализации данного метода:


// Инициализируем COM-соединение
Эксель = Новый COMОбъект("Excel.Application");

// Обходим все зарегистрированные надстройки и отключаем их связь с текущей сессией
Для Каждого Надстройка Из Эксель.COMAddIns Цикл
    Попытка
        Надстройка.Connect = Ложь;
    Исключение
        // Игнорируем ошибки для тех надстроек, которые заблокированы системой от изменений
    КонецПопытки;
КонецЦикла;

// Теперь можно безопасно открывать книгу и читать данные
Книга = Эксель.Workbooks.Open(ПутьКФайлу);

Данный подход гарантирует локальное "очищение" окружения Excel во время сеанса импорта и страхует от появления новых непредвиденных ошибок, если пользователь установит себе еще несколько плагинов.

Способ 4. Подавление системных окон и отключение макросов в коде 1С

Для минимизации вероятности возникновения конфликтов во время COM-сессии крайне важно правильно настроить параметры безопасности и отображения самого объекта Excel.Application. Мы можем принудительно запретить запуск макросов книги и отключить вывод любых предупреждений и окон ошибок на экран.

Давайте проанализируем, какие свойства COM-объекта помогают нам сделать процесс загрузки максимально изолированным и «тихим»:


Эксель = Новый COMОбъект("Excel.Application");

// Отключаем отображение системных предупреждений и диалоговых окон
Эксель.DisplayAlerts = Ложь;

// Отключаем обработку событий Excel (включая автоматический запуск встроенных макросов книги)
Эксель.EnableEvents = Ложь;

// Устанавливаем принудительное отключение макросов (безопасность автоматизации)
// Значение 3 означает msoAutomationSecurityForceDisable (принудительное отключение всех макросов без вывода запросов)
Эксель.AutomationSecurity = 3; 

Использование свойства AutomationSecurity = 3 гарантирует, что даже если в самом загружаемом файле Excel содержатся вредоносные или конфликтующие макросы пользователя, они будут принудительно заблокированы на время выполнения нашей процедуры импорта.

Способ 5. Настройка параметров доверия в самом Microsoft Excel

Иногда ошибка вызова пустой ссылки возникает из-за того, что файл загрузки блокируется встроенными системами безопасности Windows. Например, если файл был получен из интернета, прислан по почте или загружен из сетевой папки общего доступа, Excel при открытии помещает его в режим «Защищенного просмотра» (Protected View).

В этом режиме доступ к объектной модели документа сильно ограничен, что также вызывает сбои у плагинов и надстроек, пытающихся обработать открываемый файл.

Чтобы решить эту проблему без изменения кода, выполните следующие действия в интерфейсе MS Excel на компьютере пользователя:

  1. Откройте Microsoft Excel и перейдите в меню Файл -> Параметры.
  2. Перейдите в раздел Центр управления безопасностью и нажмите кнопку Параметры центра управления безопасностью...
  3. В левом меню выберите пункт Надежные расположения. Нажмите кнопку Добавить новое расположение... и укажите путь к папке, из которой 1С производит загрузку файлов. Поставьте галочку "Также доверять всем вложенным папкам".
  4. Дополнительно перейдите в раздел Защищенный просмотр и снимите флажки, блокирующие открытие файлов, полученных из интернета или небезопасных расположений (если политика безопасности вашей компании это позволяет).

Резюме и выводы

Мы подробно разобрали природу ошибки «Ссылка на объект не указывает на экземпляр объекта» при загрузке данных из Excel в 1С. Чаще всего виновниками проблемы становятся пользовательские макросы или сторонние бизнес-надстройки (такие как XLTools), которые пытаются инициализировать интерфейс в скрытом фоновом процессе COM.

Для решения проблемы в долгосрочной перспективе мы рекомендуем постепенно переводить ваши обработки на чтение без использования COM-объекта с помощью встроенного класса ТабличныйДокумент. Если же переписывать код нет времени, используйте точечные "противоядия": перевод надстроек в режим загрузки по требованию в реестре (LoadBehavior = 2), отключение выполнения макросов через свойство AutomationSecurity = 3 или программный обход коллекции COMAddIns.

← На главную