Other times, you have to expect user to sub-select sub-shapes, then format them individually. This can be annoying, because they might not know how to sub-select. Also, if your shape has data fields anyway, why not set all variables in one place?

Color-picking in the Shape Data window seems a natural thing to do. After all, Visio allows you to define fancy data types like dates:

This gives you a nice, rich “picker” control like this calendar:

So why not allow color to be one of the available Shape Data types?

Heck, even ConceptDraw allows you to define color as a Custom Property data type:

Sure, this drop-down isn’t as elegant as a color picker might be, but this gets the job done! (And Yes, I’m trying to provoke the Visio team in Redmond, if you haven’t noticed.)

Workaround: Choose Colors by Name

Since Visio is so customizable, you find yourself pushing it all the time. And when you push enough, you end up against a wall, such as this one, with “no color picker shape data type” spray painted all over it. But that same customizability allows you to come up with workarounds, time and time again.

This time, the next best thing was to create a drop-down list of named colors.

While visual pickers are nice, text drop-downs offer the consolation that you can quickly navigate them by typing the first letter of the color you are searching for. And today’s example has 140 different colors, so that quick navigation is nice to have.

So now you just need to learn and memorize what colors like: “Dark Goldenrod”, “Lavender Blush” and “Powder Blue” actually mean!

Building Color Lists in the ShapeSheet

To make this work, we need two lists: Names and RGB formulas. In the ShapeSheet, you can specify a color with a formula like this:

FillForegnd= RGB(139, 69, 19)

Which yields a reddish-brown color.

We can then make a list of RGB formulas, and a corresponding list of names for those colors. The LOOKUP and INDEX ShapeSheet functions can then be used to transform a name into a color-formula.

The first two cells are self-explanatory. User.colors, however, is a bit more complicated.

You’ll notice that it references a Shape Data field called Prop.color1.This contains the value that is selected by the user in the Shape Data window. Once we have a name, we find it’s position in the name list using LOOKUP. Then we grab the RGB formula from the other list using that position as an argument to INDEX.

Note that Prop.Color.Format could just have easily contained the full list of names. But I put it in User.colorNames, so that it would be available for multiple fields. More on that later.

How to Get a Big List of Colors

I actually came to the idea of using color lists while working on another project, in which I was coding in C#. When you use the .NET framework, you can choose colors from built-in set, defined in the System.Drawing namespace.

I wrote a small procedure to extract all of those built-in colors, and build two lists at the same time: one for the color names, and one for the RGB ShapeSheet formulas. Programmers might be interested in this snippet, non-coders can skip right over it:

This allows me to define the logic for looking-up and indexing color names and color values in one central place. I can then re-use it multiple times without proliferating copies of that logic. If you’ve read User-defined ShapeSheet Functions in Visio 2007, then you’ll understand. If not, go have a look!

To get four different color values, I invoke the custom function like this:

There are four corresponding Shape Data cells that expose the data to the user: Prop.color1, Prop.color2, Prop.color3 and Prop.color4. You can see that by using EVALCELL to call the custom function, I only have to change one argument.

If I ever modify my color-lookup-logic, I will only have to change one formula: User.colorFunction. Pretty neat, and only available in Visio 2007 or later, by the way.

Accessing the Custom Colors from Sub-shapes

If you set up these User-cells and Prop-cells in a group, then it is easy to have sub-shapes reference the values.

Suppose your group has an ID of 5. This means your group can be referenced by the name “Sheet.5”.

Sub-shapes in the group can then refer to Sheet.5!User.color1, Sheet.5!User.color2 and so on. To control the color of a sub-shape, then, you might set this formula:

FillForegnd = Sheet.5!User.color1

or even better, if you want the sub-shape to ONLY be color-able via Shape Data:

FillForegnd = GUARD(Sheet.5!User.color1)

The download contains a single shape and a group shape, both armed with big, long drop-down lists of colors, ready for you to use in your own projects, or pick apart and learn from. Have fun!

