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