Почему пропадает колонка в журнале документов 1С и как это исправить?

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

При разработке в среде 1С:Предприятие 8.3 на управляемых формах (особенно в типовых конфигурациях, таких как УТ 11, ERP 2 или КА 2) программисты часто сталкиваются с загадочным поведением интерфейса: добавленная в динамический список колонка прекрасно отображается в конфигураторе, присутствует на сервере в начале обработчика ПриСозданииНаСервере, но бесследно исчезает при открытии формы на клиенте.

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

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

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

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

Способ 1. Программная модификация динамического запроса с помощью "Схемы запроса"

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

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

  1. Создадим обработчик ПриСозданииНаСервере с директивой &После. К этому моменту типовой запрос уже будет полностью сформирован.
  2. Используем объект платформы СхемаЗапроса для безопасного изменения текста запроса, чтобы не нарушить структуру условий и отборов.
  3. Программно добавим новое поле и свяжем его с новым элементом формы.

Посмотрим на пример реализации данного метода:


&После("ПриСозданииНаСервере")
Процедура ИН_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
    
    // Шаг 1. Получаем текущий текст запроса динамического списка
    ТекстЗапросаДС = Список.ТекстЗапроса;
    
    // Шаг 2. Используем Схему Запроса для безопасной модификации
    Схема = Новый СхемаЗапроса;
    Схема.УстановитьТекстЗапроса(ТекстЗапросаДС);
    
    // Получаем первый пакет и первый выбор запроса
    ПакетЗапросов = Схема.ПакетЗапросов[0];
    Выборка = ПакетЗапросов.Выбор;
    
    // Добавляем наше поле в запрос. 
    // Предположим, нам нужно вытащить комментарий или статус из соединенной таблицы
    ПолеСвязи = Выборка.Добавить("ВЫРАЗИТЬ(ДокументТаблица.Комментарий КАК Строка(150))");
    ПолеСвязи.Псевдоним = "ИН_МойКомментарий";
    
    // Записываем измененный запрос обратно в динамический список
    Список.ТекстЗапроса = Схема.ПолучитьТекстЗапроса();
    
    // Шаг 3. Добавляем колонку на форму, если ее там нет
    ИмяЭлементаКолонки = "СписокИН_МойКомментарий";
    Если Элементы.Найти(ИмяЭлементаКолонки) = Неопределено Тогда
        
        // Добавляем элемент формы типа "ПолеФормы" в таблицу "Список"
        НоваяКолонка = Элементы.Добавить(ИмяЭлементаКолонки, Тип("ПолеФормы"), Элементы.Список);
        НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
        НоваяКолонка.ПутьКДанным = "Список.ИН_МойКомментарий";
        НоваяКолонка.Заголовок = "Мой комментарий";
        НоваяКолонка.Видимость = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Использование объекта СхемаЗапроса гарантирует, что структура запроса не будет нарушена некорректной заменой подстрок, а ваши отборы и группировки продолжат работать в штатном режиме.

Способ 2. Оптимальный метод с использованием события "ПриПолученииДанныхНаСервере"

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

В такой ситуации проанализируем альтернативный подход: мы добавим в запрос "пустышку", а заполнять её актуальными данными будем порционно — только для тех строк, которые видны пользователю на экране в данный момент.

Разберем этот алгоритм по шагам:

  1. Добавим пустое поле нужного типа в запрос динамического списка в процедуре ПриСозданииНаСервере.
  2. Программно создадим колонку на форме и привяжем её к этому пустому полю.
  3. Создадим обработчик события динамического списка ПриПолученииДанныхНаСервере, в котором быстро и пакетно выберем нужные данные только для отображаемых строк.

Посмотрим на программную реализацию. Сначала подготовим поле в процедуре создания формы:


&После("ПриСозданииНаСервере")
Процедура ИН_ПриСозданииНаСервереПриПолучении(Отказ, СтандартнаяОбработка)
    
    // Добавляем в запрос поле-пустышку с нужным типом данных
    ТекстЗапросаДС = Список.ТекстЗапроса;
    
    Схема = Новый СхемаЗапроса;
    Схема.УстановитьТекстЗапроса(ТекстЗапросаДС);
    ПакетЗапросов = Схема.ПакетЗапросов[0];
    
    // Создаем пустую колонку строкового типа
    ПолеПустышка = ПакетЗапросов.Выбор.Добавить("ВЫРАЗИТЬ("""" КАК Строка(100))");
    ПолеПустышка.Псевдоним = "ИН_БыстроеПоле";
    
    Список.ТекстЗапроса = Схема.ПолучитьТекстЗапроса();
    
    // Создаем элемент формы для отображения
    ИмяКолонки = "СписокИН_БыстроеПоле";
    Если Элементы.Найти(ИмяКолонки) = Неопределено Тогда
        НоваяКолонка = Элементы.Добавить(ИмяКолонки, Тип("ПолеФормы"), Элементы.Список);
        НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
        НоваяКолонка.ПутьКДанным = "Список.ИН_БыстроеПоле";
        НоваяКолонка.Заголовок = "Дополнительные данные";
    КонецЕсли;
    
КонецПроцедуры

Теперь опишем обработчик события ПриПолученииДанныхНаСервере для нашей таблицы. Обратите внимание, что это событие срабатывает только для тех строк, которые реально выводятся на монитор пользователя (обычно от 20 до 45 строк за один раз), что обеспечивает колоссальную экономию ресурсов СУБД.


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    // Собираем массив ссылок на документы, которые выводятся на экран
    МассивСсылок = Новый Массив;
    Для Каждого СтрокаСписка Из Строки Цикл
        МассивСсылок.Добавить(СтрокаСписка.Ключ);
    КонецЦикла;
    
    // Выполняем один быстрый запрос к базе данных для получения нужных значений
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   РеестрДокументов.Ссылка КАК Ссылка,
        |   РеестрДокументов.ДополнительныеСведения КАК ДопСведения
        |ИЗ
        |   РегистрСведений.РеестрДокументов КАК РеестрДокументов
        |ГДЕ
        |   РеестрДокументов.Ссылка В(&МассивСсылок)";
        
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    ТаблицаДанных = Запрос.Выполнить().Выгрузить();
    
    // Заполняем нашу колонку-пустышку полученными данными
    Для Каждого СтрокаСписка Из Строки Цикл
        НайденнаяСтрока = ТаблицаДанных.Найти(СтрокаСписка.Ключ, "Ссылка");
        Если НайденнаяСтрока <> Неопределено Тогда
            // Устанавливаем значение в ячейку динамического списка
            СтрокаСписка.Значение.Данные["ИН_БыстроеПоле"] = НайденнаяСтрока.ДопСведения;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

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

← На главную