Сменить режим фактического результата отчёта и восстановить исходный режим

Учебные задачи

В толстом управляемом клиенте сохраняем реальные исходные значения настроенного и действующего режима, проверяем обычный/компактный режим и возвращаем исходную настройку. После каждого преобразования читается actual реквизит Результат, не старый параметр события. Плоский typed контракт и визуальные отличия условны и требуют ручной проверки; при неоднозначности сравнение прекращается.

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

Полный модуль подготовленной управляемой формы собственного отчёта. Все процедуры на уровне модуля, директивы уже включены. Только толстый управляемый desktop-клиент 8.5.1.1343; runtime не проверен.

Подготовка

  1. Никакие приведённые модули здесь не запускались. Статические проверки не компилируют и не запускают 1С, не подтверждают автоматическую разметку СКД, типизированные значения или отображение.

  2. Создайте новую отдельную пустую учебную информационную базу платформы 8.5.1.1343. Имя конфигурации УчебныеФормыОтчетов85, основной режим запуска УправляемоеПриложение, режим совместимости НеИспользовать. Рабочую конфигурацию не используйте.

  3. Создайте отдельного нового учебного пользователя собственной новой базы. Запустите именно толстый клиент в режиме управляемого приложения. Это обязательный desktop-стенд, не тонкий, web или мобильный клиент: native enum РежимОтображенияРезультатаОтчета доступен только в толстом клиенте.

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

  5. В дереве конфигурации Отчёты создайте УчебныеТовары85. Реквизитов прикладных объектов, справочников, документов, регистров и записей базы для него не требуется. Модуль объекта отчёта оставьте пустым: события урока принадлежат ФОРМЕ, не объекту отчёта.

  6. Схема полностью создаётся функцией СоздатьСхему в приложенном серверном общем модуле; файловый макет не нужен. Источник УчебныйИсточник имеет ТипИсточникаДанных Local, набор УчебныеТовары является запросом из собственных двух константных строк. Условие Количество > &МинимальноеКоличество, по умолчанию 0.

  7. Свой параметр порога имеет ОписаниеТипов("Число", КвалификаторыЧисла(1,0,Неотрицательный)): только целые 0..9 по описанию, а правила этого опыта допускают лишь 0, 1, 3. Квалификатор передан явно: native запрещает хранить числа в ОписаниеТипов без него. Это наш узкий учебный тип, не универсальный тип количества.

  8. Собственные четыре выбранных поля: Наименование, Количество, Цена, Сумма. Структура содержит только одну используемую группировку без полей группировки, с АвтоВыбраннымПолем: это детальные записи. Единственный ресурс Сумма вычисляется выражением Сумма(Сумма); в его массив Группировки добавлено документированное значение ОбщийИтог. Вложенных группировок и промежуточных итогов нет. Штатное размещение самого итога не считается заранее подтверждённым.

  9. Полный отдельный модуль УчебныеОтчетыФорм85 вставьте в Общие → Общие модули → УчебныеОтчетыФорм85 → Модуль. Включите Сервер, выключите Клиент, Глобальный и Вызов сервера. Экспортные функции вызываются только из серверных обработчиков собственной формы.

  10. Контракт СОБСТВЕННОГО вывода является условием будущего ручного опыта, не обещанием native авторазметки: одна строка с уникальными подписями Наименование, Количество, Цена, Сумма; далее полные детальные строки; один общий итог для непустого набора; вне найденных четырёх колонок нет данных. Максимум 200 строк и 40 колонок — защитная граница нашего reader, не предел платформы.

  11. Числовые ячейки количества, цены, суммы и непустого общего итога должны иметь СодержитЗначение=Истина и Значение типа Число. Reader не устанавливает эти свойства, не исправляет результат и никогда не преобразует текст 750/50/800 в числа. При нарушении условия он выдаёт диагностику, КонтрольПрошел остаётся Ложь.

  12. Сверка читает actual параметр Результат нового события ПослеКомпоновкиРезультата ДО помещения в реквизит. При опыте с режимами второй источник — actual реквизит формы Результат ПОСЛЕ преобразования. Ни исходный запрос, ни повторное вычисление суммы не подменяют эти источники.

  13. В каждой собственной форме создайте дополнительные реквизиты СостояниеУрока и ОтпечатокДоПомещения типа Строка неограниченной длины, КонтрольПрошел типа Булево, ПорогПриКомпоновке и СобытийДо, СобытийПосле, СобытийИзменения типа Число длиной 6, точность 0, неотрицательный.

  14. Для наблюдения создайте поля ПолеСостояния, ПолеКонтроля, ПолеПорога, ПолеСобытийДо, ПолеСобытийПосле, ПолеСобытийИзменения с путями к одноимённым подготовленным реквизитам СостояниеУрока, КонтрольПрошел, ПорогПриКомпоновке, СобытийДо, СобытийПосле, СобытийИзменения. Всем установите ТолькоПросмотр=Истина. Поле отпечатка необязательно: реквизит смотрите в отладчике.

  15. Назначьте в свойствах событий ФОРМЫ ПриСозданииНаСервере → ПриСозданииНаСервере, ПриКомпоновкеРезультата → ПриКомпоновкеРезультата, ПослеКомпоновкиРезультата → ПослеКомпоновкиРезультата, ПриИзмененииНастроек → ПриИзмененииНастроек. Полные сигнатуры уже в модуле. Не назначайте трёхпараметрическое одноимённое событие модуля объекта отчёта.

  16. АвтоматическоеСохранениеДанныхВНастройках собственной формы оставьте НеИспользовать. Не вызывайте сохранение вариантов, настроек, документа, печать или запись данных. Платформа всё же может читать/сохранять системные настройки отчётной формы: новый пользователь и новая база изолируют опыт, но это НЕ обещание отсутствия внутренних операций.

  17. В Отчёты → УчебныеТовары85 → Формы создайте управляемую форму отчёта УчебныеРежимы85 (тип формы Отчёта, Основная). В конструкторе выберите стандартную форму отчёта, не общую форму. Основной реквизит Отчет должен иметь тип ОтчетОбъект.УчебныеТовары85 и признак Основной.

  18. Проверьте созданные конструктором реквизит Результат типа ТабличныйДокумент и поле табличного документа с ПутьКДанным=Результат; явно назовите это собственное поле ПолеРезультата. Стандартная команда Сформировать должна иметь штатный результат. Если конструктор дал иные имена, исправьте подготовку на указанные, не добавляйте второй результат и не угадывайте имя.

  19. Полный основной блок вставьте целиком в Отчёты → УчебныеТовары85 → Формы → УчебныеРежимы85 → Модуль формы. Замените только исходный пустой/сгенерированный модуль СВОЕЙ новой учебной формы; никакие модули рабочего отчёта не меняйте.

  20. Создайте команды формы НачатьОпыт, ОбычныйВид, КомпактныйВид, ВосстановитьИсходныйРежим; каждой назначьте одноимённый обработчик из полного модуля и отдельную кнопку. Разместите их вне ПолеРезультата. Стандартные команды сохранения/печати в опыте не используйте.

  21. Полный отдельный модуль запуска ОткрытьУчебныеРежимы85 вставьте в Общие → Общие команды → ОткрытьУчебныеРежимы85 → Модуль команды. Команду без параметра разместите в командном интерфейсе собственного учебного приложения. Каждый запуск передаёт свежий UUID ключа уникальности и не должен случайно переиспользовать предыдущий экземпляр.

  22. Не создавайте редактируемых элементов пользовательских настроек в форме УчебныеРежимы85: порог остаётся 0. Не меняйте параметры/вариант в ходе сравнения режима. Используйте отдельный экземпляр формы, не форму порога.

  23. Все обращения к enum РежимОтображенияРезультатаОтчета и методам смены/чтения режима стоят в клиентских процедурах толстого управляемого приложения. Исходные enum хранятся в переменных клиентского модуля, не в неподтверждённых сериализуемых реквизитах формы.

  24. Команда ВосстановитьИсходныйРежим доступна и после отказа reader: она не зависит от БазовыйОтпечаток. До закрытия собственной формы выполните её и запишите реальные значения обоих getters. Не объявляйте профиль восстановленным при диагностике.

  25. Методы чтения учитывают настройки системного хранилища. Исходное значение может быть Авто: не подменяйте его Обычный. Новый пользователь/база изолируют этот системный профиль; отсутствие явно вызванного сохранения не доказывает отсутствие внутренних сохранений.

