「マクロ覚え書き(開発者向け)」の版間の差分

提供: MeryWiki
ナビゲーションに移動 検索に移動
MSY-07 (トーク | 投稿記録)
見出しの修正
MSY-07 (トーク | 投稿記録)
文章の構成を変更
 
(2人の利用者による、間の14版が非表示)
4行目: 4行目:


== 開発言語について ==
== 開発言語について ==
WSH(Windows Script Host) が対応している言語であれば利用が可能です。
WSH (Windows Script Host) が対応している言語であれば利用が可能です。


標準では JScript(≒javascript)と VBScript が入っています。
標準では JScript(≒JavaScript)と VBScript が入っています。


他の言語(Perl や Python)もインストールすれば使えますが、一般配布する場合利用者もインストールが必要になります。
他の言語(Perl や Python)もインストールすれば使えますが、一般配布する場合利用者もインストールが必要になります。
21行目: 21行目:
ただし読み込む側が FileSystemObject を利用している場合、SJIS/Unicode しか対応できないのでその場合は SJIS をお勧めします(Mery 1 時代のマクロなどはコレです)。
ただし読み込む側が FileSystemObject を利用している場合、SJIS/Unicode しか対応できないのでその場合は SJIS をお勧めします(Mery 1 時代のマクロなどはコレです)。


== window.Document と Editor.ActiveDocument の違い ==
== window.Document と editor.ActiveDocument の違い ==
window.Document は、マクロ開始時にアクティブなドキュメントを指し続けます。マクロで別のドキュメントを Activate しても変わりません。
window.Document は、マクロ開始時にアクティブなドキュメントを指し続けます。マクロで別のドキュメントを Activate しても変わりません。


Editor.ActiveDocument は、その時点でアクティブなドキュメントを指します。マクロで別のドキュメントを Activate すると当然変わります。
editor.ActiveDocument は、その時点でアクティブなドキュメントを指します。マクロで別のドキュメントを Activate すると当然変わります。
 
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Editor.Documents.Item(0).Activate();
editor.documents.Item(0).Activate();
Alert(Document.Name);
Alert(document.Name);
Alert(Editor.ActiveDocument.Name);
Alert(editor.ActiveDocument.Name);
</syntaxhighlight>
</syntaxhighlight>
また、window.Document は Documents.Item() と一致しませんが、Editor.ActiveDocument は一致します。
 
また、window.Document は documents.Item() と一致しませんが、editor.ActiveDocument は一致します。
 
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
for (var i=0; i<Editor.Documents.Count; i++) {
for (var i = 0; i < editor.documents.Count; i++) {
  if (Editor.ActiveDocument == Editor.Documents.Item(i)) {
if (editor.ActiveDocument == editor.documents.Item(i)) {
    Alert("Editor.ActiveDocument が一致");
Alert("editor.ActiveDocument が一致");
  }
}
  if (Document == Editor.Documents.Item(i)) {
if (Document == editor.documents.Item(i)) {
    Alert("window.Document が一致");
Alert("window.Document が一致");
  }
}
}
}
</syntaxhighlight>
</syntaxhighlight>
44行目: 47行目:
== window.Redraw = true は必要か ==
== window.Redraw = true は必要か ==
マクロで
マクロで
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Redraw = false;
Redraw = false;
</syntaxhighlight>
</syntaxhighlight>
にしたとき、最後
にしたとき、最後
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Redraw = true;
Redraw = true;
</syntaxhighlight>
</syntaxhighlight>
が必要かという点については、現状確認する限りでは不要です。
が必要かという点については、現状確認する限りでは不要です。


57行目: 64行目:


ただし、矩形選択中かの判定だけは以下の方法で可能です。
ただし、矩形選択中かの判定だけは以下の方法で可能です。
<syntaxhighlight lang="javascript">
 
