Каталог решений - Штрихкодирование документов

Штрихкодирование документов

Штрихкодирование документов

В наличии

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

Категория:

Описание

Раз, два, три!.. Проверка связи. Это моя первая статья на Инфостарте, причём с материалом, который частично был разработан не мной.
Но эта наработка уже не раз помогала мне быстро и весело внедрять штрихкодирование документов в любую конфигурацию на обычных формах.

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

1. Скачиваем шрифт Barcode.ttf, ставим его на все компы пользователей. Установить можно двумя способами: а) двойной клик на файле -> Установить; б) положить файл в директорию C:\Windows\Fonts.
2. В нужных макетах печатных форм документов завести ячейку под штрихкод, в качестве шрифта ячейки указать barcode. Размер я обычно ставлю 28, дело вкуса. Это будет наш параметр "ШтрихКод"
3. Простой регистр сведений "ШтрихкодыДокументов": Измерение: Штрихкод — строка, 13 (я обычно использую EAN13, просто и сердито), ресурсы: Документ — составной тип, состоящий из штрихкодируемых документов (или просто ДокументСсылка), GUID — УникальныйИдентификатор.
4. Подписка на событие при записи документа. В подписке на событие проверяем есть ли у документа штрихкод запросом к регистру, если нет генерируем новый, не забываем проверять его уникальность.
 

Результат = Ложь;
	
	// первое: получим штрихкод из GUID-а, чтобы сразу в запросе проверить его уникальность, дабы убрать лишний запрос к БД
	GUID = СсылкаНаОбъект.УникальныйИдентификатор();
	Штрихкод = ПодготовитьШтрихКодИзGIUDа(GUID);
	
	// второе: проверяем наличие штрихкода, а так же уникальность кода в пакетном запросе
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ШтрихкодыДокументов.Штрихкод
	|ИЗ
	|	РегистрСведений.ШтрихкодыДокументов КАК ШтрихкодыДокументов
	|ГДЕ
	|	ШтрихкодыДокументов.Документ = &Документ
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ШтрихкодыДокументов.Штрихкод
	|ИЗ
	|	РегистрСведений.ШтрихкодыДокументов КАК ШтрихкодыДокументов
	|ГДЕ
	|	ШтрихкодыДокументов.Штрихкод = &Штрихкод";
	
	Запрос.УстановитьПараметр("Документ", СсылкаНаОбъект);
	Запрос.УстановитьПараметр("Штрихкод", Штрихкод);
	
	Результат = Запрос.ВыполнитьПакет();
	
	ВыборкаДетальныеЗаписи = Результат[0].Выбрать();
	
	Если ВыборкаДетальныеЗаписи.Следующий() Тогда 
		// штрихкод есть - возвращаем Истину
		Возврат Истина
	КонецЕсли;        
	
	// третье: штрихкода нет - запишем
	// сначала проверим ШК на основе GUID на уникальность:
	ВыборкаУникальность = Результат[1].Выбрать();
	Если ВыборкаУникальность.Следующий() Тогда 
		// ШК не уникален. генерируем новый
		КодУникален = Ложь;
		Пока НЕ КодУникален Цикл
			Штрихкод = ПодготовитьШтрихКодИзGIUDа(Новый УникальныйИдентификатор);
			
			Запрос = Новый Запрос;
			Запрос.Текст = 
			"ВЫБРАТЬ
			|	ШтрихкодыДокументов.Штрихкод
			|ИЗ
			|	РегистрСведений.ШтрихкодыДокументов КАК ШтрихкодыДокументов
			|ГДЕ
			|	ШтрихкодыДокументов.Штрихкод = &Штрихкод";
			
			Запрос.УстановитьПараметр("Штрихкод", Штрихкод);
			Результат = Запрос.Выполнить();
			КодУникален = Результат.Пустой();
		КонецЦикла;
	КонецЕсли;
	
	ЗаписьРегистра = РегистрыСведений.ШтрихкодыДокументов.СоздатьМенеджерЗаписи();
	ЗаписьРегистра.Документ		 = СсылкаНаОбъект;
	ЗаписьРегистра.Штрихкод		 = Штрихкод;
	ЗаписьРегистра.GUID			 = GUID;
	ЗаписьРегистра.Период		 = ТекущаяДата();
	ЗаписьРегистра.Ответственный = ПараметрыСеанса.ТекущийПользователь;
	Попытка
		ЗаписьРегистра.Записать();
		Результат = Истина;
	Исключение
		Сообщить(ОписаниеОшибки());
		Результат = Ложь;
	КонецПопытки;
	
	Возврат Результат;