Перем ИсходныйПредпочтительныйРежим;
Перем ИсходныйДействующийРежим;
Перем ИсходныйРежимЗафиксирован;
Перем БазовыйОтпечаток;

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ЭтаФорма.ТипФормыОтчета <> ТипФормыОтчета.Основная Тогда
    Отказ = Истина;
    ВызватьИсключение "Подготовьте именно управляемую форму отчёта Основная";
КонецЕсли;
ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
Схема = УчебныеОтчетыФорм85.СоздатьСхему();
ОбъектОтчета.СхемаКомпоновкиДанных = Схема;
ОбъектОтчета.КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема));
ОбъектОтчета.КомпоновщикНастроек.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
ЭтаФорма.ЗначениеВРеквизитФормы(ОбъектОтчета, "Отчет");
ЭтаФорма.ПорогПриКомпоновке = 0;
ЭтаФорма.СобытийДо = 0;
ЭтаФорма.СобытийПосле = 0;
ЭтаФорма.СобытийИзменения = 0;
ЭтаФорма.КонтрольПрошел = Ложь;
ЭтаФорма.ОтпечатокДоПомещения = "";
ЭтаФорма.СостояниеУрока = "Собственная схема готова. Контракт штатного вывода ещё не подтверждён";

КонецПроцедуры

