VBAデバッグの鬼

プロゲート解説|ディレクトリから相対パスを表記する

今回の問題

プロゲートのディレクトリの説明が悪かったので私なりに訂正してみた

発見したのは、プロゲート(Progate 以降カタカナ表記)のJavaScriptレッスン5です。

↓いや、説明が全然わかりにくいんですけど。
百聞は一見に如かず

f:id:vba-tokepi:20210523084107j:plain

え?これでどうしてドットが二つになるの?私意味が分からない💦

私なりの解釈がこちらです。

f:id:vba-tokepi:20210523084226j:plain

三段階ではなく、四段階でないと、これは説明がつかないのです。

そもそもスラッシュの前にあるドットってなんですか?

ドットはフォルダです!

そうなんです。ドットはフォルダを表しているのです。
なので、一枚目の写真は、一つ目のドットであるsrcにたどり着けていないのです。
いや、初心者にこの説明では、月会費1000円返せよ!ってなる。わたしなら💦

私が修正した、二枚目の写真を見てください。

1でdataフォルダを経由するので、ドットがひとつ。

2でsrcフォルダまで戻るので、二つ目のドットを追加。

それから!やっとclassフォルダに入れるので、スラッシュの後にclassのフォルダ名を指定しましょう。

手前味噌ですが、この説明のほうが腑に落ちませんか?

実際にプロゲートで学習を進めていて、ディレクトリと相対パスでつまづいた人にぜひ読んでほしいです。

とはいえ、プロゲートがいままで独学した中で一番学習効率が良いです!

今回は説明不足をたまたま発見してしまいましたが、総合的に見て、私のプロゲートの評価は95点です。

3年間独学してきました。

まずはドットインストールでHTML,CSSおさらい。
次にPython入門を書籍で。
ここで一旦迷子になるんですね。
作りたいものも特にないし、学んだものをどこにどう生かしていいのやら。
そこで、sololearnというプログラミング学習アプリに出会います。
www.sololearn.com
今思えば、これって英語版プロゲートなんですよね。
そもそも英検二級の私が、スマホでこれをちまちま解いていたわけです。
書いてあることは6割くらいしか理解できてなかった(泣)
PythonPHPJavaScriptを一通り修了しましたが、まだコードが書けるようにならないし、やっぱり作りたいものがイメージできない。

ここから1年半くらいの空白があり、そして友達経由でVBAにであったんですね。

VBAは一年くらいじっくり学習できました。そして、就労支援のスタッフさんに教えてもらったサイト、マクロVBA練習問題を日々解いていく今に至っています。
excel-ubara.com

そして2021年5月プロゲートに出会う

先月下旬、プログラミング学習をしながらお仕事ができる事業所を見つけました。
早速情報集め、応募。とんとん拍子で話が進み、6月から就労支援を卒業して、事業所に所属になります。
は~、これで2年縛りの恐怖に怯えないで済みます✨

それはさておき、新しい事業所では、まずプロゲートから始めてもらうという話だったんですね。
私は待ちきれなくて、早々とフライングしてしまったわけです。

でも、プロゲートを始めてみてびっくり!

難解な書籍を読むよりも、プログラミング言語オブジェクト指向がスイスイ頭に入っていきます。

難しくて、読み進められなかった参考書も、プロゲートで一通りやったあと、再び読んでみると「あ!理解できる!!」

この感動ったらなかったです。
f:id:vba-tokepi:20210523092158j:plain

sololearn以降の1年半ブランクが来る前に出会っていれば(笑)

いえいえ、まだ45歳。まだやれる!
爆速でプロゲート終えて、本格的なWeb開発とVBAでの自動化(RPA)、どっちもものにしますよ!!

二兎追うものは一兎も得ず!なんていうけれど、プログラミング学習に関しては二兎追っていいと思いますよ。
基本的にどの言語も基本は演算、条件分岐、ループ、配列、クラスでしょ?ちょっと書き方が違うだけ。
それは考え方が甘いのかな?

やはり、ばっちりできる一つの言語がないと、上には積み上げていけないそうです。

英語学習もそうですよね。日本語という言語の下地があるから、英語を言語として学習できる。
プログラミング言語にしても語学学習にしても、コアになる言語は必要。

