「集計」機能を自分で作るサンプル。

前項の単純な合計では、このような考え方の重要性が解らないと思います。そこでもっと細かい分類集計のサンプルで考えてみましょう。



結構単純なパターン化した機能分割なので、理解を進めるには良いと思います。
サンプルは、「基本操作」「分類ごとに集計がしたい。」で使ったものを利用することにします。ここで説明しているように、Excelではこのような多段の分類集計はマクロを書くこともなくできてしまいます。繰り返し利用するなら、この操作をマクロの記録で取り込んでしまえます。
分類ごとに集計がしたいのサンプル
(この画像をクリックすると、このページのサンプルがダウンロードができます。)
ですが、ここでは大きな処理を作成していく段階での処理の組み立ての考え方の説明材料として利用することにします。
上がその元データです。このように「部門」「大分類」「小分類」と「総合計」が必要ですから、合計4階層の集計処理になります。「部門」「大分類」「小分類」順での並び替えは完了しています。
さあ、「集計機能も計算式も使わずにマクロを記述して処理して下さい。」というのが課題です。すぐに取り掛かれる人は、この章を読んでいただく必要がないかも知れません。

前頁の図を何階層も重ねたようになります。
「総合計」だけなら、前項で説明した「前処理」「主処理」「後処理」が1段あるだけの機能分割を考えれば良いわけですが、今回は4階層の合計が必要です。「分類ごとに集計がしたい。」で説明した集計機能では、総合計を除く3階層について、それぞれ集計処理を呼び出しましたが、ここでは1工程で4階層の合計を一気に作成してみます。
当然ながら、「大分類」の処理を「小分類」の処理の前に行なうわけはありません。下位層の合計を算出したら、それを上位の合計に加算すれば良いわけです。
これらの考え方を先ほどの図(モジュール構成図)に表わすと、
4階層の合計処理の構造図
このようになると思います。以前の説明した「制御」と「処理」の関係から、上にも下にも線が出ている処理は、上層から見れば「処理」ですが、下層から見れば「制御」なのです。
では、ここで各処理での中の機能を考えてみます。
(1)全体制御 ①「全体前処理」を行なう。
②「全体主処理」を全ての行が完了するまで繰り返して行なう。
③「全体後処理」を行なう。
(2)全体前処理 ①処理最大行数を取得する。
②総合計を初期化する。
③先頭の行カウンタをセットする。
(3)全体主処理 ①「部門前処理」を行なう。
②「部門主処理」を部門がブレークする(変わる)まで繰り返して行なう。
③「部門後処理」を行なう。
(4)全体後処理 ①総合計をセットする。
(5)部門前処理 ①部門合計を初期化する。
②現在の部門をブレーク判断用変数に取得する。
(6)部門主処理 ①「大分類前処理」を行なう。
②「大分類主処理」を大分類がブレークする(変わる)まで繰り返して行なう。
③「大分類後処理」を行なう。
(7)部門後処理 ①合計をセットする行を挿入する。
②部門合計をセットする。
③部門合計を総合計に加算する。
(8)大分類前処理 ①大分類合計を初期化する。
②現在の大分類をブレーク判断用変数に取得する。
(9)大分類主処理 ①「小分類前処理」を行なう。
②「小分類主処理」を小分類がブレークする(変わる)まで繰り返して行なう。
③「小分類後処理」を行なう。
(10)大分類後処理 ①合計をセットする行を挿入する。
②大分類合計をセットする。
③大分類合計を部門合計に加算する。
(11)小分類前処理 ①小分類合計を初期化する。
②現在の小分類をブレーク判断用変数に取得する。
(12)小分類主処理 ①明細行の金額を小分類合計に加算する。
②行カウンタを加算する。
(13)小分類後処理 ①合計をセットする行を挿入する。
②小分類合計をセットする。
③小分類合計を大分類合計に加算する。
これで、実際のマクロの記述が少し見えてきました。良く見ると上の図の各階層が似たようなことをやっていることが解ると思います。

では、また、この機能分割のままコードを起こしてみます。
さて、ではこの13の詳細処理を実際にマクロに記述してみます。
説明の都合上、処理構造の考え方にできるだけ沿ってコードを作成するので、いささか「タブー」とされているモジュールレベル変数を多用します。この説明はVBA初心者向けですから、引数とかByRefとかに触れないで説明していきたいのでこのような方法を採ります。プロシージャは上の説明の通り13個作成します。
まず、「(1)全体制御」「(2)全体前処理」「(3)全体主処理」「(4)全体後処理」です。

'***************************************************************************************************
'   多分類合計を算出するサンプル①                                  Module1(Module)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/06/14(1.00)新規作成
'16/11/19(1.10)*.xlsm化の変更
'20/02/17(1.20)コード整理、標準化準拠作業
'***************************************************************************************************
Option Explicit
'===================================================================================================
Private g_lngRow As Long                                    ' 現在行
Private g_lngRow1 As Long                                   ' 部門先頭行
Private g_lngRow2 As Long                                   ' 大分類先頭行
Private g_lngRow3 As Long                                   ' 小分類先頭行
Private g_lngRowMax As Long                                 ' 最終行
Private g_lngGokei0 As Long                                 ' 総合計
Private g_lngGokei1 As Long                                 ' 部門合計
Private g_lngGokei2 As Long                                 ' 大分類合計
Private g_lngGokei3 As Long                                 ' 小分類合計

'***************************************************************************************************
'   ■■■ 起動処理 ■■■
'***************************************************************************************************
'* 処理名 :全体制御
'* 機能  :(1)全体制御
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Sub 全体制御()
    '-----------------------------------------------------------------------------------------------
    ' (2)全体前処理
    Call 全体前処理
    ' 全部の行を繰り返す
    Do While g_lngRow <= g_lngRowMax
        ' (3)全体主処理
        Call 全体主処理
    Loop
    ' (4)全体後処理
    Call 全体後処理
End Sub

'***************************************************************************************************
'   ■■■ サブ処理(Private) ■■■
'***************************************************************************************************
'* 処理名 :全体前処理
'* 機能  :(2)全体前処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 全体前処理()
    '-----------------------------------------------------------------------------------------------
    g_lngRowMax = Range("$A$" & Rows.Count).End(xlUp).Row           ' 最大行数の取得(A列)
    g_lngGokei0 = 0                                                 ' 総合計クリア
    g_lngRow = 2                                                    ' 先頭行のセット
End Sub

'***************************************************************************************************
'* 処理名 :全体主処理
'* 機能  :(3)全体主処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 全体主処理()
    '-----------------------------------------------------------------------------------------------
    ' (5)部門前処理
    Call 部門前処理
    ' 部門ブレークまで繰り返す
    Do While Cells(g_lngRow, 1).Value = Cells(g_lngRow1, 1).Value
        ' (6)部門主処理
        Call 部門主処理
    Loop
    ' (7)部門後処理
    Call 部門後処理
End Sub

'***************************************************************************************************
'* 処理名 :全体後処理
'* 機能  :(4)全体後処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 全体後処理()
    '-----------------------------------------------------------------------------------------------
    Cells(g_lngRow, 1).Value = "■総合計"
    Cells(g_lngRow, 4).Value = g_lngGokei0                          ' 合計を表示
End Sub

(5)部門前処理」「(6)部門主処理」「(7)部門後処理」です。

'***************************************************************************************************
'* 処理名 :部門前処理
'* 機能  :(5)部門前処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 部門前処理()
    '-----------------------------------------------------------------------------------------------
    g_lngGokei1 = 0                                                 ' 部門計クリア
    g_lngRow1 = g_lngRow                                            ' 先頭行のセット
End Sub

'***************************************************************************************************
'* 処理名 :部門主処理
'* 機能  :(6)部門主処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 部門主処理()
    '-----------------------------------------------------------------------------------------------
    ' (8)大分類前処理
    Call 大分類前処理
    ' 部門、大分類ブレークまで繰り返す
    Do While ((Cells(g_lngRow, 1).Value = Cells(g_lngRow2, 1).Value) And _
              (Cells(g_lngRow, 2).Value = Cells(g_lngRow2, 2).Value))
        ' (9)大分類主処理
        Call 大分類主処理
    Loop
    ' (10)大分類後処理
    Call 大分類後処理
End Sub

