🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →

The ExcelMaster.ai Blog

Excel VBA の Shell — 外部プログラムを起動する、そしてコードが待ってくれない理由

Excel VBA の Shell — 外部プログラムを起動する、そしてコードが待ってくれない理由

VBA の Shell 関数は外部プログラムを起動した瞬間に立ち去る、撃ちっぱなしの関数です。Shell が返すのはタスク ID であって、プログラムの終了コードでも出力でも成功フラグでもなく、次の行はプログラムがまだ起動している最中に走り出します。これが Shell コードの大半のバグ — コンバーターを Shell で起動し、まだ書き出されていないファイルを開こうとする — の正体です。この記事では、Shell が待たない理由、空白を含むパスを引用符で囲む方法、Shell が exe は起動できても PDF や URL を単独では開けない理由、そしてプログラムの完了を実際に待って出力を読むために Shell を捨てて WScript.Shell の Run や Exec に切り替える場面を解説します。

Henry
Excel VBA の Environ — ユーザーフォルダーをハードコードせずに Windows のパスを読む

Excel VBA の Environ — ユーザーフォルダーをハードコードせずに Windows のパスを読む

VBA の Environ 関数は、Windows がすべてのプログラムに渡す環境変数 — USERPROFILE、TEMP、USERNAME、APPDATA — を読み、C:\Users\John のようなハードコードなしでユーザー固有のパスを組み立てられるようにします。ハードコードは他のどのマシンでも壊れるからです。その最大の罠は静かです — 存在しない、あるいは綴りを間違えた変数はエラーではなく空文字列を返すので、名前のタイプミスは静かに空の値を返し、パスはドライブのルートに落ちます。この記事では、Environ が可搬パスの道具である理由、あらゆる結果を空になりうるものとして扱うべき理由、2 つの呼び出し形式(名前による指定と数値インデックスによる指定)、Excel 起動時に Environ が取るスナップショット、そして Environ にできないこと — 変数の設定や、起動後に変更された変数の読み取り — を解説します。

Henry
Excel VBA の CreateObject — 遅延バインディング、GetObject、そして Outlook が開いたままになる理由

Excel VBA の CreateObject — 遅延バインディング、GetObject、そして Outlook が開いたままになる理由

CreateObject は、Excel の外にあるあらゆるものへの VBA のマスターキーです — ProgID 文字列で任意の COM アプリケーションを起動します。Scripting.FileSystemObject、Scripting.Dictionary、Outlook.Application、WScript.Shell、Word.Application、どれでも同じです。その文字列による検索が遅延バインディングであり、コンパイラはそのオブジェクトについて何も知らないため、間違った ProgID やインストールされていないアプリは実行時に error 429 で初めて失敗します。この記事では、遅延バインディングと事前バインディングの本当の選択(可搬性か IntelliSense か)、CreateObject がつねに新しいインスタンスを起動する一方で GetObject が実行中のものにつなぐ理由、そして Quit と Set Nothing を忘れたときに、ヘッドレスな Outlook や Excel のプロセスがタスクマネージャーに取り残される理由を解説します。

Henry
Excel VBA の Now・Date・Time — 時計を読む、そして Date が「ステートメント」でもある理由

Excel VBA の Now・Date・Time — 時計を読む、そして Date が「ステートメント」でもある理由

VBA の日付は Double です — 整数部は 1899-12-30 からの日数、小数部はその日の時刻を表すので、Now・Date・Time は同じ時計を 3 通りに読んでいるにすぎません。Now は日付と時刻、Date は今日の 0 時、Time は時刻だけを返します。多くのコードを壊すのは、Now で保存した値を Date と比較して決して一致しないバグです。Now は小数の時刻を抱え、整数の Date は抱えないからです。さらに Date と Time は、コンピューターのシステム時計を書き換えるステートメントでもあります。この記事では Double の正体、等値比較が失敗する理由、Int や DateValue で時刻を落とす方法、そして Now が UTC ではなくローカル時刻である理由を解説します。

Henry
Excel VBA の DateAdd・DateDiff — 月の長さバグのない日付計算

Excel VBA の DateAdd・DateDiff — 月の長さバグのない日付計算

VBA の日付は Double なので、1 を足せば 1 日進み、素の足し算は正しく動きます — ただし日数のときだけです。ひと月を 30 日、1 年を 365 日として扱った瞬間に破綻します。月やうるう年は長さが一定ではないからです。DateAdd はカレンダーを知っているので、1 月 31 日に 1 か月足すと、ありえない 31 日ではなく 2 月 28 日を返します。DateDiff は経過時間ではなく越えた境界の数を数えるので、12 月 31 日から 1 月 1 日までは 1 日しか経っていなくても 1 年になります。DateSerial は年・月・日から地域差なく日付を組み立て、あふれた値を正規化するので、月末を求める定番のイディオムが書けます。この記事では素の足し算で足りる場面、つまずきやすいインターバルコード、そして DateDiff が境界の数え上げである理由を解説します。

Henry
Excel VBA の Weekday・DatePart — 日付の部品を取り出す、そして月曜日が 1 でない理由

Excel VBA の Weekday・DatePart — 日付の部品を取り出す、そして月曜日が 1 でない理由

Year・Month・Day・Hour・Minute・Second は、すでに中身の見えている Double から整数を 1 つずつ取り出すだけで、見た目どおり単純です。噛みついてくるのは Weekday です — 1 から 7 を返しますが、その番号付けは第 2 引数に左右され、既定では日曜日が 1 なので、素の呼び出しでは月曜日は 1 ではなく 2 になり、ハードコードした数値に頼った週末判定はどれも静かに間違います。DatePart は DateAdd と同じインターバルコードを使う汎用の取り出し役で、週番号や四半期のような専用関数のない部品にも届きます。ただし既定の週ルールは ISO 8601 ではありません。WeekdayName と MonthName はマシンの言語で名前を返すので、表示には向きますが読み戻しには向きません。この記事ではあらゆる部品の取り出し方と、月曜日が 1 でない理由を解説します。

Henry
VBA FreeFile と Open ステートメント in Excel — ファイル番号を取得し、テキストファイルを開く(ブックではなく)

VBA FreeFile と Open ステートメント in Excel — ファイル番号を取得し、テキストファイルを開く(ブックではなく)

組み込みの VBA では、テキストファイルは番号付きのチャネルを通して扱います — Open path For Output As #n と書くと、その番号 n は自分で選ぶのではなく FreeFile から受け取るべきハンドルになります。#1 をハードコードすると、2 つ目のファイルを開いた瞬間に error 55 File already open にぶつかり、すでにデータを持つファイルを For Output で開くと中身が空に切り詰められ、Close を忘れると Excel を終了するまでファイルはロックされたままになります。この記事では、FreeFile が変数で受け取るべきチャネル番号を渡す理由、For Output・For Append・For Input の違い、Open ステートメントが Workbooks.Open ではない理由、そしてチャネルを必ず閉じるクリーンアップのパターンを解説します。

Henry
VBA Print # と Write # in Excel — テキストファイルや CSV を書き出す(そして、あなたのファイルがすべて引用符で囲まれている理由)

VBA Print # と Write # in Excel — テキストファイルや CSV を書き出す(そして、あなたのファイルがすべて引用符で囲まれている理由)

Print # と Write # は、ディスク上のバイトがどう見えるべきかに正反対の答えを返します。Print # はテキストを見たとおりに書きます — 引用符もカンマもなく、レイアウトはあなたが組み立てます — だからレポートや手作りの CSV に向いています。Write # はマシン形式を書きます — すべての文字列を引用符で囲み、値の間にカンマを入れ、日付をハッシュで囲む — 人や Excel ではなく Input # に読み戻させるための形式です。この記事では、あなたの CSV が引用符だらけになる原因が Write # である理由、Print # リストの中のカンマが CSV のカンマではなくプリントゾーンを挿入する理由、For Output が切り詰める一方で For Append が追加する仕組み、小数点カンマのロケールの罠、そして組み込みの書き込みが UTF-8 ではなく ANSI である理由を解説します。

Henry
VBA Read Text File in Excel — Line Input と Input #、そして行を落とさない EOF ループ

VBA Read Text File in Excel — Line Input と Input #、そして行を落とさない EOF ループ

VBA でテキストファイルを読むには 3 つの道具があり、間違ったものを選ぶとデータが混線します。Line Input # は 1 行の生の行を文字列に読み込み、分割は自分で行うので、予測可能です。Input # は区切られたフィールドをそのまま変数に解析します — Write # が作ったファイルには速いのですが、引用符のないカンマや余計な引用符でつまずきます。Input(LOF(f), #f) はファイル全体を 1 つの文字列に一気に読み込みます。この記事では、すべての行をちょうど一度ずつ読む EOF ループ、Input # が Write # の双子で Line Input # が Print # の双子である理由、error 62 を発生させる off-by-one を避ける方法、そして CSV を手で解析するよりブックとして開くほうがよいのはいつかを解説します。

Henry
VBA MkDir in Excel — フォルダーを作る、そして入れ子のパスを作れない理由

VBA MkDir in Excel — フォルダーを作る、そして入れ子のパスを作れない理由

VBA の MkDir ステートメントはフォルダーをちょうど 1 階層だけ作り、パス全体は作りません — 親が存在しないパスに対する MkDir は error 76 を、すでに存在するフォルダーに対する MkDir は何もしない代わりに error 75 を発生させます。だから、このフォルダーを作るという日常の仕事は、実際には足りない階層をすべて、しかも欠けている場所にだけ作ることなのです。この記事では、MkDir が 1 階層しか作らない理由、FileSystemObject.CreateFolder もまた再帰しない理由、フルパスを安全に組み立てる存在ガード付きのループ、そして裸のフォルダー名がブックのフォルダーではなく CurDir の下に着地する理由を解説します。

Henry
VBA RmDir in Excel — フォルダーを削除する、ただし空のときだけ

VBA RmDir in Excel — フォルダーを削除する、ただし空のときだけ

VBA の RmDir ステートメントは、フォルダーが完全に空のときにだけそれを削除します — まだファイルやサブフォルダーを含むフォルダーに向けると error 75 を発生させます。これは、どんなファイルも容赦なく削除する Kill のちょうど鏡像です。だから、このフォルダーを削除するは、実際にはまず空にしてから取り除くことなのです。この記事では、RmDir が空でないフォルダーを拒む理由、フォルダーは削除してもファイルは決して削除しない理由、RmDir の前に Kill でフォルダーを空にする方法、そして FileSystemObject.DeleteFolder が 1 回の呼び出しでツリー全体を消し去るのはいつか — ごみ箱もなく取り消しもなく — を解説します。

Henry
VBA CurDir & ChDir in Excel — 相対パスが間違ったフォルダーに着地する理由

VBA CurDir & ChDir in Excel — 相対パスが間違ったフォルダーに着地する理由

VBA では、相対パスは CurDir、つまりカレントディレクトリに対して解決されるまで何の意味も持ちません — そして Excel では、そのディレクトリはあなたが制御できない移ろいやすい設定であって、ブックが保存されているフォルダーではありません。だから MkDir Reports や Open data.csv は実行のたびに別の場所に着地しかねません。ファイルを開くダイアログが CurDir を無言で動かすからです。この記事では、CurDir が ThisWorkbook.Path ではない理由、ChDir が ChDrive なしにドライブを変えられない理由、そして間違ったフォルダーのバグをまるごと取り除くたった一つの習慣 — すべてのパスを ThisWorkbook.Path に固定すること — を解説します。

Henry
Excel VBA でファイルをコピーする — FileCopy、FileSystemObject.CopyFile、そして開いているブックをコピーできない理由

Excel VBA でファイルをコピーする — FileCopy、FileSystemObject.CopyFile、そして開いているブックをコピーできない理由

VBA でファイルをコピーするのは 1 行ですが、どの 1 行を使うかはファイルが開いているかどうかで決まります。FileCopy は参照設定のいらない組み込みで、コピー先を無言で上書きしますが、開いているファイルはコピーできず、いちばんバックアップしたいブックに対して error 70 Permission denied を投げます。この記事は 3 つの状況に対応する 3 つのコピー道具の線引きを示します — ディスク上の閉じたファイルには FileCopy、ワイルドカードと明示的な上書きフラグには FileSystemObject.CopyFile、たった今開いているブックには SaveCopyAs。そして、コピー先がファイル名を含むフルパスでなければならない理由、対象フォルダーがあらかじめ存在していなければならない理由、そしてコピーしてから削除するとどうして移動になるのかを解説します。

Henry
Excel VBA でファイルを削除する — Kill、FileSystemObject.DeleteFile、そして取り消しができない理由

Excel VBA でファイルを削除する — Kill、FileSystemObject.DeleteFile、そして取り消しができない理由

VBA の Kill ステートメントはファイルを完全に削除します — ごみ箱なし、確認なし、取り消しなし。このたった一つの事実こそが目的そのものであり、危険そのものでもあり、ファイル削除に関するほかのあらゆるルールは、その取り返しのつかない一線を守るための工夫です。この記事では、ファイルが存在しないときや開いているときに Kill が何もしないのではなくエラーになる理由、Temp フォルダー内の *.tmp のようなワイルドカードが一致するすべてを確認なしで一度に消し去る仕組み、Kill がフォルダーを削除できず RmDir と DeleteFolder がその仕事をどう分担するのか、そして読み取り専用ファイルには Force フラグ付きの FileSystemObject.DeleteFile がより安全な選択になるのはいつかを解説します。

Henry
Excel VBA でファイルの名前を変更する — 移動もこなし、上書きを拒む Name ステートメント

Excel VBA でファイルの名前を変更する — 移動もこなし、上書きを拒む Name ステートメント

VBA の Name ステートメントはファイルの名前を変更しますが、実際にはリネーム兼移動のステートメントです — 新しいパスを別のフォルダーに向ければ、VBA はその場で名前を変えるのではなくファイルをそこへ移動します。そしてディスク上のほぼすべてのものと違い、Name は上書きを拒み、対象がすでに存在すると error 58 を発生させます。無言で上書きする FileCopy とはちょうど正反対です。この記事では、Name がリネームだけでなく移動もする理由、ドライブをまたげない理由とその場合を FileCopy と Kill あるいは FileSystemObject.MoveFile がどう処理するか、そして既存ファイルでのエラーが無人マクロを止めないようコピー先をガードしなければならない理由を解説します。

Henry
Excel VBA の Dir — フォルダー内のファイルをループする、そして噛みついてくるステートフルなイテレーター

Excel VBA の Dir — フォルダー内のファイルをループする、そして噛みついてくるステートフルなイテレーター

Dir は関数のように見えて、隠れた記憶を持つイテレーターのように振る舞います。Dir(path) は最初に一致したファイル名を返し、引数なしの Dir() が次を返し、フォルダーを使い切ると空文字列を返します。身を守るたった一つのルールは、Dir ループの途中で二度目の Dir を呼ばないこと。二度目の Dir は新しい検索を始めて最初の検索をリセットし、ファイルが飛ばされたり無限ループになったりするナンバーワンの原因になるからです。フォルダー内の全 .xlsx をループする方法、Dir がパスではなく名前だけを返す理由、サブフォルダーへ再帰できない理由、そしてファイルに触れる前に名前を配列へ集めるべきタイミングを学びましょう。

Henry
Excel VBA の FileSystemObject — CreateObject 対 参照設定、サブフォルダー、そしてなぜブックを開けないのか

Excel VBA の FileSystemObject — CreateObject 対 参照設定、サブフォルダー、そしてなぜブックを開けないのか

FileSystemObject はディスクをオブジェクトモデルに変えます。Dir の単一の隠れたカーソルの代わりに、For Each でループしてプロパティを読めるフォルダーとファイルです。身を守るたった一つの判断は、Dim fso As New FileSystemObject ではなく CreateObject(Scripting.FileSystemObject) を選ぶこと。遅延バインディングは参照設定なしでどのマシンでも動くのに対し、事前バインディング版は Microsoft Scripting Runtime のチェックが入っていない PC でコンパイルできなくなるからです。FSO が Dir に勝つ場面、SubFolders による再帰、Size と DateLastModified の読み方、そして FSO がテキストは開くのにブックを決して開かない理由を学びましょう。

Henry
Excel VBA でファイルの存在を確認する — Dir 対 FileSystemObject.FileExists(そして Dir ループの中の罠)

Excel VBA でファイルの存在を確認する — Dir 対 FileSystemObject.FileExists(そして Dir ループの中の罠)

VBA でファイルの存在を調べる正しいやり方は二つ、そして間違った反射がひとつあります。反射とは、とにかく開いてエラーを捕まえること。遅いうえに、本当の失敗を隠してしまいます。正しい答えは Dir(path)(組み込みの 1 行)と fso.FileExists(path)(状態を持たず、より明快)です。身を守るルールは、Dir チェックを Dir ループの中で使わないこと。Dir はひとつの隠れたカーソルを共有しており、存在テストがファイルの列挙を無言でリセットしてしまうからです。FileExists がより安全な既定である理由、Dir がフォルダーパスや末尾のバックスラッシュを取り違える理由、そしてチェックしてから開いてもなおエラーガードが必要な理由を学びましょう。

Henry
Excel VBA でブックを開く — Workbooks.Open、戻り値を受け取ること、そしてなぜ Workbook_Open とは別物なのか

Excel VBA でブックを開く — Workbooks.Open、戻り値を受け取ること、そしてなぜ Workbook_Open とは別物なのか

Workbooks.Open は、いま開いたブックを返す関数です。だから身を守るたった一つのルールは Set wb = Workbooks.Open(path) — その戻り値を受け取り、フォーカスが移った瞬間に変わってしまう ActiveWorkbook ではなく、つねに wb を通して操作すること。自分で呼ぶメソッド Workbooks.Open と、自動で走るイベント Workbook_Open の違い、存在しないパスを実行時エラー 1004 ではなくメッセージにするガードの掛け方、すでに開いているファイルの扱い、そして無人マクロを無言でダイアログ待ちにしてしまうパラメーターを学びましょう。

Henry
Excel VBA でブックを保存する — Save 対 SaveAs、FileFormat の罠、そしてマクロが消える理由

Excel VBA でブックを保存する — Save 対 SaveAs、FileFormat の罠、そしてマクロが消える理由

.Save は、いま持っているファイルをその場で、ダイアログなしに上書きします。.SaveAs は新しいファイルや別の形式を書き出し、そして罠は FileFormat の番号です — マクロ入りブックを xlOpenXMLWorkbook(51、xlsx 形式)として保存すると、Excel はあなたの VBA を一行残らず無言で捨てます。xlsm には xlOpenXMLWorkbookMacroEnabled(52)が必要です。Save・SaveAs・SaveCopyAs の使い分け、まっさらな新規ブックへの Save が名前を付けて保存ダイアログを出して無人マクロをハングさせる理由、DisplayAlerts が上書きプロンプトを事前承認に変えるしくみ、そして wb.Saved = True が何も書き込まずにブックを変更なしと印づける理由を学びましょう。

Henry
Excel VBA でブックを閉じる — SaveChanges、マクロをハングさせるプロンプト、そして保存せずに閉じる方法

Excel VBA でブックを閉じる — SaveChanges、マクロをハングさせるプロンプト、そして保存せずに閉じる方法

未保存の変更があるブックへの wb.Close は、モーダルの「変更を保存しますか」ダイアログを突きつけ、無人マクロではそのダイアログが永遠に待ち続けます。それにはコードで、SaveChanges 引数を使って答えます — wb.Close SaveChanges:=False は破棄し、SaveChanges:=True は先に保存し、省略するとプロンプトが出ます。引数を付けずに閉じることがスケジュールされたマクロの終わらないナンバーワンの原因である理由、閉じた瞬間にオブジェクト変数が死ぬ理由、Close が Application.Quit とどう違うか、そして最後のブックを閉じると見えない EXCEL.EXE が走り続けかねない理由を学びましょう。

Henry
Excel VBA の Application.Wait — Excel が固まる理由と、代わりに Sleep を使うべきとき

Excel VBA の Application.Wait — Excel が固まる理由と、代わりに Sleep を使うべきとき

Application.Wait はストップウォッチではなく目覚まし時計です。カウントダウンする秒数ではなく、起きるべき壁時計の瞬間を渡すので、Application.Wait 5 はほとんど何もせず、正しい一行は Application.Wait Now + TimeValue("0:00:05") になります。刻めるのは秒単位だけで、待っている間は Excel を完全に固めるため、画面の再描画もステータスバーの更新もユーザーのキャンセルもできません。目覚まし時計のモデル、誰もがつまずく絶対時刻の引数、なぜ 1 秒未満の停止には Sleep が要るのか、そして Excel を生かしたままの停止はなぜ DoEvents ループになるのかを学びましょう。

Henry
Excel VBA の Sleep — Windows API 呼び出し、64 ビットの PtrSafe の罠、そして Wait と Sleep

Excel VBA の Sleep — Windows API 呼び出し、64 ビットの PtrSafe の罠、そして Wait と Sleep

Sleep は VBA のキーワードではありません。Declare 文で借りてくる Windows の kernel32 関数で、マクロをミリ秒数だけ一時停止させます。だからこそ Application.Wait には出せない 1 秒未満の精度が得られます。落とし穴は宣言そのものです。コピペされた古い Declare Sub Sleep の行は、VBA7 の条件付きコンパイルのガードの中で PtrSafe 属性を足すまで、64 ビット Excel でコンパイルエラーを投げます。借りもの API のモデル、正確な 64 ビット対応の直し方、ミリ秒が正確でない理由、そして Sleep もやはり Excel を固めるので応答的な停止は代わりに DoEvents ループになる理由を学びましょう。

Henry
Excel VBA の Timer — マクロの処理時間を測る(そしてスケジューラではない理由)

Excel VBA の Timer — マクロの処理時間を測る(そしてスケジューラではない理由)

VBA の Timer 関数は、カウントダウンタイマーではなくストップウォッチです。名前に反して、N 秒後に何かを起こすことは決してなく、コードを止めることも決してありません。ただ深夜 0 時からの経過秒数を返すだけで、それを二度読んでコードのかたまりにかかった時間を測ります。だからこそ、当て推量ではなく、ScreenUpdating = False が本当にマクロを速くしたと証明する道具になります。ストップウォッチのモデル、タイマーを探す人がたいてい本当は Application.OnTime を欲しがっている理由、負の経過時間を生む深夜 0 時またぎのバグ、そして 100 分の 1 秒という分解能を学びましょう。

Henry
Excel VBA の DoEvents — Excel の「応答なし」を止める(そしてマクロが二重に走ってしまう理由)

Excel VBA の DoEvents — Excel の「応答なし」を止める(そしてマクロが二重に走ってしまう理由)

DoEvents はマクロを一瞬だけ止め、コードが走っている間に溜まったクリック・キー入力・再描画を Excel に処理させます。これがウィンドウを灰色の「応答なし」へ落ちるのを防ぎ、機能するキャンセルボタンを可能にします。ただし Excel を生かすその同じ譲りが、マクロの途中で制御をユーザーへ返しもするので、ユーザーは同じボタンをもう一度押し、一つ目のマクロの中で二つ目のコピーを走らせてしまえます。本当の危険は性能ではなく、その再入です。DoEvents をどこに置くか、実行中フラグで再入をどう防ぐか、なぜ間引かなければならないか、そしてなぜマルチスレッドではないのかを学びましょう。

Henry
Excel VBA の StatusBar — UserForm なしでマクロの進捗を見せる(そして永遠に固まって残るメッセージ)

Excel VBA の StatusBar — UserForm なしでマクロの進捗を見せる(そして永遠に固まって残るメッセージ)

Application.StatusBar を使うと、Excel ウィンドウ下部のバーに自分のテキストを書き込めます。UserForm もちらつきもなく、実行中のマクロの進捗を見せるいちばん軽い方法です。誰もが忘れる一行がリセットです。最後に書いたテキストはマクロが終わってもそこに貼り付いたまま残ります。Application.StatusBar を False にするまで Excel はバーを取り返さないからです。しかもタイトなループの中では、Excel に描き直す間を与えないかぎり見た目が更新されません。そこで DoEvents の出番です。書いて戻すパターン、空文字列より False が良い理由、進捗パーセントの定石、そして本格的なプログレスバーが手間に見合う場面を学びましょう。

Henry
Excel VBA の DisplayAlerts — 無人マクロの確認ダイアログを止める(そして危険な操作ほど勝手に承認してしまう理由)

Excel VBA の DisplayAlerts — 無人マクロの確認ダイアログを止める(そして危険な操作ほど勝手に承認してしまう理由)

Application.DisplayAlerts を False にすると、マクロの実行中は Excel の確認・警告ダイアログを表示しないよう伝えられます。だから無人マクロが、誰かの「OK」クリックを待って止まることがありません。ただしこれは警告を黙らせるというより、Excel の既定の応答で代わりに答えてしまうもので、シートを削除する・ファイルを上書きするといったプロンプトでは既定が「実行する」です。マクロが終われば勝手に True へ戻るので、本当の罠は切りっぱなしにすることではなく、あなたを守っていた警告を抑止してしまうことです。効く場面、窓を狭くするルール、エラー処理とは別物である理由、そして ScreenUpdating や Calculation との組み合わせ方を学びましょう。

Henry
Excel VBA の ScreenUpdating — ちらつきを止めてマクロを速くする(そして遅いマクロは直せない理由)

Excel VBA の ScreenUpdating — ちらつきを止めてマクロを速くする(そして遅いマクロは直せない理由)

Application.ScreenUpdating を False にすると、マクロの実行中は画面の再描画を止め、最後に一度だけ描き直すよう Excel へ伝えられます。これでちらつきが消え、ほどよく速くなります。ただし効くのは、コードがセルへ書き込む、選択する、スクロールするときだけで、計算が重いマクロに付けても何も得られません。肝心なルールは、クラッシュすると画面がフリーズして灰色のまま固まりうること、だから自動で戻るのを当てにせず、エラーハンドラーの中で必ず戻すことです。効く場面と効かない場面、入れ子の復元によるちらつきの罠、そして Calculation や EnableEvents と組む CleanExit パターンを学びましょう。

Henry
Excel VBA の Calculation — 計算を手動にして高速化する(そして切ったまま忘れる静かな罠)

Excel VBA の Calculation — 計算を手動にして高速化する(そして切ったまま忘れる静かな罠)

Application.Calculation を xlCalculationManual にすると、書き込みのたびに再計算するのをやめ、まとめて一度で計算するよう Excel へ伝えられます。これが数式の多いブックでの本当の高速化です。ただし VBA でもっとも危険なスイッチでもあります。失敗が静かだからです。手動のまま放置すると、数式は何の見た目の変化もなく更新を止め、合計は古いままで誰も気づきません。肝心なルールは、計算状態を保存しておくこと、後の処理が結果を必要とするときは Application.Calculate で明示的に再計算すること、そして Automatic を決め打ちせず、保存した状態をエラーハンドラーの中で復元することです。手動モードの落とし穴、ブックが開いていないときの error 1004、そして CleanExit パターンを学びましょう。

Henry
Excel VBA の EnableEvents — マクロが自分のイベントを引き起こすのを止める(そしてクラッシュがイベントを殺す理由)

Excel VBA の EnableEvents — マクロが自分のイベントを引き起こすのを止める(そしてクラッシュがイベントを殺す理由)

Application.EnableEvents を False にすると、マクロの書き込みが Worksheet_Change のようなイベントハンドラーを引き起こさなくなります。これは、ハンドラーがセルを編集して自分自身を再発火させる無限ループを断ち切るスイッチです。速度ではなく、正しさのためのスイッチです。肝心なルールは、EnableEvents がアプリケーション全体のプロパティで、自動では戻らないこと。False のままクラッシュすると、開いているすべてのブックのあらゆるイベントが、Excel を再起動するまで死んだままになります。ユーザーが「ボタンが動かなくなった」と言うのは、たいていこれが原因です。再帰する Worksheet_Change の直し方、CleanExit による復元、そしてこのスイッチが他の二つ以上に重要な理由を学びましょう。

Henry
Excel VBA の SpecialCells — 空白・可視セル・定数を選択する(そして 1 つも見つからないとエラーになる理由)

Excel VBA の SpecialCells — 空白・可視セル・定数を選択する(そして 1 つも見つからないとエラーになる理由)

SpecialCells は、アドレスではなく種類でセルを選ばせます。すべての空白、すべての可視行、すべての数式、すべての定数を Excel が代わりに拾います。条件を選択してジャンプ(Go To Special)のコード版です。命綱となる唯一のルールは、1 つも見つからないとき SpecialCells が error 1004 を投げることで、無防備な呼び出しは時限爆弾になります。成熟した書き方は必ず On Error Resume Next と If Not result Is Nothing を添えます。使うべきセルの種類、空白埋めと可視行コピーのパターン、そして結果が複数エリアの参照になる理由を学びましょう。

Henry
Excel VBA の Union — 離れた範囲を 1 つの参照にまとめる(そしてなぜ重複を取り除かないのか)

Excel VBA の Union — 離れた範囲を 1 つの参照にまとめる(そしてなぜ重複を取り除かないのか)

Union は、散らばった長方形を 1 つの参照に貼り合わせ、離れた複数のブロックを色づけ・消去・コピーする操作を一度で行えるようにします。複数のエリアを Ctrl を押しながらクリックすることのコード版です。誰もがつまずくルールは、Union が連結するだけで重複を取り除かないことです。重なったセルは二重に数えられるので .Count は嘘をつき、Union は集合の和ではなくバッチのリストになります。Union of Nothing エラーを避ける蓄積パターン、なぜセルごとのループではなく参照ごとに 1 回の操作なのか、そして Union が Intersect とどう違うのかを学びましょう。

Henry
Excel VBA の Intersect — 2 つの範囲が重なる場所を見つける(そして誰もが使う Worksheet_Change のガード)

Excel VBA の Intersect — 2 つの範囲が重なる場所を見つける(そして誰もが使う Worksheet_Change のガード)

Intersect は、2 つの範囲が共有するセルだけを返し、触れ合わないときは Nothing を返します — そしてその Nothing こそが肝心な点です。一番の用途は Worksheet_Change のガードで、If Not Intersect(Target, Range) Is Nothing と書けば、シート上のあらゆる編集でイベントが発火するのを止められます。命綱となるルールは、重なりがなければ Nothing が返ることで、Is Nothing の確認なしにプロパティへ触れると error 91 でクラッシュします。EnableEvents を使った完全なイベントガード、マクロを対象エリアに限定する方法、そして Intersect が Union とどう違うのかを学びましょう。

Henry
Excel VBA の Cells と Range — セルを数値で参照する(そしてなぜ Cells(1, 2) は A2 ではなく B1 なのか)

Excel VBA の Cells と Range — セルを数値で参照する(そしてなぜ Cells(1, 2) は A2 ではなく B1 なのか)

Cells は Range を数値でアドレス指定したものです。Range(A1) は列の文字・行番号の順、つまり目で読む順でセルを指し、Cells(row, column) は Excel が格納する順、まず行・次に列で 1 つのセルを指します。だから Cells(1, 2) は A2 ではなく B1 になります。Cells と Range の使い分け、Range(Cells, Cells) で計算した角からブロックを組む方法、添字なしの Cells がシート全体を意味する理由、そして Cells をワークシートで修飾すべき理由を学びましょう。

Henry
Excel VBA の Resize — アンカーから範囲を作り直す(そしてなぜデルタではなく総数なのか)

Excel VBA の Resize — アンカーから範囲を作り直す(そしてなぜデルタではなく総数なのか)

Resize は範囲の左上のアンカーを固定したまま、長方形を新しいサイズに描き直します。Offset のように参照を移動させず、何も選択もしません — 同じ角から始まる新しい範囲を返します。誰もがつまずくルールは、Resize(rows, columns) が加える差分ではなく、最終サイズを表す 1 始まりの絶対的な総数だということです。だから Range(A1).Resize(5, 3) は A1:C5 になり、Resize(0) は error 1004 を投げます。引数を省いて片方の次元をそのままにする方法、アンカーが常に左上である理由、そして見返りの大きい 2 つのパターン — Offset と Resize で見出しを落とす、そして配列を収まるブロックへ書き戻す — を学びましょう。

Henry
Excel VBA の CurrentRegion — データブロック全体を 1 行で取得する(そして空白行がそれに何をするのか)

Excel VBA の CurrentRegion — データブロック全体を 1 行で取得する(そして空白行がそれに何をするのか)

CurrentRegion は、あるセルを囲む連続したセルのブロックです。Excel はそのセルから外へ広がり、完全に空白の行と完全に空白の列にぶつかるまで拡張して、その途切れない島を囲む最小の長方形を返します — ちょうど Ctrl+Shift+アスタリスク で選択されるものです。端は自分で計算しません。Excel が見つけます。罠は、たった 1 本の完全に空白の行や列が壁となってブロックを静かに分断することで、エラーもなくデータの半分だけが返ってきます。CurrentRegion が見出しを含む理由と Offset・Resize で落とす方法、UsedRange や End(xlUp) との違い、そしていつ本物のテーブルを使うべきかを学びましょう。

Henry
Excel VBA の罫線 — コードでセルの罫線を引く(そしてブロック全体が枠で囲まれてしまう理由)

Excel VBA の罫線 — コードでセルの罫線を引く(そしてブロック全体が枠で囲まれてしまう理由)

Excel VBA における罫線は、セルのスイッチではなく、辺のプロパティです。範囲にはアドレス指定できる罫線が 8 本あり — 4 つの外周の辺、2 組の内側のグリッド線、そして 2 本の対角線 — 素の Range.Borders コレクションはその全部を一度に指します。だから Range.Borders.LineStyle = xlContinuous は 1 本の外枠を引く代わりに、すべてのセルを囲んでしまいます。外枠だけが欲しいときに BorderAround を使う場面、LineStyle・Weight・Color の組み合わせ方、xlEdgeBottom で 1 辺だけを設定する方法、そして xlLineStyleNone で罫線を消す方法を学びましょう。

Henry
Excel VBA のセルの結合 — コードで結合・解除する(そして、たいていやめておくべき理由)

Excel VBA のセルの結合 — コードで結合・解除する(そして、たいていやめておくべき理由)

Excel VBA でセルを結合することは書式設定ではなく、グリッドそのものへの構造的な変更です。Range(A1:C1).Merge は 3 つのセルを 3 列にまたがる 1 つのセルに融合し、左上の値だけが残って、ほかは消去されます。だから結合セルは、並べ替え・Range の計算・列の挿入・ループを静かに壊します。Merge・UnMerge・MergeCells・MergeArea、熟練者が代わりに Center Across Selection に手を伸ばす理由、そして結合セルをコードで安全に見つけて片付ける方法を学びましょう。

Henry
Excel VBA の列幅と行の高さ — コードでサイズ変更と AutoFit(そしてつまずかせる単位)

Excel VBA の列幅と行の高さ — コードでサイズ変更と AutoFit(そしてつまずかせる単位)

Excel VBA でセルのサイズを変えることは列や行の全体に働き、2 つの寸法は異なる単位を使います — ColumnWidth は標準フォントの文字数で、RowHeight はポイントで測ります。この食い違いこそ、幅 10 と高さ 10 がまったく似ていない理由です。もう 1 つの罠は AutoFit です。これは列や行の全体でしか動かず、表示されたテキストを測るので、結合セルを静かに無視します。ColumnWidth と読み取り専用の Width の違い、RowHeight と折り返し、EntireColumn.AutoFit、そして幅をゼロにするのが列を隠す間違ったやり方である理由を学びましょう。

Henry
Excel VBA の Font — コードで色・太字・サイズを設定する(そして ColorIndex の罠)

Excel VBA の Font — コードで色・太字・サイズを設定する(そして ColorIndex の罠)

Font オブジェクトは Excel VBA におけるセルのテキスト層です — 色、太字、斜体、サイズ、フォント名、そのどれも下にある値には触れません。厄介なのは色です。設定方法は 3 通りあり、それぞれ違う数の空間を使います。Range.Font.Color は 24 ビットの RGB 値を、Range.Font.ColorIndex は 1〜56 のパレット番号を取り、この 2 つは互換ではありません。どちらを使うか、Characters でセルの一部だけを太字にしたりサイズを変えたりする方法、値に基づく色付けが条件付き書式の担当である理由、そしてフォント色を間違った数値なしで読み戻す方法を解説します。

Henry
Excel VBA のセルの色 — コードで背景の塗りを設定する(そして色がデータでない理由)

Excel VBA のセルの色 — コードで背景の塗りを設定する(そして色がデータでない理由)

Range.Interior は Excel VBA におけるセルの塗り層です — テキストの背後にあるペンキです。Interior.Color と RGB で設定し、Interior.ColorIndex を xlNone にして消します。そして白い塗りは、塗りなしと同じではないと知っておきましょう。より深い要点は、色の付いたセルは何のデータも持たないことです。SUM も SUMIF もそれを無視するので、色で分類しているなら、数式が読めない場所に情報を隠していることになります。色のプロパティ、古びるループなしで条件によってハイライトする方法、そして多くの範囲を素早く塗る方法を学びましょう。

Henry
Excel VBA の NumberFormat — 値を変えずに数値の表示を変える

Excel VBA の NumberFormat — 値を変えずに数値の表示を変える

Range.NumberFormat は Excel VBA におけるセルの表示層です。格納された数値が画面上でどう読めるかを変えるだけで、数値そのものは決して変えません。だから、5.4999 を保持するセルを 5 と表示させる書式設定は丸めではなく、合計は依然として 5.4999 を使います。見た目と値の対立が実際に牙をむくのがここです。日付とは、実のところ衣装をまとったシリアル値だからです。書式コードの言語、NumberFormat が Format 関数とどう違うか、NumberFormatLocal というロケールの罠、そして代わりに Round が必要なときを学びましょう。

Henry
Excel VBA で WorksheetFunction を使う — Excel 自身の関数をコードから呼ぶ(そして 2 通りの失敗の仕方)

Excel VBA で WorksheetFunction を使う — Excel 自身の関数をコードから呼ぶ(そして 2 通りの失敗の仕方)

Application.WorksheetFunction を使えば、SUM や VLOOKUP、COUNTIF をループで書き直す代わりに、VBA から Excel の 450 を超える組み込み関数を借りられます。落とし穴は呼び出し方が 2 通りあり、失敗の仕方が違うことです。WorksheetFunction.X は一致がないと実行時エラーを発生させ、Application.X は IsError でテストできるエラー値を返します。どちらの呼び出し方を使うか、なぜ結果を Variant で受けなければならないか、この方法で呼んではいけない関数はどれか、そして 1 セルずつループする代わりに範囲全体を渡すのはいつかを解説します。

Henry
Excel VBA で Remove Duplicates を使う — 1 行で重複を削除(そしてなぜ元に戻せないのか)

Excel VBA で Remove Duplicates を使う — 1 行で重複を削除(そしてなぜ元に戻せないのか)

Range.RemoveDuplicates はコード 1 行で Excel の重複の削除ボタンを実行しますが、ループにはない形で破壊的です。行をその場で削除し、最初の出現を残し、マクロが動いたあとは元に戻せません。誰もがつまずく引数が Columns で、その数値はシートの列文字ではなく範囲内のオフセットです。範囲オフセットの罠、Header xlYes が大事な理由、最初ではなく最後の行を残す方法、そして代わりに Advanced Filter や Dictionary に手を伸ばすのはいつかを解説します。

Henry
Excel VBA で Advanced Filter を使う — 一意な値を抽出し、新しい範囲へフィルターする(ループなしで)

Excel VBA で Advanced Filter を使う — 一意な値を抽出し、新しい範囲へフィルターする(ループなしで)

Range.AdvancedFilter は、ビューではなくデータを出力する唯一のフィルターです。一意なリストや条件に一致した行の集合を、ループなしで、何も削除せずに、1 回の呼び出しで別の場所へ引き出せます。異質に感じる部分は、その WHERE 句がセルの中に置かれること、つまり見出しがデータと正確に一致しなければならない条件範囲です。xlFilterInPlace と xlFilterCopy の違い、条件範囲の仕組み、Unique True が非破壊的に重複を除く方法、空の出力を返す見出し不一致の罠、そして AutoFilter や Remove Duplicates とどう違うかを解説します。

Henry
Excel VBA で Find を使う — セルを正しく検索する(返すのは位置ではなく Range)

Excel VBA で Find を使う — セルを正しく検索する(返すのは位置ではなく Range)

VBA の Range.Find はコードから使う Excel の Ctrl+F で、位置を表す数値ではなく Range オブジェクト(一致がなければ Nothing)を返すため多くの人がつまずきます。error 91 のクラッシュを防ぐたった 1 つのチェック、実行のたびに Find の挙動が変わる「引数を記憶する」罠、LookAt xlWhole と xlPart が完全一致と部分一致をどう決めるか、そして無限ループにせず FindNext で全一致を取得する方法を解説します。

Henry
Excel VBA で AutoFilter を使う — コードで行をフィルターする(非表示は削除ではない)

Excel VBA で AutoFilter を使う — コードで行をフィルターする(非表示は削除ではない)

VBA の AutoFilter はコードから表をフィルターしますが、隠された行は消えていません — SUM にはやはり数えられ、コピーにも付いてきて、範囲の中にそのまま残ります。定番のバグを防ぐ考え方、可視行だけに触れるにはなぜ SpecialCells xlCellTypeVisible を通す必要があるか、条件と演算子の仕組み、2 回目の実行でフィルターがオフになるトグルの罠、そして大量の行を高速に消す「フィルターしてから削除」パターンを解説します。

Henry
Excel VBA で Sort を使う — Range.Sort と Sort オブジェクト(元の並び順を取り戻す方法)

Excel VBA で Sort を使う — Range.Sort と Sort オブジェクト(元の並び順を取り戻す方法)

VBA のソートは Ctrl+Z の効かない恒久的な並べ替えなので、最初のルールは手をつける前に元の並び順を守ることです。ビューとミューテーションを分ける考え方、Header xlYes が大事な理由(さもないと見出しがデータに紛れ込む)、手軽な Range.Sort と無制限の Sort オブジェクトの違い、古いソートキーを引き継ぐ SortFields.Clear の罠、そして文字列として保存された数値が誤った順序で並ぶ理由を解説します。

Henry
Excel VBA で行を削除する — 行・空白行・条件による削除(ループは逆順で!)

Excel VBA で行を削除する — 行・空白行・条件による削除(ループは逆順で!)

VBA で行を削除するのは、値の消去ではなく構造の変更です。削除した行の下はすべて 1 行ずつ上へ詰まるため、順方向ループは行を飛ばします。直す唯一のルール(下から上へループする、または Union でまとめて削除する)、EntireRow.Delete がセルの消去とどう違うか、空白行を高速に取り除く方法、そして参照数式やデータを壊さずに条件で行を削除する方法を解説します。

Henry
Excel VBA で行・列を挿入する — グリッドを正しくずらす(ループ挿入で崩さないコツ)

Excel VBA で行・列を挿入する — グリッドを正しくずらす(ループ挿入で崩さないコツ)

挿入は削除の鏡像です。既存の行を下へ(列なら右へ)押しやって場所を空けるので、削除ループを壊すのと同じずれが挿入ループも壊します。EntireRow.Insert と Shift 引数を使った部分範囲の挿入の違い、CopyOrigin が新しい行にどの隣の書式を継承させるか、ループ内で安全に挿入する向き、そして多数の行を 1 回の呼び出しでまとめて追加する方法を解説します。

Henry
Excel VBA で列・行を非表示にする — 非表示は削除ではない(なぜ合計が変わらないのか)

Excel VBA で列・行を非表示にする — 非表示は削除ではない(なぜ合計が変わらないのか)

VBA で列を非表示にするのは、削除でもフィルターでもありません。データはそのまま残り、すべての SUM に含まれ、範囲コピーでも一緒にコピーされ、ただ表示幅がゼロになるだけです。なぜ .Hidden が EntireColumn と EntireRow に属するのか、なぜ非表示のセルも数式で数えられるのか、動かなくなったシートを救う「すべて再表示」の 1 行、そして手動で隠した行が AutoFilter で隠れた行とループ時にどう違うのかを解説します。

Henry
Excel VBA の Worksheet_BeforeDoubleClick — ダブルクリックをアクションに変える(そして編集モードを抑制する)

Excel VBA の Worksheet_BeforeDoubleClick — ダブルクリックをアクションに変える(そして編集モードを抑制する)

Worksheet_BeforeDoubleClick は、セルをダブルクリックした瞬間に — 編集モードに入る前に — Excel が発火させるイベントで、Target セルと Cancel フラグを手渡してくれます。Cancel を True にすれば編集モードを抑制し、代わりに自分のアクションを走らせられます — チェックマークを切り替える、行を完了にする、明細へドリルダウンする。Intersect で 1 列に絞る方法、Cancel を忘れるとセルが編集モードに落ちる理由、そしてコードを置くべき場所を解説します。

Henry
Excel VBA の Worksheet_BeforeRightClick — 右クリックメニューを置き換える(そして無効化がセキュリティでない理由)

Excel VBA の Worksheet_BeforeRightClick — 右クリックメニューを置き換える(そして無効化がセキュリティでない理由)

Worksheet_BeforeRightClick は、セルを右クリックした瞬間に — コンテキストメニューが現れる前に — Excel が発火させるイベントで、Target セルと Cancel フラグを手渡してくれます。Cancel を True にすれば組み込みメニューを抑制し、代わりに自分のアクションを走らせたり独自のメニューを出したりできます。Copy や Paste を潰さないよう Intersect でスコープを絞る方法、右クリックの無効化が保護ではなく UX の選択である理由、そしてコードを置くべき場所を解説します。

Henry
Excel VBA の Workbook_BeforePrint — 印刷をブロックし、ヘッダーを刻み、印刷プレビューの落とし穴

Excel VBA の Workbook_BeforePrint — 印刷をブロックし、ヘッダーを刻み、印刷プレビューの落とし穴

Workbook_BeforePrint は、ブック内の何かが印刷される前に Excel が発火させるイベントで、Cancel フラグを手渡してくれます。Cancel を True にすれば印刷はブロックされます — 印刷前に検証する、あるいは草案が出ていくのを止める。印刷プレビューでもこのイベントが発火する理由(だから重い処理はプレビューを遅くする)、シートごとではなくブック全体で一度だけ走る理由、無言の Cancel がバグである理由、そしてコードを置くべき場所を解説します。

Henry
Excel VBA の Workbook_BeforeClose — 閉じる操作を取り消し、保存を促し、コードを置くべき場所

Excel VBA の Workbook_BeforeClose — 閉じる操作を取り消し、保存を促し、コードを置くべき場所

Workbook_BeforeClose は、誰かがファイルを閉じようとした瞬間に — 何も破棄される前に — Excel が発火させるイベントで、Cancel フラグを手渡してくれます。Cancel を True にすれば、閉じる操作は取り消されます。閉じる際の後始末を走らせる方法、Saved プロパティで Excel が二重に保存を尋ねるのを止める方法、クラッシュ時には決して発火しない理由、そしてコードを置くべき場所を解説します。

Henry
Excel VBA の Workbook_BeforeSave — 保存を検証・ブロックし、SaveAsUI が本当に伝えていること

Excel VBA の Workbook_BeforeSave — 保存を検証・ブロックし、SaveAsUI が本当に伝えていること

Workbook_BeforeSave は、保存が要求された瞬間に — ディスクに何かが書き込まれる前に — Excel が発火させるイベントで、SaveAsUI と Cancel という 2 つのフラグを手渡します。必須セルが空のときに保存をブロックする方法、誰がいつ保存したかを自動で刻む方法、ハンドラーの中で Save を呼ぶと永遠にループする理由、そして SaveAsUI でファイル名を強制する方法を解説します。

Henry
Excel VBA の Worksheet_Activate と Deactivate — シートを切り替えたときにコードを走らせる(そして離脱を取り消せない理由)

Excel VBA の Worksheet_Activate と Deactivate — シートを切り替えたときにコードを走らせる(そして離脱を取り消せない理由)

Worksheet_Activate はシートがアクティブになったときに発火し、Worksheet_Deactivate はそのシートを離れる直前に発火します — シートの到着と出発のイベントです。両者を定義づける勘所は — BeforeClose や BeforeSave と違い、どちらも Cancel を渡さないので、シートの切り替えを見ることはできても、それをブロックすることはできません。表示時にリフレッシュするパターン、押し戻しの回避策、そしてシートレベルとブックレベルのハンドラーを解説します。

Henry
Excel VBA のクラスモジュール — 自分だけのオブジェクトを作る(設計図 vs インスタンス、そして As New の罠)

Excel VBA のクラスモジュール — 自分だけのオブジェクトを作る(設計図 vs インスタンス、そして As New の罠)

VBA のクラスモジュールを使うと、データと振る舞いをまとめた設計図として自分だけのオブジェクト型を定義でき、New で独立したインスタンスをいくつでも作り出せます。誰もがつまずく落とし穴は、オブジェクトが参照型であること。Set b = a は両方の名前を同じインスタンスに向け、Dim x As New は遅延インスタンス化の罠を隠します。モジュール名がそのまま型名になる仕組み、Type よりクラスが勝る場面、そして New にまつわる典型的な落とし穴の避け方を解説します。

Henry
Excel VBA の Type — 関連するフィールドを 1 つの変数にまとめる(ユーザー定義型 vs クラス)

Excel VBA の Type — 関連するフィールドを 1 つの変数にまとめる(ユーザー定義型 vs クラス)

VBA の Type は Type ... End Type で宣言するユーザー定義型で、関連する複数のフィールドを 1 つの変数にまとめます。Name、Age、Salary を 3 本の平行配列ではなく 1 つの変数として一緒に運べます。Type は値型なので、ある Type 変数を別の変数に代入するとすべてのフィールドがコピーされ、共有されるオブジェクトとは対照的です。宣言をどこに書くべきか、コピーと共有の違いがなぜ重要か、そしてクラスモジュールに切り替えるべき正確な境目を解説します。

Henry
Excel VBA の Property — Get・Let・Set(クラスのフィールドへのアクセスを制御する)

Excel VBA の Property — Get・Let・Set(クラスのフィールドへのアクセスを制御する)

Property Get・Let・Set は、クラスのフィールドをゲートに変えます。外部が読み書きするたびにあなたのコードが走る小さなプロシージャなので、入力を検証したり、値をその場で計算したり、フィールドを読み取り専用にしたりできます。誰もがつまずく区別が Let と Set です。Let は値を代入し、Set はオブジェクトを代入します。取り違えるとコンパイルエラーか実行時エラーになります。バッキングフィールドのパターン、素の Public 変数こそが正直な選択になる場面、そして読み取り専用プロパティの作り方を解説します。

Henry
Excel VBA の ActiveCell — カーソルのある唯一のセル(ActiveCell と Selection の違い、そして壊れるとき)

Excel VBA の ActiveCell — カーソルのある唯一のセル(ActiveCell と Selection の違い、そして壊れるとき)

ActiveCell は、いまカーソルがある1つのセルを指すライブなポインターです — つねにちょうど1つのセル、アクティブシート上、そして現在の Selection の内側にあります。Selection との違い、.Value と .Offset での読み書き、そして壊れる一番の理由 — ユーザーが残したシートとカーソルにそのまま従うので、ユーザーの現在地に関係しないコードには不向きだということ — を解説します。

Henry
Excel VBA の Selection — ハイライトされたものを扱う(そして、なぜつねに Range とは限らないのか)

Excel VBA の Selection — ハイライトされたものを扱う(そして、なぜつねに Range とは限らないのか)

Selection は、いまハイライトされているものを指すライブなポインターです — ふつうはセルの範囲ですが、グラフやシェイプ、あるいは何もない場合もあります。だからこそ Selection を範囲だと決めてかかるコードは、グラフが選択された瞬間にクラッシュします。選択セルのループ、.Areas による複数エリア選択の扱い、TypeName によるガード、そして Selection を完全に避けて範囲を名指しすべきときを解説します。

Henry
Excel VBA の Select と Activate — マクロ記録の .Select 癖を断ち切る

Excel VBA の Select と Activate — マクロ記録の .Select 癖を断ち切る

マクロ記録は、あなたのマウスがすることをそのまま書きます — シートを Select し、セルを Select し、Selection に作用する — それが人の働き方であって、コードのあるべき姿ではないからです。Select(1つまたは複数のセルをハイライト)と Activate(唯一のアクティブセルを設定)の本当の違い、ほぼすべての .Select が削除できる遅く脆い回り道である理由、本当に選択が必要になるまれな場面、そして記録されたコードを、修飾された範囲参照へ直接作用するようリファクタリングする方法を解説します。

Henry
Excel VBA の Workbook_Open — ファイルを開いた瞬間にマクロを自動実行する(そしてコードを置くべき場所)

Excel VBA の Workbook_Open — ファイルを開いた瞬間にマクロを自動実行する(そしてコードを置くべき場所)

Workbook_Open は、ファイルが開き終わった瞬間に Excel が発火させるイベントです — ボタン不要で、自分から走るコード。ただし発火するのは、コードが ThisWorkbook オブジェクト(標準の Module ではなく)に置かれ、かつユーザーがマクロを有効にしている場合だけ。コードをどこに置くべきか、なぜ無言で走らないのか、Workbook_Open と Auto_Open の違い、そして速く落ちにくく保つ方法を解説します。

Henry
Excel VBA の Worksheet_Change — セルが編集されたときにコードを走らせる(そして避けるべき無限ループ)

Excel VBA の Worksheet_Change — セルが編集されたときにコードを走らせる(そして避けるべき無限ループ)

Worksheet_Change は、シート上でユーザーがセルを編集するたびに Excel が発火させるイベントで、変更されたセルを Target として手渡してくれます。誰もがはまる罠 — ハンドラーがセルに書き込むと、その書き込みがまたイベントを発火させ、Excel は永遠にループします。Application.EnableEvents による解決策、Intersect で対象を絞る方法、なぜ数式の再計算を無視するのか、そしてコードを置くべき場所を解説します。

Henry
Excel VBA の Worksheet_SelectionChange — カーソルが動いたときにコードを走らせる(もたつきなしでアクティブ行をハイライト)

Excel VBA の Worksheet_SelectionChange — カーソルが動いたときにコードを走らせる(もたつきなしでアクティブ行をハイライト)

Worksheet_SelectionChange は、カーソルが動くたび — クリック、矢印キー、Enter — に Excel が発火させるイベントです。新しい選択範囲を Target として手渡すので、アクティブ行のハイライトのような、カーソルを追う小技が可能になります。ただし絶えず発火するため、重いコードはシート全体をもたつかせます。正しいアクティブ行ハイライトのパターン、なぜループしうるのか、そして羽のように軽く保つ方法を解説します。

Henry
Excel VBA の For Each — インデックスに触れずコレクションをループする(そして隠れた罠)

Excel VBA の For Each — インデックスに触れずコレクションをループする(そして隠れた罠)

For Each は「すべての要素にこれをせよ」と伝えるだけで、順序と境界の面倒は VBA が引き受けます — カウンターも、1 つずれるバグもありません。しかしその手軽さは 3 つの手強いルールを隠しています:ループ変数はオブジェクトか Variant でなければならず、配列のループは読み取り専用で、走査中のコレクションから要素を削除してはいけません。For Each が For…Next に勝る場面と、静かに裏切る場面を解説します。

Henry
Excel VBA の Collection — 順序を保ち、伸びるリスト(そしてなぜ Dictionary ではないのか)

Excel VBA の Collection — 順序を保ち、伸びるリスト(そしてなぜ Dictionary ではないのか)

VBA の Collection は、Add するたびに伸びる順序付きのリストです — ReDim も、サイズの当て推量も要りません。しかし初心者が毎回ぶつかる 4 つの鋭い角があります:0 始まりではなく 1 始まり、要素を上書きできない(Add/Remove だけ)、重複キーはエラー 457 を投げ、組み込みの Exists チェックがない。Collection が Array や Dictionary に勝る場面と、静かに代償を求める場面を解説します。

Henry
Excel VBA の With ステートメント — オブジェクトを一度だけ書く(そして成否を分ける先頭のドット)

Excel VBA の With ステートメント — オブジェクトを一度だけ書く(そして成否を分ける先頭のドット)

With ステートメントは、オブジェクトに一度だけ名前を付け、そのメンバーに先頭のドットだけで触れさせてくれます — 打つ量が減り、コードは速く、ブロックはすっきり。しかしその先頭のドットこそがすべてです:忘れると .Font は Font になり、あなたのオブジェクトではなくアクティブシートに無言でバインドされます。With が実際に最適化するもの、ドット抜けの罠、そして With が For Each とどう組むのかを解説します。

Henry
Excel VBA の Dim — 変数の宣言、Option Explicit、そしてタイプミスが生む「空の箱」

Excel VBA の Dim — 変数の宣言、Option Explicit、そしてタイプミスが生む「空の箱」

Dim は使う前に名前付きの箱を確保します。しかし変数を宣言する本当の理由は、名前を打ち間違えた瞬間に VBA が新しい空の Variant を無言で作ってしまうことにあります。Option Explicit がなぜ VBA で最も価値ある 1 行なのか、Dim a, b As Long の罠、そして Set が必要になる場面を解説します。

Henry
Excel VBA のデータ型 — String、Long、Double、Variant(値ごとに正しい箱を選ぶ)

Excel VBA のデータ型 — String、Long、Double、Variant(値ごとに正しい箱を選ぶ)

VBA のデータ型とは、変数の箱の形と大きさのこと — そしてそれを選ぶことは、実は何が壊れうるかを選ぶことです。なぜ Integer は 32,767 でオーバーフローするのか(Long を使う)、なぜ Variant はバグを隠す怠惰な既定なのか、なぜお金には Double でなく Currency が要るのか、そして型が一致しませんとオーバーフローのエラーの読み方を解説します。

Henry
Excel VBA の Const — マジックナンバーに名前を付ける(そして値がずれない理由)

Excel VBA の Const — マジックナンバーに名前を付ける(そして値がずれない理由)

VBA の定数とは、コンパイル時に値へ固定された名前 — コードじゅうに散らばったマジックナンバーの処方箋です。なぜ Const は値のずれを止めるのか、なぜ定数への代入がコンパイルエラーになるのか(それが機能なのです)、なぜ Const はコンパイル時のリテラルでなければならないのか、そしていつ Enum に手を伸ばすべきかを解説します。

Henry
Excel VBA の Offset — セルからの相対移動(Offset と Resize、そして 1 つずれる罠)

Excel VBA の Offset — セルからの相対移動(Offset と Resize、そして 1 つずれる罠)

Range.Offset は (行, 列) だけずらした新しい範囲を返します — 移動するだけでサイズは変えず、Offset(1,0) は 1 行目ではなく 1 行下を意味します。考え方の軸、見出しを飛ばす定番イディオム Offset(1).Resize(n-1)、そして VBA のメソッドが OFFSET ワークシート関数とどう違うかを解説します。

Henry
Excel VBA の UsedRange と CurrentRegion — データブロック全体を取得する(どちらを信じるべきか)

Excel VBA の UsedRange と CurrentRegion — データブロック全体を取得する(どちらを信じるべきか)

UsedRange と CurrentRegion はどちらも「ブロック全体」を取得しますが、答えている問いが違います。UsedRange は Excel がキャッシュした外接矩形で、過大に報告し縮まりません。CurrentRegion はセルの周囲でその場で計算され、空白行で止まります。どちらをいつ信じるべきかを解説します。

Henry
Excel VBA の Trim — 空白が消えない理由と Chr(160) の対処法

Excel VBA の Trim — 空白が消えない理由と Chr(160) の対処法

VBA の Trim は両端だけを削り、内側の空白には触れません。さらに、Web や PDF からの貼り付けで紛れ込む非改行スペース Chr(160) も無視します。考え方の軸、使うべき正規化関数 1 つ、そしてどの関数がどの場面で勝つか。Excel 365 / 2021 / 2019 で検証済み。

Henry
VBA InputBox — 2つの InputBox と使い分け

VBA InputBox — 2つの InputBox と使い分け

VBA の InputBox は1つではなく2つあります。単純な InputBox で足りる場面、Type を付けた Application.InputBox が勝つ場面、そして両方を静かに壊す「キャンセルの落とし穴」まで。コピペで動く例、Excel 365 / 2021 / 2019 で動作確認済み。

Henry
VBA UserForm — 本格的な入力フォームを作る

VBA UserForm — 本格的な入力フォームを作る

VBA UserForm を正しく作る方法。イベント駆動の考え方、.Show のあとコードが「消える」理由、そして入力した値を読めるかどうかを決める Unload と Hide のルールまで。コピペで動くイベントコード、Excel 365 / 2021 / 2019 で動作確認済み。

Henry
Excel VBA Whileループ — Excelを固めずにループする方法

Excel VBA Whileループ — Excelを固めずにループする方法

VBAのWhileループは「必ず終わる」という約束であり、それを守るのはあなた。すべてのWhileループに必要な3つの部分、なぜDo WhileがWhile...Wendより良いのか、そして二度とExcelを固めない方法を、コピペ実例とともに。Excel 365 / 2021 / 2019で動作確認済み。

Henry