При переходе конфигураций с платформы 1С 8.2 на 1С 8.3 (при отключении режима совместимости) разработчики часто сталкиваются с ошибкой «Индекс находится за границами массива» при попытке программно обратиться к первому элементу отбора динамического списка: Список.Отбор.Элементы[0]. Разберем причины такого поведения платформы и подробно рассмотрим надежные способы установки отборов в управляемых формах.
Проанализируем архитектурные изменения платформы. В версии 8.3 механизм динамического списка приведен к строгой модели системы компоновки данных (СКД), где настройки разделены на три независимых уровня:
Список.КомпоновщикНастроек.Настройки. Именно сюда попадают элементы отбора, заданные разработчиком в конфигураторе в свойствах динамического списка.Список.КомпоновщикНастроек.ФиксированныеНастройки. Прямое свойство формы Список.Отбор является ссылкой именно на отбор фиксированных настроек. При создании формы без режима совместимости эта коллекция изначально пуста, поэтому прямое обращение по нулевому индексу [0] вызывает исключение.Список.КомпоновщикНастроек.ПользовательскиеНастройки. Сюда попадают элементы, для которых в конфигураторе или коде включен признак отображения пользователю.Таким образом, отборы, настроенные в конфигураторе, не попадают в Список.Отбор автоматически. Рассмотрим различные практические варианты решения задачи.
Если требуется жестко ограничить выборку данных на сервере, чтобы пользователь не мог снять или изменить данное условие, правильнее всего работать с фиксированными настройками (Список.Отбор). Вместо прямого обращения по индексу необходимо выполнять поиск существующего элемента по левому значению (полю компоновки) и добавлять новый элемент только при его отсутствии.
Посмотрим на пример безопасной установки отбора на сервере:
ПолеОтбора = Новый ПолеКомпоновкиДанных("Владелец");
Элемент = Неопределено;
Для Каждого ЭлементКоллекции Из Список.Отбор.Элементы Цикл
Если ЭлементКоллекции.ЛевоеЗначение = ПолеОтбора Тогда
Элемент = ЭлементКоллекции;
Прервать;
КонецЕсли;
КонецЦикла;
Если Элемент = Неопределено Тогда
Элемент = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент.ЛевоеЗначение = ПолеОтбора;
КонецЕсли;
Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Элемент.ПравоеЗначение = НужныйВладелец;
Элемент.Использование = Истина;
Если отбор уже был настроен в конфигураторе и вам требуется только поменять его значение в коде, обращаться нужно к базовым настройкам компоновщика:
Список.КомпоновщикНастроек.Настройки.Отбор.Элементы[0].ПравоеЗначение = НужныйВладелец;
Список.КомпоновщикНастроек.Настройки.Отбор.Элементы[0].Использование = Истина;
Важный нюанс: если для данного отбора в конфигураторе был установлен флаг «Включать в пользовательские настройки», простого изменения в КомпоновщикНастроек.Настройки может быть недостаточно, так как платформа переопределит его сохраненными пользовательскими значениями. В таком случае флаг в конфигураторе рекомендуется снять либо обновлять элемент через коллекцию ПользовательскиеНастройки.
В управляемом приложении 1С 8.3 нет необходимости писать программный код фильтрации в обработчике ПриСозданииНаСервере, если форму нужно открыть с уже установленным отбором. Достаточно передать структуру отбора в параметрах вызова формы:
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Новый Структура("Владелец", ЗначениеВладельца));
ОткрытьФорму("Справочник.Контрагенты.ФормаСписка", ПараметрыФормы, ЭтотОбъект);
Платформа автоматически применит указанные поля к динамическому списку при инициализации формы.
Если динамический список использует произвольный запрос, наиболее надежным и производительным решением является использование параметров запроса вместо наложения фильтров компоновки данных. Разберем по шагам:
ГДЕ Таблица.Владелец = &Владелец.
Список.Параметры.УстановитьЗначениеПараметра("Владелец", ЗначениеВладельца);
Такой подход полностью исключает коллизии между пользовательскими фильтрами и логикой конфигурации.
В конфигурациях, использующих БСП (например, 1C:ERP, УТ 11, КА 2, Бухгалтерия предприятия 3.0), для управления отборами реализованы готовые процедуры общего модуля. Они берут на себя поиск элемента, правильную адресацию и синхронизацию с пользовательскими настройками:
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбораДинамическогоСписка(
Список,
"Владелец",
ЗначениеВладельца,
ВидСравненияКомпоновкиДанных.Равно
);
Использование типовых методов является рекомендуемой практикой, так как обеспечивает единообразие кода и защищает от ошибок при обновлении версии платформы.