&НаСервере
Процедура ПриКомпоновкеРезультата(СтандартнаяОбработка)
СтандартнаяОбработка = Истина;
ЭтаФорма.КонтрольПрошел = Ложь;
ЭтаФорма.ОтпечатокДоПомещения = "";
ОбъектОтчета = ЭтаФорма.РеквизитФормыВЗначение("Отчет");
РабочиеНастройки = ОбъектОтчета.КомпоновщикНастроек.ПолучитьНастройки();
ПараметрНастроек = РабочиеНастройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("МинимальноеКоличество"));
Если ПараметрНастроек = Неопределено Тогда
    ВызватьИсключение "В фактических настройках нет собственного параметра";
КонецЕсли;
Если Не ПараметрНастроек.Использование Или ТипЗнч(ПараметрНастроек.Значение) <> Тип("Число") Тогда
    ВызватьИсключение "Собственный числовой параметр должен использоваться";
КонецЕсли;
Порог = ПараметрНастроек.Значение;
Если Порог <> 0 И Порог <> 1 И Порог <> 3 Тогда
    ВызватьИсключение "Завершите ввод одного из учебных порогов 0, 1, 3";
КонецЕсли;
ЭтаФорма.ПорогПриКомпоновке = Порог;
ЭтаФорма.СобытийДо = ЭтаФорма.СобытийДо + 1;
КонецПроцедуры

&НаСервере
Процедура ПослеКомпоновкиРезультата(Результат, СтандартнаяОбработка)
СтандартнаяОбработка = Истина;
ЭтаФорма.СобытийПосле = ЭтаФорма.СобытийПосле + 1;
ЭтаФорма.КонтрольПрошел = Ложь;
Попытка
    Прочитанное = УчебныеОтчетыФорм85.ПрочитатьПлоскийРезультат(Результат);
    ЭтаФорма.ОтпечатокДоПомещения = УчебныеОтчетыФорм85.ПроверитьСоставИПолучитьОтпечаток(Прочитанное, ЭтаФорма.ПорогПриКомпоновке);
    ЭтаФорма.КонтрольПрошел = Истина;
    ЭтаФорма.СостояниеУрока = СтрШаблон("Прочитан фактический параметр события: порог %1; детали %2. %3",
        ЭтаФорма.ПорогПриКомпоновке, Прочитанное.Детали.Количество(), Прочитанное.НаблюдениеИтога);
Исключение
    ЭтаФорма.ОтпечатокДоПомещения = "";
    ЭтаФорма.СостояниеУрока = "Контракт фактического вывода не подтверждён: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура ПриИзмененииНастроек(СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ЭтаФорма.СобытийИзменения = ЭтаФорма.СобытийИзменения + 1;
ЭтаФорма.КонтрольПрошел = Ложь;
ЭтаФорма.СостояниеУрока = "Настройки изменены. Завершите ввод и явно сформируйте новый результат";
КонецПроцедуры

&НаСервере
Функция ПрочитатьФактическийРеквизитРезультат()
Если Не ЭтаФорма.КонтрольПрошел Тогда
    ВызватьИсключение "Сначала нужен проверенный результат штатной компоновки";
КонецЕсли;
ФактическийДокумент = ЭтаФорма.Результат;
Прочитанное = УчебныеОтчетыФорм85.ПрочитатьПлоскийРезультат(ФактическийДокумент);
Возврат УчебныеОтчетыФорм85.ПроверитьСоставИПолучитьОтпечаток(Прочитанное, ЭтаФорма.ПорогПриКомпоновке);
КонецФункции

