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