Управляющий символ GS с кодом 29: откуда он в базе 1С и что с ним делать
Содержание
Символ 29 в 1С — это невидимый управляющий символ GS (Group Separator, шестнадцатеричный код 0x1D). Чаще всего он попадает в базу вместе с кодами маркировки DataMatrix, а ошибка возникает при выгрузке в XML: стандарт XML 1.0 запрещает такие символы, и обмен падает на первой же строке с ним.
Типичная ситуация: склад отсканировал партию обуви, документ провёлся, а ночной обмен с бухгалтерией остановился с сообщением о недопустимом символе. В форме документа всё выглядит чисто — символ не отображается. Исправить ошибку можно тремя путями: очистить данные, закодировать значение для передачи или настроить правила обмена так, чтобы символ не уходил в файл.
Что за символ 29 и почему он мешает базе
Коды от 0 до 31 в таблице ASCII — управляющие. Они не печатаются, а служат командами. Символ 29 исторически разделял группы данных, и именно в этой роли его используют коды маркировки.
В коде DataMatrix для «Честного знака» GS стоит между группами данных: после серийного номера, перед кодом проверки и криптохвостом. Без него система маркировки не разберёт код, поэтому сам по себе символ — не мусор, а часть данных.
Проблемы начинаются, когда такая строка уходит туда, где управляющие символы запрещены.
| Куда уходит строка | Что будет с GS |
|---|---|
| XML 1.0 (обмен, выгрузки, многие форматы ЭДО) | ❌ запрещён даже в виде ссылки , файл невалиден |
| JSON | ✅ допустим в экранированном виде \u001d |
| Хранение в реквизите 1С | ✅ хранится без проблем, но не виден в форме |
| Поиск, сравнение строк | ⚠️ две «одинаковые» на экране строки не совпадают |
| Печать, этикетки | ⚠️ зависит от шрифта и принтера, может выйти пустой квадрат |
В XML 1.0 разрешены только три управляющих символа: табуляция (9), перевод строки (10) и возврат каретки (13). Всё остальное ниже 32 — ошибка разбора. Поэтому то же самое случается с символами 1, 11, 31 и другими, но на практике в 1С чаще всего встречается именно 29.
Текст сообщения зависит от места, где сломалось. При записи файла платформа ругается на недопустимый символ в XML, при чтении принимающая сторона пишет об ошибке разбора XML с номером строки и позиции. Номер позиции — первая подсказка, где искать.
Где искать недопустимые символы: в файле и в базе
Начинать удобнее с файла обмена: там уже известна строка и позиция.
Поиск в файле
- Откройте файл в Notepad++.
- Включите отображение спецсимволов:
Вид → Отображать символы → Отображать все символы. Символ 29 покажется как меткаGSв рамке. - Нажмите
Ctrl+F, выберите режим поиска «Регулярные выражения» и ищите\x1D. - Посмотрите, в каком теге стоит находка. По соседним тегам почти всегда понятно, какой объект и реквизит виноваты.
Если файл большой и редактор его не тянет, поможет PowerShell:
Select-String -Path "C:\Exchange\Message.xml" -Pattern "\x1D" | Select-Object LineNumber, Line -First 20
Команда выведет номера строк и сами строки. Чтобы найти любые запрещённые управляющие символы, а не только 29, замените шаблон на [\x00-\x08\x0B\x0C\x0E-\x1F].
Поиск в базе
В пользовательском режиме символ не видно, поэтому искать его глазами бесполезно. Нужна обработка или консоль кода. Ниже — функция, которая возвращает позицию первого запрещённого символа или 0, если строка чистая:
Функция ПозицияУправляющегоСимвола(Знач Текст) Экспорт
Для Позиция = 1 По СтрДлина(Текст) Цикл
Код = КодСимвола(Текст, Позиция);
Если Код < 32 И Код <> 9 И Код <> 10 И Код <> 13 Тогда
Возврат Позиция;
КонецЕсли;
КонецЦикла;
Возврат 0;
КонецФункции
Для строковых реквизитов ограниченной длины можно сначала отобрать кандидатов запросом — так не придётся перебирать весь справочник в цикле:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка,
| Номенклатура.Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул ПОДОБНО &Шаблон";
Запрос.УстановитьПараметр("Шаблон", "%" + Символ(29) + "%");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Строка(Выборка.Ссылка));
КонецЦикла;
Реквизиты неограниченной длины (комментарии, описания) так не проверяются — их обходите выборкой и функцией выше.
Если в файле обмена символ стоит внутри кода маркировки — это нормальный GS, а не порча. Удалять его из базы нельзя, нужно менять способ передачи (раздел ниже).
Как очистить данные от управляющих символов
Метод зависит от того, что это за строка. Мусор удаляем, код маркировки упаковываем.
| Способ | Когда подходит | Риски |
|---|---|---|
Удалить GS через СтрЗаменить | Наименования, артикулы, комментарии | Испортит код маркировки, если применить к нему |
| Удалить все символы ниже 32, кроме 9, 10, 13 | Массовая чистка текста после загрузки | Пропадут переносы, если их кодировали иначе |
| Кодировать строку в Base64 | Коды маркировки, любые данные, где важен каждый байт | Принимающая сторона должна раскодировать |
| Заменить GS на условный знак | Ручные выгрузки, отчёты для людей | Знак может встретиться в данных, обратная замена неоднозначна |
Удаление одного символа
Самый короткий вариант для заведомо «мусорных» полей:
Объект.Наименование = СтрЗаменить(Объект.Наименование, Символ(29), "");
Удаление всех запрещённых символов
Функция пригодится, если в данных встречается не только 29, но и другие управляющие коды:
Функция БезУправляющихСимволов(Знач Текст) Экспорт
Части = Новый Массив;
Для Позиция = 1 По СтрДлина(Текст) Цикл
Код = КодСимвола(Текст, Позиция);
Если Код < 32 И Код <> 9 И Код <> 10 И Код <> 13 Тогда
Продолжить;
КонецЕсли;
Части.Добавить(Сред(Текст, Позиция, 1));
КонецЦикла;
Возврат СтрСоединить(Части, "");
КонецФункции
СтрСоединить доступна с платформы 8.3.6. На длинных текстах сборка через массив работает заметно быстрее, чем склейка строки в цикле.
Упаковка кода маркировки в Base64
Если код нужно передать целиком, кодируйте его и раскодируйте на приёме:
// при выгрузке
КодДляПередачи = Base64Строка(ПолучитьДвоичныеДанныеИзСтроки(КодМаркировки));
// при загрузке
КодМаркировки = ПолучитьСтрокуИзДвоичныхДанных(Base64Значение(КодДляПередачи));
В строке Base64 только латиница, цифры и знаки +, /, =, поэтому XML её принимает. Код после раскодирования совпадает с исходным до байта, GS на месте.
Массовую чистку реквизитов делайте только после резервной копии базы и сначала на копии: если в выборку случайно попадут коды маркировки, восстановить удалённые GS уже не получится.
Правила обмена и проверка данных до записи
Очистка — разовое лечение. Чтобы ошибка не вернулась, ставьте фильтр на входе и на выходе.
На выходе: правила обмена
- 🔄 В обменах по правилам конвертации чистку ставят в обработчик, который выполняется перед выгрузкой свойства или объекта. Для полей с кодами маркировки — упаковку в Base64 и обратное преобразование в правилах приёма.
- 🧩 В типовых обменах через формат EnterpriseData правила менять в самой конфигурации не стоит: при обновлении изменения потеряются. Обработчики выносите в расширение.
- 📄 В своих выгрузках через
ЗаписьXMLпрогоняйте каждую строку через функцию очистки или упаковки передЗаписатьТекст.
В типовых конфигурациях на БСП есть готовые служебные функции для поиска и удаления недопустимых символов XML в общем модуле ОбщегоНазначенияКлиентСервер. Перед использованием откройте модуль в конфигураторе и проверьте точное имя и параметры в вашем релизе.
На входе: проверка при записи
Надёжнее всего не пускать мусор в базу. В расширении создайте подписку на событие ПередЗаписью для нужных справочников и документов и чистите в ней строковые реквизиты — наименование, артикул, комментарий. Коды маркировки в эту подписку не включайте.
Мягкий вариант — не чистить молча, а останавливать запись с сообщением, в каком поле найден символ. Так пользователь увидит, откуда пришёл мусор, и перестанет копировать данные тем же способом.
Профилактика при загрузке из Excel, сайтов и сканеров
Символ 29 почти никогда не набирают руками. У него три основных источника.
Сканер штрихкодов
Сканер в режиме эмуляции клавиатуры передаёт символы как нажатия клавиш. GS в этом режиме соответствует сочетанию Ctrl+], и дальше всё зависит от раскладки и программы, в которую идёт ввод:
- ❌ GS теряется — код маркировки становится невалидным, система маркировки его не примет;
- ❌ GS превращается в другой символ — код не совпадает с кодом из УПД поставщика;
- ⚠️ GS попадает в поле поиска или наименования, где ему не место.
Для работы с маркировкой сканер лучше подключить через драйвер в разделе подключаемого оборудования 1С, в режиме COM или USB HID-POS, если модель его поддерживает. В инструкции к сканеру есть настройка передачи GS — проверьте, что она включена.
Проверка простая: отсканируйте код с упаковки в обработку из конфигуратора или консоль кода и выведите длину строки и коды символов. Если между группами нет кода 29, сканер настроен неверно.
Excel и выгрузки с маркетплейсов
При копировании таблиц из личных кабинетов маркетплейсов, PDF и веб-страниц вместе с текстом приходят невидимые символы. В Excel они не видны, в 1С тоже, а в XML срабатывают.
- 🧹 В обработке загрузки чистите каждую ячейку функцией
БезУправляющихСимволовдо записи в справочник. - 🔍 В самом Excel проверить ячейку можно формулой
=ДЛСТР(A2)— если длина больше видимого числа знаков, внутри есть лишнее. - 📥 Файлы CSV и TXT загружайте программно, а не через буфер обмена.
Внешние системы через API
JSON от внешних сервисов легально содержит \u001d, и 1С при чтении превратит его в настоящий символ 29. Если эти данные потом уходят в XML, ошибка всплывёт уже у вас. Решение то же — чистить или упаковывать на границе.
Чем символ 29 грозит скорости и целостности данных
На производительность сам символ не влияет: это один знак в строке, индексы и запросы работают как обычно. Вред от него в другом — в рассогласовании данных.
- 🔁 Дубли. Номенклатура «Ботинки 42» и «Ботинки 42» с GS в конце для базы — разные элементы. Контроль уникальности их пропустит, а пользователь не поймёт, почему у товара два остатка.
- 🔎 Поиск. Поиск по артикулу или штрихкоду не найдёт запись, если GS есть в одной из строк и нет в другой.
- 📏 Длина реквизита. Код маркировки с разделителями длиннее на 1-2 символа. Если реквизит строкой ограниченной длины добавлен в доработке, хвост кода обрежется при записи без предупреждения.
- 🚫 Остановка обмена. Одна запись с символом 29 блокирует весь пакет. Пока её не исправят, в узел-получатель не уходят и все остальные изменения, а очередь растёт.
- ✅ Маркировка. Удалённый GS в коде маркировки — это уже испорченные данные: код не пройдёт проверку при продаже или выводе из оборота.
Если обмен стоит давно, после исправления данных не ждите расписания: запустите обмен вручную и убедитесь, что пакет ушёл целиком. Иначе следующая ошибка в той же очереди останется незамеченной до утра.
Если ошибка не уходит
Бывает, что символ 29 вычистили, а обмен всё равно падает.
- Посмотрите номер позиции в новом сообщении. Если он другой, в данных есть ещё одна запись с запрещённым символом — возможно, с другим кодом. Ищите шаблоном
[\x00-\x08\x0B\x0C\x0E-\x1F]. - Проверьте табличные части. Чаще всего чистят реквизиты шапки и забывают про строки документа, где и лежат коды маркировки.
- Проверьте зарегистрированные изменения. Пакет мог сформироваться до исправления. После чистки данных объект нужно перезаписать, чтобы изменение снова зарегистрировалось к выгрузке.
- Проверьте сторону получателя. Если ошибка разбора возникает у получателя на файле, который у вас проходит проверку, он может читать файл в другой кодировке или по более строгой схеме.