ОтчетОбъект.<Имя отчета>.ПолучитьФорму

Методы · GetForm

Получает форму отчета.

Синтаксис

ПолучитьФорму(<Форма>, <Владелец>, <КлючУникальности>)

Примеры платформы

ОтчетОПродажах = Отчеты.Продажи.Создать();
Форма = ОтчетОПродажах.ПолучитьФорму();
Полное описание, параметры и ограничения

ОтчетОбъект.<Имя отчета>.ПолучитьФорму (ReportObject.<Report name>.GetForm)

ОтчетОбъект.<Имя отчета> (ReportObject.<Report name>)

ПолучитьФорму (GetForm)

Доступен, начиная с версии 8.0.

Синтаксис:
ПолучитьФорму(<Форма>, <Владелец>, <КлючУникальности>)
Параметры:

<Форма> (необязательный)
Тип: Строка, ОбъектМетаданных: Форма.
Имя формы, как оно задано в конфигураторе, или объект описания метаданного требуемой формы. Если параметр не указан, то используется основная форма, заданная в конфигураторе.

<Владелец> (необязательный)
Тип: Форма; Элемент управления.
Объект, который будет являться владельцем открываемой формы.

<КлючУникальности> (необязательный)
Тип: Произвольный.
В данном параметре может быть задан некоторый ключ, значение которого будет использоваться для поиска уже открытых форм.
При поиске учитываются значения свойств открытых форм соответствующим значениям параметров метода. Если найдена открытая форма (по совпадению всех параметров), то она будет возвращена вместо новой формы.
Если из некой формы (один и тот же владелец) требуется открывать новые экземпляры другой формы, то при каждом вызове метода значение данного параметра должно быть уникально (в рамках соответствующих значений свойств открытых форм).
Значение параметра присваивается свойству открываемой формы КлючУникальности.
Следует учитывать, что при получении формы из "объекта" система получает форму для конкретного экземпляра объекта с учетом совокупности переданных параметров, в то время как для "ссылки" всегда существует только один объект в базе данных и форма получается одна (для одинаковой совокупности параметров).
Возвращаемое значение:
Тип: Форма, Неопределено.
Неопределено - если в обработчике ПриСозданииНаСервере установлен признак отказа от создания формы.
Описание:

Получает форму отчета.

Доступность:

Толстый клиент.

Пример:

ОтчетОПродажах = Отчеты.Продажи.Создать();
Форма = ОтчетОПродажах.ПолучитьФорму();

Использование в версии:

Доступен, начиная с версии 8.0.

Методическая информация

Практические примеры

Свой отчет в памяти: интервальные отборы, границы и две обычные формы

Полный маршрут для новичка на отдельной пустой конфигурации. Настоящий менеджер создает отчет, его собственная табличная часть дает типизированный источник построителю; отборы и native компоновка проверяются по полным строкам и числам, а Отмена не восстанавливает чужие изменения.

Где и как запускать

Толстый клиент, обычное приложение собственной новой пустой CF; общий модуль УчебныйОтчетМаршрут85, только Клиент (обычное приложение).

Подготовка

  1. Не открывайте УТ/КА/УНФ/БП и не вставляйте этот код в рабочий отчет. Вручную создайте отдельную новую пустую файловую ИБ на установленной платформе8.5.1.1343. Имя конфигурации строго УчебныйОтчетОтбор85. В этой задаче отчет, его строки и отборы живут только в памяти; урок не создает справочников, документов или записей регистров.

  2. В свойствах конфигурации настройте поддерживаемые режимы запуска: Управляемое приложение и обычное приложение; основной режим запуска: Обычное приложение. Первый выбор нужен, чтобы в свойствах общего модуля был виден флаг Клиент (обычное приложение). Проверяйте урок только в собственной файловой ИБ и толстом обычном клиенте, не в тонком/веб/мобильном. ПолучитьФорму и ПолучитьФормуНастроек здесь возвращают старую Форма и по native справке доступны только толстому клиенту.

  3. Сохраните только свою новую конфигурацию и ее собственную учебную базу вручную. Справочники, документы, перечисления, все регистры/планы, общие реквизиты, подписки, задания, внешние источники, константы, обработки, общие формы и хранилища настроек должны отсутствовать. Не устанавливайте расширения ни в ИБ, ни в сеанс. Защитные проверки читают эти списки, но не меняют их.

  4. В ветке Роли создайте единственную роль УчебныйАдминистратор85 с административными правами своей пустой ИБ. В Администрирование → Пользователи создайте ровно одного своего пользователя УченикОтчет85, назначьте эту роль и войдите им. Это ручная подготовка только нового учебного стенда: код пользователей/ролей не создает и не меняет, не выводит их имена или UUID. UUID текущего пользователя сравнивается с единственным реальным пользователем, а не выдумывается.

  5. В Общие → Общие модули создайте единственный модуль УчебныйОтчетМаршрут85. Флаги: Клиент (обычное приложение)=Да, Сервер=Нет, Глобальный=Нет, Привилегированный=Нет. Главный блок урока целиком вставьте в этот модуль. Директив &НаСервере/НаКлиенте в нем нет: это именно толстый обычный клиент.

  6. В Отчеты создайте единственный отчет УчебныйОтбор85. Макетов и основной схемы компоновки не создавайте: результат сформирует собственный полный обработчик ПриКомпоновкеРезультата. Никакие ранее существовавшие отчеты или BSP не используются.

  7. У отчета создайте ровно6 реквизитов: Маркер85 — Строка36 переменной длины; Заголовок85 — Строка80 переменной длины, Проверка заполнения=Показывать ошибку; СуммаС85 и СуммаПо85 — Число9.2, неотрицательное; ВключатьГраницы85 и ОтбиратьPAPER85 — Булево. Для всех, кроме Заголовок85, проверка заполнения=Не проверять. Не назначайте значения по умолчанию, обработчики изменения или сторонние проверки.

  8. В табличных частях отчета создайте ровно одну Строки85 с5 реквизитами: Код85/Категория85 — Строка12 переменной длины; Количество85/Цена85/Сумма85 — Число9.2 неотрицательное. Проверка заполнения каждого=Не проверять. Не создавайте реквизит НомерСтроки самостоятельно: это стандартная нумерация табличной части.

  9. Во вкладке модуль объекта отчета вставьте целиком первый дополнительный блок. Его native события назначаются по именам: ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) и ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка). В обоих обработчиках инструкции #Если ТолстыйКлиентОбычноеПриложение оставляют вызовы клиентского общего модуля только в этом контексте. В файловом обычном приложении этот символ определен у обеих частей приложения; это не универсальный запрет серверной части File. В отдельных серверных, внешних, фоновых и иных клиентских контекстах ветвь #Иначе отказывает до вызова общего модуля: проверка устанавливает Отказ=Истина, компоновка заранее отключает стандартную обработку и оба обработчика вызывают исключение. Не создавайте обработчик ОбработкаКомпоновкиРезультата и не вызывайте ни один из этих обработчиков напрямую.

  10. У отчета создайте2 собственные обычные формы: УчебныйРезультат85 как форму отчета и УчебныеГраницы85 как форму настроек. Главный реквизит обеих — Отчет, тип ОтчетОбъект.УчебныйОтбор85. В свойствах форм отключите Восстанавливать настройки автоматически. Не добавляйте сохранение настроек, стандартные команды работы с хранилищем, файл/печать/расшифровку. Собственные команды только из следующих шагов.

  11. В обычной форме УчебныйРезультат85 добавьте поле табличного документа Результат85 и две кнопки Сформировать85/Настройки85. Назначьте их действия одноименным процедурам модуля; событие формы ПриОткрытии — процедуре ПриОткрытии. Весь второй дополнительный блок — полный модуль этой формы. Отчет создается через native менеджер, а форма получается именно у этого экземпляра, не через неизвестную ссылку.

  12. В обычной форме УчебныеГраницы85 создайте только локальные реквизиты формы ГраницаС85/ГраницаПо85 (Число9.2 неотрицательное), Включать85/КатегорияPAPER85 (Булево). Разместите2 числовых поля и2 флажка, связанные с этими реквизитами, НЕ с Отчет.СуммаС85/СуммаПо85 и НЕ напрямую с реквизитами отчета. Поэтому ввод в форму не меняет отчет до команды Применить.

  13. Там же добавьте собственные кнопки Применить85 и Отмена85 с одноименными действиями. Назначьте события ПриОткрытии/ПередЗакрытием одноименным процедурам. Полный третий дополнительный блок — модуль этой формы. Не создавайте ПриИзменении для полей или автоматическую запись/сохранение в ПриЗакрытии.

  14. В модуль обычного приложения вставьте целиком четвертый дополнительный блок; назначьте native событие ПриНачалеРаботыСистемы. Никакая команда не запускает программу/сервис/фоновое задание и не печатает документ. Подготовку метаданных и открытие своего тестового клиента выполняет только человек.

  15. Перед запуском проверьте синтаксис всех5 модулей конфигурации. Если версия/права/состав метаданных или типы не совпали, остановитесь и исправьте только новый учебный стенд. Этот опубликованный текст проверен статически по installed native справке; запуск в1С не выполнен.

  16. При начале собственного сеанса выполнятся4 числовых этапа750/950/0/1000 и5 ожидаемых исключений; затем отдельный новый отчет с пустым обязательным заголовком обязан дать Ложь у native ПроверитьЗаполнение. Платформа покажет только собственную учебную ошибку заполнения. Не очищайте чужие сообщения; здесь они не запрашиваются и никуда не отправляются.

  17. После проверок открывается своя форма результата с BOOK3×250=750. Нажмите Настройки: поставьте200/750, включенные границы, PAPER, Применить; в форме результата нажмите Сформировать и ожидайте BOOK750 + PAD200 =950. Форма настроек не обещает автообновление другой формы: формирование явно отдельно.

  18. Откройте настройки снова, меняйте только локальные поля, например50/750, и нажмите Отмена либо крестик окна. Затем Сформировать должен снова показать950, а не1000. Fresh readback проверяет неизменность всех6 настоящих реквизитов и всех3 строк; если отчет уже изменен извне, отмена не восстанавливает старый снимок, а останавливает работу.

  19. Для проверки исключения границ поставьте200/750, выключите Включать, оставьте PAPER: оба собственных товара на границах исключены, итог0. Затем50/750, включенные границы, выключите PAPER: явное удаление только собственного условия категории дает3 товара и1000. Источник с3 строками/1000 не удаляется ни на одном шаге.

  20. При неожиданной ошибке формирования/вывода/применения закройте свой тестовый сеанс и разберите ошибку. Код не обещает атомарности нескольких присваиваний или Очистить+Вывести, не повторяет неясно завершившиеся операции, не делает слепой rollback. Контроль относится к бизнес-данным и явным вызовам урока; внутренние платформенные UI-кеши/геометрию окон он не доказывает.

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

