Как перевести логику динамической таблицы из обычной формы в управляемую в 1С

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

При переводе старых обработок с обычных форм на управляемые разработчики часто сталкиваются с фундаментальными различиями в архитектуре платформы. В обычных формах весь код выполнялся в едином толстом клиенте: можно было напрямую вызвать экспортную функцию модуля объекта, получить ТаблицаЗначений, присвоить ее табличному полю и вызвать простой метод СоздатьКолонки(). В управляемом интерфейсе действуют жесткие ограничения клиент-серверного взаимодействия и типизации данных формы. Разберем по шагам, как правильно перенести подобный механизм на управляемые формы.

В чем заключаются главные отличия и сложности

Проанализируем основные архитектурные препятствия, возникающие при миграции кода:

  1. Клиент-серверное разделение: на тонком клиенте нельзя напрямую работать с объектом ТаблицаЗначений или создавать COM-объекты вроде ADODB.Command для внешних баз данных. Все операции выборки и трансформации данных должны выполняться на сервере.
  2. Изоляция модуля формы от объекта: основной реквизит формы Объект на управляемой форме не является самим объектом типа ОбработкаОбъект или ДокументОбъект. Это специальная интерфейсная проекция — ДанныеФормыСтруктура. Чтобы вызвать экспортный метод модуля объекта, необходимо явно преобразовать реквизит формы в прикладной объект.
  3. Динамическое создание элементов: метода СоздатьКолонки() в управляемых формах нет. Если состав колонок неизвестен заранее и формируется на лету по данным внешнего SQL-запроса, требуется программно модифицировать структуру формы с помощью метода ИзменитьРеквизиты() и создавать элементы интерфейса через коллекцию Элементы.

Шаг 1. Вызов метода модуля объекта из контекста формы

Рассмотрим, как связать модуль формы и модуль объекта. Если логику подключения к внешней базе данных и выборки через ADO решено оставить в модуле объекта, ее нельзя вызвать на форме напрямую. Выясним причину: контекст формы не видит методы объекта без предварительной инициализации.

Для обращения к экспортным методам объекта на сервере управляемой формы используется функция РеквизитФормыВЗначение(). Посмотрим на типовой пример реализации:


&НаСервере
Функция ПолучитьТаблицуИзОбъекта()
    // Преобразуем реквизит формы в реальный объект внешней обработки
    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    // Вызываем экспортную функцию, возвращающую ТаблицуЗначений
    Возврат ОбработкаОбъект.ИзТКС();
КонецФункции

Также разработчик может вовсе отказаться от вызова модуля объекта, перенеся саму функцию выборки данных непосредственно в модуль формы с директивой &НаСервере или вынеся ее в общий модуль / модуль менеджера.

Шаг 2. Динамическое создание реквизитов и колонок на форме

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

Метод ИзменитьРеквизиты() является ресурсоемким, поэтому все операции удаления и добавления реквизитов мы должны выполнять за один системный вызов, передавая сформированные массивы. Посмотрим на полный пример процедуры построения таблицы на форме:


&НаСервере
Процедура ПерестроитьТаблицуФормы(ТаблицаИсточник)

    ИмяТаблицыФормы = "ВременнаяТаблица1";
    
    // 1. Очищаем ранее созданные элементы и реквизиты
    РеквизитыДляУдаления = Новый Массив;
    ЭлементТаблица = Элементы[ИмяТаблицыФормы];
    
    Для Каждого КолонкаФормы Из ЭлементТаблица.ПодчиненныеЭлементы Цикл
        // Формируем путь к удаляемому реквизиту формы
        РеквизитыДляУдаления.Добавить(ИмяТаблицыФормы + "." + КолонкаФормы.Имя);
        Элементы.Удалить(КолонкаФормы);
    КонецЦикла;
    
    Если РеквизитыДляУдаления.Количество() > 0 Тогда
        ИзменитьРеквизиты(Новый Массив, РеквизитыДляУдаления);
    КонецЕсли;

    // 2. Создаем новые реквизиты колонок таблицы формы
    РеквизитыДляДобавления = Новый Массив;
    Для Каждого КолонкаИсточник Из ТаблицаИсточник.Колонки Цикл
        НовыйРеквизит = Новый РеквизитФормы(
            КолонкаИсточник.Имя,
            КолонкаИсточник.ТипЗначения,
            ИмяТаблицыФормы,
            КолонкаИсточник.Заголовок
        );
        РеквизитыДляДобавления.Добавить(НовыйРеквизит);
    КонецЦикла;
    
    ИзменитьРеквизиты(РеквизитыДляДобавления);

    // 3. Добавляем элементы интерфейса (колонки) в таблицу
    Для Каждого КолонкаИсточник Из ТаблицаИсточник.Колонки Цикл
        НовоеПоле = Элементы.Добавить(
            КолонкаИсточник.Имя,
            Тип("ПолеФормы"),
            ЭлементТаблица
        );
        НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
        НовоеПоле.ПутьКДанным = ИмяТаблицыФормы + "." + КолонкаИсточник.Имя;
    КонецЦикла;

КонецПроцедуры

Шаг 3. Загрузка данных в таблицу формы

После того как структура реквизитов и колонок приведена в полное соответствие с источником, остается загрузить строки. В управляемых формах для заполнения коллекции формы из прикладного объекта ТаблицаЗначений применяется процедура ЗначениеВДанныеФормы().

Объединим вызовы в единую серверную процедуру и подключим ее к обработчику клиентской кнопки:


&НаСервере
Процедура СформироватьОстаткиНаСервере()
    
    // Получаем прикладной объект и вызываем функцию выборки данных
    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    ТаблицаДанных = ОбработкаОбъект.ИзТКС();
    
    // Перестраиваем колонки под полученную выборку
    ПерестроитьТаблицуФормы(ТаблицаДанных);
    
    // Загружаем данные в реквизит формы
    ЗначениеВДанныеФормы(ТаблицаДанных, ЭтаФорма.ВременнаяТаблица1);
    
КонецПроцедуры

&НаКлиенте
Процедура СфорОстат(Команда)
    СформироватьОстаткиНаСервере();
КонецПроцедуры

Важные ограничения и рекомендации при работе с внешними СУБД

Рассмотрим дополнительные технические нюансы, которые необходимо учитывать при миграции кода с использованием ADODB:

  1. Разрядность платформы: если на клиенте использовалась 32-битная платформа, вызов COM-объектов работал штатно. При переносе логики на 64-битный сервер 1С системный OLE DB или ODBC драйвер базы данных также обязан быть 64-разрядным. При несовпадении разрядностей возникнет ошибка создания COM-объекта.
  2. Серверы под управлением Linux: технология COM является частью экосистемы Windows. Если сервер 1С работает на ОС Linux, вызов COMОбъект приведет к ошибке. В таких конфигурациях подключение к внешним базам следует реализовывать через стандартные Внешние источники данных 1С либо через вызов внешних HTTP-сервисов.
  3. Безопасный режим: при подключении обработки через механизм дополнительных отчетов и обработок БСП по умолчанию включается безопасный режим, запрещающий создание COM-объектов. Для выполнения кода потребуется явная настройка профилей безопасности или отключение безопасного режима в настройках регистрации обработки.
  4. Альтернатива динамическим колонкам: если задача сводится исключительно к просмотру выборки без интерактивного редактирования строк, намного проще и производительнее использовать реквизит типа ТабличныйДокумент. Вывод данных в ячейки отчета избавляет от необходимости сложного программного манипулирования реквизитами формы через ИзменитьРеквизиты().
← На главную