Что делать, когда клиент просит отчет по предложенному в Excel макету, содержащий, по меньшей мере, с полсотни столбцов, и, вдобавок, требует, чтобы была возможность все эти столбцы при желании отключать? Предложить ему воспользоваться СКД? Возможно, кто-то так и делает, но мои клиенты почему-то, при виде аббревиатуры СКД, сразу скисают, однако, отчеты с полсотни отключаемых столбцов, при этом, любят. И тем больше количество столбцов в отчете, чем крупнее город, где расположен клиент...
Поскольку работать с небольшими городами не всегда выгодно, а времени на колдовство по всем правилам с построителем жаль (*), я однажды решил что-нибудь придумать, чтобы и клиенту было удобно, и самому потратить лишь несколько минут. Решение пришло быстро, при взгляде на вереницу этих столбцов, на фоне лени вбивать все их наименования вручную. Ведь что может быть нагляднее для клиента, чем те названия, которые он сам придумал? Лишь бы все они были уникальными.
Итак, копируем таблицу из исходного xls-файла в макет нашего отчета, разбиваем на горизонтальные секции. На этом работа над макетом завершена. Никаких параметров в строках не создаем. Создаем на форме закладку «Настройки» и выводим туда список с пометками "ДоступныеПоля", а в обработчике ПриОткрытии прописываем обход колонок отчета (**):
Макет=ПолучитьМакет("Макет");
К=1;
Пока Истина Цикл
Область=Макет.ПолучитьОбласть("R1C"+К+":R1C"+К);
Если ЗначениеЗаполнено(Область.ТекущаяОбласть.Текст) Тогда
ДоступныеПоля.Добавить(Область.ТекущаяОбласть.Текст);
Иначе
Прервать;
КонецЕсли;
К=К+1;
КонецЦикла;
(*) Под колдовством с построителем подразумевается сохранение во внешнем файле сгенерированного макета отчета, облагораживание его, и дальнейшее редактирование возможности отключать столбцы через набор вертикальных секции.
(**) Оговорюсь, что если в отчете более 999 колонок, то стоит использовать не +К, а Формат(К,”ЧГ=0”) ;)
Проверяем результат в рабочем режиме, любуясь красивым списком с названиями всех колонок отчета, которые придумал наш клиент.
Впрочем, у меня был xls-макет, содержащий названия колонок не строго в определенной строке.
Большой проблемы это не вызвало:
Макет=ПолучитьМакет("Макет");
К=1;
Пока Истина Цикл
Область1=Макет.ПолучитьОбласть("R4C"+К+":R4C"+К);
Область2=Макет.ПолучитьОбласть("R5C"+К+":R5C"+К);
Если ЗначениеЗаполнено(Область2.ТекущаяОбласть.Текст) Тогда
ДоступныеПоля.Добавить(Область2.ТекущаяОбласть.Текст);
ИначеЕсли ЗначениеЗаполнено(Область1.ТекущаяОбласть.Текст) Тогда
ДоступныеПоля.Добавить(Область1.ТекущаяОбласть.Текст);
Иначе
Прервать;
КонецЕсли;
К=К+1;
КонецЦикла;
Но пойдем далее… Мы отказались от прописывания имен параметров в макете строки. Чтобы теперь вывести в строки отчета необходимую информацию, достаточно написать запрос, с составом полей, соответствующим в точности столбцам нашей таблицы, а потом просто пробежаться по ним, проверяя, что выделил пользователь в списке колонок. Каждая строка нашего отчета легко может быть построена вот такой процедурой:
Процедура СформироватьСтрокуОтчета(ТабличныйДокумент, Макет, ИмяГоризонтальнойОбласти, СтрокаРезультатаЗапроса=Неопределено)
Область=Макет.ПолучитьОбласть(ИмяГоризонтальнойОбласти);
К=1;
Перв=Истина;
Для Каждого Эл Из ДоступныеПоля Цикл
Если Эл.Пометка Тогда
ТекОбласть=Область.ПолучитьОбласть("R1C"+К+":R"+Область.ВысотаТаблицы+"C"+К);
Если СтрокаРезультатаЗапроса<>Неопределено Тогда
ТекОбласть.ТекущаяОбласть.Текст=Строка(СтрокаРезультатаЗапроса[К-1]);
КонецЕсли;
Если Перв Тогда
Перв=Ложь;
ТабличныйДокумент.Вывести(ТекОбласть);
Иначе
ТабличныйДокумент.Присоединить(ТекОбласть);
КонецЕсли;
КонецЕсли;
К=К+1;
КонецЦикла;
КонецПроцедуры
Теперь наш отчет с произвольным составом колонок строится в два счета:
Процедура ДействияФормыкнСформировать(Кнопка)
Макет=ПолучитьМакет("Макет");
ЭлементыФормы.ТабДок.Очистить();
СформироватьСтрокуОтчета(ЭлементыФормы.ТабДок,Макет,"Шапка");
РезультатЗапроса=СформироватьЗапрос();
РезультатЗапроса.Выбрать();
Пока РезультатЗапроса.Следующий() Цикл
СформироватьСтрокуОтчета(ЭлементыФормы.ТабДок,Макет,"Строка", РезультатЗапроса);
КонецЦикла;
СформироватьСтрокуОтчета(ЭлементыФормы.ТабДок,Макет,"Подвал");
ЭлементыФормы.ТабДок.Показать();
КонецПроцедуры
Ни что не мешает использовать в процедуре СформироватьЗапрос построитель отчета, выводя поля отбора значений и порядок сортировки на форму в закладке настроек, куда мы уже вывели наш список с колонками.
В этом случае, имеет смысл поместить текст запроса в обработчик ПриОткрытии:
Построитель.Текст=”…”;
Построитель.ЗаполнитьНастройки();
Тогда функция СформироватьЗапрос будет иметь всего лишь пару строк:
Функция СформироватьЗапрос()
Построитель.Выполнить();
Возврат Построитель.Результат;
КонецФункции
Вот и все…
Конечно, при заполнении столбцов отчета параметрами, правильно было бы не тупо преобразовывать значения полей запроса в строку, а как-то обрабатывать по типу, но это уже тонкости.
Кстати, прилагаю шаблон отчета, который тут старался описать…