Simplifying Visio Automation with C# 3.0, Linq, and delegates
I saw a great post by the Visio Guy today ( Save Time & Simplify Your VBA Code With CallByName ) and thought it would be a good opportunity to demonstrate some of the simplification that you can achieve with the new features in C# 3.0 and using the VisioAutoExt library.
The point of his post was that you could use CallByName in VBA to reuse an algorithm – in this case applying a function to each element in a set of shapes. The sample code below does the same thing, but I hope you see how elegant it is in C# 3.0
Key points
- The “using VisioAutomation.Extensions” and “Using System.Linq” statements are critical to making this work.
- The ProcessShapes methods allows you to apply a method to a Visio Shapes collection or any IEnumerable set of shapes.
To use the ProcessShapes method
ProcessShapes( page.Shapes , SomeMethod );
or you can even do this …
ProcessShapes( page.Shapes , shape => { shape.SetFillForefroundColor( System.Drawing.Red ) } );
The FullSource Code
Below I’ve translated the source code from his original post into the C# 3.0 equivalent.
using System;
using System.Collections.Generic;
using System.Linq;
using IVisio = Microsoft.Office.Interop.Visio;
using VisioAutomation.Extensions;
namespace VisioAutomationSamples
{
public partial class Demo
{
public static void sample4()
{
var visapp = new Microsoft.Office.Interop.Visio.ApplicationClass();
var doc = visapp.Documents.Add(new Isotope.Drawing.Size(10, 10));
var page = doc.Pages[1];
draw_stuff(page);
ProcessShapes(page.Shapes, MakeRed );
ProcessShapes(page.Shapes, RotateLeft );
ProcessShapes(page.Shapes, SetText );
}
public static void ProcessShapes( IEnumerable<IVisio.Shape> shapes , Action<IVisio.Shape> func)
{
foreach (var shape in shapes)
{
func(shape);
}
}
public static void ProcessShapes( IVisio.Shapes shapes, Action<IVisio.Shape> func)
{
foreach (IVisio.Shape shape in shapes)
{
func(shape);
}
}
public static void draw_stuff( IVisio.Page page)
{
// Draw some rectangles
int num_rows = 3;
int num_cols = 3;
var grid = new Isotope.Drawing.LayoutGrid(page.GetRect(), num_rows, num_cols, false);
var cells = grid.EnumCells(num_rows, num_cols);
var shapes = cells.Select(c => page.DrawRectangle(c.rect)).ToList();
}
public static void MakeRed( IVisio.Shape shape )
{
shape.SetFillForegroundColor( System.Drawing.Color.Red );
}
public static void RotateLeft( IVisio.Shape shape )
{
if ( shape.OneD == VisioAutomation.VisUtil.BoolToShort(false) )
{
double angle =
shape.CellsSRC(VisioAutomation.VisProps.ShapeRotation)
.get_Result(IVisio.VisUnitCodes.visDegrees);
double new_angle = angle + (45.0*System.Math.PI/180.0);
shape.CellsSRC(VisioAutomation.VisProps.ShapeRotation).ResultIU = new_angle;
}
}
public static void SetText(IVisio.Shape shape)
{
shape.Text = "Hello World";
}
}
}