Как программно обратиться к результатам отчета СКД на форме и обработать изменения пользователя

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

При разработке сложных аналитических инструментов на базе 1С часто возникает задача: не просто вывести отчет с помощью Системы компоновки данных (СКД), но и позволить пользователю отредактировать полученные цифры или текстовые комментарии прямо в форме отчета, а затем сохранить эти изменения или использовать их в дальнейших расчетах. В этой статье мы подробно разберем, как «дотянуться» до данных, которые пользователь внес в ТабличныйДокумент, и как правильно сопоставить эти строки с реальными объектами базы данных.

Проблема потери связи между данными и визуальным представлением

Когда СКД выводит результат, она формирует ТабличныйДокумент. На этом этапе живая связь с источником данных (запросом или объектной схемой) обрывается. Перед программистом встает вопрос: как понять, что число в строке №10 относится именно к «Номенклатуре: Смартфон», если пользователь мог изменить и само название, и значение в колонке? Рассмотрим наиболее эффективные способы решения этой задачи.

Способ 1. Использование механизма расшифровки (ДанныеРасшифровки)

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

Для реализации этого метода нам потребуется объект ДанныеРасшифровкиКомпоновкиДанных. Разберем по шагам, как это работает в коде:


// 1. Получаем объект расшифровки из временного хранилища (обычно хранится в реквизите формы ДанныеРасшифровки)
Данные = ПолучитьИзВременногоХранилища(ДанныеРасшифровки);

// 2. Определяем область, которую хотим обработать (например, весь табличный документ)
ТабДок = Отчет.Результат;
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
    Ячейка = ТабДок.Область(НомерСтроки, 1); // Допустим, идентификатор в первой колонке
    
    // 3. Получаем идентификатор расшифровки из ячейки
    ИдРасшифровки = Ячейка.Расшифровка;
    
    Если ИдРасшифровки <> Неопределено Тогда
        // 4. Извлекаем содержимое расшифровки
        Содержимое = Данные.Элементы.Получить(ИдРасшифровки);
        
        Если ТипЗнч(Содержимое) = Тип("ДанныеРасшифровкиПоля") Тогда
            Для Каждого Поле Из Содержимое.ПолучитьПоля() Цикл
                Если Поле.Поле = "Ссылка" Тогда
                    ОбъектБД = Поле.Значение; // Вот мы и нашли наш объект!
                    // Теперь берем измененный текст из нужной колонки
                    НовоеЗначение = ТабДок.Область(НомерСтроки, 3).Текст;
                    // Обрабатываем...
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

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

Способ 2. Хранение значений в ячейках (Свойство «Содержать значение»)

Выясним причину, по которой обычный перебор ТабДок.Область().Текст может привести к ошибкам. Если пользователь вводит число или дату, то в свойстве Текст мы получаем строковое представление. Это неудобно для вычислений. Мы можем настроить ячейки так, чтобы они хранили типизированное значение.

Рассмотрим алгоритм настройки:

  1. При программном выводе отчета (через ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент) необходимо перехватывать момент вывода каждой области.
  2. Для ячеек, предназначенных для ввода данных, устанавливается флаг СодержатьЗначение = Истина.
  3. Указывается ТипЗначения (например, ОписаниеТипов("Число")).

В этом случае при обработке результата мы будем обращаться не к .Текст, а к свойству .Значение:


ТекущаяЯчейка = ТабДок.Область(Строка, Колонка);
Если ТекущаяЯчейка.СодержатьЗначение Тогда
    Сумма = ТекущаяЯчейка.Значение; // Получаем чистое число, а не строку
КонецЕсли;

Способ 3. Скрытые идентификаторы (Техника «Колонка 0»)

Если работа с объектом ДанныеРасшифровки кажется избыточной, проанализируем более простой «хакерский» метод. Мы можем добавить в настройки СКД поле, содержащее уникальный идентификатор строки (например, GUID или Код), и вывести его в отдельную колонку.

Разберем, как скрыть эти данные от пользователя:


// Скрываем колонку с идентификатором (например, колонку №2)
ТабДок.Область(, 2, , 2).ШиринаКолонки = 0;

// При обработке:
Идентификатор = ТабДок.Область(НомерСтроки, 2).Текст;

Способ 4. Отслеживание изменений «на лету» (События формы)

Чтобы не перебирать тысячи строк в поисках одной измененной ячейки, воспользуемся событиями элемента формы Результат (тип ПолеТабличногоДокумента). Посмотрим на пример использования события ПриИзмененииСодержимогоОбласти.

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


&НаКлиенте
Процедура РезультатПриИзмененииСодержимогоОбласти(Элемент, Область)
    // Область — это именно та ячейка, которую поменяли
    НомерСтроки = Область.Верх;
    НовоеЗначение = Область.Текст;
    
    // Можем сразу найти ID строки через расшифровку или скрытую колонку
    // и записать в ТЗ "ИзмененныеДанные"
КонецПроцедуры

Способ 5. Преобразование табличного документа обратно в таблицу значений

Если структура вашего отчета плоская (простой список без группировок), иногда проще всего полностью «выгрузить» содержимое ТабличногоДокумента в ТаблицуЗначений и работать уже с ней как с обычным объектом 1С.

Посмотрим на пример универсальной функции обхода:


Функция ТЗИзТабличногоДокумента(ТабДок) Экспорт
    ТЗ = Новый ТаблицаЗначений;
    // Создаем колонки на основании заголовков (допустим, строка 1)
    Для Кол = 1 По ТабДок.ШиринаТаблицы Цикл
        ТЗ.Колонки.Добавить("Колонка" + Кол);
    КонецЦикла;
    
    // Заполняем данными
    Для Стр = 2 По ТабДок.ВысотаТаблицы Цикл
        НоваяСтрока = ТЗ.Добавить();
        Для Кол = 1 По ТабДок.ШиринаТаблицы Цикл
            НоваяСтрока["Колонка" + Кол] = ТабДок.Область(Стр, Кол).Текст;
        КонецЦикла;
    КонецЦикла;
    Возврат ТЗ;
КонецФункции

Рекомендации по оптимизации

При работе с большими отчетами (свыше 5000 строк) прямой перебор ячеек на клиенте может привести к значительному замедлению интерфейса («фризам»). В таких случаях рекомендуется передавать табличный документ на сервер и выполнять его разбор там. На сервере обращение к областям ячеек происходит быстрее, а использование расшифровки через ПолучитьИзВременногоХранилища работает стабильнее.

Подведем итог: для простого чтения данных достаточно цикла по ВысотаТаблицы. Для профессиональной разработки и надежной связи с базой данных следует использовать ДанныеРасшифровки. Если же отчет предполагает массовый ввод данных пользователем, лучшим выбором будет использование Таблицы Значений в качестве источника данных для формы, вместо прямого редактирования результата СКД.

← На главную