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

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

При формировании печатных форм или кастомных отчетов в 1С:Предприятие разработчики часто сталкиваются с необходимостью динамически изменять оформление ячеек. Например, если сотрудник уволен, нам нужно вывести числовой показатель в особом формате (например, вместо пустой ячейки или стандартного нуля с копейками 0,00 вывести строгий ноль 0), а для работающих сотрудников сохранить стандартный формат с точностью до двух знаков после запятой (ЧДЦ=2).

В этой статье мы подробно разберем, почему стандартные попытки смещения координат вызывают «дикое смещение» строк табличного документа, как правильно манипулировать областями макета и как реализовать надежное решение, устойчивое к будущим изменениям структуры печатной формы.

Анализ проблемы: почему возникает смещение строк?

Рассмотрим исходный код, с которым автор темы обратился на форум:


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
   ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
   Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
      НомерСтроки = 22 + НомПП;
      ТабДок.Область("R" + НомерСтроки+"C10:R" + НомерСтроки + "C10").Текст = "0,00";            
   КонецЕсли;
КонецЦикла;

В данном примере разработчик пытается напрямую обратиться к результирующему документу ТабДок по абсолютным координатам строки и колонки (строка рассчитывается как 22 + НомПП, где 22 — это предполагаемая высота шапки документа).

Этот подход крайне нерекомендуем и приводит к ошибкам по следующим причинам:

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

Давайте разберем по шагам несколько вариантов решения этой задачи, начиная от простого исправления кода в макете и заканчивая профессиональными практиками динамического программирования.

Решение №1: Изменение формата в области макета перед выводом

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

Посмотрим на исправленный и рабочий вариант кода:


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
   
   // Заполняем параметры строки данными из табличной части
   ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
   
   // Проверяем условие (сотрудник уволен)
   Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
       // Обращаемся к ячейке внутри одной строки макета (1-я строка области, 10-я колонка)
       ОбластьСтрока.Область(1, 10, 1, 10).Формат = "ЧН=0";
   Иначе
       // Обязательно возвращаем исходный формат для работающих сотрудников
       ОбластьСтрока.Область(1, 10, 1, 10).Формат = "ЧДЦ=2";
   КонецЕсли;
   
   // Выводим уже настроенную строку в итоговый табличный документ
   ТабДок.Вывести(ОбластьСтрока);
   
КонецЦикла;

Важный нюанс этого метода: Поскольку мы модифицируем непосредственно шаблон макета ОбластьСтрока, измененный формат применится и ко всем последующим строкам в цикле. Поэтому нам **критически важно** в ветке Иначе явно возвращать исходный формат (ЧДЦ=2). Если этого не сделать, то после первого же уволенного сотрудника у всех последующих работающих сотрудников формат также собьется на ЧН=0.

Решение №2: Форматирование в результирующем документе через ВысотаТаблицы

Хотя предыдущее решение полностью рабочее, необходимость постоянно сбрасывать формат «назад» в ветке Иначе перегружает код. Мы можем поступить более элегантно: выводить стандартную строку «как есть», а затем точечно менять формат ячейки уже в готовом результирующем документе ТабДок.

Чтобы не считать строки вручную и полностью исключить ошибки смещения, мы задействуем свойство результирующего документа ВысотаТаблицы. После вывода очередной строки её индекс в табличном документе всегда в точности равен текущей высоте таблицы.

Проанализируем этот пример кода:


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
   
   ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
   
   // Сначала выводим строку со стандартным форматированием из макета
   ТабДок.Вывести(ОбластьСтрока); 
   
   // Если условие выполняется, точечно меняем формат в только что выведенной строке
   Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
       НомерТекущейСтроки = ТабДок.ВысотаТаблицы;
       ТабДок.Область(НомерТекущейСтроки, 10).Формат = "ЧН=0";
   КонецЕсли;
   
КонецЦикла;

Преимущества данного подхода:

Решение №3: Динамическое определение колонки (защита от изменения макета)

Предыдущие решения все еще содержат один недостаток — жестко прописанный номер колонки (10). Если в будущем дизайнер или аналитик решит добавить в печатную форму новую колонку слева (например, «Подразделение» или «Табельный номер»), наша целевая колонка сместится на 11-ю или 12-ю позицию. Код продолжит форматировать 10-ю колонку, что приведет к трудноуловимым ошибкам отображения данных.

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

  1. Откройте макет в конфигураторе 1С.
  2. Выделите ячейку в 10-й колонке строки (где выводится сумма/число).
  3. В свойствах ячейки найдите поле Имя и задайте ей уникальный идентификатор, например: ЯчейкаСуммы.

Теперь мы можем один раз перед началом цикла динамически определить индекс этой колонки с помощью свойства Лево:


ОбластьСтрока = Макет.ПолучитьОбласть("Строка");

// Динамически получаем индекс колонки по ее имени в макете
НомерКолонкиСуммы = ОбластьСтрока.Область("ЯчейкаСуммы").Лево;

Для Каждого СтрокаТЧ Из ЭтотОбъект.Объект.Сотрудники Цикл
   
   ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
   ТабДок.Вывести(ОбластьСтрока); 
   
   Если СотрудникУволен(СтрокаТЧ.Сотрудник, Документ.Дата) Тогда
       // Используем динамически определенный номер колонки
       ТабДок.Область(ТабДок.ВысотаТаблицы, НомерКолонкиСуммы).Формат = "ЧН=0";
   КонецЕсли;
   
КонецЦикла;

Даже если структура макета кардинально изменится, платформа автоматически найдет именованную ячейку и вернет ее актуальный порядковый номер. Код продолжит работать корректно без дополнительного вмешательства программиста.

Важный нюанс: Сохранение типов при экспорте печатной формы в Excel

Иногда разработчики пытаются решить задачу форматирования «в лоб», преобразуя число в строку прямо при заполнении параметров:

ОбластьСтрока.Параметры.Сумма = Формат(СтрокаТЧ.Сумма, "ЧН=0");

Этого делать настоятельно не рекомендуется!

Функция Формат() преобразует числовое значение в тип Строка. Если конечный пользователь захочет сохранить полученную печатную форму в формате Excel (XLS/XLSX), то все такие ячейки запишутся туда как текстовые. В результате пользователи лишатся возможности использовать стандартные математические формулы Excel (например, они не смогут автоматически просуммировать колонку через функцию =СУММ() без ручной конвертации данных).

Для сохранения числового типа данных всегда придерживайтесь правил:

Подведем итоги

Мы рассмотрели три прогрессивных метода условного форматирования ячеек в 1С. Для простых разовых задач отлично подойдет Решение №2 с использованием ВысотаТаблицы. Для создания крупных корпоративных отчетов и печатных форм, которые будут активно дорабатываться в будущем, настоятельно рекомендуем использовать Решение №3 с именованными областями ячеек.

← На главную