Процедура ПодготовитьШтрихкодИзGUID
Суть проста — убираем из Уникального идентификатора все дефисы и буквы, если цифр не хватает — дополняем нулями. Здесь использован типовой справочник ФорматыШтрихКодов, в котором определяются префиксы для документов. Если такого нет в конфигурации, то я обычно добавляю свой, чтобы по префиксам различать типы документов.
 

фШтрихКод = фGIUD;
	
	фШтрихКод = СтрЗаменить(фШтрихКод, "-", "");
	фШтрихКод = СтрЗаменить(фШтрихКод, "a", "");
	фШтрихКод = СтрЗаменить(фШтрихКод, "b", "");
	фШтрихКод = СтрЗаменить(фШтрихКод, "c", "");
	фШтрихКод = СтрЗаменить(фШтрихКод, "d", "");
	фШтрихКод = СтрЗаменить(фШтрихКод, "e", "");
	фШтрихКод = СтрЗаменить(фШтрихКод, "f", "");
	
	фШтрихКод = Лев(фШтрихКод, фДлина);
	
	// на случай, если штрихкод оказался меньше нужной длины, дополняем его ведущими нулями
	Пока СтрДлина(фШтрихКод) < фДлина Цикл
		фШтрихКод = "0" + фШтрихКод;
	КонецЦикла;
	
	//фШтрихКод = фШтрихКод + КонтрольныйСимволEAN(фШтрихКод,13);
	фШтрихКод = Лев((""+Справочники.ФорматыШтрихКодов.ШКДокумента.Код + фШтрихКод), 12) + КонтрольныйСимволEAN(фШтрихКод,13);
	
	Возврат фШтрихКод;

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

5. У нас есть соответствие цифр и документов. Осталось превратить это в штрихкод на бумаге. Для этого в общий модуль добавляем следующие процедуры, на которые будем ссылаться при выводе на экран макета печатной формы. Здесь не нужно ничего менять и дописывать.
 

