Top.Mail.Ru
26 февраля в 17:00 МСК
онлайн-митап
Как мы перенесли игру «Герои меча и магии 3» на 1С

Универсальный отчет в 1С сломался: исправляем ошибку

Однажды после обновления конфигурации 1С на проекте заказчика сломался вариант Универсального отчета. Сильно сломался — вообще не открывается, падает с ошибкой, нет возможности сбросить в стандартные настройки.

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

Ситуация: что-то пошло не так

При обновлении релиза может сломаться действительно всё что угодно. В нашем случае сломались именно настройки варианта Универсального отчета. Они хранятся в хранилище значения (далее ХЗ) в реквизите «Настройки», а сам вариант хранится в справочнике «ВариантыОтчетов».

Хранятся настройки в виде НастройкаКомпоновкиДанных, и более глубинно так или иначе представляют из себя XML данные. Это были мои первые мысли при виде текста ошибки, которую мне прислали:

ошибка в универсальном отчете в 1С
Текст ошибки

Первые попытки найти ошибку

Включаем остановку по ошибке, пробуем открыть проблемный вариант отчета. Попадаем в ХранилищаНастроек.ХранилищеВариантовОтчетов.ОбработкаЗагрузки.

Именно тут возникает первая ошибка — при чтении настроек компоновки данных. А точнее — при получении их из хранилища настроек и последующем преобразовании хранимых XML данных в объект с типом НастройкиКомпоновкиДанных.

ошибка в универсальном отчете в 1С

Ошибку нашли, думаем как исправить

Из текста ошибки ясно, что хранимая в ХЗ XML содержит ссылку на тип Перечисление.ВидыСтраховыхВзносовИП, но текущая конфигурация такого типа не содержит, она содержит УдалитьВидыСтраховыхВзносовИП:

ошибка в универсальном отчете в 1С

В этом и ошибка! Получается нам нужно в хранимой XML подменить ВидыСтраховыхВзносовИП на УдалитьВидыСтраховыхВзносовИП. Как это сделать? Сейчас поделюсь своим вариантом танцев с бубнами.

Итак, сильно не оглядываясь в цикличную структуру кода, поскольку мне нужно будет чинить не один вариант Универсального отчета, сконцентрируемся на процедуре исправления единичного варианта.

Для начала нужно получить само значение из хранилища, получив ссылку на вариант отчета простейшим запросом. Или даже можно просто из реквизита внешней обработки, которую я и написал для исправления:

ошибка в универсальном отчете в 1С

Далее приложу код и опишу его поэтапно:

//Настройки = Выборка.Настройки.Получить();
ХЗСтрокой = ЗначениеВСтрокуВнутр(Выборка.Настройки);

//Вычленяем Base64 зашифрованный XML
//Не пойму формат, XML нет, JSON нет
МассивСтрок = СтрРазделить(ХЗСтрокой, ",", Ложь);
СтрокаBase64 = МассивСтрок[2];

//Отсекаем лишнее
СтрокаBase64 = СтрЗаменить(СтрокаBase64, "
|{#base64:", "");
СтрокаBase64 = СтрЗаменить(СтрокаBase64, "}
|}", "");

ДвоичныеДанныеНастроекОтчета = Base64Значение(СтрокаBase64);
ЧтениеДвоичныхДанных = Новый ЧтениеДанных(ДвоичныеДанныеНастроекОтчета);
XMLОтчета = ЧтениеДвоичныхДанных.ПрочитатьСимволы();
ЧтениеДвоичныхДанных.Закрыть();

//Чиним отчет при необходимости
КорректныеНастройкиСтрокой = ПочинитьВариантОтчета(Выборка.Ссылка, XMLОтчета);

Если КорректныеНастройкиСтрокой = Неопределено Тогда
    //Нет необходимости, но проверим открвыается ли он вообще
    Настройки = Выборка.Настройки.Получить();
    Продолжить;
КонецЕсли;  

//Сформируем новые настройки
Чтение = Новый ЧтениеXML();
Чтение.УстановитьСтроку(Прав(КорректныеНастройкиСтрокой, СтрДлина(КорректныеНастройкиСтрокой) - СтрНайти(КорректныеНастройкиСтрокой, "<?xml")+1));
НастройкиКД = СериализаторXDTO.ПрочитатьXML(Чтение);

ОтчетОбъект = Выборка.Ссылка.ПолучитьОбъект();
ОтчетОбъект.Настройки = Новый ХранилищеЗначения(НастройкиКД);
ОтчетОбъект.Записать();

Помним, что Настройки.Получить() не прокатит, нам нужно именно строковое представление на максимально низком уровне, чтобы 1С не пыталась все эти данные преобразовать в значение из XML — ведь именно на этом моменте выходит ошибка.

Для обхода используем ЗначениеВСтрокуВнутр(), передав в параметр настройки.
Получим белиберду в виде строки, но не стоит её пугаться, это всего лишь значение Base64 в виде строки, дополненное структурой хранилища значения:

ошибка в универсальном отчете в 1С
Строковое представление хранящихся настроек компоновки данных в хранилище значения

Даже в самой строке есть подсказка, что это именно Base64. Вычленяем нужную нам часть именно строкового значения Base64 и преобразуем в двоичные данные с помощью функции Base64Значение().

Полученные двоичные данные нужно преобразовать в строку, ведь преобразовать в XML мы всё ещё не можем, выйдет ошибка. Используем ЧтениеДвоичныхДанных, получаем строку, мы уже совсем близко!

На этом этапе уже вполне можно производить замены строк на нужные, опять же не обращая внимание на попытки к универсализации процедур. Смотрим, что для этого достаточно использовать функцию СтрЗаменить():

КорректныеНастройкиСтрокой = СтрЗаменить(НастройкиСтрокой, "ВидыСтраховыхВзносовИП", "УдалитьВидыСтраховыхВзносовИП");

Заменяем некорректное на корректное и бежим дальше, осталось всего ничего.

ошибка в универсальном отчете в 1С
Непонятная вставка в строковом представлении XML настроек компоновки данных

Далее нужно избавиться от непонятной вставки, иначе это нам не позволит преобразовать исправленную строку в XML. С помощью ЧтениеXML и СериализаторXDTO читаем нашу XML строку и… О чудо, получаем НастройкиКомпоновкиДанных!

ошибка в универсальном отчете в 1С

Осталось просто записать эти настройки в хранилище значения и записать объект отчета, всё! Готово, вариант исправлен и корректно открывается.

Конечно, в моём случае исправление было довольно простым. Не спорю, что момент с использованием функции СтрЗаменить может подойти не всем, всё очень сильно зависит от причины ошибки при чтении XML, но суть исправления ясна.

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar