セル内の長文を編集する

 ExcelVBAでメールを自動作成するようなマクロを作る場合、当然本文の文字列もワークシート上で管理することになると思う。
 ただ、文章が長くなると、シート上では読み書きしづらい、ということが起こる。
 私の場合、本文用の列を10列ぐらい用意して、1段落~10段落みたいにして1セルあたりの字数を減らす、ということもやってみたが、一つの文章を10列に分けて書くというのもずいぶん不細工な話だ。
  かといって、一つのセルに長い文章を入れると、どうしても行高を大きくする必要が生じるし、行高が大きいと、マウスホイールでスクロールさせるときにどうしてもたどり着けない(笑)行があったりしていらいらする。

 んで、考えたのが今回紹介するやり方。

 「メール用文例」というワークシートのC列にメール本文の文字列を保存する、ということにする。

f:id:akashi_keirin:20170218142723j:plain

 こんな感じ。

f:id:akashi_keirin:20170218142719j:plain

 こんなユーザーフォームを作る。

 オブジェクト名はそれぞれ、

  • UserForm2……ユーザーフォーム本体
  • txtMailBody……テキストボックス
  • btnCancel……「キャンセル」ボタン
  • btnEnter……「編集終了」ボタン

としておく。

 フォームモジュールに書くコードは次の通り。

Option Explicit

Private Sub btnCancel_Click()           '……(1)
  Unload Me
End Sub

Private Sub btnEnter_Click()            '……(2)
  With Me.txtMailBody
    ActiveCell.Value = .Text            '……(3)
    Unload Me
  End With
End Sub

Private Sub UserForm_Initialize()       '……(4)
  With Me                               '……(5)
    .Height = 400
    .Width = 400
  End With
  With Me.txtMailBody                   '……(6)
    .Height = 320
    .Width = 380
    .Top = 30
    .Left = 8
    .MultiLine = True                   '……(7)
    .EnterKeyBehavior = True            '……(8)
    .ScrollBars = fmScrollBarsVertical
    .Text = ActiveCell.Value            '……(9)
  End With
End Sub

 (1)は、「キャンセル」ボタンが押されたときの処理。ユーザーフォームを閉じているだけ。
 (2)は、「編集終了」ボタンが押されたときの処理。(3)で、txtMailBodyコントロールのTextプロパティの値(要するにテキストボックスの内容)をアクティブセルに書き込んでいる。
 (4)は、ユーザーフォームが呼び出されたときの処理。(5)では、HeightプロパティとWidthプロパティとでユーザーフォームのサイズを設定している。
 (6)は、テキストボックスの初期設定。Height、Widthプロパティでテキストボックスの大きさを決め、Top、Leftプロパティでフォーム内の一を決めている。
 (7)のMultilineプロパティは、Trueにすると複数行の文字列を書くことができる。
 (8)のEnterKeyBehaviorは、読んで字の如く「Enterキーのふるまい」。Trueにすると、テキストボックス内で[Enter]キーを押すと改行することができる。
 (9)は、テキストボックスにアクティブセルの値を書き込んでおく処理。こうしておくことで、前回入力したテキストを修正する、といった使い方ができる。逆にこうしておかないと、毎回イチから入力するというマヌケなことになる。

 んで、このユーザーフォームの呼び出し方だが、私は、対象のセルをダブルクリックしたらユーザーフォームを表示するようにしている。
 ちょうど、通常セル内の値を編集するときと同じやり方にしているというわけ。

 従って、「メール用文例」ワークシートのモジュールに書きのコードを書く。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  With Target
    If .Row = 1 _
       Or .Row > Worksheets("メール用文例").Cells(Rows.Count, 3).End(xlUp).Row _
       Or .Column <> 3 Then   '……(10)
      Cancel = False          '……(11)
    Else
      Cancel = True           '……(12)
      UserForm2.Show          '……(13)
    End If
  End With
End Sub

 (10)は条件指定。Targetってのは、このプロシージャが呼ばれるとき(シート上でダブルクリックというイベントが起こったとき)にこのプロシージャに渡される引数で、ダブルクリックされたセルが入っていると思えば良い。
 今回のマクロでは、C列(3列目)にメール用の本文を入力しておくという体なので、「ダブルクリックされた場所が3列目の最終行よりも下だったり、3列目以外だったりしたら」という条件を指定している。
 要するに、メール本文データを入れる場所以外をダブルクリックしたときは、(11)の処理をする、ということ。
 (11)は、CancelをFalseにしている。つまり、「ダブルクリック」というユーザーの行為をキャンセルしない、ということ。従って、(10)の条件に当てはまっている場所でダブルクリックをすると、「セルが編集モードに変わる」というごくフツーのことが起こるということ。
 で、(10)の条件に当てはまっていない場所、つまり、メール本文データが入っているセルでダブルクリックすると、Elseのところに処理が移る。
 (12)でCancelをTrueにする。すなわち、セルを編集モードにしないわけだ。
 (13)でユーザーフォームを呼び出す。

f:id:akashi_keirin:20170218152014j:plain

 対象のセルをダブルクリックすると、

f:id:akashi_keirin:20170218152042j:plain

ユーザーフォームが表示される。テキストボックス内には、セル内の文字列が入っている。

f:id:akashi_keirin:20170218142735j:plain

 テキストボックス内の文字をこんなふうに編集して、「編集終了」ボタンをクリックすると、

f:id:akashi_keirin:20170218142740j:plain

 ほれ、この通り、セルの中身が置き換えられている。

 まあ、本来セルの中に長文を入れるなんていうのは邪道なんだろうけど、VBAExcelからメールを自動作成できるようにしておくと便利なんですよねー。特に、私の場合、「たくさんの相手に一人づつ添付ファイルの異なるメールを送る」なんていう「なんてすてきな拷問!!」みたいな業務があるので……。

 今のところ、LotusNotesのメールとThunderbirdのメール自動作成マクロを作っているので、追々公開していこうかな、と。