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