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

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

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

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

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

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

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

Когда вообще нужно перечитывать документ

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

Типичные ситуации, когда требуется перечитывание:

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

Перечитывание на сервере: метод Прочитать()

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

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

// ... какая-то логика, данные могли устареть

ДокОбъект.Прочитать();

// теперь объект содержит актуальную версию из базы

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

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

Перечитывание в открытой управляемой форме

В управляемой форме документа основной реквизит Объект имеет тип ДанныеФормыСтруктура, и простого метода Обновить() у него нет. Перечитывание делается через серверный вызов: на сервере данные формы преобразуются в объект, объект перечитывается, затем значение возвращается в форму.

Вариант 1: через РеквизитФормыВЗначение

&НаСервере

Процедура ПеречитатьДокументНаСервере()

ДокОбъект = РеквизитФормыВЗначение("Объект");

ДокОбъект.Прочитать();

ЗначениеВРеквизитФормы(ДокОбъект, "Объект");

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

&НаКлиенте

Процедура Перечитать(Команда)

Если Модифицированность Тогда

ПоказатьВопрос(Новый ОписаниеОповещения("ПеречитатьЗавершение", ЭтотОбъект),

"Несохранённые изменения будут потеряны. Продолжить?",

РежимДиалогаВопрос.ДаНет);

Иначе

ПеречитатьДокументНаСервере();

КонецЕсли;

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

Вариант 2: метод Прочитать() самой формы

У управляемой формы есть собственный метод Прочитать(), который перечитывает основной реквизит из базы. Это более короткий путь, доступный в серверном контексте формы:

&НаСервере

Процедура ПеречитатьНаСервере()

ЭтаФорма.Прочитать();

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

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

Порядок действий для кнопки «Перечитать»
  1. 1
    Добавьте команду формы и кнопку в командную панель
  2. 2
    В клиентском обработчике проверьте Модифицированность и при необходимости задайте вопрос
  3. 3
    В серверной процедуре вызовите ЭтаФорма.Прочитать() или пару РеквизитФормыВЗначение/ЗначениеВРеквизитФормы
  4. 4
    После перечитывания сбросьте признак модифицированности: Модифицированность = Ложь
  5. 5
    Проверьте, что на форме отобразились свежие данные

Перечитывание в обычных формах (толстый клиент)

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

Процедура КнопкаОбновитьНажатие(Элемент)

Если ЭтаФорма.Модифицированность() Тогда

Ответ = Вопрос("Изменения будут потеряны. Продолжить?", РежимДиалогаВопрос.ДаНет);

Если Ответ = КодВозвратаДиалога.Нет Тогда

Возврат;

КонецЕсли;

КонецЕсли;

ЭтаФорма.Обновить();

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

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

Сравнение способов перечитывания

ДокументОбъект.Прочитать()

Серверные процедуры и фоновые задания. Не подходит для обновления открытой формы напрямую.

ЭтаФорма.Прочитать()

Управляемая форма, краткий способ. Нет места для вставки промежуточной логики.

РеквизитФормыВЗначение + Прочитать + ЗначениеВРеквизитФормы

Управляемая форма, когда между чтением и отображением нужна дополнительная обработка. Дороже по серверным вызовам.

ЭтаФорма.Обновить()

Только обычные формы толстого клиента. В управляемых формах недоступен.

Конфликты блокировок и повторное чтение перед записью

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

Процедура УстановитьСтатус(Ссылка, НовыйСтатус) Экспорт

НачатьТранзакцию();

Попытка

Блокировка = Новый БлокировкаДанных;

ЭлементБлокировки = Блокировка.Добавить("Документ.РеализацияТоваровУслуг");

ЭлементБлокировки.УстановитьЗначение("Ссылка", Ссылка);

Блокировка.Заблокировать();

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

ДокОбъект.Статус = НовыйСтатус;

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

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ВызватьИсключение;

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

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

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

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

Как проверить результат перечитывания

Данные на форме
Норма

Поля и табличные части показывают версию из базы

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

Остались старые значения — чтение выполнено не у того объекта

Модифицированность формы
Норма

После перечитывания равна Ложь

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

Осталась Истина — форма считает данные изменёнными

Версия данных
Норма

При повторной записи нет ошибки «данные были изменены»

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

Ошибка конфликта сохраняется — объект не перечитан

Проведение
Норма

Признак Проведен соответствует базе

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

Форма показывает устаревший статус проведения

Типичные ошибки при программном перечитывании

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

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

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

Типичные ошибки
01
Вызов ПолучитьОбъект().Прочитать() из клиентского контекста управляемой формы — форма не обновляется, потому что прочитан отдельный объект
02
Перечитывание без проверки Модифицированности — теряются несохранённые данные пользователя
03
Чтение внутри транзакции без управляемой блокировки — конфликт при записи сохраняется
04
Игнорирование исключения при чтении удалённого документа — обработка падает без понятного сообщения

Частые вопросы

Чем Прочитать() отличается от ПолучитьОбъект()?

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

Почему после Прочитать() на форме ничего не изменилось?

Скорее всего, вы перечитали отдельный объект, полученный через ПолучитьОбъект(), а не реквизит формы. В управляемой форме используйте ЭтаФорма.Прочитать() в серверном контексте или пару РеквизитФормыВЗначение/ЗначениеВРеквизитФормы.

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

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

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

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

Что произойдёт, если документ удалили, а я вызываю Прочитать()?

Метод завершится исключением, потому что объекта с такой ссылкой в базе больше нет. Перед чтением проверяйте существование ссылки запросом или обрабатывайте исключение через Попытка/Исключение с понятным сообщением пользователю.

Нужно ли перечитывать документ сразу после Записать() в том же объекте?

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

Итог

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

На сервере документ перечитывается методом Прочитать() у объекта, в управляемой форме — через ЭтаФорма.Прочитать() или преобразование реквизита в значение, в обычной форме — методом Обновить(). Всегда проверяйте Модифицированность перед перечитыванием и используйте управляемые блокировки при чтении перед записью.