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

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

При разработке внешних обработок заполнения табличных частей (ТЧ) в конфигурациях на обычных формах (таких как ЗУП 2.5, УТ 10.3, УПП 1.3) программисты часто сталкиваются с классической задачей: как сделать так, чтобы при нажатии кнопки заполнения сначала открывалась форма обработки, пользователь вводил в ней параметры (например, период или конкретный вид времени), и только после этого табличная часть документа заполнялась на основе этих параметров.

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

В чем суть проблемы: почему форма обработки «не понимает», откуда ее вызвали?

Давайте проанализируем типичную ситуацию. Разработчик создает внешнюю обработку, рисует красивую форму, добавляет на нее реквизиты (например, ДатаНачала, ДатаОкончания, ВидВремени) и пишет процедуру заполнения прямо в модуле формы обработки. Однако при попытке заполнить документ система выдает ошибку или просто ничего не делает.

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

Выясним, как связать форму обработки и модифицируемый документ «под капотом» платформы 1С.

Архитектура взаимодействия: процедура Инициализировать()

Для правильного старта нашей обработки в ее Модуле объекта обязательно должна быть объявлена следующая процедура:


Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
    // Здесь начинается магия передачи контекста
КонецПроцедуры

Рассмотрим подробнее ее параметры, которые передает сама платформа в момент вызова обработки:

  1. Объект — это непосредственно сам модифицируемый документ в оперативной памяти (тип ДокументОбъект). Все изменения, которые мы в него внесем, сразу отобразятся на экране пользователя.
  2. ИмяТабличнойЧасти — строковое имя заполняемой ТЧ (например, "Начисления" или "Исполнители"). Это позволяет делать универсальные обработки.
  3. ТабличноеПолеОбъекта — элемент управления на форме документа, визуализирующий нашу ТЧ.

Теперь разберем два лучших практических сценария реализации формы параметров.

Вариант А: Передача контекста документа в форму обработки

Этот метод считается классическим. Суть его в том, что мы сохраняем ссылку на изменяемый документ в реквизитах самой обработки, открываем форму обработки модально, а всю логику заполнения пишем внутри модуля формы.

Выполним по шагам настройку этого механизма:

Шаг 1. Создание реквизитов обработки

В метаданных нашей внешней обработки в ветке «Реквизиты» создадим два технических реквизита:

Шаг 2. Код в Модуле объекта обработки

В модуле объекта пишем процедуру инициализации. Ее задача — заполнить созданные реквизиты обработки данными документа и открыть форму:


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

Шаг 3. Код в Модуле формы обработки

Теперь на форме нашей обработки мы можем свободно разместить элементы управления (например, поля ввода для периода и вида времени). При нажатии на кнопку «Заполнить» на форме обработки выполнится следующий код:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    
    // Проверяем, что контекст документа успешно передан
    Если СсылкаНаОбъект = Неопределено Тогда
        Предупреждение("Не найден контекст документа для заполнения!");
        Возврат;
    КонецЕсли;
    
    // Получаем табличную часть документа прямо в оперативной памяти
    ТЧДокумента = СсылкаНаОбъект[ИмяТЧ];
    
    // Пример логики заполнения: очищаем старые данные или дополняем их
    ТЧДокумента.Очистить();
    
    // Реализуем наш алгоритм (например, заполнение по периоду)
    НачалоПериода = День(ДатаНачала);
    КонецПериода = День(ДатаОкончания);
    
    // Предположим, у нас есть запрос для получения данных
    ВыгрузкаДанных = СформироватьЗапросДанных(); 
    
    Для Каждого СтрокаДанных Из ВыгрузкаДанных Цикл
        НоваяСтрока = ТЧДокумента.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);
        
        // Применяем параметры, введенные пользователем на форме обработки
        НоваяСтрока.ВидВремени = ВидВремени;
        // Дополнительные расчеты...
    КонецЦикла;
    
    // Закрываем форму обработки после успешного завершения работы
    Закрыть();
    
КонецПроцедуры

Вариант Б: Возврат параметров из формы в модуль объекта

Этот подход более изящен с точки зрения архитектуры программирования (разделение интерфейса и бизнес-логики). Форма обработки используется исключительно как диалоговое окно для сбора параметров. Она не занимается модификацией документа, а лишь возвращает структуру параметров обратно в модуль объекта, где и происходит вся работа с ТЧ.

Посмотрим, как реализовать этот вариант:

Шаг 1. Код в Модуле объекта обработки

В модуле объекта мы открываем форму модально. Метод ОткрытьМодально() возвращает значение, которое передается в метод Закрыть() внутри формы:


Процедура Инициализировать(Объект, ИмяТабличнойЧасти, ТабличноеПолеОбъекта) Экспорт
    
    ФормаПараметров = ПолучитьФорму("Форма");
    
    // Ожидаем структуру параметров от формы
    СтруктураПараметров = ФормаПараметров.ОткрытьМодально();
    
    // Если пользователь закрыл форму крестиком или нажал "Отмена"
    Если ТипЗнч(СтруктураПараметров) <> Тип("Структура") Тогда
        Возврат; 
    КонецЕсли;
    
    // Получаем ТЧ документа
    ТЧ = Объект[ИмяТабличнойЧасти];
    
    // Выполняем алгоритм заполнения на основе параметров из структуры
    Для Каждого СтрокаТЧ Из ТЧ Цикл
        СтрокаТЧ.ВидВремени = СтруктураПараметров.ВидВремени;
        СтрокаТЧ.Часы = СтруктураПараметров.Часы;
    КонецЦикла;
    
КонецПроцедуры

Шаг 2. Код в Модуле формы обработки

На форме обработки при нажатии кнопки «ОК» мы собираем все реквизиты формы в структуру и закрываем форму, передавая эту структуру в качестве параметра возврата:


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

Критические ошибки при создании обработок заполнения ТЧ

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

  1. Никогда не вызывайте метод Записать() внутри обработки заполнения!

    Это грубейшая ошибка. Цель заполнения ТЧ — предоставить пользователю возможность увидеть изменения на экране своего монитора в открытой форме документа. Если результат заполнения пользователя не устроит, он должен иметь возможность просто закрыть документ без сохранения. Если ваша обработка принудительно вызовет Объект.Записать(), транзакция запишется в базу данных без согласия пользователя. Это нарушает базовые стандарты разработки 1С.

  2. Проблема «Нового документа» (Пустая ссылка).

    Если пользователь создал новый документ, еще не записал его в базу данных и сразу нажал кнопку заполнения ТЧ, реквизит Объект.Ссылка будет пустым (Документы.ИмяДокумента.ПустаяСсылка()).

    Если внутри алгоритма заполнения вы используете запросы, которые обращаются к базе данных с условием вроде ГДЕ Документ = &ДокументСсылка, ваш запрос ничего не найдет. Чтобы избежать этой проблемы, всегда получайте общие реквизиты шапки документа (организация, дата, склад) напрямую из переданной оперативной памяти: например, Объект.Организация или Объект.Дата, вместо того чтобы тянуть их запросом из БД по ссылке.

  3. Обновление интерфейса.

    Иногда после выполнения алгоритма заполнения данные в табличной части на форме документа визуально не обновляются. Чтобы гарантировать перерисовку интерфейса обычных форм, в самом конце выполнения заполнения в модуле объекта вызовите метод переданного табличного поля: ТабличноеПолеОбъекта.ОбновитьСтроки().

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

← На главную