УПП требует 8.3 или можно остаться на 8.2? Решаем проблему выгрузки отчетности без BOM

Программист 1С v8.3 (Обычные формы) Налоговый учет IT и автоматизация бизнеса
← На главную

При обновлении конфигурации «Управление производственным предприятием» (УПП, редакция 1.3) многие разработчики и системные администраторы сталкиваются с жестким требованием фирмы «1С»: для полноценного формирования отчетности в ПФР (ныне СФР) по формам СЗВ-М, СЗВ-СТАЖ, СЗВ-КОРР, ОДВ-1 и СЗВ-ИСХ требуется использовать технологическую платформу «1С:Предприятие» версии не ниже 8.3.9.1818. Это связано с тем, что контролирующие органы требуют предоставлять файлы отчетности в кодировке UTF-8 без сигнатуры BOM (Byte Order Mark).

В этой статье мы подробно разберем, почему возникает эта проблема, рассмотрим системные ограничения платформы 8.2, а также изучим несколько практических и элегантных способов обойти это ограничение программным путем, если ваша база по-прежнему вынуждена работать на платформе 8.2.

В чем суть проблемы с сигнатурой BOM?

Прежде чем перейти к коду, давайте разберем физическую суть проблемы. Сигнатура BOM (Byte Order Mark) — это последовательность байтов в самом начале текстового файла (для UTF-8 это три байта: EF BB BF), которая указывает программам-ридерам на то, в каком формате записан текст. Платформа «1С:Предприятие 8.2» при записи файлов в формате UTF-8 всегда принудительно добавляет эти три байта.

Однако приемные шлюзы контролирующих органов жестко настроены на прием файлов UTF-8 строго без BOM. Наличие этих трех байтов в начале XML-документа приводит к ошибке парсинга, и отчетность отклоняется. Начиная с версии 8.3.9, в платформе 1С появился штатный параметр, позволяющий отключать запись BOM, но в 8.2 такого механизма «из коробки» нет.

---

Решение №1: Удаление BOM через преобразование в Base64

Рассмотрим очень красивое и математически точное решение проблемы. Как известно, кодирование в Base64 переводит бинарные данные в текстовую строку. Поскольку 3 байта сигнатуры BOM в UTF-8 (0xEF 0xBB 0xBF) занимают ровно 24 бита, при преобразовании в Base64 они превращаются ровно в 4 символа в самом начале результирующей строки (строка всегда начинается с символов 77u/).

Таким образом, мы можем записать файл стандартными средствами 1С (с BOM), затем прочитать его как двоичные данные, преобразовать в Base64-строку, отрезать первые 4 символа и записать обратно. Давайте разберем этот алгоритм на примере:


// Создаем текстовый документ и записываем его в UTF-8 (платформа принудительно добавит BOM)
СписокЭкспорт = Новый ТекстовыйДокумент;
СписокЭкспорт.ДобавитьСтроку(ТекстФайлаОтчетности);
СписокЭкспорт.Записать(ИмяФайлаВыгрузки, КодировкаТекста.UTF8);

// Читаем только что записанный файл как бинарные данные
КонвертируемыйФайл = Новый ДвоичныеДанные(ИмяФайлаВыгрузки);

// Кодируем бинарные данные в строку Base64
Строка64 = Base64Строка(КонвертируемыйФайл);

// Отрезаем первые 4 символа (это и есть наши 3 байта BOM)
Строка64БезBOM = Прав(Строка64, СтрДлина(Строка64) - 4);

// Декодируем строку обратно в двоичные данные
ДляЗаписиВФайл = Base64Значение(Строка64БезBOM);

// Перезаписываем исходный файл очищенными бинарными данными
ДляЗаписиВФайл.Записать(ИмяФайлаВыгрузки);

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

---

Решение №2: Трюк с инициализацией файла в ANSI (без модификации двоичных данных)

Проанализируем еще один интересный обходной путь. Объект ЗаписьТекста в платформе 1С имеет особенность: если мы открываем файл для записи в режиме дозаписи (параметр Истина), и файл уже физически существует на диске, то платформа не пытается повторно инициализировать заголовок файла и, соответственно, не добавляет в него сигнатуру BOM. Мы можем использовать это поведение искусственно.

Давайте реализуем этот алгоритм по шагам:

  1. Создаем пустой файл в кодировке ANSI (в ней BOM отсутствует в принципе).
  2. Закрываем файл.
  3. Открываем этот же файл объектом ЗаписьТекста, но уже в режиме добавления текста (дозаписи) и пишем туда наши данные в формате UTF-8.

Посмотрим на пример реализации данного метода:


// Шаг 1: Создаем пустой файл в кодировке ANSI
ЗТ = Новый ЗаписьТекста(ИмяФайлаВыгрузки, КодировкаТекста.ANSI); 
ЗТ.Закрыть(); 

// Шаг 2: Открываем созданный файл в режиме дозаписи (параметр Истина)
ЗТ = Новый ЗаписьТекста(ИмяФайлаВыгрузки, , , Истина, Символы.ПС); 
ЗТ.Записать(ТекстФайлаОтчетности); 
ЗТ.Закрыть();

