VBAの開発画面(VBE)には様々なウィンドウがありますが、その中でも特に奥が深いのがイミディエイトウィンドウです。
イミディエイトウィンドウをどれだけ使いこなしているかで、その人のVBAプログラミングスキルがどれ程のものかひと目で分かる(かもしれません)
今回はそんなイミディエイトウィンドウだけに焦点を絞って、徹底的に紹介していきます。
- イミディエイトウィンドウとは
- なぜイミディエイトウィンドウを使うのか
- VBEのイミディエイトウィンドウの使い方
- イミディエイトウィンドウの活用事例集
- プロシージャ(Sub)を実行する
- プロシージャ(Function)を実行する
- 文字コードが知りたい
- IF文を使いたい
- For文を使いたい
- For文の中でIfを使いたい
- デバッグ中にループカウンタを少し戻したい
- Trueが整数の何に当たるか知りたい
- VBAの式がどのように評価されるのか知りたい
- いますぐApplication配下のスイッチを変えたい
- 全てのシートを表示状態にしたい
- 全てのシートを保護したい/保護解除したい
- 全てのシートの選択セルをA1に戻したい
- 全てのシートの選択セルをA1に戻すと共に先頭シートに戻りたい
- 全てのシートのズーム倍率を統一したい
- 全てのシートにウィンドウ枠の固定を適用したい
- ウィンドウが非表示のブックを閉じたい
- 開いてるエクセルブックのパスが知りたい
- アドインのシートを表示したい
- 直前のエラーのメッセージをコピペしたい
- 選択セルのデータ型が知りたい
- 配列の中身を全部出力したい
- 表の値をArrayのリテラルに使いたい
- 広範囲のセルを選択したい
- セルを一行おきに選択したい
- 選択範囲のセルを絞り込みたい
- 選択範囲にアドレスを埋め込みたい
- 選択範囲のセルを結合する数式(CONCATENATE関数)を作りたい
- 入力規則の入ったセルのアドレスを列挙したい
- 全てのシートから入力規則を削除したい
- EXCEL方眼紙の文字列を結合したい
- 結合セルを分解して同じ値で埋めたい
- ダブルクォーテーションを含む文字列の生成式が難しいので練習したい
- テーブルを管理するクラスのヘッダの宣言文を作りたい
- その他のTIPS
- 関連ツイート
- まとめ
イミディエイトウィンドウとは
1行のプログラムを書いてEnterキーを押すだけで、瞬時に実行結果が分かるというVBA開発環境の便利な機能です。
Excelを開いて Alt+F11
→ Ctrl+G
→ コードを入力 → Enter
と入力するだけで実施できます。
例えば、 Selection = "Hello World"
と入力すれば、選択しているセルに Hello World
と入力され、 ?Selection
と入力すれば Hellow World
とイミディエイトに出力 されます。そして Range("Z10").Select
と入力すれば、セル Z10 を選択させることだって出来ます。
Windowsでコマンドプロンプトの実行が Win+R
→ cmd
→ Enter
→ コマンドを入力 → Enter
なのと、同じです。
いわば、Office版のコンソールだと言えるでしょう。
個人的にVBAプログラミングで一番初めにすべきことは、「開発タブの表示」でも、「標準モジュールの作成」でも、「言語仕様の勉強」でもなく、「イミディエイトでの1行プログラムの実行」だと思っています。
プログラミングは1行のプログラムの組み合わせなのですから、1行ごとの挙動を正確に理解することが重要です。そのためにはイミディエイトウィンドウが最も適しています。
※イミディエイトウィンドウで下書きしたコードを組み合わせて開発を進めることを、即時駆動開発と勝手に命名して呼ぶことにしました。( IDD : Immediate-Driven Development )
使っている様子を少しだけ動画にしてみました。
なぜイミディエイトウィンドウを使うのか
イミディエイトの利用シーンは、大まかに3種類に分類できます。
- コーディング中に、VBAコードの動作検証や文法確認を行うため
- デバッグ中に割り込みで、変数の読み書きを行うプログラムを実行するため
- 作業を支援するワンライナー(1行のプログラム)や開発済みのマクロを直ちに実行するため
1.コーディング中に文法や関数を確認する
長年VBAを書いている人でも、仕様を完璧に頭に入れているわけではありません。
記憶がただしいか不安に感じる時や、テストコードだけでは納得できない時があります。
コーディング中に少しでも疑問を感じたら、即座にイミディエイトで確認すると、潜在バグを潰し開発が効率的に進められます。
?IsNumeric("123,456") True ?UBound(Split("a,b,c",",")) 2
2.デバッグ中に変数の書き換えや情報出力を行う
下記のいずれかの方法でプログラムを中断させることで、デバッグモードに入ることが出来ます。
- ブレークポイントの設定
- Stop や Debug.Assert
- 実行時エラー
- ウォッチウィンドウに設定した条件一致
- ESC、Ctrl+Pause/Breakキー
デバッグモードでは、現在の実行スコープにおいて、イミディエイトからプログラムを割り込みで実行できます。
例えば、ブックのパスを調べるとか
?ThisWorkbook.Path C:\~~~~.xlsm
強引に再計算を行うとか
Application.CalculateFullRebuild
For文のカウンタを書き換えるとか
i = 1
このような場面で、本当によく使われます。
また、 Ctrl+L
で【呼び出し履歴】を開くことで、対象のプロシージャを移動してバグの原因を調べることもできます。
マクロの中断方法については下記を参照。
StopとDebug.Assertについては下記を参照。
3.作業を支援するために使用する
VBAに慣れてくると、手作業で行うより即興でプログラムを書いたほうが早い場合があります。
例えば、Excelで「全ての非表示シートを再表示する」とか、「選択範囲の大きさを変えずに1行下にずらした範囲を選択する」とかの用途で使います。
For Each ws in worksheets : ws.visible=-1 : next Selection.Offset(1).Select
VBAのコーディングにおいても、イミディエイトを使うと便利なことがたくさんあります。
例えば、テストプロシージャを実行する時とか、数値が法則性のあるソースコードを作るときとか。
開発支援ツールとしても、使うことが出来るのです。
なお、ちょっと複雑なものや利用頻度の多いものは事前にマクロを作っておき、イミディエイトから呼び出すだけにしたほうが簡単です。でも、簡単なものなら準備不要でいつでも使えるのが強みの一つです。
VBEのイミディエイトウィンドウの使い方
便利な操作テクニック全集
これだけ抑えておけば、貴方も立派なイミディエイトマスターです!
Ctrl+G
でイミディエイトウィンドウを開きフォーカスを移動できる。F7
でコードウィンドウにフォーカスを戻れる。Debug.Print
の結果がイミディエイトウィンドウに出力される。- イミディエイトでは
Debug.
を省略してPrint
と書いても良い。 ?
(クエスチョンマーク) を使えばPrint
すら書かなくて良い。(?1+1
は2
と出力される。)- (VBE共通)
Ctrl+Space
でインテリセンス(入力補完)が使える。 - (VBE共通)
Ctrl+End
で末尾に、Ctrl+Home
で先頭に飛べる。 Enter
を押すと選択中の行が実行されて、次の行に結果が出力される。- カレントのプロジェクト/モジュールに対して実行される。(VBEタイトルバー参照)
モジュール名.プロシージャ名
と書けば、異なるモジュールやPrivateレベルプロシージャ
も実行できる。- デバッグモード中に行うイミディエイトからの実行は現在のプロシージャに対して実行されるので、ローカル変数の書き換えができる。
- (VBE共通)
Ctrl+L
(呼び出し履歴) で、書き換え対象のプロシージャは移動できる。 - 非デバッグ中でもモジュールレベル以上の広域変数は書き換えられる。
Ctrl+Enter
で現在の行を実行せずに改行を挿入できる。- (VBE共通)
Ctrl+N
で現在の一つ上に行を挿入できる。 - (VBE共通)
Ctrl+Y
で現在の行を切り取りできる。 ;
(セミコロン)は出力が改行されない。また、連続して書ける。?"a";"b";
はab
と出力される。- 数値は前後に半角スペースが1つ入る
?1;2;3
は_1__2__3_
と出力される。 ,
(カンマ)は出力が改行されない。 8文字毎や14文字毎になるように0文字以上の半角スペースが入る。 また、連続して書ける。?"a","b"
はa_____________b
と出力される。:
(コロン)を使えばステートメントを連結して一行にまとめる事が出来る。(マルチステートメント)- 行末に
_
(アンダースコア) を付けると、ステートメントを次の行へ折り返すことができる。 - ログに残るのは200行まで。セミコロンで終わらせた場合を除いて通常は199行しか残らない。
- イミディエイトへの出力は結構重い。ループの中に記載するとマクロが急激に遅くなるので、本番ではコメントアウトするか条件付きコンパイルで無効化するのが望ましい。
- イミディエイトウィンドウがポップアップ表示のときだけ
Alt+Enter
でコードウィンドウに戻れる。(厳密には直前のウィンドウに戻るショトカ)
ここまで徹底的に網羅している書籍・記事はきっと無いでしょう(笑)
上記のうち、分かりづらいものを解説します。
データ型による整形
Debug.Print では、値のデータ型によって整形が行われます。
数値では、前後に1字付与されます。
先頭には、値がプラスなら半角スペース、マイナスならマイナス符号が付きます。
末尾に必ず半角スペースが1字付きます。
(※以下、見やすいように半角スペースはアンダースコアで可視化)
?1 _1_ ?-1 -1_ ?1.234 _1.234_
日付では、末尾に半角スペースが1字付与されます。
?#2018/1/1# 2018/01/01_
文字列型ではなにも付与されません。
?"a"
a
セミコロンとカンマによる整形と連結
Debug.Print 及びセミコロンやカンマを使った文法は、VBAの中でもかなり特殊な文法で、プロシージャで引数の区切りを表すために使われるカンマとは全く別の性質を持ちます。
Debug.Print は、原則として末尾に改行を挿入します。 しかし、末尾にセミコロンやカンマを記入すると改行を防止することができます。
Sub Test() Debug.Print "これは"; Debug.Print "セミコロンを使った"; Debug.Print "分割出力の"; Debug.Print "テストです。" End Sub これはセミコロンを使った分割出力のテストです。
また、セミコロンやカンマで区切って複数の値を指定することもできます。
それぞれの値がデータ型による整形された状態で、続けて出力されます。
たとえば、セミコロンの場合は以下のような動作をします。
?1;1 _1__1_ ?1;-1 _1_-1_
?"a";"b" ab
カンマで区切った場合は、セミコロンの性質に加えて半角スペースの自動挿入が行われます。
いわゆるTABのように一定間隔になるように半角スペースが挿入された上で(以下、これをブロック幅と呼びます)、データ型によって整形される文字が付与されます。
ブロック幅は環境によって違うときがあるため、法則がよく分かっていません。
執筆時(2019/2/10)は下記のように1ブロック14桁毎でした。(数値は11桁まで、文字列は13桁までが1ブロックに収まる限界となった)
しかし、数カ月後(2019/9/28)に試したら1ブロック8桁になっていました。
挿入される空白の個数は0以上であり、カンマを入れても半角スペースが挿入されないという罠があるので文字列型の出力では注意が必要です。
?12345678901,2 _12345678901___2_ ?123456789012,2 _123456789012________________2_ ?"1234567890123","1234567890123" 1234567890123_1234567890123 ?"12345678901234","1234567890123" 12345678901234______________1234567890123
コロンとアンダースコアによるステートメントの連結と折り返し
どちらも通常のソースコードで使えるVBの記法ですが、イミディエイトでも使用可能です。
イミディエイトは「Enterを押した瞬間にカーソルの行のプログラムを実行する」というコマンドプロンプトみたいな機能です。
そのため、複数のステートメントから構成されるForなどは書けません。
でも、コロンを使えば後述するForが1行で書けます。
For i = 1 To 5 : ?i : Next
しかし、末尾にアンダースコアがある場合「まだ続きがある」と認識するため、実行されません。 その場合、アンダースコアの付いていない行でEnterした時に、そこまでのステートメントを連結して一気に実行します。
つまり、アンダースコアを組み合わせることで、擬似的に複数行For文を書いて実行することができます。
For i = 1 To 5 : _ ?i : _ Next
バッドノウハウ
Ctrl+Zを押してもイミディエイトウィンドウは戻せない。
- コードの方が戻って大変なことになります。
- でも、直前に書いていたコードに飛べるので便利なことも結構あったり・・・。
未定義の変数でもエラーにならない。
- イミディエイトウィンドウはOption Explicit されません。
- 気をつけないとタイプミスでハマります。
- 一方でForやForEachのカウンタが無宣言で使えるので便利なことも・・・。
VBAからイミディエイトウィンドウを消すコードが提供されていない。
- 手動操作(
Ctrl+A
→Delete
やCtrl+X
やCtrl+BackSpace
)くらいしか方法が無い。 - ただし強引に消す方法は存在する。サンプルはTIPSに記載した。
- 手動操作(
切り取り
/コピー
/貼り付け
が使えなくなる時がある。- コマンドがグレーアウトしており、
Ctrl+X
/Ctrl+C
/Ctrl+V
も使えない。 - 原因はカレントのプロジェクトがパスワードでロックされているから。
- しかしイミディエイトへの直接入力と実行は出来るので、パスワードでロックされたプロジェクトに対してもコードの実行ができてしまう。(悪用厳禁)
- コマンドがグレーアウトしており、
数値を右寄せで整列させたくても、適切な関数が存在しない。
- サンプルの汎用関数をTIPSに記載した。
イミディエイトウィンドウの活用事例集
以上の仕様を理解できたとして、実際に使いこなせるかどうかは別の話。
アイディアの詰まった素敵なワンライナーを紹介します。(実用性はマチマチですが)
プロシージャ(Sub)を実行する
テストプロシージャを実行したり、ちょっと使いたいマクロを名前から実行するのに便利です。
Proc "a" 'Procプロシージャが実行される
Subの実行結果は、基本的にイミディエイトに現れません。
意図的に Debug.Print
を書けば出力できますが、それで完成とするのは望ましくありません。
戻り値が設定可能なら、次のFunctionに変更することも検討してください。
プロシージャ(Function)を実行する
関数は先頭に はてなマーク
を付けて実行すると、イミディエイトに結果が出力されるのでデバッグしやすくなります。
?FuncSum(10,3) 13
簡易的なデバッグは、ここで値を変えながら繰り返し実行してテストをします。
本気でテストが必要な場合は、テスト用プロシージャを作るか、テスト用ワークシートを作成して、シートから関数を実行する方法があります。
文字コードが知りたい
文字コードが思い出せなくて困る時。ありますよね?
?asc("A") 'A の文字コードが知りたい 65 ?asc("""") 'ダブルクォーテーションの文字コードが知りたい 34
IF文を使いたい
IF文は少し特殊な文法となっており、(コロンを使わずとも)複数のステートメントを一行で書く事ができます。
この時、End If
は不要になるのでご注意を。
If a=1 Then ?1 Else ?2 2
For文を使いたい
For文などは最低でも3ステートメント必要なのでイミディエイトウィンドウで使えないように思えますが、コロンを使ってマルチステートメントにすればできます。
For i = 1 To 5 : ?i : Next 1 2 3 4 5
上記のままだと、ログがすごい勢いで流れてしまうので、末尾にセミコロンを付けると勝手が良くなります。
For i = 1 To 5 : ?i; : Next 1 2 3 4 5
でもカーソルが遥か彼方の右端に飛ぶので、Ctrl+Enter
を使って改行を挿入してから終わりましょう。(そうしないと、次の出力が同じ行の続きからになります)
なお、Ctrl+Enter
はイミディエイトを実行せずに改行を挿入するショートカットキーです。
For文の中でIfを使いたい
このような使い方はあまりしないかもしれませんが、知らないと苦労するので書いておきます。
実行出来ない悪い例
For i = 1 To 5 : If i Mod 2 Then : ?1 Else ?2 : End If : Next 'コンパイルエラー 行頭のみ許されるステートメントです。
For i = 1 To 5 : If i Mod 2 Then ?1 Else ?2 : Next 'コンパイルエラー Next に対応する For がありません。
IF文とは別物ですが、IIF関数を使えば対応できます。
For i = 1 To 5 : ?iif(i Mod 2, 1, 2); : Next 1 2 1 2 1
デバッグ中にループカウンタを少し戻したい
For文のデバッグ中にもう一度同じ行をやり直したい時とか、一つ前に戻りたい時とかに。
i=i-1
Trueが整数の何に当たるか知りたい
私、たまに混乱するんですよね。(いい加減に覚えてもいいんじゃないか?と思いますが。)
?true True ?0+true -1
覚えられない原因はExcelの数式とVBAで仕様が違うからだったりします。
表に整理するとこんな感じ。
- | FALSE | TRUE | ことりちゅん式の思い出し方 |
---|---|---|---|
EXCEL | 0 | 1(0以外) | TRUEをSUMしてカウントするテクニックで使うから |
VBA | 0 | -1(0以外) | 0のビットを反転させると-1だから |
VBAの式がどのように評価されるのか知りたい
稀にしか使わない演算子は、細かい仕様が思い出せないときがあります。
複数言語をやっている人は、演算子の違いで混乱するので、重宝すると思います。
?10 / 3 3.33333333333333 ?10 \ 3 3 ?10 mod 3 1 ?10 and 3 2 ?10^3 1000 ?"1"=1 True
いますぐApplication配下のスイッチを変えたい
高速化等のために切ることがありますが、逆に遅くなっている原因やエラーを発見しづらくなってしまうという問題があります。
ちょっとした作業中に機能をON/OFFしたい時もあります。
Application.EnableEvents = True Application.ScreenUpdating = True Application.DisplayAlerts = True Application.Calculation = xlCalculationAutomatic
マニュアルなんかを作成している時は、作業スペースを確保するために不要なツールバーを消したいときがあります。
そんな時はこの辺のコマンドを叩いてウィンドウをスッキリさせます。
Application.DisplayStatusBar = False Application.DisplayFormulaBar = False Application.DisplayFullScreen = False 'Alt+V+Uでも出来る
マクロ実行中に式の値が狂っている時に、再計算目的でもよく使います。
'開いている全てのブック、シートの全数式を再計算する Application.CalculateFullRebuild
全てのシートを表示状態にしたい
Excelはシートの非表示は一括でできるのに、一括で再表示する機能がありません。
シート数が多いとかなり面倒なことになります。
For Each ws in worksheets : ws.visible=-1 : next
※ちなみに非表示シートの一括削除ならドキュメントの検査から出来ます。 ※Office365 2020年末頃のアップデートで、再表示画面でシートの複数選択がサポートされました。
全てのシートを保護したい/保護解除したい
Twitterにて情報をいただきました。
GUIからはシートの一括操作が出来ないので、配布前とかに便利です。
For Each ws In Worksheets: ws.Protect: Next
For Each ws In Worksheets: ws.Unprotect: Next
全てのシートの選択セルをA1に戻したい
これも配布前に是非使いたいやつ。
For Each ws In Worksheets: ws.Select: [A1].Select: Next
全てのシートの選択セルをA1に戻すと共に先頭シートに戻りたい
上記をより実用的にしたものです。
- シートが逆順になったことで先頭シートがアクティブな状態で完了します。
- ウィンドウ枠の固定がされた状態でも、必ずスクロール状態が先頭に戻ります。
For i = Sheets.Count To 1 Step -1: Application.Goto Sheets(i).[A1], True: Next
全てのシートのズーム倍率を統一したい
これまた配布前に是非使いたいやつ。
For Each ws In Worksheets: ws.Select: ActiveWindow.Zoom=80: Next
配布用前に実行しておきたいコマンドは結構多いので、まとめて個人用マクロやアドインに組み込んだほうが良いかもしれません。
全てのシートにウィンドウ枠の固定を適用したい
Accessからエクスポートしたテーブルをエクセルで使う時に真っ先に実行するやつ。
For Each ws In Worksheets: ws.Select: [B2].Select: ActiveWindow.FreezePanes=True: Next
ウィンドウが非表示のブックを閉じたい
※閉じたいプロジェクトを選択してから実行
アドインとかPERSONAL.XLSB
が邪魔な時に。
ThisWorkbook.Close
開いてるエクセルブックのパスが知りたい
筆者、これ、とても良く使います。未保存のブックだと何も出力されないので気をつけて~
?ThisWorkbook.Path C:\~~~~.xlsm
アドインのシートを表示したい
アドイン固有の設定値をシートに保存させている場合に。(悪用厳禁?)
保存に支障が出るので、用事が済んたらTrueに戻しましょう。
ThisWorkbook.IsAddin = False
直前のエラーのメッセージをコピペしたい
誰かに質問する時は必ずコードと一緒にエラーメッセージも送りましょう。
?Err.Description
選択セルのデータ型が知りたい
謎の動きをした時はとりあえず型をチェック!
?typename(Selection.Value) String ?typename(Selection) Range
配列の中身を全部出力したい
一次元配列ならJoinを使えば一発です。
?Join(arr, vbTab) a b c
二次元配列だとForしかなさそうです。
?for i=1 To ubound(arr):?arr(i,1);:next
表の値をArrayのリテラルに使いたい
For Each r In Selection : ?"""" & r & ""","; :Next "あああ","いいい","ううう","えええ",
これをコピペして、Arr = Array("あああ","いいい","ううう","えええ")
で完成っと!
広範囲のセルを選択したい
例えば、現在の選択しているセルを基準に100x100の範囲を選択したい時。
Selection.Resize(100,100).Select
セルを一行おきに選択したい
このコマンドを実行した後、削除、挿入、着色なんでも出来ます。
For i = 1 To 100 Step 2: Union(Selection, Rows(i)).Select: Next
もちろん列もOK
For i = 1 To 100 Step 2: Union(Selection, Columns(i)).Select: Next
選択範囲のセルを絞り込みたい
選択範囲を絞り込む時Intersect()を使うと便利です。
Intersect(Selection, Columns("A:H")).Select
Intersect(Selection, ActiveSheet.UsedRange).Select
選択範囲にアドレスを埋め込みたい
for each r in Selection:r.value=r.address(0,0):next
選択範囲のセルを結合する数式(CONCATENATE関数)を作りたい
Office365やExcel 2019以降にはCONCATやTEXTJOINがありますが、無いものは仕方ありません。
=CONCAT(A1:I1)
と同等のものと作りたいとしたら、A1:I1を選択して下記を実行
for each r in Selection:?r.address(0,0);",";:next A1,B1,C1,D1,E1,F1,G1,H1,I1,
結果をコピーして=CONCATENATE(A1,B1,C1,D1,E1,F1,G1,H1,I1)
として完成!
=TEXTJOIN("-",False,A1:I1)
と同等のものと作りたいとしたら、A1:I1を選択して下記を実行
for each r in Selection:?r.address(0,0);",""" & "-""";",";:next A1,"-",B1,"-",C1,"-",D1,"-",E1,"-",F1,"-",G1,"-",H1,"-",I1,"-",
=OCONCATENATE(A1,"-",B1,"-",C1,"-",D1,"-",E1,"-",F1,"-",G1,"-",H1,"-",I1)
として完成!
入力規則の入ったセルのアドレスを列挙したい
for each r in cells.SpecialCells(xlCellTypeAllValidation):?r.address:next
全てのシートから入力規則を削除したい
リンクの解除でブックがクラッシュする場合は、結構な確率でデータの入力規則のリストが外部ファイルを参照している。
for each ws in Worksheets:ws.cells.validation.delete:next
EXCEL方眼紙の文字列を結合したい
Office365 / Excel2019はCONCAT関数で結合できますが、以前のバージョンでは一苦労です。
これならシートを汚さず素早く結合できますね。
for each r in Selection:?r;:next
結合セルを分解して同じ値で埋めたい
間違ったエクセルの使い方をする人から送られてきたデータの加工に!
for each r in Selection:r.unmerge:Selection=r.value:next
ダブルクォーテーションを含む文字列の生成式が難しいので練習したい
?"""C:\""" & "hoge\" & "file.jpg""" "C:\"hoge\file.jpg"
例えばShell関数で「出力したファイルを選択した状態でエクスプローラを開きたい」ときとかですね。
?"explorer.exe /select,""" & "path" & """ explorer.exe /select,"path"
テーブルを管理するクラスのヘッダの宣言文を作りたい
これは教えていただいて、初めて気がついたテクニックです。
ID | 名前 | 住所 | 時間 | ←ヘッダ部を選択して |
---|---|---|---|---|
0001 | hoge | ほげほげ | 102030 | |
0002 | fuga | ふがふが | 112233 | |
0003 | piyo | ぴよぴよ | 443322 |
for each r in selection:?"Public ";r;" As String":next Public ID As String Public 名前 As String Public 住所 As String Public 時間 As String
今までEXCEL関数で作ってましたが、これのほうが超かっこいいですね!
同様にTypeや列番号を定義する定数Enum、Constにも応用が効きそうです。
その他のTIPS
出力を右寄せにしたい
様々な利用方法を説明しました。
しかし一つだけどうしても解決したい問題があります。
それが数値が左寄せで出力されてしまう。ということです。
数値を確認するときは右寄せにしたいですよね。
いっその事ワークシート上に出力してしまえば済む話なのですが、イミディエイトウィンドウに出したいという時のために関数を紹介します。
適当に書いたものなので、使う時は都合の良いように直して下さい。
'14桁毎になるように右寄せにする '※14桁以上のデータは上位の桁が消える Function dpr(ParamArray vals() As Variant) As String Dim v As Variant For Each v In vals dpr = dpr & Right(String(13, " ") & CStr(v), 14) Next End Function
id:Z1000S 様よりコメント欄にてFormat関数を使う方法も提案して頂きました。
こちらのほうが可読性は良くなりそうです。
sFunction dpr(ParamArray vals() As Variant) As String Dim v As Variant For Each v In vals dpr = dpr & Format(v, String(14, "@")) Next End Function
id:umeyoshioka 様よりコメント欄にて固定長文字列を使ったサンプルを頂きました。
素晴らしいアイディアをありがとうございます。
'14桁毎になるように右寄せにする '※14桁以上のデータは上位の桁が消える Function dpr(ParamArray vals() As Variant) As String Dim v As Variant, str14 As String * 14 For Each v In vals RSet str14 = CStr(v) dpr = dpr & str14 Next End Function
テスト結果
?"1234567890123","12345" 1234567890123 12345 ?"1234567890123","123" 1234567890123 123 ?dpr("1234567890123","12345") 1234567890123 12345 ?dpr("1234567890123","123") 1234567890123 123
イミディエイトウィンドウが行方不明になった
イミディエイトウィンドウが行方不明になるというトラブルが稀にあります。
多くはデュアルディスプレイ環境で、ウィンドウが増減したことに伴うトラブルだと思いますが、対処法は2つみつかりました。
まずは、Windows共通の基本奥義。アプリケーションメニューからの移動十字キーです。
Ctrl+G → Alt+Space → 移動(M) → 十字キー → マウスに極小のウィンドウがついてくる
もう一つはVBE特有のオプションの変更です。
ツール → オプション → ドッキングタブ → チェックをOFF → コードウィンドウに出現する → 同様に操作してON
イミディエイトウィンドウをExcelのコンソールのようにしたい。
イミディエイトで右クリックして、「ドッキング可能」のチェックを外して、他のウィンドウ全てを非表示にするとイミディエイト単体のVBEが出来上がります。
これをExcelと並べて配置すれば、ほら!
なるほど!
— 神風 夜空@SES擬き (@kamikazelight) 2020年2月7日
これはいい!! pic.twitter.com/Z2ofuP3V3O
VBAからイミディエイトウィンドウの中身をリセットしたい
たまに、実行のたびにイミディエイトウィンドウを空にしたいときがあります。
ところが、コードからイミディエイトウィンドウを操作する方法は存在しません。
そのため、開発者自身の手で毎回Ctrl+A → Delete
で消すことんあるのですが、テスト回数があまりにも多い時は自動で削除したいわけです。
そんなことを考えるのは私だけではないようで、ネットで調べたところ3種類の方法が見つかりました。
- Debug.Printで流し切る
- SendKeyで消す
- APIで消す
1. ログが流れきるまで出力する
イミディエイトウィンドウは200行しか保持されないという性質を利用して、199回この改行を出力して流してしまえ。というアイディアです。
基本命令のみなのでシンプルなのが最大のメリットです。
また後に紹介する方法のような、エラーの可能性もありません。
エラーにはならないものの、Debug.Print
はVBEに負荷がかかるため、ループの中で大量に実行するとマクロ全体が遅くなります。使う場所には注意したほうが良いでしょう。
できれば条件付きコンパイルで制御し、本番では出力されないようにしておくと良いと思います。
またDebug.Print
はカーソルの位置から出力するという性質であることから、カーソルの位置が末尾にないと完全には消えないので注意が必要です。
ちなみに末尾に飛ぶにはCtrl+END
キーがおすすめです。
'空欄でログを流す 'カーソルが末尾にないと意味がない 'イミディエイトウィンドウは200行しか表示できないので改行が199個出力した時点でログが全滅する Sub DebugPrint_Flush() Debug.Print String(199, vbLf) End Sub
2. SendKeyで消す
ちょっと有名なのが Application.SendKey
で操作を再現して消す方法
VBEを開いてない時は働かないように判定しているため、「Excelのオプション」→「マクロの設定」→「VBAプロジェクトオブジェクトモデルへのアクセスを信頼する。」を有効にしないと使えないのが難点です。 この設定を変えること無く、判定する方法がないか捜索中ですですが未だに見つかりません。
また、イミディエイトの表示状態には4種類あり、状態によっては動かないとか副作用があるとか安定してないです。
'イミディエイトウィンドウを全て削除する Sub DebugPrint_Clear() On Error GoTo ENDPOINT If Application.VBE.MainWindow.Visible And _ Application.VBE.Windows("イミディエイト").Visible Then SendKeys "^{g}", False DoEvents SendKeys "^{Home}", False SendKeys "^+{End}", False SendKeys "{Del}", False SendKeys "{F7}", False End If ENDPOINT: End Sub
しかし、イミディエイトウィンドウからプロシージャを呼び出して、結果を確認するというデバッグをする場合は全て消されては困る。
そこで新たに考えたのがこちら。
'イミディエイトウィンドウの先頭行を除いてすべて削除する 'フォーカスをイミディエイトウィンドウに残す Sub DebugPrint_ClearAfter2ndLine() If Application.VBE.MainWindow.Visible And _ Application.VBE.Windows("イミディエイト").Visible Then SendKeys "^{g}", False DoEvents SendKeys "^{Home}", False SendKeys "{Down}", False SendKeys "^+{End}", False SendKeys "{Del}", False End If End Sub
3. APIで消す
SendKeyなんて方法は使いたくない。もっと良い方法はないのか。と調べていたら、StackOverflow に良さげなのがありました。
https://stackoverflow.com/questions/10203349/use-vba-to-clear-immediate-window
ただし、結局はPostMessageしており、SendKeyの問題も解決出来ておらず、色々と問題があったので放置です。
重要なヒントが隠れていそうなので、記録として残しておきます。
VBAからイミディエイトウィンドウのカーソルを末端に戻したい
カーソルの位置を末尾に移動するにはCtrl+End
です。
プロシージャでDebug.Print
を始める前に次のプロシージャを呼ぶようにしておくと、常に最終行に出力されるのようになります。これもSendKeysなので確実性はないです。
'イミディエイトウィンドウの末尾にフォーカスを移動する Sub DebugPrint_CursolMoveToLast() If Application.VBE.MainWindow.Visible And _ Application.VBE.Windows("イミディエイト").Visible Then SendKeys "^{g}", False DoEvents SendKeys "^+{End}", False SendKeys "{F7}", False DoEvents End If End Sub
イミディエイトウィンドウの内容をファイル出力したい
イミディエイトウィンドウの文字列を取得する方法が見つけられませんでした。
現実的な方法は2つあります。
- Debug.Print の代わりのプロシージャを使うようにする。
- イミディエイトウィンドウの内容をコピーで読み取ってファイルに出力する。※199行制限、開発画面の表示が必須
いずれにせよ本番運用向けであれば、エラー出力用の専用クラスを作って出力しましょう。
配列やDictionaryを見やすい表で出力したい
イミディエイトを有効活用するためには、配列やDictionary等のオブジェクトを出力するための関数を整備するのがキモとなります。
一次元配列は、先の通り Join(array, vbTab)
で対応できます。
二次元配列は、各列の文字幅をカウントして、半角スペースで埋めて幅を合わせるという処理が必要になります。
Dictionaryは、更にKeyとValueをどのように表現するかでレイアウトが変わります。
実際には各要素に更に配列やオブジェクトが入れ子になっていることも予想されます。
私は大抵のデータ構造に対応できる関数を保有していますが、ここにソースコードを載せると長くなりすぎてしまうので、いずれ記事を書いたらここにリンクを載せるかもしれません。
必要な人は作成しておくと良いでしょう。
こんなの覚えきれない
たくさんの事例を上げましたが、全部を覚えるのは不可能です。
使えそうだなと思ったものだけ、覚えておいて何度も使っているうちにスラスラ打てるようになるでしょう。
通常、ワンライナーはその場で必要になった時に即興で書くものですが、頻繁に使うようなコードはいっその事IMEに登録しておくと便利かもしれません。
たとえば、下記の記事をご覧ください。
ワンライナーである必要がなくなりますが、便利なので個人用マクロなどに登録しておき、リボンからワンクリックで呼び出せるようにすると便利かもしれませんね。
関連ツイート
元ネタは2018/11/30にTwitterにて投稿したツイートでした。
記事を書くにあたって、ネタを提供して下さった方々には心からの感謝を。
VBEのイミディエイトウィンドウの使い方
— ちゅん(・8・) (@KotorinChunChun) 2018年11月30日
1.Debug.Printは?で代用できる
2.文字の途中に改行を挿入したいときはCtrl+Enter
3.セミコロンで半角スペースが2個入る
4.コンマでタブ(半角スペースがいっぱい)が入る
5.For~Nextのような複数ステートメントの実行はコロンを使う
他にテクニックある?
休日だからって朝寝しすぎた。
— ちゅん(・8・) (@KotorinChunChun) 2019年2月10日
これから昨日の続きの記事書きます。
ところで、皆さんがイミディエイトウィンドウでよく叩くものってどんなのがありますか?
例えば、
i=i-1でカウンタを1戻す とか
?Cells(i,1) とか
?Join(arr, " ") とか
良いのがあれば載せたいです!
参考資料
Microsoft公式のイミディエイトウィンドウに関する説明はこちらです。
内容が分かりにくいことで定評ですが、公式の文章には大事なことが書いてあったりするので出来れば目を通しましょう。
まとめ
「イミディエイトウィンドウ」というネタから、随分と壮大な記事になってしまいました。
イミディエイトも、なかなか、どうして、侮れません。
ここに載せていない便利なコマンドがあれば、是非コメント等頂けると幸いです。
以上
https://www.excel-chunchun.com/archive/category/%E9%96%8B%E7%99%BA%E6%94%AF%E6%8F%B4www.excel-chunchun.com
何か御座いましたらコメント欄、またはTwitterからどうぞ♪
幸せなVBAライフを♪ ちゅんちゅん(・8・)