&НаКлиенте
Процедура НачатьОпыт(Команда)
Если ИсходныйРежимЗафиксирован <> Истина Тогда
    ИсходныйПредпочтительныйРежим = ЭтаФорма.ПолучитьРежимОтображенияРезультата();
    ИсходныйДействующийРежим = ЭтаФорма.ПолучитьТекущийРежимОтображенияРезультата();
    ИсходныйРежимЗафиксирован = Истина;
КонецЕсли;
БазовыйОтпечаток = "";
ЭтаФорма.СкомпоноватьРезультат(РежимКомпоновкиРезультата.Непосредственно);
Если Не ЭтаФорма.КонтрольПрошел Тогда
    Сообщить(ЭтаФорма.СостояниеУрока);
    Возврат;
КонецЕсли;
Попытка
    БазовыйОтпечаток = ПрочитатьФактическийРеквизитРезультат();
    ЭтаФорма.СостояниеУрока = СтрШаблон("Исходные режимы: настройка %1; действующий %2. Фактический реквизит прочитан",
        ИсходныйПредпочтительныйРежим, ИсходныйДействующийРежим);
Исключение
    ЭтаФорма.СостояниеУрока = "Нет проверенного реквизита результата: " + ОписаниеОшибки();
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры

&НаКлиенте
Процедура ОбычныйВид(Команда)
УстановитьИПроверитьВид(РежимОтображенияРезультатаОтчета.Обычный);
КонецПроцедуры

&НаКлиенте
Процедура КомпактныйВид(Команда)
УстановитьИПроверитьВид(РежимОтображенияРезультатаОтчета.Компактный);
КонецПроцедуры

&НаКлиенте
Процедура УстановитьИПроверитьВид(ЗапрошенныйРежим)
Если ИсходныйРежимЗафиксирован <> Истина Или БазовыйОтпечаток = "" Тогда
    Сообщить("Сначала выполните НачатьОпыт; после диагностики не продолжайте сравнение");
    Возврат;
КонецЕсли;
Попытка
    ДоПереключения = ПрочитатьФактическийРеквизитРезультат();
    Если ДоПереключения <> БазовыйОтпечаток Тогда
        ВызватьИсключение "Фактический исходный результат уже изменён";
    КонецЕсли;
    ЭтаФорма.УстановитьРежимОтображенияРезультата(ЗапрошенныйРежим);
    Настроенный = ЭтаФорма.ПолучитьРежимОтображенияРезультата();
    Действующий = ЭтаФорма.ПолучитьТекущийРежимОтображенияРезультата();
    Если Настроенный <> ЗапрошенныйРежим Или Действующий <> ЗапрошенныйРежим Тогда
        ВызватьИсключение "Настроенный или действующий режим не совпал с явно запрошенным";
    КонецЕсли;
    ПослеПереключения = ПрочитатьФактическийРеквизитРезультат();
    Если ПослеПереключения <> ДоПереключения Тогда
        ВызватьИсключение "Состав фактического преобразованного реквизита изменился";
    КонецЕсли;
    ЭтаФорма.СостояниеУрока = СтрШаблон("Проверен режим %1 и фактический реквизит после преобразования. Внешний вид проверьте вручную", Действующий);
Исключение
    БазовыйОтпечаток = "";
    ЭтаФорма.СостояниеУрока = "Сравнение режима остановлено: " + ОписаниеОшибки();
    Попытка
        ЭтаФорма.УстановитьРежимОтображенияРезультата(ИсходныйПредпочтительныйРежим);
        ЭтаФорма.СостояниеУрока = ЭтаФорма.СостояниеУрока + СтрШаблон(". После попытки восстановления: настройка %1; действующий %2",
            ЭтаФорма.ПолучитьРежимОтображенияРезультата(), ЭтаФорма.ПолучитьТекущийРежимОтображенияРезультата());
    Исключение
        ЭтаФорма.СостояниеУрока = ЭтаФорма.СостояниеУрока + ". Восстановление не выполнено: " + ОписаниеОшибки();
    КонецПопытки;
КонецПопытки;
Сообщить(ЭтаФорма.СостояниеУрока);
КонецПроцедуры

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

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

Полный отдельный серверный общий модуль УчебныеОтчетыФорм85. Только собственная учебная база и толстый управляемый desktop-клиент 8.5.1.1343; фактический запуск 1С не выполнен.

