gifts2017

Поиск свободного штрихкода (EAN-13) внутри одного префикса

Опубликовал Анатолий Лукьянов (KazanKokos) в раздел Программирование - Практика программирования

Частая ситуация: Крупная компания покупает штрихкод например на 99999 позиций. Пользователь ручками случайно внес штрихкод 99999. Но в выданных пределах еще много пропусков.

В обработке использовался коммент из публикации на инфостарте http://forum.infostart.ru/forum26/topic125338/

Первая функция подготавливает таблицу свободных штрихкодов. (на 77000 позициях работает 2.5-3 секунды). Ее нужно использовать до цикла присваивания штрихкодов.

Вторая выжимает из этой таблицы штрихкоды.

&НаСервере
Функция ПодготовитьТаблицуСвободныхШтрихкодов() Экспорт
 
 Запрос = Новый Запрос;
 Запрос.Текст =
 "ВЫБРАТЬ
 | ""0"" КАК Цифра,0 КАК Позиция, 1 КАК Вес
 |ПОМЕСТИТЬ СистемаСчисления
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""1"",1,10
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""2"",2,100
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""3"",3,1000
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""4"",4,10000
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""5"",5,100000
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""6"",6,1000000
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""7"",7,10000000
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""8"",8,100000000
 |ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ""9"",9,1000000000
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ
 | ""0"" + ПОДСТРОКА(ШтрихкодыНоменклатуры.Штрихкод, 8, 5) КАК Номер,
 | ШтрихкодыНоменклатуры.Штрихкод
 |ПОМЕСТИТЬ Дано
 |ИЗ
 | РегистрСведений.ШтрихкодыНоменклатуры КАК ШтрихкодыНоменклатуры
 |ГДЕ
 | ШтрихкодыНоменклатуры.Штрихкод ПОДОБНО &ПрефиксЕАН
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ
 | Дано.Штрихкод,
 | СУММА(СтепениДесяти.Вес * Цифры.Позиция) / МИНИМУМ(СтепениДесяти.Вес) КАК номер
 |ПОМЕСТИТЬ ЗанятыеШтрихкоды
 |ИЗ
 | Дано КАК Дано
 |  ВНУТРЕННЕЕ СОЕДИНЕНИЕ СистемаСчисления КАК СтепениДесяти
 |  ПО (ИСТИНА)
 |  ВНУТРЕННЕЕ СОЕДИНЕНИЕ СистемаСчисления КАК Цифры
 |  ПО (ПОДСТРОКА(Дано.Номер, 6 - СтепениДесяти.Позиция, 1) = Цифры.Цифра)
 |
 |СГРУППИРОВАТЬ ПО
 | Дано.Штрихкод
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ РАЗЛИЧНЫЕ
 | 10000 * Таб5.Позиция + 1000 * Таб4.Позиция + 100 * Таб3.Позиция + 10 * Таб2.Позиция + Таб1.Позиция + 1 КАК Число
 |ПОМЕСТИТЬ ВТ_Числа
 |ИЗ
 | СистемаСчисления КАК Таб1,
 | СистемаСчисления КАК Таб2,
 | СистемаСчисления КАК Таб3,
 | СистемаСчисления КАК Таб4,
 | СистемаСчисления КАК Таб5
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ
 | ВТ_Числа.Число КАК Номер,
 | ЕСТЬNULL(ЗанятыеШтрихкоды.Штрихкод, """") КАК Штрихкод
 |ПОМЕСТИТЬ ИндексШК
 |ИЗ
 | ВТ_Числа КАК ВТ_Числа
 |  ЛЕВОЕ СОЕДИНЕНИЕ ЗанятыеШтрихкоды КАК ЗанятыеШтрихкоды
 |  ПО (ЗанятыеШтрихкоды.Номер = ВТ_Числа.Число)
 |ГДЕ
 | ВТ_Числа.Число < 100000
 |;
 |
 |////////////////////////////////////////////////////////////////////////////////
 |ВЫБРАТЬ РАЗЛИЧНЫЕ
 | Свободные.Номер
 |ИЗ
 | ИндексШК КАК Свободные
 |ГДЕ
 | Свободные.Штрихкод = """"";
 Запрос.УстановитьПараметр("ПрефиксЕАН","%4590009%");  //Офиальный выданный компании префикс
 ДиапазоныШтучныхШтрихкодов = Запрос.Выполнить().Выгрузить();
 Если ДиапазоныШтучныхШтрихкодов.Количество() = 0 Тогда
  Возврат Неопределено;
 Иначе
  Возврат ДиапазоныШтучныхШтрихкодов;
 КонецЕсли;


КонецФункции

&НаСервере
Функция ЗанятьШтрихкод(Таблица) Экспорт
 Если Таблица.Количество() = 0 Тогда
  Возврат Неопределено;
 КонецЕсли;
 ШК = Таблица[0].Код;
 Таблица.Удалить(0); //штрихкод занят. удаляем из таблицы
 Возврат ШК;
КонецФункции 

" |ВЫБРАТЬ РАЗЛИЧНЫЕ " использована, потому что код расчета числового ряда создает дубли через каждые 10 чисел. Обойти это ошибку не смог. Главное работает. Так же пришлось добавить к текстовому индексу "0". Почему в данном случае глючит, пусть решают авторы кода создания числового ряда в запросе. Я взял их код без изменения.

Основное преимущество данного кода: Нет необходимости создания воспомогательных сущностей(регистры, справочники и т.д.) в конфигурации 1С.

См. также

Подписаться Добавить вознаграждение

Комментарии

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

Было бы интересно сравнить быстродействие на конкретном примере, поборов эти 2,5-3 секунды.
2. Анатолий Лукьянов (KazanKokos) 27.10.16 16:16
(1) ildarovich, спасибо за ссылку. я использовал запрос именно оттуда. просто не смог найти потом. 2.7 секунд на базе из 77000 штрихкодов. на клиентсервере с другого компа. точно проверено.
3. Сергей (ildarovich) 27.10.16 20:43
(2) KazanKokos, эх, не совсем то имел ввиду.

По ссылке в (1) приведена обработка, которая ОЧЕНЬ БЫСТРО определяет ВСЕ свободные номера (штрих-коды). Именно ВСЕ, потому, что ее формат вывода это диапазоны. То есть она выводит ВСЕ свободные номера От и До, не перебирая каждый номер, пытаясь определить, свободен ли он, на что в вашем варианте уходит масса времени.

Но при ближайшем рассмотрении вашей обработки оказывается, что вам не нужны все свободные штрих-коды, а достаточно одного. Тогда вообще никакой проблемы нет. Вот текст запроса, который предельно быстро покажет первый свободный номер:
ВЫБРАТЬ 0 С,    1 КАК П
ПОМЕСТИТЬ Р16
ОБЪЕДИНИТЬ ВЫБРАТЬ  1, 10
ОБЪЕДИНИТЬ ВЫБРАТЬ  2, 100
ОБЪЕДИНИТЬ ВЫБРАТЬ  3, 1000
ОБЪЕДИНИТЬ ВЫБРАТЬ  4, 10000
ОБЪЕДИНИТЬ ВЫБРАТЬ  5, 100000
ОБЪЕДИНИТЬ ВЫБРАТЬ  6, 1000000
ОБЪЕДИНИТЬ ВЫБРАТЬ  7, 10000000
ОБЪЕДИНИТЬ ВЫБРАТЬ  8, 100000000
ОБЪЕДИНИТЬ ВЫБРАТЬ  9, 1000000000
ОБЪЕДИНИТЬ ВЫБРАТЬ 10, 10000000000
ОБЪЕДИНИТЬ ВЫБРАТЬ 11, 100000000000
;
ВЫБРАТЬ СУММА(А.П * Б.С) КАК Код 
ПОМЕСТИТЬ Коды
ИЗ РегистрСведений_ШтрихкодыНоменклатуры КАК Дано, Р16 КАК А, Р16 КАК Б
ГДЕ Дано.ШтрихКод ПОДОБНО &ПрефиксЕАН
И Б.С < 10 И ПОДСТРОКА(Дано.ШтрихКод, 12 - А.С, 1) = ПОДСТРОКА("0123456789", Б.С + 1, 1)
СГРУППИРОВАТЬ ПО Дано.ШтрихКод;
ВЫБРАТЬ ПЕРВЫЕ 1 Код + 1 КАК СвободныйКод 
ИЗ Коды
ГДЕ Код + 1 НЕ В (ВЫБРАТЬ Код ИЗ Коды)
...Показать Скрыть


За основу взята статья-первоисточник Выразить строку как число и строку как дату в запросе , где, обратите внимание, оставлено только самое нужное для вашего случая.
swiss-garant; sulfur17; +2 Ответить
4. Сергей (ildarovich) 28.10.16 14:39
Вот еще один вариант. Он основан на непосредственном получении следующего кода. Без необходимости перевода в числовой тип.
В штрих-коде ищется последняя серия девяток.
Она заменяется на серию нулей.
Предшествующая цифра заменяется следующей в ряду цифр.
Начало сохраняется.
То есть решается задача инкрементирования числа непосредственно в символьном виде.

ВЫБРАТЬ 0 КАК Х ПОМЕСТИТЬ Р1 ОБЪЕДИНИТЬ ВЫБРАТЬ 1
;
ВЫБРАТЬ А.Х + 2 * Б.Х КАК Х ПОМЕСТИТЬ Р2 ИЗ Р1 КАК А, Р1 КАК Б
;
ВЫБРАТЬ А.Х + 4 * Б.Х КАК Х ПОМЕСТИТЬ Р4 ИЗ Р2 КАК А, Р2 КАК Б
;
ВЫБРАТЬ ВЫРАЗИТЬ(ПОДСТРОКА(ШтрихКод, 1, А.Х - 1) КАК СТРОКА12) 
+ ПОДСТРОКА("123456789", Б.Х + 1, 1) 
+ ПОДСТРОКА("000000000000", А.Х + 1, 12) КАК ШтрихКод
ПОМЕСТИТЬ ДаноПлюс 
ИЗ РегистрСведений_ШтрихкодыНоменклатуры, Р4 КАК А, Р4 КАК Б
ГДЕ ШтрихКод ПОДОБНО ПОДСТРОКА("%999999999999", 1, 13 - А.Х) 
И ШтрихКод НЕ ПОДОБНО ПОДСТРОКА("%999999999999", 1, 14 - А.Х)
И Б.Х < 9 И ПОДСТРОКА(ШтрихКод, А.Х, 1) = ПОДСТРОКА("012345678", Б.Х + 1, 1)
;
ВЫБРАТЬ ШтрихКод
ИЗ ДаноПлюс
ГДЕ ШтрихКод НЕ В 
(ВЫБРАТЬ Дано.ШтрихКод ИЗ РегистрСведений_ШтрихкодыНоменклатуры КАК Дано)
...Показать Скрыть


Из-за глюка движка форума ВЫРАЗИТЬ _ КАК СТРОКА12 пришлось написать без скобок вокруг 12.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа