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