【Excel VBA】セルのコメント(メモ)を一括操作する方法(コピペOK)

【VBA】セルのコメント(メモ)を一括操作する方法の解説用アイキャッチ画像 VBA
  1. 最初に結論:Excelの「メモ」と「コメント」は別のVBA APIで操作する
  2. メモ・スレッド型コメント・色分けの使い分け
  3. どちらを選ぶか迷ったときの判断基準
    1. 自動判定の結果はメモにする
    2. 会話の履歴はスレッド型コメントにする
    3. 色分けだけで足りるケースもある
    4. 部署内で名称を統一する
  4. 完成イメージ:閾値を超えたセルだけに警告メモを付ける
  5. 実行前に確認する4項目
    1. 1. コードは対象のExcelファイルに保存する
    2. 2. 元ファイルのコピーを残す
    3. 3. 対象シートと範囲を小さくする
    4. 4. Excelのバージョンを確認する
  6. スレッド型コメントを使える環境か3段階で確認する
    1. 1. テスト用ブックでコメントとメモを作り分ける
    2. 2. VBEで対象APIを1セルだけ試す
    3. 3. 配布先で最も古い環境に合わせる
  7. 本番データの前に作るテスト表
    1. 1回目は変更内容を確認する
    2. 2回目は同じ結果になるか確認する
    3. 値を変えて解除動作を確認する
    4. テスト用ファイルを本番へ上書きしない
  8. 変更前に既存の注記を棚卸しする
    1. 対象範囲の外側も数セル確認する
    2. 重要な注記を数件サンプル保存する
    3. 自動生成用の接頭辞を重複させない
    4. 「何もしなかったセル」も結果として見る
  9. 共通準備:別種類の注記を見落とさない関数を1回だけ貼る
  10. STEP1:既存メモを消さずに一括追加する
    1. 変更するのは4か所
  11. 既存メモをどう扱うか先に決める
    1. 最初はスキップを選ぶ
    2. 全文更新は対象を限定する
    3. 追記は重複対策が必要
    4. 識別マーカーは運用上の契約
  12. メモを削除するときは件数確認を入れる
  13. STEP2:閾値超過メモを安全に同期し、一覧を新規作成する
    1. この実務版が既存コードと違う点
  14. 実務版を安全に導入する7段階
    1. 1. 対象列の意味を確認する
    2. 2. 閾値の境界を決める
    3. 3. 自動生成文を業務用語へ合わせる
    4. 4. 手入力メモを意図的に混ぜて試す
    5. 5. 1回目の一覧を元データと照合する
    6. 6. 値を変えて2回目を実行する
    7. 7. 本番範囲を段階的に広げる
  15. 実行結果の数字から異常を見つける
  16. STEP3:スレッド型コメントをVBAで追加する
  17. スレッド型コメントの更新・返信・削除
    1. 本文を更新する
    2. 返信を追加する
    3. 返信ごと削除する
  18. スレッドと返信を一覧で確認する
  19. 共同編集で先に決めておく運用ルール
    1. 質問と作業指示を分ける
    2. 元の質問を上書きしない
    3. 削除条件を決める
    4. 作成者名だけを本人確認に使わない
    5. 担当範囲を限定する
    6. マクロ実行中の同時編集を避ける
  20. 件数が多いときの範囲設計
    1. 空白行より下のデータを見落とさない
    2. 不要な列やシートを含めない
    3. 速度より中断後の確認を優先する
    4. 処理単位を小さくする
  21. 失敗しやすいポイントと対処
    1. AddCommentでエラー1004が出る
    2. メモの一部が一覧に出ない
    3. 正常値に戻っても警告が残る
    4. 結合セルや保護シートで止まる
    5. 違うブックが処理される
    6. スレッド型コメントを編集できない
  22. 公開・配布前のレビュー表
  23. よくある質問
    1. Q1. AddCommentはメモとコメントのどちらを追加しますか?
    2. Q2. 既存メモを残したまま本文だけ更新できますか?
    3. Q3. スレッド型コメントへVBAで返信できますか?
    4. Q4. メモとスレッド型コメントを同じ削除コードで消せますか?
    5. Q5. コメントを印刷できますか?
    6. Q6. Application.UserNameを作成者の証明に使えますか?
    7. Q7. ボタンからマクロを実行できますか?
  24. 用途別に選ぶ最終チェック
    1. Microsoft公式情報

最初に結論:Excelの「メモ」と「コメント」は別のVBA APIで操作する

Excel for Microsoft 365では、セルに付ける注記が「メモ」「コメント」の2種類に分かれている。見た目が似ていても、用途もVBAで使うオブジェクトも別物だ。

  • メモ(旧コメント):返信機能のない付箋型の注記。VBAでは CommentAddCommentClearNotes などを使う
  • スレッド型コメント:共同編集で会話や返信を残す機能。VBAでは CommentThreadedAddCommentThreadedAddReply などを使う

この記事では、両方の違いを整理したうえで、既存の注記を勝手に消さない安全なコードを紹介する。前半は幅広いExcelで使いやすい「メモ」、後半はMicrosoft 365など、スレッド型コメントと対応APIを実際に利用できるデスクトップ版Excel向けだ。

先に答え:従来の AddComment は現在の画面上では「メモ」を追加する。新しい返信可能なコメントを追加する場合は AddCommentThreaded を使う。似た名前のAPIを混ぜないことが最重要だ。

メモ・スレッド型コメント・色分けの使い分け

注記を付ける前に、何を残したいのかを決める。自動判定の結果や定型の注意書きならメモ、担当者同士のやり取りならスレッド型コメント、異常値を目立たせるだけなら条件付き書式やセルの色分けが向いている。

比較項目 メモ(旧コメント) スレッド型コメント 色分け
主な用途 注記、警告、作業メモ 質問、回答、共同レビュー 異常値の可視化
返信 できない できる 対象外
追加するVBA AddComment AddCommentThreaded Interior.Color など
取得するVBA Range.Comment Range.CommentThreaded セルの書式を参照
一覧 Worksheet.Comments Worksheet.CommentsThreaded 対象セルを走査
向いている例 「閾値100超過」「要再検査」 「この数値の根拠を確認してください」 基準外の行を赤くする

文章を残す必要がなく、条件に合うセルを見つけやすくしたいだけなら、セルの値に応じて行を自動色分けする方法のほうが管理しやすい。文章と色の両方が必要な場合は、メモと色分けを併用する。

Microsoft公式も、現在の「コメント」は返信可能なスレッド形式、「メモ」は以前のExcelで「コメント」と呼ばれていた機能だと説明している。画面上の名称とVBAオブジェクト名が一致しないため、コードを読むときは「Comment オブジェクト=メモ」と読み替えると混乱しにくい。

どちらを選ぶか迷ったときの判断基準

メモとスレッド型コメントは、どちらが新しいかではなく、注記を残す目的で選ぶ。大量のセルへ同じ基準で警告を付けるならメモが扱いやすく、特定の数値について担当者同士で回答を往復させるならスレッド型コメントが向いている。