Функция СоздатьСхему() Экспорт
Схема = Новый СхемаКомпоновкиДанных;
Источник = Схема.ИсточникиДанных.Добавить();
Источник.Имя = "УчебныйИсточник";
Источник.ТипИсточникаДанных = "Local";
Набор = Схема.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
Набор.Имя = "УчебныеТовары";
Набор.ИсточникДанных = Источник.Имя;
Набор.АвтоЗаполнениеДоступныхПолей = Истина;
Набор.Запрос = "ВЫБРАТЬ
|    ""Книга"" КАК Наименование,
|    3 КАК Количество,
|    250 КАК Цена,
|    750 КАК Сумма
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ ""Ручка"", 1, 50, 50";
Настройки = Схема.НастройкиПоУмолчанию;
Для Каждого ИмяПоля Из СтрРазделить("Наименование,Количество,Цена,Сумма", ",") Цикл
    Выбранное = Настройки.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    Выбранное.Поле = Новый ПолеКомпоновкиДанных(ИмяПоля);
    Выбранное.Использование = Истина;
КонецЦикла;
Детали = Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
Детали.Использование = Истина;
АвтоВыбор = Детали.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
АвтоВыбор.Использование = Истина;
Набор.Запрос = "ВЫБРАТЬ Товары.Наименование, Товары.Количество, Товары.Цена, Товары.Сумма
|ИЗ (
|ВЫБРАТЬ
|    ""Книга"" КАК Наименование,
|    3 КАК Количество,
|    250 КАК Цена,
|    750 КАК Сумма
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ ""Ручка"", 1, 50, 50
|) КАК Товары
|ГДЕ Товары.Количество > &МинимальноеКоличество";
Порог = Схема.Параметры.Добавить();
Порог.Имя = "МинимальноеКоличество";
Порог.Заголовок = "Количество больше";
Порог.ТипЗначения = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(1, 0, ДопустимыйЗнак.Неотрицательный));
Порог.Значение = 0;
Порог.Использование = ИспользованиеПараметраКомпоновкиДанных.Всегда;
Порог.ЗапрещатьНезаполненныеЗначения = Ложь;
Порог.ДоступенСписокЗначений = Ложь;
Порог.ОграничениеИспользования = Ложь;
Порог.ВключатьВДоступныеПоля = Ложь;
Итог = Схема.ПоляИтога.Добавить();
Итог.ПутьКДанным = "Сумма";
Итог.Выражение = "Сумма(Сумма)";
Итог.Группировки.Добавить("ОбщийИтог");
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("МинимальноеКоличество", 0);
ПараметрНастроек = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("МинимальноеКоличество"));
Если ПараметрНастроек = Неопределено Тогда
    ВызватьИсключение "Собственная схема не создала параметр порога";
КонецЕсли;
ПараметрНастроек.Использование = Истина;
ПараметрНастроек.ИдентификаторПользовательскойНастройки = "УчебныйПорог";
ПараметрНастроек.ПредставлениеПользовательскойНастройки = "Количество больше";
Возврат Схема;
КонецФункции

Функция ПрочитатьЯчейку(Документ, НомерСтроки, НомерКолонки)
Ячейка = Документ.Область(НомерСтроки, НомерКолонки);
Содержит = Ячейка.СодержитЗначение;
ЗначениеЯчейки = Неопределено;
Если Содержит Тогда
    ЗначениеЯчейки = Ячейка.Значение;
КонецЕсли;
Возврат Новый Структура("Текст,Содержит,Значение", СокрЛП(Строка(Ячейка.Текст)), Содержит, ЗначениеЯчейки);
КонецФункции

Функция ЯчейкаПуста(Ячейка)
Возврат Ячейка.Текст = "" И (Не Ячейка.Содержит Или Ячейка.Значение = Неопределено);
КонецФункции

Функция ЧислоЯчейки(Ячейка, ИмяПоля)
Если Не Ячейка.Содержит Тогда
    ВызватьИсключение "Нет типизированного значения поля " + ИмяПоля;
КонецЕсли;
Если ТипЗнч(Ячейка.Значение) <> Тип("Число") Тогда
    ВызватьИсключение "Тип значения поля " + ИмяПоля + " не Число";
КонецЕсли;
Возврат Ячейка.Значение;
КонецФункции

Функция ПрочитатьПлоскийРезультат(Документ) Экспорт
Если ТипЗнч(Документ) <> Тип("ТабличныйДокумент") Тогда
    ВызватьИсключение "Ожидался фактический ТабличныйДокумент";
КонецЕсли;
Высота = Документ.ВысотаТаблицы;
Ширина = Документ.ШиринаТаблицы;
Если Высота = 0 Или Ширина = 0 Или Высота > 200 Или Ширина > 40 Тогда
    ВызватьИсключение "Вывод вне ограниченного собственного плоского контракта 200 на 40";
