Welcome to MSDN Blogs Sign in | Join | Help

C# and Currying – a Concrete example with Visio

In a tidy bit of paralipsis, I’m not going to mention “closures”, “currying”, or “partial function application” again. Instead, I will provide a real-world example of what you can do with C# 3.0 and how it can help solve your problems.

I will use Visio in this example because I am familiar with writing code to automate it, but you won’t need any knowledge about Visio to understand this post.

Let’s start off what the output I want. Simply this will be a rectangle with a circular gradient fill that goes from red to blue:

 

image

 

If I manually draw this in Visio 2007 it will look like this:

 

image

Now, what I want to do is to programmatically draw this shape instead of manually drawing it. So I write this code:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IVisio = Microsoft.Office.Interop.Visio;

namespace DemoCurrying
{
    class Program
    {
        static void Main(string[] args)
        {
            var visapp = new Microsoft.Office.Interop.Visio.ApplicationClass();
            var doc = visapp.Documents.Add("");
            var page = visapp.ActivePage;
            var shape1 = page.DrawRectangle(2, 2, 6, 8);
            setfill1(shape1);
        }

        static void setfill1(IVisio.Shape shape)
        {
            // set the fill foreground color to red
            shape.get_CellsSRC(
                (short)IVisio.VisSectionIndices.visSectionObject,
                (short)IVisio.VisRowIndices.visRowFill,
                (short)IVisio.VisCellIndices.visFillForegnd)
                .FormulaU = "RGB(255,0,0)";

            // set the fill background color to blue
            shape.get_CellsSRC(
                (short)IVisio.VisSectionIndices.visSectionObject,
                (short)IVisio.VisRowIndices.visRowFill,
                (short)IVisio.VisCellIndices.visFillBkgnd)
                .FormulaU = "RGB(0,0,255)";

            // set the fill background pattern to radial
            shape.get_CellsSRC(
                (short)IVisio.VisSectionIndices.visSectionObject,
                (short)IVisio.VisRowIndices.visRowFill,
                (short)IVisio.VisCellIndices.visFillPattern)
                .FormulaU = "40";

        }

}

 

Let’s take a moment to examine the setfill1() method and see what we notice about it…

  • It takes a shape object as input
  • it sets the fill foreground to red, the background to blue, and the pattern to a radial fill
  • properties are identified using three values together ( a section index, a row index, and a cell index)
  • All three fill properties share the same section index and row index
  • it uses a method on the shape object called get_CellsSRC
  • it does a lot of casting of enums to “short”
  • It’s very repetitive

Now let’s focus on the repetitive parts. These are highlighted in red…

image

The parts that are not repeated are essentially the cell index and the value for the cell:

  • IVisio.VisCellIndices.visFillForegnd , "RGB(255,0,0)"
  • IVisio.VisCellIndices.visFillBkgnd, "RGB(0,0,255)"
  • IVisio.VisCellIndices.visFillPat, “40”

In generally we don’t want to repeat ourselves in code. What we do want in this case is to minimize our code to the unique parts (the three pairs of values shown above).

So what are our options?

  • Option #1 We could make a new class that helps reduce this effort
  • Option #2 We could create a special helper function called “set_fill_cell_formula”
  • Option #3 We could just have an array of the cell indices and the cell values and use a loop to set them
  • Option #4 We could take advantage of the new functional programming features in C#

I’ll focus on Option #4 only because it will illustrate how to use the new C# features. No criticism is implied against the other options.

In some sense, essentially what we are going to do is create a new function at runtime. This function will “remember” repetitive parts (shape, section index, row index), allowing us to worry about the non-repetitive parts.

Attempt #1

It’s imagine what we want to final code to look like

static void setfill3(IVisio.Shape shape)
{
    var func_set_cell = MAKE_SETCELLFORMULA_WITH_SHAPE_SEC_ROW(shape, IVisio.VisSectionIndices.visSectionObject, IVisio.VisRowIndices.visRowFill);
    func_set_cell(IVisio.VisCellIndices.visFillForegnd, "RGB(255,0,0)"); // set the fill foreground color to red
    func_set_cell(IVisio.VisCellIndices.visFillBkgnd, "RGB(0,0,255)"); //set the fill background color to blue
    func_set_cell(IVisio.VisCellIndices.visFillPattern, "40"); // set the fill background pattern to radial
}

the first line in red creates a new function that “remembers” the repetitive parts (the shape, the section index, and the row index). The new function is stored in a variable called “func_set_cell”

And then in the remaining  three lines we call func_set_cell with just the unique pieces of data to get the same effect

Now what about this method called “MAKE_SETCELLFORMULA_WITH_SHAPE_SEC_ROW”? How can it dynamically create a new function that remembers these parameters?

static Action<IVisio.VisCellIndices, string> MAKE_SETCELLFORMULA_WITH_SHAPE_SEC_ROW(IVisio.Shape shape, IVisio.VisSectionIndices sectionindex, IVisio.VisRowIndices rowindex)
{
    Action<IVisio.VisCellIndices, string> new_action =
        (IVisio.VisCellIndices cellindex, string value) =>
        {
            var cell = shape.get_CellsSRC((short)sectionindex, (short)rowindex, (short)cellindex);
            cell.FormulaU = value;
        }
    ;

    return new_action;
}

Attached Source code

  • The full visual studio project is here: DemoCurrying.zip
  • The project contains the code above and shows several variations that accomplish the same thing

Parting Thoughts

  • I hope this real-world example was useful in showing you the new features in C# 3.0 can help you with your own code
  • I do *NOT* suggest using this pattern at every opportunity. All of the options have pros & cons – the right choice for you is relevant to your circumstances, constraints, and and the problems you are trying to solve
  • For those of you automating Visio in C#, please keep in mind in real-world code I would normally use the Page objects SetFormulas() method which is far more complicated but also far faster than a series of individual calls to retrieve cells and set the formulas
Published Tuesday, January 06, 2009 2:29 PM by saveenr

Attachment(s): DemoCurrying.zip

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# C# and Currying ??? a Concrete example with Visio | Coded Style

# C# and Currying – Looking into Performance

In my previous post, I showed an example of how to use new C# features to simplify your code. In this

Wednesday, January 07, 2009 2:07 PM by Saveen Reddy's blog

# re: C# and Currying – a Concrete example with Visio

the function definition for "MAKE_SETCELLFORMULA_WITH_SEC_ROW()" in your code does not have the "shape" argument while the reference in the "setfill3()" function has it

Thursday, January 08, 2009 1:10 PM by anonymous

# re: C# and Currying – a Concrete example with Visio

Thanks - It was a copy / paste error - I've updated the example. And uploaded the full Visual Studio 2008 project as an attachment to the post

Thursday, January 08, 2009 5:28 PM by saveenr

# re: C# and Currying – a Concrete example with Visio

hi,

i am calling visio application in my c# progam and opening a vsd file in visio but here come the prob i want the shape data to be displayed on wpf form in which visio application is embedded..

in a short...

how can i use the data of a shape in my c# progamme..

please do reply..

i need it urgently

Friday, November 27, 2009 3:14 AM by Dinesh Reddy

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker