アラサーからのプログラマー生活

アラサーの新米PGが必死に頑張る成長記録です。あとは旅行とか。

【ExcelVBA】年中〜小学校低学年向けの算数ドリルをExcelで作ってみたよ

f:id:hollage0214:20190216162442p:plain:w600

こんにちは、堀井です。

いきなりですが、私には嫁も子どももいません

でも!!

f:id:hollage0214:20190216164100p:plain:w400

算数ドリルを作りました!!

というわけで未就学児~小学校低学年のお子様がいらっしゃるご家庭向けの記事です。
またはVBAのコードを読みたい人向け

記事の最後ではこの計算ドリル(Excelファイル)を無料でダウンロードできるURLを載せていますので、最後までご覧いただければと思います。

【開発環境】
OS:Windows10
ソフト:Microsoft Excel 2013
Excel2016やMacなどを利用される方は表示が違う可能性があります。



ExcelVBAってめっちゃ便利

個人的な話ではありますが、数あるプログラミング言語の中で初めて学んだ言語がExcelVBAでして、思い入れもあるし言語としても結構好きなんです。

まだOOP(オブジェクト指向)はロクに分からないですが、関数などの使い方が分かるのであればちょっとしたものは簡単に作れてしまいます

例えば事務作業をされる方はルーティンワークの手間を省くことができます。
5時間かけていた仕事が10分で終わるとか普通にあり得る話なので非常に便利。
そして大抵会社のパソコンには開発環境(MicrosoftExcel)が入っている。



そんな多大なメリットを持つExcelVBA、開発する側としてはこの便利さを伝えたいのは山々なのですが、1点困った問題が。

「"楽だよ"とは聞くものの、プログラムを知らないから何がどう動くかも分からない
だから"どう便利にしたいか"なんて考えられない。」

と言うことです。これは友人から実際に言われたセリフです。

例えば私は機械学習は勉強したことがないので「機械学習は便利だが、どんなメリットを享受できるか?」という質問には確かに答えられません。

じゃあどうするのがいいかというと、実際に作ったものを見てもらうのが一番です。

それでは作り方をコードも交えてお話していきます。


VBAで開発できるようにExcelの設定を変えよう

まずはExcelを開いたら左上の"ファイル"タブをクリックしてください。

そうすると↓の画面になりますので、"オプション"を選択します。

f:id:hollage0214:20190216171211p:plain:w600

開いたら"リボンのユーザー設定"を選び、右側の"開発"タブにレ点を入れます

f:id:hollage0214:20190216171436p:plain:w600

その後"OK"を押していつもの画面に戻ると、

f:id:hollage0214:20190216171628p:plain:w600



開発タブが!!!



できてる!!!!!!


これで最低限の設定はできました
そのあと、

f:id:hollage0214:20190216174452p:plain:w600


"Visual Basic"ボタンをクリックする


f:id:hollage0214:20190216183527p:plain:w600


エディタ画面が開きます。

あとはエディタの設定を少しだけ変えておきます。


エディタの設定を変えよう

f:id:hollage0214:20190216175431p:plain:w600
ツール → オプション を開くとオプション画面が開きます。


f:id:hollage0214:20190216175521p:plain

  • 自動構文チェック のレ点を外す
  • 変数の宣言を強制する のレ点を入れる

これでエディタの設定も完了です。


f:id:hollage0214:20190216175731p:plain:w600
あとは挿入 → 標準モジュール を選ぶと・・・


f:id:hollage0214:20190216175912p:plain:w600
エディタが出来上がりますので、ここにプログラムを書いていきます。


核となるフォーマットを作ろう

例えばVBAのプログラムだと「B3, B5, B7, ・・・, B17とB列の3から順に2つずつ下げていき、B17まで移動する」「移動先にランダムな数字を入れる」みたいな動きをしています。

なので今回の場合、コードを書く前にどんな見た目にするかを決めなければいけません。

ということでフォーマットを整えてみました。
それがこちら。

f:id:hollage0214:20190216182619p:plain:w600

やりたいことですが「最大値、最小値」の範囲内で乱数を生成し、その値を数値のセルに突っ込んでいく、というものです。

右上の「生成する!」ボタンを押すと・・・。

f:id:hollage0214:20190216183031p:plain:w600

パッと。
こんな感じに変更された値を入れてやりたい。


プログラムの中身を書こう(コーディング)

目的ができたので、コードをバリバリ書いていきます。


・・・。


出来上がりました。

f:id:hollage0214:20190216184701p:plain

画像のコードは下記の通りです。

Option Explicit

Public Sub ドリル作成()
'-------------------------------------------------------------
'    変数宣言
'-------------------------------------------------------------
    Dim Printer As Worksheet            '印刷用ページ
    Set Printer = Sheets("印刷用")
    
    Dim rnd1 As Long, rnd2 As Long      '乱数
    Dim i As Long                       'ループカウント
    Dim HEAD As Long, LEG As Long   '開始、終了行
    Dim MAX As Long, MIN As Long    'ユーザーが設定した値

'-------------------------------------------------------------
'    問題生成
'-------------------------------------------------------------
    With Printer
        HEAD = .Cells(6, 2).End(xlDown).Row
        LEG = .Cells(Rows.Count, 2).End(xlUp).Row
        MAX = .Cells(2, 15).Value
        MIN = .Cells(4, 15).Value

        For i = HEAD To LEG Step 4
            rnd1 = random(MIN, MAX)
            rnd2 = random(MIN, MAX)
            .Cells(i, 4).Value = rnd1
            .Cells(i, 6).Value = rnd2
        Next i
    End With

