通过Python或VBA脚本在同一窗口中打开Visio图形和设计文件

0 投票
1 回答
45 浏览
提问于 2025-04-12 15:18

我希望有人能给我建议,如何解决我在使用Visio设计文档时遇到的问题。我有好几百个.vsdx文件,每个文件里的形状都会在新窗口中打开。

问题表现的样子:

问题在于如何让Visio强制把所有形状都在同一个窗口中打开。

我的目标是实现类似“选项 > 高级 > 在同一个窗口中打开所有形状”的效果。

在这里输入图片描述

我尝试了两种方法,但都没有成功:

  1. Python脚本
    import os
    import win32com.client
    directory = "C:\\Users\\User\\Documents\\Designs"
    
    def process_visio_files(directory):
        print("Visio Started.")
        visio.Visible = False  # Run Visio in the background
        for root, dirs, files in os.walk(directory):
            if "Archiv" in root:
                continue  # Skip folders containing "Archiv"
            for file in files:            
                if file.endswith('.vsdx'):
                    print("File is {}".format(file))
                    full_path = os.path.join(root, file)
                    # Process the Visio file
                    document = visio.Documents.Open(full_path)
                    dir(document)
                    document.PropertyToPreventSeparateWindows = True # HERE IS WHERE I NEED TO DO SOME MAGIC FOR THE SHAPES TO OPEN IN THE SAME WINDOW
                    document.Save()
                    document.Close()
        visio.Quit()
    
    process_visio_files(directory)

我找不到用Python实现所需更改的方法。用VBA稍微成功了一些。

  1. VBA脚本(这个脚本会关闭一些形状,所有不是以只读模式打开的形状):
Sub ProcessVisioFilesInFolders()
    Dim rootFolder As String
    rootFolder = "C:\Users\User\Documents\Designs\"

    ProcessFolder rootFolder
End Sub

Sub ProcessFolder(folderPath As String)
    Dim fs As Object
    Dim folder As Object
    Dim subfolder As Object
    Dim file As Object
    Dim visioApp As Object

    On Error Resume Next
    ' Try to get an existing instance of Visio
    Set visioApp = GetObject(, "Visio.Application")
    On Error GoTo 0

    If visioApp Is Nothing Then
        ' If Visio is not running, create a new instance
        Set visioApp = CreateObject("Visio.Application")
        visioApp.Visible = True ' Make Visio application visible
    End If

    ' Create FileSystemObject
    Set fs = CreateObject("Scripting.FileSystemObject")

    MsgBox "Processing folder: " & folderPath

    ' Loop through all files in the folder
    For Each file In fs.GetFolder(folderPath).Files
        If LCase(file.Name) Like "*.vsdx" Then
            MsgBox "Processing file: " & file.Path
            ' Process .vsdx files
            ProcessVisioFile visioApp, file.Path
        End If
    Next file

    ' Loop through all subfolders in the folder
    For Each subfolder In fs.GetFolder(folderPath).SubFolders
        ' Check if the subfolder name contains 'Archiv'
        If InStr(1, subfolder.Name, "Archiv", vbTextCompare) = 0 Then
            ' Recursively process subfolders
            ProcessFolder subfolder.Path
        Else
            MsgBox "Skipping 'Archiv' subfolder: " & subfolder.Path
        End If
    Next subfolder
End Sub

Sub ProcessVisioFile(visioApp As Object, filePath As String)
    Dim doc As Object
    Dim win As Object
    Dim shapeSheetWin As Object

    ' Open the Visio file
    Set doc = visioApp.Documents.Open(filePath)

    ' Ensure Visio application is visible and brought to the front
    visioApp.Visible = True

    ' Introduce a delay to allow the application to become active
    Dim startTime As Double
    startTime = Timer
    Do While Timer < startTime + 1 ' Adjust the delay as needed
        DoEvents
    Loop

    ' Loop through all windows
    For Each win In visioApp.Windows
        If win.Type = 1 Then ' visDrawing type
            ' Your processing logic here
            On Error Resume Next
            win.HideShapesheet
            On Error GoTo 0
        ElseIf win.Type = 2 Then ' visStencil type
            ' Close stencil windows
            Set shapeSheetWin = win
            shapeSheetWin.Close
        End If
    Next win

    ' Save the changes to the Visio file
    MsgBox "Saving changes to Visio file: " & filePath
    doc.Save

    ' Close the Visio file
    MsgBox "Closing Visio file: " & filePath
    doc.Close
End Sub

有没有人能分享一下,如何解决形状在不同窗口中打开的问题?

1 个回答

1

在你最初的帖子中,我看到第一张图片里有很多以只读方式打开的模板,这些模板是在不同的窗口中显示的……
这不是形状表窗口!!!

我没有遇到过同样的问题,所以我用代码创建了一个示例

Option Base 1
Sub Prepare()
Dim pth(3) As String, curpath As String, i As Integer
pth(1) = "C:\My Shapes\19_inch_Rack_flexible_RU.vss"
pth(2) = "C:\My Shapes\Favorites.vssx"
pth(3) = "C:\My Shapes\GOST_R_21.1101-2013.vss"
For i = LBound(pth) To UBound(pth)
    curpath = pth(i)
    Documents.OpenEx curpath, visOpenRO ' open stencil in new window as read-only
Next
ActiveDocument.DocumentSheet.OpenSheetWindow ' add Document ShapeSheet window 
End Sub

Demo

在我这边,下面的代码会关闭所有窗口,如果窗口的类型不是绘图窗口的话。请多了解一下 VisWinTypes 枚举 (Visio)
下面的代码可以关闭所有非绘图窗口

    Sub Test()
    Dim va As Application, vw As Window
    Set va = Application
    For Each vw In va.Windows
        Debug.Print vw.Caption, vw.Type, vw.SubType
        If Not vw.Type = visDrawing Then vw.Close ' visDrawing = 1 Python dont know Visio internal constants
    Next
    ActiveDocument.ContainsWorkspaceEx = False ' prevent save document workspace (a lot of RO-opened stencils)
    ActiveDocument.Save
    End Sub

ActiveDocument.ContainsWorkspaceEx = False 这一行代码可以防止保存工作区(所有只读模板)。请查看这篇文章 Document.ContainsWorkspaceEx 属性 (Visio)

~~现在我没有Python环境,我会稍后再找……~~
我在Jupyter Notebook中试了这段代码,它在我这边可以正常工作……

import win32com.client
app = win32com.client.Dispatch('Visio.Application')
app.Visible = True
for i in range(app.windows.count,1,-1):
    vw = app.windows(i)
    if vw.Type!=1:
        vw.close

app.ActiveDocument.ContainsWorkspaceEx = False
app.ActiveDocument.Save

撰写回答