may the VBA be with you

Excel VBAとか業務自動化とか

はてな記法 テーブル作成マクロの改良 おまけ

はじめに

前回、

vba-belle-equipe.hatenablog.com

Sub makeTblTxt()
  Dim maxRow As Long, maxCol As Long
  Dim i As Long, j As Long
  Dim str As String
  '最終行取得
  maxRow = Cells(Rows.Count, 1).End(xlUp).Row
  '最終列取得
  maxCol = Cells(1, Columns.Count).End(xlToLeft).Column
  For i = 1 To maxRow
    str = ""[f:id:vba-belle-equipe:20160304093937p:plain]
    For j = 1 To maxCol
      If i = 1 Then
        str = str + "|*" & Cells(i, j)
      Else
        str = str + "|" & Cells(i, j)
      End If
    Next
    Debug.Print str & "|"
  Next
End Sub


Excelの表の大きさに応じたテキスト生成が自動的にできるようになりました。

今回は、考え方③として挙げながら華麗にスルーした、もう1つの方法について考えてみます。

自動取得の弱点?

上のマクロには少し欠点があり、最終行を「A列」、最終列を「1行目」から取得しているため、それらが他よりも小さかったりするとうまくいきません。

つまり、

f:id:vba-belle-equipe:20160304091839p:plain

このような場合です。

|*人物名|*役職|
|千石 武|ギャルソン|
|原田 禄郎|パトロン|
|磯野 しずか|シェフ・ド・キュイジーヌ|
|三条 政子|バルマン|
|水原 範朝|ディレクトール|
|梶原 民生|メートル・ド・テル|
|稲毛 成志|シェフ・パティシエ|
|大庭 金四郎|ソムリエ|
|和田 一|コミ|
|畠山 秀忠|スー・シェフ|
|佐々木 教綱|プロンジュール|

なんか、少ないです。

マクロ作成者としては、「表のほうがおかしいだろ」と言いたくもなりますが、まあ世の中そんなもんですよね。

③ユーザーに指定させる

自動ではカバーできないくらい例外が多かったりする場合に有効です。
「maxRow」と「maxCol」をユーザーに指定させます。

ちなみに、ここでいうユーザーとは自分(マクロ作成者)を想定しています。

インプットボックスを使う

インプットボックスというものがあります。

Sub makeTblTxt()
  Dim maxRow As Long, maxCol As Long
  Dim i As Long, j As Long
  Dim str As String
  '最終行取得
  maxRow = InputBox("行数は?")
  '最終列取得
  maxCol = InputBox("列数は?")
  For i = 1 To maxRow
    str = ""
    For j = 1 To maxCol
      If i = 1 Then
        str = str + "|*" & Cells(i, j)
      Else
        str = str + "|" & Cells(i, j)
      End If
    Next
    Debug.Print str & "|"
  Next
End Sub

実行すると、

f:id:vba-belle-equipe:20160304094507p:plain

訊いてくれます。*1


まあ、いけますが、いちいち入力するのはめんどくさいですね。

範囲を選択させる

f:id:vba-belle-equipe:20160304093937p:plain

このように選択した上で

Sub makeTblTxt()
  Dim maxRow As Long, maxCol As Long
  Dim i As Long, j As Long
  Dim str As String
  '最終行取得
  maxRow = Selection.Rows.Count
  '最終列取得
  maxCol = Selection.Columns.Count
  For i = 1 To maxRow
    str = ""
    For j = 1 To maxCol
      If i = 1 Then
        str = str + "|*" & Cells(i, j)
      Else
        str = str + "|" & Cells(i, j)
      End If
    Next
    Debug.Print str & "|"
  Next
End Sub

を実行すると、できます。

まあ、なんというか、そりゃあできるよねという感じです。

まとめ

大事な事なので2回言いますが、ここでいうユーザーとは自分(マクロ作成者)を想定しています。

自分以外が使うのであれば

「キャンセルしたのにエラーになるんだけど」
「範囲選択ってどうやってやるの」
「めんどくさい」

とかいう質問や苦情に備える必要があります。
(というかそもそも、マクロを実行させる仕組みを作る必要があります)


実際にマクロを作る時は

  • 誰が、どのように使うか
  • どの程度時間をかけてよいか

を考えて作りましょう。


ユーザーに指定してもらったほうが柔軟だし確実かな?

というと必ずしもそうでもないのですが、オプションとして持っておくことは大事です。

おまけのおまけ

大変お世話になっている

No.8 ワークシートの最終行、最終列を取得する

に再びご登場いただき、最終手段を使ってみました

Sub makeTblTxt()
  Dim maxRow As Long, maxCol As Long
  Dim i As Long, j As Long
  Dim str As String
  With ActiveSheet.UsedRange
    '最終行取得
    maxRow = .Find("*", , xlFormulas, , xlByRows, xlPrevious).Row
    '最終列取得
    maxCol = .Find("*", , xlFormulas, , xlByColumns, xlPrevious).Column
  End With
  For i = 1 To maxRow
    str = ""
    For j = 1 To maxCol
      If i = 1 Then
        str = str + "|*" & Cells(i, j)
      Else
        str = str + "|" & Cells(i, j)
      End If
    Next
    Debug.Print str & "|"
  Next
End Sub
|*人物名|*役職|*|
|千石 武|ギャルソン|松本 幸四郎|
|原田 禄郎|パトロン|筒井 道隆|
|磯野 しずか|シェフ・ド・キュイジーヌ|山口 智子|
|三条 政子|バルマン|鈴木 京香|
|水原 範朝|ディレクトール|西村 雅彦|
|梶原 民生|メートル・ド・テル|小野 武彦|
|稲毛 成志|シェフ・パティシエ|梶原 善|
|大庭 金四郎|ソムリエ|白井 晃|
|和田 一|コミ|伊藤 俊人|
|畠山 秀忠|スー・シェフ|田口 浩正|
|佐々木 教綱|プロンジュール|杉本 隆吾|
||ガルド・マンジェ|ジャッケー・ローロン|


バッチリです。

*1:画面はExcel2002のものです