При формировании печатных форм или кастомных отчетов в 1С:Предприятие разработчики часто сталкиваются с необходимостью динамически изменять оформление ячеек. Например, если сотрудник уволен, нам нужно вывести числовой показатель в особом формате (например, вместо пустой ячейки или стандартного нуля с копейками 0,00 вывести строгий ноль 0), а для работающих сотрудников сохранить стандартный формат с точностью до двух знаков после запятой (ЧДЦ=2).
В этой статье мы подробно разберем, почему стандартные попытки смещения координат вызывают «дикое смещение» строк табличного документа, как правильно манипулировать областями макета и как реализовать надежное решение, устойчивое к будущим изменениям структуры печатной формы.
Рассмотрим исходный код, с которым автор темы обратился на форум:
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
НомерСтроки = 22 + НомПП;
ТабДок.Область("R" + НомерСтроки+"C10:R" + НомерСтроки + "C10").Текст = "0,00";
КонецЕсли;
КонецЦикла;
В данном примере разработчик пытается напрямую обратиться к результирующему документу ТабДок по абсолютным координатам строки и колонки (строка рассчитывается как 22 + НомПП, где 22 — это предполагаемая высота шапки документа).
Этот подход крайне нерекомендуем и приводит к ошибкам по следующим причинам:
22 станет неактуальной. Координаты «съедут», и код начнет форматировать совершенно другие ячейки.ТабДок.Вывести(). Попытка записать значение в ТабДок.Область(...) до фактического вывода строки ломает последовательную структуру заполнения табличного документа, вызывая наложение областей и появление лишних пустых строк.Давайте разберем по шагам несколько вариантов решения этой задачи, начиная от простого исправления кода в макете и заканчивая профессиональными практиками динамического программирования.
Самый быстрый способ исправить логику — это вносить изменения не в результирующий документ ТабДок, а непосредственно в подготовленную к выводу локальную область макета ОбластьСтрока. Только после установки всех параметров и форматов мы выводим эту область на печать.
Посмотрим на исправленный и рабочий вариант кода:
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
// Заполняем параметры строки данными из табличной части
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
// Проверяем условие (сотрудник уволен)
Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
// Обращаемся к ячейке внутри одной строки макета (1-я строка области, 10-я колонка)
ОбластьСтрока.Область(1, 10, 1, 10).Формат = "ЧН=0";
Иначе
// Обязательно возвращаем исходный формат для работающих сотрудников
ОбластьСтрока.Область(1, 10, 1, 10).Формат = "ЧДЦ=2";
КонецЕсли;
// Выводим уже настроенную строку в итоговый табличный документ
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
Важный нюанс этого метода: Поскольку мы модифицируем непосредственно шаблон макета ОбластьСтрока, измененный формат применится и ко всем последующим строкам в цикле. Поэтому нам **критически важно** в ветке Иначе явно возвращать исходный формат (ЧДЦ=2). Если этого не сделать, то после первого же уволенного сотрудника у всех последующих работающих сотрудников формат также собьется на ЧН=0.
ВысотаТаблицыХотя предыдущее решение полностью рабочее, необходимость постоянно сбрасывать формат «назад» в ветке Иначе перегружает код. Мы можем поступить более элегантно: выводить стандартную строку «как есть», а затем точечно менять формат ячейки уже в готовом результирующем документе ТабДок.
Чтобы не считать строки вручную и полностью исключить ошибки смещения, мы задействуем свойство результирующего документа ВысотаТаблицы. После вывода очередной строки её индекс в табличном документе всегда в точности равен текущей высоте таблицы.
Проанализируем этот пример кода:
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
// Сначала выводим строку со стандартным форматированием из макета
ТабДок.Вывести(ОбластьСтрока);
// Если условие выполняется, точечно меняем формат в только что выведенной строке
Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
НомерТекущейСтроки = ТабДок.ВысотаТаблицы;
ТабДок.Область(НомерТекущейСтроки, 10).Формат = "ЧН=0";
КонецЕсли;
КонецЦикла;
Преимущества данного подхода:
Иначе. Сам шаблон макета ОбластьСтрока остается нетронутым, а значит, все строки по умолчанию выводятся со своим стандартным оформлением.22 + НомПП). Программа сама динамически определяет позицию строки на основе свойства ВысотаТаблицы.Предыдущие решения все еще содержат один недостаток — жестко прописанный номер колонки (10). Если в будущем дизайнер или аналитик решит добавить в печатную форму новую колонку слева (например, «Подразделение» или «Табельный номер»), наша целевая колонка сместится на 11-ю или 12-ю позицию. Код продолжит форматировать 10-ю колонку, что приведет к трудноуловимым ошибкам отображения данных.
Чтобы защитить структуру от изменений, мы можем назначить нужной ячейке в конфигураторе уникальное имя. Давайте разберем, как это сделать:
ЯчейкаСуммы.Теперь мы можем один раз перед началом цикла динамически определить индекс этой колонки с помощью свойства Лево:
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
// Динамически получаем индекс колонки по ее имени в макете
НомерКолонкиСуммы = ОбластьСтрока.Область("ЯчейкаСуммы").Лево;
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
ТабДок.Вывести(ОбластьСтрока);
Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
// Используем динамически определенный номер колонки
ТабДок.Область(ТабДок.ВысотаТаблицы, НомерКолонкиСуммы).Формат = "ЧН=0";
КонецЕсли;
КонецЦикла;
Даже если структура макета кардинально изменится, платформа автоматически найдет именованную ячейку и вернет ее актуальный порядковый номер. Код продолжит работать корректно без дополнительного вмешательства программиста.
Иногда разработчики пытаются решить задачу форматирования «в лоб», преобразуя число в строку прямо при заполнении параметров:
ОбластьСтрока.Параметры.Сумма = Формат(СтрокаТЧ.Сумма, "ЧН=0");
Этого делать настоятельно не рекомендуется!
Функция Формат() преобразует числовое значение в тип Строка. Если конечный пользователь захочет сохранить полученную печатную форму в формате Excel (XLS/XLSX), то все такие ячейки запишутся туда как текстовые. В результате пользователи лишатся возможности использовать стандартные математические формулы Excel (например, они не смогут автоматически просуммировать колонку через функцию =СУММ() без ручной конвертации данных).
Для сохранения числового типа данных всегда придерживайтесь правил:
Формат ячейки табличного документа.Мы рассмотрели три прогрессивных метода условного форматирования ячеек в 1С. Для простых разовых задач отлично подойдет Решение №2 с использованием ВысотаТаблицы. Для создания крупных корпоративных отчетов и печатных форм, которые будут активно дорабатываться в будущем, настоятельно рекомендуем использовать Решение №3 с именованными областями ячеек.