22 Comments »

That would save so much time, and provides so much more flexibility! Of the various shapes that I’ve provided a color selection option — what a pain to have to code those into the shape sheet manually.

I am thinking of creating some sort of tool or Excel spreadsheet that allows you to easily select sub-sets of those 140 colors so you can easily build the necessary ShapeSheet functions with shorter lists.

After all, how many people need ‘Rosy Brown’ or ‘Thistle’, let alone know what they look like?

Hi Chris,
using Shape Sheet functions for this, is a great idea. I used a method with Color choosing in the Shape-Data window, too, but used the Dependson-Function to change LineColors via SETF, whenever an new color was selected in the Shape-Data-Window.
The Index/Lookup-combination is clever,too. I used many If-Functions. That was OK, when you can only choose between 4 colors, but for 140 colors that would have been akward.
Therefore I’ll use your method in the future.

But what impressed me most, was a small thing: The Color-Symbol in the Kontextmenu of the shape. How did you know the nessesary ButtonFace number? Is there a list with pictures and IDs on the internet somewhere? Or is there an easy way to find Visios Icons and their number?

The ButtonFace IDs is something I have wanted to write about for a while, but there are a few things that I still wanted to research.

You can set up a shape that will let you rapidly explore buttons faces. Smart Tags can show the buttons all the time, so you don’t always have to right-click the shape. Try this:

1. Insert a Smart Tag row
2. Set DisplayMode = 2 (always display)
3. Set ButtonFace = 0
4. Insert > Field and set a Custom Formula = SmartTags.Row_1.ButtonFace to display the current button face in the shape’s text
5. Set EventDrop = =SETF(GetRef(SmartTags.Row_1.ButtonFace),SmartTags.Row_1.ButtonFace+1)
6. Use Ctrl + Drag to copy a shape, then hit F4 to repeat the copy the shape over and over and over

You’ll now have an array of shapes with incremented ButtonFace ids, and you should be able to easily see which icon corresponds to which number.

Hi Chris,
using Smart Tags is a good idea. I pushed it a little further:

Used Step 1-4 from above to create a shape.
I created a new stencil and called it ButtonFace.
Then I put the Shape in the new stencil as a new master and called it BF.
Then I wrote this little VBA-Sub which constructs a small table with ButtonFaceIds from 0 to 1000.

I just want to create a new shape with the function you described here. I remembered your article and tried it out. At the moment I use the Visio 2010 beta and the result was: Black. All the time the shape was colored black.
Hm, with Visio 2003 I thought it should be better. But: Black…

Now I downloaded your file and what happens: black

When I refer to the cell User.Color Visio always puts a “0” as value?!?!
Do you know what the problem can be?

Sorry, but your trick doesn’t work in Visio 2010 (Russian). A element’s color has changed to black after I choose another color in a list. In the same time value in user’s cell containing a color (for example, User.color1) has a right value, but value ‘FillForegnd’ = 0!

It’s probably due to you having Dutch(?) regional settings, where the normal list separator is a semi-colon instead of a comma.

It’s something like you are getting RGB(255,0,0) returned from index/lookup ShapeSheet logic, but you really need RGB(255;0;0). Although the ShapeSheet should really be “universal” (=USA), there seems to be a problem in this area.

See my comment above, on February 6, 2013. If I had more time, I would roll that into the main article…

Hi Guys,
I was also fighting with the problems with the german version;
the workaround described above February 6 2013 is ok, but requires a lot of modifications to the shapesheet.
I think the easiest solution is the one described in the link April 21 2010 (by Stefan); this way you only have to add the Substitute function to the totally 9 user defined cells in the shapesheets;
so e.g. instead of
=EVALCELL(User.colorFunction,”chosenColorName”,Prop.color1))
you just have to write
=SUBSTITUTE(EVALCELL(User.colorFunction,”chosenColorName”,Prop.color1),”,”,LISTSEP())

and the “choose colors with Shape Data Fields” also works with German installation.