End Sub



'-------------------------------------------------------------
'    乱数の生成
'-------------------------------------------------------------
Private Function random(ByVal MIN As Long, ByVal MAX As Long) As Long
    Dim rtn As Long
    
    Randomize
    rtn = Int(rnd() * (MAX - MIN + 1) + MIN)
    random = rtn
End Function


これだけ見てもいまいち理解しきれない部分もあると思います。

なので問題生成の処理を日本語で説明します

※読みやすいように多少改行を入れています

ここからは明示しなければ問題文ページ(シート名:印刷用)に対しての処理を指すからね

    スタート位置は問1の列に設定するよ
    ゴール位置は最後の問(今回は問15)の列に設定するよ
    最大値は"最大値"の項目に入れた数字に設定するよ
    最小値は"最小値"の項目に入れた数字に設定するよ


    スタート位置からゴール位置まで順番に処理していってね

        乱数1を作って
        乱数2を作って
        乱数1の値を+の左側に入れて
        乱数2の値を+の右側に入れて

    "スタート位置から~"まで戻って、次の列でまた繰り返すよ(ゴールしたら下に抜けるよ)

ここまでがページ指定だよ

といった感じです。
なんとなく私がやりたいことや、パソコン(プログラム)が得意とする処理が見えてきたのではないでしょうか?

ちなみにこのファイルそのものですが、試行錯誤しつつも2時間くらいで書いたものなので、もっと改良の余地はあります
乱数生成の処理を簡略化したり、直接数値を入力せず(定数を使って)保守性を高めたり、+だけでなく他の演算子も代入したり・・・。
そのうちやります。きっと。


ボタンに登録して1クリックで使えるようにしよう

これでプログラムは完成しましたが、まだお手軽には使えません。

じゃあどうするかというと、

  • ボタンを作って
  • ボタンにこのプログラムを登録する

作業が必要となります。

"開発"タブから挿入を選んで、フォームコントロールの一番左上の長方形("ボタン"です)を押します
f:id:hollage0214:20190217015616p:plain:w600


そうするとマウスカーソルが+になるので、適当な場所でドラッグしてボタンを作ります
f:id:hollage0214:20190217015714p:plain:w600


ボタンにどのマクロを登録するか?という表示が出るので、先ほど作った"ドリル作成"を選択してOKを押します
f:id:hollage0214:20190217020056p:plain


ボタンが生成されるので、テキストの編集から好きな名前に変えます
f:id:hollage0214:20190217023016p:plain:w600


私は記事冒頭にある画像の通り「生成する!」って表記にしました。


もう一つ機能を追加しよう(おまけ)

あとは上記手順に従い、もう一つ標準モジュールを作ってください。
以下のコードを書き、もう一つボタンを作ってこのプログラムを登録すれば印刷もお手軽。

Public Sub 印刷プレビュー()
    ActiveSheet.PrintPreview
End Sub

印刷プレビューを開くだけのページ。
ちなみにですが、ご自身で作る際は"印刷範囲の設定"をするのをお忘れなく


完成しました

これでひとまずの完成形となりました。

ボタンを押す度にランダムな数が入ることが確認できるでしょうか。

そして、最大値・最小値の値を変えることでその間の値しか入らないようになるでしょうか。

無事動いた場合はおめでとうございます。

動かなかった場合は記事最後にある私の作ったファイルと見比べながらバグを潰してみてください。

これが"面白い!"と感じた方は是非プログラミングにハマってください


バグや不具合について

ちなみにこのコードですが、開発者である自分は基本的にバグを出す操作はしません

ですので、他の人が使った場合に起こりえるバグや不具合はいくつか考えられます。

それは、

  1. 最大値と最小値の値を入れ替える(最大値:2、最小値:10とセットするなど)
  2. 最大値や最小値の値に文字を入れる
  3. 行や列を挿入・削除する
  4. 符号を−に直接書き換えて生成した場合、計算結果が負の数になる問題も生成される(4割くらい?)

ざっと思いつくだけでもこれだけあります。

特に2, 3に関しては普通にエラー吐いて動かなくなります。

これを防ぐためには

  • 最大値<最小値だった場合に値を入れ替える
  • 数字以外のものが入っていた場合にエラーメッセージを吐くようにする
  • シートの保護をして行の挿入・削除などの変更を認めない

とかの処理を入れてあげる必要があります。

が、そんなことしないだけでエラーを避けられるので作りませんでした。
ご利用の際にはご注意ください。まあ、お金取って頒布するわけじゃないので。


ダウンロードページ

f:id:hollage0214:20190215234459p:plain:w600
最後までお読みいただきありがとうございました。

作ったファイルをダウンロードできるページです。

こちらからダウンロードしてください。

念のため注意点です。

  • ファイル内に必要最低限のルールを記載してありますのでご一読ください。
  • 数値を入れる箇所に文字を入れるなど、制作者の意図しない動きで起きたエラーに関しては基本的にご自身で解決してくださるようお願いします。
  • ウィルスチェックで非感染を確認していますが、このファイルを利用した際の損害等に対する責任は一切負いません。
  • ダウンロードの際は以上の注意点を読んで同意いただいたものとみなします。

また、ファイルが消えていた際は問い合わせフォームよりご連絡ください。

まだデータが残っていたらアップします・・・。

お問合せフォーム - アラサーからのプログラマー生活



最後に私がこのドリルを作った目的ですが、甥と姪にあげるためです。

私に子どもはいませんが、兄弟にはいるので・・・。念のためね。

それではまた次回。