При разработке отчетов на базе Системы компоновки данных (СКД) в 1С программисты часто сталкиваются с задачей, когда необходимо жестко ограничить выборку данных по нескольким элементам справочника одновременно (например, по нескольким должностям или отделам). При этом важно сделать так, чтобы обычный пользователь не мог случайно изменить или удалить эти настройки.
В процессе обсуждения этой проблемы на форуме участники столкнулись с типичной ошибкой Поле объекта не обнаружено (Значение) при попытке заполнить параметры по индексу. В данной статье мы детально разберем причины этой ошибки, рассмотрим правильные способы программной установки параметров и изучим альтернативный вариант через механизм отборов СКД.
В Сообщении 15 пользователю был предложен следующий код для заполнения списка должностей:
ЭлементНастроек = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы[0];
ЭлементНастроек.Значение = Список;
Этот подход привел к ошибке Поле объекта не обнаружено (Значение) в Сообщении 16. Давайте проанализируем ситуацию и поймем, почему так происходит.
Коллекция ПараметрыДанных.Элементы содержит параметры компоновки данных. Обращение по индексу [0] крайне небезопасно и приводит к сбоям по трем основным причинам:
0 окажется совершенно другой параметр (например, «НачалоПериода» вместо «Должность»).Неопределено, у которого нет свойства Значение.Чтобы избежать ошибок, связанных с индексацией элементов, в платформе 1С предусмотрен стандартный, надежный и лаконичный метод УстановитьЗначениеПараметра. Он самостоятельно находит параметр по его строковому имени и корректно присваивает ему переданное значение.
Рассмотрим пример правильной установки списка должностей в модуле формы отчета:
&НаСервере
Процедура ЗаполнитьПараметрыНаСервере()
// Создаем список значений и наполняем его нужными элементами
СписокДолжностей = Новый СписокЗначений;
СписокДолжностей.Добавить(Справочники.Должности.НайтиПоНаименованию("Программисты"));
СписокДолжностей.Добавить(Справочники.Должности.НайтиПоНаименованию("Дизайнеры"));
// Безопасно устанавливаем параметр по его имени
Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Должность", СписокДолжностей);
КонецПроцедуры
При таком подходе платформа сама найдет нужный параметр по имени "Должность", даже если он находится на десятой позиции в списке параметров. Это исключает возникновение непредвиденных ошибок при модификации схемы отчета.
Если вам требуется не просто установить значение, но и выполнить дополнительные действия (например, включить или выключить использование параметра, проверить его доступность), рекомендуется использовать метод НайтиЗначениеПараметра. Он возвращает элемент настроек, который мы можем предварительно проверить.
Разберем этот способ на примере:
&НаСервере
Процедура УстановитьПараметрСПроверкой()
СписокДолжностей = Новый СписокЗначений;
СписокДолжностей.Добавить(Справочники.Должности.НайтиПоНаименованию("Генеральный директор"));
// Создаем объект параметра по его имени в СКД
ИмяПараметра = Новый ПараметрКомпоновкиДанных("Должность");
ЭлементПараметра = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(ИмяПараметра);
Если ЭлементПараметра <> Неопределено Тогда
ЭлементПараметра.Значение = СписокДолжностей;
ЭлементПараметра.Использование = Истина;
КонецЕсли;
КонецПроцедуры
При работе в управляемых формах разработчики часто сталкиваются с ситуацией: код написан без ошибок, параметры устанавливаются в процедуре ПриСозданииНаСервере, но при формировании отчета данные выводятся пустые или параметры сбрасываются. Выясним, почему это происходит.
Дело в том, что в управляемом интерфейсе 1С 8.3 параметры, выведенные в быстрые настройки на форме (коллекция ПользовательскиеНастройки), имеют наивысший приоритет. При формировании отчета платформа берет значения именно из пользовательских настроек на форме и перезаписывает настройки самого компоновщика.
Для решения этой проблемы существует три основных варианта:
&НаСервере
Процедура ЗаполнитьПользовательскиеНастройки()
Список = Новый СписокЗначений;
Список.Добавить(Справочники.Должности.НайтиПоНаименованию("Бухгалтер"));
ПараметрДанных = Отчет.КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(New ПараметрКомпоновкиДанных("Должность"));
Если ПараметрДанных <> Неопределено Тогда
// Ищем элемент в пользовательских настройках по его уникальному идентификатору
ЭлементПН = Отчет.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы.Найти(ПараметрДанных.ИдентификаторПользовательскойНастройки);
Если ЭлементПН <> Неопределено Тогда
ЭлементПН.Значение = Список;
ЭлементПН.Использование = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
3. Использование модуля объекта отчета: Еще один надежный способ — осуществлять заполнение параметров не в форме, а в модуле самого отчета в предопределенном обработчике ПриКомпоновкеРезультата. В этой точке настройки формы уже применились к отчету, и мы можем гарантированно перезаписать параметры перед непосредственным выводом данных в отчет.
Для того чтобы СКД адекватно воспринимала переданный список значений, необходимо правильно настроить саму схему в конфигураторе:
Должность и обязательно установите флажок в колонке «Доступен список значений». Если этого не сделать, система будет ожидать одиночную ссылку, и при передаче объекта СписокЗначений возникнет ошибка несовместимости типов.В вместо оператора равенства =. Например:
ВЫБРАТЬ
Сотрудники.Ссылка КАК Сотрудник,
Сотрудники.Должность КАК Должность
ИЗ
Справочник.Сотрудники КАК Сотрудники
ГДЕ
Сотрудники.Должность В (&Должность)
Если параметр является необязательным, рекомендуется обернуть условие в фигурные скобки. В таком случае, если список должностей окажется пустым, СКД просто проигнорирует это условие в итоговом SQL-запросе к СУБД:
{ГДЕ Сотрудники.Должность В (&Должность)}
Если ваша задача заключается в том, чтобы жестко ограничить выборку данных по списку значений, не позволяя пользователю вмешиваться в этот процесс, использование параметров запроса не всегда является лучшим выбором. Гораздо проще и гибче использовать встроенный механизм Отборов СКД.
Этот подход имеет ряд весомых преимуществ:
Давайте разберем пример программного добавления скрытого отбора по списку должностей в модуле формы отчета:
&НаСервере
Процедура УстановитьСкрытыйОтбор()
// Создаем список значений для отбора
СписокДолжностей = Новый СписокЗначений;
СписокДолжностей.Добавить(Справочники.Должности.НайтиПоНаименованию("Программисты"));
СписокДолжностей.Добавить(Справочники.Должности.НайтиПоНаименованию("Дизайнеры"));
// Добавляем новый элемент отбора в компоновщик настроек
НовыйОтбор = Отчет.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Должность"); // Имя поля из схемы компоновки
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
НовыйОтбор.ПравоеЗначение = СписокДолжностей;
НовыйОтбор.Использование = Истина;
// Скрываем отбор, чтобы пользователь не мог его отключить на форме
НовыйОтбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
КонецПроцедуры
Использование свойства РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный гарантирует, что пользователь даже не увидит данный отбор в настройках отчета, а отчет всегда будет формироваться строго по заданному списку должностей.
Мы подробно проанализировали особенности работы со списками значений в СКД. Для успешного решения задачи всегда проверяйте соответствие типов в схеме (флаг «Доступен список значений»), используйте безопасные методы обращения к параметрам по их имени (УстановитьЗначениеПараметра) и помните о приоритете пользовательских настроек на управляемой форме. Если жесткие ограничения не требуют сложной логики в самом запросе, отдавайте предпочтение механизму скрытых программных отборов.