I hear quite often the question; “How do I do something in Visio programmatically?” Since many of those requests pertain to flowcharts and organizational charts, I thought I’d conjure up a fairly simple example that illustrates the creation of a flowchart with Visual Basic for Applications (VBA) code.
This isn’t the simplest example, because I thought it would be important to show how a decision-branch might be handled.
Nevertheless, it doesn’t stray too far from the core concepts that you’ll need to understand in order to automate Visio diagram creation:
- Open a template
- Get stencils and master objects
- Drop shapes on the page
- Set shape text and Custom Properties
- Connect the shapes
If you inspect the code, you’ll see that the program flow directly follows the outline above.
When you run the code, you’ll the code will create a simple flowchart that looks something like this:
The decision step is artificially created at step #3. By artificially, I mean that there is no data-source or supreme ethereal logic that dictates “that a decision should be here.” It’s simply the product of our defined constant:
Const DecisionStepNumber% = 3
which you can change at your leisure. Just be sure that it is at least 2 less than NumShapes, or you will run in to errors!
The more complicated bits involve the decision branch. This unfortunately required some If and Select Case blocks that clutter the code to some extent. These decision blocks control how the connections are programmed, to which shapes the connections are glued, how x- and y-offsets are specified, and what the text on the connectors should be. For instance, the “No” connector connects to the right-connection point of the Decision shape, whereas the rest of the connections connect dynamically to the shapes.
Hopefully the comments in the code will explain this more clearly. Below, I’ve included a link to a Visio diagram with more instructions, a convenient “Draw” button in place, and a ready-to-go VBA project that you can inspect and alter to your liking!
Here’s the code:
Sub CreateFlowchart() '// Step 1: get the flowchart template and stencil. '// ------------------------------------------------- '// Define some name-constants. '// We use 'universal names', which are usually U.S. '// english, or short filenames, and will work for '// non-english versions of Visio: Const FlowchartTemplateName$ = "Basic Flowchart.vst" Const FlowchartStencilName$ = "BASFLO_M.VSS" Const MasterProcessName$ = "Process" Const MasterDecisionName$ = "Decision" '// Open a new document: Dim doc As Visio.Document Dim docFlowTemplate As Visio.Document Dim docFlowStencil As Visio.Document Set docFlowTemplate = Visio.Documents. _ Add(FlowchartTemplateName) '// Search open documents for our flowchart stencil: For Each doc In Visio.Documents If (doc.Name = FlowchartStencilName) Then Set docFlowStencil = doc Exit For End If Next Set doc = Nothing '// Step 2: get the masters and connect. '// ------------------------------------------------ Dim mstProcess As Visio.Master Dim mstDecision As Visio.Master Dim conn As Variant '//...note - not a Visio.Master '// Get masters for Process and Decision: Set mstProcess = _ docFlowStencil.Masters.ItemU(MasterProcessName) Set mstDecision = _ docFlowStencil.Masters.ItemU(MasterDecisionName) '// Get the built-in connector object. Note, it's '// not typed as a master! Set conn = Visio.Application.ConnectorToolDataObject '// Step 3: Drop the masters '// ----------------------------------------------- Const NumShapes% = 7 '// Test case to illustrate adding a decision shape. '// Must be at least 2 less than NumShapes. Const DecisionStepNumber% = 3 Dim i As Integer Dim x As Double, y As Double '//...drop locations Const dx# = 1.5 Const dy# = 1 Dim pg As Visio.Page Dim shpNew As Visio.Shape Dim shpLast As Visio.Shape Dim shpConn As Visio.Shape Dim shpDec As Visio.Shape '// We'll draw on the first page of the document, '// which is probably the only page in the document! Set pg = docFlowTemplate.Pages.Item(1) '// Note: if we use auto-layout (see end of this '// procedure), then x- and y aren't super-critical. '// However, some rough positioning will help auto- '// layout to do a better job. '// Get the center, top of the page: x = pg.PageSheet.CellsU("PageWidth").ResultIU / 2 y = pg.PageSheet.CellsU("PageHeight").ResultIU - 1 For i = 1 To NumShapes '// Drop a new shape - either a Process or a '// Decision shape: If i = DecisionStepNumber Then Set shpNew = pg.Drop(mstDecision, x, y) shpNew.Text = i & "?" Set shpDec = shpNew '//...save dec. for later Else Set shpNew = pg.Drop(mstProcess, x, y) shpNew.Text = "Do Step " & i End If '// Set custom properties, illustrating '// two methods: ResultIU and Result: shpNew.Cells(& quot;Prop.Cost").ResultIU = i shpNew.Cells(& quot;Prop.Duration"). Result(Visio.VisUnitCodes.visElapsedHour) = i '// Connect shapes: If (i & lt;> 1) Then '// Drop a connector on the page: Set shpConn = pg.Drop(conn, 0, 0) '// Glue the connector to shpLast and shpNew: '// Note about glueing: By glueing to the PinX '// or PinY of a shape, we get 'Dynamic Glue' '// automatically. For the 'No' on the Decision '// shape, we specifically glue to the '// connection point on the right side of '// the shape. '// First, the Begin cell of the connector, '// glued conditionally to shpLast: If (i = DecisionStepNumber + 1) Then '// Glue to the right side: Call shpConn.CellsU(& quot;BeginX"). GlueTo(shpDec.CellsU(& quot;Connections.X2")) Else '// Glue dynamically: Call shpConn.CellsU(& quot;BeginX"). GlueTo(shpLast.CellsU(& quot;PinX")) End If '// Second, the End cell of the connector, '// glued dynamically to shpNew: Call shpConn.CellsU(& quot;EndX"). GlueTo(shpNew.CellsU(& quot;PinX")) End If '// Set-up variables for the next round. Set shpLast = shpNew '// x, y, and shpLast depend on our '// decision-branch: Select Case i Case DecisionStepNumber x = x + dx Case (DecisionStepNumber + 1) x = x - dx y = y - dy shpConn.Text = "No" Set shpLast = shpDec Case Else y = y - dy End Select Next i '// Step 4: Layout the shapes and deselect. '// ------------------------------------------------ '// Page-layout is one simple call, but look and '// see what our x and y drops have done first, '// then uncomment the next line: 'pg.Layout '// Deselect all shapes, so it looks better: Visio.ActiveWindow.DeselectAll '// Tile the windows so the user doesn't freak out! Call Visio.Windows. Arrange(Visio.visArrangeTileVertical) End Sub
Interesting flowchart links:
- CVF 3.0 Code Visual to Flowchart. A source-code flowcharting tool from Fatesoft.
- Fast Flowcharts An article from Mai-lan’s blog about using Visio’s mutli-form “Flowchart shapes” master.
- Unistep Software for animating process flow, uml sequence and other types of Visio flowcharts.
- John Marshall’s excellent collection of Visio 3rd Party links. Search for ‘flow’ and you’ll get lots of results!
- A nice user tutorial from Informit.com on creating Visio flowcharts and using custom properties, but also dabbles in ShapeSheet and report-generation.
eLiz says
Hallo Chris,
Lob für die klasse Seite und die hilfreichen Tipps immer.
Ich habe hier die Automation für ein Flowchart gefunden und bin gerade auf der Suche fÜr ein Ähnliches Problem. Ich möchte noch einen Schritt weiter gehen und die nach dem Flowchart (fÜr einen Applikation) entstandenen Wireframes automatisch als Miniaturen in einem Screenflow abbilden. Momentan muss jede Seite einzeln in eine externe Visio-Datei gebettet werden.
Gibts da einen Trick -> Ohne VBA zu können?
vielen Dank und weiter so
eLiz
Visio Guy says
Hallo Eliz,
Wie ich das verstehe, du moechtest jedes Blatt eines Dokus als Shape in einem Flussdiagramm verwenden.
Ich wuerde das so machen:
1. Ein ganzes Blatt kopieren
2. Als metafile paste-n. (Ueber die Menues: Bearbeiten > Paste Special > Als Picture)
3. Als metafile kann mann das Resultat als Shape benutzen. Ist sehr einfach klein anzupassen.
Hoffentlich hilft’s!
– Chris
Dirk says
This works for connecting one shape to one other shape. How would you create a flow diagram that has the following. When step 1 is done, steps 2, 3 and 4 can all start. They are not dependant on each other.
Visio Guy says
Hey Dirk,
Look at the decision diamnond — “3?”. There are two connectors coming out of that going to different shapes. Is that what you are talking about?
Or perhaps you need to use a “Parallel mode” shape on the “Basic Flowchart Shapes” stencil. This shape has four built-in connectors that change the automation picture slightly. Attaching them per-code is a little bit different. Let me know if that’s what you want to use.
– Chris
Dirk says
Chris,
Using you diagram, if I want to connect step 4 to step 5 how do I connect them without having to save the shape information like in “Set shpDec = shpNew ‘// save dec. for later”. In my application I have a few hundred shapes to connect and would like to not have to store the shape information of all of them in case I need it later to connect two shapes.
Visio Guy says
Hi Dirk,
You would have to have some sort of way to identify the shape on the Visio page. One way to do this is to save a shape’s ID (ala: visShp.ID — integer) That’s perhaps a bit less overhead than keeping the whole shape object around.
You can then find the shape like this: visPg.Shapes.Item(id)
Or you could search all the shapes on a page and find their text using the visShp.Text property.
Hope this gets you started anyway…
– Chris
Sean McPoland says
Wonderful….
just what I’ve been looking for
regards
Sean
Thirumal says
Unable to download CreateFlowchart.zip.
Appreciate, if you could email this zip file, so that I can test it and use.
Thanks.
Thiru
Visio Guy says
Hey Thirumal,
Try it again. There was a case-sensitive problem with the link. Should work now.
– Chris
Rakesh Kumar says
Hi, nice example.
I am working on a .NET application that uses Visio to show flowcharts. I want the dynamic grids to be seen once a shape is dropped. I am doing the following but it doesn’t work.
[code]
Page.Document.SnapEnabled = true;
Page.Document.GlueEnabled = true;
Page.Document.DynamicGridEnabled = true;
Page.Document.GlueSettings = VisGlueSettings.visGlueToGuides |
VisGlueSettings.visGlueToConnectionPoints;
Page.Document.SnapSettings
VisSnapSettings.visSnapToGrid | VisSnapSettings.visSnapToGeometry |
VisSnapSettings.visSnapToGuides | VisSnapSettings.visSnapToRulerSubdivisions |
VisSnapSettings.visSnapToConnectionPoints;
Page.Document.SnapExtensions
VisSnapExtensions.visSnapExtCenterAxes | VisSnapExtensions.visSnapExtLinearExtension;
[/code]
Visio Guy says
Hi RK,
Looks fairly good to me. I’m not sure what your “Page” object is, and it appears you are missing a few “=”, but this might just be the blog software…?
I tried this slight-modification of your code, and it seemed to work. Note the addition of: pg.Application.Settings.DrawingAids = true; to get the drawing aids to function.
//…
[code]
using Vis = Microsoft.Office.Interop.Visio;
//…
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
this.axDrawingControl1.Src = ""; //Basic Flowchart.vst";
Vis.Page pg = this.axDrawingControl1.Window.PageAsObj;
// Make some sample shapes to test if the dynamic grid is working:
pg.DrawRectangle(2, 2, 3, 2.5);
pg.DrawRectangle(2.5, 4, 3.5, 4.5);
pg.DrawLine(5, 5, 7, 7);
pg.Document.SnapEnabled = true;
pg.Document.GlueEnabled = true;
pg.Document.DynamicGridEnabled = true;
pg.Document.GlueSettings = Vis.VisGlueSettings.visGlueToGuides |
Vis.VisGlueSettings.visGlueToConnectionPoints;
pg.Document.SnapSettings =
Vis.VisSnapSettings.visSnapToGrid | Vis.VisSnapSettings.visSnapToGeometry |
Vis.VisSnapSettings.visSnapToGuides | Vis.VisSnapSettings.visSnapToRulerSubdivisions |
Vis.VisSnapSettings.visSnapToConnectionPoints;
pg.Document.SnapExtensions =
Vis.VisSnapExtensions.visSnapExtCenterAxes | Vis.VisSnapExtensions.visSnapExtLinearExtension;
// Turn on the Drawing Aids as well for line extensions, etc:
pg.Application.Settings.DrawingAids = true;
}
}
[/code]
Rakesh Kumar says
Yeah, it’s working.
I missed – pg.Application.Settings.DrawingAids = true
Thanks
Giancarlo says
Does anybody know or have an idea if this can be implemented with a database easily? What I’m trying to do is create a drawing from a database of relational tables for requirements gathering. So for a example a User Requirement might fulfill 1-to-many Business Requirements, and I have an table in between to show this relationship. So it looks like this:
[BusinessRequirement]—-[BusinessToUserLink]—-[UserRequirement]
An example of the drawing might be:
B1–U1
|______U2
|__________U3
How could I use Visio to create a visual representation of the database RECORDS, not the table design. Thanks.
Giancarlo says
You can also have:
B2——
|
B1–U1 |
|______U2
|__________U3
Ter says
Hello,
I came across an article that talked about Visio 2000 being able to import a .csv file from the File-Open and would create a Flowchart for you.
The data in the excel file would look like the following:
Shape 6.1 Global Office Locations
Shape 6.2 Media Relations
Shape 6.3 Business Proposals
Shape 10 Manager Profile
Link 1 2
Link 1 3
Link 1 4
I am using Visio 2003 and it dosn’t support this ? How can i do something similar using visio 2003 ?
-ter
Harvey says
Great work Visio Guy – Thanx.
Ter, could you post the link you found regarding .csv imports?
I’ve written some code to extract the dependencies from Microsft Access Queries and would like to integrate this into a Visio Flow Chart program.
—-> ——> ——-> ——-
| | ^ |
| | | |
Left Join Left Join Right Join Inner Join
| | | |
V V | |
Of course this diagram is very simplistic compared to the 300+ interdependant objects in my Database – this is why a flow chart is necessary.
The new Object Dependency tool in Access 2007 is helpful but not what I need. I need to see the entire chart relativity. For instance, in the above – Query 5 has a source as does Query 4 and this relationship would need to be charted as well.
Happy hunting,
Harvey
Harvey says
oops, dont put objects inside < or and > or it deletes them 🙁
and the white space is removed 🙁
Trying again with the code tag:
—-> ——> ——-> ——->
| | ^ |
| | | |
Left Join LJ RJ Inner Join
| | | |
V V | |
Harvey says
You may as well delete the comments they bear little meaning without the diagram.
🙁
Harvey says
Ter, I found this link:
http://office.microsoft.com/en-us/visio/HA010857571033.aspx
🙁 no more TXT or CSV in 2003 onward
Visio Guy says
CVS People,
Go to John Marshall’s Visio page, under VBA Information. Search the page for the “Read Text” example. This might get you started. If I had any brains I’d write a CVS importer and sell it as Donate-Ware for $7.50 🙂
Sourabh says
Hi Chris
Your FC is looking wonderful. I got what I exactly want.
I have two questions:
1. I had download your utility but when I tried to run it, says that the macros are not enabled. Contact the download site.
2. If I want to first draw the Visio Flowchart and then I want to link or play with those process boxes using VB, Do you know how to do it? If yes then please send one sort of utility which works in this way.
Thanks
–Sourabh
SHAJIPD says
Hi,
I would like to know; how can create Container type VISIO SHAPE JUST LIKE GANTT CHART, WHICH HAS CHILD ELEMENTS ATTACHED TO PARENT FRAME. Can any one can guide me in this……..
Thanks N Advance
SHAJI
Silly Questions says
Hello Visio Guy,
My team and I are just starting to use Visio. Some of us have never used it before, and we are having a hard time finding the meanings behind the shapes, for example what is a paper tape, a card, a loop limit? We have looked in two different books and no answers. Are these terms that are commonly used in a different world then ours? Or is there a place where I can find out this information? Thank you for your help.
Nilesh says
hello,
I want to add custom properties to visio shape. i get some idea using this VB code, but in C# its not working.
Can anybody tell me, how to add custom properties in C#.
Thanks,
Nilesh.
John says
The code you’ve got here works wonderfully, and I can tie to to a database using an array variable to populate the box names. However, how can I accommodate multiple decisions in a single flowchart (i.e., box 1 flows to box 2, which is a decision. No terminates, and yes goes to box 4, which is another decision. No for that decision terminates, and yes continues to box 5. Box 5 is another decision. No flows to Box 6, and Yes skips Box 6 and goes to 7, where Box 6 also flows.
How much more code would I need to make that happen?
Swimlane Flowcharts says
Other than using the db wizards I haven’t done this kind of automation but I can see it would be worthwhile. Looks like I have something else to read about.
Chaitanya says
Hi,
> I have an excel spreadsheet with more than 1000 lines. Basically the
> spreadheet shows all the connections between my network elements, i.e.:Site A
> connects to Site B with a Capacity C.
> I want to make a visio drawing showing all the network connections between
> all the sites and show also the capacity for each connection. The site will
> be represented by boxes and the connections will be represented by lines with
> a text showing the capacity.
> Is there anyway that I can automate this in visio using my excel spreadheet.
> I’m not very familiar with visio. I only do simple diagrams manually. If I
> do this task manually, it will take me a long time so I would really
> appreciate it if you can provide me tips on how to automate this.
> Thanks
Chaitanya
Sam says
Chaitanya,
Wondering if you get any solutions for your case. I have kind of same situation and love to know how you did it.
– Sam
wasif ali says
I am using Microsoft Visio as a COM object in my C# application. I want to auto arrange shapes on a Visio page. What should I code for this task? The shapes are database entities.
userView.Shapes.SomeMethod();
userView is name of COM object but what should SomeMethod be?
Visio Guy says
Hi Wasif,
Try using the Layout method on a selection or a page.
Ie:
visPg.Layout;
visApp.ActiveWindow.Selection.Layout;
Al says
Do you by any chance have code that creates an OrgChart from Excel of a database? Appreciate you.
AL
genoki says
I created org chart with 300+ departments eg one Visio file with one dept org chart per page of 300+ pages .. how can I create a separate Visio file for each dept/page? I can use VBA. What would be a good process to follow? I don’t wnat to create each dept separate as that will take a very long time and this process will be repeated as people/positions come and go.
Swamy says
Hey visio guy,
i’m trying to create network diagram using c# based on your idea.
I like to change the page orientation from horizontal to vertical. can this be done through c# program.
thanks in advance
monuogbe says
Hey VisioGuy,
I’m looking for a way to generate flowcharts from data and “Create Flowchart.vbs” is my starting point. Thanks for the hard work.
I’m using Visio 2010 professional in Developer mode. However, when I run the code, from the button or from the VBA console, I get the following error:
Run-time error ‘-2032466967 (86db03e9)’
Unexpected end of file.
When I hit the “Debug” button, the code points to:
shpNew.Cells(“Prop.Duration”). _
Result(Visio.VisUnitCodes.visElapsedHour) = i
Any idea what I’m doing wrong?
Thanks again.
Visio Guy says
@monuogbe,
Does your target shape, shpNew really have a Prop.Duration? Remember, shape data fields have a Label and a (row) Name property. “Prop.Duration” is the name. Default names are, e.g. Row_1, Row_2, Row_3.
Name is usually hidden from the user, and Label is displayed. But when you use automation, you have to work with Name. With Developer mode on, the Define Shape Data dialog shows both Name and Label. Generally, you should make them the same, except Name can’t have spaces or special characters, so you might do something like this:
Label: Task Duration
Name: Task_Duration
Rod Visio says
Hi! nice sample code,
I have run it on Visio 2013 and noticed some modifications (two) to do to run it without the Run-time error and the error 91.
you need to change the “BASFLO_M.VSS” with “BASFLO_M.VSSX” and notice that in Visio 2013 the flowchart shape have not the Duration data on their shape data (this last remark is valid for the 2010 version).
Now, I going beyond to Create Visio Flowcharts Programmatically based on Excel sheet.
Please Chris,
what is the role of “$” and “%” placed at the end of the variable
Const FlowchartTemplateName$ = “Basic Flowchart.vst”
Const NumShapes% = 7
Best REgards,
Visio Guy says
% and # and $ are used to give constants types of integer, double or string.
In VB.NET, you can declare constants with types:
Const PI as double = 3.14159265358
In VBA, you can’t specify the type with a reserved word. But you can do this:
Const PI# = 3.14159265358
Now, you can use PI or PI# in your code, it doesn’t matter as far as I know.
Similarly:
Const BlogTitle$ = “VisGuy”
Dim s as String
s = “Hello ” & BlogTitle$
Rod Visio says
Thanks so much for the explanation!
tejfl says
Hi,
I would like to generate flow chart diagrams from my c# project. How can I do it automatically with Visio? I have ~ 100 functions, so I do not want to do it by hand.
Thank you for your answer.
Adnan Haider says
Hi Visio Guy,
I am doing a project for automation of entity relationship diagram in c-sharp , and I have extracted entities and their relationship from text of data requirement, and I am required to use Visio for displaying the ERD. How can I put entities in a Chen’s or crow’s foot template. And how to connect the entities with relations? Any help will be appreciated.
Thanks for your answer in advance.
Kaustubh says
Hi Visio Guy,
I am adding a shape on a visio page programmatically using X and Y positions. But the problem is when the visio document page orientation is landscape, shape is placed on a different position.
I want to know if there is any way to know the orientation of page programmatically so that I can place the shape accordingly.
I am working in C#.Net
Thanks.
Kaustubh
Visio Guy says
Hey Kaustubh,
There’s no “horizontal” or “vertical” bit associated with a page, since pages can have any orientation, but you can look at the dimensions:
[vb]
Dim pw As Double, ph As Double
Dim pg As Visio.Page
Set pg = Visio.ActivePage
pw = pg.PageSheet.CellsU("PageWidth").ResultIU ‘//…width in inches
ph = pg.PageSheet.CellsU("PageHeight").ResultIU ‘//…height in inches
If (pw > ph) Then
Debug.Print "Landscape-ish"
Else If (ph < pw)
Debug.Print "Portrait-ish"
Else ‘//…pw = ph
Debug.Print "Square"
End If
[/vb]
Vik says
Hi,
I am looking to generate a Flow chart directly from Excel. However I am unable to.
I do not know any programming language?
Using Vision 2010 and Excel 2013.
Is there any way I can generate it directly from the excel (Like some internal function or feature)
Or I have to wirte a code and than do?
Regards,
Vik
Ankur says
HI,
I also want to implement the same which Vik and Chaitanya wants to do .
Request you to please help us in the same
Ankur says
Set docFlowTemplate = Visio.Documents. _
Add(FlowchartTemplateName)
on this line .
I am facing error
ActiveX component can’t create object
Run Time Error:429
thanks,
Ankur
Srinivasan Manuel says
Hi,
Is it possible to generate a cross functional flowchart by importing data from excel using vba in visio 2013, if yes request you all to share the code
erodrigue says
Programmatically create Visio flowchart based on Excel Data.
This article(Create Visio Flowcharts Programmatically), the code, is one of the most useful code that many programmers have used, modified, or which inspired to create an automated action in visio.
I have created some automation actions and would like to share it with you Guys
– Programmatically create Visio flowchart based on Excel Data
https://www.linkedin.com/groups/63136/63136-6041546383306031106
– programmatically create Organization Chart from Excel data
https://www.linkedin.com/groups/63136/63136-5914794546083954688
– Interactive Electrical diagram – Power of ShapeSheet
https://www.linkedin.com/groups/63136/63136-5947809319981445120
Have a programming good day!!
Ekoue
Jeffrey Brown says
Hi Visio Guy, the download link doesn’t seem to be working.
Visio Guy says
Hi Jeffrey, thanks for the heads-up. I had forgot to check the “redirect” button for the download. It should take you to OneDrive now, where the download will start.