К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как программно заполнить реквизит документа 1С

Как программно заполнить реквизит документа 1С: работа с объектом, табличными частями, метод Заполнить(), типовые ошибки и примеры кода на встроенном языке.

Заполнение реквизитов документа программным образом — одна из базовых задач разработки в 1С. Она встречается при создании документов на основании других, при обмене данными, при обработках массового ввода и при доработке типовых механизмов. Ошибки здесь дорого обходятся: неверно заполненный документ может попасть в отчётность, исказить проводки или заблокировать проведение.

Встроенный язык 1С предлагает несколько способов работы с реквизитами: прямое присваивание через объект документа, типовой метод Заполнить(), обработчики заполнения и работу с табличными частями. Выбор способа зависит от контекста — сервер это или клиент, новый документ или существующий, типовая конфигурация или самописная.

Ниже разобраны основные сценарии с примерами кода, особенности тонкого и толстого клиента, типичные ошибки и способы проверить результат до записи документа в базу.

Основной принцип: объект, а не ссылка

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

// Новый документ

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДок.Дата = ТекущаяДатаСеанса();

НовыйДок.Организация = ОрганизацияПоУмолчанию;

НовыйДок.Записать();

// Существующий документ

ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

ДокОбъект.Комментарий = "Скорректировано обработкой";

ДокОбъект.Записать();

После изменения реквизитов объект обязательно нужно записать вызовом Записать(). Без записи все изменения останутся только в памяти и будут потеряны. Если документ проводится, используйте ДокОбъект.Записать(РежимЗаписиДокумента.Проведение).

Заполнение простых реквизитов шапки

Реквизиты шапки заполняются прямым присваиванием. Важно, чтобы тип присваиваемого значения совпадал с типом реквизита, указанным в конфигураторе: ссылочному реквизиту — ссылку, числовому — число, дате — дату.

ДокОбъект = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();

ДокОбъект.Дата = ТекущаяДатаСеанса();

ДокОбъект.Организация = Организация; // ссылка на справочник

ДокОбъект.Контрагент = Контрагент; // ссылка на справочник

ДокОбъект.СуммаВключаетНДС = Истина; // булево

ДокОбъект.Комментарий = "Создан загрузкой"; // строка

Если реквизит составного типа (например, «Договор» может ссылаться на разные справочники), присваивайте значение конкретного типа — платформа сама определит вид. Если тип не совпадает ни с одним допустимым, значение будет очищено без ошибки времени выполнения, что часто становится источником трудноуловимых проблем.

Заполнение табличной части документа

Табличная часть — это коллекция строк у объекта документа. Строки добавляются методом Добавить(), после чего заполняются реквизиты строки. Очищается табличная часть методом Очистить().

ДокОбъект.Товары.Очистить();

Для Каждого СтрокаДанных Из ДанныеТоваров Цикл

НоваяСтрока = ДокОбъект.Товары.Добавить();

НоваяСтрока.Номенклатура = СтрокаДанных.Номенклатура;

НоваяСтрока.Количество = СтрокаДанных.Количество;

НоваяСтрока.Цена = СтрокаДанных.Цена;

НоваяСтрока.Сумма = СтрокаДанных.Количество * СтрокаДанных.Цена;

КонецЦикла;

Обратите внимание: суммы, ставки НДС и прочие расчётные поля платформа сама не пересчитывает при программном заполнении. В типовых конфигурациях для этого существуют процедуры вида РассчитатьСуммуСтроки() в общих модулях — их нужно вызывать явно, либо выполнять расчёт самостоятельно, как в примере выше.

При загрузке больших табличных частей не обращайтесь к строкам по индексу в цикле пересчёта — работайте с переменной строки, полученной через Добавить(). Это и быстрее, и снижает риск ошибок при изменении порядка строк.
ПЗ
Практическое замечание

Типовой механизм: метод Заполнить() и обработчик заполнения

В конфигурациях на БСП и в большинстве типовых решений у документов реализован обработчик события ОбработкаЗаполнения в модуле объекта. Он вызывается при интерактивном создании документа и при программном вызове метода Заполнить(ДанныеЗаполнения).

// Создание документа на основании другого

НовыйДок = Документы.РеализацияТоваровУслуг.СоздатьДокумент();

НовыйДок.Заполнить(СсылкаНаЗаказПокупателя);

НовыйДок.Записать();

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

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

Сравнение вариантов

Прямое присваивание реквизитов

Подходит для простых случаев и самописных конфигураций. Минус: вся логика расчёта связанных полей ложится на ваш код.

