Почему в справочнике пропадают кнопки "Создать" и "Изменить" при использовании временных таблиц в динамическом списке 1С?

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

Рассмотрим частую проблему, с которой сталкиваются разработчики при настройке форм списков справочников и документов. Допустим, перед нами стоит задача: вывести в форму списка справочника номенклатуры актуальные остатки на складах и текущие цены. Для этого мы настраиваем динамический список, включаем произвольный запрос и пишем пакетный запрос с использованием временных таблиц. Запрос выполняется, данные выводятся на форму, но внезапно из командной панели пропадают стандартные кнопки: «Создать», «Скопировать», «Изменить», «Пометить на удаление» и «Переместить в группу». Выясним причину такого поведения платформы и проанализируем доступные способы решения.

Почему пропадают стандартные команды списка?

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

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

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

Способ 1: Модификация итогового блока запроса (Быстрое решение)

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

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


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

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

Способ 2: Архитектурная оптимизация регистрами сведений (Лучшая практика)

Важно понимать, что использование виртуальных таблиц (`Остатки` и `СрезПоследних`) непосредственно в динамическом списке — это нарушение стандартов разработки 1С. При каждом обновлении списка система будет выполнять тяжелые расчеты итогов регистра накопления, что неминуемо приведет к сильным зависаниям базы у пользователей, особенно если в справочнике тысячи позиций.

Рассмотрим правильный архитектурный подход к этой задаче:

  1. Создадим специальный непериодический независимый регистр сведений, например ОстаткиИЦеныДляСпискаНоменклатуры. Измерениями сделаем Номенклатура, а ресурсами — нужные колонки с остатками по филиалам и ценами.
  2. Напишем регламентное задание (или обработчик проведения документов движения), которое будет регулярно обновлять данные в этом служебном регистре.
  3. В динамическом списке формы мы удаляем пакетные запросы с ВТ и пишем максимально простой запрос.

Текст запроса динамического списка станет простым и легковесным:


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

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

Способ 3: Создание собственных (программных) команд

Если по какой-то причине переписать запрос невозможно, и создание кэширующего регистра не согласовано, остается вариант ручного воссоздания потерянного функционала.

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


&НаКлиенте
Процедура КомандаМоеСоздание(Команда)
    ПараметрыФормы = Новый Структура;
    ОткрытьФорму("Справочник.Номенклатура.ФормаОбъекта", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры

&НаКлиенте
Процедура КомандаМоеИзменение(Команда)
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ПараметрыФормы = Новый Структура("Ключ", ТекущиеДанные.Ссылка);
    ОткрытьФорму("Справочник.Номенклатура.ФормаОбъекта", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры

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

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

← На главную