Почему падает 1С 7.7 при вызове ИсходнаяТаблица с ActiveX в классе 1С++ и как это исправить?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При использовании внешней компоненты 1С++ (1cpp.dll) для платформы 1С:Предприятие 7.7 разработчики часто применяют OOP-подход, создавая классы непосредственно внутри внешних обработок (файлов с расширением .ert). Однако при попытке обратиться из метода класса к макету таблицы, содержащей внедренный элемент ActiveX (OCX), происходит внезапный сбой работы программы.

Вызов метода ИсходнаяТаблица("Таблица", ПутьКФайлу) при наличии ActiveX в макете приводит к критическому завершению работы платформы 1cv7s.exe с ошибкой доступа в библиотеке MFC42.DLL (код исключения 0xc0000005).

Рассмотрим подробнее причины возникновения этой ошибки и проанализируем практические способы её обхода.

Выясним причину сбоя

Разберем ситуации, в которых возникает эта ошибка. Внедренные в макет таблицы ActiveX-компоненты требуют для своей корректной работы и инициализации полноценного визуального контейнера OLE (структур графического окна HWND).

Когда внешняя обработка используется как класс 1С++, обращения к ней происходят в фоновом/невизуальном контексте. В этот момент платформой 1С 7.7 не создается оконный контейнер для OLE-объекта. Попытка библиотеки MFC42.DLL обратиться к несуществующему указателю интерфейса ActiveX в памяти приводит к аварийному завершению работы приложения.

Интересной особенностью является то, что сбой происходит только при загрузке макета из самого файла обработки .ert. Если тот же самый макет таблицы сохранить в отдельный файл формата .mxl, ошибка не воспроизводится, так как алгоритм чтения внешнего файла таблицы работает без немедленной попытки создать OLE-контейнер.

Способ 1. Инициализация и вывод таблицы в процедуре ПриОткрытии

Наиболее удобное решение, позволяющее сохранить всю разработку в едином файле .ert (без плождения дополнительных внешних макетов) — это перенос работы с печатной формой в предопределенную процедуру ПриОткрытии() модуля внешней обработки.

Проанализируем алгоритм работы этого решения по шагам:

  1. Вся техническая бизнес-логика и подготовка данных остаются в методах класса 1С++.
  2. Инициализация таблицы через метод ИсходнаяТаблица() и её вывод на печать (метод Вывести()) переносятся в процедуру ПриОткрытии() модуля формы внешней обработки.
  3. При необходимости скомпоновать и вывести печатный форму класс обращается к самому файлу обработки через вызов ОткрытьФорму(), передавая в параметрах контекст или данные.

Посмотрим на пример организации кода внутри класса и модуля обработки.

В модуле внешней обработки (в файле ТестТабКласс.ert) процедура ПриОткрытии() принимает параметры и формирует печатную форму:


Процедура ПриОткрытии()
    Параметр = Форма.Параметр;
    
    // Проверяем, передан ли объект с данными
    Если ТипЗначенияСтр(Параметр) = "Объект" Тогда
        Таб = СоздатьОбъект("Таблица");
        
        // Метод ИсходнаяТаблица вызывается в контексте открывающейся формы
        Таб.ИсходнаяТаблица("Таблица");
        
        Таб.ВывестиСекцию("Шапка");
        Таб.Показать("Отчет с ActiveX", "");
        
        // Закрываем форму после вывода, если окно формы не должно оставаться
        СтатусВозврата(0);
        Возврат;
    КонецЕсли;
КонецПроцедуры

В основном методе класса вызов печати будет выглядеть следующим образом:


Процедура СформироватьОтчет() Экспорт
    // Вызываем форму текущей обработки, передавая сам класс в качестве параметра
    ОткрытьФорму("Отчет", Контекст, ПолучитьПутьФайла());
КонецПроцедуры

Таким образом, единый файл .ert одновременно выступает и как описание класса 1С++, и как обычная внешняя обработка с формами и макетами.

Способ 2. Вынос макета таблицы в отдельный файл (.mxl)

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

  1. Откройте макет таблицы в конфигураторе или редакторе и сохраните его как файл внешнего макета (например, Template.mxl).
  2. Удалите секцию с таблицей из самого файла .ert.
  3. При вызове метода ИсходнаяТаблица() передайте полный путь к файлу .mxl:

Таб = СоздатьОбъект("Таблица");
ПутьКМакету = КаталогИсполняемогоМодуля() + "Template.mxl";
Таб.ИсходнаяТаблица(ПутьКМакету);
Таб.ВывестиСекцию("СекцияСActiveX");
Таб.Показать();

Этот способ позволяет работать с таблицей напрямую из методов класса без использования вызова ОткрытьФорму().

Способ 3. Программное создание ActiveX компонентов

Если создание внешних файлов .mxl нежелательно, а ActiveX используется для стандартных задач (например, отображение штрихкодов или диаграмм), рекомендуется полностью удалить элемент ActiveX из печатной таблицы макета.

Вместо размещения OCX на макете применяют программную генерацию изображения компонента (в формат .bmp или .png) во временный каталог с последующей вставкой готовой картинки в секцию таблицы через стандартные средства 1С 7.7 или компоненту FormEx.

← На главную