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

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

В современных складских и торговых системах штрихкодирование печатных форм документов является стандартом де-факто. Печать штрихкода на расходной накладной, заказе клиента или перемещении товаров позволяет мгновенно найти этот документ в базе данных при помощи обычного сканера штрихкодов. Однако при реализации этого механизма разработчики часто сталкиваются с технической сложностью: как закодировать уникальный идентификатор (GUID) документа в числовой штрихкод и, что еще важнее, как затем корректно декодировать считанный штрихкод обратно в полноценную ссылку на объект базы данных 1С?

В этой статье мы подробно разберем математическую суть прямого и обратного преобразования GUID в числовой код, рассмотрим готовые инструменты в типовых конфигурациях (на примере УТ 11, ERP и КА) и напишем собственный отказоустойчивый алгоритм поиска документов для самописных конфигураций.

Прямое преобразование: Как ссылка становится штрихкодом

Прежде чем приступать к обратному декодированию, нам необходимо четко понять, каким образом ссылка превращается в число на печатной форме. Ссылка на любой объект в 1С (будь то справочник или документ) физически опирается на 128-битное число — Уникальный Идентификатор (GUID). Стандартное строковое представление GUID выглядит как 36-символьная строка с дефисами, например: 58df113e-c7e3-4da8-7000-1e50ee4df678.

Для генерации компактного числового штрихкода (например, формата Code128) стандартные библиотеки 1С выполняют следующие действия:

  1. Получают строковое представление GUID из ссылки.
  2. Удаляют все дефисы, превращая строку в 32-символьное шестнадцатеричное число (HEX).
  3. Преобразуют это шестнадцатеричное число в десятичную систему счисления. Полученная десятичная строка и становится штрихкодом, который выводится на печать.

Проанализируем фрагмент стандартного кода конфигурации, реализующий эту логику:


Функция ЧисловойКодПоСсылке(Ссылка) Экспорт
    // Извлекаем GUID и удаляем дефисы, получая HEX-строку
    ШестнадчатиричноеЧисло = СтрЗаменить(Строка(Ссылка.УникальныйИдентификатор()), "-", "");
    
    // Преобразуем HEX в десятичное число
    Возврат ПреобразоватьИзШестнадцатиричнойСистемыСчисленияВДесятичноеЧисло(ШестнадчатиричноеЧисло);
КонецФункции

В результате работы этой функции мы получаем длинную последовательность цифр (длиной до 38-39 символов), которая кодируется в штрихкод формата Code128. Использование стандартного EAN13 здесь невозможно, так как он вмещает всего 13 цифр, чего критически мало для сохранения уникальности 128-битного идентификатора GUID.

Проблема обратного декодирования

Когда оператор сканирует штрихкод с листа бумаги, в систему поступает исходная десятичная строка (например, d94c7b60c3e311e9baae309c2344e8cc в шестнадцатеричном эквиваленте). Задача разработчика — выполнить шаги в строго обратном порядке:

  1. Перевести десятичную строку обратно в шестнадцатеричный формат (HEX).
  2. Убедиться, что полученная HEX-строка имеет длину ровно 32 символа. Если она короче (это происходит, когда старшие разряды GUID были нулевыми), дополнить ее ведущими нулями слева.
  3. Расставить дефисы на строго определенные позиции по маске 8-4-4-4-12.
  4. Создать объект УникальныйИдентификатор из полученной строки.
  5. Найти реальную ссылку на документ в базе данных.

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

Решение 1. Использование встроенного механизма БСП и типовых конфигураций

Если вы работаете в конфигурации, созданной на базе современных типовых решений фирмы "1С" (например, "Управление торговлей 11", "Комплексная автоматизация 2", "1С:ERP" или "Управление нашей фирмой"), вам не нужно изобретать велосипед и писать сложные математические функции с нуля. В составе этих конфигураций присутствует специализированный программный модуль.

Для быстрого поиска документа по штрихкоду воспользуемся функцией общего модуля ШтрихкодированиеПечатныхФорм. Рассмотрим на примере, как правильно вызвать этот метод:


// Шаг 1. Определяем массив менеджеров документов, среди которых мы ожидаем найти объект.
// Настоятельно рекомендуется ограничивать этот список только нужными типами документов 
// для оптимизации производительности запроса к СУБД.
МассивМенеджеров = Новый Массив;
МассивМенеджеров.Добавить(Документы.РеализацияТоваровУслуг);
МассивМенеджеров.Добавить(Документы.ЗаказКлиента);
МассивМенеджеров.Добавить(Документы.ПеремещениеТоваров);

// Шаг 2. Задаем считанный со сканера числовой штрихкод
СчитанныйШтрихкод = "28859182374921384021983472198347129843"; // Пример числовой строки

// Шаг 3. Вызываем встроенную функцию для получения массива ссылок
НайденныеСсылки = ШтрихкодированиеПечатныхФорм.ПолучитьСсылкуПоШтрихкодуТабличногоДокумента(СчитанныйШтрихкод, МассивМенеджеров);

// Шаг 4. Обрабатываем результат поиска
Если НайденныеСсылки.Количество() > 0 Тогда
    СсылкаНаДокумент = НайденныеСсылки[0];
    ПоказатьЗначение(, СсылкаНаДокумент);
Иначе
    ВызватьИсключение "Документ по данному штрихкоду не найден в информационной базе!";
КонецЕсли;

Этот метод чрезвычайно удобен, безопасен и оптимален. Внутри себя он не просто выполняет математическое декодирование, но и автоматически строит быстрый запрос к базе данных СУБД с конструкцией ОБЪЕДИНИТЬ ВСЕ по выбранным таблицам, гарантируя, что полученная ссылка реально существует в базе данных и не является "битой".

Решение 2. Реализация алгоритма в самописных конфигурациях

Что делать, если ваша конфигурация написана с нуля или является сильно урезанной версией, где модуль ШтрихкодированиеПечатныхФорм отсутствует? В таком случае нам придется реализовать математику и логику поиска самостоятельно. Разберем этот процесс по шагам.

Шаг 1. Перевод из десятичной системы в шестнадцатеричную (Длинная арифметика)

Поскольку 128-битный GUID при переводе в десятичную систему дает гигантские числа (до 39 знаков), стандартные типы данных 1С могут округлять значения или вызывать переполнение разрядной сетки (платформа поддерживает точность чисел только до 38 знаков). Чтобы избежать потери точности, мы должны использовать строковые алгоритмы деления "в столбик" (длинную арифметику).

Рассмотрим функцию, которая безошибочно преобразует сверхдлинную десятичную строку в шестнадцатеричную:


Функция ДесятичноеЧислоВШестнадцатеричное(Знач ДесятичноеСтрокой) Экспорт
    Результат = "";
    Алфавит = "0123456789abcdef";
    
    Пока Истина Цикл
        ДесятичноеСтрокой = СокрЛП(ДесятичноеСтрокой);
        Если ДесятичноеСтрокой = "0" Или ДесятичноеСтрокой = "" Тогда
            Прервать;
        КонецЕсли;
        
        Остаток = 0;
        НоваяСтрокаЧисла = "";
        
        // Посимвольное деление длинной строки на 16 (аналог деления "уголком")
        Для Индекс = 1 По СтрДлина(ДесятичноеСтрокой) Цикл
            ТекущаяЦифра = Число(Сред(ДесятичноеСтрокой, Индекс, 1));
            ВременноеЧисло = Остаток * 10 + ТекущаяЦифра;
            ЦелаяЧасть = Цел(ВременноеЧисло / 16);
            Остаток = ВременноеЧисло % 16;
            
            Если НоваяСтрокаЧисла <> "" Или ЦелаяЧасть > 0 Тогда
                НоваяСтрокаЧисла = НоваяСтрокаЧисла + Строка(ЦелаяЧасть);
            КонецЕсли;
        КонецЦикла;
        
        Результат = Сред(Алфавит, Остаток + 1, 1) + Результат;
        ДесятичноеСтрокой = НоваяСтрокаЧисла;
    КонецЦикла;
    
    Если Результат = "" Тогда
        Результат = "0";
    КонецЕсли;
    
    Возврат Результат;
