WinCC VBSスクリプトにおけるタグ置換の落とし穴:クロスリファレンスに表示されない原因と対策

産業オートメーションプロジェクトのライフサイクルにおいて、WinCCシステムのメンテナンスやアップグレードは避けて通れない課題です。特にプロジェクトの規模が拡大し、タグ(変数)の数が増大すると、VBS(Visual Basic Script)内のタグ管理が非常に複雑になります。多くのエンジニアが、標準的な方法でタグを置換したはずなのに、実行時に特定の機能が動作しないという経験をしています。その原因の多くは、システムの「クロスリファレンス」から漏れてしまった「隠れた」タグ参照にあります。

1. WinCCタグアドレッシングの明示的参照と暗黙的参照

WinCCにおけるタグの指定方法は一見単純ですが、実際にはシステムが認識できるかどうかの境界線が存在します。標準的な形式で記述されたタグは、システムによって正しくインデックス化されます。

' 標準的なタグ参照の例
Dim objTag
Set objTag = HMIRuntime.Tags("MotorSpeed_01")

このような標準形式のタグは、「クロスリファレンス」や「タグ接続のリンク」にリストアップされるため、一括置換も容易です。しかし、実際のプロジェクトでは、以下のような非標準的な記述が多用されており、これらが置換漏れの主な原因となります。

  • トレンドコントロールへの代入:
    Dim ctrlTrend
    Set ctrlTrend = HMIRuntime.ActiveScreen.ScreenItems("TrendView_1")
    ctrlTrend.TrendIndex = 0
    ctrlTrend.TrendTagName = "Pressure_Value" ' 文字列として扱われるため索引から漏れる可能性がある
  • TagSetオブジェクトの使用:
    Dim tagGroup
    Set tagGroup = HMIRuntime.Tags.CreateTagSet
    tagGroup.Add "FlowRate"
    tagGroup.Add "Temperature"
    tagGroup("FlowRate").Value = 100
    tagGroup.Write

WinCCのインデックス作成メカニズムは特定の構文パターンのみをスキャンするため、文字列として動的に渡されるタグ名は、単純な検索では見落とされるリスクがあります。

2. タグがクロスリファレンスから「消える」4つの典型的なシナリオ

現場の解析に基づくと、以下の4つのケースでタグの参照関係が不透明になりやすいことがわかっています。

2.1 動的なタグ名の生成

柔軟性を高めるためにループ内でタグ名を組み立てる手法ですが、静的解析ツールでは追跡不可能です。

For i = 1 To 10
    Dim tagName
    tagName = "Pump_" & i & "_Status"
    HMIRuntime.Tags(tagName).Read
Next

2.2 オブジェクトプロパティを介した間接参照

画面上のオブジェクトの「代替テキスト」や「ユーザー定義プロパティ」にタグ名を格納し、それをスクリプトで読み取る手法です。

Dim btnObj, targetTag
Set btnObj = HMIRuntime.ActiveScreen.ScreenItems("ConfigBtn")
' プロパティからタグ名を取得
Set targetTag = HMIRuntime.Tags(btnObj.ToolTipText)

2.3 グローバルスクリプト内での辞書管理

パフォーマンス向上のためにタグ参照をDictionaryオブジェクトなどにキャッシュする場合、クロスリファレンスには表示されません。

' GlobalScript内での例
Dim dictCache
Set dictCache = CreateObject("Scripting.Dictionary")
dictCache.Add "TankLevel", HMIRuntime.Tags("Area_A.Tank_01")

2.4 外部ActiveX/.NETコンポーネントとの連携

サードパーティ製のコントロールにパラメータとしてタグ名を渡す場合、WinCCの管理外となります。

3. 確実なタグ置換を実現するためのワークフロー

漏れのないタグ置換を行うためには、以下のステップを踏むことを推奨します。

3.1 タグマッピングリストの作成

まず、Excelなどで新旧のタグ対応表を作成します。これには、物理的なタグ名だけでなく、その用途と使用されているスクリプトの範囲を記録します。

3.2 クロスリファレンスによる標準置換

WinCC標準のクロスリファレンスエディタを使用し、認識可能なタグをまとめてリンク更新します。

  1. すべてのPDL(画面ファイル)を閉じる
  2. クロスリファレンスエディタを開き、フィルタを「画面」に設定
  3. 対象タグを選択し、「編集」→「リンク」から一括置換を実行

3.3 正規表現を用いた全ファイル検索

クロスリファレンスで抽出できない箇所は、外部のエディタ(Notepad++やVS Codeなど)を使用して、プロジェクトフォルダ全体を正規表現でスキャンします。

\.(TrendTagName|TagName|Add)\s*[:=]\s*["']([^"']+)["']

3.4 WinCCコメントセクションの活用

動的な参照であっても、特定のコメントブロックで囲むことでWinCCのクロスリファレンスに対象を認識させる手法があります。

' WINCC:TAGNAME_SECTION_START
Const TAG_PUMP_A = "PumpA_Speed"
' WINCC:TAGNAME_SECTION_END

' スクリプト内では定数を使用
HMIRuntime.Tags(TAG_PUMP_A).Write 50

3.5 置換後の自動整合性チェック

置換作業が完了した後、すべてのタグが有効かどうかを確認するテストスクリプトを実行します。

Sub CheckTagIntegrity()
    On Error Resume Next
    Dim checkList, item
    checkList = Array("New_Pump_Speed", "New_Tank_Level") ' 新しいタグのリスト
    
    For Each item In checkList
        Dim t
        Set t = HMIRuntime.Tags(item)
        t.Read
        If Err.Number <> 0 Then
            ' ログ出力(例:アプリケーションログへの書き込み)
            HMIRuntime.Trace "Error: Tag not found -> " & item & vbCrLf
            Err.Clear
        End If
    Next
End Sub

4. 設計時に守るべきエンジニアリング規則

将来のメンテナンス性を確保するために、以下のルールを開発標準に組み込むべきです。

  • マジック文字列の禁止: スクリプトの途中で直接 "Tag_Name" と記述せず、必ずスクリプトの先頭で定数として定義する。
  • 命名規則の統一: タグ名に階層構造(Area_System_Unit_Signal)を持たせ、一括検索しやすくする。
  • インパクト解析の実施: タグ変更前に、そのタグがどの画面、どのスクリプト、どのアラームで使用されているかのマトリクスを作成する。

5. カスタムツールによる自動化の検討

プロジェクトが大規模な場合、手動での検索には限界があります。FSO(FileSystemObject)を利用して、VBSファイル内の特定のパターンを抽出するカスタムツールを作成するのも有効です。

' プロジェクト内のVBSファイルをスキャンしてタグの利用箇所を抽出する例
Sub ExtractScriptTags(FolderPath)
    Dim fso, folder, file, regEx, content
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set regEx = New RegExp
    
    ' タグ参照パターンにマッチさせる
    regEx.Pattern = "HMIRuntime\.Tags\(""([^""]+)""\)"
    regEx.Global = True
    
    Set folder = fso.GetFolder(FolderPath)
    For Each file In folder.Files
        If LCase(fso.GetExtensionName(file.Name)) = "vbs" Then
            Set content = fso.OpenTextFile(file.Path, 1)
            Dim textData: textData = content.ReadAll
            Dim matches: Set matches = regEx.Execute(textData)
            ' マッチした結果をログ出力
            For Each m In matches
                Debug.Print "File: " & file.Name & " Found: " & m.SubMatches(0)
            Next
            content.Close
        End If
    Next
End Sub

タグ: WinCC VBScript SCADA Siemens IndustrialAutomation

10月6日 01:50 投稿