В процессе разработки в среде «1С:Предприятие 8.3» на управляемых формах программисты часто сталкиваются с ситуацией, когда необходимо выполнить какое-либо действие с документом, который еще не был записан пользователем в базу данных. Например, при нажатии специальной кнопки нужно сформировать на основании этого документа другой объект или вывести печатную форму. Однако попытка вызвать стандартный метод записи часто приводит к ошибке. В этой статье мы подробно разберем, почему так происходит, и как правильно реализовать программную запись документа.
Разберем ситуацию, описанную автором темы. При попытке вызвать в модуле управляемой формы код Объект.Записать() система выдает ошибку «Метод объекта не обнаружен (Записать)». На первый взгляд это кажется странным, ведь у любого документа в 1С есть метод Записать(). Но здесь кроется главное различие между архитектурой обычных и управляемых форм.
Выясним причину: в управляемом приложении реквизит формы Объект на стороне клиента имеет тип ДанныеФормыСтруктура. Это специальный тип данных, предназначенный для легкой передачи информации между клиентом и сервером. Он содержит поля документа (номер, дата, табличные части), но не является самим объектом документа (ДокументОбъект). У типа ДанныеФормыСтруктура действительно нет метода Записать().
Метод Записать() существует только у типа ДокументОбъект, который «живет» исключительно на сервере. Поэтому попытка вызвать его напрямую из модуля формы на клиенте через реквизит Объект всегда будет приводить к ошибке.
Самый простой и правильный способ записать документ из его же собственной формы — это использование метода самой формы. Рассмотрим, как это выглядит в коде. Вместо обращения к реквизиту Объект, мы обращаемся к контексту формы:
&НаКлиенте
Процедура МояКоманда(Команда)
// Вместо Объект.Записать() используем метод формы
Если ЭтаФорма.Записать() Тогда
// Если запись прошла успешно, документ теперь имеет ссылку в БД
Сообщить("Документ успешно записан, ссылка: " + Объект.Ссылка);
КонецЕсли;
КонецПроцедуры
Проанализируем, что происходит при вызове ЭтаФорма.Записать(). Платформа 1С выполняет целую последовательность действий:
ДокументОбъект.ПередЗаписью, ПриЗаписи и т.д.).Часто бизнес-логика требует, чтобы программа не просто «молча» записывала документ, а спрашивала разрешение у пользователя, особенно если документ еще новый. Разберем, как реализовать это правильно с учетом современной асинхронности (чтобы код работал и в веб-клиенте).
Посмотрим на пример реализации логики: «Если документ новый — спросить, если старый — просто записать изменения».
&НаКлиенте
Процедура ВыполнитьДействие(Команда)
// Проверяем, является ли документ новым (не записанным в БД)
Если Объект.Ссылка.Пустая() Тогда
// Описываем процедуру, которая выполнится после ответа пользователя
Оповещение = Новый ОписаниеОповещения("ПослеВопросаОЗаписи", ЭтотОбъект);
ТекстВопроса = "Документ еще не записан. Для выполнения действия его необходимо записать. Продолжить?";
ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
Иначе
// Если документ уже есть в базе, просто сохраняем текущие изменения
Если ЭтаФорма.Записать() Тогда
ПродолжитьВыполнениеДействия();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОЗаписи(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Пытаемся записать документ
Если ЭтаФорма.Записать() Тогда
ПродолжитьВыполнениеДействия();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим ситуацию, которую затронул автор вопроса: пользователь изменил данные в табличной части на форме, но еще не нажал кнопку «Записать». Если вы попробуете в этот момент найти данные этого документа через запрос на сервере, вы их не найдете, так как в базе данных их еще нет.
Поэтому алгоритм всегда должен быть таким:
ЭтаФорма.Записать()). Это гарантирует, что все данные, введенные пользователем в поля и таблицы, «перекочуют» из памяти браузера или тонкого клиента в таблицы базы данных SQL.Объект.Ref), вы можете передавать эту ссылку в отчеты, печатные формы или другие обработки.Иногда нам нужно не просто сохранить черновик, а сразу провести документ. Метод Записать() позволяет передать параметры. Рассмотрим пример:
&НаКлиенте
Процедура ЗаписатьИПровести()
ПараметрыЗаписи = Новый Структура;
ПараметрыЗаписи.Вставить("РежимЗаписи", РежимЗаписиДокумента.Проведение);
// Пытаемся сразу провести документ из кода
Если ЭтаФорма.Записать(ПараметрыЗаписи) Тогда
Сообщить("Документ успешно проведен!");
КонецЕсли;
КонецПроцедуры
Важно помнить, что если в документе не заполнены обязательные поля, метод Записать() вернет Ложь, а пользователю будет выведено стандартное сообщение об ошибке заполнения. Это очень удобно, так как вам не нужно вручную проверять заполнение реквизитов перед записью.
Для успешной работы с новыми документами в управляемом интерфейсе 1С следуйте трем правилам:
Объект.Записать() на клиенте — используйте ЭтаФорма.Записать().Объект.Ссылка.Пустая().Такой подход обеспечит стабильную работу вашей конфигурации и отсутствие ошибок при взаимодействии пользователя с интерфейсом системы.