Почему поля динамического списка из регистра сведений отображаются прочерками в расширении 1С:УТ 11.5?

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

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

Детальный анализ проблемы

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

Для получения необходимых данных, таких как сумма оплаты, процент оплаты, сумма отгрузки и другие показатели состояния заказов, мы модифицируем текст запроса динамического списка. В нем мы используем левое соединение (ЛЕВОЕ СОЕДИНЕНИЕ) с регистром сведений СостоянияЗаказовКлиентов:


ВЫБРАТЬ
    ДокументЗаказКлиента.Ссылка КАК Ссылка,
    ДокументЗаказКлиента.ПометкаУдаления КАК ПометкаУдаления,
    ДокументЗаказКлиента.Номер КАК Номер,
    ДокументЗаказКлиента.Дата КАК Дата,
    ДокументЗаказКлиента.НомерПоДаннымКлиента КАК НомерПоДаннымКлиента,
    ДокументЗаказКлиента.ДатаПоДаннымКлиента КАК ДатаПоДаннымКлиента,
    ДокументЗаказКлиента.Проведен КАК Проведен,
    ДокументЗаказКлиента.Приоритет КАК Приоритет,
    ДокументЗаказКлиента.Партнер КАК Партнер,
    ДокументЗаказКлиента.Контрагент КАК Контрагент,
    // ...
    ЕСТЬNULL(СостоянияЗаказовКлиентов.СуммаОплаты, 0) КАК СуммаОплаты,
    ЕСТЬNULL(СостоянияЗаказовКлиентов.ПроцентОплаты, 0) КАК ПроцентОплаты,    
    ЕСТЬNULL(СостоянияЗаказовКлиентов.СуммаОтгрузки, 0) КАК СуммаОтгрузки,
    ЕСТЬNULL(СостоянияЗаказовКлиентов.ПроцентОтгрузки, 0) КАК ПроцентОтгрузки,
    ЕСТЬNULL(СостоянияЗаказовКлиентов.ПроцентДолга, 0) КАК ПроцентДолга,
    ЕСТЬNULL(СостоянияЗаказовКлиентов.ДатаСобытия, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаСобытия,
    ЕСТЬNULL(СостоянияЗаказовКлиентов.ЕстьРасхожденияОрдерНакладная, ЛОЖЬ) КАК ЕстьРасхожденияОрдерНакладная
    // ...
ИЗ
    Документ.ЗаказКлиента КАК ДокументЗаказКлиента
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияЗаказовКлиентов КАК СостоянияЗаказовКлиентов
    ПО (СостоянияЗаказовКлиентов.Заказ = ДокументЗаказКлиента.Ссылка)

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

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

Шаги по локализации и устранению проблемы (неудачные попытки)

Мы предпринимаем ряд логичных шагов для выявления и устранения причины, но они, к сожалению, не приводят к желаемому результату:

  1. Перезаимствование регистра: Мы пытаемся удалить весь регистр СостоянияЗаказовКлиентов из расширения и заново его заимствовать, а также все его атрибуты. Однако это не решает проблему: тип измерения Заказ снова определяется как ЛюбаяСсылка, и отображение полей в пользовательском режиме остается без изменений. Это говорит нам о том, что расширение не "видит" корректный составной тип, или же платформа игнорирует его при заимствовании.
  2. Попытка изменения типа вручную: Мы пытаемся повысить режим совместимости конфигурации до 8.3.18, чтобы получить возможность вручную назначить составной тип для измерения Заказ. Однако система сообщает, что наша конфигурация (например, ЗУП, хотя в нашем случае речь идет об УТ 11.5) не поддерживает этот режим. Это тупиковый путь.
  3. Проверка ссылочных типов: Мы проверяем, добавлены ли в расширение все типы документов, на которые ссылается составной тип измерения Заказ. Убеждаемся, что они добавлены, но это также не приводит к изменению ситуации.
  4. Изменение условия соединения: Мы пробуем изменить порядок операндов в условии левого соединения с ПО (СостоянияЗаказовКлиентов.Заказ = ДокументЗаказКлиента.Ссылка) на ПО (ДокументЗаказКлиента.Ссылка = СостоянияЗаказовКлиентов.Заказ). Разницы, по сути, нет, и ожидаемо это не влияет на результат.
  5. Изоляция проблемы от расширения: Мы удаляем заимствованную форму ЗаказКлиента из расширения. Однако это никак не влияет на проблему — поля по-прежнему отображаются прочерками. Этот шаг позволяет нам сделать вывод, что сама проблема, по крайней мере на этом этапе, не связана напрямую с тем, что форма заимствована в расширение.
  6. Тестирование других изменений формы: Мы добавляем на форму картинку или удаляем колонку из табличной части. Эти изменения отображаются корректно. Удаление одного из полей из запроса также приводит к его исчезновению на форме. Это подтверждает, что в целом механизм расширения и динамического списка работает, за исключением определенных полей.
  7. Проверка на программное переопределение запроса: Мы начинаем подозревать, что текст запроса может переопределяться программно в более поздних этапах инициализации формы. Проверяем его в обработчике ПриОткрытии(), но видим, что текст запроса не изменен.
  8. Сравнительный анализ поведения полей в запросе: Для дальнейшей локализации проблемы, мы проводим эксперимент с текстом запроса. Мы заменяем одно из полей документа ДокументЗаказКлиента.Комментарий КАК Комментарий на константное значение "Мой коммент" КАК Комментарий. Этот эксперимент срабатывает – в колонке "Комментарий" мы видим "Мой коммент". Однако, если мы аналогично заменяем проблемное поле из регистра сведений, например, ЕСТЬNULL(СостоянияЗаказовКлиентов.ПроцентОплаты, 0) КАК ПроцентОплаты на 888 КАК ПроцентОплаты, то в колонке "ПроцентОплаты" по-прежнему отображается прочерк.

Посмотрим на пример измененного запроса, где "Мой коммент" работает, а "888" - нет:


ВЫБРАТЬ
    ДокументЗаказКлиента.Ссылка КАК Ссылка,
    // ...
    ДокументЗаказКлиента.Контрагент КАК Контрагент,
    // ДокументЗаказКлиента.Комментарий КАК Комментарий, // Закомментировано
    "Мой коммент" КАК Комментарий, // Отображается корректно
    // ...
    ЕСТЬNULL(СостоянияЗаказовКлиентов.СуммаОплаты, 0) КАК СуммаОплаты,
    // ЕСТЬNULL(СостоянияЗаказовКлиентов.ПроцентОплаты, 0) КАК ПроцентОплаты, // Закомментировано
    888 КАК ПроцентОплаты, // Продолжает отображаться прочерком
    ЕСТЬNULL(СостоянияЗаказовКлиентов.СуммаОтгрузки, 0) КАК СуммаОтгрузки,
    // ...
ИЗ
    Документ.ЗаказКлиента КАК ДокументЗаказКлиента
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияЗаказовКлиентов КАК СостоянияЗаказовКлиентов
    ПО (СостоянияЗаказовКлиентов.Заказ = ДокументЗаказКлиента.Ссылка)

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

Обнаружение причины – Условное оформление

Дальнейшее расследование приводит нас к главному виновнику – условному оформлению формы. Мы обнаруживаем код, который программно устанавливает правила условного оформления для динамического списка. В этом коде перечислены именно те поля, которые у нас не отображались:


// ... в процедуре, например, ПриСозданииНаСервере() или отдельной функции установки условного оформления
    Элемент = СписокУсловноеОформление.Элементы.Добавить();
    Элемент.Представление = НСтр("ru = 'Скрытие итогов по заказу при учете расчетов по договорам или накладным'");
    
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("ДолгКлиента");
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("НашДолг");
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("ПроцентДолга");
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("ПроцентОплаты"); // Наше проблемное поле
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("СуммаОплаты");
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("СуммаПросроченнойОплаты");
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("СуммаОтгрузки");
    Элемент.Поля.Элементы.Добавить().Поле = Новый ПолеКомпоновкиДанных("ПроцентОтгрузки");
    
    СписокПорядковРасчета = Новый СписокЗначений();
    СписокПорядковРасчета.Добавить(Перечисления.ПорядокРасчетов.ПоЗаказам);
    СписокПорядковРасчета.Добавить(Перечисления.ПорядковРасчетов.ПоЗаказамНакладным);
    
    ОтборЭлемента = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ОтборЭлемента.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ПорядокРасчетов");
    ОтборЭлемента.ВидСравнения = ВидСравненияКомпоновкиДанных.НеВСписке;
    ОтборЭлемента.ПравоеЗначение = СписокПорядковРасчета;
    
    Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", WebЦвета.Серый);
    Элемент.Оформление.УстановитьЗначениеПараметра("Текст", НСтр("ru = '-'")); // Вот оно! Устанавливается прочерк
//-----------------------------------

Данный фрагмент кода создает правило условного оформления, которое, если ПорядокРасчетов не соответствует определенным значениям, устанавливает текст для перечисленных полей в виде прочерка (НСтр("ru = '-'")) и делает текст серым. Это объясняет, почему мы видим прочерки вместо данных.

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

  1. Кэш 1С: Платформа 1С активно использует кэширование для ускорения работы. Настройки форм, включая условное оформление, могут быть закэшированы. Даже после изменения кода, кэшированные настройки могут продолжать применяться. В таких случаях, очистка кэша (как клиентского, так и серверного) является первоочередным шагом. Это можно сделать, удалив информационную базу из списка и добавив ее заново, или вручную очистив папки кэша (например, %userprofile%\AppData\Roaming\1C\1Cv82 и %userprofile%\AppData\Local\1C\1cv82). Несмотря на то что в нашем случае очистка кэша не принесла мгновенного результата, это всегда стоит попробовать.
  2. Типовые механизмы платформы/конфигурации: В сложных конфигурациях, таких как УТ, могут существовать другие, неочевидные механизмы или стандартные настройки, которые применяют условное оформление для полей с определенными именами (например, "ПроцентОплаты"). Эти механизмы могут быть вызваны из других модулей или срабатывать асинхронно, обходя наши попытки их отключить.
  3. Приоритет оформления: Возможно, существует несколько правил условного оформления, и какое-то из них, установленное на более высоком уровне или с более высоким приоритетом, продолжает действовать.

Наиболее показательный эксперимент заключается в следующем: если мы изменяем наименование поля (алиас) в запросе, например, с ПроцентОплаты на МойПроцентОплаты, а затем на форме удаляем старый элемент списка, связанный с полем ПроцентОплаты, и добавляем новый, привязанный к МойПроцентОплаты, то новое поле начинает работать корректно и отображает данные! Это окончательно подтверждает, что проблема связана именно с именем поля ПроцентОплаты и специфическими настройками (вероятно, условным оформлением), привязанными к этому имени.

Окончательное решение и рабочие обходы

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

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

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

    
    ВЫБРАТЬ
        // ... другие поля
        ЕСТЬNULL(СостоянияЗаказовКлиентов.СуммаОплаты, 0) КАК МояСуммаОплаты, // Изменено
        ЕСТЬNULL(СостоянияЗаказовКлиентов.ПроцентОплаты, 0) КАК МойПроцентОплаты, // Изменено
        ЕСТЬNULL(СостоянияЗаказовКлиентов.СуммаОтгрузки, 0) КАК МояСуммаОтгрузки, // Изменено
        // ... другие поля
    ИЗ
        Документ.ЗаказКлиента КАК ДокументЗаказКлиента
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияЗаказовКлиентов КАК СостоянияЗаказовКлиентов
        ПО (СостоянияЗаказовКлиентов.Заказ = ДокументЗаказКлиенту.Ссылка)
    
  4. Корректируем элементы формы:
    • В конфигураторе открываем заимствованную форму.
    • Находим в динамическом списке старые элементы управления (колонки или поля), которые были привязаны к исходным именам полей (например, "ПроцентОплаты").
    • Удаляем эти старые элементы формы из списка.
    • Добавляем новые элементы управления на форму, привязывая их к новым алиасам полей запроса (например, "МойПроцентОплаты").
  5. Проверяем результат: После этих изменений, запускаем систему в пользовательском режиме. Мы увидим, что новые поля с измененными алиасами теперь корректно отображают данные из регистра сведений.
  6. Очистка кэша (дополнительно): Хотя в данном случае кэш не был основной причиной, а лишь мог усугублять ситуацию, всегда рекомендуется очищать кэш 1С после существенных изменений в конфигурации или расширениях. Для этого вы можете удалить базу из списка и добавить ее заново, или использовать утилиту 1cestart.exe с параметром /ClearCache.

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

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

← На главную