この記事では、アプリケーションの種類によってはあまりお目にかかる機会が少ない、でも知っていると意外と役に立つことがある、VIスクリプトの機能について、必要な設定や概要、実装例を紹介しています。
プログラムからプログラムを作る
LabVIEWでプログラムを作るためには、とても大雑把に言えば、アイコンを配置してそれらをワイヤで結ぶ、という作業をひたすら繰り返していく必要があります。
一部の操作はショートカットキーがあるものの、手作業でワイヤ配線をちまちまやっているのは意外と面倒です。
本来、プログラミングとは、人間がやって退屈な仕事を代わりにコンピュータにさせよう、ということがモチベーションの一つなのに、時にプログラムを書くという作業自体が「退屈な」ものになってしまう時があると思います。
「だったら、プログラムを書くプログラムを用意すればプログラムを書くという退屈な仕事が減る!」といった頓智みたいなことができたらな、という思いをかなえてくれるかもしれない機能、それがLabVIEWのVIスクリプトです。
これにより、プログラム的に(つまりviから)プログラムを(viを)作ることができます。
何のためにそんなことをする必要があるかと思われるかもしれませんが、例えば似たようなアプリケーションを多く作るような場合、それぞれに対してプロジェクトエクスプローラを用意し、それぞれに似たような(しかし同じではない)viを作っていくことがあります。
そんなときに、ダイアログ形式で、「ケースストラクチャは何個必要」「ループの中にあらかじめ停止のためのブール制御器を配置しておく」といったことを選択し、決定ボタンを押したらプログラムの土台が組みあがっている、そんなことを実現するためにVIスクリプトが使えます。
このブログ記事でも過去にVIスクリプトを使ったプログラムの例は紹介してきましたが、基本的な部分は紹介してなかったため今回記事にしようと考えました。
ただ、VIスクリプトは数多くのリファレンスを駆使したプログラムを書くことになるため、時にこれがとても厄介なことがあります。
そのため、思い通りのプログラムとならないという場合もあります(もちろん「頑張れば」それなりにうまくいくようになるはずですが)。
「手作業だと30分で終わる作業を3分で終わらせるために、3時間かけてプログラムを書く」といったことにもなりかねず、VIスクリプトを使うからにはそれなりの慣れが必要となります。
記事後半では、VIスクリプトを使用して新規のVIを生成する例を紹介していますが、実際に使いこなせるようになるためにはぜひ実際に組んでみることをオススメします。
(なお、本記事では、VIサーバーとの機能の違いについてはあまり気にしていません。
広く、viから、他のviの編集や作成を行う機能全般をviスクリプトの機能として紹介していきます。)
VIスクリプトの準備
VIスクリプトの機能を使用する場合、LabVIEWでデフォルトではオフになっている機能をオンにする必要があります。
ツールメニューからオプションを開いて、VIサーバーカテゴリからVIスクリプトの項目を見つけ、チェックマークを入れます。

これにより、VIスクリプトの関数が関数パレットで使用できるようになります。

また、プロパティノードの一部のプロパティ、インボークノードの一部のメソッドも扱えるようになります。

VIスクリプトで新規のVIを作成する
VIスクリプトの機能をオンにしたところで、関数パレットの中身を見てみます。
特に今回の記事で扱うのは実は二つだけで、新規VIと新規VIオブジェクトだけなのですが、これらの関数は、リファレンスデータ、refnumを扱うことで、様々な操作を行うことができるようになります。

抽象的な説明では分かりにくいと思うので、具体例として最も簡単な、新規VIに和の関数を配置するプログラムの例を紹介します。
完成例と、このプログラムを実行したときに生成されるviを紹介します。

流れを説明していきます。
まずは、新規のVIを作るための関数である新規VIが配置されています。
この新規VIから出力されるのは、今から新規で作成しようとしているVIのリファレンスです。
このリファレンスは、例えば「このVIのフロントパネルの大きさやブロックダイアグラムの大きさを決める」や、「このVIに和の関数を配置する」という「このVI」がどのVIであるかを指し示すために使用します。
そのため、次に配置したプロパティノードのリファレンス入力には新規VIから出たVIのリファレンスを配線しています。
このプロパティノードは、通常の黄色表示ではなく水色表示になっており、一部もしくは全部がVIスクリプト特有のプロパティであることを意味しています。

