Excel VBA で定期レポートを自動化していると、前回ブックからコメントをコピーする場面はよくあります。そのときに Run-time error '1004': Unable to get the NoteText property of the Range class が突然出ると、どのセルが悪いのか分からず困ってしまいます。この記事では、このエラーの正体と、安全にコメント/メモを取得するための実装・運用ポイントを詳しく解説します。
Excel VBA の NoteText 取得で実行時エラー 1004 が起きる典型パターン
まずは、実際によくあるシナリオを整理します。質問のケースでは、次のような処理でエラーが発生していました。
- 定期レポート用の Excel マクロがある
- 「前回の報告書ブック」から該当セルの「コメント」を読み取り、今月のブックに反映する処理を行っている
- コメント取得部分で
Range.NoteText(またはActiveCell.NoteText/Cells(row, col).NoteText)を使っている - 複数シートのうち、特定のシートだけで
実行時エラー 1004が発生する
コードはほぼ同じなのに、特定のシートだけエラーになる――この状況が「原因はコメントの種類の違い」であることに気づきにくいポイントです。
NoteText の正体と現在の Excel コメント仕様
エラーの原因を理解するには、まず「Excel のコメント機能が二種類存在する」という前提を押さえる必要があります。
Excel には「メモ」と「コメント」の 2 種類がある
現在の Excel には、見た目がよく似た注釈機能が 2 種類あります。
| 名称(日本語 UI) | 英語 UI | 概要 | VBA からの型 / プロパティ |
|---|---|---|---|
| メモ | Notes | 従来からあるシンプルな吹き出しコメント。スレッド機能なし。 | Comment オブジェクト(Range.Comment) |
| コメント(スレッド付きコメント) | Threaded Comments | 会話形式で返信できる新しいコメント。共同編集向け。 | CommentThreaded オブジェクト(Range.CommentThreaded) |
昔から Excel を使っている方は、セル右上の三角マークや吹き出しをまとめて「コメント」と呼びがちですが、Excel の UI と VBA の内部では明確に区別されています。
Range.NoteText は「メモ専用」のプロパティ
Range.NoteText は、もともと旧仕様の「メモ」だけを対象に用意されたプロパティです。つまり、
- セルにメモが付いている →
Range.NoteTextで内容を取得できる - セルにスレッド付きコメントが付いている →
Range.NoteTextでは扱えない
そして、セルにスレッド付きコメントが付いている状態で Range.NoteText を呼ぶと、
Run-time error '1004': Unable to get the NoteText property of the Range class
というおなじみの実行時エラー 1004 が発生します。今回のケースでは、問題のシートだけ「メモではなくスレッド付きコメント」が混ざっていたことが直接の原因でした。
エラー 1004 の発生条件を整理する
NoteText まわりの挙動を整理すると、次のようになります。
| セルに付いているもの | Range.NoteText の結果 | 備考 |
|---|---|---|
| 何も付いていない | 空文字(または長さ 0 の文字列) | 通常はエラーにならない |
| メモ(Note / Comment オブジェクト) | メモの本文を取得 | 従来のコードはこの前提で書かれている |
| スレッド付きコメント(CommentThreaded) | 実行時エラー 1004 | 今回問題になっているパターン |
つまり、NoteText エラーが出る時点で「そのセルにはスレッド付きコメントが付いている可能性が高い」と考えることができます。
メモとコメントが混在するブックで起きる実務上のトラブル
レポートの作成現場では、次のような経緯でメモとスレッド付きコメントが混在しがちです。
- 最初はメモだけを使っていた
- 後から Excel の UI が変わり、標準で「新しいコメント」(スレッド付き)が挿入されるようになった
- 別の担当者が何気なく「新しいコメント」を使い始める
- 結果として、同じブックの中に「メモ」と「スレッド付きコメント」が混ざる
VBA の側は、昔に書いた Range.NoteText をそのまま使っているため、
- メモが付いているセル → 正常に NoteText 取得
- スレッド付きコメントが付いているセル → エラー 1004 で処理停止
という状況になります。特に「特定のシートだけエラーになる」「ある日突然エラーになり始める」という場合、多くは誰かがそのシートで「スレッド付きコメント」を使い始めたのがトリガーです。
両方の形式に対応した安全な取得コード
では、メモとスレッド付きコメントが混在していてもエラーにならない、安全なコメント取得コードを見ていきます。
単一セルからコメント/メモのテキストを取得するコード
基本形は次のとおりです。変数 rng に対象セルが入っている想定です。
Dim txt As String
Dim n As Comment 'メモ用
Dim c As CommentThreaded 'スレッド付きコメント用
Set n = rng.Comment 'まずメモを確認
If Not n Is Nothing Then
txt = n.Text
Else
Set c = rng.CommentThreaded
If Not c Is Nothing Then
txt = c.Text
Else
txt = "" '何も無ければ空文字を返す
End If
End If
ポイントは次のとおりです。
- メモ(Comment)を先にチェックし、存在すればそのテキストを取得
- メモがなければ、次にスレッド付きコメント(CommentThreaded)をチェック
- どちらも無ければ空文字列を返すことで、処理を最後まで進められる
この書き方であれば、Range.NoteText を一切使わずに、メモ/コメントの両方に対応できます。
再利用しやすい関数にまとめる
同じロジックをあちこちに書くのはメンテナンスが大変なので、共通関数にしておくと便利です。
Public Function GetNoteOrCommentText(ByVal rng As Range) As String
Dim n As Comment
Dim c As CommentThreaded
If rng Is Nothing Then
GetNoteOrCommentText = ""
Exit Function
End If
Set n = rng.Comment
If Not n Is Nothing Then
GetNoteOrCommentText = n.Text
Exit Function
End If
Set c = rng.CommentThreaded
If Not c Is Nothing Then
GetNoteOrCommentText = c.Text
Else
GetNoteOrCommentText = ""
End If
End Function
以降は、どこからでも次のように呼び出せます。
txt = GetNoteOrCommentText(Worksheets("前回").Range("B5"))
これだけで、メモとスレッド付きコメントのどちらでも内容を取得でき、NoteText に依存しない安全なコードになります。
複数列にわたって取得する場合
対象セルから横方向に複数列分のコメントを読みたいケースでは、Offset と組み合わせて同じ関数を使用します。
Dim baseRng As Range
Dim i As Long
Dim resultArr(1 To 5) As String '例として 5 列分
Set baseRng = Worksheets("前回").Range("B5")
For i = 0 To 4
resultArr(i + 1) = GetNoteOrCommentText(baseRng.Offset(0, i))
Next i
このように、rng.Offset(行, 列) に対して同じロジックを適用すれば、どの列にメモ/コメントが混在していても、エラー 1004 を出さずに安全に読み込めます。
ユーザーに優しいエラーハンドリングの設計
上で紹介した関数は、基本的にエラーを発生させずに空文字を返す作りになっています。これだけでも「マクロが途中で止まる」状況は回避できますが、実務上は「なぜそのセルだけ何も入っていないのか」をユーザーが理解できるようにしておくことも重要です。
コメントが存在しない場合の通知例
例えば、必須セルにコメントが無いのは明らかな入力漏れだと分かっているのであれば、次のようなチェックを入れることができます。
Dim txt As String
Dim targetRng As Range
Set targetRng = Worksheets("前回").Range("B5")
txt = GetNoteOrCommentText(targetRng)
If txt = "" Then
MsgBox "前回レポートの " & targetRng.Address(0, 0) & _
" にはコメント/メモがありません。" & vbCrLf & _
"入力漏れか、形式の異なる注釈が設定されている可能性があります。", _
vbExclamation, "コメント未入力の確認"
End If
このように、「何も取得できなかった」ことをそのまま無視せず、ユーザーに分かりやすいメッセージを出すことで、原因調査の手間をぐっと減らせます。
ログ出力で後から原因を追えるようにする
運用上、毎回メッセージボックスを出すのが煩わしい場合は、ログ用のシートやテキストファイルに「どのセルでコメントが取得できなかったのか」を書き出す方法もあります。
Sub LogCommentIssue(ByVal rng As Range)
Dim wsLog As Worksheet
Dim nextRow As Long
Set wsLog = ThisWorkbook.Worksheets("Log")
nextRow = wsLog.Cells(wsLog.Rows.Count, 1).End(xlUp).Row + 1
wsLog.Cells(nextRow, 1).Value = Now
wsLog.Cells(nextRow, 2).Value = rng.Worksheet.Name
wsLog.Cells(nextRow, 3).Value = rng.Address(0, 0)
wsLog.Cells(nextRow, 4).Value = "コメント/メモが存在しない、または取得できませんでした"
End Sub
コメント取得に失敗したときにこのプロシージャを呼び出しておけば、後からログシートを確認するだけで「どのシートのどのセルが問題だったか」を簡単に把握できます。
NoteText をやめるべき理由と書き換え方
ここまで読んでいただいて分かるように、Range.NoteText は「メモにしか対応していない」うえに、「今後も拡張される見込みが薄い」レガシーなプロパティです。そのため、新しく作るマクロはもちろん、既存マクロでも余力があれば NoteText からの脱却を検討するのがおすすめです。
NoteText の代わりに使うべきプロパティ
コメント系の情報は、基本的に次のプロパティで扱うと安全です。
| 対象 | VBA 側のオブジェクト | テキスト取得方法 |
|---|---|---|
| メモ(旧コメント) | Comment | rng.Comment.Text |
| スレッド付きコメント | CommentThreaded | rng.CommentThreaded.Text |
ですので、NoteText を使っている部分は、可能であれば次のように書き換えます。
'Before
txt = rng.NoteText
'After
txt = GetNoteOrCommentText(rng)
この置き換えだけで、「メモしかなかった時代のブック」も「スレッド付きコメントが混ざった新しいブック」も共通のロジックで処理できるようになります。
運用での再発防止策:メモかコメントかを決めておく
コード側で両対応しておくのはもちろんとして、運用ルールを決めておくことも大事です。そうしないと、将来また別のマクロや集計で「どっちのコメントが入っているのか分からない」という問題が起きる可能性があります。
運用ルール例:報告書ではメモに統一する
シンプルで分かりやすい運用ルールの一例は次のとおりです。
- 報告書ファイルでは「メモ」だけを使う
- 新しいスレッド付きコメントは使わない
- 既にスレッド付きコメントが存在する場合は、メモへ変換してから利用する
これだけでも、将来のトラブルの多くを避けられます。ユーザーにとっても、「コメントは全部メモです」と言い切れるほうが分かりやすい運用になります。
既存のスレッド付きコメントをメモに変換する手順
Excel には、スレッド付きコメントをメモに変換する機能が用意されています。変換したいセルまたは範囲を選択し、
- セルを右クリック
- 表示されるメニューから「コメントをメモに変換」を選択
これで、そのセルに付いていたスレッド付きコメントがメモに変わります。数が多い場合は、
- コメントが付いているセルだけをフィルターで抽出してからまとめて変換する
- シートごとに変換するタイミングを決めて、作業者に割り当てる
といった工夫をすると効率的です。
コードと運用、両方から「混在リスク」を減らす
ここまで見てきたポイントを整理すると、NoteText 周りのトラブルを防ぐために取るべき対策は、コード面と運用面で次のように整理できます。
| 観点 | 対策内容 |
|---|---|
| コード | Range.NoteText を使わず、Comment と CommentThreaded を順にチェックする 共通関数(例:GetNoteOrCommentText)を作って使い回す コメントが無い場合は空文字を返し、必要に応じてメッセージやログを出す |
| 運用 | 報告書など重要なブックでは「メモに統一」する方針を決める 既存のスレッド付きコメントは、必要に応じてメモへ変換する 担当者に「メモとコメントの違い」を共有し、安易にスレッド付きコメントを使わないよう周知する |
このように、マクロ側だけでなく運用側も整えておくことで、「Excel の仕様変更や UI の違いにマクロが振り回される」状況を減らすことができます。
よくある疑問と実務的な判断ポイント
Q. これから新しく作るマクロでは、メモとコメントのどちらを使うべき?
共同編集が多く、Excel Online なども含めてリアルタイムで複数人がコメントする運用なら、スレッド付きコメントを使うメリットがあります。しかし、
- レポートの添え書き用途が中心
- VBA で一括処理することが多い
といったケースでは、あえてメモに統一してしまったほうがマクロの実装も簡単で、将来の保守も楽になります。
Q. 既存の NoteText を全部書き換えるべき?
理想を言えば書き換えたほうが安全ですが、現実的には次の優先度で対応するのがおすすめです。
- すでにエラー 1004 が出ている箇所を優先的に
GetNoteOrCommentTextを使う形に修正 - 頻繁に実行される重要マクロ(定期レポートなど)から順に NoteText の置き換えを検討
- 影響の小さいサブツールは、機会があるときに少しずつ修正
一気に全部直そうとすると大変なので、「影響が大きいところから少しずつ置き換える」というスタンスで進めると現実的です。
Q. NoteText を使い続けてもいいケースはある?
社内で「絶対にメモしか使わない」と厳格に決めており、既存ブックも全てメモだけ、という状況なら、NoteText を使い続けても困らないかもしれません。ただし、
- 新しいバージョンの Excel を導入したとき
- 別部署から持ち込まれたブックを扱うとき
などのタイミングでスレッド付きコメントが紛れ込むリスクはゼロではありません。そのため、長期的に見ると「NoteText から卒業しておく」ほうが安心です。
まとめ:NoteText に依存せず、どのセルでも安定してコメントを取得する
Excel VBA の Range.NoteText で発生する実行時エラー 1004 は、
- セルに付いているのが「メモ」ではなく「スレッド付きコメント」だった
- NoteText がメモ専用であることを前提に書かれた古いマクロを、そのまま新しい Excel で使っていた
という、仕様のギャップから生まれるトラブルです。
この記事で紹介したように、
Comment→CommentThreadedの順にチェックする関数(GetNoteOrCommentText)を用意する- コメントが存在しない場合にはメッセージやログでユーザーに分かりやすく伝える
- 運用として、報告書ではメモを基本とし、スレッド付きコメントを安易に使わないようルール化する
といった対策を取ることで、NoteText に依存しない、安定したマクロ運用が実現できます。定期レポートや帳票マクロで同様のエラーに悩んでいる場合は、まずコメントの種類を確認し、この記事のコードと運用ルールを取り入れてみてください。

コメント