В результате на диске сформируется корректный файл UTF-8, но без сигнатуры BOM в начале. Этот метод значительно быстрее предыдущего, так как не требует двойного чтения файла на диске и тяжелых операций кодирования/декодирования больших строк.

---

Решение №3: Внедрение обхода в типовой механизм УПП

Выясним, как интегрировать данное решение непосредственно в код конфигурации УПП редакции 1.3, чтобы пользователи могли беспрепятственно выгружать отчетность кнопками из стандартного интерфейса. Основная логика выгрузки регламентированных отчетов ПФР сосредоточена в общем модуле ПроцедурыПерсонифицированногоУчета, в процедуре ЗаписатьФайлДокументаНаДискету.

Нам необходимо переопределить поведение системы в блоке выгрузки UTF-8. Ниже представлен готовый участок кода, заменяющий стандартный вызов:


// Находим место выгрузки в процедуре ЗаписатьФайлДокументаНаДискету
Если Не ДобавлятьBOM И ТипКодировки = "UTF8" Тогда
    // Обходим стандартное предупреждение платформы о необходимости версии 8.3.9
    // Код закомментирован для исключения назойливых окон
    // Если Не ЕстьПоддержкаУправленияBOM() Тогда ...
Иначе
    ДобавлятьBOM = Истина;
КонецЕсли;

Если ВыбиратьКаталог Тогда
    Длг = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
    Длг.Каталог = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(ТекущийПользователь, "ОсновнойКаталогФайлов");
    Длг.Заголовок = "Укажите каталог";
    Если Длг.Выбрать() Тогда
        ИмяФайла = Длг.Каталог + "\" + ИмяФайла;
        Если ДобавлятьBOM Тогда
            ТекстовыйДокумент = Новый ТекстовыйДокумент;
            ТекстовыйДокумент.УстановитьТекст(ТекстФайла); 
            ТекстовыйДокумент.Записать(ИмяФайла, КодировкаФайла);
        Иначе
            // Наш обходной путь для выгрузки UTF-8 без BOM на платформе 8.2
            Если ТипКодировки = "UTF8" Тогда
                ЗТ = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI); 
                ЗТ.Закрыть(); 
                ЗТ = Новый ЗаписьТекста(ИмяФайла, , , Истина, Символы.ПС); 
                ЗТ.Записать(ТекстФайла); 
                ЗТ.Закрыть();                    
            Иначе
                Запись = Новый ЗаписьXML;
                Запись.ОткрытьФайл(ИмяФайла, ТипКодировки, Ложь);
                Запись.ЗаписатьБезОбработки(ТекстФайла);
                Запись.Закрыть();                    
            КонецЕсли;
        КонецЕсли;
        
        Если Не ЗначениеЗаполнено(ТекстОповещения) Тогда
            ТекстОповещения = "Файл записан под именем: ";
        КонецЕсли;
        Предупреждение(ТекстОповещения + ИмяФайла);
    КонецЕсли;
КонецЕсли;

Внедрение этого патча позволит бухгалтерам продолжать сдавать отчетность в штатном режиме без модернизации серверной инфраструктуры до версии 8.3.

---

Решение №4: Использование альтернативной кодировки CESU-8

Существует еще один малоизвестный, но крайне эффективный способ записи текстовых файлов без BOM на старых версиях платформы 1С — это использование кодировки CESU-8.

CESU-8 (Compatibility Encoding Scheme for UTF-16: 8-Bit) во многом идентична стандартной UTF-8, за исключением способа кодирования символов за пределами базовой многоязыковой плоскости (например, эмодзи или редких иероглифов, которые практически никогда не встречаются в отчетности ПФР). Самое важное для нас преимущество заключается в том, что платформа 1С при записи файлов через ЗаписьТекста с указанием КодировкаТекста.CESU-8 генерирует бинарный поток, идентичный UTF-8, но **не добавляет** сигнатуру BOM.

Пример использования:


ЗТ = Новый ЗаписьТекста(ИмяФайлаВыгрузки, КодировкаТекста.CESU-8);
ЗТ.Записать(ТекстФайлаОтчетности);
ЗТ.Закрыть();

Этот способ позволяет обойтись вообще без создания временных файлов или манипуляций с Base64, однако следует помнить, что в редких случаях валидаторы принимающих органов могут проверять XML-декларацию файла (если там принудительно прописано наименование кодировки).

---

Почему оставаться на 8.2 становится опасно?

Несмотря на то, что программисты успешно находят лазейки для обхода ограничений платформы 8.2, системным администраторам и руководству стоит понимать, что жизненный цикл этой платформы давно завершен. Рассмотрим ключевые проблемы совместимости 1С 8.2 с современным окружением:

Резюме: Если перед вами стоит оперативная задача сдать отчетность "здесь и сейчас" без обновления платформы, используйте предложенные варианты с удалением BOM через ANSI или Base64. Однако параллельно обязательно планируйте переход на платформу 8.3 (в режиме совместимости со старыми конфигурациями она работает превосходно и стабильно) и постепенную миграцию на современные решения уровня 1С:ERP.

← На главную