PHP: stampa di codici a barre EAN13 e UPC-A con le librerie EzPDF

Codice EAN13 con ezPdfLa libreria di classi R&OS non dispone di metodi per la creazione di codici a barre, è necessartio ricorrere a soluzioni esterne. Esistono principalmente due differenti modi di stampare i codici a barre in un documento PDF. Uno si basa sulla generazione di un immagine bitmap e la successiva importazione nel documento attraverso i metodi di visualizzazione delle immagini. Il secondo invece, si basa sulla generazione della sequenza di barre utilizzando l’apposito algoritmo e i metodi di disegno dei rettangoli della classe PDF.
Se si preferisce il primo metodo, si può utilizzare PHP-Barcode 0.3pl1, oppure il pacchetto PEAR-PHP: Image_Barcode. Entrambi fanno uso delle librerie grafiche PHP GD per generare immagini del codice a barre.

Pur considerando che il primo metodo ha i suoi vantaggi, trovo che la possibiltà di generare direttamente le barre sia il sistema più efficiente. Il problema principale era dover costruire l’algoritmo per il disegno delle barre, ma una breve ricerca sul forum di EzPDF (PDF-PHP) mi ha facilitato il compito: esiste infatti uno script già pronto per l’utilizzo con le librerie FPDF, si tratta quindi solo di modificarlo per farlo girare con i metodi di EzPDF. Questo script implementa la generazione di codici di tipo EAN13 e UPC-A, che sono peraltro i più diffusi, rispettivamente in Europa e negli Stati Uniti.

La conversione dello script è stata piuttosto semplice perché i metodi di FPDF hanno i corrispettivi nelle librerie EzPDF. Praticamente, l’unica correzione è stata fatta sulla scala dei punti. Il risultato finale è una classe che estende le librerie EzPDF ed integra i metodi per la generazione dei codici a barre. Il codice rimane così molto pulito senza la necessità di ricorrere a terze parti o programmi esterni:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
require('class.ezpdf.php');
class PDF extends Cezpdf {
 function EAN13($x,$y,$barcode,$h=45.3543307087,$w=0.992125984252)
   //$h=16 * 72/25.4; $w=.35 * 72/25.4;
   {
     $this->Barcode($x,$y,$barcode,$h,$w,13);
   }
 function UPC_A($x,$y,$barcode,$h=45.3543307087,$w=0.992125984252)
   //$h=16 * 72/25.4; $w=.35 * 72/25.4;
   {
     $this->Barcode($x,$y,$barcode,$h,$w,12);
   }
 function GetCheckDigit($barcode) {
   //Compute the check digit
   $sum=0;
   for($i=1;$i<=11;$i+=2)
     $sum+=3*$barcode{$i};
   for($i=0;$i<=10;$i+=2)
     $sum+=$barcode{$i};
     $r=$sum%10;
   if($r>0)
     $r=10-$r;
   return $r;
 }  
 function TestCheckDigit($barcode) {
  //Test validity of check digit
  $sum=0;
  for($i=1;$i<=11;$i+=2)
   $sum+=3*$barcode{$i};
  for($i=0;$i<=10;$i+=2)
   $sum+=$barcode{$i};
  return ($sum+$barcode{12})%10==0;
 }  
 function Barcode($x,$y,$barcode,$h,$w,$len) {
  //Padding
  $barcode=str_pad($barcode,$len-1,'0',STR_PAD_LEFT);
  if($len==12)
   $barcode='0'.$barcode;
  //Add or control the check digit
  if(strlen($barcode)==12)
   $barcode.=$this->GetCheckDigit($barcode);
  elseif(!$this->TestCheckDigit($barcode))
   die('Incorrect check digit');
  //Convert digits to bars
  $codes=array(
   'A'=>array(
   '0'=>'0001101','1'=>'0011001','2'=>'0010011','3'=>'0111101','4'=>'0100011',
   '5'=>'0110001','6'=>'0101111','7'=>'0111011','8'=>'0110111','9'=>'0001011'),
   'B'=>array(
   '0'=>'0100111','1'=>'0110011','2'=>'0011011','3'=>'0100001','4'=>'0011101',
   '5'=>'0111001','6'=>'0000101','7'=>'0010001','8'=>'0001001','9'=>'0010111'),
   'C'=>array(
   '0'=>'1110010','1'=>'1100110','2'=>'1101100','3'=>'1000010','4'=>'1011100',
   '5'=>'1001110','6'=>'1010000','7'=>'1000100','8'=>'1001000','9'=>'1110100')
  );
  $parities=array(
   '0'=>array('A','A','A','A','A','A'),
   '1'=>array('A','A','B','A','B','B'),
   '2'=>array('A','A','B','B','A','B'),
   '3'=>array('A','A','B','B','B','A'),
   '4'=>array('A','B','A','A','B','B'),
   '5'=>array('A','B','B','A','A','B'),
   '6'=>array('A','B','B','B','A','A'),
   '7'=>array('A','B','A','B','A','B'),
   '8'=>array('A','B','A','B','B','A'),
   '9'=>array('A','B','B','A','B','A')
  );
  $code='101';
  $p=$parities[$barcode{0}];
  for($i=1;$i<=6;$i++)
   $code.=$codes[$p[$i-1]][$barcode{$i}];
  $code.='01010';
  for($i=7;$i<=12;$i++)
   $code.=$codes['C'][$barcode{$i}];
  $code.='101';
  //Draw bars
  for($i=0;$i<strlen($code);$i++) {
   if($code{$i}=='1')
     $this->filledRectangle($x+$i*$w,$y,$w,$h);
  }
  $last_x = $x+$i*$w;
  //Print text uder barcode
  $this->selectFont('./fonts/Courier');
  $font_size = 12;
  $start_text = $x + (($last_x - $x) - $font_size*.6*$len) /2;
  $this->addText($start_text,$y-11,$font_size,substr($barcode,-$len)); 
 }
}
?>

