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

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

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

Постановка задачи и анализ контекста

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

Основная сложность заключается в разделении полномочий между клиентом (интерфейсом) и сервером (базой данных):

  1. Событие изменения реквизита (ПриИзменении) всегда возникает на клиенте.
  2. Обращение к ПараметрыСеанса (например, для получения текущего пользователя) возможно только на сервере.
  3. Добавление строки в Объект (данные формы) требует серверного контекста для корректной работы с метаданными и типами.

Шаг 1. Создание клиентского обработчика события

Для начала проанализируем ситуацию на форме. Нам нужно выбрать элемент управления (поле ввода), соответствующий реквизиту Исполнитель, и создать для него событие ПриИзменении. Важно понимать, что этот обработчик должен иметь директиву &НаКлиенте.

Рассмотрим пример кода клиентской процедуры:


&НаКлиенте
Процедура ИсполнительПриИзменении(Элемент)
    
    // Вызываем серверную процедуру для выполнения логики
    ДобавитьЗаписьВИсториюНаСервере();
    
КонецПроцедуры

Обратите внимание: мы не передаем Элемент на сервер без необходимости, так как объекты интерфейса на сервере недоступны. Наша цель на клиенте — просто "отловить" факт изменения и передать управление серверному коду.

Шаг 2. Реализация серверной логики добавления строки

Теперь разберем, что происходит "под капотом" на сервере. Здесь мы можем свободно обращаться к Объекту (который представляет собой данные нашего документа на форме) и к системным параметрам. Используем директиву &НаСервере.


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

Разбор типичных ошибок

Проанализируем ситуацию, с которой столкнулся автор темы: ошибка "Переменная не определена (ПараметрыСеанса)". Она возникает именно тогда, когда разработчик пытается обратиться к параметрам сеанса в процедуре с директивой &НаКлиенте. Тонкий клиент 1С не знает о существовании этой глобальной переменной, так как она хранится в памяти сервера приложений.

Еще один критически важный момент — соответствие типов. Часто реквизит КемИзменено в табличной части имеет тип СправочникСсылка.ФизическиеЛица, в то время как ПараметрыСеанса.ТекущийПользователь возвращает СправочникСсылка.Пользователи. Если типы не совпадают, строка добавится, но поле останется пустым. Проверьте настройки в конфигураторе: типы должны быть идентичны или реквизит должен иметь составной тип.

Расширение функционала: Использование БСП

Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), правильнее будет получать текущего пользователя через специализированные функции общего модуля. Это делает код более устойчивым к изменениям прав доступа.

Рассмотрим, как изменить строку заполнения автора:


// Вместо прямого обращения к параметрам сеанса используем БСП
НоваяСтрока.КемИзменено = Пользователи.ТекущийПользователь();

Оптимизация работы с формой

Посмотрим на ситуацию со стороны пользователя. Когда мы программно добавляем строку на сервере, фокус в таблице может остаться на старом месте. Чтобы сделать интерфейс более отзывчивым, мы можем вернуть идентификатор новой строки на клиент и активизировать её.

Разберем по шагам улучшенный вариант:


&НаКлиенте
Процедура ИсполнительПриИзменении(Элемент)
    
    // Получаем идентификатор новой строки из серверной функции
    ИдентификаторСтроки = ДобавитьЗаписьИВернутьID();
    
    // Устанавливаем фокус на новую строку в таблице
    Если ИдентификаторСтроки <> Неопределено Тогда
        Элементы.ТекущийИсполнитель.ТекущаяСтрока = ИдентификаторСтроки;
    КонецЕсли;
    
КонецПроцедуры

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

Заключение

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

← На главную