Функция ПроверитьСвойСтенд85() Экспорт
    ПроверитьСвойПустойСтенд();
    Если Метаданные.Отчеты.Количество() <> 1 Или Метаданные.ОбщиеМодули.Количество() <> 1
        Или Метаданные.ОбщиеФормы.Количество() <> 0 Или Метаданные.Обработки.Количество() <> 0
        Или Метаданные.Константы.Количество() <> 0 Или Метаданные.ХранилищаНастроек.Количество() <> 0
        Или Метаданные.Роли.Количество() <> 1 Тогда
        ВызватьИсключение "OWN-REPORT-METADATA: нужна только своя схема";
    КонецЕсли;
    ОписаниеОтчета = Метаданные.Отчеты.Найти("УчебныйОтбор85");
    Если ОписаниеОтчета = Неопределено Или Метаданные.ОбщиеМодули.Найти("УчебныйОтчетМаршрут85") = Неопределено
        Или Метаданные.Роли.Найти("УчебныйАдминистратор85") = Неопределено Тогда
        ВызватьИсключение "OWN-REPORT-METADATA: нет собственных объектов";
    КонецЕсли;
    Если ОписаниеОтчета.Реквизиты.Количество() <> 6 Или ОписаниеОтчета.ТабличныеЧасти.Количество() <> 1
        Или ОписаниеОтчета.Формы.Количество() <> 2 Или ОписаниеОтчета.Макеты.Количество() <> 0 Тогда
        ВызватьИсключение "OWN-REPORT-METADATA: неверный состав отчета";
    КонецЕсли;
    Для Каждого ИмяРеквизита Из СтрРазделить("Маркер85,Заголовок85,СуммаС85,СуммаПо85,ВключатьГраницы85,ОтбиратьPAPER85", ",") Цикл
        Если ОписаниеОтчета.Реквизиты.Найти(ИмяРеквизита) = Неопределено Тогда
            ВызватьИсключение "OWN-REPORT-METADATA: нет собственного реквизита";
        КонецЕсли;
    КонецЦикла;
    ТабличнаяЧасть = ОписаниеОтчета.ТабличныеЧасти.Найти("Строки85");
    Если ТабличнаяЧасть = Неопределено Или ТабличнаяЧасть.Реквизиты.Количество() <> 5
        Или ОписаниеОтчета.Формы.Найти("УчебныйРезультат85") = Неопределено
        Или ОписаниеОтчета.Формы.Найти("УчебныеГраницы85") = Неопределено Тогда
        ВызватьИсключение "OWN-REPORT-METADATA: нет своих строк или форм";
    КонецЕсли;
    Для Каждого ИмяКолонки Из СтрРазделить("Код85,Категория85,Количество85,Цена85,Сумма85", ",") Цикл
        Если ТабличнаяЧасть.Реквизиты.Найти(ИмяКолонки) = Неопределено Тогда
            ВызватьИсключение "OWN-REPORT-METADATA: нет своей колонки";
        КонецЕсли;
    КонецЦикла;
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
    Если ТипЗнч(Пользователи) <> Тип("Массив") Или Пользователи.Количество() <> 1
        Или ТипЗнч(Пользователь) <> Тип("ПользовательИнформационнойБазы") Тогда
        ВызватьИсключение "OWN-REPORT-USER: нужен ровно один собственный пользователь";
    КонецЕсли;
    Если Пользователь.Имя <> "УченикОтчет85" Или Пользователи[0].Имя <> "УченикОтчет85"
        Или ТипЗнч(Пользователь.УникальныйИдентификатор) <> Тип("УникальныйИдентификатор")
        Или Пользователь.УникальныйИдентификатор <> Пользователи[0].УникальныйИдентификатор
        Или Пользователь.УникальныйИдентификатор = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
        ВызватьИсключение "OWN-REPORT-USER: не совпал собственный аутентифицированный пользователь";
    КонецЕсли;
    Возврат Пользователь.УникальныйИдентификатор;
КонецФункции

Функция СвоиОбразцы85()
    Образцы = Новый Массив;
    Образцы.Добавить(Новый Структура("Код85,Категория85,Количество85,Цена85,Сумма85", "BOOK", "PAPER", 3, 250, 750));
    Образцы.Добавить(Новый Структура("Код85,Категория85,Количество85,Цена85,Сумма85", "PAD", "PAPER", 2, 100, 200));
    Образцы.Добавить(Новый Структура("Код85,Категория85,Количество85,Цена85,Сумма85", "PEN", "OFFICE", 1, 50, 50));
    Возврат Образцы;
КонецФункции

