Create a new stencil and populate master shapes from image files via PowerShell?

Started by PinPinPoola, March 21, 2024, 03:58:05 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

PinPinPoola

Has anyone any example PowerShell code to create a new stencil and populate it's master shapes from external image files (.png | .svg)?

I have tried recording a VBA macro and then 'converting' it to Powershell, but I am getting nowhere fast. Even ChatGPT eventually gave up giving suggestions.

I will appreciate any help/suggestions.

Thx
Pin

Surrogate

Hi, Pin!
Quote from: PinPinPoola on March 21, 2024, 03:58:05 PM
I have tried recording a VBA macro and then 'converting' it to Powershell, but I am getting nowhere fast.
Not all actions can be write via macro-recorder!  :(
Right now I have not time for PowerShell coding, but I prepare this VBA-code for 5 minutes...
Sub PicturesImportToDocStencil()
    Dim strPath As String
    Dim strFile As String, fullname As String
    Dim cnt As Integer
    Dim mst As Visio.Master
    Dim wn As Window
    cnt = 0
    strPath = "C:\Users\surrogate-tm\Pictures\VisioObjectModel\"
    strFile = Dir(strPath & "*.*") ' Searches for all files
    Do While strFile <> ""
        cnt = cnt + 1
        Debug.Print cnt, strFile
        Set mst = ActiveDocument.Masters.Add
        mst.Name = cnt
        mst.Prompt = ""
        mst.IconSize = visNormal
        mst.AlignName = visCenter
        mst.MatchByName = False
        mst.IconUpdate = visAutomatic
        Set wn = mst.Open.OpenDrawWindow
        wn.Activate
        fullname = strPath & strFile
        wn.Master.Import fullname
        wn.Master.Close
        strFile = Dir()
    Loop
End Sub



PinPinPoola

Thank you Surrogate.

I am still struggling with VBA, but getting much better with PowerShell these days; as my job uses it more & more.

As always, I really appreciate your help.

Take care,
Pin

Yacine

Yacine


PinPinPoola

Thank you both for Saveenr's details. I will take a look.

In the mean time @Surrogate I have had time to try your suggested code and nothing happens when I run it.

I have updated the strPath to my own path and strFile to (*.svg)

When I run the code, the Visio session 'flashes' or refreshes for each file, but no new shapes appear.

I have tried opening the new stencil file for edits.

Am I doing something wrong?

Cheers
Pin

Surrogate

Quote from: PinPinPoola on March 22, 2024, 01:50:46 PMAm I doing something wrong?
My simple code add new master-shapes to local document stencil, it not create new external stencil!!!

Please check Show Document Stencil option...

Surrogate

Quote from: PinPinPoola on March 21, 2024, 05:09:21 PMbut getting much better with PowerShell these days; as my job uses it more & more.
Sorry, I am not PowerShell exert :-\

$visio = [Runtime.Interopservices.Marshal]::
GetActiveObject('Visio.Application')   # Get Visio.App session   
# Get Visio ActiveDocument
$Doc = $visio.ActiveDocument     
# Set Masters counter 
$n = 0   
# Set folder path   
    $Path= 'C:\Users\surrogate-tm\Pictures\VisioObjectModel' 
    Get-ChildItem -Path $Path | ForEach-Object {
# Iterate SVG files
        If ($_.Name -like "*.svg") {
# Increment counter
            $n = $n+1
# Get current SVG fullname
            $fn = $_.FullName
# Create new master
            $mst = $doc.Masters.Add()
# Rename new master
            $mst.Name = $n
# Set normal iconsize (visNormal = 1)
            $mst.IconSize = 1
# Set align name (visCenter)
            $mst.AlignName = 2
# No MatchByName option
            $mst.MatchByName = $False 
# Set IconUpdate mode (visAutomatic = 1)
            $mst.IconUpdate = 1
# My code cant open master window
            $wn = $mst.Open.OpenDrawWindow
# I want Activate window,  but I cant do this
            $wn.Activate
# Import SVG picture
            $wn.Master.Import, $fn
# Close master's window
            $wn.Master.Close
# Debug output
            Write-Host -Object "Added master: $fn"
        } ElseIf ($_.PSIsContainer) {
# ???
        } # End If-ElseIf.

I cant translate VBA code row
Set wn = mst.Open.OpenDrawWindow

Nikolay

Visio Super Utilities can do that:
https://unmanagedvisio.com/products/vsu/

Use Stencil -> Create Stencil From Images


You will be prompted for the stencil name, and to pick the images to create the stencil from.

Surrogate

Quote from: Nikolay on March 23, 2024, 09:07:34 PM
Visio Super Utilities can do that
Sorry, I forgot!
My code is just for memory!
I had a problem with importing a picture. I couldn't do it without drawing a rectangle before importing the picture. $visio = [Runtime.Interopservices.Marshal]:: GetActiveObject('Visio.Application') # Get active Visio session
$visio.AlertResponse = $true # AlertResponse change to
$target = 'C:\Forum_BU\gifs\test1.vss' # Path for new stencil
$st = $visio.Documents.Addex('', 0, 516) # Create new stenctl
$n = 0
$Path= 'C:\surrogate-tm\Pictures\VisioObjectModel'

    Get-ChildItem -Path $Path | ForEach-Object {
        If ($_.Name -like "*.*") { #
            $n = $n+1
            $fn = $_.FullName
            $mst = $st.Masters.Add()
            $mst.Name = $n
            $mst.Prompt = ""
            $mst.IconSize = 1 #visNormal
            $mst.AlignName = 2 #visCenter
            $mst.MatchByName = $False
            $mst.IconUpdate = 1 #visAutomatic
            $wn = $mst.OpenDrawWindow()
            $wn.Activate()
            $sh1 = $wn.Master.DrawRectangle(0,0,0,0) # Draw rectangle
            $sh2 = $wn.Master.Import($fn) # Import picture
            $sh2.Cells("LocPinX").Formula = 'Width*0'
            $sh2.Cells("PinX").Formula = '0 mm'
            $sh2.Cells("LocPinY").Formula = 'Height*0'
            $sh2.Cells("PinY").Formula = '0 mm'
            $wn.Master.Close() # Close master

        } ElseIf ($_.PSIsContainer) {

        } # End If-ElseIf.
    } # End ForEach-Object.
    $visio.AlertResponse = $false #
    $st.SaveAs($target) # Save stencil
    $st.close() # Close stencil
    $visio.Documents.OpenEx($target, 6) # Open stencil for RO

wapperdude

Visio 2019 Pro

Yacine

That's not fair. PS got a super hero as mascot, we've haven't got more than a funny nerd head.
Yacine

wapperdude

Well, desperate does as desperate needs.  Obviously PowerShell feels creative need to expand user base. 

I was perusing PowerShell to see if there's any utility gained for Visio users.  I have mixed feelings.  I'm am most doubt.  Visio is so inherently powerful, I see little point, if any, to use Visio PowerShell.  The idea of Visio was to be visual object oriented, and, for the most part, avoid doing design/entry via a textual input.  PowerShell seems like a step backwards...use a textual input to drive a graphics tool?  Yes, there are unforeseen missing tools, but these can be provided from within Visio.  This topic, case in point.  Nikolay has tool that does what was requested of PowerShell. 

I even tried using binges to do this.  It failed.  It created a solution, code failed, pointed out error, fix failed.  Yada. Yada.  So, then I tried...and failed.    There are a couple sites, and YouTube vids, but this is too much of a niche topic to motivate investment time to learn something I'll not use again. 

Perhaps some of the other power users will pick up on this.
Visio 2019 Pro

wapperdude

OK.  So I am officially off my rocker!  Why? Well, 1) Nikolay has a working solution from inside Visio, 2) I know nothing about PowerShell, com stuff, etc., and 3) I hate programming.

