Automating Visio with IronPython to Generate nice, consistent gradients
A needed to generate a series of consistent gradients in Visio this week for some diagrams. It's tedious to do this manually so I automated the task with IronPython 1.1.
Running this command line:
Produces launches Visio to 2007 produce this output.
The attached package with source is here: msdn_saveenr-2007-07-07-Automating Visio with IronPython.zip
It includes three files:
- AutoVisio.Dll - where I wrote a lot of code to simplify the use of Visio from other managed code languages
- Isotope.Color.Dll - some simple colorspace utilities (RGB, HSB, HSL)
- gradient_explorer.py - the code that generates the gradients
gradient_explorer uses a seed color to generate a sequence of gradients automatically. Using different seed colors results in different colors. Examples are below:
Below is the gradient explorer source
"""
gradient_explorer
USAGE
-----
Run script. It will start visio and draw a series of gradients based on the seed_color.
HOW TO GET DIFFERENT GRADIENTS
------------------------------
-alter the seed_color
-play with the modify_color_x functions
HISTORY
-------
2007-07-06
Updated to produce multiple rows
2007-07-05
Initial Version
"""
import sys
import clr
import System
clr.AddReference("System.Drawing")
import System.Drawing
clr.AddReference("Microsoft.Office.Interop.Visio")
from Microsoft.Office.Interop import Visio
clr.AddReferenceToFileAndPath("AutoVisio.dll")
import AutoVisio
clr.AddReferenceToFileAndPath("Isotope.Color.dll")
import Isotope.Color
def modify_color_1( input_hsl ) :
return input_hsl.Add( 1.1, -input_hsl.Saturation , -0.05 )
def modify_color_2( input_hsl ) :
return input_hsl.Add( 0.0, 0.0 , -0.1 )
def modify_color_3( input_hsl ) :
return input_hsl.Add( 0.0, 0.0 , -0.2 )
def modify_color_4( input_hsl ) :
return input_hsl.Add( 0.0, 0.0 , -0.3 )
def modify_color_5( input_hsl ) :
return input_hsl.Add( 0.02, 0.1 , -0.2 )
def modify_color_6( input_hsl ) :
print input_hsl
return input_hsl.Add( -0.02, 0.1 , -0.2 )
text_color_black = Isotope.Color.HSLColor.FromWebColorString("#000000")
text_color_white = Isotope.Color.HSLColor.FromWebColorString("#ffffff")
def calc_text_color( start_color, end_color ) :
mid_lum = ((start_color.Luminance+ end_color.Luminance) /2.0)
if ( mid_lum>0.6) :
text_color = text_color_black
else :
text_color = text_color_white
return text_color
def explore_gradients():
seed_color = Isotope.Color.HSLColor.FromWebColorString( "#ff0000" )
#seed_color = Isotope.Color.HSLColor.FromRGBBytes( 193,202,221)
#seed_color = Isotope.Color.HSLColor.FromRGBBytes( 249,185,81)
#seed_color = Isotope.Color.HSLColor.FromRGBBytes( 171,205,137)
# number of blocks in each row
steps = 20
# 36 is a gradial gradient that begins in the upper left
grad_pattern_id = 36
# One row will be drawn for each color function in this list
color_funcs = [ modify_color_1, modify_color_2, modify_color_3 , modify_color_4 , modify_color_5, modify_color_6 ]
grad_rows = []
# caclculate an evenly spaced set of luminances starting from 0.0 to 1.0
luminances = [ v*(1.0/(steps-1)) for v in xrange(steps) ]
# using the seed color generate the starting color used for each row
row_start_colors= [ Isotope.Color.HSLColor( seed_color.Hue, seed_color.Saturation, lum ) for lum in luminances ]
# generate the colors for each row
# each row will contain a tuple of (start,end) colors
for color_func in color_funcs :
row_end_colors = [ color_func(start_color) for start_color in row_start_colors ]
grad_rows.append( zip( row_start_colors, row_end_colors) )
# for debugging, print out all the color strings before drawing begins
for grad_colors in grad_rows :
for i,grad_color in enumerate(grad_colors):
print i+1, grad_color[0].ToWebColorString(), "->", grad_color[1].ToWebColorString()
print
num_cols = steps
num_rows = len( grad_rows )
# each cell is one inch in width and height
# the page has a 1 inch border on each of the four sides
page_width = 2 + num_cols
page_height = 2 + num_rows
page_size = AutoVisio.Size( page_width ,page_height)
# Launch Visio to do the drawing
app = AutoVisio.VisioLib.StartVisio()
# Create a document with an initial empty page
doc = AutoVisio.VisioLib.CreateDocument( app, page_size )
# Locate that first page
page = doc.Pages[1]
# for each row draw the gradients
for grad_row_index, grad_colors in enumerate(grad_rows) :
for n,grad_color in enumerate(grad_colors) :
rect = AutoVisio.Rect( 1+n,1+grad_row_index,1+n+1,1+grad_row_index+1)
start_color,end_color = grad_color
# find the right text color that is visible on the gradient
text_color = calc_text_color( start_color, end_color )
# Draw the shape
shape= AutoVisio.VisioLib.DrawRectangle( page, rect )
# Set the shape attributes
AutoVisio.VisioLib.SetFillGradient( shape ,
grad_pattern_id,
start_color.ToSystemDrawingColor(),
end_color.ToSystemDrawingColor() )
AutoVisio.VisioLib.SetLinePattern( shape, 0 )
# for debugging, can set the text content of the shape
# shape.Text = str( grad_pattern_id )
# AutoVisio.VisioLib.SetTextColor( shape, text_color.ToSystemDrawingColor() )
if ( __name__ == '__main__' ) :
explore_gradients()