Technical Article

Uitgebreide handleiding voor het genereren van PDF-barcodes

· PDF-programmeren

Leer hoe u met de HotPDF Delphi-component verschillende barcodetypen in PDF-documenten genereert en waar u bij productiegebruik op moet letten.

Dit artikel is bedoeld voor ontwikkelaars die met pdf-programmeren werken. Productnamen, API-namen, bestandsnamen en codefragmenten zijn bewust ongewijzigd gehouden, zodat de voorbeelden direct met de oorspronkelijke documentatie en broncode te vergelijken zijn.

Overzicht

De pagina beschrijft het probleemgebied, de relevante implementatiekeuzes en de controles die belangrijk zijn voordat de oplossing in een echte toepassing wordt gebruikt.

Codevoorbeeld

Het onderstaande codefragment is ongewijzigd uit de Engelse bron overgenomen om identifiers, API-aanroepen en syntaxis exact te behouden.

1
2
3
Code 128A: Uppercase letters, control characters, digits
Code 128B: Mixed case letters, digits, special characters  
Code 128C: Numeric pairs encoded as single characters (high density)
1
2
3
4
5
6
7
8
9
10
11
Legacy Approach:
1. Generate barcode as image file
2. Load image into PDF library
3. Position and scale image
4. Handle cleanup of temporary files
 
Modern Approach:
1. Direct barcode generation within PDF context
2. Vector-based output for scalability
3. Integrated positioning and sizing
4. No temporary file management required
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
program Barcodes;
{$APPTYPE CONSOLE}
 
uses
  System.Classes,
  System.SysUtils,
  Vcl.Graphics,
  HPDFDoc;
 
var
  I, H: Integer;
  HotPDF: THotPDF;
 
const
  Names: array [0 .. 21] of AnsiString = (
    'Code 25 Interleaved', 'Code 25 Industrial', 'Code 25 Matrix',
    'Code39', 'Code39 Extended', 'Code128A', 'Code128B', 'Code128C',
    'Code93', 'Code93 Extended', 'MSI', 'PostNet', 'Codebar',
    'EAN8', 'EAN13', 'UPC_A', 'UPC_E0', 'UPC_E1',
    'UPC Supp2', 'UPC Supp5', 'EAN128A', 'EAN128B'
  );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function GetBarcodeText(BarcodeType: Integer): AnsiString;
begin
  case BarcodeType of
    0, 1, 2: Result := '12345678'; // Code 25 variants (digits only)
    3: Result := 'ABC123'; // Code39 (alphanumeric)
    4: Result := 'Code39Ext'; // Code39 Extended (mixed case)
    5, 6: Result := 'Hello123'; // Code128A/B (text)
    7: Result := '123456789012'; // Code128C (digits only, even length)
    8: Result := 'CODE93'; // Code93 (uppercase)
    9: Result := 'Code93Ext'; // Code93 Extended (mixed case)
    10: Result := '123456789'; // MSI (digits only)
    11: Result := '12345'; // PostNet (ZIP code)
    12: Result := 'A12345B'; // Codabar (starts/ends with letter)
    13: Result := '1234567'; // EAN8 (7 digits, check digit added)
    14: Result := '123456789012'; // EAN13 (12 digits, check digit added)
    15: Result := '012345678905'; // UPC_A (12 digits)
    16, 17: Result := '1234567'; // UPC_E variants (7 digits)
    18: Result := '59'; // UPC Supp2 (2 digits)
    19: Result := '12345'; // UPC Supp5 (5 digits)
    20, 21: Result := 'EAN128TEST'; // EAN128 variants (text)
    else Result := '12345'; // Default
  end;
end;
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
begin
  HotPDF := THotPDF.Create(nil);
  try
    HotPDF.AutoLaunch := true;
    HotPDF.FileName := 'Barcodes.pdf';
    HotPDF.BeginDoc;
    
    // Display 22 barcode types in a compact layout (4 columns x 6 rows)
    for I := 0 to 5 do // 6 rows (0-5)
    begin
      for H := 0 to 3 do // 4 columns (0-3)
      begin
        if ((I * 4) + H) > 21 then Break; // Total 22 barcodes (0-21)
        
        // Use new DirectDrawBarcode method with compact size
        HotPDF.CurrentPage.DirectDrawBarcode(
          H * 130 + 30,     // X position (tighter spacing)
          I * 110 + 40,     // Y position
          100, 30,          // Width, Height (optimized for clarity)
          GetBarcodeText((I * 4) + H), // Appropriate test data
          (I * 4) + H       // BarcodeType (0-21)
        );
        
        HotPDF.CurrentPage.SetFont('Arial', [], 6);
        HotPDF.CurrentPage.TextOut(H * 130 + 30, I * 110 + 75, 0,
          Names[(I * 4) + H]);
      end;
    end;
    
    HotPDF.EndDoc;
  finally
    HotPDF.Free;
  end;
