Visio and Python

Visio and Python - The Journey.

A while ago I though I'd investigate the Python language and how well it works with Visio. Follow the story ...

First you need to download and install Python.

  1. Go to the Python.org downloads website at https://www.python.org/downloads/ and
  2. Download the current version. I used V3.10.2 with the filename python-3.10.2-amd64.exe. I have no idea why there is the 'amd' in the filename as I have an Intel processor in this computer, but it's all there is and it seems to work, so just go for it.
  3. Run the downloaded .exe file, this will install Python on your computer. When finished you will find a Python entry on the Windows Start menu ...
    Python on Windows Start menu

The new items on the Windows Start menu.

  1. IDLE is the Python IDE (Integrated Development Environment) command line, where you type Python commands etc.
  2. Python 3.10.2 looks like a DOS prompt but is a Python prompt - to be investigated
  3. The Manuals entry is the full Python documentation - and it looks very comprehensive.
  4. The Module Docs entry is the documentaion for all the modules within Python, it opens a page in your web browser.
Python IDLE screen Python prompt screen

A couple of basic tests to make sure it works ...

In the IDLE window type
print("hello")
and it should do so.
We'll try the same in a file. On the IDLE menu select File -> New File,
this opens a new editor screen, type
print("hello again")
menu File -> Save
and save it as test.py in some suitable location like your My Documents folder.
Now do menu Run -> Run Module and it should work.

Next stage - installing the Windows module.

1. At the Windows Start menu select Windows System -> Command Prompt, but do a right-click and select Run as Administrator and type:
python -m pip install pywin32
				

and it should respond with something like:
				Collecting pywin32
				Downloading pywin32-303-cp310-cp310-win_amd64.whl (9.2 MB)
				|████████████████████████████████| 9.2 MB 36 kB/s
				Installing collected packages: pywin32
				Successfully installed pywin32-303
				
2. Still using the command prompt window navigate to where Python scripts are installed. For the above installation for me it is at C:\Users\xxxxxx\AppData\Local\Programs\Python\Python310\Scripts so type cd C:\Users\xxxxxx\AppData\Local\Programs\Python\Python310\Scripts and the prompt should change to
C:\Users\xxxxxx\AppData\Local\Programs\Python\Python310\Scripts>
and type
				python pywin32_postinstall.py -install
and it should respond with
				Parsed arguments are: Namespace(install=True, remove=False, wait=None, silent=False, quiet=False, destination='C:\\Users\\xxxxxx\\AppData\\Local\\Programs\\Python\\Python310\\Lib\\site-packages')
				Copied pythoncom310.dll to C:\WINDOWS\system32\pythoncom310.dll
				Copied pywintypes310.dll to C:\WINDOWS\system32\pywintypes310.dll
				Registered: Python.Interpreter
				Registered: Python.Dictionary
				Registered: Python
				-> Software\Python\PythonCore\3.10\Help[None]=None
				-> Software\Python\PythonCore\3.10\Help\Pythonwin Reference[None]='C:\\Users\\xxxxxx\\AppData\\Local\\Programs\\Python\\Python310\\Lib\\site-packages\\PyWin32.chm'
				Registered help file
				Pythonwin has been registered in context menu
				Shortcut for Pythonwin created
				Shortcut to documentation created
				The pywin32 extensions were successfully installed.
If you now look at the list of Python modules installed (that's the Python Module Docs link from the Start menu) there should be a win32.com package down at the bottom of the list, click that link and .... ah,
				ErrorDuringImport: problem in win32com - ModuleNotFoundError: No module named 'win32api' 
				
Apparently you have to reset the IDLE program to fix this, so close the IDLE window and restart it.
Ah, now the win32com package is in the site-packages section.
On the restarted IDLE menu select File -> New File,
this opens a new editor screen, type

import win32com.client speaker = win32com.client.Dispatch("SAPI.SpVoice") speaker.Speak("It works. Hoorah!")
menu File -> Save
and save it as talk.py in some suitable location like your My Documents folder.
Now do menu Run -> Run Module and it should work. It did, Hooray!
I've put the source code at speak.py
This code came from the SuperUser website at SuperUser question

Let's try to get it to do something with Visio.

We'll open a new Visio page, open a stencil and drop a couple of shapes on the page and set their text.

import win32com.client appVisio = win32com.client.Dispatch("Visio.Application") doc = appVisio.Documents.Add("Basic Diagram.vst") pagObj = doc.Pages.Item(1) stnObj = appVisio.Documents("Basic Shapes.vss") shpObj1 = pagObj.Drop(stnObj.Masters("Square"), 4, 7) shpObj1.Text = "Square text" shpObj2 = pagObj.Drop(stnObj.Masters("Circle"), 5, 4) shpObj2.Text = "Circle text."
It seems that the only template type that can be used is a .vst format template, the XML version .vtx isn't accepted, nor is the newer Visio .vstx format.
Similarly with the stencil formats, only the .vss format is allowed.
The code is at create.py

But usually we want to work on existing files, not create a new one ...

So we need to get the instance of the already open Visio
				import win32com.client
				appVisio = win32com.client.GetObject(Class="Visio.Application")
				
so now let's get the number of open documents (which includes saved and unsaved files and stencils) and print their names:

import win32com.client appVisio = win32com.client.GetObject(Class="Visio.Application") docCount = appVisio.Documents.Count print(docCount) if docCount > 0: for doc in range(0, docCount): print(appVisio.Documents[doc].Name)
The code is at printdocs.py

or, a better way of doing it:

import win32com.client appVisio = win32com.client.GetObject(Class="Visio.Application") docs = appVisio.Documents docCount = docs.Count print(docCount) for doc in docs: print(doc.Name)
The code is at printdocs2.py

Now check whether the item is a document and if so loop through printing the page names


import win32com.client appVisio = win32com.client.GetObject(Class="Visio.Application") docs = appVisio.Documents docCount = docs.Count print(str(docCount) + ' open documents') for doc in docs: print(doc.Name) if doc.type == 1: #visTypeDrawing: pages = doc.Pages pageCount = pages.Count print(str(pageCount) + ' pages') for page in pages: print(' ' + page.Name)
The code is at printpages.py

Next step ...

It seems to work, but this is apparently not the best way to get going with Python and Visio, more exploring to be done ...

Learn more ...

I've setup a wiki for Python with Visio at https://python-and-visio.paulherber.co.uk/