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

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

При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда на форме справочника или документа отображается таблица с данными, но при попытке найти её в дереве метаданных (в составе самого объекта) выясняется, что такой табличной части не существует. Рассмотрим подробнее, почему это происходит, где физически хранятся данные и как правильно организовать их выборку.

Почему данных нет в составе объекта?

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

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

Шаг 1. Определение источника данных через программный код

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

  1. ПриСозданииНаСервере: Именно здесь чаще всего вызываются процедуры инициализации.
  2. ПриЧтенииНаСервере: Используется, если данные таблицы логически связаны с объектом, но хранятся отдельно.
  3. Процедуры с названиями типа ЗаполнитьДанные, ОбновитьИнформацию или ЗагрузитьИнформациюОПараметрах.

В рассматриваемом примере мы находим процедуру ЗагрузитьИнформациюОПараметрахДоступа(). Рассмотрим её код, чтобы понять логику заполнения:


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

Из этого кода становится ясно: таблица на форме — это всего лишь визуализация данных из регистров сведений НастройкиПараметровДоступа и ПараметрыДоступаПользователейВОбъектахОбслуживания.

Шаг 2. Как осуществить общую выборку по всем объектам

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

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


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

Важный момент: Обратите внимание, что в запросе из модуля формы использовался фильтр ГДЕ НастройкиПараметровДоступа.КонфигурационнаяЕдиница = &КЕ. Для массовой выборки этот фильтр нужно убрать, тогда система выдаст данные сразу по всем объектам.

Шаг 3. Работа с данными непосредственно в форме

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

В модуле формы мы обращаемся к таблице напрямую по имени реквизита. Например:


Для Каждого СтрокаПараметра Из удПараметры Цикл
    Если СтрокаПараметра.Параметр = Справочники.Параметры.ПустаяСсылка() Тогда
        Сообщить("Заполните параметр!");
    КонецЕсли;
КонецЦикла;

Если же работа происходит в контексте серверной процедуры, где требуется использование методов ТаблицыЗначений (таких как НайтиСтроки или Свернуть), используем функцию РеквизитФормыВЗначение:


&НаСервере
Процедура ОбработатьТаблицуНаСервере()
    // Превращаем реквизит формы в полноценную ТЗ
    ТаблицаОбъект = РеквизитФормыВЗначение("udПараметры");
    
    // Теперь доступны все методы таблицы значений
    ТаблицаОбъект.Свернуть("Параметр", "Значение");
    
    // Возвращаем измененные данные обратно на форму
    ЗначениеВРеквизитФормы(ТаблицаОбъект, "udПараметры");
КонецПроцедуры

Подведем итоги

Выясним основные правила работы с "виртуальными" таблицами на форме:

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

Помните: Разделение данных на "данные объекта" и "данные формы" — это стандарт проектирования интерфейсов 1С. Это позволяет делать формы более легкими, а работу пользователей — более быстрой.

← На главную