В этой статье мы по шагам рассмотрим два простейших примера реализации расшифровки в отчете на платформе 8.1.
В платформе 1С 8 появился механизм, называемый системой компоновки данных, или СКД. Этот механизм значительно облегчил процедуру создания отчетов. Однако он может вызывать затруднения в реализации каких-то специальных расшифровок.
Допустим, у нас есть справочник:
Вид расчета | Сумма |
Начисление 1 | 3 |
Начисление 2 | 4 |
Начисление 3 | 6 |
Начисление 1 | 9 |
Требуется получить отчет, в котором напротив каждого начисления будет итоговая сумма этого начисления. Т.е. результат отчета должен быть таким:
Вид расчета | Сумма |
Начисление 1 | 12 |
Начисление 2 | 4 |
Начисление 3 | 6 |
При этом должна быть возможность расшифровать любую из полученных сумм двойным щелчком мыши, т.е. получить состав сумм, из которых получился такой результат.
В справочнике два элемента «Начисление 1», с суммами 3 и 9. Таким образом, при расшифровке суммы этого начисления, должна получиться примерно такая табличка:
Вид расчета | Сумма |
Итого | 12 |
Начисление 1 | 3 |
Начисление 1 | 9 |
Подробно рассмотрим, как реализовать эту расшифровку в двух вариантах – когда отчет написан без использования СКД, и когда он написан с использованием СКД.
Вы можете скачать и развернуть у себя базу с примерами реализации этого отчета вот по этой ссылке:
(ссылка не работает из соображений безопасности, если база нужна, напишите комментарий к этой статье, вышлем базу)
Реализация расшифровки в отчете, созданном без использования СКД
Сначала создадим в конфигураторе новый отчет. Назовем его «ОтчетСРасшифровкойБезСКД». В этом отчете создадим новую форму и добавим в диалоге формы поле табличного документа:
Рис 1. Создание формы отчета.
В разделе «События» свойств поля табличного документа назначаем процедуру обработки расшифровки (см. на рисунке — выделено в рамку).
На вкладке модуля формы, во-первых, создаем процедуру-обработчик нажатия на кнопку «Сформировать», во вторых, пишем код процедуры обработки расшифровки:
// парочка вспомогательных функций: // Функция ТекстЗапроса() Возврат "ВЫБРАТЬ | Начисления.ВидРасчета, | Начисления.Сумма КАК Сумма |ИЗ | Справочник.Начисления КАК Начисления |ГДЕ | Начисления.ВидРасчета = &ВидРасчета |ИТОГИ | СУММА(Сумма) |ПО | ОБЩИЕ"; КонецФункции // ТекстЗапроса() Функция ПолучитьЗначениеПредыдущейОбласти(ИмяОбласти) Возврат ЭлементыФормы.ПолеТабличногоДокумента.ПолучитьОбласть("R" + Сред(ИмяОбласти,2,Найти(ИмяОбласти,"C")-2) + "C1").ТекущаяОбласть.Текст; КонецФункции // процедура-обработчик нажатия на кнопку "Сформировать" // Процедура КнопкаСформироватьНажатие(Кнопка) ПечатныйДокумент = Новый ТабличныйДокумент; Макет = ПолучитьМакет("НашМакет"); //выведем шапку ОбластьМакетаШапкаДокумента = Макет.ПолучитьОбласть("Шапка"); ПечатныйДокумент.Вывести(ОбластьМакетаШапкаДокумента); // выведем табличную часть ОбластьМакетаСтрокаДокумента = Макет.ПолучитьОбласть("СтрокаВР"); Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | Начисления.ВидРасчета, | СУММА(Начисления.Сумма) КАК Сумма |ИЗ | Справочник.Начисления КАК Начисления | |СГРУППИРОВАТЬ ПО | Начисления.ВидРасчета |ИТОГИ | СУММА(Сумма) |ПО | ОБЩИЕ"; Результат = Запрос.Выполнить(); Выборка = Результат.Выбрать(); Пока Выборка.Следующий() Цикл Если Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ДетальнаяЗапись Тогда ОбластьМакетаСтрокаДокумента.Параметры.Сумма = Выборка.Сумма; ОбластьМакетаСтрокаДокумента.Параметры.ВР = Выборка.ВидРасчета; ПечатныйДокумент.Вывести(ОбластьМакетаСтрокаДокумента); КонецЕсли; КонецЦикла; // выведем сформированный табличный документ в поле табличного документа формы: ЭлементыФормы.ПолеТабличногоДокумента.ВставитьОбласть(ПечатныйДокумент.Область()); // установим защиту, чтобы при двойном щелчке мыши срабатывала обработка расшифровки: ЭлементыФормы.ПолеТабличногоДокумента.Защита = Истина; КонецПроцедуры // процедура - обработчик расшифровки: // Процедура ПолеТабличногоДокументаОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка) ИмяТекОбл = Элемент.ТекущаяОбласть.Имя; ПозСимволаС = Найти(ИмяТекОбл,"C"); // временные переменные для определения текущей колонки Если Сред(ИмяТекОбл, ПозСимволаС + 1,СтрДлина(ИмяТекОбл) - ПозСимволаС) = "2" Тогда // значит, и правда текущая колонка - вторая, значит, расшифровываем колонку с суммой СтандартнаяОбработка = Ложь; // - чтобы не открылось стандартное окно расшифровки // Создадим, заполним и покажем список начислений этого ВР в новом табличном документе: ПечатныйДокумент = Новый ТабличныйДокумент; Макет = ПолучитьМакет("НашМакет"); //выведем шапку ОбластьМакетаШапкаДокумента = Макет.ПолучитьОбласть("Шапка"); ПечатныйДокумент.Вывести(ОбластьМакетаШапкаДокумента); // выведем табличную часть ОбластьМакетаСтрокаДокумента = Макет.ПолучитьОбласть("СтрокаВР"); Запрос = Новый Запрос; Запрос.Текст = ТекстЗапроса(); Запрос.УстановитьПараметр("ВидРасчета", ПолучитьЗначениеПредыдущейОбласти(Элемент.ТекущаяОбласть.Имя));// нужно получить значение соседней области, чтобы расшифровать эту сумму Результат = Запрос.Выполнить(); Выборка = Результат.Выбрать(); Пока Выборка.Следующий() Цикл Если Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ДетальнаяЗапись Тогда ОбластьМакетаСтрокаДокумента.Параметры.Сумма = Выборка.Сумма; ОбластьМакетаСтрокаДокумента.Параметры.ВР = Выборка.ВидРасчета; ПечатныйДокумент.Вывести(ОбластьМакетаСтрокаДокумента); Иначе ОбластьМакетаСтрокаДокумента.Параметры.Сумма = Выборка.Сумма; ОбластьМакетаСтрокаДокумента.Параметры.ВР = "Итого"; ПечатныйДокумент.Вывести(ОбластьМакетаСтрокаДокумента); КонецЕсли; КонецЦикла; // тут же покажем сформированную табличку рашифровки: ПечатныйДокумент.Показать(); //// или, как вариант, можно не таблицу выводить, а тут же вывести в форме, затерев предыдущую таблицу: //// выведем сформированный табличный документ в поле табличного документа формы: //ЭлементыФормы.ПолеТабличногоДокумента.ВставитьОбласть(ПечатныйДокумент.Область()); КонецЕсли; КонецПроцедуры
И еще нам потребуется макет для вывода отчета и его расшифровки (в нашем случае он получился универсальный, но обычно макет отчета и макет расшифровки различаются, и требуется создавать макеты отдельно):
Рис.2. Создание макета отчета и макета расшифровки отчета.
Для того, чтобы появлялся специальный курсор и была возможность расшифровать ячейку при наведении мышки на ячейку и двойном щелчке, должны быть соблюдены два условия: в свойствах этой ячейки нужно установить защиту и у нее должен быть определен параметр расшифровки (см. рисунок, поля обведены в рамочку).
Вот и все. Теперь можно открыть 1С:Предприятие и убедиться, что разработанный отчет покажет требуемую расшифровку:
Реализация отчета с использованием Системы Компоновки Данных (СКД)
В прилагаемой в качестве примера конфигурации отчет назван «ОтчетСРасшифровкойСКД».
Итак, последовательность разработки отчета следующая.
Создаем новый отчет. Назначаем ему новую схему компоновки данных (см. рисунок — отмечено цифрой 1). Создаем в ней новый набор данных — запрос (см. рис — отметка 2). Пишем текст запроса(см. рисунок — отметка 3):
Переходим на вкладку «Настройки» схемы компоновки и с помощью конструктора настроек определяем список выводимых полей:
На этом разработка действий, выполняемых по кнопке «Сформировать», закончена. Фактически использование Схемы Компоновки Данных позволяет избежать написания процедуры «Процедура КнопкаСформироватьНажатие(Кнопка)» (см. выше). Кроме того, для самого отчета можно не разрабатывать макет — он генерируется автоматически Схемой Компоновки Данных «на лету».
Однако нам понадобится макет для самой расшифровки. Поэтому создадим его в этом отчете по аналогии с отчетом без использования СКД (см Рис.2. Создание макета отчета и макета расшифровки отчета). Кроме того, для работы расшифровки нам понадобится форма отчета (которая в общем случае тоже гененрируется Схемой Компоновки Данных «на лету»), однако, если нам нужна расшифровка, использовать автоматически генерируемую форму не удастся из-за того, что в ней не будет назначено Событие «ОбработкаРасшифровки», а нам оно нужно. Поэтому создаем форму отчета — в точности такую же, как если бы не использовали СКД — см. Рис 1. Создание формы отчета — в свойствах поля табличного документа в разделе «События» для события «ОбработкаРасшифровки» назначаем процедуру «ПолеТабличногоДокументаОбработкаРасшифровки».
Самое интересное — это как получить и проверить имя расшифровываемого поля. Чтобы в процедуре «ПолеТабличногоДокументаОбработкаРасшифровки» определить, какое поле пытается расшифровать пользователь, нам нужно получить его наименование (специальная обработка расшифровки у нас должна быть назначена для поля «Сумма» — именно так его имя определено в СКД конструктором). Имя этого поля можно извлечь из предопределенного параметра «Расшифровка» процедуры ПолеТабличногоДокументаОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка). К сожалению, во встроенном в конфигуратор синтакс-помощнике достаточно трудно разобраться, как это сделать. Поэтому поясним подробнее.
Для нашего примера проверка имени этого поля выполняется вот в таком операторе сравнения:
Если ДанныеРасшифровки.Элементы.Получить(Расшифровка).ПолучитьПоля().Найти("Сумма") <> Неопределено Тогда
У любой формы любого отчета среди свойств есть свойство «ДанныеРасшифровки». Посмотрим, что об этом говорится в синтакс-помощнике конфигуратора. Расширение формы отчета:
**********************************************************
Расширение формы отчета (Report form extension)Свойства:ВосстанавливатьЗначенияПриОткрытии (RestoreValuesOnOpen)
ДанныеРасшифровки (DetailsData)
РезультатОтчета (ReportResult)События:ПередСохранениемЗначений (BeforeSaveValues)
ПослеВосстановленияЗначений (AfterRestoreValues)Описание:Дополнительные свойства и события объекта «Форма отчета».
Недоступен на сервере 1С:Предприятие. Не используется в модуле внешнего соединения.**********************************************************
Его свойство «ДанныеРасшифровки»:
**********************************************************
Расширение формы отчета (Report form extension)ДанныеРасшифровки (DetailsData)Использование:Чтение и запись.
Описание:Тип: ДанныеРасшифровкиКомпоновкиДанных. Содержит данные расшифровки последнего выполненного отчета.
Недоступно на сервере 1С:Предприятие. Не используется в модуле внешнего соединения.**********************************************************
Посмотрим, что это за тип такой, ДанныеРасшифровкиКомпоновкиДанных:
**********************************************************
ДанныеРасшифровкиКомпоновкиДанных (DataCompositionDetailsData)Свойства:Настройки (Settings)
Элементы (Items)Конструкторы:По умолчанию
Описание:Объект, содержащий информацию о расшифровке.
XML-сериализация. Поддержка отображения в XDTO; пространство имен: {http://v8.1c.ru/8.1/data-composition-system/details}. Имя типа XDTO: DetailsInformation.См. также:ОтчетОбъект, свойство
Расширение формы отчета, свойство ДанныеРасшифровки
ПроцессорКомпоновкиДанных, метод Инициализировать
КомпоновщикМакетаКомпоновкиДанных, метод Выполнить
ОбработкаРасшифровкиКомпоновкиДанных, конструктор На основании данных расшифровки и источника доступных настроек**********************************************************
Т.е. из описания видим, что у этого типа есть свойство «Элементы». Посмотрим описание этого свойства:
**********************************************************
ДанныеРасшифровкиКомпоновкиДанных (DataCompositionDetailsData)
Элементы (Items)Использование:Только чтение.
Описание:Тип: ЭлементыРасшифровкиКомпоновкиДанных. Содержит элементы расшифровки.
XML-сериализация.**********************************************************
Посмотрим описание типа «ЭлементыРасшифровкиКомпоновкиДанных», чтобы выяснить, какие методы к нему применимы:
**********************************************************
ЭлементыРасшифровкиКомпоновкиДанных (DataCompositionDetailsItems)Элементы коллекции:ЭлементРасшифровкиКомпоновкиДанныхПоля, ЭлементРасшифровкиКомпоновкиДанныхГруппировка
Для объекта доступен обход коллекции посредством оператора Для каждого … Из … Цикл. При обходе выбираются элементы расшифровки.
Возможно обращение к элементу посредством оператора […]. В качестве аргумента передается индекс (нумерация с 0), идентификатор расшифровки.Методы:Добавить (Add)
Индекс (IndexOf)
Количество (Count)
Получить (Get)Описание:Коллекция элементов расшифровки.
См. также:ДанныеРасшифровкиКомпоновкиДанных, свойство Элементы
**********************************************************
Как видим из описания, к элементу расшифровки компоновки данных применим метод «Получить». Посмотрим его описание в синтакс-помощнике Конфигуратора::
**********************************************************
ЭлементыРасшифровкиКомпоновкиДанных (DataCompositionDetailsItems)Получить (Get)Синтаксис:Получить(<Идентификатор>) (*см примечание)
Параметры:<Идентификатор> (обязательный)Тип: ИдентификаторРасшифровкиКомпоновкиДанных. Идентификатор элемента.
Возвращаемое значение:Тип: ЭлементРасшифровкиКомпоновкиДанныхПоля, ЭлементРасшифровкиКомпоновкиДанныхГруппировка.
Описание:Получает элемент коллекции по индексу. Работает аналогично оператору [].
**********************************************************
*Примечание. Текст, выделенный серым цветом, отсутствует в синтакс-помощнике конфигуратора, что является ошибкой, и вводит в заблуждение неопытных программистов. Однако некоторым пытливым умам удалось выявить эту ошибку, поэтому приводим тут исправленный вариант. Теперь посмотрим, что это за тип — ЭлементРасшифровкиКомпоновкиДанныхПоля:
**********************************************************
ЭлементРасшифровкиКомпоновкиДанныхПоля (DataCompositionFieldDetailsItem)Свойства:Методы:ПолучитьПоля (GetFields)
ПолучитьРодителей (GetParents)Описание:Элемент расшифровки, содержащий значения полей.
Поддержка отображения в XDTO; пространство имен: {http://v8.1c.ru/8.1/data-composition-system/details}. Имя типа XDTO: DetailsItemFields.**********************************************************
Итак, мы добрались до идентификатора «Идентификатор (ID)» и метода «ПолучитьПоля». Тип значения параметра «Расшифровка» в случае расшифровки поля, заполняемого с помощью СКД, — «ИдентификаторРасшифровкиКомпоновкиДанных». Посмотрим описание этого типа в синтакс-помощнике Конфигуратора:
**********************************************************
ИдентификаторРасшифровкиКомпоновкиДанных (DataCompositionDetailsID)Описание:Представляет собой специальный объект для идентификации объекта расшифровки.
Поддержка отображения в XDTO; пространство имен: {http://v8.1c.ru/8.1/data-composition-system/details}. Имя типа XDTO: DetailsID.См. также:ЭлементРасшифровкиКомпоновкиДанныхПоля, свойство Идентификатор
ЭлементРасшифровкиКомпоновкиДанныхГруппировка, свойство Идентификатор
ОбработкаРасшифровкиКомпоновкиДанных, метод Выполнить
ОбработкаРасшифровкиКомпоновкиДанных, метод ОткрытьЗначение
ОбработкаРасшифровкиКомпоновкиДанных, метод Отфильтровать
ОбработкаРасшифровкиКомпоновкиДанных, метод Упорядочить
ОбработкаРасшифровкиКомпоновкиДанных, метод Сгруппировать
ОбработкаРасшифровкиКомпоновкиДанных, метод Расшифровать
ОбработкаРасшифровкиКомпоновкиДанных, метод ПрименитьНастройки**********************************************************
ЭлементРасшифровкиКомпоновкиДанныхПоля (DataCompositionFieldDetailsItem)
Идентификатор (ID)
Использование:
Только чтение.
Описание:
Тип: ИдентификаторРасшифровкиКомпоновкиДанных. Идентификатор элемента.**********************************************************
Пояснение к методу «ПолучитьПоля»:
**********************************************************
ЭлементРасшифровкиКомпоновкиДанныхПоля (DataCompositionFieldDetailsItem)ПолучитьПоля (GetFields)Синтаксис:ПолучитьПоля()
Возвращаемое значение:Тип: ЗначенияПолейРасшифровкиКомпоновкиДанных.
Описание:Получает значения полей, установленных в элементе расшифровки.
**********************************************************
Посмотрим описание типа «ЗначенияПолейРасшифровкиКомпоновкиДанных»:
**********************************************************
ЗначенияПолейРасшифровкиКомпоновкиДанных (DataCompositionDetailsFieldValues)Элементы коллекции:ЗначениеПоляРасшифровкиКомпоновкиДанных
Для объекта доступен обход коллекции посредством оператора Для каждого … Из … Цикл. При обходе выбираются значения полей.
Возможно обращение к значению посредством оператора […]. В качестве аргумента передается имя, индекс (нумерация с 0).Методы:Вставить (Insert)
Добавить (Add)
Индекс (IndexOf)
Количество (Count)
Найти (Find)
Очистить (Clear)
Получить (Get)
Сдвинуть (Move)
Удалить (Delete)Описание:Коллекция значений полей.
См. также:ЭлементРасшифровкиКомпоновкиДанныхПоля, метод ПолучитьПоля
ЭлементыРасшифровкиКомпоновкиДанных, метод Добавить
**********************************************************
Как видим, к этому типу применим метод «Найти»:
**********************************************************
ЗначенияПолейРасшифровкиКомпоновкиДанных (DataCompositionDetailsFieldValues)Найти (Find)Синтаксис:Найти(<Имя>)
Параметры:<Имя> (необязательный)Тип: Строка. Имя искомого элемента.
Возвращаемое значение:Тип: ЗначениеПоляРасшифровкиКомпоновкиДанных; Неопределено. Если элемент не найден, будет возвращено значение Неопределено.
Описание:Осуществляет поиск элемента коллекции по имени.
**********************************************************
ЗначениеПоляРасшифровкиКомпоновкиДанных:
**********************************************************
ЗначениеПоляРасшифровкиКомпоновкиДанных (DataCompositionDetailsFieldValue)Свойства:Значение (Value)
Иерархия (Hierarchy)
Поле (Field)Описание:Содержит значения полей элемента расшифровки.
Поддержка отображения в XDTO; пространство имен: {http://v8.1c.ru/8.1/data-composition-system/details}. Имя типа XDTO: FieldValue.См. также:ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Добавить
ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Вставить
ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Получить
ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Найти
ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Удалить
ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Индекс
ЗначенияПолейРасшифровкиКомпоновкиДанных, метод Сдвинуть
**********************************************************
Самое сложное позади — таким образом мы получили возможность проверить значение имени расшифровываемого поля и теперь можем обработать его соответствующим образом. Все остальное в процедуре обработки расшифровки будет аналогично процедуре обработки расшифровки, написанной для отчета, реализованного без использования СКД. Приведем полностью модуль формы отчета:
// парочка вспомогательных функций: // Функция ТекстЗапроса() Возврат "ВЫБРАТЬ | Начисления.ВидРасчета, | Начисления.Сумма КАК Сумма |ИЗ | Справочник.Начисления КАК Начисления |ГДЕ | Начисления.ВидРасчета = &ВидРасчета |ИТОГИ | СУММА(Сумма) |ПО | ОБЩИЕ"; КонецФункции // ТекстЗапроса() Функция ПолучитьЗначениеПредыдущейОбласти(ИмяОбласти) Возврат ЭлементыФормы.ПолеТабличногоДокумента.ПолучитьОбласть("R" + Сред(ИмяОбласти,2,Найти(ИмяОбласти,"C")-2) + "C1").ТекущаяОбласть.Текст; КонецФункции // процедура - обработчик расшифровки: // Процедура ПолеТабличногоДокументаОбработкаРасшифровки(Элемент, Расшифровка, СтандартнаяОбработка) Если ДанныеРасшифровки.Элементы.Получить(Расшифровка).ПолучитьПоля().Найти("Сумма") <> Неопределено Тогда // значит, действительно пытаемся расшифровать сумму СтандартнаяОбработка = Ложь; // - чтобы не открылось стандартное окно расшифровки // Создадим, заполним и покажем список начислений этого ВР в новом табличном документе: ПечатныйДокумент = Новый ТабличныйДокумент; Макет = ПолучитьМакет("НашМакет"); //выведем шапку ОбластьМакетаШапкаДокумента = Макет.ПолучитьОбласть("Шапка"); ПечатныйДокумент.Вывести(ОбластьМакетаШапкаДокумента); // выведем табличную часть ОбластьМакетаСтрокаДокумента = Макет.ПолучитьОбласть("СтрокаВР"); Запрос = Новый Запрос; Запрос.Текст = ТекстЗапроса(); Запрос.УстановитьПараметр("ВидРасчета", ПолучитьЗначениеПредыдущейОбласти(Элемент.ТекущаяОбласть.Имя));// нужно получить значение соседней области, чтобы расшифровать эту сумму Результат = Запрос.Выполнить(); Выборка = Результат.Выбрать(); Пока Выборка.Следующий() Цикл Если Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ДетальнаяЗапись Тогда ОбластьМакетаСтрокаДокумента.Параметры.Сумма = Выборка.Сумма; ОбластьМакетаСтрокаДокумента.Параметры.ВР = Выборка.ВидРасчета; ПечатныйДокумент.Вывести(ОбластьМакетаСтрокаДокумента); Иначе ОбластьМакетаСтрокаДокумента.Параметры.Сумма = Выборка.Сумма; ОбластьМакетаСтрокаДокумента.Параметры.ВР = "Итого"; ПечатныйДокумент.Вывести(ОбластьМакетаСтрокаДокумента); КонецЕсли; КонецЦикла; // тут же покажем сформированную табличку рашифровки: ПечатныйДокумент.Показать(); //// или, как вариант, можно не таблицу выводить, а тут же вывести в форме, затерев предыдущую таблицу: //// выведем сформированный табличный документ в поле табличного документа формы: //ЭлементыФормы.ПолеТабличногоДокумента.ВставитьОбласть(ПечатныйДокумент.Область()); КонецЕсли; КонецПроцедуры
Огромное спасибо за статью.
Если нужно, скажем, экспортировать отчет в файл — нужно заменить
ЭлементыФормы.ПолеТабличногоДокумента.Защита = Истина;
на
ЭлементыФормы.ПолеТабличногоДокумента.ТолькоПросмотр = Истина;
весьма полезный материал.
Хорошая статья помогла.
Спасибо за помощь.→ Полезный материал.