Процедура ПроверитьТипКолонки85(ОписаниеТипа, Имя)
    Числовая = Имя = "Количество85" Или Имя = "Цена85" Или Имя = "Сумма85";
    НужныйТип = ?(Числовая, Тип("Число"), Тип("Строка"));
    Если ОписаниеТипа.Типы().Количество() <> 1 Или Не ОписаниеТипа.СодержитТип(НужныйТип) Тогда
        ВызватьИсключение "OWN-REPORT-COLUMN-TYPE: " + Имя;
    КонецЕсли;
    Если Числовая Тогда
        Квалификаторы = ОписаниеТипа.КвалификаторыЧисла;
        Если Квалификаторы.Разрядность <> 9 Или Квалификаторы.РазрядностьДробнойЧасти <> 2
            Или Квалификаторы.ДопустимыйЗнак <> ДопустимыйЗнак.Неотрицательный Тогда
            ВызватьИсключение "OWN-REPORT-COLUMN-TYPE: нужны Число9.2 и неотрицательный знак";
        КонецЕсли;
    Иначе
        Если ОписаниеТипа.КвалификаторыСтроки.Длина <> 12 Тогда
            ВызватьИсключение "OWN-REPORT-COLUMN-TYPE: нужна Строка12";
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьТаблицу85(Таблица, Ожидания, ПроверятьКвалификаторы = Истина) Экспорт
    Если ТипЗнч(Таблица) <> Тип("ТаблицаЗначений") Или ТипЗнч(Ожидания) <> Тип("Массив") Тогда
        ВызватьИсключение "OWN-REPORT-TABLE-TYPE: нужны собственные типизированные данные";
    КонецЕсли;
    Имена = СтрРазделить("Код85,Категория85,Количество85,Цена85,Сумма85", ",");
    Если Таблица.Колонки.Количество() <> 5 Или Таблица.Количество() <> Ожидания.Количество() Тогда
        ВызватьИсключение "OWN-REPORT-DATA: неверные размеры таблицы";
    КонецЕсли;
    Для Каждого Имя Из Имена Цикл
        Колонка = Таблица.Колонки.Найти(Имя);
        Если Колонка = Неопределено Тогда
            ВызватьИсключение "OWN-REPORT-DATA: нет собственной колонки";
        КонецЕсли;
        Если ПроверятьКвалификаторы Тогда
            ПроверитьТипКолонки85(Колонка.ТипЗначения, Имя);
        Иначе
            НужныйТип = ?(Имя = "Код85" Или Имя = "Категория85", Тип("Строка"), Тип("Число"));
            Если Не Колонка.ТипЗначения.СодержитТип(НужныйТип) Тогда
                ВызватьИсключение "OWN-REPORT-COLUMN-TYPE: результат должен содержать нужный тип";
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    Встреченные = Новый Массив;
    Для Каждого СтрокаДанных Из Таблица Цикл
        Совпадение = Неопределено;
        Для Каждого Ожидание Из Ожидания Цикл
            Если СтрокаДанных.Код85 = Ожидание.Код85 Тогда
                Совпадение = Ожидание;
                Прервать;
            КонецЕсли;
        КонецЦикла;
        Если Совпадение = Неопределено Или Встреченные.Найти(СтрокаДанных.Код85) <> Неопределено Тогда
            ВызватьИсключение "OWN-REPORT-DATA: чужой или повторный код";
        КонецЕсли;
        Для Каждого Имя Из Имена Цикл
            Факт = СтрокаДанных[Имя];
            Ожидается = Совпадение[Имя];
            Если ТипЗнч(Факт) <> ТипЗнч(Ожидается) Или Факт <> Ожидается Тогда
                ВызватьИсключение "OWN-REPORT-DATA: не совпала полная собственная строка";
            КонецЕсли;
        КонецЦикла;
        Если СтрокаДанных.Количество85 * СтрокаДанных.Цена85 <> СтрокаДанных.Сумма85 Тогда
            ВызватьИсключение "OWN-REPORT-DATA: неверная арифметика строки";
        КонецЕсли;
        Встреченные.Добавить(СтрокаДанных.Код85);
    КонецЦикла;
КонецПроцедуры

Функция ПроверитьОтчет85(СвойОтчет, СвойUUID, РазрешитьПустойЗаголовок = Ложь) Экспорт
    ПроверитьСвойСтенд85();
    Если ТипЗнч(СвойUUID) <> Тип("УникальныйИдентификатор")
        Или СвойUUID = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000")
        Или ТипЗнч(СвойОтчет) <> Тип("ОтчетОбъект.УчебныйОтбор85") Тогда
        ВызватьИсключение "OWN-REPORT-OWNER: нужен собственный отчет и ненулевой UUID";
    КонецЕсли;
    Если СвойОтчет.Метаданные() <> Метаданные.Отчеты.УчебныйОтбор85 Или СвойОтчет.Маркер85 <> Строка(СвойUUID) Тогда
        ВызватьИсключение "OWN-REPORT-OWNER: не совпал собственный объект";
    КонецЕсли;
    Если СвойОтчет.Заголовок85 <> "Три своих учебных товара" Тогда
        Если Не РазрешитьПустойЗаголовок Или СвойОтчет.Заголовок85 <> "" Тогда
            ВызватьИсключение "OWN-REPORT-HEADER: неизвестный заголовок";
        КонецЕсли;
    КонецЕсли;
    ПроверитьГраницы85(СвойОтчет.СуммаС85, СвойОтчет.СуммаПо85, СвойОтчет.ВключатьГраницы85, СвойОтчет.ОтбиратьPAPER85);
    Если ТипЗнч(СвойОтчет.Строки85) <> Тип("ОтчетТабличнаяЧасть.УчебныйОтбор85.Строки85") Тогда
        ВызватьИсключение "OWN-REPORT-OWNER: нет своей настоящей табличной части";
    КонецЕсли;
    Данные = СвойОтчет.Строки85.Выгрузить(, "Код85,Категория85,Количество85,Цена85,Сумма85");
    ПроверитьТаблицу85(Данные, СвоиОбразцы85());
    Если Данные.Итог("Сумма85") <> 1000 Тогда
        ВызватьИсключение "OWN-REPORT-DATA: полный источник должен давать1000";
    КонецЕсли;
    Возврат Данные;
КонецФункции

Процедура ПроверитьГраницы85(СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER) Экспорт
    Если ТипЗнч(СуммаС) <> Тип("Число") Или ТипЗнч(СуммаПо) <> Тип("Число")
        Или ТипЗнч(ВключатьГраницы) <> Тип("Булево") Или ТипЗнч(ОтбиратьPAPER) <> Тип("Булево") Тогда
        ВызватьИсключение "OWN-REPORT-RANGE-TYPE: границы числа, переключатели булево";
    КонецЕсли;
    Если СуммаС < 0 Или СуммаПо > 1000 Или СуммаС > СуммаПо
        Или Окр(СуммаС, 2) <> СуммаС Или Окр(СуммаПо, 2) <> СуммаПо Тогда
        ВызватьИсключение "OWN-REPORT-RANGE: нужны0..1000, два знака, начало не больше конца";
    КонецЕсли;
КонецПроцедуры

Функция СоздатьСвоиДанные85()
    ПользовательUUID = ПроверитьСвойСтенд85();
    Менеджеры = Отчеты;
    Если ТипЗнч(Менеджеры) <> Тип("ОтчетыМенеджер") Тогда
        ВызватьИсключение "OWN-REPORT-FACTORY: нужен настоящий менеджер отчетов";
    КонецЕсли;
    СвойОтчет = Менеджеры["УчебныйОтбор85"].Создать();
    Если ТипЗнч(СвойОтчет) <> Тип("ОтчетОбъект.УчебныйОтбор85") Или СвойОтчет.Строки85.Количество() <> 0 Тогда
        ВызватьИсключение "OWN-REPORT-FACTORY: нужен новый пустой экземпляр";
    КонецЕсли;
    СвойUUID = Новый УникальныйИдентификатор;
    СвойОтчет.Маркер85 = Строка(СвойUUID);
    СвойОтчет.Заголовок85 = "Три своих учебных товара";
    СвойОтчет.СуммаС85 = 250;
    СвойОтчет.СуммаПо85 = 750;
    СвойОтчет.ВключатьГраницы85 = Истина;
    СвойОтчет.ОтбиратьPAPER85 = Истина;
    Для Каждого Образец Из СвоиОбразцы85() Цикл
        НоваяСтрока = СвойОтчет.Строки85.Добавить();
        НоваяСтрока.Код85 = Образец.Код85;
        НоваяСтрока.Категория85 = Образец.Категория85;
        НоваяСтрока.Количество85 = Образец.Количество85;
        НоваяСтрока.Цена85 = Образец.Цена85;
        НоваяСтрока.Сумма85 = НоваяСтрока.Количество85 * НоваяСтрока.Цена85;
    КонецЦикла;
    ПроверитьОтчет85(СвойОтчет, СвойUUID);
    Контекст = Новый Структура("UUID,ПользовательUUID,Отчет", СвойUUID, ПользовательUUID, СвойОтчет);
    Если Не СвойОтчет.ПроверитьЗаполнение() Тогда
        ВызватьИсключение "OWN-REPORT-FILL: подготовленные данные не прошли native проверку";
    КонецЕсли;
    Возврат Контекст;