Функция Код128(A) Экспорт
 
	Перем BCode;
	Перем BInd;
	Перем CurMode;
	Перем Ch;
	Перем Ch2;
	Перем I;
	Перем LenA;
	Перем CCode;
	Перем S;
	Перем BarArray;
	СписокКБ = Новый Соответствие;
	СписокКБ.Вставить("0","0082");
	СписокКБ.Вставить("1","00:0");
	СписокКБ.Вставить("2","0802");
	СписокКБ.Вставить("3",":000");
	СписокКБ.Вставить("4","0280");
	СписокКБ.Вставить("5","2080");
	СписокКБ.Вставить("6","8002");
	СписокКБ.Вставить("7","8020");
	СписокКБ.Вставить("8","8200");
	СписокКБ.Вставить("9","2800");
	СписокКБ.Вставить("-","0802");
	СписокКБ.Вставить("$","0:00");
	СписокКБ.Вставить(":","2022");
	СписокКБ.Вставить("/","2202");
	СписокКБ.Вставить(".","2220");
	СписокКБ.Вставить("+","0222");
	СписокКБ.Вставить("a","0:00");
	СписокКБ.Вставить("b","8802");
	СписокКБ.Вставить("c","0882");
	СписокКБ.Вставить("d","08:0");
	СписокКБ.Вставить("t","0:80");
	СписокКБ.Вставить("n","8802");
	СписокКБ.Вставить("*","0882");
	СписокКБ.Вставить("e","08:0"); 	
	
	Список128 = Новый СписокЗначений;
	Список128.Добавить("212222");
    Список128.Добавить("222122");
    Список128.Добавить("222221");
    Список128.Добавить("121223");
    Список128.Добавить("121322");
    Список128.Добавить("131222");
    Список128.Добавить("122213");
    Список128.Добавить("122312");
    Список128.Добавить("132212");
    Список128.Добавить("221213");
    Список128.Добавить("221312");
    Список128.Добавить("231212");
    Список128.Добавить("112232");
    Список128.Добавить("122132");
    Список128.Добавить("122231");
    Список128.Добавить("113222");
    Список128.Добавить("123122");
    Список128.Добавить("123221");
    Список128.Добавить("223211");
    Список128.Добавить("221132");
    Список128.Добавить("221231");
    Список128.Добавить("213212");
    Список128.Добавить("223112");
    Список128.Добавить("312131");
    Список128.Добавить("311222");
    Список128.Добавить("321122");
    Список128.Добавить("321221");
    Список128.Добавить("312212");
    Список128.Добавить("322112");
    Список128.Добавить("322211");
    Список128.Добавить("212123");
    Список128.Добавить("212321");
    Список128.Добавить("232121");
    Список128.Добавить("111323");
    Список128.Добавить("131123");
    Список128.Добавить("131321");
    Список128.Добавить("112313");
    Список128.Добавить("132113");
    Список128.Добавить("132311");
    Список128.Добавить("211313");
    Список128.Добавить("231113");
    Список128.Добавить("231311");
    Список128.Добавить("112133");
    Список128.Добавить("112331");
    Список128.Добавить("132131");
    Список128.Добавить("113123");
    Список128.Добавить("113321");
    Список128.Добавить("133121");
    Список128.Добавить("313121");
    Список128.Добавить("211331");
    Список128.Добавить("231131");
    Список128.Добавить("213113");
    Список128.Добавить("213311");
    Список128.Добавить("213131");
    Список128.Добавить("311123");
    Список128.Добавить("311321");
    Список128.Добавить("331121");
    Список128.Добавить("312113");
    Список128.Добавить("312311");
    Список128.Добавить("332111");
    Список128.Добавить("314111");
    Список128.Добавить("221411");
    Список128.Добавить("431111");
    Список128.Добавить("111224");
    Список128.Добавить("111422");
    Список128.Добавить("121124");
    Список128.Добавить("121421");
    Список128.Добавить("141122");
    Список128.Добавить("141221");
    Список128.Добавить("112214");
    Список128.Добавить("112412");
    Список128.Добавить("122114");
    Список128.Добавить("122411");
    Список128.Добавить("142112");
    Список128.Добавить("142211");
    Список128.Добавить("241211");
    Список128.Добавить("221114");
    Список128.Добавить("413111");
    Список128.Добавить("241112");
    Список128.Добавить("134111");
    Список128.Добавить("111242");
    Список128.Добавить("121142");
    Список128.Добавить("121241");
    Список128.Добавить("114212");
    Список128.Добавить("124112");
    Список128.Добавить("124211");
    Список128.Добавить("411212");
    Список128.Добавить("421112");
    Список128.Добавить("421211");
    Список128.Добавить("212141");
    Список128.Добавить("214121");
    Список128.Добавить("412121");
    Список128.Добавить("111143");
    Список128.Добавить("111341");
    Список128.Добавить("131141");
    Список128.Добавить("114113");
    Список128.Добавить("114311");
    Список128.Добавить("411113");
    Список128.Добавить("411311");
    Список128.Добавить("113141");
    Список128.Добавить("114131");
    Список128.Добавить("311141");
    Список128.Добавить("411131");
    Список128.Добавить("211412");
    Список128.Добавить("211214");
    Список128.Добавить("211232");
    Список128.Добавить("2331112");   

	
	BCode = Новый Массив(1024);
	//Собираем строку кодов
	BInd = 0;
	CurMode = "";
	I = 1;
	LenA = СтрДлина(A);
	Пока (I <= LenA) Цикл
		//Текущий символ в строке
		Ch = КодСимвола(Сред(A, I, 1));
		I = I + 1;
		//Разбираем только символы от 0 до 127
		Если Ch <= 127 Тогда
			//Следующий символ
			Если I <= LenA Тогда
				Ch2 = КодСимвола(Сред(A, I, 1));
			Иначе
				Ch2 = 0;
			КонецЕсли;
			//'Пара цифр - режим С
			Если (48 <= Ch)И(Ch <= 57)И(48 <= Ch2)И(Ch2 <= 57) Тогда
				I = I + 1;
				Если BInd = 0 Тогда
					//Начало с режима С
					CurMode = "C";
					BCode[BInd] = 105;
					BInd = BInd + 1;
				ИначеЕсли CurMode <> "C" Тогда
					//Переключиться на режим С
					CurMode = "C";
					BCode[BInd] = 99;
					BInd = BInd + 1;
				КонецЕсли;
				//Добавить символ режима С
				BCode[BInd] = Число(""+Символ(Ch) + Символ(Ch2));
				BInd = BInd + 1;
			Иначе
				Если BInd = 0 Тогда
					Если Ch < 32 Тогда
						//Начало с режима A
						CurMode = "A";
						BCode[BInd] = 103;
						BInd = BInd + 1;
					Иначе
						//Начало с режима B
						CurMode = "B";
						BCode[BInd] = 104;
						BInd = BInd + 1;
					КонецЕсли;
				КонецЕсли;
				//Переключение по надобности в режим A
				Если (Ch < 32)И(CurMode <> "A") Тогда
					CurMode = "A";
					BCode[BInd] = 101;
					BInd = BInd + 1;
					//Переключение по надобности в режим B
				ИначеЕсли ((64 <= Ch)И(CurMode <> "B"))ИЛИ(CurMode = "C") Тогда
					CurMode = "B";
					BCode[BInd] = 100;
					BInd = BInd + 1;
				КонецЕсли;
				//Служебные символы
				Если (Ch < 32) Тогда
					BCode[BInd] = Ch + 64;
					BInd = BInd + 1;
					//Все другие символы
				Иначе
					BCode[BInd] = Ch - 32;
					BInd = BInd + 1;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	//Подсчитываем контрольную сумму 
	CCode = MOD(BCode[0],103);
	Для I = 1 По BInd - 1 Цикл
		CCode = MOD(CCode + BCode[I] * I,103);
	КонецЦикла;
	BCode[BInd] = CCode;
	BInd = BInd + 1;
	//Завершающий символ
	BCode[BInd] = 106;
	BInd = BInd + 1;
	//Собираем строку символов шрифта
	S = "";
	Для I = 0 По BInd - 1 Цикл
		S = S + Code_Char(Список128[BCode[I]].Значение);
	КонецЦикла;
	Возврат S;
 
