Разработка и Конфигурация · 11 мин
Как программно заполнить реквизит документа 1С
Как программно заполнить реквизит документа 1С: работа с объектом, табличными частями, метод Заполнить(), типовые ошибки и примеры кода на встроенном языке.
Заполнение реквизитов документа программным образом — одна из базовых задач разработки в 1С. Она встречается при создании документов на основании других, при обмене данными, при обработках массового ввода и при доработке типовых механизмов. Ошибки здесь дорого обходятся: неверно заполненный документ может попасть в отчётность, исказить проводки или заблокировать проведение.
Встроенный язык 1С предлагает несколько способов работы с реквизитами: прямое присваивание через объект документа, типовой метод Заполнить(), обработчики заполнения и работу с табличными частями. Выбор способа зависит от контекста — сервер это или клиент, новый документ или существующий, типовая конфигурация или самописная.
Ниже разобраны основные сценарии с примерами кода, особенности тонкого и толстого клиента, типичные ошибки и способы проверить результат до записи документа в базу.
Основной принцип: объект, а не ссылка
Ключевое правило, которое нужно понять в первую очередь: изменять реквизиты можно только у объекта документа, а не у ссылки. Ссылка — это лишь идентификатор записи в базе, она доступна для чтения. Чтобы что-то поменять, нужно получить модифицируемый объект: создать новый документ или загрузить существующий.
// Новый документ
НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДок.Дата = ТекущаяДатаСеанса();
НовыйДок.Организация = ОрганизацияПоУмолчанию;
НовыйДок.Записать();
// Существующий документ
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.Комментарий = "Скорректировано обработкой";
ДокОбъект.Записать();
После изменения реквизитов объект обязательно нужно записать вызовом Записать(). Без записи все изменения останутся только в памяти и будут потеряны. Если документ проводится, используйте ДокОбъект.Записать(РежимЗаписиДокумента.Проведение).
Заполнение простых реквизитов шапки
Реквизиты шапки заполняются прямым присваиванием. Важно, чтобы тип присваиваемого значения совпадал с типом реквизита, указанным в конфигураторе: ссылочному реквизиту — ссылку, числовому — число, дате — дату.
ДокОбъект = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();
ДокОбъект.Дата = ТекущаяДатаСеанса();
ДокОбъект.Организация = Организация; // ссылка на справочник
ДокОбъект.Контрагент = Контрагент; // ссылка на справочник
ДокОбъект.СуммаВключаетНДС = Истина; // булево
ДокОбъект.Комментарий = "Создан загрузкой"; // строка
Если реквизит составного типа (например, «Договор» может ссылаться на разные справочники), присваивайте значение конкретного типа — платформа сама определит вид. Если тип не совпадает ни с одним допустимым, значение будет очищено без ошибки времени выполнения, что часто становится источником трудноуловимых проблем.
Заполнение табличной части документа
Табличная часть — это коллекция строк у объекта документа. Строки добавляются методом Добавить(), после чего заполняются реквизиты строки. Очищается табличная часть методом Очистить().
ДокОбъект.Товары.Очистить();
Для Каждого СтрокаДанных Из ДанныеТоваров Цикл
НоваяСтрока = ДокОбъект.Товары.Добавить();
НоваяСтрока.Номенклатура = СтрокаДанных.Номенклатура;
НоваяСтрока.Количество = СтрокаДанных.Количество;
НоваяСтрока.Цена = СтрокаДанных.Цена;
НоваяСтрока.Сумма = СтрокаДанных.Количество * СтрокаДанных.Цена;
КонецЦикла;
Обратите внимание: суммы, ставки НДС и прочие расчётные поля платформа сама не пересчитывает при программном заполнении. В типовых конфигурациях для этого существуют процедуры вида РассчитатьСуммуСтроки() в общих модулях — их нужно вызывать явно, либо выполнять расчёт самостоятельно, как в примере выше.
При загрузке больших табличных частей не обращайтесь к строкам по индексу в цикле пересчёта — работайте с переменной строки, полученной через Добавить(). Это и быстрее, и снижает риск ошибок при изменении порядка строк.
Типовой механизм: метод Заполнить() и обработчик заполнения
В конфигурациях на БСП и в большинстве типовых решений у документов реализован обработчик события ОбработкаЗаполнения в модуле объекта. Он вызывается при интерактивном создании документа и при программном вызове метода Заполнить(ДанныеЗаполнения).
// Создание документа на основании другого
НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДок.Заполнить(СсылкаНаЗаказПокупателя);
НовыйДок.Записать();
Преимущество этого подхода в том, что вся логика заполнения (подбор договора, счетов учёта, перенос табличных частей) уже реализована в типовом коде и будет корректно работать после обновлений конфигурации. Ручное присваивание реквизитов в обход Заполнить() приводит к тому, что часть связанных данных остаётся незаполненной.
Если типовой обработчик заполнения не покрывает ваш сценарий, добавьте свою ветку в ОбработкаЗаполнения через расширение конфигурации или передайте в Заполнить() структуру с нужными данными и обработайте её в модуле объекта.
Сравнение вариантов
Подходит для простых случаев и самописных конфигураций. Минус: вся логика расчёта связанных полей ложится на ваш код.
Предпочтителен в типовых конфигурациях: использует штатную логику объекта. Ограничение: работает только с типами данных, предусмотренными обработчиком заполнения.
Используется при переносе документов между базами. Требует строгого контроля ссылочной целостности.
Заполнение реквизита из формы документа
Когда код выполняется в модуле формы (например, в обработчике команды), работа идёт через объект Объект — данные формы документа. Реквизиты доступны напрямую: Объект.Контрагент = НайденныйКонтрагент;. После изменения форма отобразит новое значение, но в базу оно попадёт только после записи.
Для вызова серверной логики из клиентской процедуры используются серверные процедуры с директивой &НаСервере. Прямой вызов ПолучитьОбъект() на клиенте в управляемом приложении недоступен — модификация данных возможна только на сервере.
&НаКлиенте
Процедура ЗаполнитьПоУмолчанию(Команда)
ЗаполнитьПоУмолчаниюНаСервере();
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьПоУмолчаниюНаСервере()
Объект.Склад = Справочники.Склады.НайтиПоНаименованию("Основной");
Объект.Валюта = Константы.ВалютаРегламентированногоУчета.Получить();
КонецПроцедуры
- 1Определите контекст: новый документ, существующий или форма документа
- 2Получите объект документа: СоздатьДокумент() или Ссылка.ПолучитьОбъект()
- 3Проверьте, есть ли типовой метод Заполнить() — если есть, используйте его
- 4Заполните реквизиты шапки с соблюдением типов значений
- 5Очистите и заполните табличные части, пересчитайте суммы
- 6Запишите объект и проверьте результат в базе
Типичные ошибки и как их избежать
Самая частая ошибка — попытка изменить реквизит через ссылку: Ссылка.Комментарий = "текст" вызовет ошибку «Поле объекта недоступно для записи». Вторая по распространённости — забытый Записать(), из-за чего код отрабатывает без ошибок, но в базе ничего не меняется.
Ещё одна группа проблем связана с проведением: если изменить реквизиты проведённого документа и записать его в режиме простой записи, проводки останутся старыми и перестанут соответствовать данным документа. После изменения такой документ нужно перепровести.
Как проверить результат
Минимальная проверка — открыть документ в пользовательском режиме и убедиться, что реквизиты заполнены и документ проводится без ошибок. Для пакетных обработок полезно программно вызывать проверку заполнения: метод ПроверитьЗаполнение() объекта вернёт Ложь, если обязательные реквизиты пусты.
Если ДокОбъект.ПроверитьЗаполнение() Тогда
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Иначе
// зафиксировать документ в протоколе ошибок
КонецЕсли;
Как проверить результат
Ссылка на документ заполнена, документ открывается в списке
Ссылка пустая или документ отсутствует — Записать() не вызывался или завершился ошибкой
ПроверитьЗаполнение() возвращает Истина
Метод возвращает Ложь — смотрите сообщения пользователю, там перечислены пустые поля
После проведения движения соответствуют данным документа
Проводки отсутствуют или устарели — документ нужно перепровести
FAQ
Можно ли заполнить реквизит документа без записи объекта?
Нет. Изменения существуют только в оперативной памяти до вызова метода Записать(). Исключение — работа в форме: там данные изменяются в данных формы, но в базу тоже попадают только при записи документа пользователем или кодом.
Как заполнить реквизит у нескольких документов сразу?
Выполните запрос к документам, получите выборку ссылок, затем в цикле для каждой ссылки вызовите ПолучитьОбъект(), измените реквизит и запишите. Для больших объёмов оборачивайте обработку в транзакцию порциями и ведите протокол ошибок, чтобы сбой одного документа не останавливал всю обработку.
Почему после присваивания реквизит остаётся пустым?
Чаще всего тип значения не входит в состав типов реквизита — платформа молча очищает такое значение. Проверьте тип реквизита в конфигураторе и тип присваиваемого значения через ТипЗнч(). Вторая причина — код выполняется не для того объекта, который потом записывается.
Чем Заполнить() отличается от прямого присваивания?
Заполнить() вызывает обработчик ОбработкаЗаполнения в модуле объекта, где реализована вся типовая логика: подстановка организации, договора, счетов учёта, копирование табличных частей из документа-основания. Прямое присваивание меняет только указанные поля, всё остальное придётся заполнять вручную.
Как заполнить реквизит в управляемой форме с клиента?
На клиенте можно менять реквизиты через Объект напрямую, если логика не требует серверных вызовов. Если нужны запросы или методы объектов — создайте серверную процедуру с директивой &НаСервере и вызывайте её из клиентской. Прямой вызов ПолучитьОбъект() на клиенте в управляемом приложении невозможен.
Безопасно ли менять реквизиты проведённых документов обработкой?
Только с перепроведением и только после резервного копирования. Изменение ключевых реквизитов (организация, дата, контрагент) влияет на проводки, регистры и отчётность. Безопасный порядок: копия базы, тест на нескольких документах, проверка отчётов, затем запуск на рабочей базе.
Что важно запомнить
Реквизиты меняются только через объект документа, а не через ссылку; изменения фиксируются методом Записать(). В типовых конфигурациях предпочитайте метод Заполнить() с типовым обработчиком. После заполнения табличных частей пересчитывайте суммы, а изменённые проведённые документы — перепроводите. Массовые изменения выполняйте только после резервного копирования.