КонецФункции

Процедура ПроверитьКонтекст85(Контекст) Экспорт
    Если ТипЗнч(Контекст) <> Тип("Структура") Или Контекст.Количество() <> 3 Тогда
        ВызватьИсключение "OWN-REPORT-CONTEXT: нужен свой полный контекст";
    КонецЕсли;
    Если Не Контекст.Свойство("UUID", UUID) Или Не Контекст.Свойство("ПользовательUUID", ПользовательUUID)
        Или Не Контекст.Свойство("Отчет", СвойОтчет) Тогда
        ВызватьИсключение "OWN-REPORT-CONTEXT: неверные поля контекста";
    КонецЕсли;
    Если ТипЗнч(ПользовательUUID) <> Тип("УникальныйИдентификатор") Или ПользовательUUID <> ПроверитьСвойСтенд85() Тогда
        ВызватьИсключение "OWN-REPORT-USER: контекст не своего пользователя";
    КонецЕсли;
    ПроверитьОтчет85(СвойОтчет, UUID);
КонецПроцедуры

Функция СнятьНастройки85(Контекст) Экспорт
    ПроверитьКонтекст85(Контекст);
    СвойОтчет = Контекст.Отчет;
    Возврат Новый ФиксированнаяСтруктура(Новый Структура("Маркер,Заголовок,СуммаС,СуммаПо,ВключатьГраницы,ОтбиратьPAPER",
        СвойОтчет.Маркер85, СвойОтчет.Заголовок85, СвойОтчет.СуммаС85, СвойОтчет.СуммаПо85,
        СвойОтчет.ВключатьГраницы85, СвойОтчет.ОтбиратьPAPER85));
КонецФункции

Процедура ПроверитьСнимок85(Контекст, Снимок) Экспорт
    Свежий = СнятьНастройки85(Контекст);
    Если ТипЗнч(Снимок) <> Тип("ФиксированнаяСтруктура") Или Снимок.Количество() <> 6 Тогда
        ВызватьИсключение "OWN-REPORT-SNAPSHOT: нужен свой снимок";
    КонецЕсли;
    Для Каждого Пара Из Свежий Цикл
        Если Не Снимок.Свойство(Пара.Ключ, Значение) Или ТипЗнч(Значение) <> ТипЗнч(Пара.Значение) Или Значение <> Пара.Значение Тогда
            ВызватьИсключение "OWN-REPORT-SNAPSHOT: настройки уже изменились; остановитесь";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Процедура ПринятьГраницы85(Контекст, Снимок, СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER) Экспорт
    ПроверитьСнимок85(Контекст, Снимок);
    ПроверитьГраницы85(СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER);
    Контекст.Отчет.СуммаС85 = СуммаС;
    Контекст.Отчет.СуммаПо85 = СуммаПо;
    Контекст.Отчет.ВключатьГраницы85 = ВключатьГраницы;
    Контекст.Отчет.ОтбиратьPAPER85 = ОтбиратьPAPER;
    Свежий = СнятьНастройки85(Контекст);
    Если Свежий.СуммаС <> СуммаС Или Свежий.СуммаПо <> СуммаПо Или Свежий.ВключатьГраницы <> ВключатьГраницы
        Или Свежий.ОтбиратьPAPER <> ОтбиратьPAPER Тогда
        ВызватьИсключение "OWN-REPORT-READBACK: принятие настроек не подтверждено";
    КонецЕсли;
КонецПроцедуры

Функция ОжидаемыеСтроки85(СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER)
    ПроверитьГраницы85(СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER);
    Ожидания = Новый Массив;
    Для Каждого Образец Из СвоиОбразцы85() Цикл
        ВДиапазоне = ?(ВключатьГраницы, Образец.Сумма85 >= СуммаС И Образец.Сумма85 <= СуммаПо,
            Образец.Сумма85 > СуммаС И Образец.Сумма85 < СуммаПо);
        Если ВДиапазоне И (Не ОтбиратьPAPER Или Образец.Категория85 = "PAPER") Тогда
            Ожидания.Добавить(Образец);
        КонецЕсли;
    КонецЦикла;
    Возврат Ожидания;
КонецФункции

Функция ВыполнитьСвойПостроитель85(Построитель, Ожидания)
    Построитель.Выполнить();
    Если ТипЗнч(Построитель.Результат) <> Тип("РезультатЗапроса") Тогда
        ВызватьИсключение "OWN-REPORT-RESULT: нет настоящего результата";
    КонецЕсли;
    Результат = Построитель.Результат.Выгрузить();
    ПроверитьТаблицу85(Результат, Ожидания, Ложь);
    Возврат Результат;
КонецФункции

Функция ОтобратьСвоиСтроки85(СвойОтчет, СвойUUID)
    Данные = ПроверитьОтчет85(СвойОтчет, СвойUUID);
    Описание = Новый ОписаниеИсточникаДанных(Данные);
    ПроверитьТаблицу85(Описание.ИсточникДанных, СвоиОбразцы85());
    Если Описание.Колонки.Количество() <> 5 Тогда
        ВызватьИсключение "OWN-REPORT-SOURCE: описание не своего источника";
    КонецЕсли;
    Для Каждого КолонкаОписания Из Описание.Колонки Цикл
        Если Данные.Колонки.Найти(КолонкаОписания.Имя) = Неопределено Тогда
            ВызватьИсключение "OWN-REPORT-SOURCE: чужая колонка описания";
        КонецЕсли;
        КолонкаОписания.Поле = Истина;
        Если КолонкаОписания.Имя = "Категория85" Или КолонкаОписания.Имя = "Сумма85" Тогда
            Если ТипЗнч(КолонкаОписания.Отбор) <> Тип("Булево") Или Не КолонкаОписания.Отбор Тогда
                ВызватьИсключение "OWN-REPORT-SOURCE: native возможность отбора должна быть доступна";
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    Построитель = Новый ПостроительОтчета;
    Построитель.ИсточникДанных = Описание;
    Построитель.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
    Построитель.ВыбранныеПоля.Очистить();
    Для Каждого Колонка Из Данные.Колонки Цикл
        Построитель.ВыбранныеПоля.Добавить(Колонка.Имя, Колонка.Имя);
    КонецЦикла;
    Отбор85 = Построитель.Отбор;
    Если ТипЗнч(Отбор85) <> Тип("Отбор") Или Отбор85.Количество() <> 0 Тогда
        ВызватьИсключение "OWN-REPORT-FILTER: нужен собственный пустой отбор";
    КонецЕсли;
    Доступные = Отбор85.ПолучитьДоступныеПоля();
    Если ТипЗнч(Доступные) <> Тип("ПоляНастройки") Или Доступные.Найти("Категория85") = Неопределено
        Или Доступные.Найти("Сумма85") = Неопределено Тогда
        ВызватьИсключение "OWN-REPORT-FILTER: свои поля недоступны";
    КонецЕсли;
    Для Каждого Поле Из Доступные Цикл
        Если Данные.Колонки.Найти(Поле.Имя) = Неопределено Тогда
            ВызватьИсключение "OWN-REPORT-FILTER: доступно неизвестное поле";
        КонецЕсли;
    КонецЦикла;
    Категория = Отбор85.Добавить("Категория85", "СвояКатегория85", "Только свои PAPER");
    Интервал = Отбор85.Добавить("Сумма85", "СвойИнтервал85", "Свой диапазон суммы");
    Если Категория = Неопределено Или Интервал = Неопределено Тогда
        ВызватьИсключение "OWN-REPORT-FILTER: native Добавить вернул Неопределено";
    КонецЕсли;
    Категория.ВидСравнения = ВидСравнения.Равно;
    Категория.Значение = "PAPER";
    Категория.Использование = Истина;
    Интервал.ВидСравнения = ?(СвойОтчет.ВключатьГраницы85, ВидСравнения.ИнтервалВключаяГраницы, ВидСравнения.Интервал);
    Интервал.ЗначениеС = СвойОтчет.СуммаС85;
    Интервал.ЗначениеПо = СвойОтчет.СуммаПо85;
    Интервал.Использование = Истина;
    Интервал.Представление = "Диапазон собственного отчета " + Строка(СвойUUID);
    Если Отбор85.Количество() <> 2 Или Отбор85.Индекс(Категория) <> 0 Или Отбор85.Индекс(Интервал) <> 1
        Или Отбор85.Получить(0) <> Категория Или Отбор85.Получить(1) <> Интервал
        Или Категория.ПутьКДанным <> "Категория85" Или Интервал.ПутьКДанным <> "Сумма85"
        Или Интервал.Представление <> "Диапазон собственного отчета " + Строка(СвойUUID)
        Или Интервал.ЗначениеС <> СвойОтчет.СуммаС85 Или Интервал.ЗначениеПо <> СвойОтчет.СуммаПо85 Тогда
        ВызватьИсключение "OWN-REPORT-FILTER: неверная структура собственных условий";
    КонецЕсли;
    СКатегорией = ОжидаемыеСтроки85(СвойОтчет.СуммаС85, СвойОтчет.СуммаПо85, СвойОтчет.ВключатьГраницы85, Истина);
    ВыполнитьСвойПостроитель85(Построитель, СКатегорией);
    Отбор85.Сдвинуть(Отбор85.Индекс(Интервал), -1);
    Если Отбор85.Индекс(Интервал) <> 0 Или Отбор85.Индекс(Категория) <> 1 Или Отбор85.Получить(0) <> Интервал Тогда
        ВызватьИсключение "OWN-REPORT-FILTER: перемещение собственного условия не подтверждено";
    КонецЕсли;
    Результат = ВыполнитьСвойПостроитель85(Построитель, СКатегорией);
    Если Не СвойОтчет.ОтбиратьPAPER85 Тогда
        ИндексКатегории = Отбор85.Индекс(Категория);
        Если ИндексКатегории <> 1 Или Отбор85.Количество() <> 2 Или Отбор85.Получить(ИндексКатегории) <> Категория Тогда
            ВызватьИсключение "OWN-REPORT-FILTER: удаление только подтвержденного собственного условия";
        КонецЕсли;
        Отбор85.Удалить(ИндексКатегории);
        Если Отбор85.Количество() <> 1 Или Отбор85.Индекс(Категория) <> -1 Или Отбор85.Получить(0) <> Интервал Тогда
            ВызватьИсключение "OWN-REPORT-FILTER: удаление собственного условия не подтверждено";
        КонецЕсли;
        Ожидания = ОжидаемыеСтроки85(СвойОтчет.СуммаС85, СвойОтчет.СуммаПо85, СвойОтчет.ВключатьГраницы85, Ложь);
        Результат = ВыполнитьСвойПостроитель85(Построитель, Ожидания);
    КонецЕсли;
    ПроверитьТаблицу85(Описание.ИсточникДанных, СвоиОбразцы85());
    ПроверитьОтчет85(СвойОтчет, СвойUUID);
    Возврат Результат;
