Как добавить и отобразить пользовательскую колонку в форме подбора товаров в 1С:УТ 11?

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

В работе с конфигурацией 1С:Управление торговлей 11 (УТ 11) часто возникает потребность в расширении стандартных форм для вывода дополнительной информации. Одной из таких задач является добавление пользовательской колонки, например, для отображения цены по определенному виду цен, в форму подбора товаров. Эта задача может показаться нетривиальной из-за особенностей архитектуры УТ 11, где активно используются динамические списки и управляемые формы. В этой статье мы подробно разберем, как решить эту задачу, используя расширения и программный код.

Почему это нужно и в чем сложность?

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

Сложность задачи в 1С:УТ 11 заключается в нескольких аспектах, которые мы рассмотрим подробнее:

  1. Динамические списки: Большинство форм подбора в современных конфигурациях 1С построены на базе динамических списков. Эти списки формируют данные с помощью запросов, которые исполняются на сервере. Простое добавление реквизита на форму не приведет к появлению данных в таблице, если этот реквизит не включен в запрос, питающий динамический список.
  2. Модификация запроса: Запрос динамического списка в типовых конфигурациях 1С может быть достаточно сложным, многосоставным и формироваться программно в общих модулях. Нам необходимо найти правильное место для его модификации и аккуратно встроить наши данные.
  3. Управляемые формы: В управляемых формах все элементы управления создаются и управляются программно или через механизм расширений. Добавление новой колонки требует не только изменения запроса, но и программного создания элемента формы (типа "ПолеФормы") и его правильной привязки к добавленному полю данных.
  4. Сохранение типовой конфигурации: Прямые изменения в типовой конфигурации 1С крайне нежелательны, так как они усложняют процесс обновления конфигурации и могут привести к потере доработок. Все модификации рекомендуется выполнять с использованием мощного механизма расширений, который позволяет добавлять функциональность без изменения исходных объектов.

Основные шаги по добавлению колонки в форму подбора

Для успешного решения задачи, мы рекомендуем пройти следующие этапы, уделяя внимание каждой детали:

  1. Модификация текста запроса динамического списка

Первый и самый важный шаг — это включение нужных нам данных в текст запроса, который питает динамический список формы подбора. Как мы уже выяснили, в 1С:УТ 11 формы подбора товаров используют динамические списки. Для добавления новой колонки, которая не является реквизитом объекта (например, вычисляемая цена), нам потребуется изменить текст запроса, формирующего данные для этого списка.

Мы знаем, что в общем модуле ПодборТоваровСервер содержится логика формирования запроса для динамического списка формы подбора. Конкретно, нас будет интересовать место, где формируется свойство ТекстЗапроса динамического списка. В типовых конфигурациях часто встречается процедура или функция, которая возвращает или модифицирует этот текст. Например, это может быть свойство ПодборТоваровСервер.ТекстЗапросаСпискаФормыПодбора или другие процедуры, отвечающие за инициализацию динамического списка.

Предположим, нам нужно вывести цену по определенному виду цен. Для этого мы можем добавить в запрос левое соединение (LEFT JOIN) с регистром сведений "Цены номенклатуры.СрезПоследних" по номенклатуре и виду цены. Это позволит нам получить актуальную цену для каждой номенклатуры в списке.

Критически важный момент: Все эти изменения необходимо производить через расширение конфигурации. Для этого мы перенесем процедуру формы (например, ПриСозданииНаСервере или другую, где формируется динамический список или его запрос) в расширение с модификатором "После". Это позволит нам выполнить наш код после выполнения типового кода конфигурации, не изменяя ее напрямую и сохраняя возможность легкого обновления.

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


