При формировании сложных отчетов, особенно в регламентированной отчетности, разработчики часто сталкиваются с необходимостью не просто вывести данные в ТабличныйДокумент, но и обеспечить интерактивность. Основная проблема заключается в том, что при использовании метода Вывести() ячейкам по умолчанию присваиваются системные адреса формата R1C1 (например, R6C7). Если логика формы (например, в обработчике ТабличныйДокументВыбор) завязана на конкретные имена ячеек, стандартный вывод «ломает» работу алгоритмов. В этой статье мы подробно разберем, как программно назначать уникальные имена ячейкам в процессе формирования документа.
Представим ситуацию: у нас есть макет с многострочной частью. В макете ячейка имеет имя П1000001_1. При выводе этой области в цикле 1С копирует содержимое, но не может продублировать имя ячейки для каждой новой строки, так как имена в коллекции Области табличного документа должны быть уникальными. В итоге, после вывода второй, третьей и последующих строк, мы теряем возможность обращаться к ячейкам по имени П1000001_1, так как оно либо пропадает, либо ссылается только на последний выведенный экземпляр.
Для решения этой задачи нам необходимо реализовать алгоритм, который будет «подхватывать» только что выведенную область и переименовывать в ней нужные ячейки, добавляя к ним индекс строки (например, П1000001_1_1, П1000001_1_2 и так далее).
Разберем фундаментальный механизм метода Вывести(). Мало кто использует тот факт, что данный метод возвращает значение. Согласно синтакс-помощнику, результатом выполнения метода Вывести() является объект типа ОбластьЯчеекТабличногоДокумента. Это именно та область, которая только что была вставлена в итоговый документ.
Рассмотрим пример базового кода в цикле:
// Подготовка счетчика для уникальности имен
ИндексСтроки = 0;
Пока Выборка.Следующий() Цикл
ИндексСтроки = ИндексСтроки + 1;
// Получаем область из макета
ОбластьСтрока = Макет.ПолучитьОбласть("МногострочнаяЧасть");
// Заполняем параметры
ОбластьСтрока.Параметры.Значение = Выборка.Ном;
// Выводим область и СОХРАНЯЕМ результат в переменную
ВыведеннаяОбласть = ТабДок.Вывести(ОбластьСтрока);
// Теперь переменная ВыведеннаяОбласть содержит ссылку на блок в ТабДок
КонецЦикла;
Проблема, озвученная многими разработчиками, заключается в том, что ВыведеннаяОбласть — это чаще всего целая строка или блок. Чтобы переименовать конкретную ячейку внутри этого блока, нам нужно обратиться к ней по относительным координатам. Для этого используется метод Область(), но уже не к макету, а к нашей переменной ВыведеннаяОбласть.
Проанализируем синтаксис: ВыведеннаяОбласть.Область(НомерСтроки, НомерКолонки, НомерСтроки, НомерКолонки). Поскольку мы работаем внутри одной выведенной строки, координаты обычно начинаются с 1.
Важно: При назначении имени необходимо строго соблюдать правила именования идентификаторов в 1С. Имя не может содержать пробелы, начинаться с цифры или содержать специальные символы вроде скобок. Предложение использовать формат "Имя(1)" является ошибочным и приведет к исключению.
Правильный алгоритм переименования выглядит так:
// Внутри цикла после вывода
// Предположим, нужная нам ячейка — первая в выведенной области
ЯчейкаИмя = ВыведеннаяОбласть.Область(1, 1, 1, 1);
// Формируем уникальное имя без запрещенных символов
НовоеИмя = "П1000001_1_" + Формат(ИндексСтроки, "ЧГ=0");
// Назначаем имя
ЯчейкаИмя.Имя = НовоеИмя;
Соберем все части решения в единый рабочий код. Рассмотрим ситуацию, когда в макете есть область МногострочнаяЧастьП10000, внутри которой нам нужно именовать ячейки для последующей обработки в ТабличныйДокументВыбор.
Индекс = 0;
ОбластьМакета = Макет.ПолучитьОбласть("МногострочнаяЧастьП10000");
Пока Выборка.Следующий() Цикл
Индекс = Индекс + 1;
// Заполняем значение в области макета (подготовка)
ОбластьМакета.Области.П1000001_1.Значение = Выборка.Ном;
// Выводим область в итоговый документ
ТекущаяСтрокаДокумента = ТабДок.Вывести(ОбластьМакета);
// Находим нужную ячейку внутри выведенного блока.
// Если П1000001_1 была единственной или первой колонкой:
НужнаяЯчейка = ТекущаяСтрокаДокумента.Область(1, 11, 1, 11); // Например, 11-я колонка
// Устанавливаем уникальное имя
НужнаяЯчейка.Имя = "П1000001_1_" + Формат(Индекс, "ЧГ=0");
// Дополнительно можно прописать расшифровку, если имен недостаточно
НужнаяЯчейка.Расшифровка = Выборка.Ссылка;
КонецЦикла;
Проанализируем причину, по которой стандартные механизмы 1С требуют именно именования. В типовых конфигурациях (БП, ЗУП, ERP) обработка клика по ячейке часто реализована через поиск подстроки в имени ячейки. Если вы измените структуру имен, стандартный обработчик ТабличныйДокументВыбор просто не поймет, по какой строке нажал пользователь. Присваивая имена программно через индекс (_1, _2), мы сохраняем совместимость с типовыми механизмами расшифровки, которые ожидают увидеть код показателя и его порядковый номер.
Если задача не жестко привязана к именам ячеек (например, вы создаете отчет «с нуля»), рассмотрите возможность использования механизма Расшифровка (Details). Вместо создания тысяч именованных областей, что может замедлить работу ТабличногоДокумента и увеличить размер файла при сохранении в Excel, можно записывать в ячейку структуру или уникальный идентификатор. В обработчике события Выбор данные расшифровки доступны напрямую, что избавляет от необходимости парсить строку имени ячейки.
Однако, в случае с правкой существующих регламентированных отчетов, метод с программным именованием через Вывести().Имя остается единственным верным техническим решением, позволяющим не переписывать сотни строк стандартного кода обработки событий.