Last active
October 20, 2024 16:55
-
-
Save alfonsrv/e630969ad189dd163446b8a6b9d7feff to your computer and use it in GitHub Desktop.
LTO Tape Barcode Labels – Print-ready (quick and easy)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python3 | |
| # -*- coding: utf-8 -*- | |
| # / ************************************* | |
| # (c) Rau Systemberatung 2024, ARJ | |
| # LTO Labelerstellung mit python-barcode | |
| # www.rausys.de | |
| # \ ************************************* | |
| __author__ = 'Rau Systemberatung GmbH' | |
| __description__ = 'LTO Label Creator' | |
| __version__ = '0.1' | |
| r''' | |
| / ******************************************************************* | |
| - 2024/04: | |
| Erstellt druckbare LTO-Label nach IBM-Vorgabe (vgl. https://suchanek.de/computer/lto-barcodes/) | |
| mit `python-barcode` aufgrund Labelangaben in `input.txt` | |
| Beispiel für `input.txt`: | |
| RZD100L8 | |
| RAU101L9 | |
| RAU102L9 | |
| RAU201L9 | |
| RAU202L9 | |
| RAU301L9 | |
| RAU302L9 | |
| RAU401L9 | |
| RAU402L9 | |
| RAU501L9 | |
| RAU502L9 | |
| RAU601L5 | |
| RAU602L5 | |
| Benötigt zur Verwendung `pip install python-barcode` | |
| \ ******************************************************************* | |
| ''' | |
| import os | |
| try: | |
| import barcode | |
| except ModuleNotFoundError: | |
| print('Barcode Library fehlt; bitte `pip3 install python-barcode` ausführen') | |
| exit(2) | |
| INPUT_FILE = "input.txt" | |
| OUTPUT_FILE = "LTO-Labels.html" | |
| WRITER_OPTIONS = { | |
| 'compress': True, | |
| 'font_size': 20, | |
| 'module_width': 0.36 | |
| } | |
| LTO_TEMPLATE = r""" | |
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | |
| <html xmlns="http://www.w3.org/1999/xhtml"> | |
| <head> | |
| <title>RAUSYS LTO Labels</title> | |
| <meta charset="utf-8" /> | |
| <meta content="nocache" http-equiv="pragma" /> | |
| <style type="text/css"> | |
| @page { | |
| size: 21cm 29.7cm; | |
| margin: 1cm 2cm 1cm 2cm; | |
| size: portrait; | |
| } | |
| @media all { | |
| #barform { | |
| visibility: visible; | |
| background-color: Red; | |
| padding: 5px; | |
| width: 307px; | |
| } | |
| .barform_r { | |
| font-size: 10px; | |
| text-align: right; | |
| padding-right: 4px; | |
| border: none; | |
| width: 60px; | |
| } | |
| .barform_i { | |
| font-size: 10px; | |
| text-align: left; | |
| padding-left: 4px; | |
| border: none; | |
| width: 200px; | |
| } | |
| .barform_d { | |
| font-size: 10px; | |
| text-align: left; | |
| border: none; | |
| width: 42px; | |
| } | |
| .barform_is { | |
| font-weight: normal; | |
| font-size: 10px; | |
| color: #000000; | |
| background: #f3f3f3; | |
| border: 1px solid #696969; | |
| width: 40px; | |
| } | |
| .barform_bs { | |
| font-weight: normal; | |
| font-size: 10px; | |
| color: #000000; | |
| background: #f3f3f3; | |
| border: 1px solid #696969; | |
| width: 60px; | |
| } | |
| #bclabel { | |
| position: relative; | |
| color: #000; | |
| background: #fff; | |
| width: 78mm; | |
| height: 16mm; | |
| padding: 2px; | |
| margin: 2px; | |
| border-collapse: collapse; | |
| border: thin solid black; | |
| z-index: 220; | |
| overflow: hidden; | |
| clear: both; | |
| } | |
| #bclabel { | |
| position: relative; | |
| color: #000; | |
| background: #fff; | |
| width: 78mm; | |
| height: 16mm; | |
| padding: 2px; | |
| margin: 2px; | |
| border-collapse: collapse; | |
| border: thin solid black; | |
| z-index: 220; | |
| overflow: hidden; | |
| clear: both; | |
| } | |
| #barbox { | |
| position: relative; | |
| width: 74mm; | |
| height: 5.5mm; | |
| padding: 0px; | |
| margin-top: 0px; | |
| margin-left: 2mm; | |
| margin-right: 2mm; | |
| z-index: 220; | |
| /* overflow:hidden;*/ | |
| } | |
| #bar { | |
| float: left; | |
| padding: 0px; | |
| width: 10mm; | |
| height: 5.5mm; | |
| padding: 0px; | |
| margin: 0px; | |
| font-weight: bold; | |
| border: thin solid black; | |
| text-align: center; | |
| } | |
| table.bar { | |
| position: inherit; | |
| display: inline; | |
| padding: 0px; | |
| margin: 0px; | |
| left: 4mm; | |
| width: 70mm; | |
| border-collapse: collapse; | |
| border: thin solid black; | |
| z-index: 210; | |
| } | |
| td.bar { | |
| padding: 0px; | |
| width: 10mm; | |
| height: 5.5mm; | |
| margin: 0px; | |
| empty-cells: show; | |
| table-layout: fixed; | |
| text-align: center; | |
| vertical-align: middle; | |
| font-weight: bold; | |
| caption-side: inherit; | |
| border: thin solid black; | |
| } | |
| .bar_code { | |
| border: none; | |
| position: inherit; | |
| display: inline; | |
| height: 12mm; | |
| left: 7mm; | |
| width: 64mm; | |
| margin: 0px; | |
| padding: 0px; | |
| z-index: 200; | |
| } | |
| .date { | |
| writing-mode: tb-lr; | |
| } | |
| #prcount { | |
| visibility: hidden; | |
| } | |
| } | |
| @media all { | |
| .bar_other { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| font-size: 16px; | |
| background: #fff; | |
| color: #000; | |
| } | |
| .bar_otherq { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| font-size: 10px; | |
| background: #fff; | |
| color: #000; | |
| } | |
| .bar_char { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numA { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numB { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numC { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numD { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numE { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numF { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numG { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numH { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numI { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numJ { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numK { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numL { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numM { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numN { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numO { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numP { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numQ { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numR { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numS { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numT { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numU { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numV { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numW { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numX { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numY { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_numZ { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00a; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num0 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #ff0000; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num1 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #ffff00; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num2 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #00ff00; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num3 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #0000ff; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num4 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #808080; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num5 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #f80; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num6 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #ff55ee; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num7 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #080; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num8 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #fa0; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| .bar_num9 { | |
| font-family: Arial, Helvetica, Sans-Serif; | |
| background: #800080; | |
| font-size: 16px; | |
| color: #fff; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <table style="border-collapse: collapse;"> | |
| <tr> | |
| <td style="padding: 0px; margin-right: -1px;" valign="top"> | |
| <table style="border-collapse: collapse; margin-right: -1px;"> | |
| <tr> | |
| <td style="padding: 0px;" valign="top"> | |
| {{ PLACEHOLDER }} | |
| </td> | |
| </tr> | |
| </table> | |
| </td> | |
| </tr> | |
| </table> | |
| </body> | |
| </html> | |
| """ | |
| LTO_FRAGMENT = r""" | |
| <div id="bclabel" style="margin: 0px; margin-bottom: -1px;"> | |
| <div id="barbox">{{ BARS }}</div> | |
| <div class="bar bar_code" style="top: -3px; left: 15px;" />{{ BARCODE }}</div> | |
| </div> | |
| """ | |
| def fragment_from_label(*, label_name: str) -> str: | |
| print(f'|--> Verarbeite: "{label_name}"') | |
| if len(label_name) < 6: | |
| print(f'[!] Label "{label_name}" kleiner 6 Stellen; vermutlich ungültig!') | |
| return | |
| _bars = [] | |
| for i, letter in enumerate(label_name): | |
| if i == 6: | |
| _bar = r"""<div class="bar_other" id="bar">{{ LETTER }}</div>""".replace(r'{{ LETTER }}', label_name[6:]) | |
| _bars.append(_bar) | |
| break | |
| _bar = r"""<div class="bar_num{{ LETTER }}" id="bar">{{ LETTER }}</div>""".replace(r'{{ LETTER }}', letter) | |
| _bars.append(_bar) | |
| label_barcode = barcode.codex.Code39(label_name, add_checksum=False).render(writer_options=WRITER_OPTIONS).decode() | |
| label_barcode = label_barcode[label_barcode.find('<svg'):] | |
| print('|--> OK') | |
| _fragment = LTO_FRAGMENT.replace(r'{{ BARCODE }}', label_barcode).replace(r'{{ BARS }}', ''.join(_bars)) | |
| return _fragment | |
| if __name__ == '__main__': | |
| print('Starting RAUSYS LTO Label Creator') | |
| print(f'Lese Datei "{INPUT_FILE}" ein...') | |
| label_catalog = [] | |
| try: | |
| with open(INPUT_FILE, mode='r') as f: | |
| label_catalog = [line.upper() for line in f.read().splitlines() if line] | |
| except FileNotFoundError: | |
| print('[!] Nicht gefunden! Bitte erstellen und Skript erneut ausführen') | |
| exit(1) | |
| _fragments = [fragment_from_label(label_name=label_name) for label_name in label_catalog] # List of LTO_FRAGMENTs | |
| print(f'Speichern als "{os.path.join(os.getcwd(), OUTPUT_FILE)}"') | |
| with open(OUTPUT_FILE, mode='w', encoding='utf-8') as f: | |
| f.write(LTO_TEMPLATE.replace(r'{{ PLACEHOLDER }}', ''.join(_fragments))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment