mirror of
https://github.com/aborelis/ASN-Label-Generator.git
synced 2026-03-14 16:43:27 +00:00
Compare commits
14 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75e39bf8a3 | ||
|
|
be654118bb | ||
|
|
55f9f91b55 | ||
|
|
9137595e22 | ||
|
|
cf486c9416 | ||
|
|
59d3d1fa8a | ||
|
|
c10b5f2bdd | ||
|
|
e9e64e95f5 | ||
|
|
de48bf919a | ||
|
|
b3494b15f6 | ||
|
|
26138614e3 | ||
|
|
a9337407b7 | ||
|
|
b8cdab0e4a | ||
|
|
e2bb5dfc9c |
8 changed files with 366 additions and 249 deletions
23
.github/workflows/pylint.yml
vendored
Normal file
23
.github/workflows/pylint.yml
vendored
Normal 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
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
__pycache__
|
||||||
|
venv
|
||||||
|
.idea
|
||||||
|
/*.pdf
|
||||||
|
out/*.pdf
|
||||||
|
|
@ -24,9 +24,9 @@ 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),
|
||||||
|
|
@ -36,57 +36,62 @@ labelInfo = {
|
||||||
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):
|
||||||
|
"""open a canvas for the file"""
|
||||||
self.canvas = canvas.Canvas(filename, pagesize=self.pagesize)
|
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,16 +104,18 @@ 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])
|
||||||
|
|
@ -120,14 +127,15 @@ class AveryLabel:
|
||||||
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
15
Dockerfile
Normal 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
|
||||||
76
README.md
76
README.md
|
|
@ -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,41 +33,40 @@ Besides generating ASN labels with a QR Code the tool can also
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
### 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
|
||||||
|
|
||||||
You'll need Python 3 on your system.
|
### Usage
|
||||||
|
|
||||||
To install all dependencies use
|
|
||||||
|
|
||||||
`` pip install -r requirements.txt ``
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
|
|
||||||
This tool is hightly flexible, almost all parameters can be controlled from the command line.
|
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`.
|
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]
|
Usage: asn-gen.py [OPTIONS] [filename]
|
||||||
|
|
||||||
ASN Label Generator
|
ASN Label Generator
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
filename output filename of PDF file generated
|
filename output filename of PDF file generated, if .pdf extension is missing the string will be used
|
||||||
|
as directory
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-l, --labeltype=STR Type of label, e.g. 4731, get a list of supported labels with --labels (default: 4731)
|
-l, --labeltype=STR Type of label, e.g. 4731, get a list of supported labels with --labels (default: 4731)
|
||||||
|
|
@ -84,9 +83,15 @@ Options:
|
||||||
--position-helper enable position helpers, e.g. as cutting guides when using sub labels
|
--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-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)
|
--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-width, --hw=INT
|
||||||
--highlight-bar-color, --hc=STR Color of the highlight bar, HEX notation (default: d9a4a6)
|
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)
|
-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:
|
Other actions:
|
||||||
-h, --help Show the help
|
-h, --help Show the help
|
||||||
|
|
@ -94,13 +99,21 @@ Other actions:
|
||||||
--version Show the version
|
--version Show the version
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing your printer settings
|
#### Testing your printer settings
|
||||||
Use ``--debug`` and ``--position-helper`` to test 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._
|
_**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._
|
_**Note**: Make sure to set print size to 100%, not fit to page or similar._
|
||||||
|
|
||||||
### Running the program
|
|
||||||
|
### Running from CLI
|
||||||
|
|
||||||
|
You'll need Python 3 on your system.
|
||||||
|
|
||||||
|
To install all dependencies use
|
||||||
|
|
||||||
|
`` pip install -r requirements.txt ``
|
||||||
|
|
||||||
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
4
ag-docker.sh
Executable 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/
|
||||||
268
asn-gen.py
268
asn-gen.py
|
|
@ -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.labeltype = 4731
|
||||||
self.number = 189
|
self.number = 189
|
||||||
|
|
||||||
numDigits = 6
|
self.num_digits = 6
|
||||||
self.firstAsn = 1
|
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 incASN(self):
|
|
||||||
self.currentASN = self.currentASN + 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def inc_asn(self):
|
||||||
|
"""increase current asn count """
|
||||||
|
self.current_asn = self.current_asn + 1
|
||||||
|
|
||||||
|
|
||||||
def render(context: LabelContext, c: canvas.Canvas, width: float, height: float):
|
def render(context: LabelContext, c: canvas.Canvas, width: float, height: float):
|
||||||
|
""" 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
|
||||||
|
|
||||||
subLabelWidth = width/context.subLabelsX
|
for i in range(context.sub_labels_x):
|
||||||
subLabelHeight = height/context.subLabelsY
|
for j in range(context.sub_labels_y - 1, -1, -1): # no idea why inverted...
|
||||||
|
sub_x = sub_label_width * i
|
||||||
for i in range(context.subLabelsX):
|
sub_y = sub_labelheight * j
|
||||||
for j in range(context.subLabelsY-1, -1, -1): # no idea why inverted...
|
|
||||||
subX = subLabelWidth*i
|
|
||||||
subY = subLabelHeight*j
|
|
||||||
|
|
||||||
c.saveState()
|
c.saveState()
|
||||||
c.translate(subX, subY)
|
c.translate(sub_x, sub_y)
|
||||||
|
|
||||||
# barcode_value = f"ASN{currentASN:06d}"
|
# barcode_value = f"ASN{currentASN:06d}"
|
||||||
barcode_value = context.prefix+str(context.currentASN).zfill(context.numDigits)
|
barcode_value = context.prefix + str(context.current_asn).zfill(
|
||||||
context.incASN()
|
context.num_digits
|
||||||
|
)
|
||||||
|
context.inc_asn()
|
||||||
|
|
||||||
qr = QRCodeImage(barcode_value, size=subLabelHeight*context.qrSize)
|
qr_width = min(sub_labelheight * context.qr_size, sub_labelheight - 2 * context.qr_margin)
|
||||||
qr.drawOn(c, x=context.qrMargin, y=subLabelHeight*((1-context.qrSize)/2))
|
qr = QRCodeImage(barcode_value, size=qr_width, border=0)
|
||||||
c.setFont("Helvetica", size=context.fontSize)
|
qr.drawOn(
|
||||||
c.drawString(x=subLabelHeight, y=(
|
c, x=context.qr_margin, y=(sub_labelheight - qr_width) / 2
|
||||||
subLabelHeight-context.fontSize)/2, text=barcode_value)
|
)
|
||||||
|
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.barWidth > 0 :
|
if context.bar_width > 0:
|
||||||
c.setFillColor(context.barColor)
|
c.setFillColor(context.bar_color)
|
||||||
c.rect(subLabelWidth-context.barWidth, 0, context.barWidth, subLabelHeight,0, 1)
|
c.rect(
|
||||||
if context.highlightBarWidth > 0 :
|
sub_label_width - context.bar_width,
|
||||||
c.setFillColor(context.highlightBarColor)
|
0,
|
||||||
c.rect(subLabelWidth-context.barWidth-context.highlightBarWidth, 0, context.highlightBarWidth, subLabelHeight,0, 1)
|
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:
|
||||||
|
|
||||||
if context.positionHelper:
|
|
||||||
r = 0.1
|
r = 0.1
|
||||||
d = 0
|
d = 0
|
||||||
if context.debug:
|
if context.debug:
|
||||||
r = 0.5
|
r = 0.5
|
||||||
d = r
|
d = r
|
||||||
c.circle(x_cen=0 + d, y_cen=0 + d, r=r, stroke=1)
|
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=sub_label_width - 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=0 + d, y_cen=sub_labelheight - d, r=r, stroke=1)
|
||||||
c.circle(x_cen=subLabelWidth-d,
|
c.circle(
|
||||||
y_cen=subLabelHeight-d, r=r, stroke=1)
|
x_cen=sub_label_width - d, y_cen=sub_labelheight - d, r=r, stroke=1
|
||||||
|
)
|
||||||
|
|
||||||
c.restoreState()
|
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( filename = None, *, labeltype:'l' = '4731',
|
def generate(
|
||||||
number:'n'= 189,
|
filename=None,
|
||||||
offset:'o' = 0,
|
*,
|
||||||
numDigits:'d'= 6,
|
labeltype: "l" = "4731",
|
||||||
firstAsn:'s' = 1,
|
number: "n" = 189, # type: ignore
|
||||||
fontSize:'f' = '2mm',
|
offset: "o" = 0, # type: ignore
|
||||||
qrSize:'q' = 0.9,
|
num_digits: "d" = 6, # type: ignore
|
||||||
qrMargin:'m' = '1mm',
|
first_asn: "s" = 1, # type: ignore
|
||||||
|
font_size: "f" = "2mm", # type: ignore
|
||||||
subLabelsX:'lx' = 1,
|
qr_size: "q" = 0.9, # type: ignore
|
||||||
subLabelsY:'ly' = 1,
|
qr_margin: "m" = "1mm", # type: ignore
|
||||||
|
sub_labels_x: "lx" = 1, # type: ignore
|
||||||
|
sub_labels_y: "ly" = 1, # type: ignore
|
||||||
debug=False,
|
debug=False,
|
||||||
positionHelper = False,
|
position_helper=False,
|
||||||
|
bar_width: "bw" = 0, # type: ignore
|
||||||
|
bar_color: "bc" = "d2dede", # type: ignore
|
||||||
|
highlight_bar_width: "hw" = 0, # type: ignore
|
||||||
barWidth:'bw'=0,
|
highlight_bar_color: "hc" = "d9a4a6", # type: ignore
|
||||||
barColor:'bc'= 'd2dede',
|
prefix: "p" = "ASN", # type: ignore
|
||||||
highlightBarWidth:'hw'= 0 ,
|
page_offset_x: "dx" = "0mm", # type: ignore
|
||||||
highlightBarColor:'hc'= 'd9a4a6',
|
page_offset_y: "dy" = "0mm", # type: ignore
|
||||||
prefix:'p' = 'ASN'
|
): # pylint: disable=too-many-locals
|
||||||
):
|
# pylint: disable=unused-argument
|
||||||
"""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():
|
||||||
|
"""Main function - entry point"""
|
||||||
run(generate, alt=[labels, version])
|
run(generate, alt=[labels, version])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
0
out/empty
Normal file
0
out/empty
Normal file
Loading…
Add table
Add a link
Reference in a new issue