C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

アクティブなドキュメントに関連するファイルを開く1

こちらの成果物です。
GUIで開かれているドキュメントを判断する - C#ATIA

本来であればアドインにすべきですが、もう少し機能を
確立してからアドインにしますので、お許しください。

アクティブなドキュメントを変更した際、最新の状態にするべき
ドキュメントを一括して開きます。図面もです。

# Author-kantoku
# Description-アクティブなドキュメントに関連するファイルを開く
# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core
import re

def run(context):
    ui: adsk.core.UserInterface = None
    try:
        app: adsk.core.Application = adsk.core.Application.get()
        ui = app.userInterface

        # オフラインチェック
        if app.isOffLine:
            msg = 'オフラインモードではチェック出来ません!!'
            ui.messageBox(msg)
            return

        # datafile取得
        actData: adsk.core.DataFile = app.activeDocument.dataFile
        if not actData:
            msg = 'アクティブなドキュメントを参照している'
            msg += '\nf3dファイルは有りません!!(一度も保存されていません)'
            ui.messageBox(msg)
            return

        # 天辺のファイル取得
        rootDataFiles: list = getRootDataFiles(actData)

        if len(rootDataFiles) < 1:
            msg = f'[{getDocumentFullName(actData)}]を'
            msg += '\n参照しているf3dファイルは見つかりませんでした!'
            ui.messageBox(msg)
            return

        # トップレベルドキュメント名
        topLevelNames = getTopLevelDocumentNames()

        # 問い合わせ
        names = [getDocumentFullName(df, topLevelNames) for df in rootDataFiles]

        msg = f'以下の{len(rootDataFiles)}個のf3d/f2dファイルに参照されています。'
        msg += '\n全て開きますか?\n\n'
        msg += '\n'.join(names)

        res: adsk.core.DialogResults = ui.messageBox(
            msg,
            '',
            adsk.core.MessageBoxButtonTypes.YesNoButtonType)

        if res != adsk.core.DialogResults.DialogYes:
            return

        # オープン
        execOpen(rootDataFiles, topLevelNames)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def execOpen(
    rootDataFiles: list,
    topLevelNames: list):

    app: adsk.core.Application = adsk.core.Application.get()
    docs: adsk.core.Documents = app.documents

    def getDocFromDatafileId(id) -> adsk.fusion.FusionDocument:
        for d in docs:
            if d.dataFile.id == id:
                return d
        return None

    df: adsk.core.DataFile
    for df in rootDataFiles:
        name = getDocumentNameFromDataFile(df)
        if name in topLevelNames:
            continue

        doc: adsk.fusion.FusionDocument = getDocFromDatafileId(df.id)
        if doc:
            doc.activate()
        else:
            docs.open(df)

def getTopLevelDocumentNames() -> list:
    app: adsk.core.Application = adsk.core.Application.get()
    res: str = app.executeTextCommand(u'DocumentMgt.DumpDocTxnEntity')
    topLevelNames = re.findall(r'Top level document: (.+)\r', res)

    return topLevelNames

def getDocumentNameFromDataFile(
    datafile: adsk.core.DataFile,) -> str:

    return f'{datafile.name} v{datafile.latestVersionNumber}'

def getDocumentFullName(
    datafile: adsk.core.DataFile,
    topLevelNames: list) -> str:

    docName = getDocumentNameFromDataFile(datafile)
    info = ' (既に開かれています)' if docName in topLevelNames else ''

    return f'{datafile.name}.{datafile.fileExtension}{info}'

def getRootDataFiles(
    datafile: adsk.core.DataFile,) -> list:
    
    # 対象拡張子
    targetFileExtension = [
        'f3d',
    ]
    drawFileExtension = [
        'f2d',
    ]

    # サポート関数
    def getHasDrawDataFile(
        datafile: adsk.core.DataFile) -> list:

        return getHasExtensionDataFile(
            datafile,
            drawFileExtension 
        )

    def getHasParentDataFile(
        datafile: adsk.core.DataFile) -> list:

        return getHasExtensionDataFile(
            datafile,
            targetFileExtension
        )

    def getHasExtensionDataFile(
        datafile: adsk.core.DataFile,
        extensionLst: list) -> list:

        return [d for d in datafile.parentReferences.asArray() 
            if d.fileExtension in extensionLst]


    # *********
    checkDatas: list  = getHasParentDataFile(datafile)

    # 再帰はしたくない
    rootDatas: list = []
    drawDatas: list = []
    df: adsk.core.DataFile
    while len(checkDatas) > 0:
        hasParentDatas: list  = []
        for df in checkDatas:
            # 2d
            draws: list  = getHasDrawDataFile(df)
            if len(draws) > 0:
                drawDatas.extend(draws)
            # 3d
            parents: list  = getHasParentDataFile(df)
            if len(parents) < 1:
                rootDatas.append(df)
            else:
                hasParentDatas.extend(parents)

        if len(hasParentDatas) > 0:
            checkDatas = hasParentDatas
        else:
            checkDatas = []

    rootDatas.extend(drawDatas)
    return rootDatas

・・・作りかかっていた状態のものをうっかり削除し、
作り直しました。

スクリプト実行後、関連ファイル名が出ますが、既に
開かれているドキュメントの場合、それっぽく表示します。
f:id:kandennti:20220311183113p:plain

結果的に関連ドキュメントに対し
・開かれていない -> 開く
・開かれている-> 何もしない
・読み込まれているが表示されていない(特に図面が開いているとき) -> アクティブにする
と言うのが、ユーザーを一番待たさない と判断しました。
(で、そのように処理させる様にしました)

最新状態に更新する必要があるかどうかは、ドキュメントを
開かないとわかんないんですよね・・・。