КонецЕсли;
Заголовки = СтрРазделить("Наименование,Количество,Цена,Сумма", ",");
Колонки = Неопределено;
СтрокаЗаголовков = 0;
Для НомерСтроки = 1 По Высота Цикл
    Найденные = Новый Структура;
    Для НомерКолонки = 1 По Ширина Цикл
        Ячейка = ПрочитатьЯчейку(Документ, НомерСтроки, НомерКолонки);
        Если Заголовки.Найти(Ячейка.Текст) <> Неопределено Тогда
            Если Найденные.Свойство(Ячейка.Текст) Тогда
                ВызватьИсключение "Повтор заголовка в одной строке: " + Ячейка.Текст;
            КонецЕсли;
            Найденные.Вставить(Ячейка.Текст, НомерКолонки);
        КонецЕсли;
    КонецЦикла;
    Если Найденные.Количество() = 4 Тогда
        Если Колонки <> Неопределено Тогда
            ВызватьИсключение "Несколько полных строк заголовков: вывод неоднозначен";
        КонецЕсли;
        Колонки = Найденные;
        СтрокаЗаголовков = НомерСтроки;
    ИначеЕсли Найденные.Количество() <> 0 Тогда
        ВызватьИсключение "Неполная строка собственных заголовков";
    КонецЕсли;
КонецЦикла;
Если Колонки = Неопределено Тогда
    ВызватьИсключение "Четыре собственных заголовка не найдены в одной строке";
КонецЕсли;
Детали = Новый Массив;
ИтогПрочитан = Ложь;
КандидатовИтога = 0;
ЗначениеИтога = Неопределено;
НаблюдениеИтога = "В колонке Сумма отдельная строка итога не обнаружена";
Для НомерСтроки = 1 По Высота Цикл
    Для НомерКолонки = 1 По Ширина Цикл
        Если НомерКолонки = Колонки.Наименование Или НомерКолонки = Колонки.Количество
            Или НомерКолонки = Колонки.Цена Или НомерКолонки = Колонки.Сумма Тогда
            Продолжить;
        КонецЕсли;
        ВнешняяЯчейка = ПрочитатьЯчейку(Документ, НомерСтроки, НомерКолонки);
        Если Не ЯчейкаПуста(ВнешняяЯчейка) Тогда
            ВызватьИсключение "Есть данные вне четырёх найденных колонок";
        КонецЕсли;
    КонецЦикла;
    Если НомерСтроки = СтрокаЗаголовков Тогда
        Продолжить;
    КонецЕсли;
    Имя = ПрочитатьЯчейку(Документ, НомерСтроки, Колонки.Наименование);
    Количество = ПрочитатьЯчейку(Документ, НомерСтроки, Колонки.Количество);
    Цена = ПрочитатьЯчейку(Документ, НомерСтроки, Колонки.Цена);
    Сумма = ПрочитатьЯчейку(Документ, НомерСтроки, Колонки.Сумма);
    Если Не ЯчейкаПуста(Количество) Или Не ЯчейкаПуста(Цена) Тогда
        Если Имя.Текст = "" Тогда
            ВызватьИсключение "Детальная строка без наименования";
        КонецЕсли;
        Если НомерСтроки < СтрокаЗаголовков Тогда
            ВызватьИсключение "Детальные данные расположены перед заголовками";
        КонецЕсли;
        Детали.Добавить(Новый Структура("Наименование,Количество,Цена,Сумма", Имя.Текст,
            ЧислоЯчейки(Количество, "Количество"), ЧислоЯчейки(Цена, "Цена"), ЧислоЯчейки(Сумма, "Сумма")));
    Иначе
        Если Имя.Текст <> "" И Имя.Текст <> "Итого" И Имя.Текст <> "Общий итог" И Имя.Текст <> "Всего" Тогда
            ВызватьИсключение "Неполная детальная строка или неизвестная подпись: " + Имя.Текст;
        КонецЕсли;
        Если Не ЯчейкаПуста(Сумма) Или Имя.Текст <> "" Тогда
            КандидатовИтога = КандидатовИтога + 1;
            Если КандидатовИтога > 1 Тогда
                ВызватьИсключение "Несколько итогов без деталей: вывод неоднозначен";
            КонецЕсли;
        КонецЕсли;
        Если Не ЯчейкаПуста(Сумма) Тогда
            ЗначениеИтога = ЧислоЯчейки(Сумма, "общий итог Сумма");
            ИтогПрочитан = Истина;
            НаблюдениеИтога = "Фактический типизированный итог: " + Строка(ЗначениеИтога);
        ИначеЕсли Имя.Текст <> "" Тогда
            НаблюдениеИтога = "Фактическая подпись " + Имя.Текст + ": ячейка Сумма пуста";
        КонецЕсли;
    КонецЕсли;
