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";
        }

    }

}