'***************************************************************************************************
'* 処理名 :部門後処理
'* 機能  :(7)部門後処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 部門後処理()
    '-----------------------------------------------------------------------------------------------
    Rows(g_lngRow).Insert                                           ' 合計行を挿入
    Cells(g_lngRow, 1).Value = "■部門計"
    Cells(g_lngRow, 4).Value = g_lngGokei1                          ' 合計を表示
    g_lngGokei0 = g_lngGokei0 + g_lngGokei1                         ' 総合計に加算
    g_lngRowMax = g_lngRowMax + 1                                   ' 挿入行対応
    g_lngRow = g_lngRow + 1                                         ' 挿入行対応
End Sub
※大分類のブレークを判断する場合、部門も合わせて比較するようにして下さい。さもないと、データ量が少ない場合に部門1分類1の次に部門2分類1が発生するようなケースでブレークせずに先に進んでしまいます。(小分類も同様です。)

(8)大分類前処理」「(9)大分類主処理」「(10)大分類後処理」「(11)小分類前処理」「(12)小分類主処理」「(13)小分類後処理」です。

'***************************************************************************************************
'* 処理名 :大分類前処理
'* 機能  :(8)大分類前処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 大分類前処理()
    '-----------------------------------------------------------------------------------------------
    g_lngGokei2 = 0                                                 ' 大分類計クリア
    g_lngRow2 = g_lngRow                                            ' 先頭行のセット
End Sub

'***************************************************************************************************
'* 処理名 :大分類主処理
'* 機能  :(9)大分類主処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 大分類主処理()
    '-----------------------------------------------------------------------------------------------
    ' (11)小分類前処理
    Call 小分類前処理
    ' 部門、大分類、小分類ブレークまで繰り返す
    Do While ((Cells(g_lngRow, 1).Value = Cells(g_lngRow3, 1).Value) And _
              (Cells(g_lngRow, 2).Value = Cells(g_lngRow3, 2).Value) And _
              (Cells(g_lngRow, 3).Value = Cells(g_lngRow3, 3).Value))
        ' (12)小分類主処理
        Call 小分類主処理
    Loop
    ' (13)小分類後処理
    Call 小分類後処理
End Sub

'***************************************************************************************************
'* 処理名 :大分類後処理
'* 機能  :(10)大分類後処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 大分類後処理()
    '-----------------------------------------------------------------------------------------------
    Rows(g_lngRow).Insert                                           ' 合計行を挿入
    Cells(g_lngRow, 2).Value = "■大分類計"
    Cells(g_lngRow, 4).Value = g_lngGokei2                          ' 合計を表示
    g_lngGokei1 = g_lngGokei1 + g_lngGokei2                         ' 部門合計に加算
    g_lngRowMax = g_lngRowMax + 1                                   ' 挿入行対応
    g_lngRow = g_lngRow + 1                                         ' 挿入行対応
End Sub

'***************************************************************************************************
'* 処理名 :小分類前処理
'* 機能  :(11)小分類前処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 小分類前処理()
    '-----------------------------------------------------------------------------------------------
    g_lngGokei3 = 0                                                 ' 小分類計クリア
    g_lngRow3 = g_lngRow                                            ' 先頭行のセット
End Sub

'***************************************************************************************************
'* 処理名 :小分類主処理
'* 機能  :(12)小分類主処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 小分類主処理()
    '-----------------------------------------------------------------------------------------------
    g_lngGokei3 = g_lngGokei3 + Cells(g_lngRow, 4).Value            ' 明細金額を小分類に加算
    g_lngRow = g_lngRow + 1                                         ' 行インデックスを加算
End Sub

'***************************************************************************************************
'* 処理名 :小分類後処理
'* 機能  :(13)小分類後処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:
'* 注意事項:
'***************************************************************************************************
Private Sub 小分類後処理()
    '-----------------------------------------------------------------------------------------------
    Rows(g_lngRow).Insert                                           ' 合計行を挿入
    Cells(g_lngRow, 3).Value = "■小分類計"
    Cells(g_lngRow, 4).Value = g_lngGokei3                          ' 合計を表示
    g_lngGokei2 = g_lngGokei2 + g_lngGokei3                         ' 大分類合計に加算
    g_lngRowMax = g_lngRowMax + 1                                   ' 挿入行対応
    g_lngRow = g_lngRow + 1                                         ' 挿入行対応
End Sub

'------------------------------------------<< End of Source >>--------------------------------------
上の図からそのままコードを作成すると、このようになります。ここから割合単純な繰り返しであることが解ります。