私はVBAを軸にしていくつもりですがね^v^
ただ、悩みは。。。やはり作りたいものがない(泣)

VBA データの抽出、入力作業にFor~Nextを使うかDo~Loopを使うか

すっかりFor~Nextでやる癖がついてしまいました

今回の問題
エクセルの神髄-マクロ練習問題から【練習問題15】
excel-ubara.com

この問題について、私は次のような簡易フローチャートを描きました。

支店抽出→支店別に列を選ぶ→商品別に行を選ぶ→売り上げをセルに記入。

やってみると案外サクッとコードは書けてしまいました。
やたらFor~Nextを使って、Pythonのようにインデントするようなコーディングが私の癖です。

Sub 練習問題15()
Dim i As Long, j As Long, k As String
Dim brc As Long
Dim ws1 As Worksheet, ws2 As Worksheet

Set ws1 = Sheets("練習15")
Set ws2 = Sheets("練習15_回答")

ws2.Range("A1").CurrentRegion.Offset(1, 1).ClearContents

For brc = 2 To 5
    For i = 2 To ws1.Cells(Rows.Count, 1).End(xlUp).Row
        If ws1.Cells(i, 1) = ws2.Cells(1, brc) Then
            For j = 2 To ws2.Cells(Rows.Count, 1).End(xlUp).Row
                If ws1.Cells(i, 2) = ws2.Cells(j, 1) Then
                ws2.Cells(j, brc) = ws2.Cells(j, brc) + ws1.Cells(i, 3)
                End If
            Next
        End If
    Next
Next

End Sub

brcはbranchの略です。昨日プロゲートのJavaScriptコースで、変数にローマ字を当てるのは良くないとありました。branchはローマ字ではなく英単語ですがbrcにした方がプログラミング言語っぽいよな、ということでbrcです。

欲を出せばbrcの終わりの数は最終列を取得する文字列を入れたかったですが、最終行は出来ても、最終列については、まだ勉強不足であります。近々、最終列の取得の仕方も学習します。

さてさて、For〜Nextを3つもネストしてしまうことは、VBAのプログラミング的にはありなんでしょうか?練習問題15の解答を見ると、For〜NextではなくLoopを使っています。

しかし、このコードでも、見た目には問題なく動きます。

そもそも、なんでもFor~Nextで片付けるようになったのはこの書籍の影響が大きかったです。
図解! Excel VBAのツボとコツがゼッタイにわかる本 プログラミング実践編 立山秀利
図解!  Excel VBAのツボとコツがゼッタイにわかる本 プログラミング実践編

この本は、入門書を一通り読んだけど、まだ自分ではコードを書けない!という人に、ぜひ読んでほしい本です。

この本を読んで得られるメリット

  • RangeよりもCellsを使うことに慣れる。
  • For~Nextの使いこなしに強くなる。

For〜Nextを使ってセルの値を累計していく

この手法はエクセルの真髄-マクロ練習問題の練習問題12で出てきて覚えました。
excel-ubara.com


ws2.Cells(j, brc) = ws2.Cells(j, brc) + ws1.Cells(i, 3)

このように記述することで、空のws2.Cells(j,brc)にws1.Cells(i, 3)の数値を繰り返しのたびに入れてくれるのですね。
繰り返しで2回目、3回目と入れていくたびに、ws2.Cells(j, brc)の中に数値が累計されていきます。

Do~Loopを使う方法について

やはり、ソースを見比べてもFor~Nextのみで片付けるよりも、Do~Loopを使ったソースのほうがすっきりしています。
何も参照することなく、このようなコードがポンとかけるようになりたいです✨

【Do~Loopを使った際の簡易フローチャート
1.For~Nextでws1のリストの上から下までざ~~っとチェック

2.ws2の支店の行とws1の支店の列が一致するまで→(1 , ixC)= (i , 1)になるまで、ixCをひとつずつ増やしていく。

3.ws2の分類の列とws1の分類の列が一致するまで→(ixR , 1)= (i , 2)になるまで、ixRをひとつずつ増やしていく。

4.ws2の(ixR ,ixC)のセルの支店の列と分類の行がws1のi行のものと一致する。

