Как в запросе или СКД преобразовать число в строку без пробелов для соединения таблиц

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

В практике разработки на платформе 1С:Предприятие часто возникает классическая коллизия типов данных. Например, в одном документе штрихкод хранится в виде Числа (с разделителями групп разрядов, например, 200 000 576 241), а в регистре сведений тот же штрихкод записан как Строка без пробелов (200000576241). При попытке связать эти таблицы в запросе напрямую через ПО разработчик сталкивается с невозможностью сопоставить разные типы данных.

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

Метод 1. Использование встроенных функций работы со строками в запросе (Платформа 8.3.20 и выше)

Если ваша информационная база работает на платформе версии 8.3.20.1549 или более поздней, вам крупно повезло. Фирма «1С» добавила в язык запросов полноценную поддержку функций работы со строками. Теперь мы можем преобразовывать число в строку и удалять пробелы непосредственно внутри запроса.

Рассмотрим важный нюанс: при автоматическом приведении числа к строке платформа 1С использует локальные настройки ИБ и по умолчанию разделяет триады чисел неразрывным пробелом (символ с кодом ASCII 160 или Unicode U+00A0). Обычная замена стандартного пробела (код 32) функцией СтрЗаменить здесь не сработает. Нам нужно передать в качестве параметра именно неразрывный пробел.

Проанализируем пример запроса, решающего эту задачу:


ВЫБРАТЬ
	СтрЗаменить(Строка(ДокументТаблица.ШтрихкодДок), &НеразрывныйПробел, "") КАК ШтрихкодСтрокой,
	ДокументТаблица.Ссылка КАК ДокументСсылка
ПОМЕСТИТЬ ВтДокументыСоШтрихкодом
ИЗ
	Документ.РеализацияТоваровУслуг.Товары КАК ДокументТаблица
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
	ВтДокументы.ДокументСсылка КАК ДокументСсылка,
	РегистрШтрихкоды.Штрихкод КАК ШтрихкодРегистра
ИЗ
	ВтДокументыСоШтрихкодом КАК ВтДокументы
	ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ШтрихкодыНоменклатуры КАК РегистрШтрихкоды
		ПО ВтДокументы.ШтрихкодСтрокой = РегистрШтрихкоды.Штрихкод

В качестве параметра &НеразрывныйПробел в коде вызова запроса необходимо передать значение Символы.НПП:


Запрос = Новый Запрос;
Запрос.Текст = "..."; // Текст запроса выше
Запрос.УстановитьПараметр("НеразрывныйПробел", Символы.НПП);
Результат = Запрос.Выполнить();

Этот способ является наиболее изящным и быстрым, поскольку вся обработка происходит непосредственно на уровне СУБД силами встроенного транслятора SQL.

Метод 2. Соединение наборов данных в СКД по вычисляемому выражению

Если вы работаете на более ранних версиях платформы (до 8.3.20), то в обычном запросе преобразовать число в строку штатными методами невозможно (функция ВЫРАЗИТЬ не поддерживает приведение чисел к строкам). Однако мы можем использовать механизм Системы компоновки данных (СКД).

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

  1. Создайте в схеме компоновки данных первый набор данных - запрос (например, НаборДанныхДокумент), который выбирает данные документа с числовым полем ШтрихкодДок.
  2. Создайте второй набор данных - запрос (например, НаборДанныхРегистр), выгружающий строковые штрихкоды из регистра сведений.
  3. Перейдите на вкладку «Связи наборов данных».
  4. Добавьте новую строку связи:
    • Источник связи: НаборДанныхДокумент
    • Приемник связи: НаборДанныхРегистр
    • Условие связи: оставьте пустым
    • Выражение источника: Формат(ШтрихкодДок, "ЧГ=0")
    • Выражение приемника: Штрихкод

Функция Формат(..., "ЧГ=0") полностью убирает группировку разрядов (пробелы) из числа и возвращает чистую строку, пригодную для сопоставления.

Важное предупреждение о производительности: помните, что соединение наборов данных по вычисляемому выражению происходит на уровне сервера приложений 1С (постобработка), а не на СУБД. Платформа сначала получит все записи из БД для обоих наборов, а затем начнет сопоставлять их в оперативной памяти. На таблицах объемом более 10-20 тысяч строк этот метод может вызвать сильные задержки в работе отчета.

