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