ほんの数行のプロシージャ単位に細かく分割するのは、実際には効率は良くありません。
上のコードは、仕様の図式化から正直にコードにしているため、実際のところ細かいプロシージャの行き来が多くなり、決して良いものではありません。 ですが、今回の説明を正直にコード化したもので、ダウンロードさせて動作を確認してもらえば、正しく動作することが解ると思います。
私は、このようなケースでは、考え方だけはこの方法に準じますが、コード化の段階では参照する変数と切り出して共用化できる部分があまりないことを考慮して、以下のようなコードにしてしまっています。 ただ、先にお断わりしておきますが、ここでは下記のコードを理解することは必要ありません。実際に時間計測していただければ判りますが、それほど大きな違いはありません。まずは上のような考え方を理解して下さい。

'***************************************************************************************************
'   多分類合計を算出するサンプル②                                  Module2(Module)
'
'   作成者:井上治  URL:https://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'***************************************************************************************************
'変更日付 Rev  変更履歴内容------------------------------------------------------------------------>
'03/06/14(1.00)新規作成
'16/11/19(1.10)*.xlsm化の変更
'20/02/17(1.20)コード整理、標準化準拠作業
'***************************************************************************************************
Option Explicit

'***************************************************************************************************
'   ■■■ 起動処理 ■■■
'***************************************************************************************************
'* 処理名 :集計処理
'* 機能  :集計処理
'---------------------------------------------------------------------------------------------------
'* 返り値 :(なし)
'* 引数  :(なし)
'---------------------------------------------------------------------------------------------------
'* 作成日 :2003年06月14日
'* 作成者 :井上 治
'* 更新日 :2020年02月17日
'* 更新者 :井上 治
'* 機能説明:「(1)全体制御」レベル以下全体を単一プロシージャで記述したもの
'* 注意事項:
'***************************************************************************************************
Sub 集計処理()
    '-----------------------------------------------------------------------------------------------
    Dim lngRow As Long                                              ' 現在行
    Dim lngRow1 As Long                                             ' 部門先頭行
    Dim lngRow2 As Long                                             ' 大分類先頭行
    Dim lngRow3 As Long                                             ' 小分類先頭行
    Dim lngRowMax As Long                                           ' 最終行
    Dim lngGokei0 As Long                                           ' 総合計
    Dim lngGokei1 As Long                                           ' 部門合計
    Dim lngGokei2 As Long                                           ' 大分類合計
    Dim lngGokei3 As Long                                           ' 小分類合計
    '-------------------------------------------------------------------------------
    ' (2)全体前処理
    lngRowMax = Range("$A$65536").End(xlUp).Row                     ' 最大行数の取得
    lngGokei0 = 0                                                   ' 総合計クリア
    lngRow = 2                                                      ' 先頭行のセット
    '-------------------------------------------------------------------------------
    ' (3)全体主処理
    Do While lngRow <= lngRowMax
        '---------------------------------------------------------------------------
        ' (5)部門前処理
        lngGokei1 = 0                                               ' 部門計クリア
        lngRow1 = lngRow                                            ' 先頭行のセット
        '---------------------------------------------------------------------------
        ' (6)部門主処理
        Do While Cells(lngRow, 1).Value = Cells(lngRow1, 1).Value
            '-----------------------------------------------------------------------
            ' (8)大分類前処理
            lngGokei2 = 0                                           ' 大分類計クリア
            lngRow2 = lngRow                                        ' 先頭行のセット
            '-----------------------------------------------------------------------
            ' (9)大分類主処理
            Do While ((Cells(lngRow, 1).Value = Cells(lngRow2, 1).Value) And _
                      (Cells(lngRow, 2).Value = Cells(lngRow2, 2).Value))
                '-------------------------------------------------------------------
                ' (11)小分類前処理
                lngGokei3 = 0                                       ' 小分類計クリア
                lngRow3 = lngRow                                    ' 先頭行のセット
                '-------------------------------------------------------------------
                ' (12)小分類主処理
                Do While ((Cells(lngRow, 1).Value = Cells(lngRow3, 1).Value) And _
                          (Cells(lngRow, 2).Value = Cells(lngRow3, 2).Value) And _
                          (Cells(lngRow, 3).Value = Cells(lngRow3, 3).Value))
                    ' 明細金額を小分類に加算
                    lngGokei3 = lngGokei3 + Cells(lngRow, 4).Value
                    lngRow = lngRow + 1                             ' 行カウンタを加算
                Loop
                '-------------------------------------------------------------------
                ' (13)小分類後処理
                Rows(lngRow).Insert                                 ' 合計行を挿入
                Cells(lngRow, 3).Value = "■小分類計"
                Cells(lngRow, 4).Value = lngGokei3                  ' 合計を表示
                lngGokei2 = lngGokei2 + lngGokei3                   ' 大分類合計に加算
                lngRowMax = lngRowMax + 1                           ' 挿入行対応
                lngRow = lngRow + 1                                 ' 挿入行対応
            Loop
            '-----------------------------------------------------------------------
            ' (10)大分類後処理
            Rows(lngRow).Insert                                     ' 合計行を挿入
            Cells(lngRow, 2).Value = "■大分類計"
            Cells(lngRow, 4).Value = lngGokei2                      ' 合計を表示
            lngGokei1 = lngGokei1 + lngGokei2                       ' 部門合計に加算
            lngRowMax = lngRowMax + 1                               ' 挿入行対応
            lngRow = lngRow + 1                                     ' 挿入行対応
        Loop
        '---------------------------------------------------------------------------
        ' (7)部門後処理
        Rows(lngRow).Insert                                         ' 合計行を挿入
        Cells(lngRow, 1).Value = "■部門計"
        Cells(lngRow, 4).Value = lngGokei1                          ' 合計を表示
        lngGokei0 = lngGokei0 + lngGokei1                           ' 総合計に加算
        lngRowMax = lngRowMax + 1                                   ' 挿入行対応
        lngRow = lngRow + 1                                         ' 挿入行対応
    Loop
    '-------------------------------------------------------------------------------
    ' (4)全体後処理
    Cells(lngRow, 1).Value = "■総合計"
    Cells(lngRow, 4).Value = lngGokei0                              ' 合計を表示