Un esempio di codice per l’applicazione della classe:

1
2
3
4
5
6
7
<?php
require('ezbarcode.php');
$pdf =&amp; new PDF('a4','portrait');
$pdf->selectFont('./fonts/Courier');
$pdf->EAN13(40,700,'123456789012');
$pdf->stream();
?>

Questo è il risultato, il file è scaricabile qui.

Ho ritoccato la stampa del testo sotto il codice in modo che la stringa venga centrata. Per fare questo ho utilizzato il font Courier che ha la proprietà di avere i caratteri di lunghezza fissa.

Conclusioni:

Mi sembra una soluzione semplice ed efficace per quanti abitualmente utilizzano le librerie PDF di R&OS. Potrà essere utile anche a chi utilizza queste librerie per la stampa di PDF con il framework PHP: P4A2. Gli utilizzatori di P4A3 potrebbero essere anche interessati a questo progetto dello Zend Framework.

Riferimenti ed approfondimenti:


Alberto ha scritto:

Ciao, complimenti per l’articolo molto ben fatto!!!
Non sono molto pratico della libreria PDF come posso fare se volessi aggiungere più codici a barre sulla stessa pagina? grazie!!!!

Alberto
21.04.09 10:23
Mario Spada ha scritto:

Ciao Alberto, per mettere più codici sulla stessa pagina basta inserire il metodo $pdf->EAN13() in un ciclo. Per esempio:

foreach ($data as $riga){
$pdf->EAN13($x,$y,$riga[‘barcode’]);
$x+= $a;
$y-=$b;
}

dove $a e $b sono rispettivamente gli shift delle coordinate della pagina e $data è un array multidimensionale che contiene i dati, e ‘barcode’ è il nome del campo che contiene i valori dei codici a barre. Ovviamente devi controllare $a e $b per avere il numero di colonne che desideri e fare il salto pagina dove vuoi tu…!