Оказывается существует шрифт 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 и получить работающий штрихкод.
Комментариев нет:
Отправить комментарий