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

提供: MeryWiki
ナビゲーションに移動 検索に移動
MSY-07 (トーク | 投稿記録)
改行とマークアップの修正
MSY-07 (トーク | 投稿記録)
句読点の修正
1行目: 1行目:
== 概要 ==
== 概要 ==
マクロ開発者向けの覚え書きです.
マクロ開発者向けの覚え書きです。


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


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


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


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


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


=== マクロを保存する際の文字コード ===
=== マクロを保存する際の文字コード ===
基本的に単体で利用する場合はどの文字コードでも構いません.
基本的に単体で利用する場合はどの文字コードでも構いません。


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


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


ただし読み込む側が 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();
32行目: 32行目:
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++) {
49行目: 49行目:
Redraw = false;
Redraw = false;
</syntaxhighlight>
</syntaxhighlight>
にしたとき,最後
にしたとき、最後
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
Redraw = true;
Redraw = true;
</syntaxhighlight>
</syntaxhighlight>
が必要かという点については,現状確認する限りでは不要です.
が必要かという点については、現状確認する限りでは不要です。


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


ただし,矩形選択中かの判定だけは以下の方法で可能です.
ただし、矩形選択中かの判定だけは以下の方法で可能です。
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
var s = Document.Selection;
var s = Document.Selection;
69行目: 69行目:


=== Document.GetLines の引数 ===
=== Document.GetLines の引数 ===
リファレンスには '''meGetLineView''' しか書かれていませんが,論理行単位での行数取得には引数に 0 を渡します.
リファレンスには '''meGetLineView''' しか書かれていませんが、論理行単位での行数取得には引数に 0 を渡します。


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


=== プリプロセス(#title など) ===
=== プリプロセス(#title など) ===
対応しているプリプロセスコードは以下の通りです.
対応しているプリプロセスコードは以下の通りです。
* <code>#icon = "****" [, アイコン番号]</code>
* <code>#icon = "****" [, アイコン番号]</code>
* <code>#title = "****"</code>
* <code>#title = "****"</code>
* <code>#tooltip = "****"</code>
* <code>#tooltip = "****"</code>
* <code>#include "****.js"</code>
* <code>#include "****.js"</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>#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>#begingroup = true</code>[https://www.haijin-boys.com/software/mery/mery-2-8-0#4] (または 1 - 3 の数値. ※Mery 2.8.0 以降のみ)
* <code>#begingroup = true</code>[https://www.haijin-boys.com/software/mery/mery-2-8-0#4] (または 1 - 3 の数値。 ※Mery 2.8.0 以降のみ)


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


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


==== FileSystemObject を利用する ====
==== FileSystemObject を利用する ====
コードが短く簡単に扱えます.
コードが短く簡単に扱えます。


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


ただし扱える文字コードは SJIS または Unicode 限定.
ただし扱える文字コードは SJIS または Unicode 限定。
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
// Scripting.FileSystemObject の定数
// Scripting.FileSystemObject の定数
123行目: 123行目:


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


また(信頼性は低いが)文字コードの自動判定も可能です.
また(信頼性は低いが)文字コードの自動判定も可能です。
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
var adTypeBinary = 1;          // バイナリ データを表します。
var adTypeBinary = 1;          // バイナリ データを表します。
155行目: 155行目:


==== include ライブラリの IO クラスを利用する ====
==== include ライブラリの IO クラスを利用する ====
ファイルの読み書きを簡単にするクラスです.
ファイルの読み書きを簡単にするクラスです。


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


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


=== 他のマクロの実行方法 ===
=== 他のマクロの実行方法 ===
他のマクロを実行するには,以下の方法があります.
他のマクロを実行するには、以下の方法があります。
* #include で取り込む
* #include で取り込む
* ファイルをロードして eval する
* ファイルをロードして eval する
前者は先頭でしかかけない上,動的にロードの切り替えができません.
前者は先頭でしかかけない上、動的にロードの切り替えができません。


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


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


=== マクロからファイル選択ダイアログ ===
=== マクロからファイル選択ダイアログ ===
できません.
できません。


2019/06/11追記 (有志): 以下の関数で可能です。
2019/06/11追記 (有志): 以下の関数で可能です。
244行目: 244行目:


=== Prompt で空入力とキャンセルの区別 ===
=== Prompt で空入力とキャンセルの区別 ===
できません.
できません。


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


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

2023年5月17日 (水) 18:54時点における版

概要

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

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

覚え書き

開発言語について

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 s = Document.Selection;
var isBoxed = (s.GetBottomPointY(mePosView) - s.GetTopPointY(mePosView)) != (s.Text.match(/\n/g) || []).length;

2019/06/11追記(有志):使い道は限られますが、Alt + Shit + カーソル移動のキーコードを送ることで、矩形範囲指定の開始と範囲変更は可能です。

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

Document.GetLines の引数

リファレンスには meGetLineView しか書かれていませんが、論理行単位での行数取得には引数に 0 を渡します。

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

プリプロセス(#title など)

対応しているプリプロセスコードは以下の通りです。

  • #icon = "****" [, アイコン番号]
  • #title = "****"
  • #tooltip = "****"
  • #include "****.js"
  • #language = "****"[1] (スクリプトの言語を指定。 ※省略時は "JScript(Chakra)"
  • #begingroup = true[2] (または 1 - 3 の数値。 ※Mery 2.8.0 以降のみ)

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

  • #titleは、マクロメニューやマクロバー、「ツールバーのカスタマイズ」に表示される マクロ名 です(未指定の場合はファイル名の ****.js で表示されます)。
  • #tooltipは、マクロバーにマウスカーソルをあてたときにポップアップ表示される黄色い小窓(ヒント/ツールチップ/トースト)内の 説明文 の文字列に使用されます。
  • #languageの詳細は、Mery.txt 内の更新履歴 『▼ 2018/03/22 (2.6.6)』 に記載されています。

他のファイルのロード方法

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

  • 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");

他のマクロの実行方法

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

  • #include で取り込む
  • ファイルをロードして eval する

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

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

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

#include "include/IO.js"

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

マクロからファイル選択ダイアログ

できません。

2019/06/11追記 (有志): 以下の関数で可能です。

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');

2019/06/17追記 (有志): PoserShell 版追加,, 2019/06/19 修正: Exec と標準出力の組み合わせを、Runとクリップボードに変更

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 で空入力とキャンセルの区別

できません。

PopupMenu.Add の ID

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

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

スポンサーリンク