August 6, 2019 at 8:16 AM by Dr. Drang
I’ve written several times about how I keep track of and follow up on unpaid invoices, most recently here. It’s a system that’s evolved over time to become both more automated and less reliant on me being in my office in front of my Mac. This past weekend, I wrote a Shortcut that allows me to quickly calculate the total of my outstanding invoices from an iOS device., something I’ve been able to do on my Mac for quite a while.
To recap, every time I generate and send out an invoice at work, an item is added to my Invoices list in Reminders. The Reminder is set to follow up with the client 45 days1 after the invoice is issued (assuming it hasn’t been paid) and includes the project name, project number, invoice number, and invoiced amount.
What I wanted was a quick way to get the total of all those dollar amounts in parentheses. The solution was a Shortcut, named Unpaid, that was saved to my home screen and then stored in a folder with other work-related items.
Tapping the Unpaid icon runs the shortcut, which finishes by displaying a dialog box with the number of unpaid invoices and their total.
It’s obviously not good when this number gets too high, but it’s also bad when it gets too low. That usually means I’ve been delinquent in sending out invoices.
The Unpaid shortcut, which is on all my iDevices, looks like this:
The first two steps initialize the variable
total to zero. This is where we’ll accumulate the sum of all the invoiced amounts.
The next step gets all the items in the Invoices list that are unchecked. I should mention that all these reminders are set to repeat. Checking an item on the list doesn’t mean the bill has been paid, it means that I’ve sent a followup email on the bill, and it creates an new item to follow up again two weeks later. When an invoice is paid, I delete its reminder from the list.
We then get a count of the reminders, which we’ll use later.
The bulk of the work is done by a loop that goes through each item in the list, pulling out the title (), extracting the parenthetical with a regular expression ( ), deleting the extraneous characters—parentheses, dollar sign, comma—from that string ( and ), and adding that amount to the running total ( and ).
Finally, total is formatted with commas () and included with the item count in message to the user ( ).
Overall, it’s a pretty simple shortcut. The trickiest parts are the regular expressions. If you don’t care about regexes, you can consider the post finished right here. The rest is a discussion of how each of them work.
The first regex, in, is this:
It’s messy because it has to escape the dollar sign and the parentheses at the beginning and end. But the idea is simple: find any string that starts with an opening parenthesis and a dollar sign and collect every character through the first closing parenthesis.
The second regular expression, in the firststep, is this:
It defines a character class consisting of opening and closing parentheses, dollar signs, and commas. Any instance of this class is replaced by an empty string, i.e, deleted. I do this because the amount of the invoice has to be parsed as a number, and these extraneous characters prevent that.2
An unstated feature of Shortcuts’s
Finally, we have the hardest regex, the one in the final:
I adapted this from a Stack Overflow answer that handled integers. It starts with a digit and then the
(?=… ) construct, which is called a positive lookahead. The lookahead finds groups of three digits (one or more of such groups) followed by a period. The key is that the regex engine considers the lookahead to have zero width, which has two effects:
It allows us to use the simple replace string,
which puts a comma after the digit captured in the first set of parentheses. We don’t have to worry about the part of the string matched in the lookahead because the engine considers the match to have ended just after the captured digit.3
It means that after the first replacement, the regex continues its search after the comma. This allows it to put commas between all the groupings of three digits. The pattern will not only convert
51,600.61, it will also convert
51,600,600.61, and so on, into the billions, trillions, etc. If the search pattern had been
and the replacement pattern
51,600.61as before, but
51600600.61would be turned into
51,600600.61because the search would pick up after the period and skip the second comma. The zero-width makes all the difference.
You could, of course, argue that this application has no need to format numbers in the millions or higher. I’ve never even had as much as a six-figure accumulation of unpaid invoices, let alone a seven-figure one. So a simpler pattern, one that anticipates no more than one comma separator, would work. But it’s more fun to explore the dark corners and learn new things.
Strictly speaking, it’s the first Tuesday that comes after 45 days, but that detail isn’t important here. ↩
Actually, Shortcuts seems to be able to parse commas in numeric strings, but I deleted them anyway to be on the safe side. ↩
Oddly, you can capture things by using parentheses inside the lookahead construct, but the regex engine still considers the match to have ended just before the lookahead. ↩