やりたいこと 推奨する機能 理由
基準外のセルへ定型警告を付ける メモ 同じ文言を一括追加・更新しやすい
作業手順や注意事項をセルに残す メモ 返信が不要で、付箋として参照しやすい
数値の根拠を担当者へ質問する スレッド型コメント 質問と回答を1つの会話として残せる
修正が終わったか確認し合う スレッド型コメント 返信と作成者情報を確認できる
異常値をひと目で見つける 色分け 文章を開かなくても状態が分かる
警告理由も見た目の強調も必要 メモ+色分け 詳細と一覧性を両立できる

自動判定の結果はメモにする

「100を超えた」「期限を過ぎた」「必須項目が空白」といった機械的な判定では、相手から返信を受け取ることより、同じルールで注記を付けることが重要になる。メモなら定型文を統一でき、一覧へ書き出した後の集計もしやすい。

ただし、マクロが作った警告と人が書いた説明を区別できない設計では、次回実行時に大切な内容を消す危険がある。本記事では自動生成メモへ専用の印を付け、管理対象を限定する。

会話の履歴はスレッド型コメントにする

「この金額は税込みですか」「元データを確認してください」のように、回答や追加質問が発生する内容はスレッド型コメントが適している。元の質問を上書きせず、返信として経緯を残せるからだ。

一方、一括処理で既存の会話を更新すると、作成者の意図や途中経過が失われる可能性がある。スレッド型コメントを大量追加するコードでも、既存項目は既定でスキップし、更新・返信・削除は対象セルを明示した別操作に分ける。

色分けだけで足りるケースもある

読者が必要としているのが「どの行に問題があるか」だけなら、すべてのセルへメモを付ける必要はない。色分けは一覧性が高く、メモの印が画面に増えすぎる問題も避けられる。原因や対処方法まで残したいセルだけにメモを付けると、表が読みやすい。

部署内で名称を統一する

Microsoft 365の画面で「コメント」と呼ばれる機能を、以前のExcel利用者が旧コメントの意味で使うことがある。仕様書や作業手順では「メモ(旧コメント)」「スレッド型コメント」と省略せず書き、どちらを対象にするか明確にする。

マクロ名も、単にAddCommentsではなくAddNotesやAddThreadedCommentsのように種類を含めるとよい。半年後にコードを見返したときや、別の担当者へ引き継いだときに、削除対象を取り違える事故を減らせる。

完成イメージ:閾値を超えたセルだけに警告メモを付ける

例として、C列の数値が100を超えたセルに「要確認」のメモを付ける。正常値に戻った場合は、マクロが以前に付けた警告だけを解除する。担当者が手入力したメモは削除しない。

実行前

VBAでメモを追加する前のExcel表
製品名 ロット 数値
部品A L001 85
部品B L002 120
部品C L003 95
部品D L004 150
部品E L005 78

実行後

VBAで閾値超過セルに警告メモを追加したExcel表
製品名 ロット 数値 追加されたメモ
部品A L001 85 なし
部品B L002 120 [AUTO:THRESHOLD] 閾値100超過
部品C L003 95 なし
部品D L004 150 [AUTO:THRESHOLD] 閾値100超過
部品E L005 78 なし

先頭の [AUTO:THRESHOLD] は、マクロが作成したメモを識別するための印だ。この印があるメモだけを自動更新・自動削除するため、人が書いたレビュー内容を誤って消しにくい。

実行前に確認する4項目

1. コードは対象のExcelファイルに保存する

この記事のコードは ThisWorkbook を使う。つまり、コードが保存されているブックを処理対象にする。対象ファイルを .xlsm 形式で保存し、そのファイルの標準モジュールにコードを貼り付ける。

PERSONAL.XLSBやアドインへ貼り付けた場合、ThisWorkbook は作業中のファイルではなく、コードを保存した側を指す。初心者のうちは対象ブック内にコードを置くほうが安全だ。

2. 元ファイルのコピーを残す

VBAでメモやコメントを削除すると、通常のセル編集と同じ感覚で元に戻せない場合がある。削除系マクロを試す前にファイルをコピーし、テスト用の範囲で動作確認する。

3. 対象シートと範囲を小さくする

最初から列全体や全シートを指定しない。まずは C2:C5 のような数セルで試し、追加される種類、文言、既存データの扱いを確認してから範囲を広げる。

4. Excelのバージョンを確認する

CommentThreaded 系のコードは、Microsoft 365など、スレッド型コメントと対応APIを実機で確認できるデスクトップ版Excelを対象とする。製品名だけで可否を決めず、下記の手順で確認する。MicrosoftのExcel 2021の機能案内によると、Excel LTSC 2021ではModern Commentsを利用できない。Excel 2019/2016ではメモ用コードを使う。Excel for the webではVBAマクロを作成・実行・編集できない

スレッド型コメントを使える環境か3段階で確認する

買い切り版かサブスクリプション版かという区分だけでは、手元のExcelで同じコードが動くとは限らない。更新状況、OS、組織の管理設定、ファイルの保存場所や権限も関係するため、本番マクロへ組み込む前に画面・VBE・利用者環境の順で確認する。

1. テスト用ブックでコメントとメモを作り分ける

元ファイルのコピーまたは新しい空のブックを開き、校閲メニューやセルの右クリックから、返信できるコメントと付箋型のメモを別々のセルへ1件ずつ作成する。コメントへ返信できれば画面側の機能を確認できる。メニュー名が異なる、またはメモしか作れない場合は、その環境でスレッド型コードを前提にしない。

この確認は必ずテスト用ブックで行う。共同編集の本番ファイルでは、試しに投稿した文章も他の利用者へ通知されたり、会話履歴として残ったりする可能性がある。動作確認用のセルと文章を決め、試験後に削除してよいことも先に確認する。

2. VBEで対象APIを1セルだけ試す

画面でスレッド型コメントを使えても、いきなり一括処理はしない。後半の追加コードで対象範囲を空の1セルだけにし、追加、取得、返信、削除を順番に試す。コンパイルエラーや実行時エラーが出た場合は、エラーを無視して範囲を広げず、メモ用コードへ切り替える。

テストでは、既存メモがあるセル、既存のスレッド型コメントがあるセル、何もないセルを分ける。3種類のセルで結果を確認すると、別形式の注記を上書きしていないか判断しやすい。権限やサインイン状態による失敗もあるため、APIが存在することと、現在のファイルで編集できることは別々に確認する。

3. 配布先で最も古い環境に合わせる

作成者のExcelで動いても、利用者全員が同じ環境とは限らない。部署で使うExcelの種類と更新状況を確認し、スレッド型APIを利用できない人が1人でもいるなら、メモ版とスレッド型版を分けるか、メモ版へ統一する。マクロを開いた時点でコンパイルできないコードを同じ配布ファイルへ混ぜない。

特にExcel LTSC 2021は、名称に「2021」が含まれていてもModern Commentsを利用できないとMicrosoftが案内している。Excel 2024など別の買い切り版についても名称だけで対応を断定せず、実際にコメントを作成でき、VBEで対象APIを呼び出せることを確認してから使う。