КонецЦикла;
Возврат Новый Структура("Детали,ЕстьИтог,Итог,НаблюдениеИтога", Детали, ИтогПрочитан, ЗначениеИтога, НаблюдениеИтога);
КонецФункции

Функция ПроверитьСоставИПолучитьОтпечаток(Прочитанное, Порог) Экспорт
Если ТипЗнч(Порог) <> Тип("Число") Тогда
    ВызватьИсключение "Фактический порог не Число";
КонецЕсли;
Если Порог <> 0 И Порог <> 1 И Порог <> 3 Тогда
    ВызватьИсключение "В этом опыте допустимы только пороги 0, 1, 3";
КонецЕсли;
КоличествоОжидается = 0;
Если Порог = 0 Тогда
    КоличествоОжидается = 2;
ИначеЕсли Порог = 1 Тогда
    КоличествоОжидается = 1;
КонецЕсли;
Если Прочитанное.Детали.Количество() <> КоличествоОжидается Тогда
    ВызватьИсключение "Фактическое число детальных строк отличается от собственного набора";
КонецЕсли;
Книга = "";
Ручка = "";
Для Каждого Деталь Из Прочитанное.Детали Цикл
    Если Деталь.Наименование = "Книга" Тогда
        Если Книга <> "" Или Деталь.Количество <> 3 Или Деталь.Цена <> 250 Или Деталь.Сумма <> 750 Тогда
            ВызватьИсключение "Неверная или повторная фактическая строка Книга";
        КонецЕсли;
        Книга = СтрШаблон("Книга;%1;%2;%3", Деталь.Количество, Деталь.Цена, Деталь.Сумма);
    ИначеЕсли Деталь.Наименование = "Ручка" Тогда
        Если Ручка <> "" Или Порог <> 0 Или Деталь.Количество <> 1 Или Деталь.Цена <> 50 Или Деталь.Сумма <> 50 Тогда
            ВызватьИсключение "Неверная, повторная или лишняя фактическая строка Ручка";
        КонецЕсли;
        Ручка = СтрШаблон("Ручка;%1;%2;%3", Деталь.Количество, Деталь.Цена, Деталь.Сумма);
    Иначе
        ВызватьИсключение "Неизвестная фактическая детальная строка";
    КонецЕсли;
КонецЦикла;
Если Порог < 3 И Книга = "" Тогда
    ВызватьИсключение "В фактическом результате отсутствует Книга";
КонецЕсли;
Если Порог = 0 И Ручка = "" Тогда
    ВызватьИсключение "В фактическом результате отсутствует Ручка";
КонецЕсли;
Если Порог < 3 Тогда
    Если Не Прочитанное.ЕстьИтог Тогда
        ВызватьИсключение "Нет отдельного типизированного общего итога";
    КонецЕсли;
    Если (Порог = 0 И Прочитанное.Итог <> 800) Или (Порог = 1 И Прочитанное.Итог <> 750) Тогда
        ВызватьИсключение "Фактический общий итог отличается от собственного набора";
    КонецЕсли;
КонецЕсли;
Возврат СтрШаблон("%1|%2|итог:%3:%4|%5", Книга, Ручка,
    Прочитанное.ЕстьИтог, Строка(Прочитанное.Итог), Прочитанное.НаблюдениеИтога);
КонецФункции
ОткрытьУчебныеРежимы85

Общие → Общие команды → ОткрытьУчебныеРежимы85 → Модуль команды

Полный отдельный клиентский модуль общей команды запуска именно собственной подготовленной формы отчёта, толстый управляемый desktop-клиент 8.5.1.1343.

