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

Программист 1С:Зарплата и Управление Персоналом Управленческий учет IT и автоматизация бизнеса
← На главную

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

Почему табличная часть остается пустой после выполнения кода?

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

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

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

Способ 1. Прямая работа с данными формы (рекомендовано)

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

Проанализируем пример кода для процедуры, выполняемой на сервере:


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

В этом случае нам не нужно вызывать ОбновитьОтображениеДанных() или Прочитать(), так как платформа сама синхронизирует состояние реквизита Объект между сервером и клиентом.

Способ 2. Использование механизмов конвертации данных формы в объект

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

Рассмотрим пошагово, как это сделать:

  1. Используем функцию РеквизитФормыВЗначение, чтобы получить полноценный объект документа.
  2. Выполняем все необходимые манипуляции с табличными частями.
  3. Используем процедуру ЗначениеВРеквизитФормы, чтобы обновить экранные данные.

Пример реализации:


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

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

Проблема заполнения колонки «Сотрудник»

Иногда программисты сталкиваются с тем, что строки добавляются, но конкретные поля (например, Сотрудник) остаются пустыми. Выясним причину этой ситуации на примере кода автора темы.

Часто ошибка кроется в неправильной ссылке на данные. Если вы используете поиск в таблице значений, убедитесь, что вы присваиваете именно ссылку на справочник, а не всю строку таблицы значений или объект поиска. Посмотрим на типичную ошибку:

НовСтр.Сотрудник = МассивНайденныхСтрок; // Ошибка! Массив не является ссылкой

Правильный вариант при поиске через НайтиСтроки:


Если МассивНайденныхСтрок.Количество() > 0 Тогда
    // Обращаемся к первому элементу массива найденных строк и берем нужную колонку
    НовСтр.Сотрудник = МассивНайденныхСтрок[0].Сотрудник; 
КонецЕсли;

Также стоит проверить типизацию исходной таблицы ТЗДанные. Если в ней колонка Сотрудник имеет строковый тип, а в документе это СправочникСсылка.Сотрудники, то прямое присваивание не сработает. В таком случае необходимо сначала найти ссылку в базе по наименованию или коду.

Как принудительно обновить форму?

Если вы все же решили записывать объект в базу на сервере (через Записать()), то форма на клиенте действительно останется «старой». Чтобы обновить её программно, расмотрим следующие методы:

Итог: Для корректного заполнения ТЧ в открытом документе используйте прямую работу с реквизитом Объект на сервере. Это самый простой и надежный способ взаимодействия с управляемыми формами 1С.

← На главную