КонецФункции

Процедура КонструкторШК()
	
	СписокКБ = Новый Соответствие;
	СписокКБ.Вставить("0","0082");
	СписокКБ.Вставить("1","00:0");
	СписокКБ.Вставить("2","0802");
	СписокКБ.Вставить("3",":000");
	СписокКБ.Вставить("4","0280");
	СписокКБ.Вставить("5","2080");
	СписокКБ.Вставить("6","8002");
	СписокКБ.Вставить("7","8020");
	СписокКБ.Вставить("8","8200");
	СписокКБ.Вставить("9","2800");
	СписокКБ.Вставить("-","0802");
	СписокКБ.Вставить("$","0:00");
	СписокКБ.Вставить(":","2022");
	СписокКБ.Вставить("/","2202");
	СписокКБ.Вставить(".","2220");
	СписокКБ.Вставить("+","0222");
	СписокКБ.Вставить("a","0:00");
	СписокКБ.Вставить("b","8802");
	СписокКБ.Вставить("c","0882");
	СписокКБ.Вставить("d","08:0");
	СписокКБ.Вставить("t","0:80");
	СписокКБ.Вставить("n","8802");
	СписокКБ.Вставить("*","0882");
	СписокКБ.Вставить("e","08:0"); 	
	
	Список128 = Новый СписокЗначений;
	Список128.Добавить("212222");
    Список128.Добавить("222122");
    Список128.Добавить("222221");
    Список128.Добавить("121223");
    Список128.Добавить("121322");
    Список128.Добавить("131222");
    Список128.Добавить("122213");
    Список128.Добавить("122312");
    Список128.Добавить("132212");
    Список128.Добавить("221213");
    Список128.Добавить("221312");
    Список128.Добавить("231212");
    Список128.Добавить("112232");
    Список128.Добавить("122132");
    Список128.Добавить("122231");
    Список128.Добавить("113222");
    Список128.Добавить("123122");
    Список128.Добавить("123221");
    Список128.Добавить("223211");
    Список128.Добавить("221132");
    Список128.Добавить("221231");
    Список128.Добавить("213212");
    Список128.Добавить("223112");
    Список128.Добавить("312131");
    Список128.Добавить("311222");
    Список128.Добавить("321122");
    Список128.Добавить("321221");
    Список128.Добавить("312212");
    Список128.Добавить("322112");
    Список128.Добавить("322211");
    Список128.Добавить("212123");
    Список128.Добавить("212321");
    Список128.Добавить("232121");
    Список128.Добавить("111323");
    Список128.Добавить("131123");
    Список128.Добавить("131321");
    Список128.Добавить("112313");
    Список128.Добавить("132113");
    Список128.Добавить("132311");
    Список128.Добавить("211313");
    Список128.Добавить("231113");
    Список128.Добавить("231311");
    Список128.Добавить("112133");
    Список128.Добавить("112331");
    Список128.Добавить("132131");
    Список128.Добавить("113123");
    Список128.Добавить("113321");
    Список128.Добавить("133121");
    Список128.Добавить("313121");
    Список128.Добавить("211331");
    Список128.Добавить("231131");
    Список128.Добавить("213113");
    Список128.Добавить("213311");
    Список128.Добавить("213131");
    Список128.Добавить("311123");
    Список128.Добавить("311321");
    Список128.Добавить("331121");
    Список128.Добавить("312113");
    Список128.Добавить("312311");
    Список128.Добавить("332111");
    Список128.Добавить("314111");
    Список128.Добавить("221411");
    Список128.Добавить("431111");
    Список128.Добавить("111224");
    Список128.Добавить("111422");
    Список128.Добавить("121124");
    Список128.Добавить("121421");
    Список128.Добавить("141122");
    Список128.Добавить("141221");
    Список128.Добавить("112214");
    Список128.Добавить("112412");
    Список128.Добавить("122114");
    Список128.Добавить("122411");
    Список128.Добавить("142112");
    Список128.Добавить("142211");
    Список128.Добавить("241211");
    Список128.Добавить("221114");
    Список128.Добавить("413111");
    Список128.Добавить("241112");
    Список128.Добавить("134111");
    Список128.Добавить("111242");
    Список128.Добавить("121142");
    Список128.Добавить("121241");
    Список128.Добавить("114212");
    Список128.Добавить("124112");
    Список128.Добавить("124211");
    Список128.Добавить("411212");
    Список128.Добавить("421112");
    Список128.Добавить("421211");
    Список128.Добавить("212141");
    Список128.Добавить("214121");
    Список128.Добавить("412121");
    Список128.Добавить("111143");
    Список128.Добавить("111341");
    Список128.Добавить("131141");
    Список128.Добавить("114113");
    Список128.Добавить("114311");
    Список128.Добавить("411113");
    Список128.Добавить("411311");
    Список128.Добавить("113141");
    Список128.Добавить("114131");
    Список128.Добавить("311141");
    Список128.Добавить("411131");
    Список128.Добавить("211412");
    Список128.Добавить("211214");
    Список128.Добавить("211232");
    Список128.Добавить("2331112");   