プロパティノードからでるリファレンス出力は入力したリファレンスのクラスを変えないので、プロパティノードから出たリファレンスは依然として(新規の)VIのリファレンスです。
これを、次に新規VIオブジェクトに配線しています。
この新規VIオブジェクトは、入力したリファレンスの元になっているもの(今回はVI)に対して特定のオブジェクトを配置するための関数です。(入力したリファレンスの元になるのが毎回VIであるとは限らないことに注意)
ここでいうオブジェクトとは、制御器や表示器、関数を指します。
そしてこの新規VIオブジェクトで「関数」として「和(Add)」をブロックダイアグラム上のある位置(座標)に配置する、という指定を行うことで、新規のVI上に和の関数を置くことができます。
(この時点でスタイル列挙体の選択肢が英語表記で「Add」となっておらず、日本語表記になっている場合には「和」を探してください。)

ですが、プログラムは当然これだけでは何の意味もなく、実際には和の関数に制御器や定数、そして表示器を配線しなくてはいけません。
そこで、もう少し拡張してこれらの機能を追加したVIスクリプトのプログラム例を紹介します。
実行した結果を右の方に載せています。

ぐっと複雑度が増したと思われるかもしれません、実際VIスクリプトを書くのに慣れていないとリファレンスの扱いに戸惑うことも少なくないと思います。
新規VIオブジェクトで追加するのは和の関数だけでなく、数値制御器2つと数値表示器です。
そして、これらから出たオブジェクト自体のリファレンスをプロパティノードに配線し、各制御器や表示器のラベルを指定しています。
また、和の関数を作成した新規VIオブジェクトから出るオブジェクトリファレンスもプロパティノードにつないで、この和の関数の「端子のリファレンスの配列」をプロパティとして取得し、これらに対して制御器や表示器の端子のリファレンスを用いてワイヤ配線を行うようにしています。
また、配列連結追加の入力は以下の図の通りの順番としてください。(後述するように、Terms[]に関連してこの順番には意味があります)

結局VIスクリプトは関数の配置だけでなく制御器や表示器の作成およびワイヤ配線なども全て指定しないといけないので作るのにそれなりに労力がかかります。
この作業、想像してもらうとわかると思いますが、複数の関数を配置するようなプログラムをVIスクリプトで書く場合、もちろんうまく整理して書けば見やすくなりますが、結構複雑で面倒になります。
もう一つ、別の例として、Whileループの中に待機関数を配置して反復端子に表示器を、条件端子にブール制御器を付けたプログラムを作る場合です。

先ほどの例では、新規VIオブジェクトへ入力するリファレンスはVI自体のリファレンスでした。
これは、そのVI自体に何か関数(和の関数など)を配置する時の方法です。
しかし、VIの中にWhileループがあり、その中に待機関数を配置する場合には、この待機関数を置くために新規VIリファレンスの関数に入力すべきは、Whileループ自体のリファレンスになります。
なぜなら、この場合にはWhileループが待機関数の「所有者」になっているためです。
また、新規VIオブジェクトとして作成した特定の制御器(今回はブール制御器)を特定の端子(条件端子)に配線する場合、その端子のワイヤを接続メソッド上でワイヤのソースとして制御器のリファレンスを配線してやります。

ちなみに、待機関数に制御器を配線するときに、端子のリファレンスから指標配列で「1」の要素を取り出していますが、これがなぜ「1」なのかは詳細ヘルプを見ればわかります。
例えば、端子が多い関数として、ファイルを開く/作成/置換の関数を例にとると、以下の図のようになります。
詳細ヘルプの制御器や表示器に角括弧付きで書かれている数字が、Terms[]配列のリファレンス配列の要素番号に対応します。

これで、どのリファレンスを指標配列で取り出せばいいかを知ることができます。
せっかくファイルI/Oの関数を題材に紹介したので、最後にもう一例として、テキストをファイルに書くプログラムを生成するプログラムの例を紹介します。
生成されるプログラムは以下のようなものになります。

こちらは長いので、前半後半に分けて紹介します。
まずは前半、今までの内容を踏まえればおおよそ理解できるかと思います。
ファイルを開く/作成/置換の関数の端子「7」は「操作」という入力で、列挙体が入ります。
列挙体をオブジェクトして作りこれを配線するのではなく、「定数を作成(Create Constant)」で「2」と指定してやることで、列挙体の要素番号2の要素が定数として作成、配線されます。
定数を用意してこれを配線する場合の方法も敢えて実装していますが、数値定数を作り、関数の端子「6」(これも列挙体を受け付ける「アクセス」入力)に対して配線しています。