判断に迷った場合:定型警告を付ける目的ならメモ版を選ぶ。返信履歴が業務上必要で、利用者全員の環境と権限を確認できた場合だけスレッド型コメント版を使う。

本番データの前に作るテスト表

正常な数値だけで試すと、実務データで起きる問題を見落とす。空白、文字列、セルエラー、既存メモ、自動生成メモを含む小さなテスト表を作り、1回目と2回目の結果を確認する。

C列の値 実行前の状態 期待する結果
2 85 注記なし 何も追加しない
3 120 注記なし 自動警告メモを追加
4 空白 注記なし 処理対象外
5 未確認 注記なし 数値ではないため処理対象外
6 #N/A 注記なし エラー値として数えてスキップ
7 150 人が書いたメモあり 既存メモを残してスキップ
8 130 古い自動警告メモあり 現在の文言へ更新
9 90 自動警告メモあり 正常化したため自動メモだけ削除
10 95 人が書いたメモあり 正常値でも人のメモは残す

1回目は変更内容を確認する

実行後に、追加件数、更新件数、解除件数、手入力メモのスキップ件数、エラーセルのスキップ件数を照合する。件数が期待と違う場合は、本番範囲へ広げず、どの行で想定がずれたかを確認する。

2回目は同じ結果になるか確認する

値を変えずに同じマクロをもう一度実行したとき、同じ警告が重複して増えないことを確認する。自動化では、何度実行しても状態が崩れないことが重要だ。自動メモは追加ではなく更新になり、人が書いたメモは引き続き残るのが正しい。

値を変えて解除動作を確認する

120だったセルを80へ変更して再実行し、自動生成メモだけが消えるか確認する。逆に、人が書いたメモを持つセルの値を変えても、そのメモが残ることを確認する。追加だけでなく解除まで試して初めて、繰り返し運用に使える。

テスト用ファイルを本番へ上書きしない

テストでは元ファイルのコピーを使い、結果を確認した後も元データとは別名で保存する。対象シート名や列が異なる本番ファイルへ移すときは、定数を書き換えた直後にもう一度少数行で試す。

変更前に既存の注記を棚卸しする

安全なコードでも、実行前の状態を把握していなければ結果を判断できない。対象範囲にメモとスレッド型コメントが何件あるか、誰がどの目的で使っているかを先に確認する。特に、同じ列を自動警告と担当者のレビューに兼用している場合は、一括処理を始める前に用途を分ける。

実行前の状態 今回の扱い 実行後の確認
注記なし 条件に合う場合だけ新規追加 想定した文面と種類か
手入力メモあり 変更せずスキップ 本文がそのまま残ったか
自動生成メモあり 接頭辞が一致するものだけ同期 更新または解除が正しいか
スレッド型コメントあり メモ用処理から除外 本文と返信が残ったか
セルエラーあり 値を評価せずスキップ スキップ件数に含まれたか

対象範囲の外側も数セル確認する

設定した範囲内だけを見ると、開始行や最終行の指定ミスに気付きにくい。対象範囲の直前と直後にある数セルも確認し、処理されるべきセルが外れていないか、処理してはいけない見出しや小計行を含んでいないかを見る。列を間違えた場合は件数が正常に見えることもあるため、セル番地と実データを組み合わせて確認する。

重要な注記を数件サンプル保存する

実行前に、手入力メモと返信付きコメントをそれぞれ数件選び、セル番地と本文を控える。画面キャプチャでもよいが、長い文章は別シートや管理用ファイルへコピーすると比較しやすい。実行後は同じセルを開き、本文だけでなく、注記の種類と返信が変わっていないことを確認する。

サンプル確認はバックアップの代わりではない。バックアップはファイル全体を元へ戻すため、サンプルはマクロが設計どおりに対象を選んだかを短時間で確かめるために使う。両方を用意しておくと、問題があったときに復旧と原因調査を分けて進められる。

自動生成用の接頭辞を重複させない

[AUTO:THRESHOLD] と同じ文字列を人が手入力すると、そのメモは自動生成分として更新・削除される可能性がある。接頭辞は部署や用途ごとに決め、利用者が通常の文章へ使わない形式にする。既存の別マクロが同じ接頭辞を使っていないことも確認する。

運用開始後に接頭辞を変更すると、旧接頭辞のメモが管理対象から外れて残る。変更が必要な場合は、旧形式をどの範囲で新形式へ移行するかを決め、移行用マクロと日常運用マクロを分ける。日常マクロの中で複数世代のメモを無条件に削除しない。

「何もしなかったセル」も結果として見る

追加件数だけを確認すると、既存メモやスレッド型コメントを正しく避けたか分からない。本記事のコードは、既存メモ、スレッド型コメント、セルエラーを分けて数える。想定よりスキップが多い場合は成功とみなさず、対象列の用途、注記の混在、入力形式を確認する。

反対にスキップが0件でも、確認処理が働いているとは限らない。テスト表へ意図的にメモとスレッド型コメントを1件ずつ置き、それぞれの件数が1になることを確かめる。異常系を含めた小さなテストで結果を説明できてから、本番範囲へ広げる。

確認結果を残すときは、「成功」だけでなく、実行したブック名、シート名、対象範囲、閾値、各スキップ件数、一覧シート名を記録する。後日同じマクロを実行して件数が変わった場合、データの変化なのか設定の違いなのかを比較できる。担当者が交代しても、何を確認すればよいかを引き継ぎやすい。

記録した件数とサンプルセルの確認結果が一致しない場合は、その場で保存・配布を止める。原因を特定するまでは本番ファイルへ再実行せず、コピーしたテストファイルで条件と対象範囲を見直す。

共通準備:別種類の注記を見落とさない関数を1回だけ貼る

メモ用マクロでも、対象セルにスレッド型コメントがあれば変更対象から外す必要がある。ただし古いExcelでは CommentThreaded プロパティ自体を直接書くとコンパイルできない場合がある。次の共通関数は CallByName を使い、利用できる環境だけでプロパティを調べる。

標準モジュールの先頭へ次のコードを1回だけ貼る。後続の AddNotesSafelySyncThresholdNotesAndExport は、この関数を呼び出して既存のスレッド型コメントをスキップする。


Option Explicit

Private Function HasThreadedComment(ByVal target As Range) As Boolean

    Dim item As Object

    On Error Resume Next
    Set item = CallByName(target, "CommentThreaded", VbGet)
    On Error GoTo 0

    HasThreadedComment = Not item Is Nothing

End Function

On Error Resume Next は、プロパティの取得部分だけに限定している。スレッド型APIがない古いExcelや、対象セルにスレッド型コメントがない場合は False を返す。メモの追加・更新処理そのもののエラーは、この関数で握りつぶさない。

STEP1:既存メモを消さずに一括追加する

最初のコードは、指定範囲の空白でないセルへメモを追加する。既存メモまたはスレッド型コメントがあるセルは既定でスキップするため、担当者が書いた文章を勝手に置き換えない。