End Sub

'------------------------------------------<< End of Source >>--------------------------------------
ループが4重にもネストするようなプロシージャは良くないと言われる人もあるのですが、処理構造がきちんと解っていての処理であって、記述もコメントを使って解りやすく切り分けて考え方を明確にします。
多重ループを一気に1プロシージャに書いてしまっていますが、このような場合は、処理レベルをインデント(字下げ)で明確にし、各機能区分の名称をコメントに盛り込み、線などを入れると見やすいコードになります。

では、「まとめ」です。
実は、このような機能分割の図は「モジュール構成図」と呼ばれています。「構造化プログラム」での考え方を図に表わす方法のひとつなのです。私自身は「構造化プログラム」の全容を正しく理解しているとは思っていませんが、実践の上で利用している認識はあります。
この「構造化プログラム」の考え方は、以下のような利点があります。
  • 仕様要件を図式化して解りやすくなります。機能の考え方が統一できてくると、誤りが少なくなり、検証に掛かる時間が軽減できます。
  • コードの作成時は、「箱」の単位で記述することで何が終わって、何が未完成なのかが明確になります。
  • コードのテスト時は、最下層の編集記述がある程度未完成であっても、上層のループ状態のテストを進めることが可能です。
  • 仕様変更に対しての柔軟性が向上します。例えば、上のサンプルに「中分類合計」を追加しようとすると、図から考えて1階層増やすのに何を行なう必要があるのかの判別が明確になります。
  • 毎回、この図式化作業を行なうと、それほどバリエーションがない数種のパターンで構成できることに気がつくと思います。慣れてくれば、この図式化をいちいち「紙」に起こさなくても頭の中で作業できるようになると思います。
  • プログラム構造が理解できてくると転用性も向上し、転用利用することで開発効率全体の向上が望めます。この要素は最も重要だと思うのです。
どうでしょう。解りましたか? ベテランの人が「ちょちょい」とマクロを作ってしまうのは、このような設計手法が頭に入っているからです。でも、きちんと紙に書いて、「部品化」とその部品の組み付けを考えれば、ある程度の仕組みをエンドユーザーが作ってしまうことは充分可能だと思います。
11つの「部品」をできるだけ単純な機能に分割して追い込んでしまうことで、それぞれの「部品」の中の記述での間違いが防げます。動作テストでも、不具合が見つかれば、それがどこの記述によるものかがすぐに判るはずです。