feat: add several options for customizing label placement

* --row-wise, for going left to right instead of top to bottom
* --num-labels, for specifying how many labels to print
* --pages, for specifying how many pages to print
* --start-position, for continuing on sheets where some labels were already used

Co-authored-by: Jan Christian Grünhage <jan.christian@gruenhage.xyz>
This commit is contained in:
LoopingLudwig 2024-05-05 22:38:15 +02:00 committed by Jan Christian Grünhage
parent a6e8fadf72
commit 8bc64be93b
Signed by: jcgruenhage
GPG key ID: EEC1170CE56FA2ED
3 changed files with 82 additions and 10 deletions

View file

@ -13,7 +13,9 @@ pip install paperless-asn-qr-codes
## Usage
```
usage: paperless-asn-qr-codes [-h] [--format {averyL4731,avery5160,avery5161,avery5163,avery5167,avery5371}] [--border] start_asn output_file
usage: paperless-asn-qr-codes [-h] [--format {averyL4731,avery5160,avery5161,avery5163,avery5167,avery5371}] [--digits DIGITS] [--border] [--row-wise] [--num-labels NUM_LABELS] [--pages PAGES]
[--start-position START_POSITION]
start_asn output_file
CLI Tool for generating paperless ASN labels with QR codes
@ -27,6 +29,13 @@ options:
--digits DIGITS, -d DIGITS
Number of digits in the ASN (default: 7, produces 'ASN0000001')
--border, -b Display borders around labels, useful for debugging the printer alignment
--row-wise, -r Increment the ASNs row-wise, go from left to right
--num-labels NUM_LABELS, -n NUM_LABELS
Number of labels to be printed on the sheet
--pages PAGES, -p PAGES
Number of pages to be printed, ignored if NUM_LABELS is set (default: 1)
--start-position START_POSITION, -s START_POSITION
Define the starting position on the sheet, eighter as ROW:COLUMN or COUNT, both starting from 1 (default: 1:1 or 1)
```
### Mandatory arguments
@ -43,6 +52,10 @@ options:
- `-f`, `--format`: Selects the format of the output sheet (see [Supported Sheets](#supported-sheets))
- `-d`, `--digits`: Specifies the number of digits in the ASN (e.g. for the default number 7, the ASN will look like 'ASN0000001')
- `-b`, `--border`: Generates the borders around the labels to help debug alignment issues (see [Tips & Tricks](#tips--tricks))
- `-r`, `--row-wise`: Increments the labels from left to right instead of top to bottom
- `-n`, `--num-labels`: Number of lables to be printed on the sheet
- `-p`, `--pages`: Number of pages to be generated, ignored if -n is present.
- `-s`, `--start-position`: Positon of first label to be printed, eighter defined as ROW:COLUMN or NUMBER. Starting from 1 eg. to use the whole sheet it would be 1:1 or 1. Useful if you have a partly used sheet from using `-n`.
## Supported Sheets
Some different sheet types are supported with the `-f`/`--format` argument, however, not all are tested.

View file

@ -89,7 +89,9 @@ BUSINESS_CARDS = 5371
class AveryLabel:
def __init__(self, label, debug, **kwargs):
def __init__(self, label, debug,
topDown=True, start_pos=None,
**kwargs):
data = labelInfo[label]
self.across = data.labels_horizontal
self.down = data.labels_vertical
@ -99,10 +101,27 @@ class AveryLabel:
self.size[1] + data.gutter_size[1],
)
self.margins = data.margin
self.topDown = True
self.topDown = topDown
self.debug = debug
self.pagesize = data.pagesize
self.position = 0
#Calculate start offset
if isinstance(start_pos, tuple):
rows, columns = start_pos
# Minimum Value 1 for row/column
rows = max(rows, 1)
columns = max(columns, 1)
if self.topDown:
offset = (columns - 1) * self.down + rows - 1
else:
offset = (rows - 1) * self.across + columns - 1
elif start_pos:
offset = start_pos - 1
else:
offset = 0
# Limit start position to number of labels - 1
self.position = min(offset, self.across * self.down - 1)
self.__dict__.update(kwargs)
def open(self, filename):

View file

@ -1,4 +1,5 @@
import argparse
import re
from reportlab.lib.units import mm
from reportlab_qrcode import QRCodeImage
@ -19,6 +20,15 @@ def render(c, x, y):
def main():
# Match the starting position parameter. Allow x:y or n
def _start_position(arg):
if mat := re.match(r"^(\d{1,2}):(\d{1,2})$", arg):
return (int(mat.group(1)), int(mat.group(2)))
elif mat := re.match(r"^\d+$", arg):
return int(arg)
else:
raise argparse.ArgumentTypeError("invalid value")
parser = argparse.ArgumentParser(
prog="paperless-asn-qr-codes",
description="CLI Tool for generating paperless ASN labels with QR codes",
@ -46,17 +56,47 @@ def main():
action="store_true",
help="Display borders around labels, useful for debugging the printer alignment",
)
parser.add_argument(
"--row-wise",
"-r",
action="store_false",
help="Increment the ASNs row-wise, go from left to right",
)
parser.add_argument(
"--num-labels",
"-n",
type=int,
help="Number of labels to be printed on the sheet",
)
parser.add_argument(
"--pages",
"-p",
type=int,
default=1,
help="Number of pages to be printed, ignored if NUM_LABELS is set (default: 1)",
)
parser.add_argument(
"--start-position",
"-s",
type=_start_position,
help="Define the starting position on the sheet, eighter as ROW:COLUMN or COUNT, both starting from 1 (default: 1:1 or 1)",
)
args = parser.parse_args()
global startASN
global digits
startASN = int(args.start_asn)
digits = int(args.digits)
label = avery_labels.AveryLabel(args.format, args.border)
label.open(args.output_file)
# by default, we render all labels possible on a single sheet
count = (
avery_labels.labelInfo[args.format].labels_horizontal
* avery_labels.labelInfo[args.format].labels_vertical
label = avery_labels.AveryLabel(
args.format, args.border, topDown=args.row_wise, start_pos=args.start_position
)
label.open(args.output_file)
# If defined use parameter for number of labels
if args.num_labels:
count = args.num_labels
else:
# Otherwise number of pages*labels - offset
count = args.pages * label.across * label.down - label.position
label.render(render, count)
label.close()