Как в табличной части документов 1С вывести составной код номенклатуры и характеристики через дробь?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет
← На главную

В типовых конфигурациях 1С, таких как 1С:Управление нашей фирмой (УНФ), часто возникает задача кастомизации интерфейса под нужды складской логистики. Одной из таких задач является вывод специфических идентификаторов в табличную часть документов (например, в «Заказ покупателя» или «Приходную накладную»). Если в организации привыкли работать с кодами, стандартного отображения наименований может быть недостаточно. Рассмотрим, как программно реализовать вывод составного кода формата «КодНоменклатуры / КодХарактеристики» в одной колонке, сохранив при этом типовую конфигурацию на поддержке.

Анализ проблемы и выбор стратегии

Основная сложность заключается в том, что нам необходимо обработать сразу большое количество документов (около 20 форм) и сделать это максимально эффективно с точки зрения будущих обновлений. Использование расширений конфигурации является здесь единственно верным архитектурным решением. Мы проанализируем ситуацию: стандартный механизм «Изменить форму» позволяет вытащить код номенклатуры или код характеристики отдельными колонками, но он не позволяет «склеить» их через произвольный разделитель (дробь) в одной ячейке. Поэтому нам потребуется программное вмешательство.

Решение 1: Программное создание группы колонок и использование условного оформления

Этот метод считается наиболее «чистым», так как он не требует добавления новых реквизитов в базу данных. Мы будем программно создавать две колонки и помещать их в одну группу с режимом отображения «В ячейке». Для того чтобы имитировать логику «если есть характеристика — показываем оба кода, если нет — только один», воспользуемся механизмом Условного оформления.

Рассмотрим пример кода, который необходимо разместить в расширении для формы документа (в обработчике ПриСозданииНаСервере):


&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Определяем родительскую группу (табличную часть)
    ТаблицаЗапасы = Элементы.Запасы;
    
    // Создаем группу для объединения кодов в одной ячейке
    ГруппаКод = Элементы.Вставить("ГруппаСоставнойКод", Тип("ГруппаФормы"), ТаблицаЗапасы, Элементы.ЗапасыНоменклатура); 
    ГруппаКод.Вид = ВидГруппыФормы.ГруппаКолонок;
    ГруппаКод.Группировка = ГруппировкаКолонок.ВЯчейке;
    ГруппаКод.Заголовок = "Код / Хар.";

    // Добавляем поле кода номенклатуры
    НовыйЭлементНом = Элементы.Добавить("КолонкаКодНом", Тип("ПолеФормы"), ГруппаКод);
    НовыйЭлементНом.Вид = ВидПоляФормы.ПолеНадписи;
    НовыйЭлементНом.ПутьКДанным = "Объект.Запасы.Номенклатура.Код"; 
    
    // Добавляем поле разделителя (декорация)
    НовыйЭлементРазделитель = Элементы.Добавить("КолонкаРазделитель", Тип("ПолеФормы"), ГруппаКод);
    НовыйЭлементРазделитель.Вид = ВидПоляФормы.ПолеНадписи;
    НовыйЭлементРазделитель.Заголовок = " / ";

    // Добавляем поле кода характеристики
    НовыйЭлементХар = Элементы.Добавить("КолонкаКодХар", Тип("ПолеФормы"), ГруппаКод);
    НовыйЭлементХар.Вид = ВидПоляФормы.ПолеНадписи;
    НовыйЭлементХар.ПутьКДанным = "Объект.Запасы.Характеристика.Код"; 
    
КонецПроцедуры

Теперь разберем, как скрыть разделитель и код характеристики, если характеристика не выбрана. Для этого программно настроим Условное оформление формы. Это позволит избежать лишних символов в строках, где используется только номенклатура.


&НаСервере
&После("УстановитьУсловноеОформлениеФормы")
Процедура Расш1_УстановитьУсловноеОформлениеФормы()
    
    // Скрываем разделитель и код характеристики, если характеристика пустая
    ЭлементОформления = УсловноеОформление.Элементы.Добавить();
    
    ПолеРазделитель = ЭлементОформления.Поля.Элементы.Добавить();
    ПолеРазделитель.Поле = Новый ПолеКомпоновкиДанных("КолонкаРазделитель");
    
    ПолеКодХар = ЭлементОформления.Поля.Элементы.Добавить();
    ПолеКодХар.Поле = Новый ПолеКомпоновкиДанных("КолонкаКодХар");
    
    ОтборЭлемента = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Запасы.Характеристика");
    ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
    
    ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Отображать", Ложь);
    
КонецПроцедуры

Решение 2: Использование строкового реквизита формы (Вычисляемое поле)

Если заказчик настаивает на жестком формате строки или требуется сложная логика формирования (например, поиск кода по какому-то особому алгоритму), лучше использовать текстовый реквизит формы. Выясним причину, почему это может быть удобнее: такой подход позволяет манипулировать строкой как единым объектом, что упрощает копирование значения пользователем.

Рассмотрим шаги реализации:

  1. В расширении для каждого документа добавляем в таблицу Запасы (или аналогичную) строковый реквизит формы СоставнойКод.
  2. Выводим этот реквизит в колонки таблицы на форме.
  3. Создаем общую процедуру в общем модуле расширения, которая будет обходить строки таблицы и заполнять этот реквизит.

Пример функции для заполнения строки:


Функция СформироватьСоставнойКод(СтрокаТаблицы) Экспорт
    КодНом = СтрокаТаблицы.Номенклатура.Код;
    Если ЗначениеЗаполнено(СтрокаТаблицы.Характеристика) Тогда
        Возврат Строка(КодНом) + " / " + Строка(СтрокаТаблицы.Характеристика.Код);
    Иначе
        Возврат Строка(КодНом);
    КонецЕсли;
КонецФункции

Проанализируем ситуацию с производительностью: вызов СтрокаТаблицы.Номенклатура.Код в цикле по строкам документа может привести к большому количеству запросов к базе данных (проблема N+1). Чтобы избежать этого, при чтении документа рекомендуется использовать один запрос, который соберет все коды номенклатуры и характеристик, задействованных в табличной части, и поместит их во временное Соответствие.

Оптимизация для 20+ документов

Чтобы не прописывать один и тот же код в 20 различных формах, применим метод глобального перехвата. Создадим в расширении общий модуль с типом «Сервер» и добавим в него процедуру, обрабатывающую создание любой формы.

Рассмотрим пример реализации универсального обработчика:


// В общем модуле расширения
&После("ПриСозданииНаСервере")
Процедура Глобальный_ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
    
    // Список имен форм, которые подлежат модификации
    МассивИменФорм = Новый Массив;
    МассивИменФорм.Добавить("Документ.ЗаказПокупателя.Форма.ФормаДокумента");
    МассивИменФорм.Добавить("Документ.ПриходнаяНакладная.Форма.ФормаДокумента");
    // ... заполняем весь список документов
    
    Если МассивИменФорм.Найти(Форма.ИмяФормы) = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Логика добавления колонок, описанная в Решении 1
    // Используем Форма.Элементы для программного создания
КонецПроцедуры

Этот метод позволяет внести изменения один раз, и они автоматически подтянутся во все нужные документы. Это минимизирует трудозатраты и делает решение легко поддерживаемым.

Важные замечания

Проанализируем дополнительные аспекты, которые могут возникнуть при эксплуатации:

Таким образом, мы рассмотрели наиболее эффективные способы вывода составного кода в типовых конфигурациях. Использование групп колонок в сочетании с условным оформлением через расширение — это быстрый и надежный способ удовлетворить требования заказчика, не нарушая целостность типовой системы.

← На главную