#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// получим объект отчет
ВнешнийОтчет = РеквизитФормыВЗначение("Отчет"); // Если обработка, то ("Объект");
// если отчет открыт из справочника проверим заполненность ссылки
Параметры.Свойство("ДополнительнаяОбработкаСсылка", ДополнительнаяОбработкаСсылка);
// Идентификатор команды. Который укзан в СведенияОВнешнейОбработке, в данном случае для команды открытия формы
// но можно и руками указать, это же наш отчет :)
// Нужно, если разное поведение в зависимости от команды
Параметры.Свойство("ИдентификаторКоманды", ИдентификаторКоманды);
// если пустая значит открыти из вне, нужно поискать ее в справочнике
Если ДополнительнаяОбработкаСсылка.Пустая() Тогда
ДополнительнаяОбработкаСсылка = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(ВнешнийОтчет.Метаданные().Синоним);
ИдентификаторКоманды = "СформироватьОтчет";
КонецЕсли;
// если забыли добавить в справочник выполнить в фоне не получится :-(
Элементы.СформироватьОтчетВФоне.Доступность = НЕ ДополнительнаяОбработкаСсылка.Пустая();
// Либо используем авто создаваемое хранилище и удаляем его, что бы не было переполнения памяти
// либо используем один раз созданное хранилище из реквизита
//АдресРезультата=ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор); // Одно хранилище на все время жизни формы
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиКомандФормы
// Формирование отчета в фоне программно
&НаКлиенте
Процедура СформироватьОтчетВФоне(Команда)
ВыполнитьВФоне();
КонецПроцедуры
// Сформировать отчет в фоне через параметр компоновщика
//
&НаКлиенте
Процедура СформироватьОтчетРежимКомпоновкиВФоне(Команда)
ЭтаФорма.СкомпоноватьРезультат(РежимКомпоновкиРезультата.Фоновый);
КонецПроцедуры
// Процедура - Сформировать отчет программно не в фоне
//
&НаКлиенте
Процедура СформироватьОтчетПрограммно(Команда)
СформироватьОтчетПрограммноНаСервере();
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Выполнить отчет в фоне.
// Запускает НачатьВыполнениеВФоне и вешает на нее обработчик ожидания ФормированиеВФонеЗавершено
// Разделение на функции запуска и ожидания нужно, т.к. выполнение в фоне идет на сервере, а ожидание на клиенте
// Функция окончания ожидания тоже только на клиенте
//
&НаКлиенте
Процедура ВыполнитьВФоне()
// Результат отчета формируется
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "ФОРМИРОВАНИЕОТЧЕТА");
ОчиститьСообщения();
Результат = Новый ТабличныйДокумент; // для чистоты результата
// Запускаем длительную операцию
// Получаем структуру со статусом
ДлительнаяОперация = НачатьВыполнениеВФоне();
// Подключаем обработчик ожидания
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ОповещениеОЗавершении = Новый ОписаниеОповещения("ФормированиеВФонеЗавершено", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
// Если закончится до вызова, то обработчик ожидания все-равно выполнится
// По окончании вызовется ФормированиеВФонеЗавершено
КонецПроцедуры
// Стартует выполнение в фоне
// Ее завершения ожидает запустившая ее ВыполнитьВФоне
//
// Возвращаемое значение:
// Структура - параметры выполнения задания (ДлительнаяОперация):
// * Статус - Строка - "Выполняется", если задание еще не завершилось;
// "Выполнено", если задание было успешно выполнено;
// "Ошибка", если задание завершено с ошибкой;
// "Отменено", если задание отменено пользователем или администратором.
// * ИдентификаторЗадания - УникальныйИдентификатор - если Статус = "Выполняется", то содержит
// идентификатор запущенного фонового задания.
// * АдресРезультата - Строка - адрес временного хранилища, в которое будет
// помещен (или уже помещен) результат работы процедуры.
// * АдресДополнительногоРезультата - Строка - если установлен параметр ДополнительныйРезультат,
// содержит адрес дополнительного временного хранилища,
// в которое будет помещен (или уже помещен) результат работы процедуры.
// * КраткоеПредставлениеОшибки - Строка - краткая информация об исключении, если Статус = "Ошибка".
// * ПодробноеПредставлениеОшибки - Строка - подробная информация об исключении, если Статус = "Ошибка".
//
&НаСервере
Функция НачатьВыполнениеВФоне()
// Имя процедуры, которая будет выполнятся в фоне
// Она может быть в общем модуле, модуле менеджера
// Процедуру формы так запустить нельзя
// Указываем процедуру общего модуля БСП. Она стартанет команду нашего отчета, зарегестрированную в СведенияОВнешнейОбработке
// Для этого в параметрах выполнения нужно указать ссылку на наш отчет в справочнике и идентификатор команды
ИмяПроцедуры = "ДополнительныеОтчетыИОбработки.ВыполнитьКоманду"; // Что будет выполнятся в фоне
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru='Выполнение отчета...'");
// Либо используем авто создаваемое хранилище и удаляем его, что бы не было переполнения памяти
// либо используем один раз созданное хранилище из реквизита
//ПараметрыВыполнения.АдресРезультата = АдресРезультата; // Используем хранилище формы, если не указать будет создано автоматом
// Указываем процедуре общего модуля ДополнительныеОтчетыИОбработки.ВыполнитьКоманду, что нужно стартануть
ПараметрыПроцедуры = Новый Структура; // Создаем структуру, заполняем нужными нам параметрами
ПараметрыПроцедуры.Вставить("ДополнительнаяОбработкаСсылка", ДополнительнаяОбработкаСсылка); // Какой доп отчет
// ИдентификаторКоманды - берется из идентификатора команды из СведенияОВнешнейОбработке
// Команда.Идентификатор = "СформироватьОтчет";
// При этом выполняется процедура, в зависимости от типа команды (клиентская или серверная)
// Например: Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
// Подразумеваем, что для типа открытие формы будет вызвана ВыполнитьКоманду на сервере и ей передан идентификатор "СформироватьОтчет"
ПараметрыПроцедуры.Вставить("ИдентификаторКоманды", ИдентификаторКоманды); // Какая команда доп отчета.
ПараметрыПроцедуры.Вставить("ПараметрыОтчета", ПолучитьПараметрыОтчета()); // Параметры формирования отчета, для команды
// Адрес хранилища указывать не обязательно. Можно указать в ПараметрыВыполнения.АдресРезультата, но процедура создаст его сама
// с привязкой к форме. Вопрос только в переполнении памяти от постоянного создания?
// Результат работы процедуры отчета в ВыполнитьКоманду нужно помещать в ПараметрыПроцедуры.РезультатВыполнения
// эта структура будет так же создана, нужно только наполнить ее нужными нам полями в ВыполнитьКоманду.
// И эту структуру процедуры БСП поместят в хранилище по адресу ДлительнаяОперация.АдресРезультата
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "ФОРМИРОВАНИЕОТЧЕТА");
ДлительнаяОперация = ДлительныеОперации.ВыполнитьВФоне(ИмяПроцедуры, ПараметрыПроцедуры, ПараметрыВыполнения);
Возврат ДлительнаяОперация;
КонецФункции
// Формирование в фоне завершено. Может быть только на клиенте
//
// В Хранилище по адресу РезультатФоновогоЗадания.АдресРезультата находится структура заполняемая командой
// внешнего отчета в ПараметрыВыполненияКоманды.РезультатВыполнения
//
// Параметры:
// РезультатФоновогоЗадания - Структура - Результат выполнения длительной операции
// * Статус - Строка - "Выполняется", если задание еще не завершилось;
// "Выполнено", если задание было успешно выполнено;
// "Ошибка", если задание завершено с ошибкой;
// "Отменено", если задание отменено пользователем или администратором.
// * ИдентификаторЗадания - УникальныйИдентификатор - если Статус = "Выполняется", то содержит
// идентификатор запущенного фонового задания.
// * АдресРезультата - Строка - адрес временного хранилища, в которое будет
// помещен (или уже помещен) результат работы процедуры.
// * АдресДополнительногоРезультата - Строка - если установлен параметр ДополнительныйРезультат,
// содержит адрес дополнительного временного хранилища,
// в которое будет помещен (или уже помещен) результат работы процедуры.
// * КраткоеПредставлениеОшибки - Строка - краткая информация об исключении, если Статус = "Ошибка".
// * ПодробноеПредставлениеОшибки - Строка - подробная информация об исключении, если Статус = "Ошибка".
// ДополнительныеПараметры - Струткура - Доп параметры, преданные из вызывающей ожидание процедуры.
//
&НаКлиенте
Процедура ФормированиеВФонеЗавершено(РезультатФоновогоЗадания, ДополнительныеПараметры) Экспорт
Если РезультатФоновогоЗадания.Статус="Выполнено" Тогда
// Отображаем отчет, т.к. ПолучитьИзВременногоХранилища работает только на сервере, вызываем серверную процедуру
ОтобразитьДанныеФоновогоОтчета(РезультатФоновогоЗадания.АдресРезультата);
КонецЕсли;
КонецПроцедуры
// Отображает отчет сформированный в фоне. Читая его из временного хранилища
// Параметры:
// АдресРезультата - Строка - Адрес временного хранилища с результатом выполнения фоновой команды отчета
// * Результат - ТабличныйДокумент - Отчет
// * ДанныеРасшифровки - ДанныеРасшифровкиКомпоновкиДанных - данные расшифровки
//
&НаСервере
Процедура ОтобразитьДанныеФоновогоОтчета(АдресРезультата)
РезультатВыполнения = ПолучитьИзВременногоХранилища(АдресРезультата);
// Данные расшифровки поместить в хранилище, что бы работала расшифровка
// Память переполнится, но стандартная процедура Сформировать неизвестно как работает, может так же не удаляет
ДанныеРасшифровки = ПоместитьВоВременноеХранилище(РезультатВыполнения.ДанныеРасшифровки, УникальныйИдентификатор);
ЭтаФорма.Результат = РезультатВыполнения.Результат; // Этаформа.Результат - что бы не путались реквизит формы с параметром процедуры
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "НеИспользовать");
// Либо используем авто создаваемое хранилище и удаляем его, что бы не было переполнения памяти
// либо используем один раз созданное хранилище из реквизита
УдалитьИзВременногоХранилища(АдресРезультата); // дабы память не переполнялась
КонецПроцедуры
// Возвращает параметры отчета
// Возможно это все можно получить в СформироватьОтчет.
//
// Возвращаемое значение:
// Структура - параметры отчета для программного формирования
// * СхемаКомпоновкиДанных - СхемаКомпоновкиДанных - Схема компоновки данных
// * НастройкиПользователя - ПользовательскиеНастройкиКомпоновкиДанных - настройки пользователя
&НаСервере
Функция ПолучитьПараметрыОтчета()
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
ПараметрыОтчета = Новый Структура;
ПараметрыОтчета.Вставить("СхемаКомпоновкиДанных" , ОтчетОбъект.СхемаКомпоновкиДанных);
ПараметрыОтчета.Вставить("НастройкиПользователя" , Отчет.КомпоновщикНастроек.ПользовательскиеНастройки);
Возврат ПараметрыОтчета;
КонецФункции // ПолучитьПараметрыОтчета()
// Формирует отчет программно, не в фоне.
// Использует ту же процедуру отчета СформироватьОтчет, что и фоновая. Но обходится без вызова команды и временного хранилища.
//
&НаСервере
Процедура СформироватьОтчетПрограммноНаСервере()
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "ФОРМИРОВАНИЕОТЧЕТА");
// Формируем параметры отчета
ПараметрыОтчета = ПолучитьПараметрыОтчета(); // Параметры нужны и фоновой
РезультатВыполнения = Новый Структура(); // Для получения результата формирования
// Выполняем процедуру отчета по формированию
ОтчетОбъект = РеквизитФормыВЗначение("Отчет");
ОтчетОбъект.СформироватьОтчет(ПараметрыОтчета, РезультатВыполнения);
// Данные расшифровки поместить в хранилище, что бы работала расшифровка
// Память переполнится, но стандартная процедура Сформировать неизвестно как работает, может так же не удаляет
ДанныеРасшифровки = ПоместитьВоВременноеХранилище(РезультатВыполнения.ДанныеРасшифровки, УникальныйИдентификатор); // Что с памятью?
// Отображаем результат
Результат=РезультатВыполнения.Результат;
ОбщегоНазначенияКлиентСервер.УстановитьСостояниеПоляТабличногоДокумента(Элементы.Результат, "НеИспользовать");
КонецПроцедуры
#КонецОбласти