Невидимый символ, из-за которого 1С не принимает код маркировки

11.08.26

Интеграция - Обмен с ГосИС

Коды маркировки приехали от поставщика в Excel, глазами выглядят целыми, 1С их не принимает. История о том, как я полдня искал то, чего не видно, и что нашёл в исходниках типовой БП, когда наконец догадался туда залезть. С кодом проверки файла до загрузки.

Задача на двадцать минут

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

Клиент сформулировал задачу так: «коды приходят, но 1С их не принимает». Всё.

Открываю файл. Excel, один столбец, 2 470 строк. Никаких пустых ячеек, никаких объединённых заголовков, никакой обычной прайсовой дичи. Строки начинаются одинаково, длина плюс-минус одна и та же, символы читаемые. Файл, честно говоря, выглядел приличнее девяноста процентов того, что мне присылают.

Ну, думаю, двадцать минут.

Первое, на что я подумал, — кодировка. Самая скучная и самая частая причина. Полчаса на это убил и только потом сообразил, что подозревать тут нечего: в коде маркировки кириллицы нет вообще, там латиница, цифры и знаки препинания. Кодировка ни при чём физически.

Дальше — пробелы по краям. Классика: Excel любит подсунуть неразрывный пробел или табуляцию, и строка перестаёт совпадать. Обернул всё в СокрЛП, перезапустил. Ничего не изменилось.

Тут я начал раздражаться. Файл выглядит правильно, программа говорит «нет», и никакой зацепки.

От безысходности взял один код из файла и один код, считанный сканером с настоящей упаковки той же продукции. Положил рядом в окно сообщений. Смотрю — одинаковые. Буква в букву.

Потом сравнил длину.

44 и 42.

Я минуты три сидел и смотрел на эти два числа. Строки одинаковые, а длина разная. Так не бывает.

 

Два символа, которых не видно

Первое, что я сделал дальше, — вывел обе строки посимвольно с кодами. Штука на пять строчек, но именно она всё и решила:

Процедура ПоказатьКодыСимволов(Знач Строка) Экспорт
	
	Результат = "";
	Для Позиция = 1 По СтрДлина(Строка) Цикл
		Символ = Сред(Строка, Позиция, 1);
		Код = КодСимвола(Символ);
		Если Код < 32 Тогда
			// Управляющий символ — печатаем в угловых скобках
			Результат = Результат + "<" + Формат(Код, "ЧГ=0") + ">";
		Иначе
			Результат = Результат + Символ;
		КонецЕсли;
	КонецЦикла;
	
	Сообщить(Результат);
	
КонецПроцедуры

На коде со сканера в двух местах вылезло <29>. На коде из Excel — ни одного.

 Рис. 1 — посимвольный дамп: со сканера и после Excel

Символ с кодом 29 — это GS, Group Separator. Управляющий символ без графического начертания. Он не пробел: пробел хотя бы занимает место, его видно по ширине. GS не занимает ничего. Его не видно на экране, он не переживает вставку в ячейку Excel и чаще всего не переживает копирование через буфер обмена. Почему именно Excel — разберу ниже, причина там сильнее, чем «программа кривая».

То есть я полдня искал то, чего в принципе нельзя увидеть глазами. Прекрасно.

И тут мне стало любопытно: а типовая-то про этот символ знает? Полез в конфигурацию — скорее из вредности, чем с надеждой. И вот там началось интересное.

 

Что про это думает сама 1С

Дальше всё — из выгрузки «Бухгалтерии предприятия» 3.0, релиз 3.0.111.25. Про границы этой проверки честно скажу в конце, но имена модулей и функций вы найдёте и у себя.

Первое, что попалось, — в модуле РазборКодаМаркировкиИССлужебныйКлиентСервер лежит функция из одной строки:

Функция РазделительGS() Экспорт
	Возврат Символ(29);
КонецФункции

 

Экспортная функция ради одного символа. Такое пишут не от красоты, а когда константа нужна в десятке мест и её надоело размазывать по коду.

А вот это меня совсем добило. Модуль ИнтеграцияИСМПСлужебный, формирование текста ошибки:

ВызватьИсключение СтрШаблон(
	НСтр("ru ='Не удалось разобрать код маркировки: %1
	          |%2'"),
	СтрЗаменить(КодМаркировки, Символ(29), "<GS>"),
	ПримечаниеКРезультатуРазбора.ТекстОшибки);

 

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

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

 

Почему без разделителя разбор невозможен в принципе

Код маркировки — не одна строка, а последовательность полей формата GS1. Каждое поле начинается с идентификатора применения (две-четыре цифры), дальше значение. У части полей длина фиксированная, у части — переменная.

Таблица этих идентификаторов лежит прямо в коде, в модуле МенеджерОборудованияМаркировкаКлиентСервер. Выдержка по тем, что реально встречаются в кодах маркировки:

 
ДобавитьКодGS1(Коды, "01"  , "GTIN"            , 14);
ДобавитьКодGS1(Коды, "10"  , "BATCH_LOT"       ,   , 20, , ТипGS1Строка());
ДобавитьКодGS1(Коды, "17"  , "EXPIRE"          ,  6);
ДобавитьКодGS1(Коды, "21"  , "SERIAL"          ,   , 20, , ТипGS1Строка());
ДобавитьКодGS1(Коды, "8005", "PRICE_PER_UNIT"  ,  6, , , , Истина);
ДобавитьКодGS1(Коды, "91"  , "INTERNAL1"       ,   , 90, , ТипGS1Строка());
ДобавитьКодGS1(Коды, "92"  , "INTERNAL2"       ,   , 90, , ТипGS1Строка());

Третий параметр — фиксированная длина, четвёртый — максимальная переменная. Закономерность видна сразу: 01 (GTIN) всегда ровно 14 знаков, 17 (срок годности) всегда 6, 8005 (в типовой названо PRICE_PER_UNIT, у табака в этом поле едет МРЦ) всегда 6. А 21 (серийный номер) — до 20, 91 и 92 — до 90.

И вот строчка, ради которой стоило туда лезть:

 
ОписаниеКода.Вставить("ЕстьРазделитель",
	?(Параметры.ПеременнаяДлина > 0, Истина, Параметры.ЕстьРазделитель));

Переменная длина — разделитель обязателен. Фиксированная — не нужен. Всё.

Разберём, что происходит без него. Пусть идёт 21 (серийник, до 20 знаков), сразу за ним 91 (до 90). После идентификатора строка выглядит так:

 

21AbC1dEf991EE07...

Где кончается серийный номер? Может, AbC1dEf9, а дальше идентификатор 91 со значением EE07. А может, серийник — это AbC1dEf991EE07, потому что серийники бывают какие угодно, в том числе с цифрами 9 и 1 посередине. А может, AbC1dEf991, и тогда следующий идентификатор начинается с EE, что тоже формально не запрещено.

Однозначного ответа нет. Не «трудно найти», а нет — информация о границе поля утеряна физически, вместе с символом. С разделителем строка выглядела бы так:

 

21AbC1dEf9<GS>91EE07...

и вопросов бы не возникло вовсе.

 Рис. 2 — структура кода: где разделитель обязателен

 

Про FNC1, чтобы не путать

Тут надо развести две вещи, которые все путают. Я сам путал часа полтора, пока не разобрался.

GS (Символ(29)) живёт в строке. Это то, что вы получаете после декодирования: обычный управляющий символ внутри последовательности. Вся эта статья — про него.

FNC1 живёт в символике. Это служебный элемент самого кода DataMatrix, который помечает символ как GS1-совместимый. В декодированной строке его как такового нет — он про то, как код закодирован в картинку, а не про то, что из картинки вышло.

Вылезает это при печати. Если сгенерировать этикетку обычным DataMatrix вместо GS1 DataMatrix, картинка получится, глазами не отличишь, сканер её прочитает — но не как GS1-код. В компонентах печати это разные типы, и в типовой не просто так заведено отдельное перечисление ТипыШтрихкодов. На форуме Инфостарта эту разницу разбирали не раз, там же всплывает и второй нюанс: в ряде компонент FNC1 задаётся во входной строке отдельным служебным символом, а не тем же 29-м.

Короче: потеря GS ломает разбор уже считанного кода, неправильный тип символики ломает печатаемый. Симптом со стороны пользователя один и тот же — «код не принимается», — а лечится в разных местах. Дальше речь только про первое.

 

А теперь самое красивое

Я полез смотреть, что типовая делает, когда разделителей всё-таки нет. Ожидал увидеть заглушку или исключение.

Увидел функцию с названием ВариантыРазбораШтрихкодаGS1БезРазделителей.

Прочитайте название ещё раз. Не «РазобратьШтрихкодБезРазделителей». Варианты. Множественное число зашито в имя, и это не случайность — функция возвращает массив.

Внутри — вот что (обратите внимание на переменную Стек, к ней ещё вернёмся):

Стек = Новый Массив;
Стек.Добавить(ЭлементСтека);

Пока Стек.Количество() > 0 Цикл
	
	ЭлементСтека = Стек[0];
	Стек.Удалить(0);
	
	...
	
	ИначеЕсли ЗначениеЗаполнено(РезультатРазбора.ЗначениеПеременное)
		И Не РезультатРазбора.ЗначениеПеременноеОбработано Тогда
		
		МаксимальнаяДлинаЗначенияПеременнойДлины = Мин(
			РезультатРазбора.ОписаниеКода.ПеременнаяДлина,
			СтрДлина(РезультатРазбора.ЗначениеПеременное));
		
		Для ВариантДлины = 1 По МаксимальнаяДлинаЗначенияПеременнойДлины Цикл
			
			Часть1 = РезультатРазбора.ОписаниеКода.Код
				+ Лев(РезультатРазбора.ЗначениеПеременное, ВариантДлины);
			Часть2 = Сред(РезультатРазбора.ЗначениеПеременное, ВариантДлины + 1);
			
			...
			Стек.Добавить(ЭлементСтека);
			
		КонецЦикла
		
	КонецЕсли;
	
КонецЦикла;

По-человечески: дойдя до поля переменной длины, алгоритм не угадывает границу. Он перебирает все возможные длины — от одного символа до максимально допустимой — и на каждую заводит отдельную ветку разбора. Каждая ветка досчитывается до конца сама по себе. Кто дошёл — попадает в результат.

Мелочь, которая меня развеселила: переменная называется Стек, а ведёт себя как очередь. Элемент берётся с начала (Стек[0], потом Стек.Удалить(0)), а новые ветки добавляются в конец — то есть это FIFO и обход в ширину, а не стек и не поиск с возвратом. На результат не влияет никак, все ветки всё равно будут пройдены. Но если полезете читать сами — не обманывайтесь именем, я обманулся.

 Рис. 3 — перебор вариантов разбора

Я не ожидал найти в типовой полноценный перебор. Аккуратный, с копированием состояния ветки через СкопироватьРекурсивно, с отсечением заведомо мёртвых вариантов (Если ЗначениеЗаполнено(Часть2) И СтрДлина(Часть2) <= 2 Тогда Продолжить — хвост короче трёх символов не может быть идентификатором со значением). Кто-то в 1С сел и написал это всерьёз, понимая задачу.

И решение принципиально правильное. Раз информация утеряна — честный ответ «вот все прочтения, которые не противоречат формату», а не одно выдуманное с уверенным видом.

Для нас практический вывод неприятный: восстановить потерянный GS в общем случае нельзя. Можно перебрать варианты и надеяться, что уцелеет ровно один. На кодах с длинным криптохвостом — а 919293 это до 90 символов каждый — надеяться особо не на что.

 

Где именно теряется разделитель

Дальше я потратил вечер на то, чтобы понять, кто конкретно виноват. Метод дурацкий, но рабочий: берёшь код со сканера, гоняешь через каждый маршрут по отдельности, сравниваешь длину и посимвольный дамп до и после.

XLSX — не подозреваемый, а приговор. Я сначала думал, что Excel «почему-то теряет» символ, и злился на Excel. Оказалось хуже и честнее: .xlsx — это XML внутри zip, а XML 1.0 запрещает управляющие символы с кодами 0–8, 11–12 и 14–31. GS с кодом 29 попадает ровно в запрещённый диапазон. Его туда физически нечем записать. Это не баг Excel и не его каприз — это свойство формата, и никакая настройка тут не поможет.

Проверил на всякий случай программно: библиотека записи xlsx на такой строке просто отказывается работать и говорит «cannot be used in worksheets». Excel в этой ситуации молча вычищает символ и сохраняет остальное — что для пользователя даже хуже, потому что выглядит как успех.

И — да, типовая про это знает тоже. В том же модуле разбора есть функция НайденНедопустимыйСимволXML, и в ней прямым текстом перечислено:

// Коды символов от 0 до 2^16-1, которые метод НайтиНедопустимыеСимволыXML
// считает недопустимыми: 0-8, 11-12, 14-31, 55296-57343.

Тот же диапазон. То есть код маркировки с разделителем — это строка, которую нельзя положить ни в XML, ни в xlsx, ни в любой обмен, который под капотом XML. Люди, писавшие подсистему, на эти грабли наступили и обвязались проверкой.

Заодно, раз уж речь про Excel: проверяйте GTIN на съеденные ведущие нули. Прогнал круг записи-чтения — 04600000000017 в числовой ячейке возвращается как 4600000000017. Ноль отвалился молча, длина стала 13 вместо 14. И на научную нотацию тоже смотрите, в неё Excel сворачивает всё длинное и цифровое.

CSV, вопреки ожиданиям, ни при чём. Я был уверен, что CSV портит не меньше, и погнал через него тот же код. Не портит: обычный CSV в UTF-8 переносит Символ(29) без потерь, на входе 43 знака и два разделителя, на выходе столько же. Так что если у вас есть выбор формата для передачи кодов — просите CSV, а не Excel. Ровно тот случай, когда старый скучный формат объективно лучше.

Осторожность с CSV нужна в другом месте — в алфавите допустимых символов. В типовой он перечислен явно (привожу выдержку, всего там четыре набора):

Алфавит.Вставить("БуквыЦифры",         "ABC…XYZabc…xyz0123456789");
Алфавит.Вставить("БуквыЦифрыЗнаки",    "ABC…XYZabc…xyz0123456789!”""%&’'()*+,-./_:;=<>?");
Алфавит.Вставить("БуквыЦифрыЗнакиМРЦ", "ABC…XYZabc…xyz0123456789!""%&'*+-./_,:;=<>?");
Алфавит.Вставить("Цифры",              "0123456789");

Посмотрите на второй набор: кавычки, запятая, точка с запятой — ровно то, вокруг чего строится любой разбор CSV. Сам символ выживает, а вот наивный разбор строки по запятой на таком коде развалится.

Сканер. До файла дело может и не дойти. Передаёт сканер управляющие символы или нет — зависит от модели и настройки. Отсюда, кстати, растёт та самая фраза «на одном рабочем месте работает, на другом нет», которая звучит как мистика, а на деле просто разные настройки железа.

Чужая система в середине. Если код проходит через промежуточную систему, которая чистит поле от управляющих символов, вы получаете испорченные данные и чинить их у себя нечем. Только просить перевыгрузку.

 

Что я в итоге сделал

Вывод простой: файл с кодами надо проверять до того, как он поехал в базу. Не после, когда половина строк записалась, а до.

Минимальная проверка одной строки:

// Возвращает структуру с результатом проверки строки кода маркировки.
// Проверяется структурная целостность, не действительность кода в ГИС МТ.
Функция ПроверитьКодМаркировки(Знач Код) Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("Корректен",      Истина);
	Результат.Вставить("Предупреждения", Новый Массив);
	Результат.Вставить("Представление",  ВидимоеПредставление(Код));
	
	Если Не ЗначениеЗаполнено(Код) Тогда
		Результат.Корректен = Ложь;
		Результат.Предупреждения.Добавить("Пустое значение");
		Возврат Результат;
	КонецЕсли;
	
	Если Код <> СокрЛП(Код) Тогда
		Результат.Предупреждения.Добавить("Пробелы по краям — обрезаны при проверке");
		Код = СокрЛП(Код);
	КонецЕсли;
	
	// Код может прийти и в скобочной форме: (01)04600000000017(21)...
	// Типовая её обрабатывает, значит и мы обязаны.
	СоСкобками = СтрНачинаетсяС(Код, "(");
	Если Не СоСкобками И Не СтрНачинаетсяС(Код, "01") Тогда
		Результат.Корректен = Ложь;
		Результат.Предупреждения.Добавить("Код не начинается с идентификатора 01 (GTIN)");
		Возврат Результат;
	КонецЕсли;
	
	GTIN = ?(СоСкобками, Сред(Код, 5, 14), Сред(Код, 3, 14));
	Если СтрДлина(GTIN) < 14 Или Не ТолькоЦифры(GTIN) Тогда
		Результат.Корректен = Ложь;
		Результат.Предупреждения.Добавить(
			"GTIN повреждён: получено """ + GTIN + """. Частая причина — числовой формат ячейки Excel");
		Возврат Результат;
	КонецЕсли;
	
	Если СтрНайти(Код, Символ(29)) = 0 Тогда
		Результат.Корректен = Ложь;
		Результат.Предупреждения.Добавить(
			"В коде нет ни одного разделителя GS. Разбор будет неоднозначным");
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция ВидимоеПредставление(Знач Код)
	Возврат СтрЗаменить(Код, Символ(29), "<GS>");
КонецФункции

Функция ТолькоЦифры(Знач Строка)
	Для Позиция = 1 По СтрДлина(Строка) Цикл
		Если СтрНайти("0123456789", Сред(Строка, Позиция, 1)) = 0 Тогда
			Возврат Ложь;
		КонецЕсли;
	КонецЦикла;
	Возврат Истина;
КонецФункции

Самое важное здесь — ВидимоеПредставление. Приём я честно украл у типовой: подменяем невидимое на видимое, прежде чем показать человеку. Пока пользователь видит строку «как есть», он будет уверен, что всё нормально, и будет спорить с программой. Я же спорил.

Последнюю проверку — на полное отсутствие GS — я специально сделал грубой. Точная проверка «после каждого поля переменной длины стоит разделитель» требует полного разбора по шаблонам вида продукции, а это работа типового механизма, и дублировать её незачем. Для отлова файла, побывавшего в Excel, грубой хватает с запасом: если во всех 2 470 строках нет ни одного разделителя — диагноз ставится за секунду.

 

Чего эта штука не делает

Действительность кода не проверяет. Существует ли он в ГИС МТ, не выведен ли из оборота, ваш ли он — ничего этого без обращения к «Честному ЗНАКу» не узнать. Здесь только структурная целостность строки. Код может быть безупречен по структуре и при этом полгода как продан.

Потерянный разделитель не восстанавливает. Как выше и разобрано — в общем случае это невозможно. Если GS потерялся на стороне поставщика, единственное рабочее решение — просить перевыгрузку в формате, который управляющие символы переживают.

И про стенд. Всё, что я показал из типового кода, — из выгрузки БП 3.0, релиз 3.0.111.25, учебная поставка. Релиз не свежий, и как та же логика выглядит в актуальных версиях с ТС ПИоТ, я не смотрел — там могло измениться многое. Но GS1 это внешний стандарт, а не изобретение 1С, и правило «поле переменной длины требует разделителя» от релиза конфигурации не зависит.

Проверить у себя — минута: откройте свою конфигурацию, найдите общий модуль РазборКодаМаркировкиИССлужебныйКлиентСервер и посмотрите, есть ли там РазделительGS и ВариантыРазбораШтрихкодаGS1БезРазделителей. Если есть — всё описанное про вас.

 

Осадок

Задача, которая звучала как «1С не принимает коды», оказалась задачей про один невидимый символ, потерянный по дороге. Программа была права. Файл был испорчен. А человек не мог этого увидеть, потому что смотреть было буквально не на что.

Больше всего меня в этой истории цепляет вот что. Я потратил полдня, а прямо в конфигурации, которая была открыта у меня в соседнем окне, лежала функция с ответом. И приём с подменой Символ(29) на <GS> в тексте ошибки тоже лежал — то есть кто-то этот путь прошёл раньше меня и оставил указатель. Я просто не догадался посмотреть.

С тех пор, когда упираюсь в непонятное поведение вокруг ГосИС, лезу в типовую первым делом, а не последним. Там, конечно, тринадцать тысяч строк в одном модуле и разбираться неприятно. Но написано это не идиотами, и обычно к нужному месту уже кто-то ходил.

А отвечать клиенту в итоге пришлось так: программа исправна, файл испорчен, просите поставщика перевыгрузить. Формулировка, которую никто не любит слышать, — поэтому к ней теперь прилагается скриншот с посимвольным дампом. Против <GS> красным по белому не поспоришь.

Сейчас собираю всё это в обработку проверки файла с кодами до загрузки — построчный разбор, подсветка найденного, режим проверки без записи. Если сталкивались с такими файлами и знаете способы их испортить, которых нет в моём списке, — напишите, добавлю в проверки. Особенно интересны экзотические выгрузки: у меня подозрение, что Excel тут не самый изобретательный.

Вступайте в нашу телеграмм-группу Инфостарт

маркировка Честный ЗНАК код маркировки GS1 DataMatrix разбор кода маркировки загрузка из Excel ИнтеграцияИСМП ГИС МТ символ GS

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Обмен с ГосИС Бюджетный учет Регламентированный учет и отчетность Бухгалтер Пользователь 1С:Предприятие 8 1С:Бухгалтерия 3.0 1С:Управление холдингом Химическая промышленность Государственные, бюджетные структуры Электротехника и микроэлектроника Машиностроение и приборостроение Металлургическая промышленность Россия Бухгалтерский учет Бюджетный учет Платные (руб)

Автоматизация раздельного учета в 1С:Бухгалтерии по ГОЗ в соответствии с 275-ФЗ. Готовое решение для учета госконтрактов, формирования отчетности и контроля исполнения. Поддержка военной приемки, НИОКР и требований Минпромторга. Профессиональный консалтинг и регулярные обновления продукта

40000 руб.

28.08.2020    559966    3899    145    

1446

Оптовая торговля Розничная торговля Обмен с ГосИС Бухгалтер 1С:Предприятие 8 1С:Управление торговлей 10 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Розничная и сетевая торговля (FMCG) Оптовая торговля, дистрибуция, логистика Рестораны, кафе и фаст-фуд Россия Бухгалтерский учет Управленческий учет Акцизы Платные (руб)

Автоматизация учета ЕГАИС в 1С для оптовой торговли, производства и импорта алкогольной продукции. Получение и отправка ТТН, отправка акта о постановке на баланс и акта о списании. Получение остатков. Загрузка и сопоставление номенклатуры и контрагентов. Оправка в ЕГАИС отчетов о производстве и импорте.

11699 руб.

15.12.2015    186997    1468    374    

418

Бюджетный учет Обмен с ГосИС Бухгалтер 1С:Предприятие 8 1С:Бухгалтерия 3.0 Государственные, бюджетные структуры Россия Бухгалтерский учет Платные (руб)

Доработка конфигурации 1С:Бухгалтерия предприятия, редакция 3.0. реализована в виде расширения. Предназначена для ведения раздельного учета и автоматизации заполнения отчетности исполнения контрактов ГОЗ в конфигурациях 1С БП КОРП, ПРОФ, Базовая, БИТ.ФИНАНС.

62220 руб.

16.08.2019    106357    326    95    

185

Обмен с ГосИС 1С:Предприятие 8 1С:Комплексная автоматизация 1.х 1С:Бухгалтерия 2.0 1С:Управление торговлей 10 1С:Розница 2 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика Пищевая промышленность Россия Бухгалтерский учет Платные (руб)

Модуль подходит для производителей и импортеров упакованной воды, молочной продукции, соковой продукции, пива и пивных напитков, безалкогольных напитков, морепродуктов, кормов для домашних животных, антисептики (список поддерживаемых товарных групп постоянно дополняется). Для оптовиков и розницы можно работать с любыми товарными группами по ЭДО.

45000 руб.

25.10.2024    6973    19    0    

17

Оптовая торговля Розничная торговля Обмен с ГосИС Программист Бухгалтер Пользователь 1С:Предприятие 8 1C:Бухгалтерия Розничная и сетевая торговля (FMCG) Оптовая торговля, дистрибуция, логистика Россия Бухгалтерский учет Управленческий учет Платные (руб)

Решение создано для помощи разработчикам, интеграторам и другим заинтересованным лицам по настройке системы маркировки обуви, одежды, лекарств, табака, фото, молока, духов(парфюма), питьевой воды, велосипедов и шин. Задавайте вопросы по работе с ЦРПТ, GS1, ЭДО, Национальным каталогом, накоплен опыт и знания по данным темам.

20900 руб.

18.03.2019    125663    82    115    

207

Обмен с ГосИС Бухгалтер Пользователь 1С 8.3 1С 8.5 1С:Бухгалтерия 3.0 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 1.6 1С:Управление нашей фирмой 3.0 1С:Управление торговлей 11 1С:Розница 2 1С:Розница 3.0 1С:РМК Ювелирная промышленность и торговля Россия Управленческий учет Платные (руб)

Интеграция для работы 1С с ГИИС ДМДК. Государственная интегрированная информационная система в сфере контроля за оборотом драгоценных металлов, драгоценных камней и изделий из них на всех этапах этого оборота.

80000 руб.

12.04.2022    27061    208    34    

55

Бюджетный учет Обмен с ГосИС Бухгалтер Пользователь 1С:Предприятие 8 1С:Управление производственным предприятием Государственные, бюджетные структуры Россия Бухгалтерский учет Платные (руб)

Для 1С: УПП 1.3 предлагаем Вашему вниманию подсистему "Раздельный учет результатов финансово-хозяйственной деятельности организаций, выполняющих государственный оборонный заказ (раздельный учет ГОЗ)". Ключевые возможности подсистемы: - Автоматическое заполнение регламентированного отчета «Исполнение контрактов ГОЗ»; - Расшифровка показателей отчета об исполнении контрактов ГОЗ с детализацией до документов; - Контроль хозяйственных операций на соответствие требованиям Постановления Правительства № 47; - Автоматизированный ввод начальных данных по контрактам, заключенным ранее даты начала использования подсистемы.

91500 руб.

25.09.2020    38661    47    10    

44

Обмен с ГосИС Логистика, склад и ТМЦ Программист Пользователь 1С:Предприятие 8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)

Внешняя обработка для инвентаризации кодов маркировки в системе "Честный знак". Позволяет быстро определить и списать коды маркировки проданного, испорченного, утраченного (полный перечень причин списания указан ниже)  товара, которые всё ещё числятся за организацией. Привести в соответствие остатки маркированного товара программы 1С и системы "Честного знака".

6649 руб.

09.01.2024    19021    190    30    

173
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. RocKeR_13 1483 11.08.26 10:42 Сейчас в теме
Шел 8 (?) год маркировки. Люди продолжают открывать формат GS1-DataMatrix... Это ж надо еще уметь из такой мелочи такую статью раздуть-то)
alexey-simf; slavik27; SerVer1C; +3 Ответить
5. G_100802897175107255412 24 11.08.26 11:41 Сейчас в теме
(1) Формат и правда не новость. Статья не про то, что такое GS1-DataMatrix, а про то, где именно символ теряется по дороге и что с этим делает типовая — в ней на такой случай лежит перебор всех длин серийника с возвратом массива вариантов. Мне это попалось впервые, и объясняет оно больше, чем совет настроить сканер.

Если тема для вас пройденная — подскажите, куда копать дальше, я в маркировке недавно.
13. RocKeR_13 1483 12.08.26 11:56 Сейчас в теме
(5) Весь вопрос в том, а зачем вы их вообще загружаете в базу? По большому счету вам достаточно у номенклатуры добавить штрихкоды, которые соответствуют GTIN из кодов маркировки: дальше при сканировании 1С сама "понимает", какому товару соответствует код маркировки. Как показывает практика, для подбора в документы 1С нормально справляется и с кодами без символов GS (полными, краткими, со скобками и без). Был опыт интеграции с другими системами, которые упорно слали полные коды вообще без символа GS; в этом случае приходилось вклиниваться в разбор кода маркировки, в сквозных параметрах сохранять информацию о шаблоне, по которому 1С удалось разобрать код, и по этому шаблону восстанавливать полный код, вставляя символ GS перед нужными идентификаторами применения.
16. RustIG 1979 12.08.26 13:04 Сейчас в теме
(13) Алексей, у вас большой опыт и понимание вот таких деталей. Этим и ценна статья - поднимает вопросы, объединяет вокруг себя таких специалистов, как вы.
17. RocKeR_13 1483 12.08.26 13:14 Сейчас в теме
(16) А опыт подсказывает, что обычно проблема в матчасти, когда инструкцию читают только после того, как что-то не работает/сломалось)
18. RustIG 1979 12.08.26 13:21 Сейчас в теме
(17) читать только матчасть (инструкции) не помогает, помогает циклическая связка: матчасть - практика - снова какая-то матчасть (форум, статьи, инструкции) + снова практика....
я остановился на каком-то 100-вом шаге - решил задачу клиента и дальше не стал углублять свои знания...То есть, можно решать задачи клиентов, даже не углубляясь в какие-то причинно-следственные связи...
вот ваш диалог мне очень интересен - как раз оставались не закрытые вопросы...
а вот полной готовой инструкции у Честного Знака никогда не появится.... так что сила 1с-ников только в общении :)
24. RocKeR_13 1483 12.08.26 15:21 Сейчас в теме
(18) Опять же, из своего опыта написания всяких инструкций: обычно при ее написании приходится балансировать между крайностями "писать как для пятилетних австралопитеков" и "тут и так все понятно") И все равно будут моменты, которые пишущий отметил про себя как "тут и так все понятно", но как назло их бы не помешало бы пояснить)) Но матчасть изучать все равно надо - экономит уйму сил и времени)
26. G_100802897175107255412 24 12.08.26 15:26 Сейчас в теме
(24) Про «тут и так всё понятно» — попал точно. У меня в статье именно так и вышло: написал про разделители одной фразой, потому что казалось очевидным, а правило оказалось сложнее, чем я его запомнил. Причём заметил не сам.
14. RocKeR_13 1483 12.08.26 12:03 Сейчас в теме
(5)
Статья не про то, что такое GS1-DataMatrix, а про то, где именно символ теряется по дороге

Когда ознакомился с форматом GS1-DataMatrix, сразу отпали вопросы про символ GS и что он мог где-то потеряться.

Еще один полезный момент: символ GS не сериализуется в XML, поэтому явная передача текста кода маркировки между клиентом и сервером будет у вас падать в ошибку. С этой целью 1С сначала кодирует строку с полным кодом в Base64 и передает именно ее с клиента на сервер и обратно, если это необходимо.
15. G_100802897175107255412 24 12.08.26 12:21 Сейчас в теме
(14) Спасибо, это самое ценное, что можно было добавить. Полез проверять — подтверждается: в МенеджерОборудованияМаркировкаКлиентСервер есть параметр ШтрихкодВBase64, и РазобратьШтриховойКодТовара на клиенте уходит в …ВызовСервера именно с ним.

Добавлю деталь, которая мне попалась рядом: в структуре данных кода товара лежат два поля в Base64 — РеквизитКодаТовара для тега 1162 и ШтрихкодBase64 для тега 1163. То есть в чек код уезжает тем же способом.

Получается, у моей статьи и вашего замечания одна причина: XML не сериализует коды 14–31. У меня это вылезло на xlsx, у вас — на границе клиент-сервер. Хорошее дополнение, я эту сторону не увидел.

Про «зачем вообще грузить в базу» — принимаю. У меня сценарий был производственный: фабрика сама заказывает коды и раскладывает по позициям до нанесения, там штрихкодами номенклатуры не обойтись. Но для розничного подбора вы правы, и это стоило оговорить в тексте.

А приём с сохранением шаблона в сквозных параметрах и восстановлением GS перед нужными идентификаторами — забираю. Это ровно та задача, которую типовая решает перебором вариантов, а вы обошли её, запомнив успешный разбор. Дешевле и надёжнее.
19. RocKeR_13 1483 12.08.26 13:23 Сейчас в теме
(15) В бухгалтерии может быть отличие, особенно если библиотека ГосИС отличается, но примерно так делал:

1) РазборКодаМаркировкиИССлужебныйКлиентСервер.РазобратьКодМаркировки - в переменную ДанныеРезультата вставляем данные шаблона (см.скриншот)
2) Далее выполняем разбор ДанныеРазбора = РазборКодаМаркировкиИССлужебный.РазобратьКодМаркировки(КодМаркировки);
3) И вот такой функцией вставляем разделители GS согласно шаблона, где ОписаниеЭлементовКМ = ДанныеРазбора.сэ_ОписаниеЭлементовКМ (ставит перед всеми разделителями, кроме 01 и 21; но тут надо, конечно, смотреть описания товарных групп - вдруг где-то он не нужен):

Функция ДополнитьКодРазделителями(Знач КодМаркировки, ОписаниеЭлементовКМ)
	
	НовыйКод = КодМаркировки;
	Результат = "";
	
	
	Для Каждого Описание Из ОписаниеЭлементовКМ Цикл
		
		ДлинаКода = СтрДлина(Описание.Код);
		
		Если Лев(НовыйКод, ДлинаКода) = Описание.Код Тогда
			
			Если Описание.Код <> "01" И Описание.Код <> "21" Тогда
				Результат = Результат+Символ(29);
			КонецЕсли;
			
			Результат = Результат+Лев(НовыйКод, Описание.Длина+ДлинаКода);
			НовыйКод = Сред(НовыйКод, Описание.Длина+ДлинаКода+1);
			
		Иначе
			
			Возврат КодМаркировки;
			
		КонецЕсли;
				
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции
Показать
Прикрепленные файлы:
20. G_100802897175107255412 24 12.08.26 14:19 Сейчас в теме
Собрал корпус живых кодов — снял с упаковок и распознал пять штук пяти разных форматов: БАД, минералка, молочка, пачка сигарет, обувь. Прогнал через вашу функцию, делюсь результатами.

На кодах с идентификаторами применения отрабатывает верно, включая случай, где я ждал подвоха: у 8005 длина фиксированная, но в КодыGS1 ему явно проставлен признак разделителя, так что GS после него нужен — и ваше правило его ставит.

Два края нашлись ровно там, куда вы и показывали своим «надо смотреть описания товарных групп».

Первый — фиксированные поля без признака разделителя, то есть даты 11–17. В типовой есть живой шаблон GTIN + СерийныйНомер + ГоденДо + КодПроверки (молочная продукция, устаревший формат): после 17 разделитель не нужен, а правило «перед всем, кроме 01 и 21» его поставит.

Второй вылез на пачке сигарет — 04640030090525Cf3qCq7AD!o9OLZ, 29 знаков, разделителей ноль. По типовой это ОписаниеКодаМаркировкиТабачнойПачки: GTIN 14 + серийный 7 + МРЦ 4 + проверочный 4, и идентификаторы применения там заданы пустыми строками, разбор чисто позиционный. Функция туда формально заходит, потому что Лев(НовыйКод, 0) совпадает с пустым идентификатором, и ставит разделитель перед каждым элементом. Но это уже за границей вашей задачи: в интеграциях, которые шлют коды с идентификаторами, такого формата не бывает.

Если пригодится: хардкод 01/21 можно снять — в типовой есть готовый набор РазборКодаМаркировкиИССлужебныйКлиентСервер.ИдентификаторыПримененияСРазделителемGS(), соответствие, собранное из КодыGS1 по признаку ЕстьРазделитель. Условие становится «предыдущий элемент входит в набор», и даты закрываются сами. Я это не компилировал, подаю как идею.

Два уточнения по себе. Я был уверен, что у табака шаблон 01 + 21 + 8005 + 93 — оказалось, это формат блока, а не пачки, у них разные схемы. И в статье у меня сказано «переменная длина — разделитель нужен, фиксированная — нет»: это упрощение, четырнадцати идентификаторам фиксированной длины признак проставлен явно.
21. RocKeR_13 1483 12.08.26 14:56 Сейчас в теме
(20) Да, по табаку там отдельная история - в библиотеке ГосИС там отдельные даже модули с суффиксом МОТП) Далеко не со всеми товарными группами попадались клиенты, преимущественно у меня сейчас легпром, обувь и шины.
22. G_100802897175107255412 24 12.08.26 15:01 Сейчас в теме
(21) Проверил, подтверждается: у МОТП пятнадцать отдельных модулей — ИнтерфейсМОТП, ПроверкаИПодборПродукцииМОТП и далее, действительно своя ветка.

И ваша реплика заодно объяснила то, что меня озадачило при сверке. Код, который я снял с банки и считал БАДом, совпал не с БАД-шаблоном, а с процедурой ОписаниеКодаМаркировкиПродукцииИСМП — а она, судя по комментарию в коде, обслуживает лёгкую промышленность, духи, шины, велосипеды и коляски. То есть ровно ваши группы.

Там у всех элементов есть идентификаторы применения, 01 + 21 + 91 + 92, и на таком шаблоне ваше правило работает без единого исключения. Расходится оно только там, где идентификаторов нет совсем, — а это как раз табак, с которым вам и не приходилось.
23. RocKeR_13 1483 12.08.26 15:16 Сейчас в теме
(22) с табаком вообще все строже, никаких маркировок остатков и перемаркировок + у табачных производителей обычно собственный штат программистов, поэтому толком с ними и не работал. Да и, наверное, там подобные загрузки не особо актуальны
25. G_100802897175107255412 24 12.08.26 15:24 Сейчас в теме
(23) Логично — отдельный режим и отдельные правила, отсюда и отдельные модули МОТП в конфигурации. Получается, структура библиотеки просто повторяет структуру регулирования.

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

Спасибо за разговор — по нему я узнал больше, чем пока писал саму статью.
RocKeR_13; +1 Ответить
11. amiralnar 9 12.08.26 08:30 Сейчас в теме
(1) Так и уметь теперь не надо. Ок, гемини: напиши мне статью как я страдал на 10к символов для ИС.
Очередной нейрокал.
12. G_100802897175107255412 24 12.08.26 08:36 Сейчас в теме
(5) Взаимно. Про «по одной позиции за раз» — понятная механика, спасибо, отложил на случай длинных табличных частей. Такие разговоры и есть лучшее, что может случиться с публикацией.
2. RustIG 1979 11.08.26 10:45 Сейчас в теме
добрый день. для справки, вот еще справочная статья Маркировка. Без паники
v8_088; ardn; +2 Ответить
3. RustIG 1979 11.08.26 11:08 Сейчас в теме
1. у людей, которые начинают максимально использовать ИИ, атрофируется навык вдумчивого внимательного чтения и глубокого анализа больших сложных статей...
"поиск-чтение-анализ" заменяется на "промт-еще промт-еще промт"...без критики, без негатива, ИИ - мощь и нужна людям....

2. что пошло не так у автора статьи? не делал поиск по ИС, не читал статьи, не анализировал? сразу отправил запрос (промт) в свой ИИ? без критики, просто исследование...

3. я впервые столкнулся с разделителями, когда с сайта ЧЗ выгружал список марок в цсв, а потом блокнотом открывал файлы цсв.
точнее из блокнота построчно копировал в 1с... символы -разделители терялись из-за неправильного моего алгоритма, марка получалась "другой" - в отличие от марки на сайте ЧЗ.... статей на эту тему было мало, поясняющих причину....но пару статей (ровно две) было на ИС, ссылки все есть на них...Сам ЧЗ не допетрил разъяснить людям, что спецсимволы генерируются специальными программами, что в популярных программах Эксель и Блокнот эти спецсимволы не генерируются, что их надо дополнительно добавлять к штрихкоду.... я даже внятно пояснить не могу - не помню за давностью лет - как-то смешанно информация подавалась - 1с сама долго пилила алгоритмы с опозданием на полгода - помню , как все нервничали в УТ 10.3, кстати в УТ 11 также с опозданием программировали... Потом УТ 10.3 стали обновлять с опозданием в 2 мес по сравнению с УТ 11.... Тем, кто разбирался через алгоритмы типовых, сначала обновляли у себя УТ 11, затем копировали компоненту оборудования, копировали модули в УТ 10.3 через внешние обработки....было время, когда часть специалистов -внедренцев перегорели, а кто-то наоборот выпустили готовый программный продукт, начав его продавать ... было время :)
4. G_100802897175107255412 24 11.08.26 11:33 Сейчас в теме
(3) Спасибо за развёрнутый комментарий и за историю — про копирование из блокнота построчно это ровно тот же механизм, только на десять лет раньше.

По вашему вопросу отвечу честно: поиск по ИС я сделал плохой. Искал по «ТС ПИоТ», «маркировка», «DataMatrix» — и мимо прошли как раз публикации про сам разделитель. Сейчас нашёл, в том числе про сохранение GS в RDP и про передачу символа сканерами. Дайте ссылки на те две, о которых говорите, если под рукой — добавлю в текст, читателю полезнее увидеть их рядом, чем натыкаться на ту же стену второй раз.

Что я считаю в статье своим: не описание формата, оно и правда старое, а разбор того, как с этим живёт типовая — ВариантыРазбораШтрихкодаGS1БезРазделителей с перебором всех длин и возвратом массива вариантов. Про этот кусок я на ИС не нашёл ничего, а он объясняет, почему потерянный GS в общем случае не восстановить, а не просто «настройте сканер».

И про ЧЗ вы точно подметили: внятного объяснения, что спецсимвол не рождается в Экселе и блокноте, от них так и не появилось.
6. RustIG 1979 11.08.26 11:56 Сейчас в теме
(4) я заново открыл комментарии к той статье "Без паники" - я забыл, что комментарии закрыты были - ссылок много в комментариях + если комменты закрыть, то исчезают "Лучшие комменты" - вот один из них:
это ссылка на полезную статью https://infostart.ru/journal/news/uchet-nalogi-pravo/poyavilis-rekomendatsii-po-kodirovaniyu-i-preobrazovaniyu-koda-markirovki_1209448/
7. RustIG 1979 11.08.26 12:01 Сейчас в теме
(4) вторая статья - это обработка для ККТ для УТ 10.3 - я ее купил, посмотрел алгоритмы, сопоставил с тем, что описано было в первой статье, и написал свой простой алгоритм по созданию марки, чтению марки, обработки марки - все алгоритмы отразил в статье "Без паники" и в своих обработках для УТ 10.3. Статьи и обработки с тех пор не поддерживаю в плане технического обновления. Висят на ИС в качестве справочной информации.
8. v8_088 11.08.26 14:12 Сейчас в теме
Ноутпад ++ не теряет символ GS
9. G_100802897175107255412 24 11.08.26 14:29 Сейчас в теме
Точно, проверил — и не только Notepad++, обычный .txt сохраняет байт 0x1D в любой кодировке, я специально прогнал круг записи-чтения. Файл никогда и не был виноват.

Ценность Notepad++ в другом: он этот символ показывает. В обычном блокноте байт лежит в файле, но на экране его нет, поэтому проверить глазами нельзя и человек уверен, что всё в порядке.

Настоящие два места потери — буфер обмена и .xlsx. Причём это разные причины: буфер теряет по реализации, а в xlsx символ записать физически нечем, потому что формат — это XML, а XML запрещает коды 14–31.

Кстати, это объясняет историю выше: там символ терялся при копировании из блокнота построчно в 1С — то есть в буфере. Сам файл был цел.
RustIG; iozik; +2 Ответить
10. RustIG 1979 11.08.26 15:52 Сейчас в теме
(9)
Кстати, это объясняет историю выше: там символ терялся при копировании из блокнота построчно в 1С — то есть в буфере. Сам файл был цел.

Проверьте, пож-та, такую гипотезу. После открытия файла цсв в блокноте, затем закрытия файла через сохранение файла, остаются ли все спецсимволы?
Копирование я программировал алгоритмом - построчное чтение файла, разбивал марку из строки на составляющие, затем снова собирал марку...Сейчас уже не вспомню проблематику

ЧЗ в то время давал возможность выгрузить марки списком с длинным хвостиком, потом запретили такую практику, стали выгружать только короткий код марки без хвостика.... Хвостик приходилось забирать из самой двумерной марки (изображения) - просто сидел у компа, сканировал сканером с фото на телефоне или на экране компа - экран компа делил пополам - слева открытая 1с, справа фото марки крупным планом...сидел сканировал экран компа....не долго это было ...первоначальный ввод марок вроде бы делал
27. alexey-simf 37 12.08.26 15:55 Сейчас в теме
1) "Excel, один столбец, 2 470 строк" вообще не вяжется с "...и разложить по позициям".

2) С учётом того, что это типовая БП, правильный путь: "ЗаказНаЭмиссиюКодовМаркировкиСУЗ", потом "МаркировкаТоваровИСМП" и потом "ПоступлениеТоваровУслуг", но можно и без первого документа, тем более, что во второй можно из упомянутого экселя копипастом массив кодов засунуть и там никакие символы никуда не потеряются.
28. G_100802897175107255412 24 12.08.26 19:17 Сейчас в теме
(27) [По первому пункту — справедливо, у меня в описании нестыковка. Из одного столбца кодов по позициям действительно не разложишь.

По второму спасибо, маршрут вы назвали точно. Уточню про потерю символов, потому что механика там любопытная. Если коды пришли в xlsx, разделителей в них уже нет — формат физически не может их хранить, это XML, а XML запрещает управляющие символы 14–31. Терять при вставке нечего.

А работает вставка потому, что форма МаркировкаТоваровИСМП вызывает типовой разбор с видом продукции из шапки:

НастройкиРазбораКодаМаркировки = РазборКодаМаркировкиИССлужебный.НастройкиРазбораКодаМаркировки(Объект.ВидПродукции);

Зная ожидаемый шаблон, типовая раскладывает код и без разделителей — для этого есть отдельная ветка с перебором вариантов. То есть символы не уцелели, а их отсутствие скомпенсировано.

Практическая разница вылезает там, где прочтений оказывается несколько. Но в вашем сценарии, с заданным видом продукции, этого и не случится — так что совет рабочий.
Для отправки сообщения требуется регистрация/авторизация