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

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

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

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

Проанализируем исходную ситуацию. Разработчик пытается заполнить склад в табличной части ОбеспечениеМатериаламиИРаботами и получателя в табличной части ВыходныеИзделия в модуле управляемой формы документа внутри события ПриСозданииНаСервере:


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

При таком подходе разработчик сталкивается сразу с двумя проблемами: реквизиты на форме подчеркнуты красным цветом (система считает их пустыми), а при проведении документа из формы списка или по кнопке бизнес-процесса возникает ошибка валидации.

---

Причина №1. Разделение контекста выполнения (Форма vs Объект)

Давайте выясним причину, почему документ не проводится из списка или при вызове команд автоматизации. Процедура ПриСозданииНаСервере — это событие модуля формы. Код внутри него выполняется исключительно в тот момент, когда пользователь физически открывает форму документа на своем экране.

Когда мы выполняем проведение из формы списка, вызываем групповую обработку или используем автоматические команды (такие как "Передать к выполнению" в 1С:ERP), платформа работает напрямую с объектом базы данных. При этом:

  1. Экземпляр формы документа физически не создается в оперативной памяти сервера.
  2. Событие ПриСозданииНаСервере не вызывается.
  3. Код по заполнению реквизитов склада и получателя игнорируется.
  4. В базу данных записывается пустой объект, что приводит к закономерной ошибке контроля заполнения при проведении.

---

Причина №2. Пропуск связанных интерактивных обработчиков событий

В сложных современных конфигурациях 1С, таких как ERP, КА или УТ, поля на форме связаны сложными цепочками зависимостей. При ручном (интерактивном) выборе значения в колонке Склад или Получатель на форме всегда срабатывает событие ПриИзменении.

Этот обработчик выполняет множество неявных действий:

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

---

Оптимизация кода: избавляемся от запросов в цикле

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


// ПЛОХОЙ КОД: Запрос к БД на каждой строке ТЧ
Для Каждого стр Из Объект.ОбеспечениеМатериаламиИРаботами Цикл
    стр.Склад = Справочники.Склады.НайтиПоНаименованию("Производственный цех"); // Поиск в цикле!
КонецЦикла;

Если в документе будет 100 или 1000 строк, система сделает ровно столько же запросов к базе данных для поиска одного и того же склада. Это приводит к колоссальным просадкам производительности. Давайте оптимизируем этот момент, получив ссылку один раз перед началом циклов:


// ХОРОШИЙ КОД: Поиск выполняется один раз
СкладПолучатель = Справочники.Склады.НайтиПоНаименованию("Производственный цех");

Если ЗначениеЗаполнено(СкладПолучатель) Тогда
    Для Каждого стр Из Объект.ОбеспечениеМатериаламиИРаботами Цикл
        стр.Склад = СкладПолучатель;
    КонецЦикла;

    Для Каждого стр Из Объект.ВыходныеИзделия Цикл
        стр.Получатель = СкладПолучатель;
    КонецЦикла;
КонецЕсли;

---

Варианты правильного решения задачи

Рассмотрим подробнее три основных сценария программного заполнения данных в зависимости от того, какая бизнес-логика закладывается в документ.

Сценарий А. Заполнение реквизитов по умолчанию при создании нового документа

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

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

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

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

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

---

Сценарий Б. Гарантированное заполнение данных перед записью или проведением

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

Проанализируем пример кода:


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

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

---

Сценарий В. Заполнение данных строго на форме (с имитацией интерактивных действий)

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

Для реализации этого сценария в процедуре ПриСозданииНаСервере модуля формы мы должны сделать следующее:

  1. Программно присвоить значение реквизиту.
  2. Явно вызвать экспортный обработчик изменения реквизита строки (обычно он находится в модуле формы или общем клиент-серверном модуле конфигурации).
  3. Установить признак модифицированности формы, чтобы платформа знала о наличии несохраненных изменений.

Рассмотрим схематичный пример реализации в модуле формы управляемого приложения:


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

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

---

Подведем итоги

Мы подробно разобрали причины, по которым программное заполнение табличных частей в обработчиках формы может приводить к ошибкам проведения и некорректному визуальному поведению системы. Для построения надежной архитектуры в 1С всегда разделяйте контекст представления данных (формы) и контекст самих данных (объекты). Перенос бизнес-логики заполнения по умолчанию в модуль объекта — это золотой стандарт разработки, гарантирующий стабильную работу вашей программы в любых режимах проведения.

← На главную