Универсальный отчет в 1С сломался: исправляем ошибку
Однажды после обновления конфигурации 1С на проекте заказчика сломался вариант Универсального отчета. Сильно сломался — вообще не открывается, падает с ошибкой, нет возможности сбросить в стандартные настройки.
Поделюсь своим способом починки отчета. Сразу отмечу, что не претендую на самый верный вариант танцев с бубном при такой ошибке, но именно так мне удалось справится с задачей.
Contents
Ситуация: что-то пошло не так
При обновлении релиза может сломаться действительно всё что угодно. В нашем случае сломались именно настройки варианта Универсального отчета. Они хранятся в хранилище значения (далее ХЗ) в реквизите «Настройки», а сам вариант хранится в справочнике «ВариантыОтчетов».
Хранятся настройки в виде НастройкаКомпоновкиДанных
, и более глубинно так или иначе представляют из себя XML данные. Это были мои первые мысли при виде текста ошибки, которую мне прислали:
Первые попытки найти ошибку
Включаем остановку по ошибке, пробуем открыть проблемный вариант отчета. Попадаем в ХранилищаНастроек.ХранилищеВариантовОтчетов.ОбработкаЗагрузки
.
Именно тут возникает первая ошибка — при чтении настроек компоновки данных. А точнее — при получении их из хранилища настроек и последующем преобразовании хранимых XML данных в объект с типом НастройкиКомпоновкиДанных
.
Ошибку нашли, думаем как исправить
Из текста ошибки ясно, что хранимая в ХЗ XML содержит ссылку на тип Перечисление.ВидыСтраховыхВзносовИП
, но текущая конфигурация такого типа не содержит, она содержит УдалитьВидыСтраховыхВзносовИП
:
В этом и ошибка! Получается нам нужно в хранимой XML подменить ВидыСтраховыхВзносовИП
на УдалитьВидыСтраховыхВзносовИП
. Как это сделать? Сейчас поделюсь своим вариантом танцев с бубнами.
Итак, сильно не оглядываясь в цикличную структуру кода, поскольку мне нужно будет чинить не один вариант Универсального отчета, сконцентрируемся на процедуре исправления единичного варианта.
Для начала нужно получить само значение из хранилища, получив ссылку на вариант отчета простейшим запросом. Или даже можно просто из реквизита внешней обработки, которую я и написал для исправления:
Далее приложу код и опишу его поэтапно:
//Настройки = Выборка.Настройки.Получить();
ХЗСтрокой = ЗначениеВСтрокуВнутр(Выборка.Настройки);
//Вычленяем Base64 зашифрованный XML
//Не пойму формат, XML нет, JSON нет
МассивСтрок = СтрРазделить(ХЗСтрокой, ",", Ложь);
СтрокаBase64 = МассивСтрок[2];
//Отсекаем лишнее
СтрокаBase64 = СтрЗаменить(СтрокаBase64, "
|{#base64:", "");
СтрокаBase64 = СтрЗаменить(СтрокаBase64, "}
|}", "");
ДвоичныеДанныеНастроекОтчета = Base64Значение(СтрокаBase64);
ЧтениеДвоичныхДанных = Новый ЧтениеДанных(ДвоичныеДанныеНастроекОтчета);
XMLОтчета = ЧтениеДвоичныхДанных.ПрочитатьСимволы();
ЧтениеДвоичныхДанных.Закрыть();
//Чиним отчет при необходимости
КорректныеНастройкиСтрокой = ПочинитьВариантОтчета(Выборка.Ссылка, XMLОтчета);
Если КорректныеНастройкиСтрокой = Неопределено Тогда
//Нет необходимости, но проверим открвыается ли он вообще
Настройки = Выборка.Настройки.Получить();
Продолжить;
КонецЕсли;
//Сформируем новые настройки
Чтение = Новый ЧтениеXML();
Чтение.УстановитьСтроку(Прав(КорректныеНастройкиСтрокой, СтрДлина(КорректныеНастройкиСтрокой) - СтрНайти(КорректныеНастройкиСтрокой, "<?xml")+1));
НастройкиКД = СериализаторXDTO.ПрочитатьXML(Чтение);
ОтчетОбъект = Выборка.Ссылка.ПолучитьОбъект();
ОтчетОбъект.Настройки = Новый ХранилищеЗначения(НастройкиКД);
ОтчетОбъект.Записать();
Помним, что Настройки.Получить()
не прокатит, нам нужно именно строковое представление на максимально низком уровне, чтобы 1С не пыталась все эти данные преобразовать в значение из XML — ведь именно на этом моменте выходит ошибка.
Для обхода используем ЗначениеВСтрокуВнутр()
, передав в параметр настройки.
Получим белиберду в виде строки, но не стоит её пугаться, это всего лишь значение Base64 в виде строки, дополненное структурой хранилища значения:
Даже в самой строке есть подсказка, что это именно Base64
. Вычленяем нужную нам часть именно строкового значения Base64
и преобразуем в двоичные данные с помощью функции Base64Значение()
.
Полученные двоичные данные нужно преобразовать в строку, ведь преобразовать в XML мы всё ещё не можем, выйдет ошибка. Используем ЧтениеДвоичныхДанных
, получаем строку, мы уже совсем близко!
На этом этапе уже вполне можно производить замены строк на нужные, опять же не обращая внимание на попытки к универсализации процедур. Смотрим, что для этого достаточно использовать функцию СтрЗаменить()
:
КорректныеНастройкиСтрокой = СтрЗаменить(НастройкиСтрокой, "ВидыСтраховыхВзносовИП", "УдалитьВидыСтраховыхВзносовИП");
Заменяем некорректное на корректное и бежим дальше, осталось всего ничего.
Далее нужно избавиться от непонятной вставки, иначе это нам не позволит преобразовать исправленную строку в XML. С помощью ЧтениеXML
и СериализаторXDTO
читаем нашу XML строку и… О чудо, получаем НастройкиКомпоновкиДанных
!
Осталось просто записать эти настройки в хранилище значения и записать объект отчета, всё! Готово, вариант исправлен и корректно открывается.
Конечно, в моём случае исправление было довольно простым. Не спорю, что момент с использованием функции СтрЗаменить может подойти не всем, всё очень сильно зависит от причины ошибки при чтении XML, но суть исправления ясна.
Comments
So empty here ... leave a comment!