Метод 3. Исправление архитектуры данных (Рекомендуемый подход)

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

Самым правильным решением будет приведение структуры метаданных к единому стандарту. Мы рекомендуем добавить в документ строковый реквизит (например, ШтрихкодСтрокой с типом Строка(13)) и настроить его автоматическое заполнение.

Разберем по шагам, как выполнить этот переход без потери старых данных:

Шаг 1. Добавьте в документ новый реквизит ШтрихкодСтрокой (Длина 13, Допустимые символы — Любые, Индексировать — Да).

Шаг 2. В модуле объекта документа в процедуре ПередЗаписью пропишите автоматическое заполнение нового поля при изменении старого числового значения:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
	
	Если ЗначениеЗаполнено(ШтрихкодДок) Тогда
		// Преобразуем число в строку без группировки разрядов
		ШтрихкодСтрокой = Формат(ШтрихкодДок, "ЧГ=0");
	Иначе
		ШтрихкодСтрокой = "";
	КонецЕсли;
	
КонецПроцедуры

Шаг 3. Напишите и запустите разовую обработку для заполнения нового строкового реквизита в уже существующих в базе документах:


Выборка = Документы.ЗаказКлиента.Выбрать();
Пока Выборка.Следующий() Цикл
	Если ЗначениеЗаполнено(Выборка.ШтрихкодДок) И Не ЗначениеЗаполнено(Выборка.ШтрихкодСтрокой) Тогда
		ДокументОбъект = Выборка.ПолучитьОбъект();
		ДокументОбъект.ШтрихкодСтрокой = Формат(Выборка.ШтрихкодДок, "ЧГ=0");
		// Записываем без проведения и проверок для ускорения процесса
		ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
	КонецЕсли;
КонецЦикла;

После выполнения этих шагов вы сможете делать классическое, легкое и быстрое внутреннее соединение в любом запросе на уровне СУБД, используя проиндексированное строковое поле.

Метод 4. Математический метод («Академический» запрос для старых платформ)

Для полноты картины рассмотрим сложный математический алгоритм, который использовался разработчиками до появления платформы 8.3.20. Если у вас нет прав на изменение метаданных (чтобы применить Метод 3) и вы не можете использовать СКД (Метод 2), преобразовать число в строку можно чистой математикой в запросе.

Идея состоит в том, чтобы разделить число на разряды (сотни, десятки, единицы) математическими операциями деления и вычитания остатков, округлить их с помощью ВЫРАЗИТЬ КАК ЧИСЛО, а затем сопоставить каждую цифру с ее строковым символом из константы "0123456789" с помощью функции ПОДСТРОКА().

Рассмотрим пример такого математического разбора для трехзначного числа:


ВЫБРАТЬ
	ПОДСТРОКА("0123456789", ВЫРАЗИТЬ(ИсходнаяТаблица.Число / 100 - 0.5 КАК ЧИСЛО(10, 0)) + 1, 1) +
	ПОДСТРОКА("0123456789", ВЫРАЗИТЬ((ИсходнаяТаблица.Число - ВЫРАЗИТЬ(ИсходнаяТаблица.Число / 100 - 0.5 КАК ЧИСЛО(10, 0)) * 100) / 10 - 0.5 КАК ЧИСЛО(10, 0)) + 1, 1) +
	ПОДСТРОКА("0123456789", ИсходнаяТаблица.Число - ВЫРАЗИТЬ(ИсходнаяТаблица.Число / 10 - 0.5 КАК ЧИСЛО(10, 0)) * 10 + 1, 1) КАК ЧислоСтрокой
ИЗ
	Справочник.Номенклатура КАК ИсходнаяТаблица

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

Важно: для 12-значного штрихкода этот запрос вырастет до гигантских размеров и станет практически нечитаемым, а нагрузка на процессор сервера СУБД при расчете триллионных значений возрастет многократно. Используйте данный метод исключительно в крайних случаях и для небольших диапазонов чисел.

Подведем итоги

Мы проанализировали четыре принципиально разных подхода к решению проблемы сопоставления числовых и строковых значений штрихкодов в 1С. Наилучшим выбором с точки зрения чистоты кода и быстродействия является Метод 3 (исправление архитектуры). Если же вы ограничены рамками существующей конфигурации, используйте современные функции платформы Строка() и СтрЗаменить() (Метод 1) или функционал связей наборов в СКД (Метод 2).

← На главную