Conditional Formatting Digital Clock

I was staring at a video player the other day and thinking about digital clocks, specifically, of course, digital clocks created in Excel. As I imagined, there are quite a few out there: Juan Pablo Gonzalez already had one on DDOE back in 2004, Andy Pope’s is indistinguishable from the real thing, and Tushar Mehta’s is accurate to within one nanosecond every three years. But as far as I can tell there aren’t any created using conditional formatting. Let me know if I’m wrong, but meanwhile here’s a conditional formatting digital clock in a live workbook.

As the notes in the worksheet above say, you can update this clock by clicking in a cell and hitting F9. Not very convenient, but the best I can do without macros. (See the download at the end for full automation). You can adjust the time to your location, instead of that of your server, with the “Hour Offset” setting. To see the full works click on the second worksheet tab.

My basic idea was to use conditional formatting cell borders to form the digits. Each digit would consist of two cells on top of each other.

The first issue was how to have doubled lines for cell borders. Conditional formatting doesn’t have this option. Regular cell borders do though, so the answer was to put double line borders around all the digit cells and then have the conditional formatting “erase” the unneeded ones.

border settings table

The formatting feeds from this grid, which you can see on the second worksheet. Each clock digit is formed from two cells, the “top” and “bottom.” Each of the four borders for each cell has a 0 or 1 setting.

I originally had the table rows filled with 1, 2, 4 and 8 for each cell, thinking to roll the four numbers up into something like a composite enumerated value. Then I tried to use Mod to parse the rolled-up result for each half-digit. If that sounds confusing, it should! I eventually realized that since I essentially needed to determine if each border’s “bit” was on or off, I should just use a table with zeros and ones.

The conditional formatting formula, listed below, finds the relevant digit and it’s top or bottom position and checks whether it’s set to 0. If so, the conditional formatting “erases” the existing border. Otherwise the original double border is left in place.

There are actually four very similar formulas. The only thing that changes is the …”,1)=0″ part at the end. That’s checking the first column, i.e., the left border. The other formulas check, the 2nd, 3rd and 4th columns (the top, bottom and right borders).

=INDEX($R$6:$U$25,
SUMPRODUCT(
($P$6:$P$25=$S1)*
($Q$6:$Q$25=(MID($T$1,((COLUMNS($A:A)+1)/2),1)))*
(ROW($P$6:$P$25)-ROW($P$5)))
,1)
=0

It’s a two-dimensional Index formula. The most interesting thing is that the row dimension is determined by a Sumproduct formula, which finds the row that has the correct digit and top or bottom position. I’ll try to do a short post on this sometime, or if anybody has a good link, let me know.

clock's off button

This digital clock requires Excel 2007 or 2010 because there are four conditions per cell, and Excel 2003 only supports three. I could maybe figure a way around that, but… nah!

You can download the Excel 2007/10 .xlsm zip file, complete with “clocks on / clocks off” button.

Solving the NPR Sunday Puzzle – #3

Every time I hear Will Shortz say “name a country of the world” my heart beats a little faster, cause I know there’s probably an array-formula post in it. This week was no exception:

“Name an article of clothing that contains three consecutive letters of the alphabet consecutively in the word. For example, “canopy” contains the consecutive letters N-O-P. This article of clothing is often worn in a country whose name also contains three consecutive letters of the alphabet together. What is the clothing article, and what is the country?”

This spreadsheet is live. Double-clicking in a cell in the 2nd column shows the formula. You can then drag the lower-right fill handle to see the whole gnarly thing.

Countries are a lot more list-friendly, so I solved that part first. There are two types of solutions above: an array formula in the 2nd column, and a conditional formatting solution in the 3rd to 40-somethingth column. The 2nd solution is the way I’d do it for serious work, but the array formula is more fun:

=IFERROR(
MID(A4,MIN(IF(
CODE(MID(LOWER($A4),ROW(INDIRECT("1:"& LEN($A4)-2)),1))+1=
CODE(MID(LOWER($A4),ROW(INDIRECT("2:"& LEN($A4)-1)),1)),
IF(CODE(MID(LOWER($A4),ROW(INDIRECT("1:"& LEN($A4)-2)),1))+2=
CODE(MID(LOWER($A4),ROW(INDIRECT("3:"& LEN($A4))),1)),
ROW(INDIRECT("1:"& LEN($A4)-2))))),3),
"")