&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
ОткрытьФорму("Отчет.УчебныеТовары85.Форма.УчебныеРежимы85", , , "owned-report-" + Строка(Новый УникальныйИдентификатор));
КонецПроцедуры

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

  1. Откройте ОткрытьУчебныеРежимы85 и нажмите НачатьОпыт. До первого изменения режима клиент фиксирует фактическую настройку ПолучитьРежимОтображенияРезультата и фактически использованный ПолучитьТекущийРежимОтображенияРезультата.

  2. Выполняется штатная компоновка собственного набора с порогом 0. Сначала событие проверяет actual параметр до помещения; затем серверная функция отдельно читает actual реквизит формы Результат после помещения/возможного компактного преобразования.

  3. Если исходный преобразованный реквизит не соответствует строгому typed плоскому контракту, БазовыйОтпечаток остаётся пустым и команды сравнения не продолжают опыт. При этом исходные режимы сохранены для отдельной команды восстановления.

  4. Нажмите ОбычныйВид. Сначала actual реквизит повторно сверяется с базовым отпечатком, затем setter задаёт явно Обычный; оба getters сравниваются с запросом, после чего заново читаются actual ячейки преобразованного реквизита.

  5. Нажмите КомпактныйВид. Те же проверки выполняются для Компактный. Изменение координат само по себе не ошибка: reader вновь находит заголовки. Отсутствие единого плоского вывода после компактного преобразования является отказом, не поводом читать старый документ.

  6. Визуально исследуйте различия обычного/компактного вида только если реальный клиент применил их. Значения enum/getters и статические тесты не доказывают расположение, переносы или внешний вид.

  7. Нажмите ВосстановитьИсходныйРежим. В setter передаётся сохранённая исходная настройка, включая Авто, если это было реальное исходное. Настроенный и действующий getters сверяются со своими исходными снимками.

  8. При сохранённом пригодном базовом отпечатке повторно прочитайте actual реквизит после восстановления. При отказе переключения/reader код пробует вернуть исходную настройку, показывает фактические getters и не заявляет успешное сравнение.

  9. Не перезаписывайте исходный снимок повторным НачатьОпыт. Если действующий режим после возврата настройки отличается от первоначального, фиксируйте диагностику, а не подставляйте ожидаемое значение.

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

  1. ИсходныйПредпочтительныйРежим и ИсходныйДействующийРежим фиксируются реальными getters до первого setter и не заменяются константами.

  2. Для каждого явно выбранного режима обе проверки getters должны совпасть с запросом; затем полный actual состав Книга/Ручка и отдельный typed итог 800 должны совпасть до/после, иначе нет положительного результата.

  3. После setter источник — ЭтаФорма.Результат в серверной функции, не ОтпечатокДоПомещения и не старый аргумент события. Координаты не фиксированы.

  4. После возврата совпадают сохранённая настройка и сохранённый действующий режим. Восстановление данных подтверждается отдельно только если reader пригоден.

  5. При диагностике БазовыйОтпечаток очищается и последующие кнопки сравнения прекращают действие; кнопка восстановления остаётся работоспособной.

  6. Компактный вывод может нарушить собственный плоский контракт. Это ожидаемая допустимая диагностика ручного опыта, не доказанный runtime-дефект платформы и не успешная проверка.

  7. Изменение внешнего вида и реальные системные сохранения статически не проверены. Не называйте этот тест доказательством отсутствия системного сохранения профиля.

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

Подготовлен условный опыт реального преобразования отображаемого отчёта, строгой сверки actual реквизита и возврата фактически исходного режима; визуальный/runtime результат ещё не подтверждён.

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

  1. Запуск в 1С не подтверждён. Native API-контракты и статические тесты не доказывают, что стандартный генератор даст наш плоский контракт вывода; это обязательная будущая ручная проверка, а не безусловный успешный результат.

  2. При отсутствии уникальных заголовков, полном повторе заголовков, частичной строке, лишних колонках, нескольких итогах или отсутствии typed values reader отказывает. Не удаляйте диагностику ради зелёного сообщения и не преобразуйте текст числа в ожидаемый результат.

  3. Суммы 750/50/800 в проверке — известный контроль собственного константного набора, но сравниваемая сторона прочитана из фактического документа. Независимый BSL-расчёт 3*250+1*50 не подтверждает сформированный отчёт.

  4. Отказ от СтандартнойОбработки в ПослеКомпоновкиРезультата не отменяет действие, а отключает автоматическое компактное преобразование. Урок оставляет Истина; события и реквизит читаются в разные моменты.

  5. Все уроки ограничены толстым управляемым desktop-клиентом: узкая доступность enum режима не расширяется более широкими контекстами методов.

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

  7. Авто — настройка выбора, не обязательно фактически применённый вид. Не приравнивайте оба getters и не назначайте readonly устаревшее свойство РежимОтображенияРезультата.

  8. Восстановление предпочтительной настройки не гарантирует прежний действующий режим при изменённых условиях. Код проверяет оба и сообщает несовпадение; исходное действующее значение не используется как замена исходной настройки.

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

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

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

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

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