КонецПроцедуры //КонструкторШК()

////
Функция Кодабар(КодШК)   
	
	//Перем ШтрихКод;	
	//ШтрихКод = "";
	//Для Н = 1 По СтрДлина(КодШК) Цикл
	//    ШтрихКод = ШтрихКод + СписокКБ.Получить(Сред(КодШК, Н, 1));
	//КонецЦикла;   
	//ШтрихКод = СписокКБ.Получить("d") + ШтрихКод + СписокКБ.Получить("e");
	//
	//Возврат ШтрихКод;
	
КонецФункции //Кодабар()

//Функция получает остаток при делении
// Параметры:
//	Делимое  <число> - число, которое делим
//	Делитель <число> - число, на которое делим
// Возвращаемое значение:
//	Рез 	 <число> - остаток при делении
//
Функция MOD(Делимое,Делитель)
	
	Перем Рез;
	Рез=0;
	Частное=Цел(Делимое/Делитель);
	Рез=Делимое-Частное*Делитель;   
	Возврат Рез;
	
КонецФункции //MOD() 

//Штриховые символы шрифта iQs Code 128 по набору полос
//
Функция Code_Char(A)
	
	Перем S;
	Перем I;
	Перем B;
	Если A="211412" Тогда S = "A"; Возврат S; КонецЕсли;
	Если A="211214" Тогда S = "B"; Возврат S; КонецЕсли;
	Если A="211232" Тогда S = "C"; Возврат S; КонецЕсли;
	Если A="2331112"Тогда S = "@"; Возврат S; КонецЕсли;
	S = ""; 
	LenA=СтрДлина(A);
	Для I = 0 По (LenA/ 2 - 1) Цикл
		Стр=Сред(A, 2 * I + 1, 2); 
		Если Стр="11"      Тогда S = S+"0";Продолжить;
		ИначеЕсли Стр="21" Тогда S = S+"1";Продолжить;
		ИначеЕсли Стр="31" Тогда S = S+"2";Продолжить;
		ИначеЕсли Стр="41" Тогда S = S+"3";Продолжить;
		ИначеЕсли Стр="12" Тогда S = S+"4";Продолжить;
		ИначеЕсли Стр="22" Тогда S = S+"5";Продолжить;
		ИначеЕсли Стр="32" Тогда S = S+"6";Продолжить;
		ИначеЕсли Стр="42" Тогда S = S+"7";Продолжить;
		ИначеЕсли Стр="13" Тогда S = S+"8";Продолжить;
		ИначеЕсли Стр="23" Тогда S = S+"9";Продолжить;
		ИначеЕсли Стр="33" Тогда S = S+":";Продолжить; 
		ИначеЕсли Стр="43" Тогда S = S+";";Продолжить; 
		ИначеЕсли Стр="14" Тогда S = S+"<";Продолжить;     
		ИначеЕсли Стр="24" Тогда S = S+"=";Продолжить; 
		ИначеЕсли Стр="34" Тогда S = S+">";Продолжить; 
		ИначеЕсли Стр="44" Тогда S = S+"?";Продолжить; 
		КонецЕсли;
	КонецЦикла;
	
	Возврат S; 
	
КонецФункции //Code_Char()

6. В процедуре вывода табличного документа на экран нужно добавить только две строки кода:

ШтрихКод = ПолучитьШтрихКодДокумента(ЭтотОбъект.Ссылка);
ОбластьМакета.Параметры.ШтрихКод = [ИмяВашегоОбщегоМодуля].Код128(ШтрихКод);
ОбластьМакета.Параметры.Код = ШтрихКод;

ПолучитьШтрихКодДокумента — просто получает цифры штрихкода из регистра сведений "ШтрихкодыДокументов".
Всё! Штрихкод готов, я получаю профит, клиент доволен. В дальнейшем обрабатывать событие сканирования очень легко — просто подтягиваем по номеру ссылку на документ из регистра и делаем с ним что угодно.

has been added to your cart:
Оформление заказа