Process Automation · CareCenter AS · Hotel Continental, Oslo

An end-to-end invoicing pipeline built in Excel & VBA

A self-initiated automation project at CareCenter that replaced a manual end-of-month invoicing routine with a one-click pipeline from input form to Tripletex-ready export.

Role
Garage Administrator
Built alongside daily operations
Built with
Excel · VBA · Tripletex
Native, no external dependencies
Customer base
568
corporate accounts handled
Time saved
~50%
per billing cycle
01

A spreadsheet that quietly bled time

CareCenter operates a service garage at Hotel Continental in Oslo. Mechanics log every job — the work performed, the customer, the price, and the payment method — into a shared Excel sheet as the day unfolds. That part worked fine.

Before · January 2026 A typical month — manager scans the full list to find every entry for each customer.
Date
Customer
Work
Payment
Sum
02.01.26
Alpha AS
Utv
Faktura
1 000
Alpha AS
Innv
Faktura
500
03.01.26
Bravo AS
Polering
Faktura
1 800
05.01.26
Charlie AS
tp
Faktura
700
06.01.26
Delta Eiendom
Utv
Kort
1 200
07.01.26
Bravo AS
tp
Faktura
450
08.01.26
Echo Consulting
Innv
Faktura
900
Echo Consulting
Polering
Faktura
1 600
10.01.26
Foxtrot Bygg
tp
Vipps
300
13.01.26
Bravo AS
Utv
Faktura
1 100
14.01.26
Golf Holding
tp
Faktura
600
15.01.26
Alpha AS
Polering
Faktura
2 200
16.01.26
Hotel Indigo
Innv
Faktura
800
17.01.26
Charlie AS
Utv
Faktura
1 500
20.01.26
Bravo AS
Polering
Faktura
2 400
Juliet AS
tp
Kort
350
22.01.26
Kilo Eiendom
Innv
Faktura
700
23.01.26
Delta Eiendom
tp
Faktura
550
26.01.26
Bravo AS
tp
Faktura
380
27.01.26
Foxtrot Bygg
Utv
Faktura
1 300
28.01.26
Hotel Indigo
Polering
Faktura
1 950
30.01.26
Bravo AS
Innv
Faktura
650
31.01.26
Golf Holding
Utv
Faktura
1 400
Highlighted in green: every job for one customer (Bravo AS), scattered across the month — six rows out of twenty-three. Repeat the same hunt for every other invoice customer. Miss one — that revenue disappears.

The problem started at the end of each billing cycle. To prepare invoices, the manager had to scan the entire chronological log, manually identify every row tied to a single corporate customer, highlight them as he went, and re-enter each one into Tripletex by hand. Then repeat for the next customer. And the next. And the next.

It was slow, but more importantly it was fragile: a single missed row meant an unbilled job — revenue lost without anyone noticing.

02

One macro that does five things at once

The system keeps the mechanics' workflow untouched — they still log every job into a simple form on a single sheet. The complexity sits behind a button labelled "Lagre".

When pressed, the macro validates the input, writes the raw entry to a master log, separates invoice customers into their own sheet, generates a unique order number per customer per month, looks up the customer's Tripletex ID from a database of 568 corporate accounts, and finally produces a Tripletex-ready import file with a single additional click.

Five things that used to be five different mental steps — collapsed into one.

The biggest change is structural, not just technical: invoice customers now live grouped in their own sheet. The manager no longer hunts for "Bravo AS" through fifty rows of mixed entries — every Bravo-job is already gathered, ordered, and tagged with its customer ID.

See it in motion

The animation below shows what happens when a mechanic enters a job and clicks save. All jobs land in the master log; only invoice rows continue down to the invoice queue, automatically tagged with an order number and customer ID.

SHEET 1 Front · Input form
All jobs logged
SHEET 2 Tabell · Master log (all jobs)
Date
Customer
Work
Pay
Sum
Only invoice rows continue
SHEET 3 Fakturakunder · Invoice rows only
Order
Customer
Work
Cust ID
Sum
Watch a job entry move from the input form to its destination — invoice rows are grouped under a generated order number; cash and card rows stop at the master log.
03

From entry to Tripletex

The data path moves through five sheets, each with a clear purpose. The mechanic only ever sees the first.

SHEET 1 Front Mechanic input SHEET 2 Tabell Master log (all jobs) SHEET 3 Fakturakunder Invoice rows only REFERENCE Faste Kunder 568 customers SHEET 4 order_import Tripletex format EXTERNAL Tripletex Accounting customer ID lookup log filter format Date · Customer · Work · Price All jobs, all payment types Grouped, order # assigned 8-column export schema DATA FLOW · ONE BUTTON · END-TO-END
04

Three problems worth solving carefully

Most of the macro is straightforward bookkeeping. Three pieces required actual design decisions.

Order Number Logic
Customer-Month Sequencing

Each customer should receive one invoice per month with multiple line items grouped together. The macro uses a Scripting.Dictionary keyed on customer + month to either fetch the existing order number or assign the next available one in that month — ensuring jobs for the same customer collapse into one Tripletex order.

Customer Lookup
568-Row Reference Table

A separate sheet holds CareCenter's full corporate customer database — 568 entries with Tripletex IDs, addresses, and contact details. Every invoice row gets enriched with the correct customer ID via a name-based match before export. No manual ID entry required.

Tripletex Export
Schema-compliant File Output

The export macro copies the formatted sheet into a new workbook, applies a timestamped filename (Tripletex_Export_yyyymmdd_hhmmss.xlsx), and saves it directly to the Desktop in xlOpenXMLWorkbook format. Tripletex accepts the file as-is — no manual reformatting.

Validation & UX
Required Fields, Quick Drafts

The form blocks submission unless all mandatory fields are filled, preventing the silent loss of jobs that plagued the old system. A separate row of "kladd"-shortcuts lets mechanics queue up several jobs and copy them into the form one at a time during quiet moments.

Order number generation — the core of the design

The snippet below shows the simplified logic used to assign order numbers. Customer names and IDs are illustrative only.

' For each invoice row, check if this customer already has ' an order number assigned for the current month. ' If yes — reuse it. If no — assign the next available. Dim dictOrder As Object Set dictOrder = CreateObject("Scripting.Dictionary") For Each row In invoiceRows orderKey = customer & "_" & Format(jobDate, "yyyymm") If dictOrder.Exists(orderKey) Then currentOrderNum = dictOrder(orderKey) Else currentOrderNum = maxOrderNumInMonth + 1 dictOrder.Add orderKey, currentOrderNum maxOrderNumInMonth = currentOrderNum End If ' Write order number back to the row row.Cells(1, COL_ORDER_NUM).Value = currentOrderNum Next row
Simplified excerpt. The full implementation also handles month rollover and re-runs idempotently.
05

What changed

The improvement is measured in two dimensions — the time the manager spends on each billing cycle, and the number of jobs that quietly disappeared between the spreadsheet and Tripletex.

Time
~50%
reduction in manual processing time per billing cycle
Coverage
100%
of invoice-eligible jobs captured — no more missed entries
Scale
568
corporate customers handled by automatic lookup

The system has been in daily production use at CareCenter since 2024 and replaced an entirely manual workflow. The mechanics' input experience is unchanged — only the manager's end-of-month workflow was transformed.