5(ixR ,ixC)にws1のi行の売り上げをセルに入れる

1.に戻ってws1、i行のデータがなくなるまで繰り返し

程よい手ごたえ!頑張って続けていきます!

エクセルの神髄-マクロ練習問題を、日々解き進めていますが、入門書、中級の書籍を読んだあたりで、少し迷子になった私には程よい手ごたえです。
まずはスクレイピングができるようになるところまで頑張ります!^^v

VBAでCOUNTIFを使いこなすための重要事項

今回の問題

C5以降、列に、地名でも食べ物の名前でもいいので4種類、50個ほどランダムに並べてください。
C2に記入した単語と同じ単語をCOUNTIFで数えるとします。

私は、渋谷、品川、池袋、新宿の4つの単語を利用しました。

Excelとは勝手が違うVBAのCOUNTIF

指定した単語がデータの中にいくつあるのか、数値を求めたい時があると思います。
ExcelであればCOUNTIFで一発ですが、このCOUNTIFをVBAで使うとなるとなかなかに厄介でした。
忘備録として、私が VBAでCOUNTIFを正常に機能させるまでの奮闘記をここに残しておきます。

Excelの要領ででとりあえず私が書いてみたCOUNTIFのコード

Sub cnt()
Dim nmb As Long

nmb = WorksheetFunction.CountIf(Range("C5:C65"), C2)
Debug.Print nmb

End Sub

F5で実行してみると、次のようなエラーがでました。
f:id:vba-tokepi:20210418181406j:plain

キャプチャでうまくいかなかったのですが、C2の文字がハイライトされています。
ExcelのようにC2の表記では、値として認識してくれない模様。
かといって"C2"とすると、今度はC2という文字列になってしまいますし。

ここは初心に返り、数を求めたい単語をダイレクトに指定してあげましょう。
C2を個数を求めたい"池袋"に書き換えます。

nmb = WorksheetFunction.CountIf(Range("C5:C65"), "池袋")
Debug.Print nmb

お!直接単語を指定してあげると数えてくれるようです。
イミディエイトウィンドウに13の文字が。
f:id:vba-tokepi:20210418181943j:plain

注:見間違えでC65をC61としてましたので13ですが、以降はC65に書き直して14とカウントされます。うっかりミスです。すみません。

しかしこれでは、求めたい数値の単語が変わるたびにVBAコードを書き変えなければなりません。
なんとか取得できないものか。。。
セルの値を取得したいので、セル範囲を指定してあげましょう。

nmb = WorksheetFunction.CountIf(Range("C5:C65"), Range("C2"))
Debug.Print nmb

来ました!C2ではなく、ちゃんとセル範囲を指定してあげればよかったのです。

ただ、これではいまいちです。
データがC65よりも増えた時に、またいちいち書き直しますか?

さてさて、どんどんVBAのコードらしくしていきますよ!

とりあえず、最終行を取得する変数iを設定して、範囲をCellsで指定してあげましょう。

Sub cnt()
Dim nmb As Long
Dim i As Long
i = Cells(Rows.count, 1).End(xlUp).Row

nmb = WorksheetFunction.CountIf(Range(Cells(5, 3), Cells(i, 3)), Range("C2"))
Debug.Print nmb

End Sub

お~!サクサク数えてくれますね。

しかし、この関数、シートがアクティブではなくなると、数えてくれません。
セルしか指定してないんですもの。そのため、現在アクティブになっているシート上で動いてしまいます。

空のsheets(2)がアクティブになると、0を返してきます。

ど素人な私は、シートを指定するために、このようなコードを書いてしまいました。
nmb = Sheets(1).WorksheetFunction.CountIf(Range(Cells(5, 3), Cells(i, 3)), Range("C2"))
Debug.Print nmb


写真の通りのエラーが出ました。nmbの行が一気に黄色にハイライトされました。
f:id:vba-tokepi:20210418184101j:plain

ググりまくりましたよ。どこでシートを指定すりゃいいの??

とりあえず、シートの指定、そこじゃないよ。

では、これでどうでしょう?
nmb = WorksheetFunction.CountIf(Sheets(1).Range(Cells(5, 3), Cells(i, 3)), Range("C2"))
Debug.Print nmb

