ListViewコントロールを使ってコメントを管理する例を紹介します。TreeViewコントロールと組み合わせて使うとさらに効果的ですが、ここではListViewコントロールを中心に作ってみましょう。TreeViewコントロールについては、「UserFormでツリービューを使う」をご覧ください。
こんなイメージです。
ListViewコントロールの初期化は、前に解説した通りです。列見出し(ColumnHeader)を追加するとき、同時に列幅も指定しています。
続いて、アクティブシートにあるすべてのコメントを取得します。なお、本項ではコメントに関する技術的な解説は割愛いたします。それは、また別のコンテンツで解説しましょう。
Private Sub UserForm_Initialize() Dim Memo With ListView1 ''プロパティ .View = lvwReport ''表示 .LabelEdit = lvwManual ''ラベルの編集 .HideSelection = False ''選択の自動解除 .AllowColumnReorder = True ''列幅の変更を許可 .FullRowSelect = True ''行全体を選択 .Gridlines = True ''グリッド線 ''列見出し .ColumnHeaders.Add , "_Address", "アドレス", 46 .ColumnHeaders.Add , "_View", "表示", 46 .ColumnHeaders.Add , "_Text", "テキスト", 126 ''コメントの取得 Call GetComments End With End Sub
アクティブシートのコメントを取得する処理は、ほかの機会にも利用しますので独立したプロシージャとしました。
Sub GetComments() ''すべてのコメントを取得する Dim Memo With ListView1 .ListItems.Clear For Each Memo In ActiveSheet.Comments With .ListItems.Add .Text = Memo.Parent.Address(0, 0) .SubItems(1) = Memo.Visible .SubItems(2) = Memo.Text End With Next Memo If .ListItems.Count > 0 Then .ListItems(1).Selected = True End With End Sub
チェックボックスを利用して、2つの処理を行います。
(1)シート上の全コメントについて、表示/非表示を切り替える
シートの全コメントを表示するには、ApplicationオブジェクトのDisplayCommentIndicatorプロパティで設定します。すべてのコメントを表示しているときは、DisplayCommentIndicatorプロパティに1が設定されていますので、UserFormの初期化処理でチェックボックスの状態に反映させます。この、DisplayCommentIndicatorプロパティは少々クセ(というかバグ)のあるプロパティです。まぁ、そのへんの話は、別のコンテンツで詳しくやりましょう(^^;
Private Sub UserForm_Initialize() Dim Memo With ListView1 ''プロパティ .View = lvwReport ''表示 .LabelEdit = lvwManual ''ラベルの編集 .HideSelection = False ''選択の自動解除 .AllowColumnReorder = True ''列幅の変更を許可 .FullRowSelect = True ''行全体を選択 .Gridlines = True ''グリッド線 ''列見出し .ColumnHeaders.Add , "_Address", "アドレス", 46 .ColumnHeaders.Add , "_View", "表示", 46 .ColumnHeaders.Add , "_Text", "テキスト", 126 ''コメントの取得 Call GetComments CheckBox1 = Application.DisplayCommentIndicator > 0 End With End Sub
チェックボックスがクリックされたら、DisplayCommentIndicatorプロパティの設定も変わるようにします。オフのときは「コメントマークのみ」表示するとします。このプロパティを変更すると、すべてのコメントのVisibleプロパティが変化しますので、ListViewコントロールのデータも更新してやります。
Private Sub CheckBox1_Click() ''[コメントを表示する] Dim SelectedRow As Long Application.DisplayCommentIndicator = (CheckBox1 + 1) * (-2) + 1 With ListView1 If .ListItems.Count = 0 Then Exit Sub SelectedRow = ListView1.SelectedItem.Index Call GetComments ListView1.ListItems(SelectedRow).Selected = True End With End Sub
(CheckBox1 + 1) * (-2) + 1は、ちょっと意地になりました(^^; すなおにIfステートメントやSelect Caseステートメントを使った方が簡単かもしれません。DisplayCommentIndicatorプロパティを変更すると、コメントのVisibleプロパティが変化しますので、GetCommentsをコールして、すべてのコメントを取得し直しています。ここでのポイントは、ListViewコントロールで選択されていた行を保持するということです。GetCommentsプロシージャではListItems.Clearを実行していますので、そのままだと毎回1行目が選択されてしまいます。ちょっと、UIとしてはお粗末です。そこで、現在選択されている行番号を変数(SelectedRow)に格納しておき、GetCommentsの後で選択し直してやります。注意すべきは、ListViewコントロールにデータが登録されていないケースです。1件もデータがないということは、選択されている行が存在しないということですから、上の考え方ではエラーになります。そこで、まずListViewコントロールに登録されているデータの個数を調べています。
(2)コメント1行目に自動入力される作成者の、表示/非表示を切り替える
コメント挿入すると、1行目に作成者名(ユーザー名)が自動的に入力されます。複数のユーザーで使う共有ブックなら役立つ機能ですが、ひとりで使っている場合は邪魔な気もします。今回のように、コメントのテキストをListViewコントロールで表示するときは、なおさらそう思います。そこで、チェックボックスで作成者名の表示/非表示を切り替えられるようにします。
作成者名を消すということは、要するに「コメントの2行目以降をテキストとする」ということです。しかし、もしかするとユーザーが、自ら作者名を削除しているかもしれません。そこで「1行目の行末が:かどうか」という判断も入れておきましょう。
Private Sub CheckBox2_Click() ''[作成者を表示しない] Dim i As Long, buf As String With ListView1 If .ListItems.Count = 0 Then Exit Sub If CheckBox2 Then For i = 1 To .ListItems.Count buf = Range(.ListItems(i)).Comment.Text If Right(Left(buf, InStr(buf, vbLf) - 1), 1) = ":" Then .ListItems(i).SubItems(2) = Mid(buf, InStr(buf, vbLf) + 1) End If Next i Else For i = 1 To .ListItems.Count .ListItems(i).SubItems(2) = Range(.ListItems(i)).Comment.Text Next i End If End With End Sub
2つのチェックボックスによる処理をプログラミングしましたが、実は両者は整合性がとれていません。[コメントを表示する]チェックボックスを切り替えると、相変わらず作者名ごとデータが登録されてしまいます。[コメントを表示する]チェックボックスのコードを変更すれば対応は簡単ですが、ここでは割愛します。ListViewコントロールの使い方という本筋から大きく離れるからです。あと、ちょっと解説が面倒くさいからです(^^; 興味のある方はチャレンジしてください。
ListViewコントロールでデータをダブルクリックしたら、そのコメントが挿入されているセルにアクティブセルを移動してみましょう。まぁ、これは簡単ですね。でも、実装していると便利な機能です。
Private Sub ListView1_DblClick() Range(ListView1.SelectedItem).Select End Sub
[Delete]キーを押したら、選択しているコメントを削除できるようにします。
Private Sub ListView1_KeyUp(KeyCode As Integer, ByVal Shift As Integer) With ListView1 If .ListItems.Count = 0 Then Exit Sub If KeyCode = 46 Then Range(.SelectedItem).ClearComments Call GetComments End If End With End Sub
コメントを削除するには、RangeオブジェクトのClearCommentsメソッドを実行します。この場合は、必ずコメントが挿入されているセルですから、削除の前にコメントの有無を判定する必要はありません。その代わり、ListViewコントロールにデータが登録されていないとエラーになりますので、そちらの判定を加えておきます。コメントを削除したら、シート上の全コメントを取得し直すのを忘れないでください。