Skip to main content
  1. Posts/

Labeling My Basement Inventory: From Herma Stickers to a Dymo LabelWriter

· David Steeman · Electronics, DIY, Linux

When you have been accumulating electronic components for as long as I have, labeling and organizing them becomes a project in its own right. This is the story of how my labeling system evolved from round stickers on a DIY plywood cabinet to a custom LibreOffice macro driving a thermal label printer — and the surprisingly tricky orientation problems I had to solve along the way.

The original setup
#

Back in 2014, I built a simple wooden cabinet to hold small yoghurt-drink containers full of components. About 150 bottles, each needing a label. I settled on round Herma 4386 stickers — 20mm diameter, 96 per A4 sheet — printed using the free Herma Label Designer software. I even figured out how to mail-merge data from an Excel spreadsheet onto the labels, so I did not have to type every component name by hand.

That system worked. But it had friction:

  • Waste. A4 sheets hold 96 labels. If you need three, you waste 93. Partial sheets could be reused, but only so many times before the paper started smearing in the printer.
  • Windows dependency. Herma Label Designer is Windows-only. My daily machines run Linux.
  • Physical distance. The family inkjet printer is upstairs. My workbench is in the basement. Every labeling session meant running up and down the stairs with a sheet of stickers, then peeling and sticking them one by one.

It was fine for 150 containers. Then I acquired 10 wall-mounted cabinets with small component trays, and suddenly I was looking at hundreds of new labels. The Herma workflow was not going to scale.

The upgrade: a thermal label printer
#

I bought a Dymo LabelWriter 450 and a box of Dymo 30334 labels (12mm x 50mm). Thermal printing solves the core problems:

  • One at a time. Print exactly the labels you need. No sheets, no waste.
  • On the workbench. The Dymo is small enough to sit next to the component cabinets. No more stairs.
  • No ink. Thermal printing means no cartridges to replace, no smearing, no drying time.

The Dymo 30334 labels are narrow strips — 12mm tall, 50mm wide. They fit perfectly on the front of the small trays in the wall-mounted cabinets. Each label has room for a short description and a location code.

Dymo provides their own labeling software, but it is proprietary, does not integrate with my spreadsheet workflow, and would lock me into their ecosystem. I wanted something simpler: select rows in a spreadsheet, press a button, get labels.

KelderInventory.ods: the spreadsheet as both database and print interface
#

I built the system around a LibreOffice Calc spreadsheet called KelderInventory.ods (“kelder” is Dutch for basement). Each row represents one labeled container:

ColumnFieldRequiredPrinted
ABoxYesYes
BBinYesYes
CLabel row 1YesYes
DLabel row 2NoYes
ELabel row 3NoYes
FKeywordsNoNo
GCommentsNoNo

Box and Bin are location codes — think of them like a library reference. Box 03, Bin 02 tells me exactly which tray to pull. The Label rows describe what is in the container. Keywords and Comments are for searching and personal notes; they do not appear on the label.

The spreadsheet lives on a Samba share, so I can open it from any machine on the network — Linux or Windows. There is a “Print Label(s)” button embedded in the sheet. Select one or more rows, click the button, and labels come out of the Dymo. No export step, no external program, no file format conversions.

The orientation saga
#

Getting text to print correctly on a 12mm x 50mm label turned out to be the hardest part of the project. LibreOffice Writer does not have a built-in “label” concept. To print a label, the macro creates a hidden Writer document, sets the page size to match the physical label, lays out the text programmatically, and sends it to the printer.

The first attempt used a landscape page — 50mm wide, 12mm tall — which seems logical for a wide label. But the Dymo LabelWriter feeds labels in portrait orientation. The result: perfectly formatted text, printed sideways.

Attempt 1: Landscape page (50mm x 12mm). Text appeared vertical on the physical label because the printer rotated everything 90 degrees to match its feed direction.

The fix was to switch to a portrait page — 12mm wide, 50mm tall — to match the printer’s feed direction. Now the page geometry was correct, but the text was laid out along the 12mm width. Everything appeared sideways.

Attempt 2: Portrait page (12mm x 50mm). Page geometry correct, but all text runs vertically — readable only if you tilt your head 90 degrees.

The solution was counter-intuitive: keep the portrait page, but rotate all text 90 degrees counter-clockwise. In the LibreOffice UNO API, this is CharRotation = 900 (the value is in tenths of a degree). On screen, the text looks vertical in the Writer document. But when the Dymo prints it, the text comes out horizontal — because the printer’s own rotation and the text rotation cancel each other out.

Attempt 3: Portrait page + 90 degree CCW text rotation. Text appears vertical on screen but prints horizontally on the physical label. This is the final approach.

