Как получить данные всей строки табличного документа при клике на ячейку в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Часто перед разработчиком 1С встает задача: пользователь нажимает на ячейку в отчете или табличном документе, и нужно выполнить действие, используя данные не только из этой ячейки, а из всей строки. Например, при клике на сумму в строке заказа нужно открыть форму именно этого документа, ссылка на который находится в другой колонке. Давайте разберемся, как это сделать в процедуре-обработчике РезультатОбработкаРасшифровки.

Проанализируем стандартную ситуацию. У нас есть табличный документ на форме. Мы кликаем по ячейке, для которой было задано значение расшифровки, и попадаем в обработчик:


Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры)
    
    СтандартнаяОбработка = Ложь;
    
    // Здесь нам нужно получить данные всей строки, а не только значение из параметра "Расшифровка"

КонецПроцедуры

В параметре Расшифровка содержится значение, которое мы заложили только для одной конкретной ячейки. Наша цель — получить доступ к соседним ячейкам той же строки. Рассмотрим три основных способа решения этой задачи.

Способ 1: Закладка всех данных строки в расшифровку (рекомендуемый)

Это самый правильный и надежный метод. Идея заключается в том, чтобы на этапе формирования табличного документа закладывать в расшифровку каждой ячейки не одно значение, а сразу всю необходимую информацию о строке. Обычно для этого используют объект Структура.

Разберем по шагам:

  1. При формировании отчета: Вместо того чтобы в расшифровку помещать примитивное значение (число, строку), создаем структуру и заполняем ее всеми данными, которые могут понадобиться. Затем эту структуру присваиваем в качестве расшифровки всем ячейкам выводимой строки.

    Посмотрим на пример. Допустим, мы выводим отчет по продажам с колонками "Номенклатура", "Количество", "Сумма".

    
    // Фрагмент кода формирования табличного документа
    Пока Выборка.Следующий() Цикл
        
        // Создаем структуру с данными текущей строки
        ДанныеСтроки = Новый Структура;
        ДанныеСтроки.Вставить("Номенклатура", Выборка.Номенклатура);
        ДанныеСтроки.Вставить("Количество", Выборка.Количество);
        ДанныеСтроки.Вставить("Сумма", Выборка.Сумма);
        ДанныеСтроки.Вставить("ДокументПродажи", Выборка.Регистратор);
        
        // Получаем области ячеек
        ОбластьНоменклатура = Макет.ПолучитьОбласть("Номенклатура");
        ОбластьКоличество = Макет.ПолучитьОбласть("Количество");
        ОбластьСумма = Макет.ПолучитьОбласть("Сумма");
    
        // Заполняем параметры
        ОбластьНоменклатура.Параметры.Номенклатура = Выборка.Номенклатура;
        ОбластьКоличество.Параметры.Количество = Выборка.Количество;
        ОбластьСумма.Параметры.Сумма = Выборка.Сумма;
        
        // ВАЖНО: Присваиваем одну и ту же структуру в расшифровку каждой ячейки
        ОбластьНоменклатура.Расшифровка = ДанныеСтроки;
        ОбластьКоличество.Расшифровка = ДанныеСтроки;
        ОбластьСумма.Расшифровка = ДанныеСтроки;
        
        // Выводим области
        ТабДок.Вывести(ОбластьНоменклатура);
        ТабДок.Присоединить(ОбластьКоличество);
        ТабДок.Присоединить(ОбластьСумма);
        
    КонецЦикла;
    
  2. При обработке расшифровки: Теперь, когда пользователь кликнет на любую из ячеек строки, в параметр Расшифровка прилетит наша структура. Работать с ней очень просто.

    
    Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры)
        
        СтандартнаяОбработка = Ложь;
        
        Если ТипЗнч(Расшифровка) = Тип("Структура") Тогда
            // Расшифровка содержит все, что нам нужно
            Сообщить("Выбрана номенклатура: " + Расшифровка.Номенклатура);
            Сообщить("Количество: " + Расшифровка.Количество);
            
            // Можем, например, открыть документ
            Если ЗначениеЗаполнено(Расшифровка.ДокументПродажи) Тогда
                ОткрытьФорму(Расшифровка.ДокументПродажи.ПолучитьФорму());
            КонецЕсли;
        КонецЕсли;
        
    КонецПроцедуры
    

Преимущества этого способа: код обработки расшифровки становится простым, читаемым и не зависит от расположения колонок в отчете. Это самый производительный и архитектурно верный подход.

Способ 2: Получение данных через `ТекущаяОбласть`

Этот метод полезен, когда мы не можем или не хотим изменять механизм формирования отчета. Например, работаем с готовым отчетом, в котором в расшифровку заложены только простые значения. Суть способа — определить координаты ячейки, по которой кликнули, и от них "дотянуться" до соседних.

