Оказывается существует шрифт ean13, позволяющий генерировать штрихкоды. Но напрямую его использовать нельзя, необходимо сместись символы по алгоритму, чтобы получить необходимое нам изображение.
Здесь я приведу рабочий код, с минимальным описанием. Функция преобразует уже готовые штрихкоды, с рассчитанными контрольными суммами (Как считать контрольную сумму, можно прочитать тамже). Код на Oracle PL/Sql.
Ean13 и UPC-A
Отличие штрихкода UPC-A от EAN13 в одном первом символе. В UPC-A он всегда = 0
CREATE OR REPLACE FUNCTION FNC_GET_BARCODE_EAN13 ( sFBarCode IN VARCHAR2) RETURN VARCHAR2 IS retBarCode VARCHAR2(15); lcnt INTEGER := 3; tableA BOOLEAN := FALSE; first CHAR(1); sBarCode VARCHAR2(15); BEGIN sBarCode := sFBarCode;--внутренний буфер IF(length(sBarCode) = 12) THEN sBarCode := '0' || sBarCode; ELSIF(length(sBarCode) <> 13) THEN raise_application_error(-20010, 'Штрих код EAN13 должен содержать 13 символов'); return ''; END IF; retBarCode := SUBSTR(sBarCode, 1, 1); first := retBarCode; retBarCode := retBarCode || chr(65+SUBSTR(sBarCode, 2, 1)); -- первая половина штрихкода FOR lcnt IN 3..7 LOOP tableA := FALSE; if (lcnt=3) and ((first=0) or (first=1) or (first=2) or (first=3)) THEN tableA:=TRUE; END IF; if (lcnt=4) and ((first=0) or (first=4) or (first=7) or (first=8)) THEN tableA:=TRUE; END IF; if (lcnt=5) and ((first=0) or (first=1) or (first=4) or (first=5) or (first=9)) THEN tableA:=TRUE; END IF; if (lcnt=6) and ((first=0) or (first=2) or (first=5) or (first=6) or (first=7)) THEN tableA:=TRUE; END IF; if (lcnt=7) and ((first=0) or (first=3) or (first=6) or (first=8) or (first=9)) THEN tableA:=TRUE; END IF; If tableA = TRUE THEN retBarCode := retBarCode || chr(65+SUBSTR(sBarCode, lcnt, 1)); ELSE retBarCode := retBarCode || Chr(75+SUBSTR(sBarCode, lcnt, 1)); END IF; tableA := FALSE; END LOOP; --разделитель середины штрихкода retBarCode := retBarCode || '*'; --вторая половина штрихкода lcnt:=8; FOR lcnt IN 8..13 LOOP retBarCode := retBarCode || Chr(97+SUBSTR(sBarCode, lcnt, 1)); END LOOP; --конец retBarCode := retBarCode || '+'; RETURN retBarCode; EXCEPTION WHEN OTHERS THEN RETURN ''; END;
EAN8
EAN8 имеет более простой механизм реализации, без смещений по таблице.
CREATE OR REPLACE FUNCTION FNC_GET_BARCODE_EAN8 ( sBarCode IN VARCHAR2) RETURN VARCHAR2 IS retBarCode VARCHAR2(11); lcnt INTEGER := 3; BEGIN if(length(sBarCode) <> 8) THEN raise_application_error(-20010, 'Штрих код EAN8 должен содержать 8 символов'); return ''; END IF; retBarCode := ':'; -- первая половина штрихкода FOR lcnt IN 1..4 LOOP retBarCode := retBarCode || chr(65+SUBSTR(sBarCode, lcnt, 1)); END LOOP; --разделитель середины штрихкода retBarCode := retBarCode || '*'; --вторая половина штрихкода FOR lcnt IN 5..8 LOOP retBarCode := retBarCode || Chr(97+SUBSTR(sBarCode, lcnt, 1)); END LOOP; --конец retBarCode := retBarCode || '+'; RETURN retBarCode; EXCEPTION WHEN OTHERS THEN RETURN ''; END;
Объединение предыдущих двух функций (В зависимости от переданной строки)
CREATE OR REPLACE FUNCTION FNC_GET_BARCODE_EAN ( sBarCode IN VARCHAR2) RETURN VARCHAR2 IS retBarCode VARCHAR2(15); BEGIN --Объединение EAN8 и EAN13 IF(length(sBarCode) = 8) THEN retBarCode := FNC_GET_BARCODE_EAN8(sBarCode); ELSE retBarCode := FNC_GET_BARCODE_EAN13(sBarCode); END IF; RETURN retBarCode; EXCEPTION WHEN OTHERS THEN RETURN ''; END;
Пример использования
select FNC_GET_BARCODE_EAN('35967101') AS ean8, FNC_GET_BARCODE_EAN('4607024381199') AS ean13, FNC_GET_BARCODE_EAN('607024381199') AS upc from DUAL;
Полученную строку (после работы функции FNC_GET_BARCODE_EAN) можно выводить шрифотом ean13 и получить работающий штрихкод.