It took three iterations to get right, and each iteration meant printing test labels, walking over to the cabinet, holding the label up to the tray, and deciding whether the text was readable. The macro still contains the three test functions — TestLabel, TestLabel2, and TestLabel3 — one for each attempt, in case I ever need to debug orientation again.

The label layout
#

Each label is divided into two sections using a borderless table:

+--------------------------------------------------+
| Label row 1 (bold)                          03   |
| Label row 2                                 02   |
| Label row 3                                      |
+--------------------------------------------------+
          Labels (78%)                    Box/Bin
                                           (18%)

The top section (78% of the label height) holds the description — up to three lines of text, left-aligned. The first line is bold. The bottom section (18%) holds the Box and Bin numbers, centered and printed in a larger font. The proportions were tuned by trial and error to make the location codes easy to spot at a glance while giving enough room for meaningful descriptions.

The macro architecture
#

The macro is written in LibreOffice Basic and embedded in the .ods file. The flow is straightforward:

  1. User selects one or more rows and clicks the “Print Label(s)” button.
  2. PrintLabels() reads the current selection and loads configuration from a dedicated “Config” worksheet.
  3. Each selected row is validated — Box, Bin, and Label row 1 are mandatory. If any row is missing required fields, nothing prints and the user gets a clear error message listing which rows and which fields are missing.
  4. For each valid row, PrintSingleLabel() creates a hidden LibreOffice Writer document, sets the page size to 12mm x 50mm, builds the label layout with rotated text, and either sends it to the printer or exports it as a PDF.
  5. The hidden document is closed automatically. The user never sees it.

Configuration lives in a separate “Config” worksheet with sensible defaults:

SettingDefaultPurpose
Font Size - Box14 ptBox number
Font Size - Bin12 ptBin number
Font Size - Label 19 ptFirst description line (bold)
Font Size - Label 27 ptSecond description line
Font Size - Label 36 ptThird description line
Output ModeDRY_RUNPRINT or DRY_RUN
Show Complete MessageNOShow a dialog after printing
Export Path(document folder)Where PDF previews are saved

Font sizes were tuned for the 12mm label height. At 34 points total height, there is room for five lines of text at these sizes — enough for a description and a location code, but not much more. The constraint forces brevity, which is actually a feature: if you cannot describe a component in three lines, the label is not going to help you find it anyway.

A key design decision was to use only LibreOffice’s built-in UNO API — no shell commands, no OS-specific code, no external tools. This means the macro works identically on Windows and Linux. I did not want to maintain two codepaths for something as simple as printing a label.

Dry-run mode
#

The Config sheet has an Output Mode setting that can be PRINT or DRY_RUN. In dry-run mode, labels are exported as PDFs instead of being sent to the printer. Each PDF is named after the Box and Bin codes — for example, label_03_02.pdf.

This was essential during development. I went through dozens of layout iterations, and printing a physical label each time would have been wasteful. With dry-run mode, I could adjust font sizes, tweak proportions, and verify the layout in a PDF viewer before committing to a real label.

It is also useful day-to-day. When I add a batch of new components, I do a dry-run first to check that all the text fits and the descriptions read well. Only then do I switch to PRINT mode and run the batch for real.

How the project evolved
#

The version history tells the story of the orientation struggle:

v1.0.0 — Basic macro with landscape page layout. Batch printing, validation, and the Config sheet all worked, but labels printed sideways.

v1.1.0–v1.2.0 — Added configurable font sizes and the dry-run mode. Started experimenting with layout changes.

v1.3.0 — Fixed the layout for Dymo 30334 dimensions, adjusting margins and spacing. Labels were physically correct but still oriented wrong.

v1.4.0 — The breakthrough. Switched to portrait page orientation, implemented the 90 degree counter-clockwise text rotation, changed from a 2-column to a 2-row layout, and removed all OS-specific dependencies. This is the version that finally produced correct, readable labels on both Windows and Linux.

Each version represents a round of printing test labels, inspecting the results, and adjusting the approach. The macro code includes the full history — you can trace the evolution through the commit log.

The result
#

The system has been in daily use for the basement inventory. The spreadsheet holds hundreds of entries across 10 wall-mounted cabinets. When I buy new components, I add a row to the spreadsheet, select it, and press the button. Two seconds later, the label comes out of the Dymo sitting right next to the cabinets. I stick it on the tray, put the components in, and I am done.

Compared to the old Herma workflow:

  • No more running upstairs to the family printer.
  • No more wasted label sheets.
  • No more Windows dependency.
  • The inventory data lives in a spreadsheet I can search, filter, and version control — not in a proprietary labeling application.

The project is open source on GitHub under the MIT license, complete with the macro source, a functional specification document, and a Python alternative for headless label generation.

Resources
#