Метод Заполнить(ДанныеЗаполнения)

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

Копирование через ЗначениеВСтрокуВнутр / обмен

Используется при переносе документов между базами. Требует строгого контроля ссылочной целостности.

Заполнение реквизита из формы документа

Когда код выполняется в модуле формы (например, в обработчике команды), работа идёт через объект Объект — данные формы документа. Реквизиты доступны напрямую: Объект.Контрагент = НайденныйКонтрагент;. После изменения форма отобразит новое значение, но в базу оно попадёт только после записи.

Для вызова серверной логики из клиентской процедуры используются серверные процедуры с директивой &НаСервере. Прямой вызов ПолучитьОбъект() на клиенте в управляемом приложении недоступен — модификация данных возможна только на сервере.

&НаКлиенте

Процедура ЗаполнитьПоУмолчанию(Команда)

ЗаполнитьПоУмолчаниюНаСервере();

КонецПроцедуры

&НаСервере

Процедура ЗаполнитьПоУмолчаниюНаСервере()

Объект.Склад = Справочники.Склады.НайтиПоНаименованию("Основной");

Объект.Валюта = Константы.ВалютаРегламентированногоУчета.Получить();

КонецПроцедуры

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

Типичные ошибки и как их избежать

Самая частая ошибка — попытка изменить реквизит через ссылку: Ссылка.Комментарий = "текст" вызовет ошибку «Поле объекта недоступно для записи». Вторая по распространённости — забытый Записать(), из-за чего код отрабатывает без ошибок, но в базе ничего не меняется.

Ещё одна группа проблем связана с проведением: если изменить реквизиты проведённого документа и записать его в режиме простой записи, проводки останутся старыми и перестанут соответствовать данным документа. После изменения такой документ нужно перепровести.

Типичные ошибки
01
Изменение реквизита через ссылку вместо объекта — ошибка «недоступно для записи»
02
Отсутствие вызова Записать() — изменения теряются без сообщения об ошибке
03
Присваивание значения несовместимого типа — реквизит молча очищается
04
Забытый пересчёт сумм и НДС после заполнения табличной части — документ не проходит контроль при проведении
05
Запись изменённого проведённого документа без перепроведения — расхождение данных и проводок

Как проверить результат

Минимальная проверка — открыть документ в пользовательском режиме и убедиться, что реквизиты заполнены и документ проводится без ошибок. Для пакетных обработок полезно программно вызывать проверку заполнения: метод ПроверитьЗаполнение() объекта вернёт Ложь, если обязательные реквизиты пусты.

Если ДокОбъект.ПроверитьЗаполнение() Тогда

ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

Иначе

// зафиксировать документ в протоколе ошибок

КонецЕсли;

Контрольные точки

Как проверить результат

Документ записался в базу
Норма

Ссылка на документ заполнена, документ открывается в списке

Тревожный признак

Ссылка пустая или документ отсутствует — Записать() не вызывался или завершился ошибкой

Обязательные реквизиты
Норма

ПроверитьЗаполнение() возвращает Истина

Тревожный признак

Метод возвращает Ложь — смотрите сообщения пользователю, там перечислены пустые поля

Проводки документа
Норма

После проведения движения соответствуют данным документа

Тревожный признак

Проводки отсутствуют или устарели — документ нужно перепровести

FAQ

Можно ли заполнить реквизит документа без записи объекта?

Нет. Изменения существуют только в оперативной памяти до вызова метода Записать(). Исключение — работа в форме: там данные изменяются в данных формы, но в базу тоже попадают только при записи документа пользователем или кодом.

Как заполнить реквизит у нескольких документов сразу?

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

Почему после присваивания реквизит остаётся пустым?

Чаще всего тип значения не входит в состав типов реквизита — платформа молча очищает такое значение. Проверьте тип реквизита в конфигураторе и тип присваиваемого значения через ТипЗнч(). Вторая причина — код выполняется не для того объекта, который потом записывается.

Чем Заполнить() отличается от прямого присваивания?

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

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

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

Безопасно ли менять реквизиты проведённых документов обработкой?

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

Итог

Что важно запомнить

Реквизиты меняются только через объект документа, а не через ссылку; изменения фиксируются методом Записать(). В типовых конфигурациях предпочитайте метод Заполнить() с типовым обработчиком. После заполнения табличных частей пересчитывайте суммы, а изменённые проведённые документы — перепроводите. Массовые изменения выполняйте только после резервного копирования.