// Пример в процедуре ПриСозданииНаСервере формы подбора (перенесенной в расширение с модификатором "После")
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // Предположим, что динамический список на форме имеет имя "Список"
    // Необходимо убедиться, что имя динамического списка соответствует действительности.
    Если Элементы.Найти("Список") <> Неопределено Тогда
        ДинамическийСписок = Элементы.Список;

        // Получаем текущий текст запроса динамического списка
        ТекстЗапроса = ДинамическийСписок.ТекстЗапроса;

        // Модифицируем текст запроса, добавляя необходимые поля через LEFT JOIN.
        // Этот пример - упрощенный. В реальной конфигурации текст запроса может быть сложнее,
        // и потребуется более аккуратная вставка.
        // Важно убедиться, что поле не добавлено повторно.
        Если СтрНайти(ТекстЗапроса, "ЦенаПоВидуЦен") = 0 Тогда // Проверяем, чтобы не добавить поле дважды

            // Находим место для вставки нового поля в секцию ВЫБРАТЬ
            // и для вставки LEFT JOIN в секцию ИЗ.
            // Это может быть сделано путем поиска ключевых слов "ВЫБРАТЬ" и "ИЗ".
            ПозицияВыбрать = СтрНайти(ТекстЗапроса, "ВЫБРАТЬ");
            ПозицияИз = СтрНайти(ТекстЗапроса, "ИЗ");

            Если ПозицияВыбрать > 0 И ПозицияИз > 0 Тогда
                ЧастьДоИз = Лев(ТекстЗапроса, ПозицияИз - 1);
                ЧастьПослеИз = Сред(ТекстЗапроса, ПозицияИз);

                // Добавляем поле в секцию ВЫБРАТЬ. Обычно добавляем после основных полей.
                // Здесь мы используем СтрЗаменить для добавления после первого ВЫБРАТЬ
                ЧастьДоИз = СтрЗаменить(ЧастьДоИз, "ВЫБРАТЬ", "ВЫБРАТЬ
                |    ЦеныНоменклатурыСрезПоследних.Цена КАК ЦенаПоВидуЦен,"); // Добавляем наше поле

                // Добавляем LEFT JOIN. Важно выбрать правильный вид цен.
                // Здесь мы используем параметр &ВидЦены.
                ТекстЗапроса = ЧастьДоИз +
                    "
                    |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
                    |            &ДатаСреза,
                    |            ВидЦены = &ВидЦены) КАК ЦеныНоменклатурыСрезПоследних
                    |        ПО Номенклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
                    |" + ЧастьПослеИз;

                // Устанавливаем параметры запроса для среза цен
                // Дата среза - текущая дата
                ДинамическийСписок.Параметры.УстановитьЗначениеПараметра("ДатаСреза", ТекущаяДата());
                // Пример: ищем вид цены "Оптовая". Можно получить из настроек или реквизита формы.
                ВидЦены = ПланыВидовХарактеристик.ВидыЦенНоменклатуры.НайтиПоНаименованию("Оптовая");
                Если ВидЦены <> Неопределено Тогда
                    ДинамическийСписок.Параметры.УстановитьЗначениеПараметра("ВидЦены", ВидЦены);
                Иначе
                    // Обработка ситуации, если вид цены не найден
                    Сообщить("Внимание: Вид цены 'Оптовая' не найден. Колонка с ценой может быть пустой.", СтатусСообщения.Важное);
                КонецЕсли;

                // Применяем измененный текст запроса к динамическому списку
                ДинамическийСписок.ТекстЗапроса = ТекстЗапроса;
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

После того как поле с нужными данными добавлено в запрос динамического списка, его необходимо отобразить на форме. Это делается путем программного создания нового элемента формы типа "ПолеФормы" и привязки его к добавленному полю динамического списка. Этот код также должен быть размещен в процедуре формы, перенесенной в расширение (например, ПриСозданииНаСервере с модификатором "После"), так как мы хотим модифицировать форму после ее создания типовым кодом.

Разберем по шагам, как это сделать:

  1. Создайте новый элемент формы: Мы будем использовать метод Элементы.Добавить() для создания нового поля.
  2. 
    // В рамках процедуры ПриСозданииНаСервере
    // Добавляем новый элемент в коллекцию подчиненных элементов динамического списка.
    // Предположим, что динамический список - это "Список"
    НовЭлемент = Элементы.Список.ПодчиненныеЭлементы.Добавить("ЦенаПоВидуЦенКолонка", Тип("ПолеФормы"));
    

Здесь "ЦенаПоВидуЦенКолонка" — это уникальное имя нашего нового элемента формы. Важно добавить его как подчиненный элемент к самому динамическому списку, чтобы он корректно отображался как колонка.

НовЭлемент.Вид = ВидПоляФормы.ПолеВвода;


НовЭлемент.ПутьКДанным = "Список.ЦенаПоВидуЦен"; // "Список" - имя динамического списка, "ЦенаПоВидуЦен" - алиас поля в запросе

НовЭлемент.Заголовок = "Цена (Опт)";

НовЭлемент.Видимость = Истина;

Пример кода для добавления колонки на форму:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // ... (код модификации запроса, как показано выше)

    // Добавляем колонку на форму
    Если Элементы.Найти("Список") <> Неопределено Тогда
        // Получаем коллекцию элементов (колонок) динамического списка
        СписокЭлементовФормы = Элементы.Список.ПодчиненныеЭлементы;

        // Проверяем, не добавлена ли колонка уже, чтобы избежать дублирования
        Если СписокЭлементовФормы.Найти("ЦенаПоВидуЦенКолонка") = Неопределено Тогда
            НовЭлемент = СписокЭлементовФормы.Добавить("ЦенаПоВидуЦенКолонка", Тип("ПолеФормы"));
            НовЭлемент.Вид = ВидПоляФормы.ПолеВвода;
            НовЭлемент.ПутьКДанным = "Список.ЦенаПоВидуЦен"; // Привязываем к полю из запроса
            НовЭлемент.Заголовок = "Цена (Опт)";
            НовЭлемент.Видимость = Истина;
            НовЭлемент.Ширина = 12; // Задаем ширину колонки
            НовЭлемент.ТолькоПросмотр = Истина; // Делаем колонку только для просмотра
            НовЭлемент.ИзменятьСостав = Ложь; // Запрещаем пользователю удалять или изменять эту колонку через "Изменить форму"
            НовЭлемент.ИзменятьВидимость = Ложь; // Запрещаем пользователю скрывать колонку

            // Можно настроить порядок. Например, найти колонку "Наименование" и вставить после нее.
            // Для этого потребуется найти элемент по ПутьКДанным
            ИндексКолонкиНаименования = -1;
            Для Каждого ЭлКолонки Из СписокЭлементовФормы Цикл
                Если ЭлКолонки.ПутьКДанным = "Список.Наименование" Тогда // Ищем колонку по ПутьКДанным
                    ИндексКолонкиНаименования = СписокЭлементовФормы.Индекс(ЭлКолонки);
                    Прервать;
                КонецЕсли;
            КонецЦикла;

            Если ИндексКолонкиНаименования <> -1 Тогда
                СписокЭлементовФормы.Вставить(ИндексКолонкиНаименования + 1, НовЭлемент); // Вставляем после "Наименования"
            КонецЕсли;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Мы уже упомянули об этом, но хотим подчеркнуть еще раз, поскольку это является краеугольным камнем правильной и поддерживаемой разработки в 1С: все модификации запроса и формы лучше выполнять в расширении конфигурации. Это обеспечивает сохранение работоспособности вашей доработки при обновлении типовой конфигурации и позволяет избежать конфликтов.