ダメです。まだエラーが出ます。
f:id:vba-tokepi:20210418184543j:plain

ならば、表示されているCellsすべてのシートを指定しちゃいましょう!
i = Sheets(1).Cells(Rows.count, 1).End(xlUp).Row

nmb = WorksheetFunction.CountIf(Sheets(1).Range(Sheets(1).Cells(5, 3), Sheets(1).Cells(i, 3)), Sheets(1).Range("C2"))
Debug.Print nmb

ほっ!!数えてくれました。
f:id:vba-tokepi:20210418185507j:plain

厄介でしたがVBAでCOUNTIFを使うコツがわかりました

一通りエラーしまくった挙句、ようやくこのブログを執筆しているので、スムーズに数え終わりましたが、まぁ、エラーが出るたびに、何が悪いのか何度もググりまくりましたよ。

要は

  1. 条件のセル範囲をきちんと指定してあげること。
  2. セルにはすべてシートを指定してあげること。

この二つを満たしてあげれば、うまくCOUNTIFしてくれるようです。
また、ブックをまたいでコードを書いている場合は、シートの前にブックまで指定してあげる必要があります。

Excelで関数をつかう場合と違い、VBAではシートをまたいだり、ブックをまたいだりするので、位置関係を詳細に示してあげる必要があるんですね。
面倒くさいですが、変数や定数をうまく使いこなして、すっきりとしたコードが書ければ幸いです。

あ~、疲れた(笑)

VBAエラー オーバーフローしました に、初めて対処してみた

今回の問題

プログラムを書いて実行すると、オーバーフローエラーが出た

まずはデバッグ事始め

VBAを始めて約1年半。
ざっと基礎をやって中級の参考書のソースをざっと理解したところで、VBAを放置してほかの言語に浮気をしていました。
基礎の欠落に気が付いたのは、このサイトの問題にとりかかるようになってからです。
マクロVBA練習問題|エクセルの神髄
入門書から中級の問題集に進んだけれど、バリバリコードを書くまでに至っていない方は、ここの問題をすべて解いてみてください。入門書から学んでいく過程で抜け落ちていた部分を補うことができますよ。

このサイトを解いていく過程で生じたデバッグ作業をことごとく記事にしていきます。

今回は第一回目のデバッグ

この問題を解いているときに遭遇したエラーをデバッグしてみました。
excel-ubara.com

初めてのオーバーフロー

私が書いてみたコードがこちら。

Sub 練習問題7_1()
Dim i As Long, a As Long, total As Long
a = 0
total = 0
For i = 2 To total
        Cells(i, 4) = Cells(i, 2) * Cells(i, 3)
    a = a + Cells(i, 4)
    total = total + 1
    
Next

MsgBox "合計は" & a & vbLf & "平均は" & a / total, vbOKOnly, "結果"

End Sub

これを実行するとこのようなエラーが出ます
f:id:vba-tokepi:20210327171606j:plain

オーバーフロー?!
VBAを学習し始めて、初めて見たエラーです。
デバッグの示す場所はここ。
f:id:vba-tokepi:20210327171711j:plain
そういうわけでメッセージボックスとオーバーフローの因果関係を突き止めるべく、メッセージボックスのソースをいじりたおしました。
vbLfを削除してみたり、中身を全部消して、aの中身だけ表示させようとしてみたり。

それでも、実行してみると「オーバーフローしました。」と、冷たくあしらわれます。

気を取り直して、コードをひとつひとつ見ていくことにしました。
F8でステップ実行開始。

そこでやっと気が付きました。

実際に問題のあった場所はここ
f:id:vba-tokepi:20210327172150j:plain

他のプロシージャで使いまわした変数totalがおかしなことになっていたんですね。

totalは繰り返しの中で、一つ一つ数を増やしていくために設定されている変数です。

前のプロシージャでは、最終行を取得する変数として使っていたのを、そのままにしてしまっていたのです。


これで動きます

Sub 練習問題7_1()
Dim i As Long, a As Long, total As Long
a = 0
total = 0
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
        Cells(i, 4) = Cells(i, 2) * Cells(i, 3)
    a = a + Cells(i, 4)
    total = total + 1
    
