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