Введение
Всем привет! В этой статье я хочу показать вам простой, но очень действенный "лайфхак" (позвольте назвать мне этот метод именно так), который позволит вам без особых сложностей собирать практически любые отчеты в системе компоновке данных (СКД).
Раньше данный метод я применял достаточно часто, особенно в периоды острой нехватки времени на выполнение задачи.
На своем жизненном пути я сталкивался с "программистами 1с", которые совершенно не владели системой компоновки данных и считали, что в основе СКД прежде всего лежит какой-то "лютый" запрос, за который и браться то бессмысленно. Некоторые "программисты", и это не редкость, считают, язык запросов 1с и СКД - это одно и тоже...
Собственно, как и работодатели - всегда указывают свои требования на более-менее приемлемые вакансии "требуется знание и умение пользоваться СКД" до конца, как мне кажется, имея неверное представление об СКД только как о "системе запросов к данным и отчетов по ним".
Более того, я очень аккуратно отмечу, что владение СКД все-таки - это прежде всего навык пользователя, а вот задача программиста - представить данные (любыми способами) для этой компоновки.
Многие опытные программисты уже поняли к чему я клоню, и они будут правы - да, я предлагаю "программно" разобрать механизм работы "набора данных" для системы СКД, а именно - создание набора данных (через передачу объекта) и его компоновку так, как нам нужно.
Кто не хочет читать - может скачать вот этот мой примерчик, где я и реализовал эту "сборку" набора данных.
Итак, начнем:
Подготовка
Задача - построить отчет в СКД, который бы отражал прибыль подразделения от продаж в разрезах покупатель/контрагент/номенклатура. Достаточно простой отчет. Для данного примера сойдет.
Основное, что нам нужно - это определить и подготовить "таблицу", в которой будут все необходимые данные для выполнения условий задачи.
Создаем новый внешний отчет. Нарисуем форму отчета и "пробежимся" по всем настройкам, которые нужно "нащелкать".
Здесь у нас основные реквизиты - Подразделение, Дата начала, Дата окончания. Так же есть "Результат" - с типом "Табличный документ".
Рис.1.Основная форма отчета.
Реквизиты и компоновка объекта "отчет" будут такими:
Рис.2. Настройка формы отчета. Определение реквизитов. Компоновка на форме.
На что обратим внимание в свойствах формы:
Рис.3. Результат отчета, данные расшифровки и настройки.
Пожалуй, это основные моменты самого объекта "отчет". Теперь, переходим к программной части отчета.
Для этого создадим внутри модуля отчета процедуру ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка).
В общем виде содержимое данной процедуры (ее можно скопировать) должно выглядеть вот так:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ОсновнаяТаблицаЗапроса = ПолучимТаблицуДанных();
СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
ВнешнийНаборДанных = Новый Структура("ДанныеОтчета", ОсновнаяТаблицаЗапроса);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных, ДанныеРасшифровки);
ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
Обратим внимание, на передачу ВнешнегоНабораДанных в ПроцессорКомпоновкиДанных. Мы передаем таблицу "ОсновнаяТаблицаЗапроса", данные которой получены функцией ПолучимТаблицуДанных().
Опишем в модуле отчета основную функцию ПолучимТаблицуДанных(), которая определит в дальнейшем нашу таблицу внешнего источника, выглядит она вот так:
&НаСервере
Функция ПолучимТаблицуДанных()
ТаблицаРезультат = Новый ТаблицаЗначений;
ТаблицаРезультат.Колонки.Добавить("Дата");
ТаблицаРезультат.Колонки.Добавить("Номер");
ТаблицаРезультат.Колонки.Добавить("Реализация");
ТаблицаРезультат.Колонки.Добавить("Организация");
ТаблицаРезультат.Колонки.Добавить("Подразделение");
ТаблицаРезультат.Колонки.Добавить("Контрагент");
ТаблицаРезультат.Колонки.Добавить("Номенклатура");
ТаблицаРезультат.Колонки.Добавить("ЕдиницаИзмерения");
ТаблицаРезультат.Колонки.Добавить("Количество");
ТаблицаРезультат.Колонки.Добавить("Сумма");
ТаблицаРезультат.Колонки.Добавить("СтавкаНДС");
ТаблицаРезультат.Колонки.Добавить("СуммаБезНДС");
ТаблицаРезультат.Колонки.Добавить("СебестоимостьБезНДС");
ТаблицаРезультат.Колонки.Добавить("ТипНоменклатуры");
ТаблицаРезультат.Колонки.Добавить("Цена");
ТаблицаРезультат.Колонки.Добавить("ГруппаНоменклатуры");
ТаблицаРезультат.Колонки.Добавить("РаспределенияЗатрат");
ТаблицаРезультат.Колонки.Добавить("Процент");
ТаблицаРезультат.Колонки.Добавить("Склад");
ТаблицаРезультат.Колонки.Добавить("НадбавкаПоГруппе");
ТаблицаРезультат.Колонки.Добавить("СебестоимостьСНадбавкой");
ТаблицаРезультат.Колонки.Добавить("ВаловаяПрибыль");
ТаблицаРезультат.Колонки.Добавить("Премия");
// ==== далее наполним эту таблицу данными из запроса(ов) ====
// ==== Пишем запрос, который соберет (по "документам") все необходимые "реализации", "номенклатуры" и прочих реквизитов
ПоискДанных = Новый Запрос("ВЫБРАТЬ
| РасходнаяНакладная.Ссылка КАК Реализация,
| РасходнаяНакладная.Дата КАК Дата,
| РасходнаяНакладная.Организация КАК Организация,
| РасходнаяНакладная.Подразделение КАК Подразделение,
| РасходнаяНакладная.Контрагент КАК Контрагент,
| РасходнаяНакладнаяЗапасы.Номенклатура КАК Номенклатура,
| РасходнаяНакладнаяЗапасы.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
| РасходнаяНакладнаяЗапасы.Количество КАК Количество,
| РасходнаяНакладнаяЗапасы.Сумма КАК Сумма,
| РасходнаяНакладнаяЗапасы.СтавкаНДС КАК СтавкаНДС,
| 0 КАК СуммаБезНДС,
| 0 КАК СебестоимостьБезНДС,
| РасходнаяНакладнаяЗапасы.Номенклатура.ТипНоменклатуры КАК ТипНоменклатуры,
| РасходнаяНакладнаяЗапасы.Цена КАК Цена,
| РасходнаяНакладная.Номер КАК Номер,
| РасходнаяНакладнаяЗапасы.Номенклатура.Родитель КАК ГруппаНоменклатуры,
| РасходнаяНакладнаяЗапасы.Номенклатура.Родитель.КатегорияНоменклатурыДляРаспределенияЗатрат КАК РаспределенияЗатрат,
| ВЫБОР
| КОГДА РасходнаяНакладнаяЗапасы.Номенклатура.Родитель.КатегорияНоменклатурыДляРаспределенияЗатрат = ЗНАЧЕНИЕ(Справочник.КатегорииНоменклатурыДляРаспределенияЗатрат.ПустаяСсылка)
| ТОГДА 0
| ИНАЧЕ РасходнаяНакладнаяЗапасы.Номенклатура.Родитель.КатегорияНоменклатурыДляРаспределенияЗатрат.Процент
| КОНЕЦ КАК Процент,
| РасходнаяНакладная.СтруктурнаяЕдиница КАК Склад
|ИЗ
| Документ.РасходнаяНакладная КАК РасходнаяНакладная
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РасходнаяНакладная.Запасы КАК РасходнаяНакладнаяЗапасы
| ПО РасходнаяНакладная.Ссылка = РасходнаяНакладнаяЗапасы.Ссылка
|ГДЕ
| РасходнаяНакладная.Дата МЕЖДУ &Дата1 И &Дата2
| И РасходнаяНакладная.Проведен = ИСТИНА
| И РасходнаяНакладная.Подразделение = &Подразделение
| И РасходнаяНакладнаяЗапасы.Номенклатура.ТипНоменклатуры = &ТипНоменклатуры
| И НЕ РасходнаяНакладная.Комментарий ПОДОБНО &Комментарий
|
|УПОРЯДОЧИТЬ ПО
| Контрагент,
| Дата");
// ==== Определение процентов и категорий распределения затрат
ОпределениеПроцентовИКатегорий();
// ==== Расчет ресурсов "Надбавки по группе", "Себестоимости...", "Валовой прибыли", "Премии"
//ОпределениеНадбавокИВаловойПрибыли1(); // метод 1
//ОпределениеНадбавокИВаловойПрибыли2(); // метод 2
ОпределениеНадбавокИВаловойПрибыли3(); // метод 3
// ==== Таблица "собрана", возвращаем результат:
Возврат ТаблицаРезультат;
КонецФункции
Первоначальная "идея" создания этой функции - собрать данные (любым правильным или неправильным способом) в описанную выше ТаблицаРезультат.
Для простоты дела необязательно писать огромный запрос, который соберет все и сразу (хотя это самый правильный подход).
Соберите и заполните строки "по-кусочкам", что значительно упростит подход. В этом и заключается "лайфхак", когда данные собираются частями (разными функциями, которые, кстати, можно менять в дальнейшем). Да, это медленнее.
В вышеуказанной функции, я провожу расчет Надбавок и Прибыли по функции "метод 3", остальные закомментированы, например "как устаревшие", но с сохранением алгоритма. Алгоритмы этих функций я не привожу в данной статье.
Так, будем, считать, что я собрал все необходимые данные в эту таблицу. Переходим к реализации в СКД.
Реализация в СКД
Теперь, "нащелкаем" компоновку СКД.
Создаем новый "НаборДанных1" и в имени объекта указываем "ДанныеОтчета" (см.рис.4). Затем, определяем все необходимые поля из таблицы "ДанныеОтчета". Прописываем типы, форматы, доступные значения и параметры редактирования.
Рис.4. Выбор объекта для набора данных. Определение полей отчета.
Затем, идем в закладку "Ресурсы", где определяем "числовые значения" отчета. Так же, "накликаем мышкой" (рис.1).
Рис.5. Ресурсы отчета.
Переходим на закладку "Настройки" и проводим уже окончательную настройку отчета - то, как он будет скомпонован (см. Рис 6). В "Выбранные поля" перемещаем реквизиты и ресурсы отчета. Сам отчет компонуем по реквизитам.
Рис.6. Итоговая компоновка отчета.
Так же в "других настройках" можно выбрать цветовое оформление отчета.
В итоге, все сохраняем и запускаем отчет в 1с предприятие. Смотрим, что получилось (см. рис.7). Получился красивый отчет по набору данных, собранный в СКД.
Рис.7. Готовый отчет СКД, созданный на основе собранного набора данных.
Заключение
Так, наконец, мы собрали отчет в СКД. Рабочий, с понятными настройками. Давайте отметим, какие основные плюсы и минусы данного метода:
Начнем с плюсов:
1.Небольшое время "сборки" отчета средней сложности.
2.Можно собрать "несобираемые" вещи в СКД, так же не заморачиваясь на сложных соединениях таблиц (например, подогнать все под единую таблицу и засунуть в компоновку).
3.Простая "расширяемость" отчета (легко добавить новые колонки).
4.Легко поменять алгоритмы расчета колонок (см выше).
Минусы, пожалуй, такие:
1.Невозможно расшифровать как собирается "число" в данном отчете. Никак.
2.Скорость работы на большом объеме информации будет в разы ниже, чем на отчете созданном единым запросом сразу в СКД.
Я описал лишь "базовый" подход к работе с наборами данных в системе компоновки данных.
Отмечу, что я не ставил задачу расписывать как работать с закладками "связи наборов данных", "вычисляемые поля" и т.д. Это, кончено, все возможно. Если захотите, самостоятельно вы сможете, например, соединить результаты запроса и таблицу набора данных - это тоже будет работать. Все очень удобно и главное - понятно.
Думаю, что если вы работаете с вменяемым объемом информации, на проверенных алгоритмах расчета получаемых данных, то данный способ вам пригодиться.
Всем спасибо, что дочитали данную статью до конца, надеюсь, что она оказалась вам полезна. Всем привет!
Все операции я делал на платформе 8.3.13.1865 и УНФ 1.6.
Предыдущие материалы
Так же, прошу посмотреть мои предыдущие статьи:
Работа с механизмом отладки 1С. Базовые настройки