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