При формировании отчетов или печатных форм в 1С часто возникает задача не просто вывести данные, но и акцентировать внимание пользователя на определенных значениях. Например, если какое-то число выходит за допустимые пределы, нужно подсветить ячейку или вывести предупреждение. Основная проблема заключается в том, чтобы в момент формирования табличного документа из макета точно узнать, в какой ячейке окажется то или иное значение, особенно если макет выводится многократно. При этом хочется избежать сложных и громоздких ручных счетчиков строк и колонок.
Рассмотрим по шагам, как решить эту задачу: сначала научимся точно определять координаты нужной ячейки, а затем разберем, как лучше всего привлечь к ней внимание пользователя.
Ключ к решению — это правильное использование метода Вывести() объекта ТабличныйДокумент. Многие разработчики воспринимают его как процедуру, которая просто добавляет область макета в итоговый документ. Однако на самом деле это функция, которая возвращает объект ОбластьЯчеекТабличногоДокумента. Этот возвращаемый объект содержит абсолютные координаты (верх, низ, лево, право) вставленного фрагмента в итоговом табличном документе. Именно это позволяет нам точно рассчитать положение любой ячейки внутри этого фрагмента.
Алгоритм действий будет следующим:
Разберем каждый шаг подробнее.
Прежде чем выводить область, нам нужно знать, где внутри нее находится ячейка с интересующим нас параметром. Для этого можно написать вспомогательную функцию, которая переберет все ячейки в переданной области макета и найдет ту, у которой свойство Параметр совпадает с искомым именем.
Важный момент: нужно проверять, что тип заполнения ячейки — именно Параметр, так как ячейка может быть заполнена текстом или шаблоном.
Посмотрим на пример такой функции. Она будет возвращать массив структур с относительными координатами (номер строки и колонки), так как один и тот же параметр может встречаться в области макета несколько раз.
Функция ПолучитьОтносительныйАдресВОбласти(ОбластьМакета, ИмяПараметра)
НайденныеАдреса = Новый Массив;
// Перебираем все ячейки внутри области макета
Для НомерСтроки = 1 По ОбластьМакета.Высота Цикл
Для НомерКолонки = 1 По ОбластьМакета.Ширина Цикл
// Получаем конкретную ячейку
ЯчейкаМакета = ОбластьМакета.Область(НомерСтроки, НомерКолонки, НомерСтроки, НомерКолонки);
// Проверяем тип заполнения и имя параметра
Если ЯчейкаМакета.Заполнение = ТипЗаполненияОбластиТабличногоДокумента.Параметр
И ЯчейкаМакета.Параметр = ИмяПараметра Тогда
Координаты = Новый Структура("Строка, Колонка", НомерСтроки, НомерКолонки);
НайденныеАдреса.Добавить(Координаты);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат НайденныеАдреса;
КонецФункции
Теперь, имея эту функцию, мы можем легко получить относительное положение ячейки, например: ОтносительныеКоординаты = ПолучитьОтносительныйАдресВОбласти(Макет.ПолучитьОбласть("Строка"), "Номенклатура");
Теперь самое главное. В цикле формирования отчета, когда мы выводим очередную область, мы сохраняем результат вывода в переменную.
// ... в цикле обхода данных ...
// Заполняем параметры области
ОбластьСтрока.Параметры.Заполнить(ДанныеСтроки);
// Выводим область и получаем ее положение в итоговом документе
ВыведеннаяОбласть = ТабличныйДокументРезультат.Вывести(ОбластьСтрока);
// Теперь в переменной ВыведеннаяОбласть есть свойства Верх, Лево, Низ, Право
Зная относительные координаты из Шага 1 и абсолютные координаты верхнего левого угла выведенной области, мы можем рассчитать итоговый адрес нужной нам ячейки.
// Предположим, мы ищем ячейку с параметром "Сумма"
ОтносительныеКоординаты = ПолучитьОтносительныйАдресВОбласти(ОбластьСтрока, "Сумма");
// Если ячейка найдена (берем первую из найденных для простоты)
Если ОтносительныеКоординаты.Количество() > 0 Тогда
ОтносительнаяСтрока = ОтносительныеКоординаты[0].Строка;
ОтносительнаяКолонка = ОтносительныеКоординаты[0].Колонка;
// Рассчитываем абсолютные координаты
АбсолютнаяСтрока = ВыведеннаяОбласть.Верх + ОтносительнаяСтрока - 1;
АбсолютнаяКолонка = ВыведеннаяОбласть.Лево + ОтносительнаяКолонка - 1;
// Формируем строковый адрес ячейки
АдресЯчейки = "R" + АбсолютнаяСтрока + "C" + АбсолютнаяКолонка;
// Теперь у нас есть точный адрес ячейки, и мы можем с ней что-то сделать
// Например, выделить ее, если есть некое условие
Если ДанныеСтроки.Сумма > 100000 Тогда
// ... код для выделения ячейки ...
КонецЕсли;
КонецЕсли;
Первоначальная идея автора темы — использовать объект СообщениеПользователю и его свойство Поле, чтобы привязать сообщение к ячейке табличного документа. К сожалению, этот механизм так не работает.
Свойство Поле предназначено для привязки к реквизитам формы или колонкам табличной части (например, "Объект.Товары[10].Цена"). Табличный документ на форме — это единый элемент управления, и платформа не предоставляет штатного способа адресовать сообщение к внутренней ячейке через путь вида "РезультатОтчета[R5C10]".
Но есть отличные и даже более наглядные альтернативы.
Это самый распространенный и эффективный способ. Получив адрес ячейки, мы можем изменить ее фон, цвет текста, шрифт и т.д. Это сразу бросается в глаза пользователю.
// ... после вычисления АдресЯчейки ...
Если УсловиеВыделения Тогда
// Получаем область конкретной ячейки по ее адресу
ПроблемнаяЯчейка = ТабличныйДокументРезультат.Область(АдресЯчейки);
// И меняем ее оформление
ПроблемнаяЯчейка.ЦветФона = WebЦвета.СветлоРозовый;
ПроблемнаяЯчейка.Шрифт = Новый Шрифт(ПроблемнаяЯчейка.Шрифт, , Истина); // Делаем жирным
ПроблемнаяЯчейка.ГоризонтальноеПоложение = ГоризонтальноеПоложениеЭлементаУправления.Центр;
КонецЕсли;
Если нужно не просто выделить ячейку, а дать пояснение, идеально подойдет примечание. Оно отображается при наведении курсора мыши на ячейку.
// ... после вычисления АдресЯчейки ...
Если УсловиеВыделения Тогда
ПроблемнаяЯчейка = ТабличныйДокументРезультат.Область(АдресЯчейки);
// Добавляем текст примечания
ПроблемнаяЯчейка.Примечание.Текст = "Внимание! Сумма превышает установленный лимит.";
// Можно сделать так, чтобы примечание отображалось всегда
ПроблемнаяЯчейка.ОтображатьПримечание = РежимОтображенияПримечанийТабличногоДокумента.Всегда;
КонецЕсли;
Если в дальнейшем вам понадобится обращаться к этой ячейке, можно присвоить ей уникальное имя. Это удобнее, чем каждый раз вычислять ее адрес заново.
// Генерируем уникальное имя, например, на основе идентификатора данных
УникальноеИмяЯчейки = "Сумма_" + ДанныеСтроки.Ссылка.УникальныйИдентификатор();
// Присваиваем имя
ТабличныйДокументРезультат.Область(АдресЯчейки).Имя = УникальноеИмяЯчейки;
// Позже можно легко получить эту область по имени
НужнаяОбласть = ТабличныйДокументРезультат.Область(УникальноеИмяЯчейки);
Если вам нужно найти ячейку не по параметру макета, а по ее текстовому содержимому уже после формирования документа, можно использовать метод НайтиТекст(). Важно помнить, что для поиска всех вхождений его нужно вызывать в цикле, каждый раз передавая ранее найденную область в качестве стартовой точки для следующего поиска.
Функция НайтиВсеОбластиПоТексту(ТабДок, ИскомыйТекст) Экспорт
НайденныеОбласти = Новый Массив;
// Ищем первое вхождение
НайденнаяОбласть = ТабДок.НайтиТекст(ИскомыйТекст);
Пока НайденнаяОбласть <> Неопределено Цикл
НайденныеОбласти.Добавить(НайденнаяОбласть);
// Ищем следующее вхождение, начиная с области, следующей за найденной
НайденнаяОбласть = ТабДок.НайтиТекст(ИскомыйТекст, НайденнаяОбласть);
КонецЦикла;
Возврат НайденныеОбласти;
КонецФункции
// Пример использования
ВсеЯчейкиСНужнымТекстом = НайтиВсеОбластиПоТексту(ТабличныйДокументРезультат, "Итог");
Для Каждого ОбластьИтога Из ВсеЯчейкиСНужнымТекстом Цикл
ОбластьИтога.ЦветФона = WebЦвета.СветлоЖелтый;
КонецЦикла;
Таким образом, комбинируя эти подходы, вы можете полностью контролировать процесс формирования табличного документа, точно определять положение нужных данных и гибко управлять их визуальным представлением для пользователя.