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