Compare commits

...

14 commits
v0.1 ... main

Author SHA1 Message Date
aborelis
75e39bf8a3
Merge pull request #1 from OliverFriedrich/main
Alignment for print and small layout improvements

options to handle invalid vertical and/or horizontal printer alignment
remove additional padding from qr code
use qr code margin option also as minimum spacing to upper and lower label border
fix positioning of ASN number
Add Avery L7871 label definition (it's a clone of 4731)
2025-09-21 15:13:26 +02:00
OliverFriedrich
be654118bb * updated README.md 2025-03-28 19:57:11 +01:00
OliverFriedrich
55f9f91b55 * options to handle invalid vertical and/or horizontal printer alignment
* remove additional padding from qr code
* use qr code margin option also as minimum spacing to upper and lower label border
* fix positioning of ASN number
* Add Avery L7871 label definition (it's a clone of 4731)
2025-03-28 00:43:38 +01:00
Aborelis
9137595e22 docs update 2024-05-15 11:28:22 +02:00
Aborelis
cf486c9416 docs update 2024-05-15 11:15:12 +02:00
Aborelis
59d3d1fa8a docs update 2024-05-15 02:01:26 +02:00
Aborelis
c10b5f2bdd docs update 2024-05-15 02:00:14 +02:00
Aborelis
e9e64e95f5 Docker support 2024-05-15 01:56:04 +02:00
Aborelis
de48bf919a smaller improvements and inital Docker support 2024-05-15 00:03:38 +02:00
Aborelis
b3494b15f6 cleanp 2024-05-14 02:15:42 +02:00
Aborelis
26138614e3 cleanp 2024-05-14 02:12:57 +02:00
Aborelis
a9337407b7 cleanup 2024-05-14 02:06:55 +02:00
Aborelis
b8cdab0e4a cleanup 2024-05-14 01:54:36 +02:00
aborelis
e2bb5dfc9c
Create pylint.yml 2024-05-14 01:23:51 +02:00
8 changed files with 366 additions and 249 deletions

23
.github/workflows/pylint.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: Pylint
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pylint
- name: Analysing the code with pylint
run: |
pylint $(git ls-files '*.py')

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
__pycache__
venv
.idea
/*.pdf
out/*.pdf

View file

@ -23,70 +23,75 @@ from reportlab.lib.units import mm, cm
labelInfo = { labelInfo = {
# 22x 32mm x 10mm mini labels # 22x 32mm x 10mm mini labels
3044: ( 2, 11, (32, 10), (2,2), (1, 1), (66.5*mm, 120.5*mm)), 3044: (2, 11, (32, 10), (2, 2), (1, 1), (66.5 * mm, 120.5 * mm)),
# 189x 25.4mm x 10mm mini labels # 189x 25.4mm x 10mm mini labels
4731: ( 7, 27, (25.4*mm, 10*mm), (2.5*mm, 0), (9*mm, 13.5*mm), A4), 4731: (7, 27, (25.4 * mm, 10 * mm), (2.5 * mm, 0), (9 * mm, 13.5 * mm), A4),
7871: (7, 27, (25.4 * mm, 10 * mm), (2.5 * mm, 0), (9 * mm, 13.5 * mm), A4),
# 2.6 x 1 address labels # 2.6 x 1 address labels
5160: ( 3, 10, (187, 72), (11, 0), (14, 36), A4), 5160: (3, 10, (187, 72), (11, 0), (14, 36), A4),
5161: ( 2, 10, (288, 72), (0, 0), (18, 36), A4), 5161: (2, 10, (288, 72), (0, 0), (18, 36), A4),
# 4 x 2 address labels # 4 x 2 address labels
5163: ( 2, 5, (288, 144), (0, 0), (18, 36), A4), 5163: (2, 5, (288, 144), (0, 0), (18, 36), A4),
# 1.75 x 0.5 return address labels # 1.75 x 0.5 return address labels
5167: ( 4, 20, (126, 36), (0, 0), (54, 36), A4), 5167: (4, 20, (126, 36), (0, 0), (54, 36), A4),
# 3.5 x 2 business cards # 3.5 x 2 business cards
5371: ( 2, 5, (252, 144), (0, 0), (54, 36), A4), 5371: (2, 5, (252, 144), (0, 0), (54, 36), A4),
# 48x 45.7x21.2mm # 48x 45.7x21.2mm
4778: (4, 12, (45.7*mm, 21.2*mm), (0.25*cm, 0), (1.1*cm, 2*cm), A4), 4778: (4, 12, (45.7 * mm, 21.2 * mm), (0.25 * cm, 0), (1.1 * cm, 2 * cm), A4),
# APLI 100984 40x 52.5x29.7mm # APLI 100984 40x 52.5x29.7mm
100984: (4, 10, (52.5*mm, 29.7*mm), (0, 0), (0, 0), A4), 100984: (4, 10, (52.5 * mm, 29.7 * mm), (0, 0), (0, 0), A4),
} }
class AveryLabel: class AveryLabel:
def __init__(self, label, **kwargs): def __init__(self, label, pageoffset, **kwargs):
data = labelInfo[label] data = labelInfo[label]
self.across = data[0] self.across = data[0]
self.down = data[1] self.down = data[1]
self.size = data[2] self.size = data[2]
self.labelsep = self.size[0]+data[3][0], self.size[1]+data[3][1] self.labelsep = self.size[0] + data[3][0], self.size[1] + data[3][1]
self.margins = data[4] self.margins = data[4]
self.topDown = True self.top_down = True
self.debug = False self.debug = False
self.pagesize = data[5] self.pagesize = data[5]
self.position = 0 self.position = 0
self.pageoffset = pageoffset
self.__dict__.update(kwargs) self.__dict__.update(kwargs)
def open(self, filename): def open(self, filename):
self.canvas = canvas.Canvas( filename, pagesize=self.pagesize ) """open a canvas for the file"""
self.canvas = canvas.Canvas(filename, pagesize=self.pagesize)
if self.debug: if self.debug:
self.canvas.setPageCompression( 0 ) self.canvas.setPageCompression(0)
self.canvas.setLineJoin(1) self.canvas.setLineJoin(1)
self.canvas.setLineCap(1) self.canvas.setLineCap(1)
def topLeft(self, x=None, y=None): def top_left(self, x=None, y=None):
""" return top left"""
if x is None: if x is None:
x = self.position x = self.position
if y is None: if y is None:
if self.topDown: if self.top_down:
x,y = divmod(x, self.down) x, y = divmod(x, self.down)
else: else:
y,x = divmod(x, self.across) y, x = divmod(x, self.across)
return ( return (
self.margins[0]+x*self.labelsep[0], self.margins[0] + x * self.labelsep[0] + self.pageoffset[0],
self.pagesize[1] - self.margins[1] - (y+1)*self.labelsep[1] self.pagesize[1] - self.margins[1] - (y + 1) * self.labelsep[1] - self.pageoffset[1],
) )
def advance(self): def advance(self):
""" move to next position"""
self.position += 1 self.position += 1
if self.position == self.across * self.down: if self.position == self.across * self.down:
self.canvas.showPage() self.canvas.showPage()
self.position = 0 self.position = 0
def close(self): def close(self):
"""save and close canvas"""
if self.position: if self.position:
self.canvas.showPage() self.canvas.showPage()
self.canvas.save() self.canvas.save()
@ -99,35 +104,38 @@ class AveryLabel:
# Or, pass a callable and an iterator. We'll do one label # Or, pass a callable and an iterator. We'll do one label
# per iteration of the iterator. # per iteration of the iterator.
def render( self, thing, count, offset=0, *args ): def render(self, thing, count, offset=0, pageshift=(0 * mm, 0 * mm), *args):
""" render loop"""
assert callable(thing) or isinstance(thing, str) assert callable(thing) or isinstance(thing, str)
if isinstance(count, Iterator): if isinstance(count, Iterator):
return self.render_iterator( thing, count ) self.render_iterator(thing, count)
return
canv = self.canvas canv = self.canvas
for i in range(offset+count): for i in range(offset + count):
if i >= offset: if i >= offset:
canv.saveState() canv.saveState()
canv.translate( *self.topLeft() ) canv.translate(*self.top_left())
if self.debug: if self.debug:
canv.setLineWidth( 0.25 ) canv.setLineWidth(0.25)
canv.rect( 0, 0, self.size[0], self.size[1] ) canv.rect(0, 0, self.size[0], self.size[1])
if callable(thing): if callable(thing):
thing( canv, self.size[0], self.size[1], *args ) thing(canv, self.size[0], self.size[1], *args)
elif isinstance(thing, str): elif isinstance(thing, str):
canv.doForm(thing) canv.doForm(thing)
canv.restoreState() canv.restoreState()
self.advance() self.advance()
def render_iterator( self, func, iterator ): def render_iterator(self, func, iterator):
""" render loop for iterator """
canv = self.canvas canv = self.canvas
for chunk in iterator: for chunk in iterator:
canv.saveState() canv.saveState()
canv.translate( *self.topLeft() )
canv.translate(*self.top_left())
if self.debug: if self.debug:
canv.setLineWidth( 0.25 ) canv.setLineWidth(0.25)
canv.rect( 0, 0, self.size[0], self.size[1] ) canv.rect(0, 0, self.size[0], self.size[1])
func( canv, self.size[0], self.size[1], chunk ) func(canv, self.size[0], self.size[1], chunk)
canv.restoreState() canv.restoreState()
self.advance() self.advance()

15
Dockerfile Normal file
View file

@ -0,0 +1,15 @@
FROM python:3
WORKDIR /asn-gen
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
VOLUME ["/out"]
CMD [ "python", "./asn-gen.py"]
# docker exec -it $(docker run -d --rm debian:unstable bash -c "apt-get update && apt-get upgrade -y && sleep 86400") bash

146
README.md
View file

@ -9,7 +9,7 @@ This is a tool to create ASN Labels to use for document management systems such
This Python based CLI tool outputs a PDF for printing on the label sheets. This Python based CLI tool outputs a PDF for printing on the label sheets.
# Features ## Features
Besides generating ASN labels with a QR Code the tool can also Besides generating ASN labels with a QR Code the tool can also
@ -17,7 +17,7 @@ Besides generating ASN labels with a QR Code the tool can also
_This is helpful for small label sizes even though your physical label cutout sizes are bigger._ _This is helpful for small label sizes even though your physical label cutout sizes are bigger._
* support custom number ranges * support custom number ranges
_This can be useful if you want to use different folders and number ranges for yourself (ASN**0**0001), your partner ASN**2**0001, your kids (ASN**4**0001), etc._ _This can be useful if you want to use different folders and number ranges for yourself (e.g. ASN**0**0001), your partner (ASN**2**0001), your kids (ASN**4**0001), etc._
* add a color bar to the side of the labels to allow easier visual identification where the label belongs to * add a color bar to the side of the labels to allow easier visual identification where the label belongs to
_I use expandable folders with different colors to store the physical documents for me, my wife and the kids, i.e. one color per person_ _I use expandable folders with different colors to store the physical documents for me, my wife and the kids, i.e. one color per person_
@ -33,20 +33,80 @@ Besides generating ASN labels with a QR Code the tool can also
![Label with highlight bar](docs/label-with-hbar.png) ![Label with highlight bar](docs/label-with-hbar.png)
### Example usage of ASN with colors: ### Example usage of ASN labels with colors:
| number ranges | Meaning | Color | | number ranges | Meaning | Color |
| ------------ | --------------------------------------- | ---------- | | ------------ | --------------------------------------- | ---------- |
| 000000 | Me - normal docs (shorter term storage) | blue | | 000000 | Person 1 - normal docs (shorter term storage) | blue |
| 100000 | Me - imporatant / (long term storage) | blue/red | | 100000 | Person 1 - important (long term storage) | blue/red |
| 200000 | Wife - normal | green | | 200000 | Person 2 - normal | green |
| 300000 | Wife - important | green/red | | 300000 | Person 2 - important | green/red |
| 400000 | Child 1 - normal | yellow | | 400000 | Person 3 - normal | yellow |
| 500000 | Child 1 - important | yellow/red | | 500000 | Person 3 - important | yellow/red |
| ... | ... | ... | | ... | ... | ... |
Colors give a nice visual hint on where a document belongs to.
# Getting started ## Getting started
### Usage
This tool is hightly flexible, almost all parameters can be controlled from the command line.
Other Avery (or competitor's) label sizes can be added to `labelInfo` in `AveryLabels.py`.
You can install Python and all dependencies yourself or use Docker.
```
$ ./asn-gen.py -h
Usage: asn-gen.py [OPTIONS] [filename]
ASN Label Generator
Arguments:
filename output filename of PDF file generated, if .pdf extension is missing the string will be used
as directory
Options:
-l, --labeltype=STR Type of label, e.g. 4731, get a list of supported labels with --labels (default: 4731)
-n, --number=INT number of labels to generate (default: 189)
-o, --offset=INT Number of labels to skip on the first sheet (e.g. already used) (default: 0)
-d, --num-digits=INT Number of digits for the ASN, e.g. 000001 (default: 6)
-s, --first-asn=INT First ASN to use, e.g. 100001 (default: 1)
-f, --font-size=STR Fontsize with a unit, e.g. 2mm, 0.4cm (default: 2mm)
-q, --qr-size=FLOAT Size of the QR-Code as percentage of the label hight (default: 0.9)
-m, --qr-margin=STR Margin around the QR-Code with a unit, e.g. 1mm (default: 1mm)
--sub-labels-x, --lx=INT How many labels to put on a phyical label horizontally (default: 1)
--sub-labels-y, --ly=INT How many labels to put on a phyical label vertically (default: 1)
--debug enable debug mode
--position-helper enable position helpers, e.g. as cutting guides when using sub labels
--bar-width, --bw=INT Show a colored bar on the right of the label (0 = no bar) (default: 0)
--bar-color, --bc=STR Color of the bar, HEX notation (default: d2dede)
--highlight-bar-width, --hw=INT
add a colored highlight bar on the right of the label (0 = no bar) (default: 0)
--highlight-bar-color, --hc=STR
Color of the highlight bar, HEX notation (default: d9a4a6)
-p, --prefix=STR Prefix to the actual ASN number (default: ASN)
--page-offset-x, --dx=STR Print offset of the labels on the page to handle horizontal printer alignment with unit
(e.g. -2mm) (default: 0mm)
--page-offset-y, --dy=STR Print offset of the labels on the page to handle vertical printer alignment with unit (e.g.
-1.5mm) (default: 0mm)
Other actions:
-h, --help Show the help
--labels Shows a list of supported labels
--version Show the version
```
#### Testing your printer settings
Use ``--debug`` and ``--position-helper`` to test your printer settings.
_**Recommendation:** do test prints on normal paper before printing to the actual label sheets._
_**Note**: Make sure to set print size to 100%, not fit to page or similar._
### Running from CLI
You'll need Python 3 on your system. You'll need Python 3 on your system.
@ -54,53 +114,6 @@ To install all dependencies use
`` pip install -r requirements.txt `` `` pip install -r requirements.txt ``
# Usage
This tool is hightly flexible, almost all parameters can be controlled from the command line.
Other Avery (or competitor's) label sizes can be added to `labelInfo` in `AveryLabels.py`.
```
Usage: asn-gen.py [OPTIONS] [filename]
ASN Label Generator
Arguments:
filename output filename of PDF file generated
Options:
-l, --labeltype=STR Type of label, e.g. 4731, get a list of supported labels with --labels (default: 4731)
-n, --number=INT number of labels to generate (default: 189)
-o, --offset=INT Number of labels to skip on the first sheet (e.g. already used) (default: 0)
-d, --num-digits=INT Number of digits for the ASN, e.g. 000001 (default: 6)
-s, --first-asn=INT First ASN to use, e.g. 100001 (default: 1)
-f, --font-size=STR Fontsize with a unit, e.g. 2mm, 0.4cm (default: 2mm)
-q, --qr-size=FLOAT Size of the QR-Code as percentage of the label hight (default: 0.9)
-m, --qr-margin=STR Margin around the QR-Code with a unit, e.g. 1mm (default: 1mm)
--sub-labels-x, --lx=INT How many labels to put on a phyical label horizontally (default: 1)
--sub-labels-y, --ly=INT How many labels to put on a phyical label vertically (default: 1)
--debug enable debug mode
--position-helper enable position helpers, e.g. as cutting guides when using sub labels
--bar-width, --bw=INT Show a colored bar on the right of the label (0 = no bar) (default: 0)
--bar-color, --bc=STR Color of the bar, HEX notation (default: d2dede)
--highlight-bar-width, --hw=INT add a colored highlight bar on the right of the label (0 = no bar) (default: 0)
--highlight-bar-color, --hc=STR Color of the highlight bar, HEX notation (default: d9a4a6)
-p, --prefix=STR Prefix to the actual ASN number (default: ASN)
Other actions:
-h, --help Show the help
--labels Shows a list of supported labels
--version Show the version
```
### Testing your printer settings
Use ``--debug`` and ``--position-helper`` to test your printer settings.
_**Recommendation:** do test prints on normal paper before printing to the actual label sheets._
_**Note**: Make sure to set print size to 100%, not fit to page or similar._
### Running the program
Depending on your configuration either use Depending on your configuration either use
`` ./asn-gen.py ... `` `` ./asn-gen.py ... ``
@ -109,7 +122,19 @@ or
`` python3 asn-gen.py ... `` `` python3 asn-gen.py ... ``
### Output Filename ### Running with Docker
If you don't want to install python and the dependencies on your machine you can use Docker.
There is a handy bash script :
`` ./ag-docker.sh <output directory> [normal parameters to asn-gen.py] ``
e.g. `` ./ag-docker.sh $(pwd)/out -s 500001 `` or `` ./ag-docker.sh ./ -s 500001 ``
_Note: when using docker you cannot specify the output filename. Instead the default scheme will be used._
### Output Filename Scheme
If the filename is omitted the output defaults to If the filename is omitted the output defaults to
`` label-<labeltype>-<prefix>-<first-asn>-<first-asn+number>.pdf `` `` label-<labeltype>-<prefix>-<first-asn>-<first-asn+number>.pdf ``
@ -120,8 +145,7 @@ e.g.
## Examples
# Examples
### List supported labels ### List supported labels
@ -162,6 +186,6 @@ _Output filename: label-5161-ASN-000001-000021.pdf_
# Credits ## Credits
This project is based on [work by gitolicious](https://github.com/gitolicious/avery-asn/tree/main) but was heavily modified to support CLI and some additional features. That project itself is based on the [work from timrprobocom](https://gist.github.com/timrprobocom/3946aca8ab75df8267bbf892a427a1b7) This project is based on [work by gitolicious](https://github.com/gitolicious/avery-asn/tree/main) but was heavily modified to support CLI and some additional features. That project itself is based on the [work from timrprobocom](https://gist.github.com/timrprobocom/3946aca8ab75df8267bbf892a427a1b7)

4
ag-docker.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
path="$1"; shift
docker run --rm -v $path:/out ghcr.io/aborelis/asn-gen:latest ./asn-gen.py $@ /out/

View file

@ -1,188 +1,228 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from functools import partial
import os import os
import sys
from reportlab.lib.units import mm
from reportlab.lib.units import toLength
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
from reportlab_qrcode import QRCodeImage
# from reportlab.graphics import shapes
from clize import run
import AveryLabels import AveryLabels
from AveryLabels import labelInfo from AveryLabels import labelInfo
from reportlab.lib.units import mm
from reportlab.lib.units import toLength
from reportlab_qrcode import QRCodeImage
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
#from reportlab.graphics import shapes
from clize import ArgumentError, Parameter, run
from functools import partial PROJECT_HOMEPAGE = "https://github.com/aborelis/ASN-Label-Generator"
import inspect
project_homepage = 'https://github.com/aborelis/ASN-Label-Generator'
class LabelContext: class LabelContext:
"""helper class to store context """
# pylint: disable=too-many-instance-attributes
def __init__(self, data): def __init__(self, data):
self.label = 4731 self.filename = None
self.number =189
numDigits = 6 self.labeltype = 4731
self.firstAsn = 1 self.number = 189
self.num_digits = 6
self.first_asn = 1
self.offset = 0 self.offset = 0
self.fontSize=2*mm self.font_size = 2 * mm
self.qrSize = 0.9 self.qr_size = 0.9
self.qrMargin = 1*mm self.qr_margin = 1 * mm
self.subLabelsX = 1 self.sub_labels_x = 1
self.subLabelsY = 1 self.sub_labels_y = 1
self.debug = False self.debug = False
self.positionHelper = False self.position_helper = False
self.bar_width = 0
self.bar_color = HexColor("#d2dede")
self.highlight_bar_width = 0
self.highlight_bar_color = HexColor("#d9a4a6")
self.prefix = "ASN"
self.page_offset_x = 0 * mm
self.barWidth=0 self.page_offset_y = 0 * mm
self.barColor= HexColor('#d2dede')
self.highlightBarWidth = 0
self.highlightBarColor= HexColor('#d9a4a6')
self.prefix='ASN'
self.__dict__.update(data) self.__dict__.update(data)
self.currentASN = self.firstAsn self.current_asn = self.first_asn
def inc_asn(self):
"""increase current asn count """
self.current_asn = self.current_asn + 1
def incASN(self): def render(context: LabelContext, c: canvas.Canvas, width: float, height: float):
self.currentASN = self.currentASN + 1 """ renders one label onto the provided canvas. To be used with AveryLabel. """
sub_label_width = width / context.sub_labels_x
sub_labelheight = height / context.sub_labels_y
for i in range(context.sub_labels_x):
for j in range(context.sub_labels_y - 1, -1, -1): # no idea why inverted...
sub_x = sub_label_width * i
sub_y = sub_labelheight * j
c.saveState()
c.translate(sub_x, sub_y)
# barcode_value = f"ASN{currentASN:06d}"
barcode_value = context.prefix + str(context.current_asn).zfill(
context.num_digits
)
context.inc_asn()
qr_width = min(sub_labelheight * context.qr_size, sub_labelheight - 2 * context.qr_margin)
qr = QRCodeImage(barcode_value, size=qr_width, border=0)
qr.drawOn(
c, x=context.qr_margin, y=(sub_labelheight - qr_width) / 2
)
c.setFont("Helvetica", size=context.font_size)
c.drawString(
x= qr_width + 2 * context.qr_margin,
y=(sub_labelheight - context.font_size) / 2,
text=barcode_value,
)
if context.bar_width > 0:
c.setFillColor(context.bar_color)
c.rect(
sub_label_width - context.bar_width,
0,
context.bar_width,
sub_labelheight,
0,
1,
)
if context.highlight_bar_width > 0:
c.setFillColor(context.highlight_bar_color)
c.rect(
sub_label_width - context.bar_width - context.highlight_bar_width,
0,
context.highlight_bar_width,
sub_labelheight,
0,
1,
)
if context.position_helper:
r = 0.1
d = 0
if context.debug:
r = 0.5
d = r
c.circle(x_cen=0 + d, y_cen=0 + d, r=r, stroke=1)
c.circle(x_cen=sub_label_width - d, y_cen=0 + d, r=r, stroke=1)
c.circle(x_cen=0 + d, y_cen=sub_labelheight - d, r=r, stroke=1)
c.circle(
x_cen=sub_label_width - d, y_cen=sub_labelheight - d, r=r, stroke=1
)
c.restoreState()
def gen_filename(parm):
"""generates filename from parameters"""
return '-'.join(['label',
str(parm["labeltype"]), parm["prefix"],
str(parm["first_asn"]).zfill(parm["num_digits"]),
str(parm["first_asn"] + parm["number"]).zfill(parm["num_digits"])
])+'.pdf'
def generate(
def render(context: LabelContext , c: canvas.Canvas, width: float, height: float): filename=None,
*,
labeltype: "l" = "4731",
subLabelWidth = width/context.subLabelsX number: "n" = 189, # type: ignore
subLabelHeight = height/context.subLabelsY offset: "o" = 0, # type: ignore
num_digits: "d" = 6, # type: ignore
for i in range(context.subLabelsX): first_asn: "s" = 1, # type: ignore
for j in range(context.subLabelsY-1, -1, -1): # no idea why inverted... font_size: "f" = "2mm", # type: ignore
subX = subLabelWidth*i qr_size: "q" = 0.9, # type: ignore
subY = subLabelHeight*j qr_margin: "m" = "1mm", # type: ignore
sub_labels_x: "lx" = 1, # type: ignore
c.saveState() sub_labels_y: "ly" = 1, # type: ignore
c.translate(subX, subY) debug=False,
position_helper=False,
# barcode_value = f"ASN{currentASN:06d}" bar_width: "bw" = 0, # type: ignore
barcode_value = context.prefix+str(context.currentASN).zfill(context.numDigits) bar_color: "bc" = "d2dede", # type: ignore
context.incASN() highlight_bar_width: "hw" = 0, # type: ignore
highlight_bar_color: "hc" = "d9a4a6", # type: ignore
qr = QRCodeImage(barcode_value, size=subLabelHeight*context.qrSize) prefix: "p" = "ASN", # type: ignore
qr.drawOn(c, x=context.qrMargin, y=subLabelHeight*((1-context.qrSize)/2)) page_offset_x: "dx" = "0mm", # type: ignore
c.setFont("Helvetica", size=context.fontSize) page_offset_y: "dy" = "0mm", # type: ignore
c.drawString(x=subLabelHeight, y=( ): # pylint: disable=too-many-locals
subLabelHeight-context.fontSize)/2, text=barcode_value) # pylint: disable=unused-argument
if context.barWidth > 0 :
c.setFillColor(context.barColor)
c.rect(subLabelWidth-context.barWidth, 0, context.barWidth, subLabelHeight,0, 1)
if context.highlightBarWidth > 0 :
c.setFillColor(context.highlightBarColor)
c.rect(subLabelWidth-context.barWidth-context.highlightBarWidth, 0, context.highlightBarWidth, subLabelHeight,0, 1)
if context.positionHelper:
r = 0.1
d = 0
if context.debug:
r = 0.5
d = r
c.circle(x_cen=0+d, y_cen=0+d, r=r, stroke=1)
c.circle(x_cen=subLabelWidth-d, y_cen=0+d, r=r, stroke=1)
c.circle(x_cen=0+d, y_cen=subLabelHeight-d, r=r, stroke=1)
c.circle(x_cen=subLabelWidth-d,
y_cen=subLabelHeight-d, r=r, stroke=1)
c.restoreState()
def generate( filename = None, *, labeltype:'l' = '4731',
number:'n'= 189,
offset:'o' = 0,
numDigits:'d'= 6,
firstAsn:'s' = 1,
fontSize:'f' = '2mm',
qrSize:'q' = 0.9,
qrMargin:'m' = '1mm',
subLabelsX:'lx' = 1,
subLabelsY:'ly' = 1,
debug = False ,
positionHelper = False,
barWidth:'bw'=0,
barColor:'bc'= 'd2dede',
highlightBarWidth:'hw'= 0 ,
highlightBarColor:'hc'= 'd9a4a6',
prefix:'p' = 'ASN'
):
"""ASN Label Generator """ASN Label Generator
:param filename: output filename of PDF file generated :param filename: output filename of PDF file generated, if .pdf extension is missing the string will be used as directory
:param labeltype: Type of label, e.g. 4731, get a list of supported labels with --labels :param labeltype: Type of label, e.g. 4731, get a list of supported labels with --labels
:param number: number of labels to generate :param number: number of labels to generate
:param offset: Number of labels to skip on the first sheet (e.g. already used) :param offset: Number of labels to skip on the first sheet (e.g. already used)
:param numDigits: Number of digits for the ASN, e.g. 000001 :param num_digits: Number of digits for the ASN, e.g. 000001
:param firstAsn: First ASN to use, e.g. 100001 :param first_asn: First ASN to use, e.g. 100001
:param fontSize: Fontsize with a unit, e.g. 2mm, 0.4cm :param font_size: Fontsize with a unit, e.g. 2mm, 0.4cm
:param qrSize: Size of the QR-Code as percentage of the label hight :param qr_size: Size of the QR-Code as percentage of the label hight
:param qrMargin: Margin around the QR-Code with a unit, e.g. 1mm :param qr_margin: Margin around the QR-Code with a unit, e.g. 1mm
:param subLabelsX: How many labels to put on a phyical label horizontally :param sub_labels_x: How many labels to put on a phyical label horizontally
:param subLabelsY: How many labels to put on a phyical label vertically :param sub_labels_y: How many labels to put on a phyical label vertically
:param debug: enable debug mode :param debug: enable debug mode
:param positionHelper: enable position helpers, e.g. as cutting guides when using sub labels :param position_helper: enable position helpers, e.g. as cutting guides when using sub labels
:param barWidth: Show a colored bar on the right of the label (0 = no bar) :param bar_width: Show a colored bar on the right of the label (0 = no bar)
:param barColor: Color of the bar, HEX notation :param bar_color: Color of the bar, HEX notation
:param highlightBarWidth: add a colored highlight bar on the right of the label (0 = no bar) :param highlight_bar_width: add a colored highlight bar on the right of the label (0 = no bar)
:param highlightBarColor: Color of the highlight bar, HEX notation :param highlight_bar_color: Color of the highlight bar, HEX notation
:param prefix: Prefix to the actual ASN number :param prefix: Prefix to the actual ASN number
:param page_offset_x: Print offset of the labels on the page to handle horizontal printer alignment with unit (e.g. -2mm)
:param page_offset_y: Print offset of the labels on the page to handle vertical printer alignment with unit (e.g. -1.5mm)
""" """
parm = locals() parm = locals()
parm['fontSize'] = toLength(parm['fontSize']) parm["font_size"] = toLength(parm["font_size"])
parm['qrMargin'] = toLength(parm['qrMargin']) parm["qr_margin"] = toLength(parm["qr_margin"])
parm['barColor'] = HexColor('#'+parm['barColor']) parm["bar_color"] = HexColor("#" + parm["bar_color"])
parm['highlightBarColor'] = HexColor('#'+parm['highlightBarColor']) parm["highlight_bar_color"] = HexColor("#" + parm["highlight_bar_color"])
parm['labeltype'] = int(parm['labeltype']) parm["labeltype"] = int(parm["labeltype"])
parm["page_offset_x"] = toLength(parm["page_offset_x"])
parm["page_offset_y"] = toLength(parm["page_offset_y"])
if parm["filename"] is None:
parm["filename"] = gen_filename(parm)
elif not parm["filename"].endswith(".pdf"):
parm["filename"] = os.path.join(parm["filename"], gen_filename(parm))
if parm['filename'] == None:
parm['filename']= 'label-'+str(parm['labeltype'])+'-'+parm['prefix']+'-'+str(parm['firstAsn']).zfill(parm['numDigits'])+'-'+str(parm['firstAsn']+parm['number']).zfill(parm['numDigits'])+'.pdf'
context = LabelContext(parm) context = LabelContext(parm)
label = AveryLabels.AveryLabel(context.labeltype, (context.page_offset_x, context.page_offset_y))
label = AveryLabels.AveryLabel(context.labeltype)
label.debug = context.debug label.debug = context.debug
@ -192,24 +232,22 @@ def generate( filename = None, *, labeltype:'l' = '4731',
label.render(render_func, count=context.number, offset=context.offset) label.render(render_func, count=context.number, offset=context.offset)
label.close() label.close()
print
print(f"Output written to {context.filename}") print(f"Output written to {context.filename}")
def labels(): def labels():
""" Shows a list of supported labels """Shows a list of supported labels"""
""" print("Supported Labels: " + ", ".join(map(str, sorted(labelInfo.keys()))))
print('Supported Labels: '+', '.join(map(str,labelInfo.keys())))
def version(): def version():
"""Show the version""" """Show the version"""
return 'ASN Label Generator - version 0.1 \n' + project_homepage return "ASN Label Generator - version 0.1 \n" + PROJECT_HOMEPAGE
def main(): def main():
run(generate, alt=[labels,version]) """Main function - entry point"""
run(generate, alt=[labels, version])
if __name__ == '__main__':
main() if __name__ == "__main__":
main()

0
out/empty Normal file
View file