var s = Document.Selection;
<syntaxhighlight lang="javascript" copy>
var isBoxed = (s.GetBottomPointY(mePosView) - s.GetTopPointY(mePosView)) != (s.Text.match(/\n/g) || []).length;
var sel = document.selection;
var isBoxed = (sel.GetBottomPointY(mePosView) - sel.GetTopPointY(mePosView)) != (sel.Text.match(/\n/g) || []).length;
</syntaxhighlight>
</syntaxhighlight>
2019/06/11追記(有志):使い道は限られますが、Alt + Shit + カーソル移動のキーコードを送ることで、矩形範囲指定の開始と範囲変更は可能です。
 
<syntaxhighlight lang="javascript">
使い道は限られますが、Alt + Shit + カーソル移動のキーコードを送ることで、矩形範囲指定の開始と範囲変更は可能です。
new ActiveXObject("WScript.Shell").SendKeys("+%{left}");//{right},{up},{down}
 
<syntaxhighlight lang="javascript" copy>
new ActiveXObject("WScript.Shell").SendKeys("+%{left}"); //{right},{up},{down}
</syntaxhighlight>
</syntaxhighlight>


== Document.GetLines の引数 ==
== document.GetLines の引数 ==
リファレンスには '''meGetLineView''' しか書かれていませんが、論理行単位での行数取得には引数に 0 を渡します。
Ver 3.3.2 以降では引数を省略すると論理行単位での行数取得になります。
 
Ver 3.3.1 以前では引数に 0 を渡すと論理行単位での行数取得になります。


'''meGetLineLogical''' という定数はありません。
meGetLineLogical という定数はありません。


