和風スパゲティのレシピ

日本語でコーディングするExcelVBA

関数(プロシージャ)分割は思ってるより簡単です

このブログの記事数が100を突破しました。


1年での達成を目指していましたが、14ヶ月での到達となりました。

ここ1ヶ月では20本書けていて、執筆スピードが上がった実感がありますので、
このままじゃんじゃん書いて目標数に追いついていこうと思います。


月並みですが、ブログを書いていると自分自身とても勉強になります。

今まで無意識にやっていたことを言語化しなけれないけないので、
自分を見つめ直すいいきっかけになります。


Microsoftの公式ドキュメントなんて、実務でマクロを書いている間は全く見もしませんでしたが、ブログを書き始めてからは、必ず目を通すようになりましたからね。


私のお勉強にお付き合いいただいている皆様に、あらためてお礼申し上げます。
いつもご愛読ありがとうございます(´∀`)



さて最近書いた記事10本ほどは、ExcelVBAの主役である「ワークシート」を題材にしました。

特にワークシートを指定する方法7選は、Worksheetオブジェクトの基本となる記事なので、是非目を通していただければと思います。


これでExcelVBAの主役である

の3記事をひとまずは公開できました。


これらの記事は「初級者~中級者」を想定して書いておりますが、
これを書くにあたって、ちょっと挑戦してみたことがあります。


それは、

Function Get最終行(ws As Worksheet, C As Long) As Long
    Get最終行 = ws.Cells(ws.Rows.Count, C).End(xlUp).Row
End Function

For R = 2 To Worksheets("売上データ").Cells(Rows.Count, 1).End(xlUp).Row
' ↓
For R = 2 To Get最終行(Worksheets("売上データ"), 1)

このように、それぞれの関数化にも触れてみた事です。

おそらく同じレベルの方を想定した他のサイトの記事と比べると、
相当早い段階でプロシージャ分割を紹介している気がします。


これがいいことなのかは分かりませんし、
皆さんの声を聞いた上で「やっぱりやーめた」となるかもしれませんが、
この段階でプロシージャを取り上げたのは、もちろん理由があります。


それは、「母国語を使って学べるなら、関数って実は簡単」と思っているからです。


関数分割が難しいという方は、
「なにを関数にすればいいのかわからない」
が最大の悩みであるように感じます。

構文自体は単純ですからね。


そこでいざFunctionプロシージャを学ぼうと思っても、解説ページに出てくるのは

Function func1

とか

Function Sample

とかが多くて、
「これじゃあなんで関数を使うのかわからないのもしょうがないよな」
と思ってしまうのですが、関数化の本当のメリットは、わりかし有名な「部品化」とか、「重複したコードをまとめる」ではないと思うんですよね。


関数分割の本質は「処理のまとまりに名前をつけられること」だと思うんですよ。


ぶっちゃけ関数って、

Function ○○

の○○の部分が最も重要で、あとはおまけみたいなもんだと思っています。


例えば上に挙げた「最終行の取得」を見ていただくと、

Function Get最終行(ws As Worksheet, C As Long) As Long
    Get最終行 = ws.Cells(ws.Rows.Count, C).End(xlUp).Row
End Function
' ↓
For R = 2 To Get最終行(Worksheets("売上データ"), 1)

これは「EndプロパティにGet最終行という名前をつけていること」こそが、
関数が果たした最も重要な役割だと思うわけです。



これだけ重要(と私が勝手に思っている)にもかかわらず、
このメリットが全然語られていない原因を推測します。


関数の分け方を勉強中の初学者にとっては、
英語の名前を付けられることはメリットでも何でもない
からなんじゃないでしょうかね?

翻訳して対応を考える必要のある識別子を1個追加するのは、
初学者にとってはメリットどころかデメリットですから。


その命名の負担を軽減するためには、func1という名前を使わざるを得なくなり、
結果「関数にする目的」が迷宮入りしてしまってるんですよ。


上のコードを再掲しますが、

Function Get最終行(ws As Worksheet, C As Long) As Long
    Get最終行 = ws.Cells(ws.Rows.Count, C).End(xlUp).Row
End Function
' ↓
For R = 2 To Get最終行(Worksheets("売上データ"), 1)

これって、「なんで関数分割するのか」を説明する必要はないですよね?
見ればその便利さはわかる気がします。


そんでもって、なんで便利かをなんとなくつかんだうえでコードを見る、
すなわち「目的が分かった状態でコードを読む」ことができれば、

「引数はどう書くか」「返り値はどう書くか」なんて、
解説しなくても推測できるんじゃないかな?と。


例えばこのデータシートから、
分割元データ
みかんだけのデータにしたシートを新しく出力する」マクロを↓のように書きます。
 

Dim ws出力シート As Worksheet
Set ws出力シート = シートを新規ブックへコピーする(Worksheets("購入歴データ"))

Call 他ブックを参照している数式をすべて値に固定する(ws出力シート)

Call フィルターをクリアする(ws出力シート)
Call フィルターで抽出する("みかん", ws出力シート,"F")
If Countフィルター抽出件数(ws出力シート) > 0 Then
    Call フィルター抽出されていないデータを削除する(ws出力シート)
End If

いままでVBAを教えてきた経験で言うと、Functionを今から勉強しようと思っている人には、引数とか返り値とか一切説明せず、いきなりこれを見せた方が理解が早い印象を受けます。

先に目的を教えて、書き方は、まあ見ればわかるよ的な。


現に関数になれている方は、この関数の中身って、
別に書かなくてもなんとなくわかりますよね?


もう一つ例を挙げます。

せっかく「関数化って簡単!」って記事なので、
関数化の重要なポイント「条件式の関数化」と「例外処理の排出」を、
ためしに勉強してみましょう。

Sub 帳票をデータに取り込む(ws帳票シート As Worksheet)

    If Is必須項目が正しく入力されているか確認する(ws帳票シート) = False Then
        Call 入力不備でスキップした帳票をログに記録する(ws帳票シート)
        Exit Sub
    End If

    ~~ここからメインコード開始

End Sub

以上です。

もうなんとなくわかりましたよね?
こんな風に使うと関数って便利なんですよ。




新しい機能やオブジェクトを勉強するのは「単語や熟語の勉強」みたいなものです。

意味と使い方を知って、引数の渡し方などを覚えます。


対して、関数分割やクラスの設計は「文章問題」みたいなものじゃないでしょうか?

文と文のつながりを読み解いたり、
あれとは何を指すか?10字以内で答えよ」を解くみたいな。


その視点で見ると「英単語の勉強 ⇒ 英文の読解」は一気に難易度が上がるんですよ。

英語のテストでも、とりあえず単語の問題から解いて点数稼いでましたよね?


でも母国語ではこれが逆転するんです。

「単語がよくわからんから、文章から推測する」スキルのレベルが、
外国語の比ではありませんから。


「語彙力には自信はないけど、会話する分には困らない」
なんて、母国語でなければ成し得ないスキルですからね。
(日本の英語教育の問題に起因しているのかもしれませんが…)


この差が、上のみかん搾りコードで顕著に出ています。

あのコードを英訳したら、翻訳するだけで労力になり、関数の勉強の邪魔になります。
「書き方は、まあ見ればわかるよ」なんて、夢のまた夢でしょう。



と、話が長くなりましたが、母国語で学ぶプロシージャ分割は、その辺のオブジェクトを勉強するより簡単なんじゃじゃないかと思っています。


このブログの裏目標は「もっと関数化に(そしてクラスに)なじみが出ること」です。

「漢字練習は嫌いだけど読書は好きな人」に気に入ってもらえるブログを目指します。


お読みいただいている皆さんで、「関数ってなんか難しいな」と感じていた方がいらっしゃいましたら、せっかくですからこの機会に勉強してみてください(´∀`)



なお、今日の主張をもって「関数名は日本語にすべし」とまでは飛躍していません。

あくまで「勉強するならまず母国語で」という話です。


この記事を読んで
「関数なんとなくわかった!書いてみよ!」
と思い立ったら、作る関数は別に半角で問題ないです。


識別子に何語を採用するかは、書く人が好きに決めればいいことですし、
それこそ「どっちも使いこなして使い分ける」のが最強ですからね。


ということでいつもの締め方で締めさせていただきますが、
日本語識別子を使う人も使わない人も、みんな仲良く、
今後ともどうぞ、よろしくお願いいたします(´∀`)