This formula says to compare every letter in the country name to the next two letters. If the numeric code for a letter is one less than the letter after it, and two less than the letter after that, return those three letters. The reason the 2nd column is mostly blank is because surprisingly few country names have three consecutive letters. (Or my formula sucks.)

Here’s how it works. Let’s assume the formula refers to Albania, the 3rd country in the list:

LEN returns the length of the country’s name.

INDIRECT(“1:”& LEN($A4)-2) evaluates to (1:5).

ROW(INDIRECT(“1:”& LEN($A4)-2)) evaluates to {1;2;3;4;5}. This tells the array formula which characters in “Albania” to evaluate against their respective two next characters. Using ROW this way is very handy in array formulas.

CODE(MID(LOWER($A4),ROW(INDIRECT(“1:”& LEN($A4)-2)),1)) resolves to {97;108;98;97;110}. In other words, the numeric values of the first five letters of Albania are 97, 108, etc. CODE is the function that returns the values. LOWER converts each letter to lower case, otherwise, for example, a lowercase “b” wouldn’t be seen as following an uppercase “A”. The MID piece tells the array formula to parse each of the first 5 letters in the word.

Okay, now we’re getting close. This bit:
CODE(MID(LOWER($A4),ROW(INDIRECT(“1:”& LEN($A4)-2)),1))+1=
CODE(MID(LOWER($A4),ROW(INDIRECT(“2:”& LEN($A4)-1)),1))
resolves to
{98;109;99;98;111}={108;98;97;110;105}, which in turn resolves to {FALSE;FALSE;FALSE;FALSE;FALSE}. In other words, one added to the code for the first five letters in “Albania” doesn’t ever equal the code for their respective next letters. So there’s not even two consecutive letters. What a country! The next two lines in the formula repeat the comparison, this time with the 2nd through 7th letters.

The 2nd line, which starts with MID, and the 2nd to last line say that if the whole mess is true, return the three letters that start at that position.

The IFERROR function at the beginning and the last line simply say that if the formula errors (doesn’t find three consecutive letters) put a blank in the cell. IFERROR is available in Excel 2007 and 2010. I like it very much as they keep formulas like this from being twice as ridiculously long.

Much of the evaluation above was done using the F9 key. Selecting part of a formula and then pressing F9 evaluates that piece of the formula, a very useful feature.

There are only two countries that meet the criteria, Afghanistan and Tuvalu. I figured it was probably the former and soon enough realized the article of clothing was “hijab.”

If you’ve made it this far, thanks! Oh yeah, the multiple cell and conditional formatting way works similarly to the array formula, only by breaking it up it’s a lot easier.

If anybody has a better array formula, please share.

Solving the NPR Sunday Puzzle – #2

This week’s NPR Sunday Puzzle was array formula nirvana.

Take the trees hemlock, myrtle, oak and pine. Rearrange the letters in their names to get four other trees, with one letter left over. What trees are they?

I made this workbook to solve the puzzle:

At the left is a list of trees whose names meet three criteria:

  • The name only contains letters from the four starting trees.
  • The name doesn’t contain more of any letter than are in the four starting names combined.
  • The name isn’t in the original list.

To solve the puzzle, enter TRUE next to trees to choose them. The list of letters on the right will change as you do. Letters shaded blue are still available and the number remaining is shown. If a letter is shaded orange, you’ve overused it and the “remaining” number is negative. Unshaded letters have been used perfectly.

When the number of trees selected is four and one letter is unused, you’ve solved the puzzle. Go ahead and try it! And, oh yeah, there may be something tricky about the list.

Now for the array formulas, all entered with Ctrl-Shft-Enter. There’s one in the “Used” column:

{=SUM(LEN(IF(tblTrees[Use?],tblTrees[Tree],"")))-
SUM(LEN(SUBSTITUTE(IF(tblTrees[Use?],tblTrees[Tree],""),[@[Letters To Use]],"")))}

It compares the length of the names chosen against the length of their names after removing the letter, i.e., how many times that letter is used.

To get the list of tree names my family did some brainstorming, which we augmented with a list from the web. It was sliced and diced using Text to Columns and Remove Duplicates from the Excel 2010 Data menu.

Two more array formulas winnow the list to names that meet our three criteria. They’re on the “Good Trees” tab of the workbook. The “Contains Only Valid Letters” formula determines if a name meets the first criteria:

{=MATCH(0,COUNTIF(tblLetters[Letters To Use],
MID($A2,{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},1)),0)>LEN($A2)}

This formula assumes that the longest name is 15 letters. The CountIf increments through the letters in the word, counting the occurrences of each letter in the list, which will either be one or zero. It uses Match to find the position of the first zero. If that’s greater than the number of letters in the word it passes the test.

The “Contains Less Of Each Letter Than Total” formula checks our second criteria:

{=ISERROR(MATCH(FALSE,(tblLetters[Count Of Letter]>=
(LEN(A2)-LEN(SUBSTITUTE(A2,tblLetters[Letters To Use],"")))),0))}

This also uses the trick of comparing the length of the name against its length with the character removed, to get the count of that letter in the word. It then assumes that the count of that letter overall is greater than or equal to the count in the word, for each letter in the word. If that assumption is FALSE in any letter position the word is no good.

The “Not In Original List” formula checks … you know. The last one combines the first three and if they’re all true the word makes the cut.

I’d love to hear how other people would do these tests. I’m curious too if others are using Excel to solve puzzles, NPR or otherwise. Do you have a good source of lists? I always just google around, with mixed results.

After I had done all the processing I used the workbook to get the answer. I chose three names – elm, hickory and lemon, and had a, e, k, p and t left over. Four of those letters spelled the last tree. It wasn’t on the list but I added it. You could just put it where pecan is now if you want. If you already did, then “teak” a bough. Yew should be proud.

Speaking of tree-related words, one of my favorite words is “pitch.” It’s arboreal, nautical, romantic, and so much more.

Solving the NPR Sunday Puzzle

The yoursumbuddy official smartphone has two alarms. One wakes me up at the reasonable hour of 6:23, and one goes off at 9:35 every Sunday with a reminder that NPR’s Sunday Puzzle starts in three minutes. Last Sunday’s lent itself nicely to some Excel fun:

Name two fictional characters – the first one good, the second one bad. Each is a one-word name. Drop the last letter of the name of the first character. Read the remaining letters in order from left to right. The result will be a world capital. What is it?

To solve this, I wanted a list of villains and another of world capitals.

I recently realized that Excel’s Data > From Web feature is easier than copying stuff straight from the web. A lot of web lists have weird html formatting and this feature cuts past much of that. So I sucked in a list of villains from kaijuphile.com

Villain List

… and one of capitals from, that’s right, Wikipedia. Now down to work.

With both lists in a sheet, I added a couple of columns for each. For the villains, the first column gets rid of numbers and the word “The.” The 2nd strips out all villains with names longer than one word, per Mr. Shortz’s instructions. Here’s the formula:

=IFERROR(TEXT(SEARCH(" ",B2),""),B2)

Setup

There’s two fun things here:

1. The IfError part is formed backwards from its normal usage. We actually want the part that returns an error when it doesn’t find a space in the villain’s name: a one-word name.

2. However, this means that all the more-than-one-word villains will return a number – the location of the space. The Text part of the formula fixes that by returning blanks for numbers and leaving strings intact. For example Text(23,””) returns a blank, but Text(“twerp”,””) returns “twerp.” Hey, maybe the answer is Antwerp!

For the capitals, there’s just a bunch of columns, each one lopping off one more letter from the beginning. The villainous name forms the 2nd part of the capital, so if we’re lucky one of the froncated (front-truncated) strings will match a villain. The formula is:

=IFERROR(RIGHT($D2,LEN($D2)-COLUMNS($E:E)),"")

Conditional formatting in column E rightwards turns a cell orange if it matches any of the villain names in column C.  And, sure enough:

Iago

“Santiago” yields “Iago,” who as we all know, flew too near the sun and made a lot of people mad.

This means there’s a good fictional character whose name starts “Sant” followed by one more letter. Hmmm… I guess he wasn’t thinking of the Billie Bob Thornton version.

goofy code

The other day I needed to increment some footnotes for a document that gets published yearly. The footnotes look something like:

(8,11)

I needed to increment them all by three and there are a few pages, so of course I wrote some VBA. The line that prompted this post removes the left and right parentheses, then Splits the remaining string with comma as the delimiter, and assigns the resulting array to a variant. Here it is:

 SplitCell = Split(Replace(Replace(cell.Value2, ")", ""), "(", ""), ",")

I admit I’m easily amused, but that is some funny looking code.