В практике разработки на платформе 1С:Предприятие 8.3 часто возникает задача связать данные различных объектов. Типичный пример: в форме документа необходимо создать кнопку, которая открывает список записей регистра сведений (например, с прикрепленными файлами), но не весь список сразу, а только те записи, которые относятся к текущему документу. Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с ошибками контекста и неправильной передачей параметров.
В данной статье мы подробно разберем, как правильно реализовать этот механизм, проанализируем типичные ошибки и рассмотрим продвинутые способы управления динамическими списками. Для решения смежных задач можно использовать практические методы программного добавления полей в динамические списки.
Рассмотрим ситуацию: у нас есть документ Задания и регистр сведений Медиа_файлы. В регистре есть измерение (или реквизит) Задание, где хранится ссылка на документ. Нам нужно при нажатии кнопки на форме документа открыть список регистра с фильтром по текущему документу.
Разберем основные ошибки, которые совершают новички:
Документы.Задания.ПолучитьСсылку() непосредственно в процедуре кнопки на клиенте. Менеджеры объектов (такие как Документы, Справочники, РегистрыСведений) доступны только на стороне сервера.Объект — это данные формы (тип ДокументОбъект), а для отбора в базе данных всегда требуется Ссылка.Отбор.Начнем с самого простого и правильного способа реализации команды на клиенте. Если кнопка находится на форме документа, у нас уже есть доступ к ссылке текущего документа через реквизит Объект.Ссылка. Нам не нужно обращаться к серверу, чтобы получить эту ссылку.
Рассмотрим правильный алгоритм написания кода для обработчика команды:
&НаКлиенте
Процедура Файлы(Команда)
// 1. Создаем структуру самого отбора.
// Ключ - это ИМЯ ПОЛЯ в регистре сведений, по которому фильтруем.
// Значение - это ссылка на наш документ.
ОтборПоЗначению = Новый Структура("Задания", Объект.Ссылка);
// 2. Создаем структуру параметров для открытия формы.
// Платформа ожидает ключ "Отбор", внутри которого лежит наша структура.
ПараметрыОткрытия = Новый Структура("Отбор", ОтборПоЗначению);
// 3. Открываем форму списка регистра.
ОткрытьФорму("РегистрСведений.Медиа_файлы.ФормаСписка", ПараметрыОткрытия);
КонецПроцедуры
Важный нюанс: Обратите внимание, что имя ключа в структуре ОтборПоЗначению (в примере — "Задания") должно в точности совпадать с именем измерения или реквизита в метаданных регистра сведения. Если в конфигураторе поле называется ОбъектОснование, то и в коде должно быть Новый Структура("ОбъектОснование", Объект.Ссылка).
Проанализируем ситуацию: пользователь открыл файлы для «Задания №1», не закрыл окно, вернулся в список документов и нажал кнопку «Файлы» для «Задания №2». Если использовать код выше, 1С просто активирует уже открытое окно с файлами первого задания, и пользователь увидит неактуальные данные.
Чтобы для каждого документа открывалось свое отдельное окно, мы должны использовать КлючУникальности. В качестве такого ключа идеально подходит ссылка на сам документ.
&НаКлиенте
Процедура Файлы(Команда)
ОтборПоЗначению = Новый Структура("Задания", Объект.Ссылка);
ПараметрыОткрытия = Новый Структура("Отбор", ОтборПоЗначению);
// Используем четвертый параметр функции ОткрытьФорму - КлючУникальности
ОткрытьФорму("РегистрСведений.Медиа_файлы.ФормаСписка",
ПараметрыОткрытия,
ЭтаФорма,
Объект.Ссылка); // Ключ уникальности
КонецПроцедуры
Даже если код написан верно, отбор может не сработать. Выясним причину, которая часто кроется в настройках самой формы списка регистра. Чтобы стандартный параметр Отбор применился автоматически, динамический список в открываемой форме должен отвечать определенным требованиям:
ДинамическийСписок) на форме регистра обязательно должно быть заполнено свойство ОсновнаяТаблица (например, РегистрСведений.Медиа_файлы). Если там пусто или используется произвольный запрос без указания основной таблицы, платформа не «поймет», к какому полю применить структуру отбора.Рассмотрим ситуацию, когда стандартного отбора недостаточно. Например, если вы хотите, чтобы пользователь не мог отключить этот отбор в открывшемся окне, или если вам нужен сложный вид сравнения (например, «В списке» или «Больше»). В этом случае рекомендуется использовать ФиксированныеНастройки.
Этот метод чуть сложнее, так как требует работы с системой компоновки данных (СКД), но он гораздо надежнее. Поскольку работа с объектами компоновки требует серверного контекста, нам придется разбить задачу на две части. Для упрощения программного конструирования таких настроек можно использовать общий модуль-обертку над объектной моделью СКД.
&НаКлиенте
Процедура ФайлыРасширенный(Команда)
ПараметрыОткрытия = Новый Структура;
// Получаем фиксированные настройки с сервера
ПараметрыОткрытия.Вставить("ФиксированныеНастройки", ПолучитьНастройкиОтбораНаСервере(Объект.Ссылка));
ОткрытьФорму("РегистрСведений.Медиа_файлы.ФормаСписка", ПараметрыОткрытия, ЭтаФорма, Объект.Ссылка);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьНастройкиОтбораНаСервере(СсылкаДокумента)
НастройкиКомпоновки = Новый НастройкиКомпоновкиДанных;
ЭлементОтбора = НастройкиКомпоновки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
// Указываем поле, по которому фильтруем
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Задания");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.Использование = Истина;
// Указываем значение
ЭлементОтбора.ПравоеЗначение = СсылкаДокумента;
Возврат НастройкиКомпоновки;
КонецФункции
Проанализируем ошибку автора темы: Переменная не определена (Документы). Это классическая проблема понимания клиент-серверной архитектуры 1С.
В управляемом приложении код исполняется либо на Клиенте (в браузере или тонком клиенте), либо на Сервере (в кластере серверов 1С). На клиенте нам доступны:
На сервере нам доступны:
Документы, Справочники и т.д.).ДокументОбъект), которые можно записывать и проводить.Когда вы пишете Документы.Задания.ПолучитьСсылку на клиенте, программа пытается обратиться к менеджеру всех документов «Задания», которого на клиенте просто не существует. Если вам нужно получить ссылку программно по какому-то признаку, делайте это в функции &НаСервере, а затем передавайте результат на клиент.
Подведем итог. Для успешного открытия формы списка с отбором достаточно придерживаться трех правил:
Объект.Ссылка), а не сам Объект."Отбор" для простых фильтров.Если вы только начинаете свой путь в 1С, рекомендуем всегда проверять, в каком контексте исполняется ваш код. Если конфигуратор «ругается» на неизвестное имя (например, РегистрыСведений или Запрос), скорее всего, вы пытаетесь выполнить серверный код на стороне клиента.