Sub AddNotesSafely()

    Const SHEET_NAME As String = "Sheet1"
    Const TARGET_ADDRESS As String = "C2:C100"
    Const NOTE_TEXT As String = "チェック済み"
    Const OVERWRITE_EXISTING As Boolean = False

    Dim ws As Worksheet
    Dim target As Range
    Dim cell As Range
    Dim addedCount As Long
    Dim updatedCount As Long
    Dim skippedCount As Long
    Dim threadedSkippedCount As Long

    On Error GoTo ErrHandler

    Set ws = ThisWorkbook.Worksheets(SHEET_NAME)
    Set target = ws.Range(TARGET_ADDRESS)

    If ws.ProtectContents Then
        MsgBox "シートが保護されています。保護を解除してから実行してください。", vbExclamation
        Exit Sub
    End If

    Application.ScreenUpdating = False

    For Each cell In target.Cells

        If Not IsError(cell.Value2) Then
            If Len(CStr(cell.Value2)) > 0 Then

                If HasThreadedComment(cell) Then
                    threadedSkippedCount = threadedSkippedCount + 1

                ElseIf cell.Comment Is Nothing Then
                    cell.AddComment Text:=NOTE_TEXT
                    addedCount = addedCount + 1

                ElseIf OVERWRITE_EXISTING Then
                    cell.Comment.Text Text:=NOTE_TEXT
                    updatedCount = updatedCount + 1

                Else
                    skippedCount = skippedCount + 1
                End If

            End If
        End If

    Next cell

CleanExit:
    Application.ScreenUpdating = True

    MsgBox "追加: " & addedCount & " 件" & vbCrLf & _
           "更新: " & updatedCount & " 件" & vbCrLf & _
           "既存メモのためスキップ: " & skippedCount & " 件" & vbCrLf & _
           "既存のスレッド型コメントのためスキップ: " & _
           threadedSkippedCount & " 件", vbInformation
    Exit Sub

ErrHandler:
    Application.ScreenUpdating = True
    MsgBox "処理を中止しました。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical

End Sub

変更するのは4か所

定数 役割 初期値
SHEET_NAME 対象シート名 Sheet1
TARGET_ADDRESS メモを追加する範囲 C2:C100
NOTE_TEXT 追加する文章 チェック済み
OVERWRITE_EXISTING 既存メモを全文更新するか False

安全を優先するなら OVERWRITE_EXISTINGFalse のまま使う。True にすると、指定範囲内の既存メモを定型文へ置き換える。どちらを選んでも、実行結果として追加・更新・スキップ件数が表示される。

セルに #N/A などのエラー値がある場合でも止まりにくいように、先に IsError で確認している。VBAの And は短絡評価ではないため、複数条件を1行へ詰め込まず、判定を内側へ分けている。既存のスレッド型コメントは共通関数で先に検出し、メモを追加せずスキップ件数へ含める。

既存メモをどう扱うか先に決める

メモの一括処理で最も危険なのは、追加に失敗することではなく、既存の説明を気付かず消すことだ。マクロを配布する前に、既存メモがあるセルをどの方針で扱うか決める。

方針 動作 向いている場面 注意点
スキップ 既存メモを変更しない 初回導入、共同作業 新しい定型文は付かない
全文更新 既存本文を置き換える 対象が自動生成メモだけと保証できる場合 手入力内容を失う危険がある
末尾へ追記 既存本文の後ろへ文章を足す 履歴を残したい単発処理 繰り返すと同じ文が増える
識別マーカーで同期 自動生成分だけ更新・解除する 定期実行、長期運用 マーカーのルールを変更しない

最初はスキップを選ぶ

どのメモを誰が書いたか分からない状態では、スキップが最も安全だ。処理後にスキップ件数を確認し、必要なセルだけ人が判断する。数件の手作業が残っても、重要なレビュー内容を一括消去するより安全性が高い。

全文更新は対象を限定する

範囲内のメモがすべてマクロ生成だと確認できる場合だけ、全文更新を使う。シート全体や列全体へ無条件に適用せず、専用列や専用シートに限定する。運用途中から人が自由記入を始める可能性もあるため、定期的に前提を見直す。

追記は重複対策が必要

既存本文を残して追記する方法は安全に見えるが、毎日実行すると同じ警告が何行も増える。追記前に同じ文言が含まれているか確認するか、日付ごとに1回だけ追加する規則が必要になる。単純な一括処理ではスキップか識別マーカーのほうが管理しやすい。

識別マーカーは運用上の契約

実務版で使う印は、単なる飾りではない。マクロが変更してよいメモを判定する境界になる。担当者が手作業で同じ印を書かないこと、別のマクロが同じ印を使わないこと、印の文字列を途中で変えないことをチーム内で共有する。

メモを削除するときは件数確認を入れる

一括削除は追加より影響が大きい。次のコードは対象範囲にあるメモ数を数え、シート名・範囲・件数を確認ダイアログへ表示してから、数えたメモを1件ずつ Comment.Delete で削除する。スレッド型コメントはこのコードの対象ではない。


Sub DeleteNotesWithConfirmation()

    Const SHEET_NAME As String = "Sheet1"
    Const TARGET_ADDRESS As String = "C2:C100"

    Dim ws As Worksheet
    Dim target As Range
    Dim cell As Range
    Dim noteCount As Long
    Dim answer As VbMsgBoxResult

    Set ws = ThisWorkbook.Worksheets(SHEET_NAME)
    Set target = ws.Range(TARGET_ADDRESS)

    If ws.ProtectContents Then
        MsgBox "シートが保護されています。保護を解除してから実行してください。", vbExclamation
        Exit Sub
    End If

    For Each cell In target.Cells
        If Not cell.Comment Is Nothing Then
            noteCount = noteCount + 1
        End If
    Next cell

    If noteCount = 0 Then
        MsgBox "対象範囲にメモはありません。", vbInformation
        Exit Sub
    End If

    answer = MsgBox( _
        "シート: " & ws.Name & vbCrLf & _
        "範囲: " & target.Address(False, False) & vbCrLf & _
        "削除するメモ: " & noteCount & " 件" & vbCrLf & vbCrLf & _
        "削除を実行しますか?", _
        vbYesNo + vbExclamation, _
        "メモ削除の確認")

    If answer <> vbYes Then Exit Sub

    For Each cell In target.Cells
        If Not cell.Comment Is Nothing Then
            cell.Comment.Delete
        End If
    Next cell

    MsgBox noteCount & " 件のメモを削除しました。", vbInformation

End Sub

ClearNotes は範囲内のメモをまとめて削除するメソッドだ。ただしMicrosoft公式ではサウンド付きメモも削除対象に含まれるため、上の確認コードは数えた Comment オブジェクトを1件ずつ削除し、確認件数と処理対象をそろえている。古いコードでは ClearComments も見かけるが、現在の画面上の「コメント」と区別して説明する場合は ClearNotes または Comment.Delete のほうが意図を読み取りやすい。

STEP2:閾値超過メモを安全に同期し、一覧を新規作成する

実務では、毎回メモを追加するだけでは不十分だ。前回は基準外だった値が正常に戻った場合、古い警告を残すと判断を誤る。一方で、すべてのメモを削除して付け直すと、人が書いたレビュー内容まで消えてしまう。