== プリプロセス(#title など) ==
== プリプロセス(#title など) ==
対応しているプリプロセスコードは以下の通りです。
対応しているプリプロセスコードは以下の通りです(詳細は[https://www.haijin-boys.com/wiki/%E3%83%9E%E3%82%AF%E3%83%AD%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9:3:%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96 ディレクティブ]を参照)。
* <code>#icon = "****" [, アイコン番号]</code>
 
* <code>#title = "****"</code>
* <code>#title = "****"</code> ツール バーのボタンに表示するタイトルの文字列を指定します。
* <code>#tooltip = "****"</code>
* <code>#tooltip = "****"</code> ツール バーのボタンにマウスを乗せたときに表示されるヒントの文字列を指定します。
* <code>#include "****.js"</code>
* <code>#begingroup = true</code> [マクロ] メニューおよびマクロ バーの項目の手前に区切りバーを挿入します。
* <code>#language = "****"</code>[https://www.haijin-boys.com/software/mery/mery-2-6-6#5] (スクリプトの言語を指定。 ※[https://www.haijin-boys.com/software/mery/mery-2-6-7#9 省略時は "JScript(Chakra)"])
* <code>#icon = "****" [, アイコン番号]</code> ツール バーのボタンに表示するアイコンを指定します。
* <code>#begingroup = true</code>[https://www.haijin-boys.com/software/mery/mery-2-8-0#4] (または 1 - 3 の数値。 ※Mery Ver 2.8.0 以降のみ)
* <code>#icondark = "****" [, アイコン番号]</code> ダークモード有効時にツール バーのボタンに表示するアイコンを指定します。
* <code>#include "****.js"</code> 指定したファイルをマクロの先頭に含めます。
* <code>#language = "****"</code> スクリプト言語を指定します。


これらは必ず '''ファイル先頭''' に書かなければなりません(コメントや VBS の Option Explicit などよりも先)。
これらは必ず ファイル先頭 に書かなければなりません(コメントや VBS の Option Explicit などよりも先)。
* <code>#title</code>は、マクロメニューやマクロバー、「ツールバーのカスタマイズ」に表示される '''マクロ名''' です(未指定の場合はファイル名の ****.js で表示されます)。
* <code>#tooltip</code>は、マクロバーにマウスカーソルをあてたときにポップアップ表示される黄色い小窓(ヒント/ツールチップ/トースト)内の '''説明文''' の文字列に使用されます。
* <code>#language</code>の詳細は、CHANGELOG.txt 内の 『## 2.6.6 (2018-03-22)』(Mery Ver 2.8.8 以前は Mery.txt 内の更新履歴 『▼ 2018/03/22 (2.6.6)』)に記載されています。


== 他のファイルのロード方法 ==
== 他のファイルのロード方法 ==
マクロから他のファイルを直接ロードするには以下の方法があります。
マクロから他のファイルを直接ロードするには以下の方法があります。
* FileSystemObject を利用する
* FileSystemObject を利用する
* ADODB.Stream を利用する
* ADODB.Stream を利用する
97行目: 109行目:


ただし扱える文字コードは SJIS または Unicode 限定。
ただし扱える文字コードは SJIS または Unicode 限定。
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript" copy>
// Scripting.FileSystemObject の定数
// Scripting.FileSystemObject の定数
var ForReading = 1;           // ファイルを読み取り専用として開きます。このファイルには書き込むことができません。
var ForReading = 1;         // ファイルを読み取り専用として開きます。このファイルには書き込むことができません。
var ForWriting = 2;           // ファイルを書き込み専用として開きます。
var ForWriting = 2;         // ファイルを書き込み専用として開きます。
var ForAppending = 8;         // ファイルを開き、ファイルの最後に追加して書き込みます。
var ForAppending = 8;       // ファイルを開き、ファイルの最後に追加して書き込みます。
var TristateUseDefault = -2; // システム デフォルトを使ってファイルを開きます。
var TristateUseDefault = -2; // システム デフォルトを使ってファイルを開きます。
var TriStateTrue = -1;       // ファイルを Unicode ファイルとして開きます。
var TriStateTrue = -1;       // ファイルを Unicode ファイルとして開きます。
var TristateFalse = 0;       // ファイルを ASCII ファイルとして開きます。
var TristateFalse = 0;       // ファイルを ASCII ファイルとして開きます。


var fso = new ActiveXObject("Scripting.FileSystemObject");
var fso = new ActiveXObject("Scripting.FileSystemObject");


// ファイルの読み込み
// ファイルの読み込み
var fsIn = fso.OpenTextFile(Document.FullName, ForReading, false, TristateUseDefault);
var fsIn = fso.OpenTextFile(document.FullName, ForReading, false, TristateUseDefault);
var text = fsIn.ReadAll();
var text = fsIn.ReadAll();
fsIn.Close();
fsIn.Close();
124行目: 137行目:


また(信頼性は低いが)文字コードの自動判定も可能です。
また(信頼性は低いが)文字コードの自動判定も可能です。
<syntaxhighlight lang="javascript">
 
var adTypeBinary = 1;           // バイナリ データを表します。
<syntaxhighlight lang="javascript" copy>
var adTypeText = 2;             // 既定値です。Charset で指定された文字セットにあるテキスト データを表します。
var adTypeBinary = 1;         // バイナリ データを表します。
var adReadAll = -1;             // 既定値です。現在の位置から EOS マーカー方向に、すべてのバイトをストリームから読み取ります。これは、バイナリ ストリームに唯一有効な StreamReadEnum 値です。
var adTypeText = 2;           // 既定値です。Charset で指定された文字セットにあるテキスト データを表します。
var adReadLine = -2;           // ストリームから次の行を読み取ります (LineSeparator プロパティで指定)。
var adReadAll = -1;           // 既定値です。現在の位置から EOS マーカー方向に、すべてのバイトをストリームから読み取ります。これは、バイナリ ストリームに唯一有効な StreamReadEnum 値です。
var adSaveCreateNotExist = 1;   // 既定値です。FileName パラメータで指定したファイルがない場合は新しいファイルが作成されます。
var adReadLine = -2;           // ストリームから次の行を読み取ります (LineSeparator プロパティで指定)。
var adSaveCreateOverWrite = 2; // FileName パラメータで指定したファイルがある場合は、現在開かれている Stream オブジェクトのデータでファイルが上書きされます。
var adSaveCreateNotExist = 1; // 既定値です。FileName パラメータで指定したファイルがない場合は新しいファイルが作成されます。
var adSaveCreateOverWrite = 2; // FileName パラメータで指定したファイルがある場合は、現在開かれている Stream オブジェクトのデータでファイルが上書きされます。


// ファイルの読み込み
// ファイルの読み込み
137行目: 151行目:
adodb.Charset = 'utf-8';
adodb.Charset = 'utf-8';
adodb.Open();
adodb.Open();
adodb.LoadFromFile(Document.FullName);
adodb.LoadFromFile(document.FullName);
var text = adodb.ReadText(adReadAll);
var text = adodb.ReadText(adReadAll);
adodb.Close();
adodb.Close();
158行目: 172行目:


逆にソースを読むしか資料がないこと、ユーザに導入してもらう必要があるのが欠点です。
逆にソースを読むしか資料がないこと、ユーザに導入してもらう必要があるのが欠点です。
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript" copy>
#include "include/IO.js"
#include "include/IO.js"


// ファイルの読み込み
// ファイルの読み込み
var text = IO.LoadFromFile(Document.FullName, "utf-8");
var text = IO.LoadFromFile(document.FullName, "utf-8");
Alert(text);
Alert(text);


171行目: 186行目:
== 他のマクロの実行方法 ==
== 他のマクロの実行方法 ==
他のマクロを実行するには、以下の方法があります。
他のマクロを実行するには、以下の方法があります。
* #include で取り込む
* #include で取り込む
* ファイルをロードして eval する
* ファイルをロードして eval する
前者は先頭でしかかけない上、動的にロードの切り替えができません。
* [[マクロリファレンス:3:Editor オブジェクト#ExecuteMacro メソッド|editor.ExecuteMacro メソッド]]を使用する(Ver 3.7.13 で追加)
 
1つ目は先頭でしか書けない上、動的にロードの切り替えができません。


後者は文字コードの問題とプリプロセス処理に関する問題があります。
2つ目は文字コードの問題とプリプロセス処理に関する問題があります。


[[includeライブラリ]]の IO.Include を使うことで、プリプロセス処理に関しては解決できます。
[[includeライブラリ]]の IO.Include を使うことで、プリプロセス処理に関しては解決できます。
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript" copy>
#include "include/IO.js"
#include "include/IO.js"


eval(IO.Include("test.js", "utf-8")); // #include なども処理される
eval(IO.Include("test.js", "utf-8")); // #include なども処理される
</syntaxhighlight>
</syntaxhighlight>
3つ目は任意の場所で指定したマクロを実行することができます。


== マクロからファイル選択ダイアログ ==
== マクロからファイル選択ダイアログ ==
できません。
以下の関数で可能です。


2019/06/11追記 (有志): 以下の関数で可能です。
<syntaxhighlight lang="javascript" copy>
<syntaxhighlight lang="javascript">
function OpenFileDlg() {
function OpenFileDlg(){
var HTASource =
  var HTASource = '<object id=HtmlDlgHelper classid=CLSID:3050f4e1-98b5-11cf-bb82-00aa00bdce0b></object>\n'
'<object id=HtmlDlgHelper classid=CLSID:3050f4e1-98b5-11cf-bb82-00aa00bdce0b></object>\n'
  +'<script language=vbscript>\n'
+ '<script language=vbscript>\n'
  +'resizeTo 0,0\n'
+ 'resizeTo 0,0\n'
  +'Sub window_onload()\n'
+ 'Sub window_onload()\n'
  +'CreateObject("Scripting.FileSystemObject").GetStandardStream(1).Write HtmlDlgHelper.object.openfiledlg(,,"All Files(*.*)|*.*|","ファイル選択")\n'
+ 'CreateObject("Scripting.FileSystemObject").GetStandardStream(1).Write HtmlDlgHelper.object.openfiledlg(,,"All Files(*.*)|*.*|","ファイル選択")\n'
  +'close\n'
+ 'close\n'
  +'End Sub\n'
+ 'End Sub\n'
  +'</script>\n'
+ '</script>\n'
  +'<hta:application caption=no showintaskbar=no />\n';
+ '<hta:application caption=no showintaskbar=no />\n';


  var oExec = new ActiveXObject('WScript.Shell').Exec(
var oExec = new ActiveXObject('WScript.Shell').Exec(
    'MSHTA.EXE "javascript:new ActiveXObject(\'Scripting.FileSystemObject\').GetStandardStream(0).ReadAll()"'
'MSHTA.EXE "javascript:new ActiveXObject(\'Scripting.FileSystemObject\').GetStandardStream(0).ReadAll()"'
  );
);
  oExec.StdIn.Write(HTASource);
oExec.StdIn.Write(HTASource);
  oExec.StdIn.Close();
oExec.StdIn.Close();


  var filename = oExec.StdOut.ReadAll();
var filename = oExec.StdOut.ReadAll();
  var nullcharAt = filename.indexOf(String.fromCharCode(0x0));
var nullcharAt = filename.indexOf(String.fromCharCode(0x0));
  if (nullcharAt > 0) filename = filename.substring(0, nullcharAt);
if (nullcharAt > 0) {
  return filename;
filename = filename.substring(0, nullcharAt);
}
return filename;
}
}
</syntaxhighlight>
</syntaxhighlight>


使用例
使用例
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
var filename = OpenFileDlg();
var filename = OpenFileDlg();
window.alert((filename)?filename:'Canceled');
window.alert((filename) ? filename : 'Canceled');
</syntaxhighlight>
</syntaxhighlight>


2019/06/17追記 (有志): PoserShell 版追加,, 2019/06/19 修正: Exec と標準出力の組み合わせを、Runとクリップボードに変更
=== PowerShell 版 ===
HtmlDlgHelper.object.openfiledlg の第1引数はダイアログに初期表示する InitFile。疑似的に初期フォルダを指定することが可能だが、パス区切り文字 "\" で終わることはできない。PowerShell 版なら初期フォルダの明示、複数ファイル選択が可能。Multiselect = $false にしても $dialog.FileName に書き換えせずに $dialog.FileNames でアクセス可能。


HtmlDlgHelper.object.openfiledlg の第1引数はダイアログに初期表示する InitFile。疑似的に初期フォルダを指定することが可能だが、パス区切り文字 "\" で終わることはできない。PowerShell 版なら初期フォルダの明示、複数ファイル選択が可能。Multiselect = $false にしても $dialog.FileName に書き換えせずに $dialog.FileNames でアクセス可能。
<syntaxhighlight lang="javascript" copy>
<syntaxhighlight lang="javascript">
function OpenFileDlg() {
function OpenFileDlg(){
ClipboardData.ClearData();
  ClipboardData.ClearData();
var PS1Source =
  var PS1Source = '[void][System.Reflection.Assembly]::LoadWithPartialName(\'System.windows.forms\');'
'[void][System.Reflection.Assembly]::LoadWithPartialName(\'System.windows.forms\');'
                +'$dialog = New-Object System.Windows.Forms.OpenFileDialog;'
+ '$dialog = New-Object System.Windows.Forms.OpenFileDialog;'
                +'$dialog.Filter = \'AllFiles(*.*)|*.*\';'
+ '$dialog.Filter = \'AllFiles(*.*)|*.*\';'
                +'$dialog.InitialDirectory = \'C:\\\';'
+ '$dialog.InitialDirectory = \'C:\\\';'
                +'$dialog.Title = \'ファイル選択\';'
+ '$dialog.Title = \'ファイル選択\';'
                +'$dialog.Multiselect = $true;'
+ '$dialog.Multiselect = $true;'
                +'if($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){ Set-Clipboard $dialog.FileNames }'
+ 'if($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){ Set-Clipboard $dialog.FileNames }'
  new ActiveXObject('WScript.Shell').Run(
new ActiveXObject('WScript.Shell').Run(
      'PowerShell.EXE -sta -ExecutionPolicy RemoteSigned ' + PS1Source, 0, true
'PowerShell.EXE -sta -ExecutionPolicy RemoteSigned ' + PS1Source, 0, true
  );
);
  var result=ClipboardData.GetData();
var result = ClipboardData.GetData();
  ClipboardData.ClearData();
ClipboardData.ClearData();
  return result;
return result;
}
}
</syntaxhighlight>
</syntaxhighlight>


== Prompt で空入力とキャンセルの区別 ==
== Prompt で空入力とキャンセルの区別 ==
できません。
Ver 3.7.13 以降では空欄で [OK] ボタンを押した場合は空文字列を返し、[キャンセル] ボタンを押した場合は<code>null</code>を返すようになりました。
 
Ver 3.7.12 以前では両方とも空文字列を返すので区別できません。


== PopupMenu.Add の ID ==
== PopupMenu.Add の ID ==
PopupMenu.Add() の ID は必ず 0 以外にしましょう。
PopupMenu.Add() の ID は必ず 0 以外にしましょう。


PopupMenu.Track() はキャンセルされた(メニューが押されなかった)場合、0 を返します
PopupMenu.Track() はキャンセルされた(メニューが押されなかった)場合、0 を返します。

2025年8月31日 (日) 11:22時点における最新版

マクロ開発者向けの覚え書きです。

リファレンスなどに載っていない、豆知識的なことを集めています。

開発言語について[編集]

WSH (Windows Script Host) が対応している言語であれば利用が可能です。

標準では JScript(≒JavaScript)と VBScript が入っています。

他の言語(Perl や Python)もインストールすれば使えますが、一般配布する場合利用者もインストールが必要になります。

どの言語でも良いですが、JScript での開発者が多いため、JScript の方が情報が集まりやすくお勧めです。

マクロを保存する際の文字コード[編集]

基本的に単体で利用する場合はどの文字コードでも構いません。

ただし「他のマクロから読まれる」場合は文字コードの選択が重要になります。

今のマクロでは #title のようなプリプロセス処理が必要で、それに対応したロードができる includeライブラリの IO.Include はデフォルトで UTF-8 対応なので、UTF-8 をお勧めします(個別の指定は可能)。

ただし読み込む側が FileSystemObject を利用している場合、SJIS/Unicode しか対応できないのでその場合は SJIS をお勧めします(Mery 1 時代のマクロなどはコレです)。

window.Document と editor.ActiveDocument の違い[編集]

window.Document は、マクロ開始時にアクティブなドキュメントを指し続けます。マクロで別のドキュメントを Activate しても変わりません。

editor.ActiveDocument は、その時点でアクティブなドキュメントを指します。マクロで別のドキュメントを Activate すると当然変わります。

editor.documents.Item(0).Activate();
Alert(document.Name);
Alert(editor.ActiveDocument.Name);

また、window.Document は documents.Item() と一致しませんが、editor.ActiveDocument は一致します。

for (var i = 0; i < editor.documents.Count; i++) {
	if (editor.ActiveDocument == editor.documents.Item(i)) {
		Alert("editor.ActiveDocument が一致");
	}
	if (Document == editor.documents.Item(i)) {
		Alert("window.Document が一致");
	}
}

window.Redraw = true は必要か[編集]

マクロで

Redraw = false;

にしたとき、最後

Redraw = true;

が必要かという点については、現状確認する限りでは不要です。

矩形選択の扱い[編集]

マクロで矩形選択は扱えません(プラグインですら無理)。

ただし、矩形選択中かの判定だけは以下の方法で可能です。

var sel = document.selection;
var isBoxed = (sel.GetBottomPointY(mePosView) - sel.GetTopPointY(mePosView)) != (sel.Text.match(/\n/g) || []).length;

使い道は限られますが、Alt + Shit + カーソル移動のキーコードを送ることで、矩形範囲指定の開始と範囲変更は可能です。

new ActiveXObject("WScript.Shell").SendKeys("+%{left}"); //{right},{up},{down}

document.GetLines の引数[編集]

Ver 3.3.2 以降では引数を省略すると論理行単位での行数取得になります。

Ver 3.3.1 以前では引数に 0 を渡すと論理行単位での行数取得になります。

meGetLineLogical という定数はありません。

プリプロセス(#title など)[編集]

対応しているプリプロセスコードは以下の通りです(詳細はディレクティブを参照)。

  • #title = "****" ツール バーのボタンに表示するタイトルの文字列を指定します。
  • #tooltip = "****" ツール バーのボタンにマウスを乗せたときに表示されるヒントの文字列を指定します。
  • #begingroup = true [マクロ] メニューおよびマクロ バーの項目の手前に区切りバーを挿入します。
  • #icon = "****" [, アイコン番号] ツール バーのボタンに表示するアイコンを指定します。
  • #icondark = "****" [, アイコン番号] ダークモード有効時にツール バーのボタンに表示するアイコンを指定します。
  • #include "****.js" 指定したファイルをマクロの先頭に含めます。
  • #language = "****" スクリプト言語を指定します。

これらは必ず ファイル先頭 に書かなければなりません(コメントや VBS の Option Explicit などよりも先)。

他のファイルのロード方法[編集]

マクロから他のファイルを直接ロードするには以下の方法があります。

  • FileSystemObject を利用する
  • ADODB.Stream を利用する
  • includeライブラリの IO クラスを利用する

FileSystemObject を利用する[編集]

コードが短く簡単に扱えます。

また FileSystemObject 自体に、ファイルの有無やフォルダ作成の機能があります。

ただし扱える文字コードは SJIS または Unicode 限定。

// Scripting.FileSystemObject の定数
var ForReading = 1;          // ファイルを読み取り専用として開きます。このファイルには書き込むことができません。
var ForWriting = 2;          // ファイルを書き込み専用として開きます。
var ForAppending = 8;        // ファイルを開き、ファイルの最後に追加して書き込みます。
var TristateUseDefault = -2; // システム デフォルトを使ってファイルを開きます。
var TriStateTrue = -1;       // ファイルを Unicode ファイルとして開きます。
var TristateFalse = 0;       // ファイルを ASCII ファイルとして開きます。

var fso = new ActiveXObject("Scripting.FileSystemObject");

// ファイルの読み込み
var fsIn = fso.OpenTextFile(document.FullName, ForReading, false, TristateUseDefault);
var text = fsIn.ReadAll();
fsIn.Close();
Alert(text);

// ファイルの書き込み
var fsOut = fso.OpenTextFile("hoge.txt", ForWriting, true, TristateUseDefault);
fsOut.Write(text);
fsOut.Close();

ADODB.Stream を利用する[編集]

書き方は若干複雑ですが、システムが対応している文字コードであれば全て扱えます。

また(信頼性は低いが)文字コードの自動判定も可能です。

var adTypeBinary = 1;          // バイナリ データを表します。
var adTypeText = 2;            // 既定値です。Charset で指定された文字セットにあるテキスト データを表します。
var adReadAll = -1;            // 既定値です。現在の位置から EOS マーカー方向に、すべてのバイトをストリームから読み取ります。これは、バイナリ ストリームに唯一有効な StreamReadEnum 値です。
var adReadLine = -2;           // ストリームから次の行を読み取ります (LineSeparator プロパティで指定)。
var adSaveCreateNotExist = 1;  // 既定値です。FileName パラメータで指定したファイルがない場合は新しいファイルが作成されます。
var adSaveCreateOverWrite = 2; // FileName パラメータで指定したファイルがある場合は、現在開かれている Stream オブジェクトのデータでファイルが上書きされます。

// ファイルの読み込み
var adodb = new ActiveXObject('ADODB.Stream');
adodb.Type = adTypeText;
adodb.Charset = 'utf-8';
adodb.Open();
adodb.LoadFromFile(document.FullName);
var text = adodb.ReadText(adReadAll);
adodb.Close();
Alert(text);

// ファイルの書き込み
var adodb = new ActiveXObject('ADODB.Stream');
adodb.Type = adTypeText;
adodb.Charset = 'utf-8';
adodb.Open();
adodb.WriteText(text);
adodb.SaveToFile("hoge.txt", adSaveCreateOverWrite);
adodb.Close();

includeライブラリの IO クラスを利用する[編集]

ファイルの読み書きを簡単にするクラスです。

簡単に扱えることと、BOM なしの UTF-8 を書き込めることがメリットです。

逆にソースを読むしか資料がないこと、ユーザに導入してもらう必要があるのが欠点です。

#include "include/IO.js"

// ファイルの読み込み
var text = IO.LoadFromFile(document.FullName, "utf-8");
Alert(text);

// ファイルの書き込み
IO.SaveToFile("hoge.txt", text, "utf-8");

他のマクロの実行方法[編集]

他のマクロを実行するには、以下の方法があります。

1つ目は先頭でしか書けない上、動的にロードの切り替えができません。

2つ目は文字コードの問題とプリプロセス処理に関する問題があります。

includeライブラリの IO.Include を使うことで、プリプロセス処理に関しては解決できます。

#include "include/IO.js"

eval(IO.Include("test.js", "utf-8")); // #include なども処理される

3つ目は任意の場所で指定したマクロを実行することができます。

マクロからファイル選択ダイアログ[編集]

以下の関数で可能です。

function OpenFileDlg() {
	var HTASource =
		'<object id=HtmlDlgHelper classid=CLSID:3050f4e1-98b5-11cf-bb82-00aa00bdce0b></object>\n'
		+ '<script language=vbscript>\n'
		+ 'resizeTo 0,0\n'
		+ 'Sub window_onload()\n'
		+ 'CreateObject("Scripting.FileSystemObject").GetStandardStream(1).Write HtmlDlgHelper.object.openfiledlg(,,"All Files(*.*)|*.*|","ファイル選択")\n'
		+ 'close\n'
		+ 'End Sub\n'
		+ '</script>\n'
		+ '<hta:application caption=no showintaskbar=no />\n';

	var oExec = new ActiveXObject('WScript.Shell').Exec(
		'MSHTA.EXE "javascript:new ActiveXObject(\'Scripting.FileSystemObject\').GetStandardStream(0).ReadAll()"'
	);
	oExec.StdIn.Write(HTASource);
	oExec.StdIn.Close();

	var filename = oExec.StdOut.ReadAll();
	var nullcharAt = filename.indexOf(String.fromCharCode(0x0));
	if (nullcharAt > 0) {
		filename = filename.substring(0, nullcharAt);
	}
	return filename;
}

使用例

var filename = OpenFileDlg();
window.alert((filename) ? filename : 'Canceled');

PowerShell 版[編集]

HtmlDlgHelper.object.openfiledlg の第1引数はダイアログに初期表示する InitFile。疑似的に初期フォルダを指定することが可能だが、パス区切り文字 "\" で終わることはできない。PowerShell 版なら初期フォルダの明示、複数ファイル選択が可能。Multiselect = $false にしても $dialog.FileName に書き換えせずに $dialog.FileNames でアクセス可能。

function OpenFileDlg() {
	ClipboardData.ClearData();
	var PS1Source =
		'[void][System.Reflection.Assembly]::LoadWithPartialName(\'System.windows.forms\');'
		+ '$dialog = New-Object System.Windows.Forms.OpenFileDialog;'
		+ '$dialog.Filter = \'AllFiles(*.*)|*.*\';'
		+ '$dialog.InitialDirectory = \'C:\\\';'
		+ '$dialog.Title = \'ファイル選択\';'
		+ '$dialog.Multiselect = $true;'
		+ 'if($dialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK){ Set-Clipboard $dialog.FileNames }'
	new ActiveXObject('WScript.Shell').Run(
		'PowerShell.EXE -sta -ExecutionPolicy RemoteSigned ' + PS1Source, 0, true
	);
	var result = ClipboardData.GetData();
	ClipboardData.ClearData();
	return result;
}

Prompt で空入力とキャンセルの区別[編集]

Ver 3.7.13 以降では空欄で [OK] ボタンを押した場合は空文字列を返し、[キャンセル] ボタンを押した場合はnullを返すようになりました。

Ver 3.7.12 以前では両方とも空文字列を返すので区別できません。

PopupMenu.Add の ID[編集]

PopupMenu.Add() の ID は必ず 0 以外にしましょう。

PopupMenu.Track() はキャンセルされた(メニューが押されなかった)場合、0 を返します。

スポンサーリンク