КонецФункции

Процедура ПроверитьДокумент85(Документ, Ожидания) Экспорт
    Если ТипЗнч(Документ) <> Тип("ТабличныйДокумент") И ТипЗнч(Документ) <> Тип("ПолеТабличногоДокумента") Тогда
        ВызватьИсключение "OWN-REPORT-OUTPUT-TYPE: нужен свой документ или его поле";
    КонецЕсли;
    Если Документ.ВысотаТаблицы <> Ожидания.Количество() + 3 Или Документ.ШиринаТаблицы <> 5
        Или Документ.Область(1, 1).Текст <> "Собственный учебный отбор" Тогда
        ВызватьИсключение "OWN-REPORT-OUTPUT: неверная структура вывода";
    КонецЕсли;
    Сумма = 0;
    Если Ожидания.Количество() > 0 Тогда
        Для Индекс = 0 По Ожидания.Количество() - 1 Цикл
            Образец = Ожидания[Индекс];
            СтрокаВывода = Индекс + 3;
            Если Документ.Область(СтрокаВывода, 1).Текст <> Образец.Код85
                Или Документ.Область(СтрокаВывода, 2).Текст <> Образец.Категория85 Тогда
                ВызватьИсключение "OWN-REPORT-OUTPUT: неверный собственный товар";
            КонецЕсли;
            Для НомерКолонки = 3 По 5 Цикл
                Имя = СтрРазделить("Код85,Категория85,Количество85,Цена85,Сумма85", ",")[НомерКолонки - 1];
                Ячейка = Документ.Область(СтрокаВывода, НомерКолонки);
                Если Не Ячейка.СодержитЗначение Или ТипЗнч(Ячейка.Значение) <> Тип("Число") Или Ячейка.Значение <> Образец[Имя] Тогда
                    ВызватьИсключение "OWN-REPORT-OUTPUT: числа проверяются как числа, не строки";
                КонецЕсли;
            КонецЦикла;
            Сумма = Сумма + Образец.Сумма85;
        КонецЦикла;
    КонецЕсли;
    Итог = Документ.Область(Ожидания.Количество() + 3, 5);
    Если Не Итог.СодержитЗначение Или ТипЗнч(Итог.Значение) <> Тип("Число") Или Итог.Значение <> Сумма Тогда
        ВызватьИсключение "OWN-REPORT-OUTPUT: итог не совпал с независимыми ожиданиями";
    КонецЕсли;
КонецПроцедуры

Процедура СформироватьСвойДокумент85(СвойОтчет, СвойUUID, ДокументРезультат) Экспорт
    Если ТипЗнч(ДокументРезультат) <> Тип("ТабличныйДокумент") Или ДокументРезультат.ВысотаТаблицы <> 0 Тогда
        ВызватьИсключение "OWN-REPORT-OUTPUT-TYPE: только свой новый пустой документ";
    КонецЕсли;
    СтрокиРезультата = ОтобратьСвоиСтроки85(СвойОтчет, СвойUUID);
    Ожидания = ОжидаемыеСтроки85(СвойОтчет.СуммаС85, СвойОтчет.СуммаПо85, СвойОтчет.ВключатьГраницы85, СвойОтчет.ОтбиратьPAPER85);
    ДокументРезультат.Область(1, 1).Текст = "Собственный учебный отбор";
    Имена = СтрРазделить("Код85,Категория85,Количество85,Цена85,Сумма85", ",");
    Для Индекс = 0 По 4 Цикл
        ДокументРезультат.Область(2, Индекс + 1).Текст = Имена[Индекс];
    КонецЦикла;
    Если Ожидания.Количество() > 0 Тогда
        Для Индекс = 0 По Ожидания.Количество() - 1 Цикл
            Образец = Ожидания[Индекс];
            СтрокаРезультата = СтрокиРезультата.Найти(Образец.Код85, "Код85");
            Если СтрокаРезультата = Неопределено Тогда
                ВызватьИсключение "OWN-REPORT-RESULT: собственная ожидаемая строка не найдена";
            КонецЕсли;
            Для Колонка = 0 По 4 Цикл
                Ячейка = ДокументРезультат.Область(Индекс + 3, Колонка + 1);
                Если Колонка < 2 Тогда
                    Ячейка.Текст = СтрокаРезультата[Имена[Колонка]];
                Иначе
                    Ячейка.СодержитЗначение = Истина;
                    Ячейка.Значение = СтрокаРезультата[Имена[Колонка]];
                КонецЕсли;
            КонецЦикла;
        КонецЦикла;
    КонецЕсли;
    ИтоговаяСтрока = Ожидания.Количество() + 3;
    ДокументРезультат.Область(ИтоговаяСтрока, 1).Текст = "Итого";
    Итог = ДокументРезультат.Область(ИтоговаяСтрока, 5);
    Итог.СодержитЗначение = Истина;
    Итог.Значение = 0;
    Для Каждого СтрокаРезультата Из СтрокиРезультата Цикл
        Итог.Значение = Итог.Значение + СтрокаРезультата.Сумма85;
    КонецЦикла;
    ПроверитьДокумент85(ДокументРезультат, Ожидания);
    ДокументРезультат.ТолькоПросмотр = Истина;
КонецПроцедуры