КонецФункции

Шаг 2. Восстановление структуры GUID

После получения HEX-строки нам необходимо дополнить ее ведущими нулями до длины в 32 символа и расставить дефисы. Посмотрим на пример реализации этой процедуры:


Функция ПолучитьGUIDИзЧисловогоШтрихкода(Знач ШтрихкодДесятичный) Экспорт
    // Получаем HEX представление из десятичной строки
    HEXСтрока = ДесятичноеЧислоВШестнадцатеричное(ШтрихкодДесятичный);
    
    // Дополняем ведущими нулями до стандартного размера GUID (32 символа без дефисов)
    Пока СтрДлина(HEXСтрока) < 32 Цикл
        HEXСтрока = "0" + HEXСтрока;
    КонецЦикла;
    
    // Формируем строковое представление UUID по стандартной маске: 8-4-4-4-12
    СтрокаGUID = Сред(HEXСтрока, 1, 8) + "-" +
                 Сред(HEXСтрока, 9, 4) + "-" +
                 Сред(HEXСтрока, 13, 4) + "-" +
                 Сред(HEXСтрока, 17, 4) + "-" +
                 Сред(HEXСтрока, 21, 12);
                 
    Возврат СтрокаGUID;
КонецФункции

Шаг 3. Безопасный поиск ссылки в базе данных по GUID

Теперь, когда у нас есть строковое представление GUID, мы можем легко создать объект УникальныйИдентификатор. Но помните: метод ПолучитьСсылка() у менеджеров документов не проверяет физическое существование объекта в СУБД, он лишь конструирует объект ссылки в оперативной памяти. Если документа с таким идентификатором нет, ссылка окажется "битой".

Для надежного поиска напишем функцию, использующую запрос:


Функция НайтиДокументПоДекодированномуGUID(СтрокаGUID, МассивМенеджеров) Экспорт
    УИД = Новый УникальныйИдентификатор(СтрокаGUID);
    
    Запрос = Новый Запрос;
    ТекстЗапроса = "";
    
    // Динамически строим запрос по переданным таблицам документов
    Для Каждого Менеджер Из МассивМенеджеров Цикл
        ИмяТаблицы = Менеджер.ПустаяСсылка().Метаданные().ПолноеИмя();
        
        Если ТекстЗапроса <> "" Тогда
            ТекстЗапроса = ТекстЗапроса + Символы.ПС + "ОБЪЕДИНИТЬ ВСЕ" + Символы.ПС;
        КонецЕсли;
        
        ТекстЗапроса = ТекстЗапроса + 
            "ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка КАК Ссылка ИЗ " + ИмяТаблицы + " ГДЕ Ссылка = &Ссылка";
            
        СсылкаПоУИД = Менеджер.ПолучитьСсылка(УИД);
        Запрос.УстановитьПараметр("Ссылка", СсылкаПоУИД);
    КонецЦикла;
    
    Если ТекстЗапроса = "" Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    Запрос.Текст = ТекстЗапроса;
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Ссылка;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Важные архитектурные ограничения и оптимизация

При использовании математического декодирования GUID необходимо помнить о нескольких критически важных моментах:

Альтернатива: Использование регистра сведений штрихкодов

Проанализируем альтернативный подход, который упоминался в Сообщении 9 на форуме. Вместо математического кодирования длинного 128-битного GUID в громоздкое десятичное число, мы можем пойти классическим путем создания связей через базу данных.

Для этого в системе создается независимый регистр сведений ШтрихкодыДокументов со следующей структурой:

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

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

Недостатки альтернативного подхода: Требуется выделение физического места в базе данных под хранение записей регистра. В распределенных информационных базах (РИБ) необходимо тщательно настраивать правила синхронизации диапазонов генерации коротких кодов во избежание коллизий (дублирования штрихкодов на разных узлах сети).

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

← На главную