При разработке сложных программных отчетов в 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда стандартный вывод данных из запроса не подходит. Запрос может возвращать данные в одном порядке, а бизнес-логика или требования пользователя диктуют совершенно иной. Попытки перестроить сам запрос часто приводят к его усложнению или «поломке» из-за специфических соединений и группировок. В этой статье мы подробно разберем, как решить проблему вывода колонок в произвольном порядке, используя программные методы работы с табличным документом.
Рассмотрим классическую ситуацию: у нас есть основной набор данных (результат запроса) и вспомогательный набор данных (например, Таблица Значений), в котором жестко задан правильный порядок следования ключевых полей. Наша цель — вывести отчет так, чтобы колонки следовали именно в том порядке, который указан во вспомогательной таблице. Главная ошибка новичков — попытка «найти» уже выведенную колонку в готовом документе. Правильный подход заключается в управлении процессом вывода в момент формирования документа.
Самый гибкий и эффективный способ — это создание в макете одной вертикальной секции, которую мы будем многократно выводить методом Присоединить(). Давайте проанализируем, как это работает по шагам.
Во-первых, в макете создается область (например, с именем КолонкаДанных), охватывающая нужные колонки по вертикали. Во-вторых, мы организуем цикл не по результату основного запроса, а по той самой таблице, где задан верный порядок.
Рассмотрим пример кода:
// Получаем макет и создаем табличный документ
Макет = ПолучитьМакет("МойМакет");
ТабДок = Новый Табличный Документ;
// Область шапки (горизонтальная)
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ТабДок.Вывести(ОбластьШапка);
// Цикл по Таблице Значений, где задан ПРАВИЛЬНЫЙ порядок колонок
Для Каждого СтрокаПорядка Из ТЗ_ПравильныйПорядок Цикл
// Получаем вертикальную область для колонки
ОбластьКолонка = Макет.ПолучитьОбласть("Колонка");
// Заполняем параметры области данными из основного набора
// Предположим, у нас есть СтруктураДанных, где ключи - названия колонок
ОбластьКолонка.Параметры.Заголовок = СтрокаПорядка.ИмяКолонки;
// Присоединяем колонку справа к предыдущим
ТабДок.Присоединить(ОбластьКолонка);
КонецЦикла;
Этот метод позволяет полностью абстрагироваться от того, в какой последовательности данные пришли из базы данных. Мы управляем порядком «на лету».
В сообщениях форума упоминалось использование Структуры, однако важно помнить: элементы структуры не имеют гарантированного порядка. Если вы добавите элементы в структуру, нет никакой уверенности, что при обходе Для Каждого они появятся в том же порядке.
Чтобы эффективно связать данные и порядок, мы рекомендуем использовать следующую связку:
Соответствие, где ключом будет уникальный идентификатор колонки, а значением — данные для вывода.Массив или Таблицу Значений для хранения ключей в нужном порядке.Соответствия и выводим их в ТабДок.Разберем пример реализации:
// 1. Собираем данные в соответствие (ключ -> данные)
ДанныеКолонок = Новый Соответствие;
Для Каждого СтрДанных Из РезультатЗапроса Цикл
ДанныеКолонок.Вставить(СтрДанных.КлючСвязи, СтрДанных.Значение);
КонецЦикла;
// 2. Выводим в порядке, заданном в Массиве "НужныйПорядокКлючей"
Для Каждого ТекКлюч Из НужныйПорядокКлючей Цикл
ЗначениеДляВывода = ДанныеКолонок.Получить(ТекКлюч);
Область = Макет.ПолучитьОбласть("СекцияДанных");
Область.Параметры.Значение = ЗначениеДляВывода;
ТабДок.Присоединить(Область);
КонецЦикла;
Если ваш отчет базируется на Системе компоновки данных (СКД), то задача решается еще элегантнее. Вместо того чтобы вручную рисовать ячейки, мы можем программно переопределить состав и порядок выбранных полей.
Проанализируем алгоритм работы с настройками компоновки:
КомпоновщикНастроек.Настройки).ВыбранныеПоля.Пример программного добавления полей:
Настройки = КомпоновщикНастроек.Настройки;
Настройки.ВыбранныеПоля.Элементы.Очистить();
Для Каждого ИмяПоля Из МассивНужныхИмен Цикл
НовоеПоле = Настройки.ВыбранныеПоля.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
НовоеПоле.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
НовоеПоле.Использование = Истина;
КонецЦикла;
Иногда удобнее сначала «собрать» финальную таблицу данных в памяти, а потом просто вывести её целиком. В объекте ТаблицаЗначений можно программно управлять колонками.
Хотя метода «ПереместитьКолонку» с индексом в 1С нет, мы можем использовать метод Сдвинуть() для коллекции колонок. Однако надежнее создать новую ТЗ, добавить в нее колонки в нужном порядке и скопировать данные. После этого вывод в ТабличныйДокумент превращается в два простых вложенных цикла: по строкам и по колонкам ТЗ.
В сообщении №4 автор спрашивает: «Как найти нужную колонку из таб дока для их связи?». Запомните: искать колонку в сформированном документе — это ресурсоемкая операция, требующая чтения текста ячеек.
Рекомендация: всегда используйте имена параметров в макете. В области макета ячейке можно назначить параметр (например, <текст>ТекущийПоказатель</текст>). При выводе области вы обращаетесь к нему напрямую: Область.Параметры.ТекущийПоказатель = Значение. Это исключает необходимость поиска «по координатам» или «по тексту».
Мы выяснили причину сложности: попытка подстроиться под результат запроса вместо того, чтобы управлять выводом самостоятельно. Рассмотренные методы — использование вертикальных областей с Присоединить() и программная настройка СКД — являются профессиональными стандартами разработки в 1С. Выбор конкретного метода зависит от объема данных и используемого механизма отчетов в вашей конфигурации.