後半部分も特に目新しいことはないかと思います。
ただただひたすらに、リファレンスワイヤが多くなるので、どの配線をどこにつけるかといったことを見失わないように注意します。

このようにリファレンスを駆使するプログラムは、慣れないと頭がこんがらがるので整理が必要です。
VIオブジェクトクラスはショートカットで
何となくプログラムを書くための流れについて説明してきましたが、特に新規VIオブジェクトを使う上で面倒くさい点が二つあります。
まずは、新規VIオブジェクトで指定するVIオブジェクトクラスの定数を探すのが面倒、という点です。
関数なら関数、数値なら数値といったオブジェクトのクラスを指定することになりますが、クラスはたくさん存在するので毎回リストから自分の目的にあったクラスを探すのは手間です。
なのですが、オブジェクトクラスの名前がもしわかっているのであればショートカットキーが役に立ちます。
VIオブジェクトクラスの定数を選択してCtrlとスペースでQuickDropを表示させ、QuickDropのウィンドウで目的にVIオブジェクトクラスの名前を指定したら、Ctrl + Bを押すことで、その名前のオブジェクトクラスの定数に変換してくれます。

指定した名前のオブジェクトクラスが存在しない場合には変換されませんが、どのようなオブジェクトを配置すればいいかである程度名前の目星はつけられると思うので、このショートカットキーを使用することでいちいちリストから探すことなくプログラムを作ることができます。
スタイルの探し方
他に面倒なのは、新規VIオブジェクトで指定する必要のあるスタイル入力です。
これは「Add」とか「数値制御器(モダン)」、「数値表示器(モダン)」などといった選択肢を列挙体から探すという作業になるのですが、関数や制御器、表示器はかなりの数があるため、毎回列挙体項目を探すのはとても面倒です。

ただし、探す対象の名前はわかっていることから、列挙体項目名からうまく検索してやる仕組みを作っておくと多少楽になります。
私個人は、以下のような、列挙体項目名を探すためのプログラムを使って探し、その列挙体の項目番号がわかったら、新規VIオブジェクトに対して実際に使用する列挙体のデジタル表示を有効にし、目的の列挙体の項目番号をデジタル表示枠に直接入力しています。

やり方は簡単で、まず新規VIオブジェクトで列挙体を作成します。
この作成した列挙体を制御器にして文字列と値プロパティを作成し、このプロパティの出力値(クラスタの配列)を定数にしておきます。

あとはクラスタの配列定数を使用して以下のようにプログラムを組めば、探したいオブジェクトである制御器や表示器、関数の名前をキーワードとして検索でき、そのオブジェクトの列挙体番号がわかります。

なお、上の図では、列挙体の項目名の表記が英語になったものも同様にクラスタの配列定数として、英語で検索できるようにもしていますが、列挙体の項目名が英語になったものは、サンプルファインダの中のVIスクリプトに関するサンプルから入手できます。
この英語表記の列挙体についてもプロパティノードで文字列と値[]によって文字とその文字に対応した列挙体の項目番号の情報を持った配列を得ることができるので、上記のプログラムを作る際に使用できます。

もっと他の例も知りたい場合には
上で紹介したVIスクリプトの使用例でも何となく使い方が見えてきたかもしれませんが、VIスクリプトについてはそれなりにサンプルやヘルプの記述が多くあります。
チュートリアル的な内容もあるので、この記事で紹介した以外の書き方についても参考になることが多くあります。
困ったときにはこれらの情報も確認しながら進めていってみてください。

本記事では、VIからVIを作る、VIスクリプトの機能の使い方の初歩的な流れを紹介しました。
実際、メインのアプリケーションとしてVIスクリプトのプログラムを書くということは少ないかもしれません。
冒頭で紹介したような、ある程度の規模のVIスクリプトのプログラムを書くと簡単にテンプレートプログラムが生成出来たり便利な点はあるので、VIによるプログラミングの自動化を目指すときの参考になればうれしいです。
ここまで読んでいただきありがとうございました。
コメント