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

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

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

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

Изменение реквизита документа программно — одна из базовых задач при доработке конфигураций 1С: исправление данных обработкой, автозаполнение полей при записи, интеграция с внешними системами. Ключевой принцип один: нельзя изменить реквизит через ссылку на документ напрямую — нужно получить объект документа, изменить его свойства и записать. Попытка присвоить значение через ссылку приведёт к ошибке «Поле объекта не обнаружено» или просто не сработает.

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

Базовый способ: ПолучитьОбъект и Записать

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

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

ДокументОбъект.Комментарий = "Изменено обработкой";

ДокументОбъект.Ответственный = ПараметрыСеанса.ТекущийПользователь;

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

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

bsl
ДокументОбъект = ДокументСсылка.ПолучитьОбъект();
ДокументОбъект.Склад = НовыйСклад;
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

Изменение табличной части документа

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

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

Для Каждого СтрокаТовара Из ДокументОбъект.Товары Цикл

СтрокаТовара.Цена = СтрокаТовара.Цена * 1.1;

КонецЦикла;

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

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

Особенности изменения проведённых документов

Для проведённого документа есть два варианта. Первый — записать с режимом Запись: реквизиты изменятся, движения по регистрам останутся прежними. Это уместно для «неучётных» полей вроде комментария или ответственного. Второй — перепровести документ: тогда движения будут пересчитаны с учётом новых значений реквизитов.

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

Изменение реквизита без получения объекта: когда это возможно

Через ссылку реквизиты доступны только для чтения: ДокументСсылка.Номер вернёт значение, но присвоить его нельзя. Исключение — прямое обновление через запрос с конструкцией ИЗМЕНИТЬ, однако встроенный язык 1С такой возможности для таблиц документов не предоставляет в штатном режиме; обходные пути через внешние компоненты и прямой SQL нарушают логику платформы и поддерживаемы не будут.

Легитимная альтернатива — установка значений через менеджер документа при создании нового документа: Документы.РеализацияТоваровУслуг.СоздатьДокумент() сразу возвращает объект, и заполнение реквизитов до первой записи — самый быстрый сценарий. Для существующих документов ПолучитьОбъект() остаётся единственным корректным путём.

Транзакции и обработка ошибок при записи

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

Для Каждого СтрокаВыборки Из Выборка Цикл

Попытка

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

ДокументОбъект.Комментарий = НовыйКомментарий;

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

Исключение

Сообщить("Не удалось изменить " + СтрокаВыборки.Ссылка

+ ": " + ОписаниеОшибки());

КонецПопытки;

КонецЦикла;

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

Порядок безопасного массового изменения
  1. 1
    Сделайте резервную копию базы или протестируйте обработку на копии
  2. 2
    Сформируйте запросом список ссылок на документы для изменения
  3. 3
    В цикле получайте объект, меняйте реквизит, записывайте в нужном режиме
  4. 4
    Оборачивайте запись в Попытка/Исключение и собирайте протокол ошибок
  5. 5
    Проверьте результат на выборке документов и в связанных отчётах

Проверка результата и типовые ошибки

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

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

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

FAQ: частые вопросы

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

Нет, штатного способа точечного обновления одного поля встроенный язык не предоставляет. Любое изменение проходит через получение объекта и Записать(). Прямые обращения к СУБД минуют механизмы платформы, ломают версионирование и кэш и считаются недопустимой практикой.

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

Технически так же — через ПолучитьОбъект() и Записать(). Но сначала решите, зачем это нужно: обычно корректнее снять пометку удаления методом УстановитьПометкуУдаления(Ложь), изменить данные и затем работать с документом как с обычным.

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

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

Как изменить реквизит у документов за закрытый период?

Нужно временно сдвинуть дату запрета редактирования для пользователя или группы, выполнить изменения и вернуть дату обратно. Делать это следует осознанно: изменение документов закрытого периода может потребовать корректировки отчётности и перепроведения зависимых документов.

Чем отличается ОбменДанными.Загрузка = Истина при записи?

Этот режим отключает проверки заполнения и бизнес-логику подписок на события записи. Он предназначен для загрузки данных из обменов. Использовать его для обычного изменения реквизитов опасно: документ запишется без контроля, но может оказаться в неконсистентном состоянии.

Итог

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

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