Next

MsgBox "合計は" & a & vbLf & "平均は" & a / total, vbOKOnly, "結果"

End Sub

こつこつF8実行で解決

オーバーフローというエラーを目にしたのが初めてであたふたしてしまいましたが、F8でプログラムを一行一行実行しながらおかしな箇所に気付けることが解消への道です。
それにしても、プロシージャや変数の使いまわしをするときは、使いまわし前に機能していた部分と、新しく機能させたい部分に矛盾が生じていないか、入念にチェックする必要があります。

自分で新たなVBAのプログラムを組むとき、GitHubやブログに載っているソースを使い回すこともあるはずです。その時に、オーバーフローなどのエラーが出たら、引き継いだ変数などに矛盾がないか、F8でひとつひとつ確認しましょう。

このブログの説明

このブログをざっくり一言でいえば・・・

 

VBAを仕事にするための奮闘記

 

になります。

 

更新頻度は月に2回程度ですが、VBAで仕事ができるくらいのレベルになるまで、コツコツデバッグを繰り返し、その経過を記していきます。

 

想定する読者ターゲットは、VBAの入門書は読んだけれど、何をやっていいかわからない人向けです。使っている参考書なども紹介していきます。

 

とはいえ、個人的には

「とにかくVBAスペシャリストになるしかない!」

そんな気負いがありまして、そこにはこのような背景があります。

 

睡眠障害のため雇用で働かせてもらえない現実

 

私は現在45歳。高校一年生、15歳の時に睡眠障害を発症しました。

 

 この30年、実にいろんな苦難がありましたが、軒並み寝付くまでに、毎日4~6時間の時間が犠牲になっています。時には眠れないまま朝を迎えることもあります。30分くらいで毎日ことっと寝てしまう人には「4時間床についていても眠れない」ということがどれほどの苦痛を伴うものなのかピンとこないかもしれません。寝ようとウトウトしだすと針で刺されて延々と寝させてもらえない。そんな拷問のような時間を過ごしています。

 

眠れない苦痛は、実生活にかなりの差し障りをもたらします。

兎にも角にも、いつ不眠が起きるかわからないため、時間を守るということが不可能です。

一睡も出来なかった日は、寝不足のストレスからパニック発作を起こして意識が飛ぶこともたびたび。

 

友達と待ち合わせをして、朝まで眠れなかった日は、ドタキャンせざるを得ません。

ましては、雇用契約を結んで、毎日決まった時間に働くことをやです。 

 

それでも仕事がしたい!

 

2013年からフリーランスで仕事を取っていますが、なんの実績を積むこともできなかった私にやらせてもらえる仕事はほとんどなく、やっとみつけた仕事でも、せいぜい時給150円にしかならないということも。

 

3年前に一念発起して、プログラミングを身に着けて、単価の高い仕事を取ってやる!という目標を立てました。

 

 最初はPythonから手を付けましたが、基礎を一通りやり終えたところで学習迷子になりました。次にやるべきことがわからないのです。

 

なによりPythonはじめ、プログラミング言語は、それらを使用するための統合開発環境などの環境構築が大変です。

 

VBAとの出会い

友達が、業務で役に立つかもしれないからVBAを始めたという話を聞きました。

その時に、はっ!と気づきました。

VBAならExcelさえあれば統合開発環境なしで存分にプログラミングがやれる!

 

早速、私はアマゾンからVBAの入門書を取り寄せました。

 

入門書から始めて、プログラムを実行するとセルに反映されて、くるくる動いてくれる快感。

 

VBAは学習迷子になることもなく今も学習が続いています。

 

時にはVBAに限界を感じて、またPythonJavaScriptに戻ることもありました。

一通りのことが出来るようになると、仕事になるというスクレイピングAPI活用をやりたくなったのです。

 

しかし、VBAは実は奥が深くて、これらのこともやれてしまうということを知りました。

私をやる気にしてくれた記事がこちら

www.fastclassinfo.com

というわけで、とにかく、まずはVBAを極めます。

 

そしてVBAで仕事ができるようになるまで頑張る!

 

飽くなき挑戦は続きます。