Для реализации через расширение необходимо:

  1. Создать или выбрать существующее расширение: Откройте конфигуратор, перейдите в меню "Конфигурация" -> "Расширения конфигурации". Создайте новое расширение или выберите уже имеющееся, в котором вы планируете размещать свои доработки.
  2. Перенести форму в расширение: Найдите в дереве объектов конфигурации типовую форму подбора, которую вы хотите изменить (например, "ФормаВыбора" справочника "Номенклатура" или специализированную форму подбора). Перетащите ее в созданное расширение.
  3. Добавить процедуру формы с модификатором: Откройте форму в расширении, перейдите на вкладку "Модули" -> "Модуль формы". Найдите процедуру ПриСозданииНаСервере (или другую, где происходит инициализация динамического списка и его запроса). Добавьте эту процедуру в расширение, нажав на иконку с зеленой стрелкой. Обязательно установите для нее модификатор "После". Это гарантирует, что ваш код выполнится после того, как типовой код сформирует форму и ее динамические списки, что позволит вам их модифицировать, не вмешиваясь в их первичное создание.
  4. Вставить код: Вставьте ваш код модификации запроса и добавления элемента формы внутрь этой процедуры ПриСозданииНаСервере в расширении.

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

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

Рассмотрим распространенные причины, по которым колонка может не отображаться, и способы их устранения:

Для эффективной отладки используйте точки останова в конфигураторе. Пошагово просматривайте выполнение кода, особенно части, отвечающей за модификацию запроса и добавление элементов формы. Проверяйте значение свойства ТекстЗапроса динамического списка до и после вашей модификации. Также проверяйте наличие нового элемента в коллекции Элементы.Список.ПодчиненныеЭлементы и его свойства.

В некоторых более сложных случаях, когда вам необходимо не просто отобразить данные из запроса, а работать с ними как с полноценными реквизитами формы (например, для интерактивного изменения, выполнения сложных вычислений, которые не могут быть выполнены в запросе, или если данные не привязаны напрямую к динамическому списку), может потребоваться программное добавление реквизитов формы. Это может быть актуально для табличных частей, не связанных напрямую с источниками данных формы, или для хранения промежуточных вычислений, которые затем отображаются.

Для этого используется процедура ИзменитьРеквизиты(). После добавления реквизита на форму, к нему можно привязать элемент формы, как и в случае с полями динамического списка, используя его имя как ПутьКДанным.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // ... (другой код)

    // Пример добавления нового реквизита формы
    МассивРеквизитов = Новый Массив;
    МассивРеквизитов.Добавить(Новый РеквизитФормы("МойПроизвольныйРеквизит", Новый ОписаниеТипов("Число", , Новый КвалификаторыЧисла(15, 2))));
    ИзменитьРеквизиты(МассивРеквизитов);

    // Затем можно добавить элемент формы, привязанный к этому реквизиту:
    // Если у вас есть группа, куда вы хотите добавить реквизит
    // Элементы.Добавить("МойПроизвольныйРеквизитПоле", Тип("ПолеФормы"), Элементы.ГруппаСДополнительнымиДанными);
    // НовЭлементРеквизит.ПутьКДанным = "МойПроизвольныйРеквизит";
    // НовЭлементРеквизит.Заголовок = "Произвольное значение";
    // ...
КонецПроцедуры

Однако, для задачи простого вывода данных из запроса динамического списка, как в нашем случае с ценой, этот метод обычно не требуется. Достаточно прямой работы с полями динамического списка, как описано в шаге 2.

Добавление пользовательской колонки в форму подбора товаров в 1С:УТ 11 — это выполнимая задача, требующая аккуратного подхода к модификации запроса динамического списка и программному созданию элементов формы. Использование расширений является ключевым фактором для поддержания обновляемости конфигурации и предотвращения конфликтов. Внимательная отладка и проверка всех шагов помогут избежать распространенных проблем с отображением колонки.

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

← На главную