Функция Скомпоновать85(Контекст) Экспорт
    ПроверитьКонтекст85(Контекст);
    Снимок = СнятьНастройки85(Контекст);
    Если Не Контекст.Отчет.ПроверитьЗаполнение() Тогда
        ВызватьИсключение "OWN-REPORT-FILL: формирование отказано";
    КонецЕсли;
    Документ = Новый ТабличныйДокумент;
    Контекст.Отчет.СкомпоноватьРезультат(Документ);
    ПроверитьСнимок85(Контекст, Снимок);
    ПроверитьДокумент85(Документ, ОжидаемыеСтроки85(Снимок.СуммаС, Снимок.СуммаПо, Снимок.ВключатьГраницы, Снимок.ОтбиратьPAPER));
    Возврат Документ;
КонецФункции

Процедура ПроверитьЭтап85(Контекст, СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER, ЧислоСтрок, Сумма)
    ПринятьГраницы85(Контекст, СнятьНастройки85(Контекст), СуммаС, СуммаПо, ВключатьГраницы, ОтбиратьPAPER);
    Документ = Скомпоновать85(Контекст);
    Если Документ.ВысотаТаблицы <> ЧислоСтрок + 3 Или Документ.Область(ЧислоСтрок + 3, 5).Значение <> Сумма Тогда
        ВызватьИсключение "OWN-REPORT-GOLDEN: не совпал независимый числовой этап";
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьМаркерОтказа85(Номер, Маркер)
    ОтказПолучен = Ложь;
    Попытка
        Если Номер = 1 Тогда
            ПроверитьГраницы85("200", 750, Истина, Истина);
        ИначеЕсли Номер = 2 Тогда
            ПроверитьГраницы85(751, 750, Истина, Истина);
        ИначеЕсли Номер = 3 Тогда
            Контекст = СоздатьСвоиДанные85();
            Контекст.Отчет.Строки85.Получить(0).Сумма85 = 749;
            ПроверитьКонтекст85(Контекст);
        ИначеЕсли Номер = 4 Тогда
            Контекст = СоздатьСвоиДанные85();
            ПроверитьОтчет85(Контекст.Отчет, Новый УникальныйИдентификатор);
        ИначеЕсли Номер = 5 Тогда
            Контекст = СоздатьСвоиДанные85();
            Снимок = СнятьНастройки85(Контекст);
            Контекст.Отчет.СуммаС85 = 200;
            ПроверитьСнимок85(Контекст, Снимок);
        Иначе
            ВызватьИсключение "OWN-REPORT-NEGATIVE: неизвестная проверка";
        КонецЕсли;
    Исключение
        Если СтрНайти(ОписаниеОшибки(), Маркер) = 0 Тогда
            ВызватьИсключение;
        КонецЕсли;
        ОтказПолучен = Истина;
    КонецПопытки;
    Если Не ОтказПолучен Тогда
        ВызватьИсключение "OWN-REPORT-NEGATIVE: ожидаемый отказ не получен";
    КонецЕсли;
КонецПроцедуры

Процедура ОткрытьСвоиГраницы85(Контекст, ПолеВладелец) Экспорт
    ПроверитьКонтекст85(Контекст);
    Если ТипЗнч(ПолеВладелец) <> Тип("ПолеТабличногоДокумента") Тогда
        ВызватьИсключение "OWN-REPORT-FORM: только реальное поле своей формы результата";
    КонецЕсли;
    СвояФорма = Контекст.Отчет.ПолучитьФормуНастроек("УчебныеГраницы85", ПолеВладелец, Новый УникальныйИдентификатор);
    Если СвояФорма = Неопределено Или ТипЗнч(СвояФорма) <> Тип("Форма") Тогда
        ВызватьИсключение "OWN-REPORT-FORM: форма своих границ не создана";
    КонецЕсли;
    СвояФорма.Подготовить85(Контекст);
    СвояФорма.Открыть();
КонецПроцедуры

Процедура Запустить85() Экспорт
    Контекст = СоздатьСвоиДанные85();
    ПроверитьЭтап85(Контекст, 250, 750, Истина, Истина, 1, 750);
    ПроверитьЭтап85(Контекст, 200, 750, Истина, Истина, 2, 950);
    ПроверитьЭтап85(Контекст, 200, 750, Ложь, Истина, 0, 0);
    ПроверитьЭтап85(Контекст, 50, 750, Истина, Ложь, 3, 1000);
    ПроверитьМаркерОтказа85(1, "OWN-REPORT-RANGE-TYPE");
    ПроверитьМаркерОтказа85(2, "OWN-REPORT-RANGE:");
    ПроверитьМаркерОтказа85(3, "OWN-REPORT-DATA:");
    ПроверитьМаркерОтказа85(4, "OWN-REPORT-OWNER:");
    ПроверитьМаркерОтказа85(5, "OWN-REPORT-SNAPSHOT:");
    ПустойЗаголовок = СоздатьСвоиДанные85();
    ПустойЗаголовок.Отчет.Заголовок85 = "";
    Если ПустойЗаголовок.Отчет.ПроверитьЗаполнение() Тогда
        ВызватьИсключение "OWN-REPORT-FILL: пустой обязательный заголовок должен быть отвергнут";
    КонецЕсли;
    ПринятьГраницы85(Контекст, СнятьНастройки85(Контекст), 250, 750, Истина, Истина);
    ФормаРезультата = Контекст.Отчет.ПолучитьФорму("УчебныйРезультат85", , Контекст.UUID);
    Если ФормаРезультата = Неопределено Или ТипЗнч(ФормаРезультата) <> Тип("Форма") Тогда
        ВызватьИсключение "OWN-REPORT-FORM: создание своей обычной формы отказано";
    КонецЕсли;
    ФормаРезультата.ВосстанавливатьЗначенияПриОткрытии = Ложь;
    СвоеПоле = ФормаРезультата.ЭлементыФормы.Результат85;
    Если ТипЗнч(СвоеПоле) <> Тип("ПолеТабличногоДокумента") Тогда
        ВызватьИсключение "OWN-REPORT-FORM: результат должен выводиться в реальное свое поле";
    КонецЕсли;
    ФормаРезультата.РезультатОтчета = СвоеПоле;
    Если ФормаРезультата.ВосстанавливатьЗначенияПриОткрытии Или ФормаРезультата.РезультатОтчета <> СвоеПоле Тогда
        ВызватьИсключение "OWN-REPORT-FORM: настройка результата не подтверждена";
    КонецЕсли;
    ФормаРезультата.Подготовить85(Контекст);
    ФормаРезультата.Открыть();
КонецПроцедуры
Полный модуль объекта собственного отчета УчебныйОтбор85

Отчеты → УчебныйОтбор85 → Модуль объекта

Собственный File-стенд и толстое обычное приложение: символ ТолстыйКлиентОбычноеПриложение определен у обеих частей File; отдельные server/external/background и другие клиентские контексты отказывают до client-only общего модуля. Native события вызываются только платформой.

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
#Если ТолстыйКлиентОбычноеПриложение Тогда
    Если ТипЗнч(ПроверяемыеРеквизиты) <> Тип("Массив") Или ПроверяемыеРеквизиты.Найти("Заголовок85") = Неопределено Тогда
        Отказ = Истина;
        ВызватьИсключение "OWN-REPORT-FILL: в native списке должна оставаться проверка заголовка";
    КонецЕсли;
    УчебныйОтчетМаршрут85.ПроверитьОтчет85(ЭтотОбъект, Новый УникальныйИдентификатор(ЭтотОбъект.Маркер85), Истина);
#Иначе
    Отказ = Истина;
    ВызватьИсключение "OWN-REPORT-CONTEXT: проверка этого учебного отчета разрешена только в толстом обычном клиенте";
#КонецЕсли
КонецПроцедуры

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
#Если ТолстыйКлиентОбычноеПриложение Тогда
    УчебныйОтчетМаршрут85.ПроверитьОтчет85(ЭтотОбъект, Новый УникальныйИдентификатор(ЭтотОбъект.Маркер85));
    Если ДанныеРасшифровки <> Null Тогда
        ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
    КонецЕсли;
    УчебныйОтчетМаршрут85.СформироватьСвойДокумент85(ЭтотОбъект, Новый УникальныйИдентификатор(ЭтотОбъект.Маркер85), ДокументРезультат);
