サクラエディタのソート用マクロとVBScriptのArrayのArrayListへの格納方法
答えは、Alt+A=昇順、Alt+D=降順、Alt+M=連続重複削除、でした。
サクラエディタのマクロで、編集画面上でソートができると便利なので、ソート用マクロを作ってみようと思う。
秀丸エディタのときはVC++で実行ファイルを作ってソートを実現したが、サクラエディタはVBScriptが使えるのでVBScript縛りで実現してみる。 +ソースコードの行数も50行程度までの縛りで。
基本的な処理は以下になる。
- 選択範囲を切り取り
- クリップボードの内容をソート
- 貼り付け
クリップボードの内容をソートする処理は以下になる。
クリップボード周りはサクラエディタのマクロ関数にあるので問題なし。
文字列の分割と配列要素の結合はVBScriptの機能にあるので問題なし。
VBScriptのArrayにはソートがないが、ArrayListを使用するとソートもできるみたい。
実験記録 No.02 : VBSで動的配列(ArrayList)を使う
ただ、基本的にはVBScriptで書くとするとArrayを途中でArrayListに格納したくなるが、1件ずつ格納する以外に方法が見つからない。
ArrayListのメソッドではどれもダメだった。
- AddRange … ICollectionのオブジェクトでないとダメ
- Insert … 値を挿入するメソッドで、配列を挿入することはできない
- コンストラクタ … CreateObjectでは渡せない、など
Arrayを使わない場合にはSystem.String→Split→System.Collections.ArrayListのようなことがあるが、System.StringはCreateOjectには使えないようなので、System.Text.StringBuilder→ToStringかな?
...結局は、Stringに代入する方法が見つからなかったので断念。
Arrayを1件ずつArrayListにAddする方法でやってみた。
あと、いろいろなソート方法を指定できるのもいいかなと思ったけど、以下の2点でこちらも断念。
- VBScriptでソート指定用のダイアログを出してその結果を受け取る必要あり。
- SortメソッドのコールバックにIComparerを用意する必要あり。
試行錯誤の結果、ソート用マクロはこうなった。
- 2017/6/8 重複なしでソートできるようにした。
マクロファイル:C:\Users\ユーザ名\AppData\Roaming\sakura\clipsort.vbs
'ソート方法を指定(選択ダイアログを作れなかった) rc = Editor.YesNoBox("昇順=はい、降順=いいえ を選択してください。") Select Case rc Case 6 'はい order = 0 '昇順 Case 7 'いいえ order = 1 '降順 End Select rc = Editor.YesNoBox("重複あり=はい、重複なし=いいえ を選択してください。") Select Case rc Case 6 'はい unique = 0 '重複あり Case 7 'いいえ unique = 1 '重複なし End Select '選択状態 mode = Editor.IsTextSelected() Select Case mode Case 0 '選択なし=全体をソート Editor.SelectAll(0) Case 1 '選択 mode = 0 '通常貼り付け Case 2 '矩形選択 mode = 1 '矩形貼り付け End Select '選択部分をクリップボードにコピー Editor.Cut(0) 'コピーした文字列を取得 clip = Editor.GetClipboard(0) '改行(LF)で分割(CR/LFはCRを残す) arr = Split(clip, vbLf) 'ソートが可能なArrayListオブジェクトを用意 Dim list Set list = CreateObject("System.Collections.ArrayList") '領域拡張が起こらないよう要素数を事前に設定 list.Capacity = UBound(arr) '最後の空行を含めない行数を算出 n = UBound(arr)-1 If arr(n) = "" or arr(n) = vbCr Then n = n - 1 End If 'Array→ArrayListのコピー(他に方法がなかった) For i=0 to n list.add(arr(i)) Next 'ソート list.Sort() '重複なしの場合は重複を削除する If unique = 1 Then pre = list.Item(n) For i=n-1 to 0 step -1 If list.Item(i) = pre Then list.RemoveAt(i) End If pre = list.Item(i) Next End If '降順の場合は逆順にする If order = 1 Then list.Reverse() End If '改行(LF)で結合して文字列化 clip = Join(list.ToArray(), vbLf) 'クリップボードに設定 rc = Editor.SetClipboard(mode, clip) '貼り付け Editor.Paste(0)