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