#Иначе
    ВызватьИсключение "OWN-REPORT-CONTEXT: компоновка этого учебного отчета разрешена только в толстом обычном клиенте";
#КонецЕсли
КонецПроцедуры
Полный модуль обычной формы результата УчебныйРезультат85

Отчеты → УчебныйОтбор85 → Формы → УчебныйРезультат85 → Модуль

Толстый клиент, обычная форма отчета с главным реквизитом Отчет.

Перем СвойКонтекст85;

Процедура Подготовить85(Контекст) Экспорт
    УчебныйОтчетМаршрут85.ПроверитьКонтекст85(Контекст);
    Если Отчет <> Контекст.Отчет Тогда
        ВызватьИсключение "OWN-REPORT-FORM: форма должна принадлежать своему экземпляру";
    КонецЕсли;
    Если ТипЗнч(ЭлементыФормы.Результат85) <> Тип("ПолеТабличногоДокумента") Тогда
        ВызватьИсключение "OWN-REPORT-FORM: нужен свой реальный элемент управления";
    КонецЕсли;
    ВосстанавливатьЗначенияПриОткрытии = Ложь;
    РезультатОтчета = ЭлементыФормы.Результат85;
    Если ВосстанавливатьЗначенияПриОткрытии Или РезультатОтчета <> ЭлементыФормы.Результат85 Тогда
        ВызватьИсключение "OWN-REPORT-FORM: параметры своей формы не подтверждены";
    КонецЕсли;
    СвойКонтекст85 = Контекст;
КонецПроцедуры

Процедура ПриОткрытии()
    Если СвойКонтекст85 = Неопределено Тогда
        ВызватьИсключение "OWN-REPORT-FORM: запускайте только через свой модуль приложения";
    КонецЕсли;
    ВывестиСвоиДанные85();
КонецПроцедуры

Процедура Сформировать85(Кнопка)
    ПроверитьСвоюКнопку85(Кнопка, "Сформировать85");
    ВывестиСвоиДанные85();
КонецПроцедуры

Процедура ПроверитьСвоюКнопку85(Кнопка, Имя)
    Если Кнопка = Неопределено Или ТипЗнч(Кнопка) <> Тип("Кнопка") Тогда
        ВызватьИсключение "OWN-REPORT-BUTTON: нужна настоящая кнопка своей формы";
    КонецЕсли;
    Если Кнопка <> ЭлементыФормы[Имя] Или Кнопка.Имя <> Имя Тогда
        ВызватьИсключение "OWN-REPORT-BUTTON: неизвестная кнопка";
    КонецЕсли;
КонецПроцедуры

Процедура ВывестиСвоиДанные85()
    УчебныйОтчетМаршрут85.ПроверитьКонтекст85(СвойКонтекст85);
    Если Отчет <> СвойКонтекст85.Отчет Или РезультатОтчета <> ЭлементыФормы.Результат85
        Или ТипЗнч(РезультатОтчета) <> Тип("ПолеТабличногоДокумента") Или ВосстанавливатьЗначенияПриОткрытии Тогда
        ВызватьИсключение "OWN-REPORT-FORM: неизвестная форма или поле результата";
    КонецЕсли;
    НовыйДокумент = УчебныйОтчетМаршрут85.Скомпоновать85(СвойКонтекст85);
    РезультатОтчета.Очистить();
    РезультатОтчета.Вывести(НовыйДокумент);
    Если РезультатОтчета.ВысотаТаблицы <> НовыйДокумент.ВысотаТаблицы
        Или РезультатОтчета.ШиринаТаблицы <> НовыйДокумент.ШиринаТаблицы Тогда
        ВызватьИсключение "OWN-REPORT-FORM: вывод не подтвержден; не повторяйте автоматически";
    КонецЕсли;
    Для Строка = 1 По НовыйДокумент.ВысотаТаблицы Цикл
        Для Колонка = 1 По НовыйДокумент.ШиринаТаблицы Цикл
            Ожидаемая = НовыйДокумент.Область(Строка, Колонка);
            Факт = РезультатОтчета.Область(Строка, Колонка);
            Если Ожидаемая.СодержитЗначение Тогда
                Если Не Факт.СодержитЗначение Или ТипЗнч(Факт.Значение) <> ТипЗнч(Ожидаемая.Значение) Или Факт.Значение <> Ожидаемая.Значение Тогда
                    ВызватьИсключение "OWN-REPORT-FORM: число после вывода изменилось";
                КонецЕсли;
            Иначе
                Если Факт.СодержитЗначение Или Факт.Текст <> Ожидаемая.Текст Тогда
                    ВызватьИсключение "OWN-REPORT-FORM: текст после вывода изменился";
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
    РезультатОтчета.ТолькоПросмотр = Истина;
КонецПроцедуры

Процедура Настройки85(Кнопка)
    ПроверитьСвоюКнопку85(Кнопка, "Настройки85");
    УчебныйОтчетМаршрут85.ПроверитьКонтекст85(СвойКонтекст85);
    Если Отчет <> СвойКонтекст85.Отчет Или РезультатОтчета <> ЭлементыФормы.Результат85 Тогда
        ВызватьИсключение "OWN-REPORT-FORM: владелец настроек должен быть своим";
    КонецЕсли;
    УчебныйОтчетМаршрут85.ОткрытьСвоиГраницы85(СвойКонтекст85, РезультатОтчета);
КонецПроцедуры
Полный модуль обычной формы настроек УчебныеГраницы85

Отчеты → УчебныйОтбор85 → Формы → УчебныеГраницы85 → Модуль

Толстый клиент, обычная форма настроек того же отчета; локальные реквизиты не связаны с Отчет.*.

Перем СвойКонтекст85;
Перем СвойСнимок85;
Перем Принято85;

Процедура Подготовить85(Контекст) Экспорт
    УчебныйОтчетМаршрут85.ПроверитьКонтекст85(Контекст);
    Если Отчет <> Контекст.Отчет Тогда
        ВызватьИсключение "OWN-REPORT-SETTINGS: не свой объект отчета";
    КонецЕсли;
    ВосстанавливатьЗначенияПриОткрытии = Ложь;
    Если ВосстанавливатьЗначенияПриОткрытии Тогда
        ВызватьИсключение "OWN-REPORT-SETTINGS: восстановление настроек должно быть отключено";
    КонецЕсли;
    СвойКонтекст85 = Контекст;
    СвойСнимок85 = УчебныйОтчетМаршрут85.СнятьНастройки85(Контекст);
    ГраницаС85 = СвойСнимок85.СуммаС;
    ГраницаПо85 = СвойСнимок85.СуммаПо;
    Включать85 = СвойСнимок85.ВключатьГраницы;
    КатегорияPAPER85 = СвойСнимок85.ОтбиратьPAPER;
    Принято85 = Ложь;
КонецПроцедуры

Процедура ПриОткрытии()
    УчебныйОтчетМаршрут85.ПроверитьСнимок85(СвойКонтекст85, СвойСнимок85);
    Если Отчет <> СвойКонтекст85.Отчет Или ВосстанавливатьЗначенияПриОткрытии Тогда
        ВызватьИсключение "OWN-REPORT-SETTINGS: неизвестная форма настроек";
    КонецЕсли;
КонецПроцедуры

Процедура Применить85(Кнопка)
    ПроверитьСвоюКнопку85(Кнопка, "Применить85");
    УчебныйОтчетМаршрут85.ПроверитьСнимок85(СвойКонтекст85, СвойСнимок85);
    Если Отчет <> СвойКонтекст85.Отчет Или Принято85 Тогда
        ВызватьИсключение "OWN-REPORT-SETTINGS: применение допускается один раз для своего объекта";
    КонецЕсли;
    УчебныйОтчетМаршрут85.ПринятьГраницы85(СвойКонтекст85, СвойСнимок85, ГраницаС85, ГраницаПо85, Включать85, КатегорияPAPER85);
    Принято85 = Истина;
    Закрыть();
КонецПроцедуры

Процедура Отмена85(Кнопка)
    ПроверитьСвоюКнопку85(Кнопка, "Отмена85");
    УчебныйОтчетМаршрут85.ПроверитьСнимок85(СвойКонтекст85, СвойСнимок85);
    Если Отчет <> СвойКонтекст85.Отчет Или Принято85 Тогда
        ВызватьИсключение "OWN-REPORT-SETTINGS: неизвестная отмена";
    КонецЕсли;
    Закрыть();
