Add template selection and multiple copy printing features
- Implemented template selection: type 0=OK (green), type 1=NOK (red) - Added multiple copy printing (1-100 copies) - Extended file format to 5 fields: ARTICLE;NR_ART;SERIAL;TYPE;COUNT - Created OK/NOK SVG templates with visual distinction - Fixed PDF landscape orientation issues - Updated SumatraPDF to use noscale for exact dimensions - Auto-generate conf folder with default templates on first run - Made pystray optional for system tray functionality - Updated build scripts for Python 3.13 compatibility (Kivy 2.3+, PyInstaller 6.18) - Added comprehensive build documentation - Improved printer configuration guidance
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,6 +1,12 @@
|
||||
label/
|
||||
build/
|
||||
dist/
|
||||
logs/
|
||||
pdf_backup/
|
||||
venv/
|
||||
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.spec
|
||||
*.egg-info/
|
||||
.eggs/
|
||||
|
||||
303
BUILD_EXECUTABLE.md
Normal file
303
BUILD_EXECUTABLE.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# Build Windows Executable (.exe)
|
||||
|
||||
## Quick Start
|
||||
|
||||
**Option 1: One Command (Recommended)**
|
||||
```bash
|
||||
build_windows.bat
|
||||
```
|
||||
|
||||
**Option 2: Python Script**
|
||||
```bash
|
||||
python build_exe.py
|
||||
```
|
||||
|
||||
**Option 3: Direct PyInstaller**
|
||||
```bash
|
||||
pyinstaller LabelPrinter.spec
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Windows** 10/11
|
||||
- **Python** 3.10 - 3.13 (Python 3.14+ may have compatibility issues)
|
||||
- **Dependencies** installed (see below)
|
||||
|
||||
---
|
||||
|
||||
## Step-by-Step Build Process
|
||||
|
||||
### 1. Install Python Dependencies
|
||||
|
||||
If not already installed:
|
||||
```bash
|
||||
pip install -r requirements_windows.txt
|
||||
```
|
||||
|
||||
Or install manually:
|
||||
```bash
|
||||
pip install python-barcode pillow reportlab kivy==2.2.1 pyinstaller==6.1.0 pywin32 wmi watchdog svglib cairosvg
|
||||
```
|
||||
|
||||
### 2. Build the Executable
|
||||
|
||||
Run the build script:
|
||||
```bash
|
||||
build_windows.bat
|
||||
```
|
||||
|
||||
This will:
|
||||
- ✅ Install/upgrade dependencies
|
||||
- ✅ Clean old build artifacts
|
||||
- ✅ Create `LabelPrinter.exe` in `dist/` folder
|
||||
- ⏱️ Takes 5-15 minutes
|
||||
|
||||
### 3. Test the Executable
|
||||
|
||||
```bash
|
||||
cd dist
|
||||
LabelPrinter.exe
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What Gets Included
|
||||
|
||||
The executable is **self-contained** and includes:
|
||||
- ✅ All Python code
|
||||
- ✅ All dependencies (Kivy, ReportLab, svglib, cairosvg, etc.)
|
||||
- ✅ Auto-generates `conf/` folder on first run
|
||||
- ✅ Auto-generates `pdf_backup/` and `logs/` folders
|
||||
|
||||
**On first run, the app automatically creates:**
|
||||
```
|
||||
LabelPrinter.exe location/
|
||||
├── conf/
|
||||
│ ├── app.conf (default settings)
|
||||
│ ├── label_template.svg (default template)
|
||||
│ ├── label_template_ok.svg (OK labels - green)
|
||||
│ └── label_template_nok.svg (NOK labels - red)
|
||||
├── pdf_backup/ (generated PDFs)
|
||||
└── logs/ (print logs)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output
|
||||
|
||||
After successful build:
|
||||
|
||||
```
|
||||
📁 dist/
|
||||
└── LabelPrinter.exe (Single file, ~80-120 MB)
|
||||
```
|
||||
|
||||
**File size**: 80-120 MB (includes Python runtime + all libraries)
|
||||
|
||||
---
|
||||
|
||||
## Distribution
|
||||
|
||||
### To Deploy on Other Windows Machines:
|
||||
|
||||
**Simply copy `LabelPrinter.exe` to the target machine!**
|
||||
|
||||
The executable is **100% self-contained**:
|
||||
- ✅ No Python installation needed
|
||||
- ✅ No dependencies needed
|
||||
- ✅ Auto-creates all required folders on first run
|
||||
- ✅ Generates default templates automatically
|
||||
|
||||
**First run will create:**
|
||||
```
|
||||
[wherever you put LabelPrinter.exe]/
|
||||
├── LabelPrinter.exe ← Copy just this file!
|
||||
├── conf/ ← Auto-generated on first run
|
||||
│ ├── app.conf
|
||||
│ ├── label_template.svg
|
||||
│ ├── label_template_ok.svg
|
||||
│ └── label_template_nok.svg
|
||||
├── pdf_backup/ ← Auto-generated
|
||||
└── logs/ ← Auto-generated
|
||||
```
|
||||
|
||||
**To customize templates on target machine:**
|
||||
1. Run `LabelPrinter.exe` once (generates conf folder)
|
||||
2. Edit SVG files in the `conf/` folder
|
||||
3. Restart the application
|
||||
|
||||
**Requirements on target machine:**
|
||||
- ✅ Windows 10/11
|
||||
- ✅ Thermal printer configured (35mm x 25mm paper size)
|
||||
- ⚠️ No other software required!
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Fails - Missing Dependencies
|
||||
```bash
|
||||
pip install --upgrade pip setuptools wheel
|
||||
pip install -r requirements_windows.txt
|
||||
```
|
||||
|
||||
### Build Fails - PyInstaller Error
|
||||
```bash
|
||||
pip install --upgrade pyinstaller==6.1.0
|
||||
```
|
||||
|
||||
### Executable Won't Start
|
||||
- Check Windows Defender didn't quarantine it
|
||||
- Run as Administrator once to register
|
||||
- Check Event Viewer for errors
|
||||
|
||||
### Executable is Huge (>150 MB)
|
||||
This is normal! It includes:
|
||||
- Python runtime (~40 MB)
|
||||
- Kivy framework (~30 MB)
|
||||
- ReportLab, PIL, etc. (~20 MB)
|
||||
- Your code + data (~10 MB)
|
||||
|
||||
### First Run is Slow
|
||||
- First launch takes 10-30 seconds (Kivy initialization)
|
||||
- Subsequent launches are faster (~2-5 seconds)
|
||||
- This is normal behavior
|
||||
|
||||
---
|
||||
|
||||
## Advanced Options
|
||||
|
||||
### Build with Console (for debugging)
|
||||
Edit `build_windows.bat` and remove `--windowed`:
|
||||
```bat
|
||||
pyinstaller label_printer_gui.py ^
|
||||
--onefile ^
|
||||
--name=LabelPrinter ^
|
||||
...
|
||||
```
|
||||
|
||||
### Add Custom Icon
|
||||
```bat
|
||||
pyinstaller label_printer_gui.py ^
|
||||
--onefile ^
|
||||
--windowed ^
|
||||
--icon=icon.ico ^
|
||||
...
|
||||
```
|
||||
|
||||
### Reduce File Size
|
||||
Not recommended, but possible:
|
||||
```bat
|
||||
pyinstaller label_printer_gui.py ^
|
||||
--onefile ^
|
||||
--windowed ^
|
||||
--strip ^
|
||||
--exclude-module=tkinter ^
|
||||
--exclude-module=matplotlib ^
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What's Built
|
||||
|
||||
**Source Files Compiled:**
|
||||
- `label_printer_gui.py` (Main GUI)
|
||||
- `print_label.py` (Printing logic)
|
||||
- `print_label_pdf.py` (PDF generation)
|
||||
|
||||
**Data Files Included:**
|
||||
- `conf/app.conf` (Settings)
|
||||
- `conf/label_template.svg` (Default template)
|
||||
- `conf/label_template_ok.svg` (OK labels - green)
|
||||
- `conf/label_template_nok.svg` (NOK labels - red)
|
||||
- `conf/accepted.png` (Checkmark image)
|
||||
|
||||
**Output Folders:**
|
||||
- `pdf_backup/` - Stores generated PDFs
|
||||
- `logs/` - Stores print logs
|
||||
|
||||
---
|
||||
|
||||
## Build Times
|
||||
|
||||
- **First build**: 10-15 minutes (PyInstaller analyzes all dependencies)
|
||||
- **Rebuild**: 5-10 minutes (cached analysis)
|
||||
- **Clean build**: 10-15 minutes (removed cache)
|
||||
|
||||
---
|
||||
|
||||
## File Structure After Build
|
||||
|
||||
```
|
||||
📁 Project Root/
|
||||
├── 📄 label_printer_gui.py
|
||||
├── 📄 print_label.py
|
||||
├── 📄 print_label_pdf.py
|
||||
├── 📄 build_windows.bat ← Run this
|
||||
├── 📄 build_exe.py
|
||||
├── 📄 LabelPrinter.spec
|
||||
│
|
||||
├── 📁 dist/
|
||||
│ ├── 📄 LabelPrinter.exe ← Your executable!
|
||||
│ ├── 📁 conf/
|
||||
│ ├── 📁 pdf_backup/
|
||||
│ └── 📁 logs/
|
||||
│
|
||||
├── 📁 build/ (temp files, can delete)
|
||||
└── 📁 conf/
|
||||
├── app.conf
|
||||
├── label_template.svg
|
||||
├── label_template_ok.svg
|
||||
└── label_template_nok.svg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Clean Build
|
||||
|
||||
To remove all build artifacts:
|
||||
```bash
|
||||
rmdir /s /q build
|
||||
rmdir /s /q dist
|
||||
del *.spec
|
||||
```
|
||||
|
||||
Then rebuild:
|
||||
```bash
|
||||
build_windows.bat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
After building, test with:
|
||||
|
||||
1. **Run the executable**:
|
||||
```bash
|
||||
dist\LabelPrinter.exe
|
||||
```
|
||||
|
||||
2. **Configure monitoring**:
|
||||
- File: `C:\Users\Public\Documents\check.txt`
|
||||
|
||||
3. **Test print**:
|
||||
- Add to check.txt: `COM-001;ART-123;SN-001;0;1`
|
||||
- Should print 1 OK label
|
||||
|
||||
4. **Test template switching**:
|
||||
- `COM-002;ART-456;SN-002;1;1` → NOK label (red)
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
If build fails, check:
|
||||
1. Python version (3.10-3.13 required)
|
||||
2. All dependencies installed
|
||||
3. Windows 10/11 (not Windows 7/8)
|
||||
4. Disk space (need ~500MB for build)
|
||||
5. Antivirus not blocking PyInstaller
|
||||
@@ -46,6 +46,12 @@ args = [
|
||||
'--hidden-import=reportlab',
|
||||
'--hidden-import=print_label',
|
||||
'--hidden-import=print_label_pdf',
|
||||
'--hidden-import=svglib',
|
||||
'--hidden-import=cairosvg',
|
||||
'--hidden-import=watchdog',
|
||||
'--hidden-import=watchdog.observers',
|
||||
'--hidden-import=watchdog.events',
|
||||
'--hidden-import=pystray',
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -39,8 +39,8 @@ echo.
|
||||
|
||||
REM Install dependencies
|
||||
echo [3/5] Installing dependencies...
|
||||
echo Installing: python-barcode, pillow, reportlab, kivy, pyinstaller, pywin32, wmi...
|
||||
pip install python-barcode pillow reportlab kivy==2.2.1 pyinstaller==6.1.0 pywin32 wmi
|
||||
echo Installing: python-barcode, pillow, reportlab, kivy, pyinstaller, pywin32, wmi, watchdog, svglib, cairosvg, pystray...
|
||||
pip install python-barcode pillow reportlab kivy pyinstaller pywin32 wmi watchdog svglib cairosvg pystray
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Failed to install dependencies
|
||||
pause
|
||||
@@ -72,6 +72,12 @@ pyinstaller label_printer_gui.py ^
|
||||
--hidden-import=reportlab ^
|
||||
--hidden-import=print_label ^
|
||||
--hidden-import=print_label_pdf ^
|
||||
--hidden-import=svglib ^
|
||||
--hidden-import=cairosvg ^
|
||||
--hidden-import=watchdog ^
|
||||
--hidden-import=watchdog.observers ^
|
||||
--hidden-import=watchdog.events ^
|
||||
--hidden-import=pystray ^
|
||||
-y
|
||||
|
||||
if errorlevel 1 (
|
||||
|
||||
20
check_pdf_size.py
Normal file
20
check_pdf_size.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from reportlab.lib.pagesizes import landscape
|
||||
from reportlab.lib.utils import ImageReader
|
||||
from reportlab.pdfgen import canvas
|
||||
import os
|
||||
|
||||
# Check the test PDF file
|
||||
if os.path.exists('test_label.pdf'):
|
||||
file_size = os.path.getsize('test_label.pdf')
|
||||
print(f'test_label.pdf exists ({file_size} bytes)')
|
||||
print(f'Expected: 35mm x 25mm landscape (99.2 x 70.9 points)')
|
||||
print(f'')
|
||||
print(f'Open test_label.pdf in a PDF viewer to verify:')
|
||||
print(f' - Page size should be wider than tall')
|
||||
print(f' - Content should be correctly oriented')
|
||||
print(f'')
|
||||
print(f'In Adobe Reader: File > Properties > Description')
|
||||
print(f' Page size should show: 3.5 x 2.5 cm or 1.38 x 0.98 in')
|
||||
else:
|
||||
print('test_label.pdf not found')
|
||||
|
||||
64
conf/label_template_nok.svg
Normal file
64
conf/label_template_nok.svg
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="35mm" height="25mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 35 25"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<font id="FontID0" horiz-adv-x="722" font-variant="normal" style="fill-rule:nonzero" font-style="normal" font-weight="700">
|
||||
<font-face
|
||||
font-family="Arial">
|
||||
<font-face-src>
|
||||
<font-face-name name="Arial Bold"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<missing-glyph><path d="M0 0z"/></missing-glyph>
|
||||
<glyph unicode="." horiz-adv-x="277" d="M71.0096 0l0 136.998 136.998 0 0 -136.998 -136.998 0z"/>
|
||||
<glyph unicode=":" horiz-adv-x="332" d="M98.0096 381.997l0 136.998 136.998 0 0 -136.998 -136.998 0zm0 -381.997l0 136.998 136.998 0 0 -136.998 -136.998 0z"/>
|
||||
<glyph unicode="A" horiz-adv-x="722" d="M718.011 0l-156.185 0 -61.8388 162.999 -287.163 0 -59.482 -162.999 -153.342 0 277.993 715.987 153.162 0 286.856 -715.987zm-265.005 284.013l-99.4954 264.979 -96.6775 -264.979 196.173 0z"/>
|
||||
<glyph unicode="C" horiz-adv-x="722" d="M531.009 264.006l139.995 -43.0105c-21.4924,-78.8227 -57.3302,-137.331 -107.334,-175.654 -50.0038,-38.1689 -113.328,-57.3302 -190.179,-57.3302 -95.1661,0 -173.323,32.482 -234.649,97.4972 -61.1727,64.9896 -91.836,153.828 -91.836,266.67 0,119.143 30.8169,211.825 92.3227,277.813 61.5058,66.0143 142.506,99.0086 242.847,99.0086 87.6604,0 158.824,-26.001 213.49,-77.8236 32.6613,-30.6888 56.9972,-74.6727 73.3407,-132.182l-143.018 -33.9934c-8.47914,36.9905 -26.1547,66.3217 -52.9754,87.8397 -27,21.4924 -59.687,32.149 -98.0096,32.149 -53.1803,0 -96.3445,-18.982 -129.339,-57.1509 -33.1737,-38.0152 -49.6708,-99.6747 -49.6708,-185.004 0,-90.3246 16.3435,-154.827 48.8511,-193.176 32.6613,-38.5019 74.9801,-57.6632 127.161,-57.6632 38.5019,0 71.65,12.1679 99.316,36.6831 27.6661,24.4896 47.6727,62.8122 59.687,115.326z"/>
|
||||
<glyph unicode="N" horiz-adv-x="722" d="M73.0077 0l0 715.987 140.328 0 294.669 -479.827 0 479.827 134.001 0 0 -715.987 -144.837 0 -290.161 470.656 0 -470.656 -134.001 0z"/>
|
||||
<glyph unicode="S" horiz-adv-x="667" d="M34.9924 232.011l141.02 13.9867c8.47914,-47.1604 25.4886,-81.6661 51.3103,-103.825 25.8473,-22.1841 60.686,-33.1737 104.516,-33.1737 46.315,0 81.3331,9.83682 104.824,29.5105 23.5162,19.648 35.3255,42.6518 35.3255,68.9858 0,17.0095 -4.99526,31.3293 -14.8321,43.3435 -9.8112,11.8349 -27.1537,22.1585 -51.8226,30.8169 -16.8302,6.01993 -55.1784,16.3435 -115.173,31.3549 -77.1576,19.315 -131.337,42.9849 -162.487,71.1633 -43.8302,39.501 -65.6813,87.6604 -65.6813,144.504 0,36.4782 10.3492,70.8302 30.8425,102.646 20.6727,31.8416 50.3369,55.9982 89.1718,72.6746 38.835,16.6765 85.483,25.0019 140.482,25.0019 89.5048,0 157.005,-19.8273 202.167,-59.6613 45.3416,-39.834 69.0115,-92.835 71.3426,-159.336l-144.991 -4.99526c-6.17363,36.9905 -19.3406,63.5039 -39.501,79.668 -20.186,16.1642 -50.5162,24.3359 -90.8369,24.3359 -41.6784,0 -74.3397,-8.68407 -97.8303,-26.001 -15.1651,-11.1689 -22.8501,-26.001 -22.8501,-44.6756 0,-17.0095 7.17268,-31.5086 21.518,-43.4972 18.1623,-15.4981 62.3255,-31.5086 132.49,-48.1594 70.1642,-16.5228 122.012,-33.8397 155.494,-51.5152 33.686,-17.8292 60.02,-41.9858 79.002,-72.8283 19.0076,-30.8425 28.5114,-68.8321 28.5114,-113.994 0,-41.0124 -11.3482,-79.5143 -34.1727,-115.352 -22.8245,-35.8122 -54.9991,-62.4792 -96.6775,-79.8217 -41.6528,-17.4962 -93.6547,-26.1547 -155.827,-26.1547 -90.5039,0 -160.002,20.8264 -208.495,62.6585 -48.4925,41.6528 -77.3369,102.493 -86.8407,182.34z"/>
|
||||
<glyph unicode="a" horiz-adv-x="556" d="M173.989 358.993l-123.985 22.0048c13.9867,50.6699 38.1689,88.1728 72.3416,112.509 34.1471,24.3359 84.9963,36.5038 152.317,36.5038 61.1727,0 106.847,-7.17268 136.845,-21.6717 29.8179,-14.4991 51.0029,-32.8406 63.1708,-55.1784 12.1679,-22.3378 18.316,-63.1708 18.316,-122.832l-1.9981 -160.002c0,-45.4953 2.17742,-79.1557 6.50665,-100.827 4.32923,-21.6717 12.501,-44.8293 24.4896,-69.4982l-135.999 0c-3.48387,8.99147 -7.99242,22.3378 -13.167,39.9877 -2.1518,8.17173 -3.81689,13.5 -4.81594,16.0105 -23.3368,-23.0038 -48.3388,-40.167 -75.0058,-51.6689 -26.667,-11.5019 -54.9991,-17.3169 -85.1756,-17.3169 -53.1547,0 -95.1661,14.4991 -125.829,43.4972 -30.6632,28.8188 -46.0076,65.502 -46.0076,109.819 0,29.1774 7.01898,55.3321 21.0057,78.3359 14.0123,22.8245 33.5067,40.5 58.8416,52.668 25.1556,12.1679 61.5058,22.8245 108.999,31.9953 63.9906,12.0142 108.487,23.3368 133.156,33.6604l0 13.833c0,26.667 -6.48103,45.6746 -19.4943,57.1765 -13.167,11.3482 -37.8359,17.0095 -74.0067,17.0095 -24.4896,0 -43.4972,-4.84156 -57.1509,-14.6784 -13.833,-9.6575 -24.8482,-26.8207 -33.353,-51.3359zm184.005 -110.997c-17.4962,-5.84061 -45.316,-12.834 -83.4849,-21.0057 -38.0152,-8.14612 -63.0171,-16.1642 -74.6727,-23.8236 -17.8292,-12.834 -26.8463,-28.8444 -26.8463,-48.3388 0,-19.315 7.17268,-35.8378 21.518,-49.8245 14.3197,-14.0123 32.482,-21.0057 54.6661,-21.0057 24.6689,0 48.3388,8.17173 70.8302,24.3359 16.4972,12.501 27.4867,27.5124 32.6613,45.4953 3.50949,11.6812 5.32828,33.9934 5.32828,66.834l0 27.333z"/>
|
||||
<glyph unicode="c" horiz-adv-x="556" d="M523.99 365.013l-135 -24.0029c-4.48293,26.8207 -14.8321,46.9811 -30.9962,60.6604 -16.1642,13.5 -36.9905,20.3397 -62.6585,20.3397 -34.1727,0 -61.5058,-11.8349 -81.8454,-35.5048 -20.3141,-23.6699 -30.4839,-63.1708 -30.4839,-118.682 0,-61.6595 10.3235,-105.157 30.9962,-130.645 20.6727,-25.5143 48.3388,-38.1689 82.9982,-38.1689 26.001,0 47.3397,7.48008 63.8369,22.3122 16.6509,14.8577 28.3321,40.3463 35.1718,76.6709l135 -23.0038c-14.0123,-61.9925 -40.8331,-108.82 -80.5134,-140.482 -39.6547,-31.6623 -92.835,-47.4934 -159.669,-47.4934 -75.6718,0 -136.153,23.9773 -181.161,71.8293 -45.1623,47.9801 -67.6538,114.327 -67.6538,199.17 0,85.816 22.6452,152.496 67.8331,200.323 45.1623,47.8264 106.309,71.6756 183.493,71.6756 62.9915,0 113.175,-13.6793 150.498,-40.8331 37.1699,-27.1793 63.8369,-68.4991 80.1547,-124.164z"/>
|
||||
<glyph unicode="d" horiz-adv-x="610" d="M547.993 0l-126.982 0 0 76.1585c-21.185,-29.6642 -46.3407,-51.8226 -75.1851,-66.834 -28.8188,-14.8321 -57.9963,-22.3122 -87.3274,-22.3122 -59.8407,0 -110.997,23.9773 -153.675,72.1623 -42.4981,48.1594 -63.8113,115.147 -63.8113,201.322 0,87.9934 20.6471,155.007 62.1462,200.835 41.4991,45.8283 93.8341,68.6784 157.184,68.6784 57.9963,0 108.333,-24.1822 150.652,-72.3416l0 258.319 136.998 0 0 -715.987zm-365.986 269.488c0,-55.4858 7.6594,-95.6528 22.8245,-120.475 22.1585,-36.0171 53.001,-54.0001 92.6813,-54.0001 31.483,0 58.3293,13.5 80.3084,40.5 22.1841,27 33.1737,67.1414 33.1737,120.808 0,59.8407 -10.6566,102.851 -32.149,129.185 -21.518,26.334 -48.8511,39.501 -82.3578,39.501 -32.482,0 -59.6613,-13.0133 -81.6661,-39.0143 -21.8254,-26.001 -32.815,-64.8359 -32.815,-116.505z"/>
|
||||
<glyph unicode="e" horiz-adv-x="556" d="M372.006 163.998l136.998 -23.0038c-17.4962,-50.1575 -45.3416,-88.3265 -83.1775,-114.66 -37.9896,-26.1547 -85.483,-39.3217 -142.327,-39.3217 -90.1709,0 -157.005,29.4848 -200.169,88.4802 -34.1727,47.3397 -51.3359,107.001 -51.3359,179.163 0,86.021 22.5171,153.521 67.3464,202.167 44.8293,48.8511 101.647,73.187 170.326,73.187 77.0039,0 137.844,-25.5143 182.494,-76.5172 44.4962,-51.0029 65.835,-129.16 63.8369,-234.495l-343.008 0c0.999052,-40.6537 12.0142,-72.3416 33.1737,-94.9868 21.0057,-22.6708 47.3397,-34.019 78.669,-34.019 21.4924,0 39.501,5.84061 54.0001,17.4962 14.6784,11.6812 25.668,30.5095 33.1737,56.5105zm7.99242 138.996c-0.999052,39.834 -11.1689,70.1642 -30.6632,90.8369 -19.4943,20.8264 -43.1642,31.1756 -71.1633,31.1756 -29.8435,0 -54.5124,-11.0152 -74.0067,-32.8406 -19.4943,-21.8254 -28.9981,-51.6689 -28.6651,-89.1718l204.498 0z"/>
|
||||
<glyph unicode="i" horiz-adv-x="277" d="M72.0086 589.005l0 126.982 136.998 0 0 -126.982 -136.998 0zm0 -589.005l0 518.995 136.998 0 0 -518.995 -136.998 0z"/>
|
||||
<glyph unicode="l" horiz-adv-x="277" d="M72.0086 0l0 715.987 136.998 0 0 -715.987 -136.998 0z"/>
|
||||
<glyph unicode="m" horiz-adv-x="889" d="M61.9925 518.995l126.009 0 0 -70.8302c45.1623,54.5124 99.0086,81.8454 161.488,81.8454 33.1737,0 62.0181,-6.83966 86.354,-20.519 24.4896,-13.6537 44.4962,-34.3264 59.9944,-61.9925 22.8245,27.6661 47.4934,48.3388 73.8274,61.9925 26.334,13.6793 54.5124,20.519 84.5096,20.519 37.9896,0 70.1642,-7.68502 96.6519,-23.1831 26.334,-15.4981 46.0076,-38.1689 58.9953,-68.1661 9.5038,-22.0048 14.166,-57.8169 14.166,-107.334l0 -331.327 -136.998 0 0 296.155c0,51.5152 -4.66224,84.6889 -14.166,99.521 -12.6547,19.4943 -32.3283,29.3311 -58.6623,29.3311 -19.1613,0 -37.3236,-5.84061 -54.3331,-17.4962 -16.8302,-11.8349 -29.1518,-28.9981 -36.6575,-51.5152 -7.5057,-22.6708 -11.1689,-58.3293 -11.1689,-107.155l0 -248.841 -136.998 0 0 284.013c0,50.3112 -2.51044,82.9982 -7.32638,97.4972 -4.84156,14.6528 -12.3473,25.668 -22.6708,32.815 -10.1698,7.17268 -24.1822,10.6822 -41.6784,10.6822 -21.1594,0 -40.167,-5.6613 -56.9972,-17.0095 -17.0095,-11.5019 -28.9981,-27.8198 -36.3245,-49.3378 -7.352,-21.4924 -11.0152,-57.1509 -11.0152,-106.822l0 -251.838 -136.998 0 0 518.995z"/>
|
||||
<glyph unicode="n" horiz-adv-x="610" d="M543.997 0l-136.998 0 0 264.493c0,55.9982 -2.99716,92.169 -8.83777,108.512 -5.99431,16.4972 -15.4981,29.1518 -28.8188,38.3226 -13.3463,9.17079 -29.3311,13.6793 -48.0057,13.6793 -24.0029,0 -45.4953,-6.50665 -64.5029,-19.4943 -19.1613,-13.0133 -32.1746,-30.3558 -39.168,-51.6689 -7.17268,-21.518 -10.6566,-61.1727 -10.6566,-119.169l0 -234.675 -136.998 0 0 518.995 126.982 0 0 -76.1585c45.4953,58.1756 102.672,87.1737 171.837,87.1737 30.3302,0 58.1756,-5.5076 83.3312,-16.3435 25.3349,-10.9896 44.3425,-24.8226 57.1765,-41.6784 12.9877,-16.9839 22.0048,-36.1452 27,-57.6632 5.17458,-21.4924 7.6594,-52.1556 7.6594,-92.169l0 -322.156z"/>
|
||||
<glyph unicode="o" horiz-adv-x="610" d="M39.9877 265.825c0,45.6746 11.1689,89.8378 33.686,132.515 22.4915,42.8312 54.3331,75.3388 95.4991,97.8303 41.1661,22.4915 86.9944,33.8397 137.818,33.8397 78.5153,0 142.685,-25.5143 192.843,-76.5172 50.1575,-51.1566 75.1595,-115.48 75.1595,-193.483 0,-78.669 -25.3349,-143.838 -75.8255,-195.507 -50.6699,-51.6689 -114.327,-77.4906 -191.178,-77.4906 -47.4934,0 -92.835,10.8103 -135.999,32.3283 -42.9849,21.4924 -75.8255,53.001 -98.317,94.6538 -22.5171,41.4991 -33.686,92.169 -33.686,151.83zm141.02 -7.32638c0,-51.4896 12.1679,-90.9906 36.5038,-118.324 24.4896,-27.5124 54.4868,-41.1661 90.3246,-41.1661 35.6585,0 65.6557,13.6537 89.8378,41.1661 24.1566,27.333 36.3245,67.167 36.3245,119.323 0,50.8236 -12.1679,89.9915 -36.3245,117.325 -24.1822,27.5124 -54.1794,41.1661 -89.8378,41.1661 -35.8378,0 -65.835,-13.6537 -90.3246,-41.1661 -24.3359,-27.333 -36.5038,-66.834 -36.5038,-118.324z"/>
|
||||
<glyph unicode="r" horiz-adv-x="389" d="M203.013 0l-137.024 0 0 518.995 127.008 0 0 -73.6737c21.8254,34.8387 41.4991,57.6889 58.9953,68.5247 17.4962,10.8103 37.3492,16.1642 59.5076,16.1642 31.3293,0 61.5058,-8.68407 90.5039,-25.8473l-42.4981 -119.656c-23.1831,14.9858 -44.6756,22.4915 -64.5029,22.4915 -19.3406,0 -35.6585,-5.32828 -49.0048,-15.8311 -13.3207,-10.6566 -23.8236,-29.6642 -31.5086,-57.3302 -7.6594,-27.6661 -11.4763,-85.6623 -11.4763,-173.835l0 -160.002z"/>
|
||||
<glyph unicode="t" horiz-adv-x="332" d="M308.989 518.995l0 -108.999 -93.9878 0 0 -210.16c0,-42.6775 0.819735,-67.5001 2.66414,-74.4934 1.8444,-7.01898 5.84061,-12.834 12.3473,-17.5218 6.32733,-4.48293 13.9867,-6.81405 23.1575,-6.81405 12.834,0 31.1756,4.32923 55.3321,13.167l11.5019 -106.668c-31.8416,-13.6793 -67.8331,-20.4934 -108.179,-20.4934 -24.6689,0 -46.8274,4.14991 -66.6547,12.4753 -19.8273,8.35105 -34.3264,19.1869 -43.4972,32.3539 -9.3501,13.3207 -15.6774,31.1499 -19.3406,53.8207 -2.84346,16.0105 -4.32923,48.3388 -4.32923,97.1642l0 227.169 -62.9915 0 0 108.999 62.9915 0 0 103.005 136.998 81.0001 0 -184.005 93.9878 0z"/>
|
||||
<glyph unicode="{" horiz-adv-x="389" d="M28.9981 200.989l0 117.017c23.8236,1.33207 41.6784,4.81594 53.8464,10.8359 11.9886,5.815 22.3122,15.6518 31.1499,29.4848 8.83777,13.833 14.8321,31.1756 18.1623,52.0019 2.51044,15.6774 3.84251,42.8312 3.84251,81.6661 0,63.1708 2.99716,107.18 8.83777,132.182 5.84061,25.0019 16.3179,44.983 31.6623,60.1481 15.3444,15.1651 37.6566,27 66.834,35.8378 19.8273,5.84061 51.1566,8.83777 93.8341,8.83777l25.8217 0 0 -116.992c-36.3245,0 -59.482,-1.9981 -69.8312,-6.17363 -10.3235,-3.99621 -17.8292,-10.1698 -22.8245,-18.4953 -4.84156,-8.35105 -7.32638,-22.5171 -7.32638,-42.6775 0,-20.4934 -1.33207,-59.5076 -3.99621,-116.659 -1.66509,-32.3283 -5.84061,-58.3293 -12.6803,-78.5153 -6.83966,-19.981 -15.4981,-36.4782 -26.1547,-49.4915 -10.5029,-12.9877 -26.667,-26.4877 -48.5181,-40.5 19.3406,-10.9896 35.0181,-24.0029 47.3397,-38.835 12.3473,-14.8321 21.6717,-32.8406 28.1784,-54.0001 6.66035,-21.1594 10.8359,-49.6708 12.834,-85.15 1.9981,-54.0001 2.99716,-88.6851 2.99716,-103.671 0,-21.518 2.66414,-36.5038 7.83872,-45.0086 5.14896,-8.32543 12.9877,-14.8321 23.6442,-19.1613 10.5029,-4.50854 33.353,-6.66035 68.4991,-6.66035l0 -117.017 -25.8217 0c-44.0095,0 -77.6699,3.50949 -101.16,10.5029 -23.3368,6.99337 -43.1642,18.6746 -59.1746,34.9924 -16.1642,16.1898 -27,36.3501 -32.5076,60.353 -5.48198,23.8236 -8.32543,61.6595 -8.32543,113.149 0,59.8407 -2.66414,98.8293 -7.83872,116.684 -7.17268,26.1547 -17.9829,44.8293 -32.482,55.9982 -14.4991,11.3226 -36.6831,17.6499 -66.6803,19.315z"/>
|
||||
<glyph unicode="}" horiz-adv-x="389" d="M355.996 200.989c-23.8236,-1.33207 -41.6528,-4.81594 -53.667,-10.6566 -12.1679,-5.99431 -22.4915,-15.8311 -31.1499,-29.6642 -8.50475,-13.833 -14.6784,-31.1756 -18.3416,-52.0019 -2.51044,-15.6774 -3.84251,-42.6775 -3.84251,-81.1538 0,-63.1708 -2.81784,-107.334 -8.50475,-132.515 -5.6613,-25.0019 -16.1642,-45.1623 -31.483,-60.3274 -15.3444,-15.1651 -37.8359,-27 -67.3464,-35.8378 -19.8273,-5.84061 -51.1566,-8.83777 -93.8341,-8.83777l-25.8217 0 0 117.017c34.9924,0 57.8169,2.1518 68.6528,6.66035 10.6822,4.32923 18.6746,10.6566 23.6699,19.0076 5.17458,8.32543 7.68502,22.3122 7.83872,42.3188 0.179317,19.8273 1.51139,57.8426 3.84251,113.841 1.66509,33.9934 5.99431,60.9934 13.167,81.4868 7.14707,20.3397 16.6509,37.6822 28.4858,51.8482 12.0142,14.166 27.1793,26.4877 45.6746,37.3236 -24.0029,15.6774 -41.6784,30.9962 -52.668,45.8283 -15.3444,21.518 -25.8473,48.8511 -31.3293,82.1784 -3.50949,22.6708 -5.99431,72.8283 -7.32638,150.319 -0.333017,24.3359 -2.51044,40.6794 -6.68596,48.8511 -3.99621,7.99242 -11.3226,14.3197 -22.0048,18.649 -10.6566,4.50854 -34.3264,6.68596 -71.317,6.68596l0 116.992 25.8217 0c44.0095,0 77.6699,-3.50949 101.186,-10.3235 23.3112,-6.83966 42.9849,-18.5209 58.9953,-34.8387 15.9848,-16.4972 26.8207,-36.6831 32.482,-60.6604 5.68691,-23.8492 8.50475,-61.6851 8.50475,-113.175 0,-59.5076 2.51044,-98.4963 7.32638,-116.659 7.17268,-26.1803 18.0086,-44.8549 32.6869,-56.0238 14.6528,-11.3226 36.9905,-17.6499 66.9877,-19.315l0 -117.017z"/>
|
||||
</font>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
@font-face { font-family:"Arial";font-variant:normal;font-style:normal;font-weight:bold;src:url("#FontID0") format(svg)}
|
||||
.fil0 {fill:#373435}
|
||||
.fil1 {fill:#373435}
|
||||
.fil2 {fill:#373435;fill-rule:nonzero}
|
||||
.fnt0 {font-weight:bold;font-size:3.9037px;font-family:'Arial'}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g transform="matrix(0.576293 0 0 1 -8.27317 4.15816)">
|
||||
<text x="17.5" y="12.5" class="fil0 fnt0">Nr. Comanda:{Article}</text>
|
||||
</g>
|
||||
<g transform="matrix(0.576293 0 0 1 -8.27317 7.72657)">
|
||||
<text x="17.5" y="12.5" class="fil0 fnt0">Nr. Art.:{NrArt}</text>
|
||||
</g>
|
||||
<g transform="matrix(0.576293 0 0 1 -8.33607 11.0472)">
|
||||
<text x="17.5" y="12.5" class="fil0 fnt0">Serial No.:{Serial}</text>
|
||||
</g>
|
||||
<g id="_1503869020736">
|
||||
<path class="fil1" d="M13.9026 6.1147c-0.0969,0.0226 -0.5344,0.3421 -0.5861,0.348 -0.0365,0.0041 -0.3442,-0.227 -0.3951,-0.2642 -0.0499,-0.0364 -0.0741,-0.0672 -0.136,-0.0838 0,0.0623 0.0141,0.1755 0.0234,0.2513 0.0277,0.2244 0.0714,0.489 0.1349,0.7076 0.086,0.2957 0.1778,0.558 0.3056,0.8116 0.2029,0.4024 0.3688,0.6622 0.6587,1.008 0.7996,0.9535 2.1521,1.6354 3.4012,1.6354 0.8602,0 1.4215,-0.0956 2.1368,-0.4273 0.2518,-0.1167 0.4901,-0.2561 0.7094,-0.4077 0.3749,-0.2591 0.6465,-0.5227 0.9323,-0.8626 0.0294,-0.035 0.0411,-0.0435 0.0679,-0.0786 0.57,-0.7469 0.8516,-1.4248 0.9811,-2.3706 0.0101,-0.0742 0.0259,-0.2049 0.0259,-0.2671 -0.0958,-0.0641 -0.1973,-0.1198 -0.293,-0.1831 -0.3674,-0.243 -0.2819,-0.2176 -0.5911,0.0133 -0.3726,0.278 -0.1599,0.0504 -0.3023,0.6684 -0.032,0.1389 -0.0657,0.2528 -0.1072,0.3873 -0.2015,0.6534 -0.7073,1.2896 -1.2311,1.6992 -0.1584,0.1239 -0.4254,0.286 -0.6008,0.37 -1.2009,0.5747 -2.7309,0.4386 -3.7667,-0.4035 -0.1586,-0.1289 -0.3761,-0.3128 -0.4993,-0.4714 -0.2438,-0.3139 -0.3987,-0.4932 -0.5704,-0.8948 -0.1469,-0.3437 -0.2981,-0.8086 -0.2981,-1.1854z"/>
|
||||
<path class="fil1" d="M12.7854 5.5653c0.092,0.0616 0.1745,0.1224 0.2711,0.1868 0.3448,0.2298 0.2204,0.2304 0.5604,0.0037 0.1015,-0.0677 0.1895,-0.1261 0.2857,-0.1905 0,-0.6008 0.3296,-1.3796 0.7036,-1.8788 0.1683,-0.2248 0.5135,-0.5784 0.7579,-0.7439 0.6122,-0.4147 1.1468,-0.6373 1.9084,-0.674 0.2685,-0.013 0.0473,-0.0281 0.3856,-0.001 0.2398,0.0192 0.2983,0.0032 0.5892,0.0702 0.4301,0.0991 0.855,0.2746 1.2086,0.513 0.7053,0.4753 1.2198,1.1687 1.4592,1.984 0.0526,0.1792 0.1303,0.5118 0.1303,0.7305 0.0881,-0.0235 0.4644,-0.3425 0.5128,-0.348 0.0656,0.0175 0.2282,0.1315 0.301,0.1752 0.0656,0.0395 0.2453,0.1592 0.3034,0.1728l-0.0573 -0.4922c-0.1187,-0.6931 -0.4034,-1.4203 -0.8244,-1.9778 -0.177,-0.2344 -0.4287,-0.5477 -0.6595,-0.7324 -0.1682,-0.1347 -0.2514,-0.2282 -0.466,-0.3765 -0.6841,-0.4728 -1.6125,-0.835 -2.5349,-0.835 -0.8789,0 -1.3878,0.1016 -2.106,0.4215 -1.3809,0.6151 -2.4156,1.9744 -2.669,3.4847 -0.0144,0.0857 -0.0219,0.1508 -0.0342,0.2406 -0.0101,0.0742 -0.0259,0.2049 -0.0259,0.2671z"/>
|
||||
<polygon class="fil2" points="14.8273,3.5997 16.8077,3.5997 17.5,4.8137 18.3014,3.5997 20.1392,3.5997 18.658,5.6752 20.2482,7.9549 18.3014,7.9549 17.5,6.5521 16.5476,7.9549 14.7434,7.9549 16.328,5.6752 "/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
63
conf/label_template_ok.svg
Normal file
63
conf/label_template_ok.svg
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="35mm" height="25mm" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
|
||||
viewBox="0 0 35 25"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<defs>
|
||||
<font id="FontID0" horiz-adv-x="722" font-variant="normal" style="fill-rule:nonzero" font-style="normal" font-weight="700">
|
||||
<font-face
|
||||
font-family="Arial">
|
||||
<font-face-src>
|
||||
<font-face-name name="Arial Bold"/>
|
||||
</font-face-src>
|
||||
</font-face>
|
||||
<missing-glyph><path d="M0 0z"/></missing-glyph>
|
||||
<glyph unicode="." horiz-adv-x="277" d="M71.0096 0l0 136.998 136.998 0 0 -136.998 -136.998 0z"/>
|
||||
<glyph unicode=":" horiz-adv-x="332" d="M98.0096 381.997l0 136.998 136.998 0 0 -136.998 -136.998 0zm0 -381.997l0 136.998 136.998 0 0 -136.998 -136.998 0z"/>
|
||||
<glyph unicode="A" horiz-adv-x="722" d="M718.011 0l-156.185 0 -61.8388 162.999 -287.163 0 -59.482 -162.999 -153.342 0 277.993 715.987 153.162 0 286.856 -715.987zm-265.005 284.013l-99.4954 264.979 -96.6775 -264.979 196.173 0z"/>
|
||||
<glyph unicode="C" horiz-adv-x="722" d="M531.009 264.006l139.995 -43.0105c-21.4924,-78.8227 -57.3302,-137.331 -107.334,-175.654 -50.0038,-38.1689 -113.328,-57.3302 -190.179,-57.3302 -95.1661,0 -173.323,32.482 -234.649,97.4972 -61.1727,64.9896 -91.836,153.828 -91.836,266.67 0,119.143 30.8169,211.825 92.3227,277.813 61.5058,66.0143 142.506,99.0086 242.847,99.0086 87.6604,0 158.824,-26.001 213.49,-77.8236 32.6613,-30.6888 56.9972,-74.6727 73.3407,-132.182l-143.018 -33.9934c-8.47914,36.9905 -26.1547,66.3217 -52.9754,87.8397 -27,21.4924 -59.687,32.149 -98.0096,32.149 -53.1803,0 -96.3445,-18.982 -129.339,-57.1509 -33.1737,-38.0152 -49.6708,-99.6747 -49.6708,-185.004 0,-90.3246 16.3435,-154.827 48.8511,-193.176 32.6613,-38.5019 74.9801,-57.6632 127.161,-57.6632 38.5019,0 71.65,12.1679 99.316,36.6831 27.6661,24.4896 47.6727,62.8122 59.687,115.326z"/>
|
||||
<glyph unicode="N" horiz-adv-x="722" d="M73.0077 0l0 715.987 140.328 0 294.669 -479.827 0 479.827 134.001 0 0 -715.987 -144.837 0 -290.161 470.656 0 -470.656 -134.001 0z"/>
|
||||
<glyph unicode="S" horiz-adv-x="667" d="M34.9924 232.011l141.02 13.9867c8.47914,-47.1604 25.4886,-81.6661 51.3103,-103.825 25.8473,-22.1841 60.686,-33.1737 104.516,-33.1737 46.315,0 81.3331,9.83682 104.824,29.5105 23.5162,19.648 35.3255,42.6518 35.3255,68.9858 0,17.0095 -4.99526,31.3293 -14.8321,43.3435 -9.8112,11.8349 -27.1537,22.1585 -51.8226,30.8169 -16.8302,6.01993 -55.1784,16.3435 -115.173,31.3549 -77.1576,19.315 -131.337,42.9849 -162.487,71.1633 -43.8302,39.501 -65.6813,87.6604 -65.6813,144.504 0,36.4782 10.3492,70.8302 30.8425,102.646 20.6727,31.8416 50.3369,55.9982 89.1718,72.6746 38.835,16.6765 85.483,25.0019 140.482,25.0019 89.5048,0 157.005,-19.8273 202.167,-59.6613 45.3416,-39.834 69.0115,-92.835 71.3426,-159.336l-144.991 -4.99526c-6.17363,36.9905 -19.3406,63.5039 -39.501,79.668 -20.186,16.1642 -50.5162,24.3359 -90.8369,24.3359 -41.6784,0 -74.3397,-8.68407 -97.8303,-26.001 -15.1651,-11.1689 -22.8501,-26.001 -22.8501,-44.6756 0,-17.0095 7.17268,-31.5086 21.518,-43.4972 18.1623,-15.4981 62.3255,-31.5086 132.49,-48.1594 70.1642,-16.5228 122.012,-33.8397 155.494,-51.5152 33.686,-17.8292 60.02,-41.9858 79.002,-72.8283 19.0076,-30.8425 28.5114,-68.8321 28.5114,-113.994 0,-41.0124 -11.3482,-79.5143 -34.1727,-115.352 -22.8245,-35.8122 -54.9991,-62.4792 -96.6775,-79.8217 -41.6528,-17.4962 -93.6547,-26.1547 -155.827,-26.1547 -90.5039,0 -160.002,20.8264 -208.495,62.6585 -48.4925,41.6528 -77.3369,102.493 -86.8407,182.34z"/>
|
||||
<glyph unicode="a" horiz-adv-x="556" d="M173.989 358.993l-123.985 22.0048c13.9867,50.6699 38.1689,88.1728 72.3416,112.509 34.1471,24.3359 84.9963,36.5038 152.317,36.5038 61.1727,0 106.847,-7.17268 136.845,-21.6717 29.8179,-14.4991 51.0029,-32.8406 63.1708,-55.1784 12.1679,-22.3378 18.316,-63.1708 18.316,-122.832l-1.9981 -160.002c0,-45.4953 2.17742,-79.1557 6.50665,-100.827 4.32923,-21.6717 12.501,-44.8293 24.4896,-69.4982l-135.999 0c-3.48387,8.99147 -7.99242,22.3378 -13.167,39.9877 -2.1518,8.17173 -3.81689,13.5 -4.81594,16.0105 -23.3368,-23.0038 -48.3388,-40.167 -75.0058,-51.6689 -26.667,-11.5019 -54.9991,-17.3169 -85.1756,-17.3169 -53.1547,0 -95.1661,14.4991 -125.829,43.4972 -30.6632,28.8188 -46.0076,65.502 -46.0076,109.819 0,29.1774 7.01898,55.3321 21.0057,78.3359 14.0123,22.8245 33.5067,40.5 58.8416,52.668 25.1556,12.1679 61.5058,22.8245 108.999,31.9953 63.9906,12.0142 108.487,23.3368 133.156,33.6604l0 13.833c0,26.667 -6.48103,45.6746 -19.4943,57.1765 -13.167,11.3482 -37.8359,17.0095 -74.0067,17.0095 -24.4896,0 -43.4972,-4.84156 -57.1509,-14.6784 -13.833,-9.6575 -24.8482,-26.8207 -33.353,-51.3359zm184.005 -110.997c-17.4962,-5.84061 -45.316,-12.834 -83.4849,-21.0057 -38.0152,-8.14612 -63.0171,-16.1642 -74.6727,-23.8236 -17.8292,-12.834 -26.8463,-28.8444 -26.8463,-48.3388 0,-19.315 7.17268,-35.8378 21.518,-49.8245 14.3197,-14.0123 32.482,-21.0057 54.6661,-21.0057 24.6689,0 48.3388,8.17173 70.8302,24.3359 16.4972,12.501 27.4867,27.5124 32.6613,45.4953 3.50949,11.6812 5.32828,33.9934 5.32828,66.834l0 27.333z"/>
|
||||
<glyph unicode="c" horiz-adv-x="556" d="M523.99 365.013l-135 -24.0029c-4.48293,26.8207 -14.8321,46.9811 -30.9962,60.6604 -16.1642,13.5 -36.9905,20.3397 -62.6585,20.3397 -34.1727,0 -61.5058,-11.8349 -81.8454,-35.5048 -20.3141,-23.6699 -30.4839,-63.1708 -30.4839,-118.682 0,-61.6595 10.3235,-105.157 30.9962,-130.645 20.6727,-25.5143 48.3388,-38.1689 82.9982,-38.1689 26.001,0 47.3397,7.48008 63.8369,22.3122 16.6509,14.8577 28.3321,40.3463 35.1718,76.6709l135 -23.0038c-14.0123,-61.9925 -40.8331,-108.82 -80.5134,-140.482 -39.6547,-31.6623 -92.835,-47.4934 -159.669,-47.4934 -75.6718,0 -136.153,23.9773 -181.161,71.8293 -45.1623,47.9801 -67.6538,114.327 -67.6538,199.17 0,85.816 22.6452,152.496 67.8331,200.323 45.1623,47.8264 106.309,71.6756 183.493,71.6756 62.9915,0 113.175,-13.6793 150.498,-40.8331 37.1699,-27.1793 63.8369,-68.4991 80.1547,-124.164z"/>
|
||||
<glyph unicode="d" horiz-adv-x="610" d="M547.993 0l-126.982 0 0 76.1585c-21.185,-29.6642 -46.3407,-51.8226 -75.1851,-66.834 -28.8188,-14.8321 -57.9963,-22.3122 -87.3274,-22.3122 -59.8407,0 -110.997,23.9773 -153.675,72.1623 -42.4981,48.1594 -63.8113,115.147 -63.8113,201.322 0,87.9934 20.6471,155.007 62.1462,200.835 41.4991,45.8283 93.8341,68.6784 157.184,68.6784 57.9963,0 108.333,-24.1822 150.652,-72.3416l0 258.319 136.998 0 0 -715.987zm-365.986 269.488c0,-55.4858 7.6594,-95.6528 22.8245,-120.475 22.1585,-36.0171 53.001,-54.0001 92.6813,-54.0001 31.483,0 58.3293,13.5 80.3084,40.5 22.1841,27 33.1737,67.1414 33.1737,120.808 0,59.8407 -10.6566,102.851 -32.149,129.185 -21.518,26.334 -48.8511,39.501 -82.3578,39.501 -32.482,0 -59.6613,-13.0133 -81.6661,-39.0143 -21.8254,-26.001 -32.815,-64.8359 -32.815,-116.505z"/>
|
||||
<glyph unicode="e" horiz-adv-x="556" d="M372.006 163.998l136.998 -23.0038c-17.4962,-50.1575 -45.3416,-88.3265 -83.1775,-114.66 -37.9896,-26.1547 -85.483,-39.3217 -142.327,-39.3217 -90.1709,0 -157.005,29.4848 -200.169,88.4802 -34.1727,47.3397 -51.3359,107.001 -51.3359,179.163 0,86.021 22.5171,153.521 67.3464,202.167 44.8293,48.8511 101.647,73.187 170.326,73.187 77.0039,0 137.844,-25.5143 182.494,-76.5172 44.4962,-51.0029 65.835,-129.16 63.8369,-234.495l-343.008 0c0.999052,-40.6537 12.0142,-72.3416 33.1737,-94.9868 21.0057,-22.6708 47.3397,-34.019 78.669,-34.019 21.4924,0 39.501,5.84061 54.0001,17.4962 14.6784,11.6812 25.668,30.5095 33.1737,56.5105zm7.99242 138.996c-0.999052,39.834 -11.1689,70.1642 -30.6632,90.8369 -19.4943,20.8264 -43.1642,31.1756 -71.1633,31.1756 -29.8435,0 -54.5124,-11.0152 -74.0067,-32.8406 -19.4943,-21.8254 -28.9981,-51.6689 -28.6651,-89.1718l204.498 0z"/>
|
||||
<glyph unicode="i" horiz-adv-x="277" d="M72.0086 589.005l0 126.982 136.998 0 0 -126.982 -136.998 0zm0 -589.005l0 518.995 136.998 0 0 -518.995 -136.998 0z"/>
|
||||
<glyph unicode="l" horiz-adv-x="277" d="M72.0086 0l0 715.987 136.998 0 0 -715.987 -136.998 0z"/>
|
||||
<glyph unicode="m" horiz-adv-x="889" d="M61.9925 518.995l126.009 0 0 -70.8302c45.1623,54.5124 99.0086,81.8454 161.488,81.8454 33.1737,0 62.0181,-6.83966 86.354,-20.519 24.4896,-13.6537 44.4962,-34.3264 59.9944,-61.9925 22.8245,27.6661 47.4934,48.3388 73.8274,61.9925 26.334,13.6793 54.5124,20.519 84.5096,20.519 37.9896,0 70.1642,-7.68502 96.6519,-23.1831 26.334,-15.4981 46.0076,-38.1689 58.9953,-68.1661 9.5038,-22.0048 14.166,-57.8169 14.166,-107.334l0 -331.327 -136.998 0 0 296.155c0,51.5152 -4.66224,84.6889 -14.166,99.521 -12.6547,19.4943 -32.3283,29.3311 -58.6623,29.3311 -19.1613,0 -37.3236,-5.84061 -54.3331,-17.4962 -16.8302,-11.8349 -29.1518,-28.9981 -36.6575,-51.5152 -7.5057,-22.6708 -11.1689,-58.3293 -11.1689,-107.155l0 -248.841 -136.998 0 0 284.013c0,50.3112 -2.51044,82.9982 -7.32638,97.4972 -4.84156,14.6528 -12.3473,25.668 -22.6708,32.815 -10.1698,7.17268 -24.1822,10.6822 -41.6784,10.6822 -21.1594,0 -40.167,-5.6613 -56.9972,-17.0095 -17.0095,-11.5019 -28.9981,-27.8198 -36.3245,-49.3378 -7.352,-21.4924 -11.0152,-57.1509 -11.0152,-106.822l0 -251.838 -136.998 0 0 518.995z"/>
|
||||
<glyph unicode="n" horiz-adv-x="610" d="M543.997 0l-136.998 0 0 264.493c0,55.9982 -2.99716,92.169 -8.83777,108.512 -5.99431,16.4972 -15.4981,29.1518 -28.8188,38.3226 -13.3463,9.17079 -29.3311,13.6793 -48.0057,13.6793 -24.0029,0 -45.4953,-6.50665 -64.5029,-19.4943 -19.1613,-13.0133 -32.1746,-30.3558 -39.168,-51.6689 -7.17268,-21.518 -10.6566,-61.1727 -10.6566,-119.169l0 -234.675 -136.998 0 0 518.995 126.982 0 0 -76.1585c45.4953,58.1756 102.672,87.1737 171.837,87.1737 30.3302,0 58.1756,-5.5076 83.3312,-16.3435 25.3349,-10.9896 44.3425,-24.8226 57.1765,-41.6784 12.9877,-16.9839 22.0048,-36.1452 27,-57.6632 5.17458,-21.4924 7.6594,-52.1556 7.6594,-92.169l0 -322.156z"/>
|
||||
<glyph unicode="o" horiz-adv-x="610" d="M39.9877 265.825c0,45.6746 11.1689,89.8378 33.686,132.515 22.4915,42.8312 54.3331,75.3388 95.4991,97.8303 41.1661,22.4915 86.9944,33.8397 137.818,33.8397 78.5153,0 142.685,-25.5143 192.843,-76.5172 50.1575,-51.1566 75.1595,-115.48 75.1595,-193.483 0,-78.669 -25.3349,-143.838 -75.8255,-195.507 -50.6699,-51.6689 -114.327,-77.4906 -191.178,-77.4906 -47.4934,0 -92.835,10.8103 -135.999,32.3283 -42.9849,21.4924 -75.8255,53.001 -98.317,94.6538 -22.5171,41.4991 -33.686,92.169 -33.686,151.83zm141.02 -7.32638c0,-51.4896 12.1679,-90.9906 36.5038,-118.324 24.4896,-27.5124 54.4868,-41.1661 90.3246,-41.1661 35.6585,0 65.6557,13.6537 89.8378,41.1661 24.1566,27.333 36.3245,67.167 36.3245,119.323 0,50.8236 -12.1679,89.9915 -36.3245,117.325 -24.1822,27.5124 -54.1794,41.1661 -89.8378,41.1661 -35.8378,0 -65.835,-13.6537 -90.3246,-41.1661 -24.3359,-27.333 -36.5038,-66.834 -36.5038,-118.324z"/>
|
||||
<glyph unicode="r" horiz-adv-x="389" d="M203.013 0l-137.024 0 0 518.995 127.008 0 0 -73.6737c21.8254,34.8387 41.4991,57.6889 58.9953,68.5247 17.4962,10.8103 37.3492,16.1642 59.5076,16.1642 31.3293,0 61.5058,-8.68407 90.5039,-25.8473l-42.4981 -119.656c-23.1831,14.9858 -44.6756,22.4915 -64.5029,22.4915 -19.3406,0 -35.6585,-5.32828 -49.0048,-15.8311 -13.3207,-10.6566 -23.8236,-29.6642 -31.5086,-57.3302 -7.6594,-27.6661 -11.4763,-85.6623 -11.4763,-173.835l0 -160.002z"/>
|
||||
<glyph unicode="t" horiz-adv-x="332" d="M308.989 518.995l0 -108.999 -93.9878 0 0 -210.16c0,-42.6775 0.819735,-67.5001 2.66414,-74.4934 1.8444,-7.01898 5.84061,-12.834 12.3473,-17.5218 6.32733,-4.48293 13.9867,-6.81405 23.1575,-6.81405 12.834,0 31.1756,4.32923 55.3321,13.167l11.5019 -106.668c-31.8416,-13.6793 -67.8331,-20.4934 -108.179,-20.4934 -24.6689,0 -46.8274,4.14991 -66.6547,12.4753 -19.8273,8.35105 -34.3264,19.1869 -43.4972,32.3539 -9.3501,13.3207 -15.6774,31.1499 -19.3406,53.8207 -2.84346,16.0105 -4.32923,48.3388 -4.32923,97.1642l0 227.169 -62.9915 0 0 108.999 62.9915 0 0 103.005 136.998 81.0001 0 -184.005 93.9878 0z"/>
|
||||
<glyph unicode="{" horiz-adv-x="389" d="M28.9981 200.989l0 117.017c23.8236,1.33207 41.6784,4.81594 53.8464,10.8359 11.9886,5.815 22.3122,15.6518 31.1499,29.4848 8.83777,13.833 14.8321,31.1756 18.1623,52.0019 2.51044,15.6774 3.84251,42.8312 3.84251,81.6661 0,63.1708 2.99716,107.18 8.83777,132.182 5.84061,25.0019 16.3179,44.983 31.6623,60.1481 15.3444,15.1651 37.6566,27 66.834,35.8378 19.8273,5.84061 51.1566,8.83777 93.8341,8.83777l25.8217 0 0 -116.992c-36.3245,0 -59.482,-1.9981 -69.8312,-6.17363 -10.3235,-3.99621 -17.8292,-10.1698 -22.8245,-18.4953 -4.84156,-8.35105 -7.32638,-22.5171 -7.32638,-42.6775 0,-20.4934 -1.33207,-59.5076 -3.99621,-116.659 -1.66509,-32.3283 -5.84061,-58.3293 -12.6803,-78.5153 -6.83966,-19.981 -15.4981,-36.4782 -26.1547,-49.4915 -10.5029,-12.9877 -26.667,-26.4877 -48.5181,-40.5 19.3406,-10.9896 35.0181,-24.0029 47.3397,-38.835 12.3473,-14.8321 21.6717,-32.8406 28.1784,-54.0001 6.66035,-21.1594 10.8359,-49.6708 12.834,-85.15 1.9981,-54.0001 2.99716,-88.6851 2.99716,-103.671 0,-21.518 2.66414,-36.5038 7.83872,-45.0086 5.14896,-8.32543 12.9877,-14.8321 23.6442,-19.1613 10.5029,-4.50854 33.353,-6.66035 68.4991,-6.66035l0 -117.017 -25.8217 0c-44.0095,0 -77.6699,3.50949 -101.16,10.5029 -23.3368,6.99337 -43.1642,18.6746 -59.1746,34.9924 -16.1642,16.1898 -27,36.3501 -32.5076,60.353 -5.48198,23.8236 -8.32543,61.6595 -8.32543,113.149 0,59.8407 -2.66414,98.8293 -7.83872,116.684 -7.17268,26.1547 -17.9829,44.8293 -32.482,55.9982 -14.4991,11.3226 -36.6831,17.6499 -66.6803,19.315z"/>
|
||||
<glyph unicode="}" horiz-adv-x="389" d="M355.996 200.989c-23.8236,-1.33207 -41.6528,-4.81594 -53.667,-10.6566 -12.1679,-5.99431 -22.4915,-15.8311 -31.1499,-29.6642 -8.50475,-13.833 -14.6784,-31.1756 -18.3416,-52.0019 -2.51044,-15.6774 -3.84251,-42.6775 -3.84251,-81.1538 0,-63.1708 -2.81784,-107.334 -8.50475,-132.515 -5.6613,-25.0019 -16.1642,-45.1623 -31.483,-60.3274 -15.3444,-15.1651 -37.8359,-27 -67.3464,-35.8378 -19.8273,-5.84061 -51.1566,-8.83777 -93.8341,-8.83777l-25.8217 0 0 117.017c34.9924,0 57.8169,2.1518 68.6528,6.66035 10.6822,4.32923 18.6746,10.6566 23.6699,19.0076 5.17458,8.32543 7.68502,22.3122 7.83872,42.3188 0.179317,19.8273 1.51139,57.8426 3.84251,113.841 1.66509,33.9934 5.99431,60.9934 13.167,81.4868 7.14707,20.3397 16.6509,37.6822 28.4858,51.8482 12.0142,14.166 27.1793,26.4877 45.6746,37.3236 -24.0029,15.6774 -41.6784,30.9962 -52.668,45.8283 -15.3444,21.518 -25.8473,48.8511 -31.3293,82.1784 -3.50949,22.6708 -5.99431,72.8283 -7.32638,150.319 -0.333017,24.3359 -2.51044,40.6794 -6.68596,48.8511 -3.99621,7.99242 -11.3226,14.3197 -22.0048,18.649 -10.6566,4.50854 -34.3264,6.68596 -71.317,6.68596l0 116.992 25.8217 0c44.0095,0 77.6699,-3.50949 101.186,-10.3235 23.3112,-6.83966 42.9849,-18.5209 58.9953,-34.8387 15.9848,-16.4972 26.8207,-36.6831 32.482,-60.6604 5.68691,-23.8492 8.50475,-61.6851 8.50475,-113.175 0,-59.5076 2.51044,-98.4963 7.32638,-116.659 7.17268,-26.1803 18.0086,-44.8549 32.6869,-56.0238 14.6528,-11.3226 36.9905,-17.6499 66.9877,-19.315l0 -117.017z"/>
|
||||
</font>
|
||||
<style type="text/css">
|
||||
<![CDATA[
|
||||
@font-face { font-family:"Arial";font-variant:normal;font-style:normal;font-weight:bold;src:url("#FontID0") format(svg)}
|
||||
.fil0 {fill:#373435}
|
||||
.fil1 {fill:black}
|
||||
.fnt0 {font-weight:bold;font-size:3.9037px;font-family:'Arial'}
|
||||
]]>
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g transform="matrix(0.576293 0 0 1 -8.27317 4.15816)">
|
||||
<text x="17.5" y="12.5" class="fil0 fnt0">Nr. Comanda:{Article}</text>
|
||||
</g>
|
||||
<g transform="matrix(0.576293 0 0 1 -8.27317 7.72657)">
|
||||
<text x="17.5" y="12.5" class="fil0 fnt0">Nr. Art.:{NrArt}</text>
|
||||
</g>
|
||||
<g transform="matrix(0.576293 0 0 1 -8.33607 11.0472)">
|
||||
<text x="17.5" y="12.5" class="fil0 fnt0">Serial No.:{Serial}</text>
|
||||
</g>
|
||||
<g id="_1503865902032">
|
||||
<path class="fil1" d="M12.82 7.2323c-0.1161,0.0271 -0.6403,0.41 -0.7023,0.417 -0.0438,0.005 -0.4125,-0.272 -0.4735,-0.3166 -0.0598,-0.0436 -0.0888,-0.0806 -0.163,-0.1004 0,0.0747 0.0169,0.2103 0.0281,0.3011 0.0331,0.269 0.0855,0.5861 0.1616,0.848 0.103,0.3544 0.2131,0.6687 0.3663,0.9726 0.2431,0.4823 0.4418,0.7936 0.7893,1.208 0.9583,1.1426 2.579,1.9598 4.0759,1.9598 1.0308,0 1.7035,-0.1145 2.5607,-0.512 0.3018,-0.1399 0.5873,-0.307 0.8502,-0.4886 0.4492,-0.3106 0.7746,-0.6264 1.1172,-1.0338 0.0352,-0.0419 0.0492,-0.052 0.0813,-0.0942 0.6831,-0.895 1.0205,-1.7074 1.1757,-2.8408 0.0122,-0.0889 0.0311,-0.2456 0.0311,-0.3201 -0.1148,-0.0768 -0.2364,-0.1435 -0.3512,-0.2195 -0.4402,-0.2912 -0.3377,-0.2606 -0.7083,0.016 -0.4465,0.3331 -0.1917,0.0604 -0.3623,0.801 -0.0383,0.1665 -0.0787,0.3029 -0.1284,0.4642 -0.2415,0.783 -0.8476,1.5453 -1.4754,2.0363 -0.1897,0.1484 -0.5097,0.3427 -0.7199,0.4433 -1.4392,0.6888 -3.2727,0.5256 -4.5139,-0.4835 -0.1901,-0.1546 -0.4507,-0.3749 -0.5984,-0.5649 -0.2922,-0.3762 -0.4778,-0.591 -0.6835,-1.0723 -0.1761,-0.412 -0.3573,-0.9691 -0.3573,-1.4206z"/>
|
||||
<path class="fil1" d="M11.4812 6.5739c0.1103,0.0738 0.2091,0.1467 0.3248,0.2238 0.4133,0.2755 0.2641,0.2761 0.6717,0.0045 0.1215,-0.0811 0.227,-0.1511 0.3423,-0.2283 0,-0.7199 0.395,-1.6532 0.8432,-2.2515 0.2017,-0.2693 0.6154,-0.6932 0.9082,-0.8915 0.7337,-0.4969 1.3743,-0.7636 2.287,-0.8077 0.3218,-0.0155 0.0567,-0.0336 0.4622,-0.0011 0.2873,0.023 0.3574,0.0038 0.706,0.0841 0.5154,0.1187 1.0246,0.3291 1.4484,0.6147 0.8452,0.5696 1.4617,1.4005 1.7486,2.3776 0.063,0.2147 0.1562,0.6133 0.1562,0.8754 0.1055,-0.0282 0.5565,-0.4104 0.6145,-0.417 0.0786,0.021 0.2734,0.1575 0.3607,0.2099 0.0787,0.0473 0.2939,0.1908 0.3636,0.2071l-0.0687 -0.5898c-0.1423,-0.8307 -0.4834,-1.7021 -0.9879,-2.3701 -0.2122,-0.2809 -0.5138,-0.6564 -0.7903,-0.8778 -0.2016,-0.1613 -0.3013,-0.2735 -0.5584,-0.4512 -0.8199,-0.5666 -1.9324,-1.0006 -3.0378,-1.0006 -1.0533,0 -1.6632,0.1218 -2.5238,0.5051 -1.6549,0.7371 -2.8948,2.3661 -3.1985,4.176 -0.0172,0.1027 -0.0262,0.1807 -0.0409,0.2883 -0.0122,0.0889 -0.0311,0.2456 -0.0311,0.3201z"/>
|
||||
<path class="fil1" d="M16.4195 7.4518l-1.4213 -1.41 -1.0534 1.0643 2.4473 2.4582 3.8738 -3.8629 -1.0537 -1.0423 -0.1758 0.164c-0.0315,0.0363 -0.0538,0.0557 -0.0893,0.0863l-0.6063 0.6008c-0.003,0.0034 -0.0071,0.0084 -0.0101,0.0119l-0.1755 0.1757c-0.0032,0.0032 -0.0077,0.0078 -0.0109,0.011l-0.2499 0.2549c-0.0507,0.0484 -0.0461,0.0309 -0.092,0.0836 -0.1863,0.2139 -1.3182,1.3079 -1.3829,1.4045z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
83
configure_printer_paper_size.ps1
Normal file
83
configure_printer_paper_size.ps1
Normal file
@@ -0,0 +1,83 @@
|
||||
# Configure Thermal Printer for 35mm x 25mm Labels
|
||||
# Run as Administrator if needed
|
||||
|
||||
Write-Host "====================================" -ForegroundColor Cyan
|
||||
Write-Host "Label Printer Paper Size Setup" -ForegroundColor Cyan
|
||||
Write-Host "Target: 35mm x 25mm (Landscape)" -ForegroundColor Cyan
|
||||
Write-Host "====================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Get list of printers
|
||||
$printers = Get-Printer | Select-Object Name, DriverName, PortName
|
||||
Write-Host "Available Printers:" -ForegroundColor Yellow
|
||||
$printers | Format-Table -AutoSize
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "MANUAL CONFIGURATION STEPS:" -ForegroundColor Green
|
||||
Write-Host "===========================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "1. Open Control Panel > Devices and Printers" -ForegroundColor White
|
||||
Write-Host "2. Right-click your thermal printer (e.g., Citizen CTS-310 or Zebra ZD420)" -ForegroundColor White
|
||||
Write-Host "3. Select 'Printing Preferences'" -ForegroundColor White
|
||||
Write-Host "4. Look for 'Paper Size' or 'Media' settings:" -ForegroundColor White
|
||||
Write-Host " - Size: Custom or 35mm x 25mm" -ForegroundColor Cyan
|
||||
Write-Host " - Width: 35mm (1.38 inches)" -ForegroundColor Cyan
|
||||
Write-Host " - Height: 25mm (0.98 inches)" -ForegroundColor Cyan
|
||||
Write-Host " - Orientation: Landscape" -ForegroundColor Cyan
|
||||
Write-Host " - Media Type: LABELS (not Continuous)" -ForegroundColor Cyan
|
||||
Write-Host "5. Click 'Apply' and 'OK'" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "IMPORTANT FOR ZEBRA PRINTERS:" -ForegroundColor Red
|
||||
Write-Host "- Must set Media Type = 'Labels' (enables gap sensor)" -ForegroundColor Yellow
|
||||
Write-Host "- If set to 'Continuous', printer will print on entire roll" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host "CRITICAL PRINTER SETTINGS:" -ForegroundColor Magenta
|
||||
Write-Host "- Darkness: 10-15 (thermal printers)" -ForegroundColor White
|
||||
Write-Host "- Speed: Medium" -ForegroundColor White
|
||||
Write-Host "- Print Mode: Thermal Transfer or Direct Thermal" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
# Show printer properties access
|
||||
Write-Host "To open printer properties directly, run:" -ForegroundColor Green
|
||||
Write-Host 'control printers' -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Check if running as admin
|
||||
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
if ($isAdmin) {
|
||||
Write-Host "✓ Running as Administrator" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "⚠ Not running as Administrator (some settings may require elevation)" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "For Citizen CTS-310 printers:" -ForegroundColor Cyan
|
||||
Write-Host " 1. Open Devices and Printers" -ForegroundColor White
|
||||
Write-Host " 2. Right-click 'Citizen CTS-310II' > Printer Properties" -ForegroundColor White
|
||||
Write-Host " 3. Device Settings tab > Form to Tray Assignment" -ForegroundColor White
|
||||
Write-Host " 4. Click 'Create Form' button" -ForegroundColor White
|
||||
Write-Host " 5. Form name: Label35x25" -ForegroundColor White
|
||||
Write-Host " 6. Width: 35mm, Height: 25mm" -ForegroundColor White
|
||||
Write-Host " 7. Save and select this form in Printing Preferences" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "For Zebra ZD420/ZD421 printers:" -ForegroundColor Cyan
|
||||
Write-Host " 1. Open Zebra Setup Utility (ZSU)" -ForegroundColor White
|
||||
Write-Host " 2. Select your printer" -ForegroundColor White
|
||||
Write-Host " 3. Click 'Printer Configuration'" -ForegroundColor White
|
||||
Write-Host " 4. Media section:" -ForegroundColor White
|
||||
Write-Host " - Media Type: Label Stock" -ForegroundColor Cyan
|
||||
Write-Host " - Label Width: 35mm" -ForegroundColor Cyan
|
||||
Write-Host " - Label Height: 25mm" -ForegroundColor Cyan
|
||||
Write-Host " 5. Print section:" -ForegroundColor White
|
||||
Write-Host " - Darkness: 10-15" -ForegroundColor Cyan
|
||||
Write-Host " - Print Speed: 4 ips (medium)" -ForegroundColor Cyan
|
||||
Write-Host " 6. Click 'Send to Printer'" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "After configuration, test print with:" -ForegroundColor Green
|
||||
Write-Host " python label_printer_gui.py" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host "Press any key to open Printer settings..." -ForegroundColor Yellow
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
control printers
|
||||
@@ -28,10 +28,17 @@ from print_label import print_label_standalone, get_available_printers
|
||||
from kivy.clock import Clock
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
import pystray
|
||||
from pystray import MenuItem as item
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Optional system tray support
|
||||
try:
|
||||
import pystray
|
||||
from pystray import MenuItem as item
|
||||
PYSTRAY_AVAILABLE = True
|
||||
except ImportError:
|
||||
PYSTRAY_AVAILABLE = False
|
||||
print("Warning: pystray not available. System tray functionality disabled.")
|
||||
|
||||
# Set window size - portrait/phone dimensions (375x667 like iPhone)
|
||||
# Adjusted to be slightly wider for touch-friendly UI
|
||||
Window.size = (420, 700)
|
||||
@@ -63,6 +70,8 @@ class LabelPrinterApp(App):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
# Initialize conf folder with default templates
|
||||
self.initialize_conf_folder()
|
||||
# Build printer display names and mapping to full names
|
||||
full_printers = get_available_printers()
|
||||
self.printer_display_map = {} # display_name -> full_name
|
||||
@@ -109,6 +118,107 @@ class LabelPrinterApp(App):
|
||||
"""Resolve display name back to full printer name for printing."""
|
||||
return self.printer_display_map.get(display_name, display_name)
|
||||
|
||||
def initialize_conf_folder(self):
|
||||
"""
|
||||
Initialize conf folder with default templates and configuration.
|
||||
Creates folder and files if they don't exist.
|
||||
"""
|
||||
conf_dir = 'conf'
|
||||
|
||||
# Create conf folder if it doesn't exist
|
||||
if not os.path.exists(conf_dir):
|
||||
os.makedirs(conf_dir, exist_ok=True)
|
||||
print(f"Created conf folder: {conf_dir}")
|
||||
|
||||
# Define default SVG template (minimal 35mm x 25mm with placeholders)
|
||||
default_svg_template = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35mm" height="25mm" viewBox="0 0 35 25">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
.text { font-family: Arial; font-weight: bold; font-size: 3.5px; fill: #000000; }
|
||||
.checkmark { fill: #008000; }
|
||||
</style>
|
||||
</defs>
|
||||
<g id="content">
|
||||
<text x="2" y="7" class="text">Nr. Comanda: {Article}</text>
|
||||
<text x="2" y="12" class="text">Nr. Art.: {NrArt}</text>
|
||||
<text x="2" y="17" class="text">Serial No.: {Serial}</text>
|
||||
<circle cx="31" cy="7" r="2.5" class="checkmark"/>
|
||||
<path d="M30,7 L30.8,7.8 L32,6" stroke="white" stroke-width="0.5" fill="none"/>
|
||||
</g>
|
||||
</svg>'''
|
||||
|
||||
# OK template (green checkmark)
|
||||
ok_svg_template = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35mm" height="25mm" viewBox="0 0 35 25">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
.text { font-family: Arial; font-weight: bold; font-size: 3.5px; fill: #000000; }
|
||||
.checkmark { fill: #008000; }
|
||||
.ok-text { font-family: Arial; font-weight: bold; font-size: 4px; fill: #008000; }
|
||||
</style>
|
||||
</defs>
|
||||
<g id="content">
|
||||
<text x="2" y="7" class="text">Nr. Comanda: {Article}</text>
|
||||
<text x="2" y="12" class="text">Nr. Art.: {NrArt}</text>
|
||||
<text x="2" y="17" class="text">Serial No.: {Serial}</text>
|
||||
<text x="29" y="5" class="ok-text">OK</text>
|
||||
<circle cx="31" cy="12" r="2.5" class="checkmark"/>
|
||||
<path d="M30,12 L30.8,12.8 L32,11" stroke="white" stroke-width="0.5" fill="none"/>
|
||||
</g>
|
||||
</svg>'''
|
||||
|
||||
# NOK template (red text and checkmark)
|
||||
nok_svg_template = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35mm" height="25mm" viewBox="0 0 35 25">
|
||||
<defs>
|
||||
<style type="text/css">
|
||||
.text { font-family: Arial; font-weight: bold; font-size: 3.5px; fill: #CC0000; }
|
||||
.checkmark { fill: #CC0000; }
|
||||
.nok-text { font-family: Arial; font-weight: bold; font-size: 4px; fill: #CC0000; }
|
||||
</style>
|
||||
</defs>
|
||||
<g id="content">
|
||||
<text x="2" y="7" class="text">Nr. Comanda: {Article}</text>
|
||||
<text x="2" y="12" class="text">Nr. Art.: {NrArt}</text>
|
||||
<text x="2" y="17" class="text">Serial No.: {Serial}</text>
|
||||
<text x="27" y="5" class="nok-text">NOK</text>
|
||||
<circle cx="31" cy="12" r="2.5" class="checkmark"/>
|
||||
<path d="M30,12 L30.8,12.8 L32,11" stroke="white" stroke-width="0.5" fill="none"/>
|
||||
</g>
|
||||
</svg>'''
|
||||
|
||||
# Create SVG template files if they don't exist
|
||||
templates = {
|
||||
'label_template.svg': default_svg_template,
|
||||
'label_template_ok.svg': ok_svg_template,
|
||||
'label_template_nok.svg': nok_svg_template,
|
||||
}
|
||||
|
||||
for filename, content in templates.items():
|
||||
file_path = os.path.join(conf_dir, filename)
|
||||
if not os.path.exists(file_path):
|
||||
try:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f"Created template: {file_path}")
|
||||
except Exception as e:
|
||||
print(f"Failed to create {file_path}: {e}")
|
||||
|
||||
# Create default app.conf if it doesn't exist
|
||||
config_path = os.path.join(conf_dir, 'app.conf')
|
||||
if not os.path.exists(config_path):
|
||||
default_config = '''[Settings]
|
||||
file_path = C:\\Users\\Public\\Documents\\check.txt
|
||||
printer = PDF
|
||||
'''
|
||||
try:
|
||||
with open(config_path, 'w', encoding='utf-8') as f:
|
||||
f.write(default_config)
|
||||
print(f"Created config: {config_path}")
|
||||
except Exception as e:
|
||||
print(f"Failed to create {config_path}: {e}")
|
||||
|
||||
def cleanup_old_pdfs(self, days=5):
|
||||
"""
|
||||
Delete PDF files older than specified days from pdf_backup folder.
|
||||
@@ -469,6 +579,10 @@ class LabelPrinterApp(App):
|
||||
"""
|
||||
Minimize the application to system tray.
|
||||
"""
|
||||
if not PYSTRAY_AVAILABLE:
|
||||
print("System tray not available - window will minimize normally")
|
||||
return
|
||||
|
||||
if self.is_minimized:
|
||||
return
|
||||
|
||||
@@ -652,9 +766,13 @@ class LabelPrinterApp(App):
|
||||
print(f"Error clearing file: {e}")
|
||||
|
||||
def read_file_variables(self):
|
||||
"""Read variables from monitored file"""
|
||||
"""Read variables from monitored file
|
||||
Expected format: article;nr_art;serial;template_type;count
|
||||
template_type: 0=OK, 1=NOK
|
||||
count: number of labels to print (default=1)
|
||||
"""
|
||||
if not self.monitored_file or not os.path.exists(self.monitored_file):
|
||||
return None, None, None
|
||||
return None, None, None, 0, 1
|
||||
|
||||
try:
|
||||
with open(self.monitored_file, 'r', encoding='utf-8') as f:
|
||||
@@ -662,14 +780,16 @@ class LabelPrinterApp(App):
|
||||
|
||||
# Skip if file is empty or only contains "-" (cleared marker)
|
||||
if not content or content == '-':
|
||||
return None, None, None
|
||||
return None, None, None, 0, 1
|
||||
|
||||
# Parse file content - expecting format: article;nr_art;serial
|
||||
# Parse file content - expecting format: article;nr_art;serial;template_type;count
|
||||
# or key=value pairs on separate lines
|
||||
lines = content.split('\n')
|
||||
article = ""
|
||||
nr_art = ""
|
||||
serial = ""
|
||||
template_type = 0 # Default to OK template
|
||||
count = 1 # Default to 1 label
|
||||
|
||||
# Try semicolon-separated format first
|
||||
if ';' in content:
|
||||
@@ -680,6 +800,20 @@ class LabelPrinterApp(App):
|
||||
nr_art = parts[1].strip()
|
||||
if len(parts) >= 3:
|
||||
serial = parts[2].strip()
|
||||
if len(parts) >= 4:
|
||||
try:
|
||||
template_type = int(parts[3].strip())
|
||||
except ValueError:
|
||||
template_type = 0
|
||||
if len(parts) >= 5:
|
||||
try:
|
||||
count = int(parts[4].strip())
|
||||
if count < 1:
|
||||
count = 1
|
||||
if count > 100: # Safety limit
|
||||
count = 100
|
||||
except ValueError:
|
||||
count = 1
|
||||
else:
|
||||
# Try key=value format
|
||||
for line in lines:
|
||||
@@ -694,16 +828,30 @@ class LabelPrinterApp(App):
|
||||
nr_art = value
|
||||
elif key in ['serial', 'serial_no', 'serial-no', 'serialno']:
|
||||
serial = value
|
||||
elif key in ['template', 'template_type', 'type']:
|
||||
try:
|
||||
template_type = int(value)
|
||||
except ValueError:
|
||||
template_type = 0
|
||||
elif key in ['count', 'quantity', 'copies']:
|
||||
try:
|
||||
count = int(value)
|
||||
if count < 1:
|
||||
count = 1
|
||||
if count > 100:
|
||||
count = 100
|
||||
except ValueError:
|
||||
count = 1
|
||||
|
||||
return article, nr_art, serial
|
||||
return article, nr_art, serial, template_type, count
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}")
|
||||
return None, None, None
|
||||
|
||||
def print_label(self, instance):
|
||||
"""Handle print button press - read from file and print"""
|
||||
# Read variables from file
|
||||
article, nr_art, serial = self.read_file_variables()
|
||||
# Read variables from file including template type and count
|
||||
article, nr_art, serial, template_type, count = self.read_file_variables()
|
||||
|
||||
# Resolve display name to full printer name
|
||||
printer = self._get_full_printer_name(self.printer_spinner.text)
|
||||
@@ -713,10 +861,23 @@ class LabelPrinterApp(App):
|
||||
self.show_popup("Error", "No data in file or file not set", auto_dismiss_after=3)
|
||||
return
|
||||
|
||||
# Select template based on template_type
|
||||
if template_type == 1:
|
||||
template_path = os.path.join('conf', 'label_template_nok.svg')
|
||||
template_name = "NOK"
|
||||
else:
|
||||
template_path = os.path.join('conf', 'label_template_ok.svg')
|
||||
template_name = "OK"
|
||||
|
||||
# Verify template exists, fallback to default if not
|
||||
if not os.path.exists(template_path):
|
||||
template_path = os.path.join('conf', 'label_template.svg')
|
||||
template_name = "DEFAULT"
|
||||
|
||||
# Create combined label text using semicolon separator
|
||||
label_text = f"{article};{nr_art};{serial}"
|
||||
|
||||
# Show loading popup
|
||||
# Show loading popup with count info
|
||||
popup = Popup(
|
||||
title='Printing',
|
||||
content=BoxLayout(
|
||||
@@ -727,15 +888,32 @@ class LabelPrinterApp(App):
|
||||
size_hint=(0.8, 0.3)
|
||||
)
|
||||
|
||||
popup.content.add_widget(Label(text='Processing label...\nPlease wait'))
|
||||
popup.content.add_widget(Label(text=f'Processing {count} label(s)...\nTemplate: {template_name}\nPlease wait'))
|
||||
popup.open()
|
||||
|
||||
# Print in background thread (using PDF by default)
|
||||
def print_thread():
|
||||
pdf_filename = None
|
||||
success = False
|
||||
all_success = True
|
||||
try:
|
||||
success = print_label_standalone(label_text, printer, preview=0, use_pdf=True)
|
||||
# Print multiple copies if count > 1
|
||||
for i in range(count):
|
||||
if count > 1:
|
||||
Clock.schedule_once(lambda dt, idx=i: popup.content.children[0].text.replace(
|
||||
f'Processing {count} label(s)...',
|
||||
f'Printing {idx+1} of {count}...'
|
||||
), 0)
|
||||
|
||||
success = print_label_standalone(label_text, printer, preview=0, use_pdf=True, svg_template=template_path)
|
||||
|
||||
if not success:
|
||||
all_success = False
|
||||
break
|
||||
|
||||
# Small delay between prints for multiple copies
|
||||
if i < count - 1:
|
||||
time.sleep(0.5)
|
||||
|
||||
# Get the PDF filename that was created
|
||||
# Files are saved to pdf_backup/ with timestamp
|
||||
@@ -744,7 +922,7 @@ class LabelPrinterApp(App):
|
||||
# Get the most recently created PDF file
|
||||
pdf_filename = max(pdf_files, key=os.path.getctime)
|
||||
|
||||
if success:
|
||||
if all_success:
|
||||
# Log the successful print action
|
||||
self.log_print_action(article, nr_art, serial, printer, pdf_filename or "unknown", True)
|
||||
|
||||
@@ -753,7 +931,7 @@ class LabelPrinterApp(App):
|
||||
|
||||
# Use Clock.schedule_once to update UI from main thread
|
||||
Clock.schedule_once(lambda dt: popup.dismiss(), 0)
|
||||
Clock.schedule_once(lambda dt: self.show_popup("Success", "Label printed successfully!", auto_dismiss_after=3), 0.1)
|
||||
Clock.schedule_once(lambda dt: self.show_popup("Success", f"{count} label(s) printed successfully!", auto_dismiss_after=3), 0.1)
|
||||
else:
|
||||
# Log the failed print action
|
||||
self.log_print_action(article, nr_art, serial, printer, pdf_filename or "unknown", False)
|
||||
|
||||
288
print_label.py
288
print_label.py
@@ -3,6 +3,7 @@ import barcode
|
||||
from barcode.writer import ImageWriter
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import platform
|
||||
import subprocess
|
||||
@@ -173,7 +174,14 @@ def create_label_image(text):
|
||||
# Resize barcode to fit in row width
|
||||
barcode_width = label_width - left_margin - 10
|
||||
barcode_height = row_height - 25
|
||||
barcode_resized = barcode_img.resize((barcode_width, barcode_height), Image.LANCZOS)
|
||||
# Use high-quality resampling for crisp barcodes
|
||||
try:
|
||||
# Try newer Pillow API first
|
||||
from PIL.Image import Resampling
|
||||
barcode_resized = barcode_img.resize((barcode_width, barcode_height), Resampling.LANCZOS)
|
||||
except (ImportError, AttributeError):
|
||||
# Fallback for older Pillow versions
|
||||
barcode_resized = barcode_img.resize((barcode_width, barcode_height), Image.LANCZOS)
|
||||
label_img.paste(barcode_resized, (left_margin, row_y + 20))
|
||||
else:
|
||||
# Fallback: show value as text
|
||||
@@ -194,13 +202,14 @@ def create_label_image(text):
|
||||
return label_img
|
||||
|
||||
|
||||
def create_label_pdf(text):
|
||||
def create_label_pdf(text, svg_template=None):
|
||||
"""
|
||||
Create a high-quality PDF label with 3 rows: label + barcode for each field.
|
||||
PDFs are saved to the pdf_backup folder.
|
||||
|
||||
Args:
|
||||
text (str): Combined text in format "article;nr_art;serial" or single value
|
||||
svg_template (str): Path to specific SVG template to use (optional)
|
||||
|
||||
Returns:
|
||||
str: Path to the generated PDF file
|
||||
@@ -221,11 +230,17 @@ def create_label_pdf(text):
|
||||
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
pdf_filename = os.path.join(pdf_backup_dir, f"final_label_{timestamp}.pdf")
|
||||
|
||||
# Check for default SVG template
|
||||
svg_template = None
|
||||
default_svg = os.path.join('conf', 'label_template.svg')
|
||||
if os.path.exists(default_svg):
|
||||
svg_template = default_svg
|
||||
# Use SVG template for customizable layout
|
||||
if svg_template is None or not os.path.exists(svg_template):
|
||||
# Try default templates
|
||||
default_svg = os.path.join('conf', 'label_template.svg')
|
||||
if os.path.exists(default_svg):
|
||||
svg_template = default_svg
|
||||
print(f"Using SVG template: {default_svg}")
|
||||
else:
|
||||
print("SVG template not found, using fallback PDF generation")
|
||||
else:
|
||||
print(f"Using SVG template: {svg_template}")
|
||||
|
||||
# Check for default image path
|
||||
image_path = os.path.join('conf', 'accepted.png')
|
||||
@@ -233,9 +248,94 @@ def create_label_pdf(text):
|
||||
return generator.create_label_pdf(article, nr_art, serial, pdf_filename, image_path, svg_template)
|
||||
|
||||
|
||||
def configure_printer_quality(printer_name, width_mm=35, height_mm=25):
|
||||
"""
|
||||
Configure printer for high quality label printing (Windows only).
|
||||
Sets paper size, orientation, and QUALITY settings.
|
||||
|
||||
Args:
|
||||
printer_name (str): Name of the printer
|
||||
width_mm (int): Label width in millimeters (default 35)
|
||||
height_mm (int): Label height in millimeters (default 25)
|
||||
|
||||
Returns:
|
||||
bool: True if successful
|
||||
"""
|
||||
if SYSTEM != "Windows" or not WIN32_AVAILABLE:
|
||||
return False
|
||||
|
||||
try:
|
||||
import win32print
|
||||
import pywintypes
|
||||
|
||||
hprinter = win32print.OpenPrinter(printer_name)
|
||||
|
||||
try:
|
||||
# Get current printer properties
|
||||
props = win32print.GetPrinter(hprinter, 2)
|
||||
devmode = props.get("pDevMode")
|
||||
|
||||
if devmode is None:
|
||||
print("Could not get printer DEVMODE")
|
||||
return False
|
||||
|
||||
# CRITICAL: Set print quality to HIGHEST
|
||||
# This prevents dotted/pixelated text
|
||||
try:
|
||||
devmode.PrintQuality = 600 # 600 DPI (high quality)
|
||||
except:
|
||||
try:
|
||||
devmode.PrintQuality = 4 # DMRES_HIGH
|
||||
except:
|
||||
pass
|
||||
|
||||
# Set custom paper size
|
||||
try:
|
||||
devmode.PaperSize = 256 # DMPAPER_USER (custom size)
|
||||
devmode.PaperLength = height_mm * 10 # Height in 0.1mm units
|
||||
devmode.PaperWidth = width_mm * 10 # Width in 0.1mm units
|
||||
except:
|
||||
pass
|
||||
|
||||
# Set orientation to landscape
|
||||
try:
|
||||
devmode.Orientation = 2 # Landscape
|
||||
except:
|
||||
pass
|
||||
|
||||
# Set additional quality settings
|
||||
try:
|
||||
devmode.Color = 1 # Monochrome for labels
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
devmode.TTOption = 2 # DMTT_BITMAP - print TrueType as graphics (sharper)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Apply settings
|
||||
try:
|
||||
props["pDevMode"] = devmode
|
||||
win32print.SetPrinter(hprinter, 2, props, 0)
|
||||
print(f"Printer configured: {width_mm}x{height_mm}mm @ HIGH QUALITY")
|
||||
return True
|
||||
except Exception as set_err:
|
||||
print(f"Could not apply printer settings: {set_err}")
|
||||
return False
|
||||
|
||||
finally:
|
||||
win32print.ClosePrinter(hprinter)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Could not configure printer quality: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def print_to_printer(printer_name, file_path):
|
||||
"""
|
||||
Print file to printer (cross-platform).
|
||||
Uses SumatraPDF for silent printing on Windows.
|
||||
|
||||
Args:
|
||||
printer_name (str): Name of printer or "PDF" for PDF output
|
||||
@@ -258,66 +358,145 @@ def print_to_printer(printer_name, file_path):
|
||||
return True
|
||||
|
||||
elif SYSTEM == "Windows":
|
||||
# Windows: Print PDF using various methods
|
||||
# Windows: Print PDF silently without any viewer opening
|
||||
try:
|
||||
if WIN32_AVAILABLE:
|
||||
import win32print
|
||||
import win32api
|
||||
|
||||
if file_path.endswith('.pdf'):
|
||||
# Method 1: Try SumatraPDF for best silent printing
|
||||
sumatra_paths = [
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf', 'SumatraPDF.exe'),
|
||||
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf', 'SumatraPDF-portable.exe'),
|
||||
# Try silent printing methods (no viewer opens)
|
||||
import os
|
||||
import winreg
|
||||
|
||||
printed = False
|
||||
|
||||
# Method 1: SumatraPDF (bundled inside exe or external)
|
||||
sumatra_paths = []
|
||||
|
||||
# Get the directory where this script/exe is running
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Running as compiled executable
|
||||
# PyInstaller extracts bundled files to sys._MEIPASS temp folder
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
# Check bundled version first (inside the exe)
|
||||
bundled_sumatra = os.path.join(sys._MEIPASS, 'SumatraPDF.exe')
|
||||
sumatra_paths.append(bundled_sumatra)
|
||||
|
||||
# Also check app directory for external version
|
||||
app_dir = os.path.dirname(sys.executable)
|
||||
sumatra_paths.append(os.path.join(app_dir, "SumatraPDF", "SumatraPDF.exe"))
|
||||
sumatra_paths.append(os.path.join(app_dir, "SumatraPDF.exe"))
|
||||
else:
|
||||
# Running as script - check local folders
|
||||
app_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
sumatra_paths.append(os.path.join(app_dir, "SumatraPDF", "SumatraPDF.exe"))
|
||||
sumatra_paths.append(os.path.join(app_dir, "SumatraPDF.exe"))
|
||||
sumatra_paths.append(os.path.join(app_dir, "conf", "SumatraPDF.exe"))
|
||||
|
||||
# Then check system installations
|
||||
sumatra_paths.extend([
|
||||
r"C:\Program Files\SumatraPDF\SumatraPDF.exe",
|
||||
r"C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe",
|
||||
os.path.expandvars(r"%LOCALAPPDATA%\SumatraPDF\SumatraPDF.exe"),
|
||||
]
|
||||
])
|
||||
|
||||
sumatra_found = False
|
||||
for sumatra_path in sumatra_paths:
|
||||
if os.path.exists(sumatra_path):
|
||||
sumatra_found = True
|
||||
try:
|
||||
# Use SumatraPDF silent printing with high quality settings
|
||||
# noscale = print at actual size without scaling
|
||||
# landscape = force landscape orientation for 35x25mm labels
|
||||
# Note: SumatraPDF uses printer driver's quality settings
|
||||
# Use noscale with paper size specification for thermal printers
|
||||
# Format: "noscale,paper=<size>" where paper size matches PDF (35mm x 25mm)
|
||||
# SumatraPDF will use the PDF's page size when noscale is used
|
||||
subprocess.run([
|
||||
sumatra_path,
|
||||
'-print-to', printer_name,
|
||||
'-silent',
|
||||
'-print-settings', 'noscale,landscape',
|
||||
file_path
|
||||
], check=True, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
"-print-to",
|
||||
printer_name,
|
||||
file_path,
|
||||
"-print-settings",
|
||||
"noscale", # Preserve exact PDF page dimensions
|
||||
"-silent",
|
||||
"-exit-when-done"
|
||||
], check=False, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
print(f"Label sent to printer via SumatraPDF: {printer_name}")
|
||||
return True
|
||||
except Exception as sumatra_err:
|
||||
print(f"SumatraPDF print failed: {sumatra_err}")
|
||||
print(f"Note: Printer '{printer_name}' should be configured for 35mm x 25mm labels")
|
||||
printed = True
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"SumatraPDF error: {e}")
|
||||
|
||||
# Method 2: Use ShellExecute with printto (requires default PDF viewer)
|
||||
if not sumatra_found or WIN32_AVAILABLE:
|
||||
try:
|
||||
import win32api
|
||||
win32api.ShellExecute(
|
||||
0, "printto", file_path,
|
||||
f'"{printer_name}"', ".", 0
|
||||
)
|
||||
print(f"Label sent to printer via ShellExecute: {printer_name}")
|
||||
return True
|
||||
except Exception as shell_err:
|
||||
print(f"ShellExecute print failed: {shell_err}")
|
||||
# Method 3: Open PDF with default viewer (last resort)
|
||||
# Method 2: Adobe Reader silent printing
|
||||
if not printed:
|
||||
adobe_path = None
|
||||
for key_path in [
|
||||
r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe",
|
||||
r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Acrobat.exe"
|
||||
]:
|
||||
try:
|
||||
os.startfile(file_path, "print")
|
||||
print(f"Opened PDF for printing: {file_path}")
|
||||
print("Please close the PDF viewer after printing.")
|
||||
return True
|
||||
except Exception as startfile_err:
|
||||
print(f"Could not open PDF: {startfile_err}")
|
||||
print("PDF saved as backup only")
|
||||
return True
|
||||
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path)
|
||||
adobe_path, _ = winreg.QueryValueEx(key, "")
|
||||
winreg.CloseKey(key)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if adobe_path and os.path.exists(adobe_path):
|
||||
try:
|
||||
subprocess.run([
|
||||
adobe_path,
|
||||
"/t", # Print and close
|
||||
file_path,
|
||||
printer_name
|
||||
], check=False, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
print(f"Label sent to printer via Adobe Reader: {printer_name}")
|
||||
printed = True
|
||||
except:
|
||||
pass
|
||||
|
||||
# Method 3: GhostScript (if installed)
|
||||
if not printed:
|
||||
gs_paths = [
|
||||
r"C:\Program Files\gs\gs10.02.1\bin\gswin64c.exe",
|
||||
r"C:\Program Files (x86)\gs\gs10.02.1\bin\gswin32c.exe",
|
||||
]
|
||||
# Try to find gswin in PATH
|
||||
try:
|
||||
gs_result = subprocess.run(['where', 'gswin64c'],
|
||||
capture_output=True, text=True, check=False)
|
||||
if gs_result.returncode == 0:
|
||||
gs_paths.insert(0, gs_result.stdout.strip().split('\n')[0])
|
||||
except:
|
||||
pass
|
||||
|
||||
for gs_path in gs_paths:
|
||||
if os.path.exists(gs_path):
|
||||
try:
|
||||
subprocess.run([
|
||||
gs_path,
|
||||
"-dNOPAUSE", "-dBATCH", "-dQUIET",
|
||||
f"-sDEVICE=mswinpr2",
|
||||
f"-sOutputFile=%printer%{printer_name}",
|
||||
file_path
|
||||
], check=False, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
print(f"Label sent to printer via GhostScript: {printer_name}")
|
||||
printed = True
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if not printed:
|
||||
# Fallback: Let user know and save PDF
|
||||
print("=" * 60)
|
||||
print("NOTICE: Silent PDF printing requires SumatraPDF")
|
||||
print("SumatraPDF not found (should be bundled inside the app)")
|
||||
print("If you built the app yourself, ensure SumatraPDF.exe is downloaded first.")
|
||||
print("=" * 60)
|
||||
print(f"PDF saved to: {file_path}")
|
||||
print("The PDF can be printed manually.")
|
||||
|
||||
return True
|
||||
else:
|
||||
# Non-PDF files: print silently with notepad
|
||||
subprocess.run(['notepad', '/p', file_path],
|
||||
check=False,
|
||||
# Non-PDF files
|
||||
subprocess.run(['notepad', '/p', file_path],
|
||||
check=False,
|
||||
creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
print(f"Label sent to printer: {printer_name}")
|
||||
return True
|
||||
@@ -343,7 +522,7 @@ def print_to_printer(printer_name, file_path):
|
||||
return True
|
||||
|
||||
|
||||
def print_label_standalone(value, printer, preview=0, use_pdf=True):
|
||||
def print_label_standalone(value, printer, preview=0, use_pdf=True, svg_template=None):
|
||||
"""
|
||||
Print a label with the specified text on the specified printer.
|
||||
Always generates a PDF backup in pdf_backup and prints that PDF.
|
||||
@@ -353,6 +532,7 @@ def print_label_standalone(value, printer, preview=0, use_pdf=True):
|
||||
printer (str): The name of the printer to use
|
||||
preview (int): 0 = no preview, 1-3 = 3s preview, >3 = 5s preview
|
||||
use_pdf (bool): False to also generate a PNG if PDF generation fails
|
||||
svg_template (str): Path to specific SVG template to use (optional)
|
||||
|
||||
Returns:
|
||||
bool: True if printing was successful, False otherwise
|
||||
@@ -370,7 +550,7 @@ def print_label_standalone(value, printer, preview=0, use_pdf=True):
|
||||
|
||||
# Always generate a PDF backup and print that PDF for verification
|
||||
try:
|
||||
pdf_file = create_label_pdf(value)
|
||||
pdf_file = create_label_pdf(value, svg_template)
|
||||
if pdf_file and os.path.exists(pdf_file):
|
||||
print(f"PDF label created: {pdf_file}")
|
||||
print(f"PDF backup saved to: {pdf_file}")
|
||||
|
||||
@@ -38,17 +38,19 @@ except (ImportError, OSError) as e:
|
||||
class PDFLabelGenerator:
|
||||
"""Generate high-quality PDF labels with image and text"""
|
||||
|
||||
def __init__(self, label_width=3.5, label_height=2.5, dpi=600):
|
||||
def __init__(self, label_width=3.5, label_height=2.5, dpi=1200):
|
||||
"""
|
||||
Initialize PDF label generator.
|
||||
|
||||
Args:
|
||||
label_width (float): Width in cm (default 3.5 cm = 35mm)
|
||||
label_height (float): Height in cm (default 2.5 cm = 25mm)
|
||||
dpi (int): DPI for image rendering (default 600 for high quality print)
|
||||
dpi (int): DPI for image rendering (default 1200 for high quality thermal printer)
|
||||
"""
|
||||
self.label_width = label_width * cm
|
||||
self.label_height = label_height * cm
|
||||
# Force landscape: ensure width > height
|
||||
self.page_size = landscape((self.label_height, self.label_width)) if self.label_width > self.label_height else (self.label_width, self.label_height)
|
||||
self.dpi = dpi
|
||||
self.margin = 1 * mm # Minimal margin
|
||||
|
||||
@@ -68,9 +70,11 @@ class PDFLabelGenerator:
|
||||
|
||||
try:
|
||||
img = Image.open(image_path)
|
||||
# Convert to RGB if needed
|
||||
if img.mode not in ['RGB', 'L']:
|
||||
# Convert to RGB for best quality (don't use grayscale)
|
||||
if img.mode != 'RGB':
|
||||
img = img.convert('RGB')
|
||||
# Set DPI information for high-quality output
|
||||
img.info['dpi'] = (self.dpi, self.dpi)
|
||||
return img
|
||||
except Exception as e:
|
||||
print(f"Image loading error: {e}")
|
||||
@@ -130,42 +134,25 @@ class PDFLabelGenerator:
|
||||
else:
|
||||
pdf_output = tempfile.NamedTemporaryFile(suffix='.pdf', delete=False).name
|
||||
|
||||
# Try svglib first (more portable, no external dependencies)
|
||||
if SVG_AVAILABLE:
|
||||
try:
|
||||
drawing = svg2rlg(temp_svg_path)
|
||||
if drawing:
|
||||
# Render at original size - quality depends on PDF rendering
|
||||
# The PDF will contain vector graphics for sharp output
|
||||
renderPDF.drawToFile(drawing, pdf_output)
|
||||
|
||||
# Clean up temp SVG
|
||||
try:
|
||||
os.remove(temp_svg_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
if filename:
|
||||
return pdf_output
|
||||
else:
|
||||
with open(pdf_output, 'rb') as f:
|
||||
pdf_bytes = f.read()
|
||||
os.remove(pdf_output)
|
||||
return pdf_bytes
|
||||
except Exception as svg_err:
|
||||
print(f"svglib conversion failed: {svg_err}, trying cairosvg...")
|
||||
|
||||
# Fallback: Try cairosvg (requires system Cairo library)
|
||||
# Use cairosvg FIRST as it handles fonts and complex SVGs better
|
||||
if CAIROSVG_AVAILABLE:
|
||||
try:
|
||||
# Render at high DPI for sharp output
|
||||
cairosvg.svg2pdf(url=temp_svg_path, write_to=pdf_output, dpi=self.dpi)
|
||||
print("Converting SVG to PDF using CairoSVG (high quality)...")
|
||||
# CRITICAL: Let CairoSVG read dimensions from SVG file (width="35mm" height="25mm")
|
||||
# DO NOT specify output_width/output_height as they control raster size, not PDF page size
|
||||
# The SVG already has the correct dimensions, just render at high DPI
|
||||
cairosvg.svg2pdf(
|
||||
url=temp_svg_path,
|
||||
write_to=pdf_output,
|
||||
dpi=300 # High DPI for sharp output, page size comes from SVG
|
||||
)
|
||||
# Clean up temp SVG
|
||||
try:
|
||||
os.remove(temp_svg_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
print(f"✅ PDF created from SVG template: {pdf_output}")
|
||||
if filename:
|
||||
return pdf_output
|
||||
else:
|
||||
@@ -174,9 +161,54 @@ class PDFLabelGenerator:
|
||||
os.remove(pdf_output)
|
||||
return pdf_bytes
|
||||
except Exception as cairo_err:
|
||||
print(f"CairoSVG conversion failed: {cairo_err}")
|
||||
print(f"CairoSVG conversion failed: {cairo_err}, trying svglib...")
|
||||
|
||||
print("SVG conversion failed. svglib and cairosvg both unavailable or failed.")
|
||||
# Fallback: Try svglib (generates many warnings but works)
|
||||
if SVG_AVAILABLE:
|
||||
try:
|
||||
print("Converting SVG to PDF using svglib (fallback)...")
|
||||
drawing = svg2rlg(temp_svg_path)
|
||||
if drawing:
|
||||
# CRITICAL: Force exact label dimensions (35mm x 25mm landscape)
|
||||
# Convert to points: 1mm = 2.834645669 points
|
||||
from reportlab.lib.units import mm
|
||||
from reportlab.pdfgen import canvas as pdf_canvas
|
||||
|
||||
target_width = 35 * mm
|
||||
target_height = 25 * mm
|
||||
|
||||
# Scale drawing to exact size
|
||||
if drawing.width > 0 and drawing.height > 0:
|
||||
scale_x = target_width / drawing.width
|
||||
scale_y = target_height / drawing.height
|
||||
drawing.width = target_width
|
||||
drawing.height = target_height
|
||||
drawing.scale(scale_x, scale_y)
|
||||
|
||||
# Create PDF with explicit landscape page size
|
||||
c = pdf_canvas.Canvas(pdf_output, pagesize=(target_width, target_height))
|
||||
c.setPageCompression(0) # No compression for quality
|
||||
renderPDF.draw(drawing, c, 0, 0)
|
||||
c.save()
|
||||
|
||||
# Clean up temp SVG
|
||||
try:
|
||||
os.remove(temp_svg_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
print(f"✅ PDF created from SVG template: {pdf_output}")
|
||||
if filename:
|
||||
return pdf_output
|
||||
else:
|
||||
with open(pdf_output, 'rb') as f:
|
||||
pdf_bytes = f.read()
|
||||
os.remove(pdf_output)
|
||||
return pdf_bytes
|
||||
except Exception as svg_err:
|
||||
print(f"svglib conversion failed: {svg_err}")
|
||||
|
||||
print("❌ SVG conversion failed. Both cairosvg and svglib unavailable or failed.")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
@@ -226,11 +258,15 @@ class PDFLabelGenerator:
|
||||
else:
|
||||
pdf_buffer = io.BytesIO()
|
||||
|
||||
# Create canvas with label dimensions
|
||||
c = canvas.Canvas(pdf_buffer, pagesize=(self.label_width, self.label_height))
|
||||
# Create canvas with label dimensions - explicitly landscape
|
||||
c = canvas.Canvas(pdf_buffer, pagesize=self.page_size)
|
||||
|
||||
# Set higher resolution for better quality
|
||||
c.setPageCompression(1) # Enable compression
|
||||
# CRITICAL: Disable compression for maximum print quality
|
||||
c.setPageCompression(0) # Disable compression for best quality
|
||||
|
||||
# Set high resolution for crisp output on thermal printers
|
||||
# Page size already set to landscape orientation
|
||||
c._pagesize = self.page_size
|
||||
|
||||
# Calculate dimensions
|
||||
usable_width = self.label_width - 2 * self.margin
|
||||
@@ -257,11 +293,11 @@ class PDFLabelGenerator:
|
||||
temp_img_path = temp_img_file.name
|
||||
temp_img_file.close()
|
||||
|
||||
# Convert to grayscale for black and white
|
||||
img_bw = img.convert('L')
|
||||
img_bw.save(temp_img_path, 'PNG')
|
||||
# Keep as RGB for better quality (thermal printers handle conversion)
|
||||
# Save at high DPI for sharp output
|
||||
img.save(temp_img_path, 'PNG', dpi=(self.dpi, self.dpi), optimize=False)
|
||||
|
||||
# Draw image maintaining aspect ratio
|
||||
# Draw image maintaining aspect ratio with high quality
|
||||
c.drawImage(
|
||||
temp_img_path,
|
||||
image_x,
|
||||
@@ -269,7 +305,8 @@ class PDFLabelGenerator:
|
||||
width=image_width,
|
||||
height=image_height,
|
||||
preserveAspectRatio=True,
|
||||
anchor='c'
|
||||
anchor='c',
|
||||
mask='auto' # Better quality rendering
|
||||
)
|
||||
|
||||
# Clean up
|
||||
@@ -291,10 +328,15 @@ class PDFLabelGenerator:
|
||||
else:
|
||||
text = f"{label_name} -"
|
||||
|
||||
# Use appropriate font size to fit (6pt = ~2.1mm height)
|
||||
font_size = 6
|
||||
# IMPROVED: Larger font size for better readability (8pt = ~2.8mm height)
|
||||
# This is critical for thermal printers - text must be crisp and readable
|
||||
font_size = 8
|
||||
c.setFont("Helvetica-Bold", font_size)
|
||||
|
||||
# Enable text rendering mode for crisp output
|
||||
c.setStrokeColorRGB(0, 0, 0)
|
||||
c.setFillColorRGB(0, 0, 0)
|
||||
|
||||
try:
|
||||
c.drawString(text_area_x, y_position, text)
|
||||
except Exception as e:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
python-barcode
|
||||
pillow
|
||||
kivy>=2.1.0
|
||||
kivy>=2.3.0
|
||||
reportlab
|
||||
pyinstaller>=6.0.0
|
||||
pywin32
|
||||
|
||||
63
test_conf_generation.py
Normal file
63
test_conf_generation.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
Test script to verify conf folder auto-generation
|
||||
Run this to test that conf/ folder is created with default templates
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Temporarily rename existing conf folder to test auto-generation
|
||||
if os.path.exists('conf'):
|
||||
print("Backing up existing conf folder to conf_backup...")
|
||||
if os.path.exists('conf_backup'):
|
||||
shutil.rmtree('conf_backup')
|
||||
shutil.move('conf', 'conf_backup')
|
||||
print("✓ Existing conf folder backed up")
|
||||
|
||||
print("\nTesting conf folder auto-generation...")
|
||||
print("Starting label_printer_gui initialization...")
|
||||
|
||||
# Import the app (this will trigger initialization)
|
||||
from label_printer_gui import LabelPrinterApp
|
||||
|
||||
# Create app instance (will auto-create conf folder)
|
||||
app = LabelPrinterApp()
|
||||
|
||||
# Check if conf folder was created
|
||||
if os.path.exists('conf'):
|
||||
print("\n✓ SUCCESS: conf folder created")
|
||||
|
||||
# Check for required files
|
||||
required_files = [
|
||||
'conf/app.conf',
|
||||
'conf/label_template.svg',
|
||||
'conf/label_template_ok.svg',
|
||||
'conf/label_template_nok.svg'
|
||||
]
|
||||
|
||||
missing_files = []
|
||||
for file in required_files:
|
||||
if os.path.exists(file):
|
||||
print(f" ✓ {file}")
|
||||
else:
|
||||
print(f" ✗ {file} MISSING")
|
||||
missing_files.append(file)
|
||||
|
||||
if not missing_files:
|
||||
print("\n✓ All required files created successfully!")
|
||||
else:
|
||||
print(f"\n✗ Missing files: {missing_files}")
|
||||
else:
|
||||
print("\n✗ FAILED: conf folder not created")
|
||||
|
||||
# Restore original conf folder
|
||||
print("\nRestoring original conf folder...")
|
||||
if os.path.exists('conf_backup'):
|
||||
if os.path.exists('conf'):
|
||||
shutil.rmtree('conf')
|
||||
shutil.move('conf_backup', 'conf')
|
||||
print("✓ Original conf folder restored")
|
||||
|
||||
print("\n" + "="*50)
|
||||
print("Test complete!")
|
||||
print("="*50)
|
||||
Reference in New Issue
Block a user