end.
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
int main(int argc, char* argv[])
{
    THotPDF* HotPDF = NULL;
    
    try
    {
        HotPDF = new THotPDF(NULL);
        HotPDF->AutoLaunch = true;
        HotPDF->FileName = "Barcodes.pdf";
        HotPDF->BeginDoc();
        
        std::cout << "Creating PDF with 22 different barcode types..." << std::endl;
        
        // Implementation continues...
    }
    catch (Exception& E)
    {
        std::cerr << "Error: " << E.Message.c_str() << std::endl;
        if (HotPDF) delete HotPDF;
        return 1;
    }
    catch (...)
    {
        std::cerr << "Unknown error occurred!" << std::endl;
        if (HotPDF) delete HotPDF;
        return 1;
    }
    
    if (HotPDF) delete HotPDF;
    return 0;
}
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
// Array of barcode type names
const AnsiString Names[22] = {
    "Code 25 Interleaved", "Code 25 Industrial", "Code 25 Matrix",
    "Code39", "Code39 Extended", "Code128A", "Code128B", "Code128C",
    "Code93", "Code93 Extended", "MSI", "PostNet", "Codebar",
    "EAN8", "EAN13", "UPC_A", "UPC_E0", "UPC_E1",
    "UPC Supp2", "UPC Supp5", "EAN128A", "EAN128B"
};
 
// Function to get appropriate test text for each barcode type
AnsiString GetBarcodeText(int BarcodeType)
{
    switch (BarcodeType)
    {
        case 0: case 1: case 2:
            return "12345678"; // Code 25 variants (digits only)
        case 3:
            return "ABC123"; // Code39 (alphanumeric)
        case 4:
            return "Code39Ext"; // Code39 Extended (mixed case)
        // Additional cases for all 22 barcode types...
        default:
            return "12345"; // Default fallback
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
for (int I = 0; I <= 5; I++) // 6 rows (0-5)
{
    for (int H = 0; H <= 3; H++) // 4 columns (0-3) { int barcodeIndex = (I * 4) + H; if (barcodeIndex > 21) break; // Total 22 barcodes (0-21)
        
        // Generate barcode with optimized parameters
        HotPDF->CurrentPage->DirectDrawBarcode(
            H * 130 + 30,           // X position
            I * 110 + 40,           // Y position
            100, 30,                // Width, Height
            GetBarcodeText(barcodeIndex),  // Appropriate test data
            barcodeIndex            // BarcodeType (0-21)
        );
        
        // Add descriptive label
        HotPDF->CurrentPage->SetFont("Arial", TFontStyles(), 6);
        HotPDF->CurrentPage->TextOut(
            H * 130 + 30, I * 110 + 75, 0, Names[barcodeIndex]
        );
        
        // Provide progress feedback
        std::cout << "Generated barcode " << (barcodeIndex + 1) << "/22: "
                 << Names[barcodeIndex].c_str() << std::endl;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Code 128 Subset A:
- ASCII characters 00-95 (0-9, A-Z, control characters)
- Start character: 11010000100
- Used for: Uppercase text, control characters
 
Code 128 Subset B:  
- ASCII characters 32-127 (0-9, A-Z, a-z, special characters)
- Start character: 11010010000
- Used for: Mixed case text, standard keyboard characters
 
Code 128 Subset C:
- Numeric pairs 00-99 encoded as single characters
- Start character: 11010011100
- Used for: High-density numeric data (even number of digits)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
UPC-A Structure:
- 12 digits total
- First digit: Number system character
- Next 5 digits: Manufacturer code
- Next 5 digits: Product code  
- Last digit: Check digit (calculated)
 
EAN-13 Structure:
- 13 digits total
- First 2-3 digits: Country code
- Next 4-5 digits: Manufacturer code
- Next 5 digits: Product code
- Last digit: Check digit (calculated)
 
EAN-8 Structure:
- 8 digits total
- First 2-3 digits: Country code
- Next 4-5 digits: Product code
- Last digit: Check digit (calculated)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PDF Barcode Object Structure:
1 0 obj
<<
  /Type /XObject
  /Subtype /Form
  /BBox [0 0 100 30]
  /Matrix [1 0 0 1 0 0]
  /Resources << /ProcSet [/PDF] >>
  /Length 245
>>
stream
q
1 0 0 1 0 0 cm
% Barcode drawing commands
0.8 w
0 0 m
0 30 l
S
% Additional barcode elements...
Q
endstream
endobj
1
2
3
4
5
6
7
Build Script Features:
- Platform detection (Win32/Win64)
- Compiler optimization settings
- Library path configuration
- Automatic dependency resolution
- Error handling and reporting
- Post-build testing and validation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Delphi memory management best practices
try
  HotPDF := THotPDF.Create(nil);
  try
    // Barcode generation operations
    HotPDF.BeginDoc;
    // ... generation code ...
    HotPDF.EndDoc;
  finally
    HotPDF.Free; // Ensure proper cleanup
  end;
except
  on E: Exception do
  begin
    // Handle errors gracefully
    WriteLn('Error: ', E.Message);
  end;
end;

Praktische aandachtspunten

  • Controleer invoerbestanden en foutpaden expliciet voordat u de routine in productie gebruikt.
  • Houd paginalay-out, lettertypen en coördinaten reproduceerbaar, vooral bij server-side verwerking.
  • Test het resultaat in meer dan één PDF-viewer wanneer rendering, annotaties of interactieve elementen belangrijk zijn.
  • Laat componentlevensduur en bestandshandles altijd via try/finally-achtige patronen opruimen.