Well, with the help of BingAI, below is working PowerShell code (script, I guess).

Some things to note:
1) translating image files into Visio shapes requires, uh, Visio.  That then begs the question, why not use Nikolay's solution.
2) the code works, mostly.  Issue with quitting VisiThe use and the pop-up dialog asking yes, no, cancel. 
3) this is proof of concept, so, code only grabs a single image.  Some sort of loop would be needed to grab more than 1
4) User must use appropriate file locations and names.
5) this code is a collaborative effort between me and BingAI

# Define the path to the image file you want to add
$imagePath = "C:\VisioPix\MyImage1.jpg"

# Define the name for the new master
$masterName = "MyImage1"

# Create a new Visio application object
$visioApp = New-Object -ComObject Visio.Application

# Make Visio invisible to the user (no UI)
$visioApp.Visible = $false

# Create a new document for importing the image
$doc = $visioApp.Documents.Add("")

# Import the image to the new document
$importedShape = $doc.Pages.Item(1).Import($imagePath)

# Define the path to the Visio stencil file
$stencilPath = "C:\VisioPix\Pix.vssx"

# Open the stencil file
$stencil = $visioApp.Documents.OpenEx($stencilPath, 64)

# Create a master of the imported image in the stencil
$master = $stencil.Drop($importedShape, 0, 0)

# Set the name for the new master
$master.Name = $masterName

# Save the modified stencil
$stencil.SaveAS($stencilPath)

# Close the stencil and the new document
$stencil.Close()
$doc.Close()

# Quit Visio
$visioApp.Quit()

# Release the COM objects
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($importedShape)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($master)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($stencil)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($doc)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($visioApp)

# Print a success message
Write-Host "Task execution done."
Visio 2019 Pro

PinPinPoola

Apologies that I have not replied sooner, but I had to go away with work for a few days.

Thank you all so much for your help; especially to Surrogate, as your second PowerShell script worked perfectly for me.

Pin.