次の実務版は、マクロが作成したメモだけに [AUTO:THRESHOLD] という印を付ける。この印を手掛かりに、基準外なら追加または更新、正常値なら自動生成メモだけを解除する。手入力メモがあるセルはスキップする。

処理後の一覧は既存シートを削除せず、メモ一覧_yyyymmdd_hhnnss という時刻付きの新規シートへ出力する。同名がすでに存在する場合は末尾に連番を付けるため、利用者のデータや直前の一覧を消さない設計だ。


Sub SyncThresholdNotesAndExport()

    Const SHEET_NAME As String = "Sheet1"
    Const DATA_COLUMN As String = "C"
    Const START_ROW As Long = 2
    Const THRESHOLD As Double = 100
    Const AUTO_PREFIX As String = "[AUTO:THRESHOLD] "

    Dim ws As Worksheet
    Dim wsOut As Worksheet
    Dim existingSheet As Worksheet
    Dim cell As Range
    Dim lastRow As Long
    Dim i As Long
    Dim outRow As Long
    Dim autoText As String
    Dim currentText As String
    Dim outputBaseName As String
    Dim outputSheetName As String
    Dim suffix As Long

    Dim addedCount As Long
    Dim updatedCount As Long
    Dim removedCount As Long
    Dim manualSkippedCount As Long
    Dim errorSkippedCount As Long
    Dim threadedSkippedCount As Long

    On Error GoTo ErrHandler

    Set ws = ThisWorkbook.Worksheets(SHEET_NAME)

    If ws.ProtectContents Then
        MsgBox "シートが保護されています。保護を解除してから実行してください。", vbExclamation
        Exit Sub
    End If

    lastRow = ws.Cells(ws.Rows.Count, DATA_COLUMN).End(xlUp).Row
    If lastRow < START_ROW Then
        MsgBox "処理対象のデータがありません。", vbInformation
        Exit Sub
    End If

    autoText = AUTO_PREFIX & "閾値" & THRESHOLD & "超過"
    Application.ScreenUpdating = False

    For i = START_ROW To lastRow
        Set cell = ws.Cells(i, DATA_COLUMN)

        If HasThreadedComment(cell) Then
            threadedSkippedCount = threadedSkippedCount + 1

        ElseIf IsError(cell.Value2) Then
            errorSkippedCount = errorSkippedCount + 1

        ElseIf Len(CStr(cell.Value2)) > 0 Then

            If IsNumeric(cell.Value2) Then

                If CDbl(cell.Value2) > THRESHOLD Then

                    If cell.Comment Is Nothing Then
                        cell.AddComment Text:=autoText
                        addedCount = addedCount + 1
                    Else
                        currentText = cell.Comment.Text

                        If Left$(currentText, Len(AUTO_PREFIX)) = AUTO_PREFIX Then
                            cell.Comment.Text Text:=autoText
                            updatedCount = updatedCount + 1
                        Else
                            manualSkippedCount = manualSkippedCount + 1
                        End If
                    End If

                ElseIf Not cell.Comment Is Nothing Then
                    currentText = cell.Comment.Text

                    If Left$(currentText, Len(AUTO_PREFIX)) = AUTO_PREFIX Then
                        cell.Comment.Delete
                        removedCount = removedCount + 1
                    End If
                End If

            End If
        End If
    Next i

    outputBaseName = "メモ一覧_" & Format(Now, "yyyymmdd_hhnnss")
    outputSheetName = outputBaseName

    Do
        Set existingSheet = Nothing

        On Error Resume Next
        Set existingSheet = ThisWorkbook.Worksheets(outputSheetName)
        On Error GoTo ErrHandler

        If existingSheet Is Nothing Then Exit Do

        suffix = suffix + 1
        outputSheetName = outputBaseName & "_" & suffix
    Loop

    Set wsOut = ThisWorkbook.Worksheets.Add( _
        After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
    wsOut.Name = outputSheetName

    wsOut.Cells(1, 1).Value = "出力日時"
    wsOut.Cells(1, 2).Value = "シート名"
    wsOut.Cells(1, 3).Value = "セル"
    wsOut.Cells(1, 4).Value = "種類"
    wsOut.Cells(1, 5).Value = "メモ本文"
    wsOut.Cells(1, 6).Value = "セルの値"
    wsOut.Rows(1).Font.Bold = True

    outRow = 2

    For i = START_ROW To lastRow
        Set cell = ws.Cells(i, DATA_COLUMN)

        If Not cell.Comment Is Nothing Then
            wsOut.Cells(outRow, 1).Value = Now
            wsOut.Cells(outRow, 2).Value = ws.Name
            wsOut.Cells(outRow, 3).Value = cell.Address(False, False)
            wsOut.Cells(outRow, 4).Value = "メモ"
            wsOut.Cells(outRow, 5).Value = cell.Comment.Text

            If IsError(cell.Value2) Then
                wsOut.Cells(outRow, 6).Value = "セルエラー"
            Else
                wsOut.Cells(outRow, 6).Value = cell.Value2
            End If

            outRow = outRow + 1
        End If
    Next i

    wsOut.Columns("A:F").EntireColumn.AutoFit
    Application.ScreenUpdating = True

    MsgBox "自動メモの追加: " & addedCount & " 件" & vbCrLf & _
           "自動メモの更新: " & updatedCount & " 件" & vbCrLf & _
           "正常化により解除: " & removedCount & " 件" & vbCrLf & _
           "手入力メモのためスキップ: " & manualSkippedCount & " 件" & vbCrLf & _
           "セルエラーのためスキップ: " & errorSkippedCount & " 件" & vbCrLf & _
           "スレッド型コメントのためスキップ: " & threadedSkippedCount & " 件" & vbCrLf & _
           "一覧シート: " & wsOut.Name, vbInformation
    Exit Sub

ErrHandler:
    Application.ScreenUpdating = True
    MsgBox "処理を中止しました。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical

End Sub

この実務版が既存コードと違う点

  • 既存メモを削除してから追加する処理をやめ、手入力メモを保護する
  • 自動生成マーカーがあるメモだけを更新・解除する
  • #N/A などのエラー値セルを数えてスキップする
  • スレッド型コメントがあるセルは変更せず、別のスキップ件数として表示する
  • 「メモ一覧」シートを削除せず、実行ごとに時刻付きで新規作成する
  • 同じ秒に再実行してシート名が重なった場合は _1_2 と連番を付ける
  • 処理件数を種類別に表示し、何が変更されたか確認できる

このコードで「同期」するのは、C列の現在の最終データ行までにある数値セルだ。空白、文字列、セルエラーは正常値とは判定せず、既存の自動メモを残す。最終行より下に古い自動メモがある場合も対象外になるため、データ行を削除した後は範囲外に注記が残っていないか別途確認する。

一覧シート名は秒単位の時刻を基準にするが、同名がすでに存在するときは連番を付けてからシートを追加する。名前変更に失敗して処理途中の空シートが残る問題を避け、同じ秒に連続実行しても既存一覧を上書きしない。

実務版を安全に導入する7段階

1. 対象列の意味を確認する

例ではC列を数値列としているが、本番ファイルで同じとは限らない。列見出し、開始行、最終行の決まりを確認する。途中に小計行や見出し行がある場合は、数値として判定してよい行だけを対象にする。

2. 閾値の境界を決める

「100を超える」と「100以上」は結果が異なる。例のコードでは100ちょうどは正常、100を超えた値だけが警告対象になる。業務ルールが100以上なら比較条件を変更する。小数や負数があり得る場合も、代表値を使って境界を確認する。

3. 自動生成文を業務用語へ合わせる

警告文は、読んだ人が次に何をすればよいか分かる内容にする。「エラー」だけではなく、「閾値100超過:元データを再確認」のように、判定理由と次の行動を短く書く。部署内で同じ表現を使えば、一覧出力後の集計もしやすい。

4. 手入力メモを意図的に混ぜて試す

本番前のテスト表へ「担当者確認済み」などの手入力メモを1件追加する。マクロ実行後もその文章が残り、スキップ件数が増えることを確認する。このテストに通らなければ、本番では既存情報を失う可能性がある。

5. 1回目の一覧を元データと照合する

新しく作成された一覧シートで、セル番地、メモ本文、セル値が元シートと一致するか確認する。件数だけで合否を決めず、先頭、中央、末尾から数件ずつ内容を見比べる。出力日時は処理時刻の記録であり、メモが最初に作成された日時ではない点にも注意する。

6. 値を変えて2回目を実行する

警告対象だったセルを正常値へ、正常値だったセルを警告対象へ変更する。2回目の実行で古い自動メモが解除され、新しい対象へ追加されるか確認する。同時に、人が書いたメモが変化していないことを確認する。

7. 本番範囲を段階的に広げる

数セル、数十行、対象列全体の順に範囲を広げる。最初から複数シートや複数ブックを処理しない。各段階で件数と一覧を確認し、想定外の列やシートへ変更がないことを確かめる。

実行結果の数字から異常を見つける

マクロ終了時の件数は、単なる完了メッセージではなく、設定ミスを見つける材料になる。対象行数と各件数の関係を見て、処理が想定どおりか判断する。

表示された状態 考えられる原因 確認する場所
追加件数が0 閾値対象がない、列指定が違う、値が文字列 対象列、開始行、セルの型
手入力メモのスキップが多い 対象列が既存レビュー欄として使われている 運用ルール、専用列の必要性
エラーセルのスキップが多い 数式エラーが広がっている 元データと数式
解除件数が急増 値が正常化した、閾値を変更した、列を誤指定した 今回の設定と前回設定
一覧件数が予想より少ない 開始行・最終行の範囲外にメモがある 出力対象範囲

件数が大きく変わったときは、成功メッセージが出てもそのまま保存しない。元ファイルのコピーと比較し、設定変更による正しい変化か、対象範囲の間違いかを切り分ける。

一覧シートは作業履歴として便利だが、これだけで厳密な監査証跡になるわけではない。ファイル自体を編集できる人は一覧も変更できるため、正式な証跡が必要ならアクセス権限、ファイルの保存履歴、承認フローも別途整える。

処理中に予期しないエラーが起きた場合、VBAはデータ変更を自動でロールバックしない。エラーハンドラは画面更新を戻して原因を表示するためのものであり、バックアップの代わりではない。エラー処理の基本はVBAのエラー処理で止まらないマクロを作る方法で詳しく解説している。

STEP3:スレッド型コメントをVBAで追加する

Microsoft 365などの新しいExcelでは、返信可能なスレッド型コメントもVBAで操作できる。追加には Range.AddCommentThreaded、取得には Range.CommentThreaded、本文更新には CommentThreaded.Text、返信には AddReply、削除には Delete を使う。

対応環境に注意:次のコードは、Microsoft 365など、スレッド型コメントと対応APIを実機確認できたデスクトップ版Excel向け。Excel LTSC 2021は対象外だ。買い切り版も製品名だけで判断せず、先ほどの3段階で確認する。コンパイルエラーになる環境では前半のメモ用コードを使う。

次のコードは指定範囲の空白でないセルへスレッド型コメントを追加する。既存のメモまたはスレッド型コメントがあるセルはスキップし、黙って置き換えない。


Sub AddThreadedCommentsSafely()

    Const SHEET_NAME As String = "Sheet1"
    Const TARGET_ADDRESS As String = "C2:C20"
    Const COMMENT_TEXT As String = "内容を確認してください"

    Dim ws As Worksheet
    Dim cell As Range
    Dim thread As CommentThreaded
    Dim addedCount As Long
    Dim skippedCount As Long

    On Error GoTo ErrHandler
    Set ws = ThisWorkbook.Worksheets(SHEET_NAME)

    For Each cell In ws.Range(TARGET_ADDRESS).Cells

        If Not IsError(cell.Value2) Then
            If Len(CStr(cell.Value2)) > 0 Then

                If Not cell.Comment Is Nothing Then
                    skippedCount = skippedCount + 1
                Else
                    Set thread = Nothing

                    ' コメントがないセルでの取得部分だけエラーを限定して吸収
                    On Error Resume Next
                    Set thread = cell.CommentThreaded
                    On Error GoTo ErrHandler

                    If thread Is Nothing Then
                        Set thread = cell.AddCommentThreaded(Text:=COMMENT_TEXT)
                        addedCount = addedCount + 1
                    Else
                        skippedCount = skippedCount + 1
                    End If
                End If

            End If
        End If

    Next cell

    MsgBox "追加: " & addedCount & " 件" & vbCrLf & _
           "既存のメモ・コメントのためスキップ: " & skippedCount & " 件", vbInformation
    Exit Sub

ErrHandler:
    MsgBox "処理を中止しました。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical

End Sub

On Error Resume Next は広い範囲に掛けず、コメントがないセルから CommentThreaded を取得する箇所だけに限定している。その直後に通常のエラー処理へ戻すことで、別の不具合まで黙って無視するのを防ぐ。

スレッド型コメントの更新・返信・削除

以下の3本はスレッド型コメント専用だ。対象セルに旧形式のメモがある場合は、Range.Comment を先に確認して処理を中止する。似たAPIから別種類の注記を取得したように見える環境があっても、メモを更新・返信・削除の対象へ混ぜない。

本文を更新する

既存のスレッド型コメント本文を全文置換する場合は Text メソッドを使う。編集権限やサインイン状態によっては更新できない場合があるため、共同編集ファイルでは1セルで試す。


Sub UpdateThreadedComment()

    Const SHEET_NAME As String = "Sheet1"
    Const TARGET_ADDRESS As String = "E5"

    Dim target As Range
    Dim thread As CommentThreaded

    Set target = ThisWorkbook.Worksheets(SHEET_NAME).Range(TARGET_ADDRESS)

    If Not target.Comment Is Nothing Then
        MsgBox "対象セルはメモです。スレッド型コメントだけを指定してください。", vbExclamation
        Exit Sub
    End If

    On Error Resume Next
    Set thread = target.CommentThreaded
    On Error GoTo 0

    If thread Is Nothing Then
        MsgBox "対象セルにスレッド型コメントはありません。", vbInformation
        Exit Sub
    End If

    On Error GoTo ErrHandler
    thread.Text Text:="更新後のコメント"
    MsgBox "コメント本文を更新しました。", vbInformation
    Exit Sub

ErrHandler:
    MsgBox "更新できませんでした。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical

End Sub

返信を追加する

会話を残したい場合は、元の本文を上書きせず AddReply で返信を追加する。


Sub ReplyToThreadedComment()

    Const SHEET_NAME As String = "Sheet1"
    Const TARGET_ADDRESS As String = "E5"

    Dim target As Range
    Dim thread As CommentThreaded
    Dim reply As CommentThreaded

    Set target = ThisWorkbook.Worksheets(SHEET_NAME).Range(TARGET_ADDRESS)

    If Not target.Comment Is Nothing Then
        MsgBox "対象セルはメモです。スレッド型コメントだけを指定してください。", vbExclamation
        Exit Sub
    End If

    On Error Resume Next
    Set thread = target.CommentThreaded
    On Error GoTo 0

    If thread Is Nothing Then
        MsgBox "対象セルにスレッド型コメントはありません。", vbInformation
        Exit Sub
    End If

    On Error GoTo ErrHandler
    Set reply = thread.AddReply(Text:="確認しました")
    MsgBox "返信を追加しました。", vbInformation
    Exit Sub

ErrHandler:
    MsgBox "返信を追加できませんでした。" & vbCrLf & _
           "エラー番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical

End Sub

返信ごと削除する

親のスレッド型コメントへ Delete を実行すると、関連する返信もすべて削除される。次のコードは旧形式のメモなら中止し、スレッド型コメントを取得できた場合だけ、セル番地と返信への影響を表示して確認する。


Sub DeleteThreadedCommentWithConfirmation()

    Const SHEET_NAME As String = "Sheet1"
    Const TARGET_ADDRESS As String = "E5"

    Dim target As Range
    Dim thread As CommentThreaded

    Set target = ThisWorkbook.Worksheets(SHEET_NAME).Range(TARGET_ADDRESS)

    If Not target.Comment Is Nothing Then
        MsgBox "対象セルはメモです。スレッド型コメントだけを指定してください。", vbExclamation
        Exit Sub
    End If

    On Error Resume Next
    Set thread = target.CommentThreaded
    On Error GoTo 0

    If thread Is Nothing Then
        MsgBox "対象セルにスレッド型コメントはありません。", vbInformation
        Exit Sub
    End If

    If MsgBox( _
        target.Address(False, False) & _
        " のコメントとすべての返信を削除しますか?", _
        vbYesNo + vbExclamation, _
        "スレッド型コメント削除の確認") = vbYes Then

        thread.Delete
    End If

End Sub

スレッドと返信を一覧で確認する

Worksheet.CommentsThreaded は、ワークシートにあるトップレベルの項目を返す。Microsoft公式資料では、このコレクションには新旧両方が含まれると説明されているため、「このコレクションを回せば新形式だけ取得できる」とは判断しない。

次のコードは、作成者、APIから取得できる日時情報、本文、返信をイミディエイトウィンドウへ出力する。VBEで「表示」→「イミディエイトウィンドウ」を開いて確認する。コレクションには旧形式も含まれるが、旧形式に対する Date の意味はMicrosoftの当該資料で詳しく説明されていないため、正式な作成日時の証明には使わず参考情報として扱う。


Sub ListCommentsAndReplies()

    Dim ws As Worksheet
    Dim thread As CommentThreaded
    Dim reply As CommentThreaded

    Set ws = ThisWorkbook.Worksheets("Sheet1")

    For Each thread In ws.CommentsThreaded
        Debug.Print thread.Author.Name, thread.Date, thread.Text

        For Each reply In thread.Replies
            Debug.Print "  Reply:", _
                        reply.Author.Name, reply.Date, reply.Text
        Next reply
    Next thread

End Sub

返信が0件でも、新しいスレッド型コメントである可能性がある。返信数だけでメモかコメントかを判定しない。確実な分類が必要な運用では、対象セルを決めて Range.CommentRange.CommentThreaded をそれぞれ確認し、実際のExcel環境で動作テストする。

共同編集で先に決めておく運用ルール

スレッド型コメントは会話を残せる反面、誰がどのタイミングで更新・返信・削除するかを決めないと、未対応項目が埋もれる。マクロで追加する前に、少なくとも次のルールを共有する。

質問と作業指示を分ける

「この値で正しいですか」という質問と「30日までに修正してください」という作業指示を同じ文面に混ぜると、返信があっても作業完了か判断しづらい。コメント本文の先頭に「質問」「修正依頼」「確認依頼」などの分類を付けると、担当者が次の行動を理解しやすい。

元の質問を上書きしない

共同レビューでは、元のコメント本文を更新するより返信を追加するほうが経緯を残しやすい。誤字修正のように本文更新が必要な場合を除き、回答や進捗は返信として記録する。マクロで一括更新する対象は、自分が作成した定型コメントなど、範囲を限定する。

削除条件を決める

解決済みだからといってすぐ削除すると、後から判断理由を追えなくなる。一定期間残す、月次締め後に削除する、削除前に一覧を保存するなどの条件を決める。親コメントを削除すると返信も消えるため、削除件数だけでなく会話全体への影響を確認する。

作成者名だけを本人確認に使わない

画面に表示される名前は作業の参考にはなるが、それだけで正式な承認者を証明できるとは限らない。重要な承認は、組織のワークフロー、ファイルのアクセス履歴、別の承認記録と組み合わせる。コメント一覧の出力も、確認用資料として扱う。

担当範囲を限定する

全員が全コメントを更新できる運用より、シート、列、案件などで担当範囲を分けるほうが競合しにくい。一括追加マクロの対象範囲も担当領域に合わせ、他部署が使う列へコメントを付けないようにする。

マクロ実行中の同時編集を避ける

共同編集ファイルで複数人が同時に注記を変更すると、実行開始時の状態と保存時の状態がずれる可能性がある。一括追加や削除を行う時間を決め、実行中は対象範囲を編集しないよう周知する。処理後に保存・同期が完了したことも確認する。

件数が多いときの範囲設計

数百行ならセルを順番に確認する方法でも扱いやすいが、シート全体の使用範囲が不必要に広いブックでは処理時間が伸びる。列全体を指定せず、データの開始行と最終行を取得して必要な範囲だけを処理する。

空白行より下のデータを見落とさない

例の最終行取得は、指定列の一番下から上へ検索する方法だ。途中に空白行があっても、その下に値があれば対象に含まれる。一方、指定列だけが空白で別列にデータが続く表では、想定より短い範囲になる。どの列を基準に最終行を決めるか確認する。

不要な列やシートを含めない

メモの一覧化を目的に使用範囲全体を走査すると、書式だけが残った遠いセルまで対象になることがある。業務上メモを付ける列が決まっているなら、その列とデータ行だけを対象にする。全シート対応は、1シート版の結果が安定してから追加する。

速度より中断後の確認を優先する

画面更新を止めると処理は速くなるが、途中で何が変更されたかは見えにくい。処理件数を記録し、エラー時には対象行を確認できるようにする。最初の導入では速度を追うより、少数行で変更内容を説明できることを優先する。

処理単位を小さくする

大量データを一度に変更すると、設定ミスがあった場合の確認範囲も大きくなる。部署別、月別、シート別など、元に戻しやすい単位へ分けて実行する。各単位の前後で一覧と件数を保存すれば、どこまで完了したか把握しやすい。

失敗しやすいポイントと対処

AddCommentでエラー1004が出る

同じセルに既存メモや別種類の注記がある可能性がある。追加前に cell.Comment Is Nothing を確認し、既存内容を残すか更新するかを明示的に決める。エラー回避のために無条件で削除するのは危険だ。

メモの一部が一覧に出ない

SpecialCells(xlCellTypeComments) はメモ取得で使われるが、該当セルがない場合にエラーになる。記事の実務版では、処理対象行を順番に確認して cell.Comment の有無を見る方式にし、広い On Error Resume Next を避けている。

正常値に戻っても警告が残る

追加だけを行うマクロでは古い警告が残る。自動生成マーカーを付け、基準を満たさなくなったときは、そのマーカーがあるメモだけを解除する。人が書いたメモは対象外にする。

結合セルや保護シートで止まる

結合セルでは範囲内の複数セルが同じ注記を共有するように見え、想定外の件数になることがある。保護シートでは追加・更新・削除が拒否される。まず結合を避けた小さな範囲で試し、保護状態も確認する。

違うブックが処理される

ActiveSheetActiveWorkbook は、実行時に選択されている画面で対象が変わる。この記事では対象を固定しやすい ThisWorkbook.Worksheets("Sheet1") を使う。PERSONAL.XLSBから実行したい場合は、対象ブックを変数へ明示的に設定する。

スレッド型コメントを編集できない

共同編集ファイルでは、作成者、サインイン中のプロフィール、編集権限によって操作できない場合がある。大量処理の前に、自分が作成した1件で追加・更新・返信・削除を確認する。

公開・配布前のレビュー表

自分だけが使う試作コードと、他の人へ渡すマクロでは確認範囲が違う。利用者が設定を読み違えても重要な注記を失わないか、次の項目を確認してから配布する。

確認項目 合格の目安
対象ブック コードを保存したファイルと処理対象が一致している
対象シート 存在するシート名を定数で指定している
対象範囲 列全体ではなく必要なデータ行だけに限定している
既存メモ 既定ではスキップし、無断で削除しない
自動生成メモ 専用の印で手入力メモと区別できる
正常化した値 自動生成した古い警告だけを解除できる
エラー値 処理を止めず、スキップ件数を確認できる
一覧シート 既存シートを削除せず、同名なら連番付きで新規作成する
削除操作 種類、範囲、件数、返信への影響を表示して確認する
復旧手段 変更前のファイルコピーがあり、元へ戻せる

レビューでは、コードを作った本人以外にもテストを依頼するとよい。作成者はシート名や列の前提を知っているため、説明不足に気付きにくい。初めて読む人が、変更箇所、対象範囲、既存メモの扱い、削除の影響を説明できれば、配布時の事故を減らせる。

マクロを更新したときは、以前のテスト結果だけで済ませず、空白、文字列、エラー値、手入力メモ、自動生成メモを含むテスト表をもう一度実行する。小さな変更でも、条件分岐や対象範囲に影響する可能性がある。

利用者向けの手順書には、実行ボタンの場所だけでなく、実行前に保存するファイル名、対象シート、対象期間、終了後に確認する件数も記載する。マクロが正常終了しても、対象期間を間違えていれば業務上は誤処理になるためだ。

また、警告メモが0件だった場合を「問題なし」と即断しない。対象列が正しいか、最終行が正しく取得できているか、数値が文字列として保存されていないかを確認する。0件も重要な結果だが、設定ミスでも同じ表示になる。

本番運用を始めた後は、初回だけでなく一定期間ごとにスキップ件数とエラー件数を確認する。急な増加は、入力形式の変更、別部署による手入力メモの増加、数式エラーの発生など、データ側の変化を示している可能性がある。

確認結果は日付と対象範囲を添えて残しておく。次回の実行結果と比較できれば、設定変更による差なのか、データそのものの変化なのかを判断しやすい。

よくある質問

Q1. AddCommentはメモとコメントのどちらを追加しますか?

現在のExcel画面上では「メモ」に相当する旧形式を追加する。返信可能なスレッド型コメントを追加する場合は AddCommentThreaded を使う。

Q2. 既存メモを残したまま本文だけ更新できますか?

できる。cell.Comment.Text Text:="新しい本文" で全文を置き換えられる。ただし他の担当者が書いた内容を上書きしないよう、対象範囲と更新条件を先に決める。

Q3. スレッド型コメントへVBAで返信できますか?

できる。対象セルの CommentThreaded を取得し、AddReply メソッドで返信を追加する。

Q4. メモとスレッド型コメントを同じ削除コードで消せますか?

同じコードにはしないほうが安全だ。メモは Comment.Delete または ClearNotes、スレッド型コメントは CommentThreaded.Delete を使う。後者は返信も削除する。

Q5. コメントを印刷できますか?

Microsoft 365では、スレッド型コメントとメモをシート末尾へ印刷できる。メモだけならシート上の表示どおりに印刷する設定もあるが、スレッド型コメントはシート上の表示どおりには印刷できない。印刷前にプレビューで確認する。

Q6. Application.UserNameを作成者の証明に使えますか?

本人確認の証拠としては使わない。設定で変更できる表示名だからだ。作業履歴を厳密に残す場合は、ファイルのアクセス権限、バージョン履歴、承認フローなど別の仕組みを併用する。

Q7. ボタンからマクロを実行できますか?

できる。シート上のボタンへマクロを登録すれば、利用者はVBEを開かずに実行できる。手順はマクロをボタン1つで実行する方法を参照。

用途別に選ぶ最終チェック

  • 定型の警告や注記を自動付与するなら、メモ用の AddComment を使う
  • 担当者同士で返信を残すなら、スレッド型の AddCommentThreadedAddReply を使う
  • 既存メモ・コメントは無条件で削除せず、スキップまたは明示的な更新にする
  • 自動生成したメモだけを管理したい場合は、識別用の接頭辞を付ける
  • 削除前には対象シート・範囲・件数を表示してYes/No確認を入れる
  • 一覧出力では既存シートを削除せず、同名なら連番付きの新規シートを作る

複数シートへ処理を広げる場合は、いきなり全シートを対象にせず、1枚で確認してから複数シートへ同じ処理を一括実行する方法と組み合わせる。コメントと色の両方で目立たせたい場合は、特定の文字を含むセルを検索してハイライトする方法も使える。

Microsoft公式情報

コメント

タイトルとURLをコピーしました