Разберем по шагам:

  1. У элемента формы, который отображает табличный документ, есть свойство ТекущаяОбласть. Оно возвращает объект ОбластьЯчеекТабличногоДокумента, у которого есть свойства Верх, Низ, Лево, Право, указывающие на координаты области. Для одиночной ячейки Верх будет равен Низ (номер строки), а Лево будет равен Право (номер колонки).
  2. Зная номер текущей строки, мы можем получить любую другую ячейку из этой строки, обратившись к табличному документу по координатам с помощью метода Область(НомерСтроки, НомерКолонки).

Посмотрим на пример: Допустим, мы кликнули на ячейку в 5-й колонке, а нам нужно получить текст из 2-й колонки той же строки.


Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка, ДополнительныеПараметры)
    
    СтандартнаяОбработка = Ложь;
    
    // Элемент - это поле формы типа "ПолеТабличногоДокумента"
    // В нашем случае это, скорее всего, Элементы.Результат
    ТекущаяОбласть = Элемент.ТекущаяОбласть;
    
    Если ТекущаяОбласть = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем номер строки, по которой кликнули
    НомерСтроки = ТекущаяОбласть.Верх;
    
    // Предположим, что нужные нам данные (например, ссылка на номенклатуру)
    // находятся во 2-й колонке этой же строки.
    НомерНужнойКолонки = 2;
    
    // Получаем область нужной ячейки по координатам
    // Элемент.Имя - это имя реквизита формы, в котором хранится табличный документ.
    // Если поле формы называется "Результат", то и реквизит, скорее всего, тоже.
    ТабличныйДокумент = ЭтаФорма[Элемент.Имя];
    НужнаяЯчейка = ТабличныйДокумент.Область(НомерСтроки, НомерНужнойКолонки, НомерСтроки, НомерНужнойКолонки);
    
    // Теперь мы можем получить ее текст или расшифровку
    ЗначениеИзДругойКолонки = НужнаяЯчейка.Текст;
    РасшифровкаИзДругойКолонки = НужнаяЯчейка.Расшифровка;
    
    Сообщить("Значение из ячейки (" + НомерСтроки + ", " + НомерНужнойКолонки + "): " + ЗначениеИзДругойКолонки);
    
КонецПроцедуры

Недостатки этого способа: код жестко привязан к структуре отчета. Если пользователь поменяет порядок колонок, логика сломается. Метод менее производителен, если нужно обойти много ячеек. Однако он является отличным решением для быстрой доработки существующих отчетов без их полного переписывания.

Способ 3: Работа с отчетами на СКД и объектом `ДанныеРасшифровки`

Когда мы работаем с отчетом, построенным на Системе Компоновки Данных (СКД), ситуация немного иная. В параметр Расшифровка обычно попадает не само значение, а числовой идентификатор. Все данные отчета хранятся в специальном объекте ДанныеРасшифровки, который является реквизитом формы отчета.

По этому идентификатору мы можем найти элемент в коллекции ДанныеРасшифровки.Элементы и получить все поля, связанные с этой записью.

Посмотрим на пример:


&НаКлиенте
Процедура РезультатОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка)

    СтандартнаяОбработка = Ложь;
    
    // ДанныеРасшифровки - это реквизит формы, связанный с результатом отчета СКД
    ЭлементРасшифровки = ДанныеРасшифровки.Элементы[Расшифровка];
    
    // Получаем коллекцию полей для данного элемента расшифровки
    ПоляРасшифровки = ЭлементРасшифровки.ПолучитьПоля();
    
    // Теперь можем перебрать поля и найти нужное
    Для Каждого Поле Из ПоляРасшифровки Цикл
        
        // Поле.Поле - это имя поля (например, "Номенклатура")
        // Поле.Значение - его значение
        
        Сообщить(Строка(Поле.Поле) + ": " + Строка(Поле.Значение));
        
        Если Поле.Поле = "Номенклатура" Тогда
            НужнаяНоменклатура = Поле.Значение;
        КонецЕсли;
        
    КонецЦикла;
    
    // Иногда нужно получить данные из родительской группировки
    Родитель = ЭлементРасшифровки.ПолучитьРодителей();
    // и так далее...

КонецПроцедуры

В обсуждении на форуме был предложен код ДанныеРасшифровки.Элементы[Расшифровка + 2]. Это очень хрупкий и ненадежный подход. Он сработает только в том случае, если элементы расшифровки для ячеек одной строки идут в коллекции подряд в строго определенном порядке. Любое изменение в макете СКД может нарушить эту последовательность. Правильнее всего получать элемент по его идентификатору (Расшифровка) и работать с его полями или родительскими группировками, как показано в примере выше.

Таким образом, выбор способа зависит от вашей конкретной ситуации. Для новых разработок всегда используйте первый метод. Для доработки существующих отчетов без СКД подойдет второй. А при работе с отчетами на СКД — используйте объект ДанныеРасшифровки.

← На главную