КонецПроцедуры

Процедура ПроверитьСвоюКнопку85(Кнопка, Имя)
    Если Кнопка = Неопределено Или ТипЗнч(Кнопка) <> Тип("Кнопка") Тогда
        ВызватьИсключение "OWN-REPORT-BUTTON: нужна настоящая кнопка своих настроек";
    КонецЕсли;
    Если Кнопка <> ЭлементыФормы[Имя] Или Кнопка.Имя <> Имя Тогда
        ВызватьИсключение "OWN-REPORT-BUTTON: неизвестная кнопка настроек";
    КонецЕсли;
КонецПроцедуры

Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
    Если СвойКонтекст85 = Неопределено Или Отчет <> СвойКонтекст85.Отчет Тогда
        Отказ = Истина;
        ВызватьИсключение "OWN-REPORT-SETTINGS: неизвестный владелец закрываемой формы";
    КонецЕсли;
    Если Не Принято85 Тогда
        УчебныйОтчетМаршрут85.ПроверитьСнимок85(СвойКонтекст85, СвойСнимок85);
    Иначе
        УчебныйОтчетМаршрут85.ПроверитьКонтекст85(СвойКонтекст85);
    КонецЕсли;
КонецПроцедуры
Полный модуль обычного приложения собственной пустой CF

Корень конфигурации → Модуль обычного приложения

Толстый клиент; только native ПриНачалеРаботыСистемы.

Процедура ПриНачалеРаботыСистемы()
    УчебныйОтчетМаршрут85.Запустить85();
КонецПроцедуры

Разбор по шагам

  1. Создать свой отчет через Отчеты[имя].Создать, доказать точные метаданные/пользователя/UUID и пустую табличную часть. Заполнить3 вымышленных товара. Сумма вычисляется как количество×цена, затем полная выгрузка независимо сравнивается с750/200/50 и общим1000.

  2. Вызвать native ПроверитьЗаполнение: платформа сама доставляет ОбработкаПроверкиЗаполнения. ЭтотОбъект — реальный текущий отчет внутри его модуля; проверка обязательного заголовка остается в native списке. Отдельный испорченный новый отчет должен быть отвергнут, не меняя положительный экземпляр.

  3. Создать ОписаниеИсточникаДанных из выгруженной ТаблицаЗначений. Проверить ее фактический ИсточникДанных и колонки. Включить5 своих выводимых полей через RW Поле; readonly возможность Отбор для категории/суммы только читать и проверить, никогда не включать присваиванием. Взять именно native Отбор своего нового построителя.

  4. Получить настоящие доступные поля; проверить свои категория/сумма и отсутствие чужих имен. Добавить2 условия, проверить nullable результаты, имена/пути/диапазон/представление/позиции. ВидСравнения.Интервал исключает обе границы, ИнтервалВключаяГраницы включает их.

  5. Выполнить реальный построитель до и после Сдвинуть(числовой индекс,-1); все условия соединены И, поэтому результат тот же. Если PAPER выключен, перед Удалить заново подтвердить ровно свой индекс1 и свой элемент; после удаления проверять count1/index-1 и новые3 строки/1000.

  6. Проверить каждую строку native результата по всем5 полям, фактическим типам скалярных значений и математике. Квалификаторы9.2/Строка12 проверяются у источника; их неизменность у результата построителя не обещается. Сформировать свой табличный документ именно из настоящих строк результата, не из ожиданий; контроль ожиданий создается отдельно из фиксированных учебных чисел. Числовые ячейки проверяются через СодержитЗначение и Значение.

  7. Вызвать у собственного отчета СкомпоноватьРезультат с новым пустым ТабличныйДокумент. Native ПриКомпоновкеРезультата получает его, первым действием отключает стандартную обработку и строит только свой результат. После возврата подтвердить неизменность источника и настроек, а также все ячейки.

  8. Получить у своего экземпляра собственную обычную форму результата. РезультатОтчета — ссылка на реальное ПолеТабличногоДокумента, а не сам ТабличныйДокумент. Полный readback после Вывести сравнивает каждую текстовую и числовую ячейку.

  9. Получить собственную форму границ через ПолучитьФормуНастроек, с реальным своим полем как владельцем и свежим UUID-ключом. Только Применить передает валидированные локальные реквизиты в отчет. Отмена и крестик лишь проверяют исходное фактическое состояние; чужих изменений не откатывают.

Как проверить результат

  1. Полный неизменный источник: BOOK/PAPER3/250/750; PAD/PAPER2/100/200; PEN/OFFICE1/50/50. Все5 типов колонок точны, исходный итог1000.

  2. 250..750 включительно +PAPER:1 строка750; 200..750 включительно +PAPER:2 строки950; 200..750 строго +PAPER:0 строк0; 50..750 включительно без категории:3 строки1000.

  3. У собственного отбора после добавления2 элемента; интервал перемещается1→0, категория0→1. После явного удаления категории1 элемент, индекс старого элемента=-1. Полные строки до/после перестановки одинаковы.

  4. 5 ожидаемых исключений: строковая граница, начало больше конца, сумма749 вместо750, чужой UUID и изменение состояния после снимка. Только точные собственные маркеры принимаются; неожиданное исключение перекидывается.

  5. Положительный заполненный отчет: native ПроверитьЗаполнение=Истина. Отдельный новый отчет с пустым Заголовок85: Ложь. Обработчики не вызываются напрямую и не подменяются обычными функциями.

  6. После изменения локальных полей и Отмена/крестика настоящий отчет и строки остаются прежними. Изменившийся извне отчет дает fail-stop, а не восстановление прошлого состояния.

Ожидаемый результат

Ожидаемый при ручном запуске результат — собственный читаемый отчет и4 подтвержденных итога750/950/0/1000 с отдельным безопасным вводом границ. Реальные1С/ИБ/формы/компоновка и внутреннее поведение сохранения платформы не проверялись; выполнены авторство и статические проверки контрактов.

На что обратить внимание

  1. Это старый ПостроительОтчета для изучения/сопровождения, не СКД и не рекомендация заменять современную компоновку. Схема компоновки и неизвестные рабочие источники не требуются.

  2. ПолучитьДоступныеПоля/Добавить/Удалить запрещены справкой у отборов динамических списков. Здесь receiver только Отбор собственного построителя; не копируйте код на СправочникСписок или ДокументСписок.

  3. Сдвинуть и Удалить у Отбор получают числовые индексы. Не переносите контракт коллекций, где передается сам элемент. ПутьКДанным только для чтения, Представление не переименовывает исходную колонку.

  4. Ctor ОписаниеИсточникаДанных принимает ТаблицаЗначений/РезультатЗапроса/ОбластьЯчеек, не табличную часть. Поэтому выполняется настоящая Выгрузить с явным списком5 колонок и без стандартного НомерСтроки.

  5. В8.5.1 новый ОбработкаКомпоновкиРезультата может получать readonly копию отчета для фонового формирования. Его здесь нет. Старый ПриКомпоновкеРезультата документирован как callback метода СкомпоноватьРезультат; Standard=false исключает стандартную схему/новый callback.

  6. По native справке безопасный режим на время старых обработчиков объекта временно отключается платформой. Урок сам защиту не отключает, а использует только свою пустую конфигурацию, проверенный источник и память. Это не образец запуска недоверенного рабочего кода.

  7. ВосстанавливатьЗначенияПриОткрытии=false отключает именно автоматическое восстановление настроек формы. Это не универсальный запрет внутренних UI-кешей и не доказательство отсутствия любой внутренней системной записи. Явных storage/settings/file/network/DB write вызовов в уроке нет.

  8. Изменение локальных реквизитов формы настроек не должно быть связано с Отчет.* напрямую. Применение нескольких присваиваний и замена вывода не атомарны: неожиданная ошибка требует остановки, не скрытого rollback или повтора.

  9. Нет печати, URL, внешних данных, записи строк в ИБ, сохранения отчета в файл, запуска фонового задания и прямых вызовов native callback. Метаданные и подготовку пользователь создаёт вручную только в новой пустой ИБ.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.