Access VBAでcollectionやitem等が使われている箇所の意味を理解したいです

今、こちら https://gist.github.com/AuroraNorthernQuarter/ca660fa7e18d71c3335b65e743332ba6 のようなVBAコードがあります。
このコードを読解しようとしたのですが疑問が生じまして、ご助言いただけますと有難いです。

①「For Each varCode In personnel」という使い方がありますが。
これはFor Eachステートメントだということですが、「バリアント型もしくはオブジェクト型で指定する必要があります。」と、説明しているサイトがありました。
https://www.sejuku.net/blog/30887
しかしpersonnelという変数は、collection型?で定義されております。
これは一体どういうことなのでしょうか…コードが間違っているのでしょうか…疑問です。

回答の条件
  • 1人20回まで
  • 登録:
  • 終了:2020/05/19 13:40:23
id:moon-fondu

② if confirmation(cstr(varCode)) then
tSQL = updSQL(PrefectureCode,KankatsuCode,_
clng(money.item(varCode)),clng(m_kazu.item(varCode)))
else
tSQL = insSQL(PrefectureCode,KankatsuCode,clng(money.item(varCode)))
end if

の箇所は、SQLのupdate文を呼び出す時はupdSQL関数、insert文を呼び出す時はinsSQL関数を呼び出し、tSQLに代入しています。

ここにおきまして、関数の引数にある「clng(money.item(varCode))」等についてですが。これは何をしているのでしょうか?
「clng関数で値を数値に変換している」という情報が、検索したら出てきましたが。
collection型のmoneyをitemプロパティで?そのitemプロパティの中に"(varCode)"という引数が入っているのもよくわからず…。
ちなみにinsSQL関数やupdSQL関数は、

------------------------
private function insSQL(ByVal i_PrefectureCode as Integer,_
ByVal i_KankatsuCode as Integer,_
ByVal i_funds as Long,_
) as string

・・・

insSQL = tSql
End Function
------------------------
private function updSQL(ByVal i_PrefectureCode as Integer,_
ByVal i_KankatsuCode as Integer,_
ByVal i_funds as Long,_
ByVal i_kazu as Long,_
) as string

・・・
updSQL = tSql
End Function
------------------------

という中身になってまして、「・・・」の部分にはSQLがずらりと並んでおります。
insSQLもupdSQLも、データベースにデータを挿入したり更新したりする関数というのはわかりますが。
collectionやitem等が絡むとどうも理解が及ばず…お力添えいただけますと幸いです。

よろしくお願い致します。

ベストアンサー

id:kaitesukkiri No.2

回答回数2ベストアンサー獲得回数1

ポイント700pt

いろいろ突っ込みどころの多い質問です。

①誤解
まず、https://www.sejuku.net/blog/30887の文章を誤解しています。
そのページには「コレクションの要素を受け取る変数がバリアント型かオブジェクト型です」と書かれています。

for eachとはコレクションや配列など要素の集合から順に要素を取り出す構文で、要素の受け取り先がバリアントかオブジェクトです。
「for each x in y」のxがVariantかObject、yがCollectionかArrayです。

・Collectionとはキーとアイテムをワンセットとした情報の集合
・collectionXX.Add(itemXX,keyXX)でコレクションにアイテムを追加する (集合なのでたいていは複数追加する)
・a=collectionXX.Item(keyXX)でkeyXXに合致するアイテム(itemXX)をaに求める
・For each a In collectionXX~NextでcolletionXX内のアイテムをすべて順にaに求めて繰り返す


③参考にしている情報が不適切
だれが書いたかわからない正しいかどうかもわからない情報を元に知識を得ようとすると遠回りになることが多い。
AccessVBAの言語仕様、構文、使用例など基本的なことはMicrosoftオフィシャルをみればちゃんと解説してある。

参照しているGithubのコードには3つのコレクション(personnel、m_kazu、money)にアイテムをaddしている部分が示されていないので、確かなことはなにも言えない。
示されている範囲から想像できるのは、

personnelコレクション
p1 アイテムは文字列 (cstrで型変換してるから)
p2 アイテムの最初の1文字は数値で都道府県コード
p3 アイテムの3文字目以降も数値で管轄コード
p4 キーは不明

m_kazuコレクション
k1 キーはpersonnelコレクションのアイテム値である文字列(p1)
k2 キーはおそらく日付をあらわす文字列 (confirmationの引数名がi_dateだから)
ということはp1も日付を表す文字列なんだろうけど、上記p2p3との整合性がないから意味不明。
k3 clng(money.item(varCode))しているかアイテムの内容は数値
k4 キー(p1)を持つアイテムがなければDBにinsertあればupdate

moneyコレクション
m1 たぶんkansu1プロシージャの内で要素が設定されるんだろう (ただし、Call kansu1 =(money)という構文はありえない)
m2 clng(money.item(varCode))としているから、アイテムは数値でキーはp1

こんなコード必死にみたって何にもならない。
業務上やらなければならない既存コードだから見ているのなら仕方ないが、言語やプログラムングを習得するためにみているならやめたほうがいい。

id:moon-fondu

ごろえもんさんありがとうございます。
For each構文、そうだったんですね。

collectionがあるということは、どこかに「collectionXX.Add(itemXX,keyXX)」という形式で、
コレクションにアイテムが追加されている記述があるはずですね。

質問ですとシステムから一部抜粋して、そのシステムが特定されないように変数名などを変えているので、
わかりにくく不完全な部分も恐らく生じておりまして、すみません。

でも少しだけ、コレクションとアイテムの関係性がわかったような気がします。
プログラミングを習得するために、読んでいてわからなかった部分を質問しております。

それぞれのコレクションにアイテムをaddしている部分を探して、"()"で囲まれている
キーも探してみます。

2020/05/19 03:20:00

その他の回答1件)

id:cancolomochi No.1

回答回数3ベストアンサー獲得回数0

ポイント500pt

①「For Each varCode In personnel」
ソースコードでpersonnelがcollection型で、varCodeがvariant型となってますが、これで大丈夫です。
personnelの中に色々なアイテムが入っていて、その全てについて一つ取り出してはvarCodeという変数に格納して何かしら処理する、という内容になっています。
普通のFor文よりこちらの構文の方が慣れると書くのが楽なので、好む人が多い印象です。

②clng(money.item(varCode))
ソースコード見るとmoneyはcollection型となってましたので、money.item(varCode)はmoneyの中からvarCodeをキーにしてアイテムを取り出してることになります。
clngという関数は引数で受け取ったデータをlong型に変換するものとなりますので、例えばclng(3.14)を実行すると3が帰ってきます。

まとめると、
moneyというcollectionからvarCodeをキーにアイテムを取り出し、それをlong型に変換
となります。

ただ、ソースコード中の
Call kansu1 =(money)
が変な気がします。私はVBA詳しくはないのですが、普通は
  money = Call kansu1()
と書く気がします。

id:moon-fondu

ICMPSNMPさんご回答ありがとうございます。

①についてですが、personnelはなぜcollection型で大丈夫なのでしょうか?
For Eachステートメントが「バリアント型もしくはオブジェクト型で指定する必要がある」であれば、コレクション型を使っているpersonnelが正しいのか、疑問です。

Access VBA 入門講座 - コレクション
http://accessvba.pc-users.net/object/collection.html

によると、collectionは数字しか入れられないだの文字列が入るといった要素的な型ではなく、実際の値などが格納されるオブジェクト?らしいですが。
personnelはオブジェクト、だからオブジェクト型という条件に一致するので、For Eachステートメントの「バリアント型 or オブジェクト型」という条件にも一致して正しい…という認識でよいでしょうか?

②itemは、「itemプロパティ」「itemメソッド」の場合があるという話を、

VBAのコレクションはItemとCountを必ず持つ:エクセルマクロ・Excel VBAの使い方
https://www.relief.jp/docs/excel-vba-collection-has-item-count.html

で読みましたが。
varcodeをキーにしてitemを取り出している…varcodeが引数になっているようなので「itemメソッド?」だと、自分は考えております(間違っておりましたらご指摘ください)。

ただこのitemメソッドは、どのような処理を行うのでしょうか?
varcodeというコレクションの中から、何を取り出すのでしょうか?

エクセルVBAで自作コレクションの要素を取得するプロパティの作り方
https://tonari-it.com/excel-vba-class-collection-item-property/

という記事によれば、独自のメンバーとして「Item」を追加しているようですが。
今回のケースでは、Itemの定義などは行われず、いきなり「.Item」と使われております。

vba上で「.Item」上で右クリックすると、オブジェクトブラウザーに飛んで「"Collection"のメンバー」に属している、という表示がされます。

しかしItemメソッドの機能、役割の部分がどうしてもわからず…お手数ですが再度、お教えいただけないでしょうか。

よろしくお願い致しますm(__)m

2020/05/18 11:43:44
id:kaitesukkiri No.2

回答回数2ベストアンサー獲得回数1ここでベストアンサー

ポイント700pt

いろいろ突っ込みどころの多い質問です。

①誤解
まず、https://www.sejuku.net/blog/30887の文章を誤解しています。
そのページには「コレクションの要素を受け取る変数がバリアント型かオブジェクト型です」と書かれています。

for eachとはコレクションや配列など要素の集合から順に要素を取り出す構文で、要素の受け取り先がバリアントかオブジェクトです。
「for each x in y」のxがVariantかObject、yがCollectionかArrayです。

・Collectionとはキーとアイテムをワンセットとした情報の集合
・collectionXX.Add(itemXX,keyXX)でコレクションにアイテムを追加する (集合なのでたいていは複数追加する)
・a=collectionXX.Item(keyXX)でkeyXXに合致するアイテム(itemXX)をaに求める
・For each a In collectionXX~NextでcolletionXX内のアイテムをすべて順にaに求めて繰り返す


③参考にしている情報が不適切
だれが書いたかわからない正しいかどうかもわからない情報を元に知識を得ようとすると遠回りになることが多い。
AccessVBAの言語仕様、構文、使用例など基本的なことはMicrosoftオフィシャルをみればちゃんと解説してある。

参照しているGithubのコードには3つのコレクション(personnel、m_kazu、money)にアイテムをaddしている部分が示されていないので、確かなことはなにも言えない。
示されている範囲から想像できるのは、

personnelコレクション
p1 アイテムは文字列 (cstrで型変換してるから)
p2 アイテムの最初の1文字は数値で都道府県コード
p3 アイテムの3文字目以降も数値で管轄コード
p4 キーは不明

m_kazuコレクション
k1 キーはpersonnelコレクションのアイテム値である文字列(p1)
k2 キーはおそらく日付をあらわす文字列 (confirmationの引数名がi_dateだから)
ということはp1も日付を表す文字列なんだろうけど、上記p2p3との整合性がないから意味不明。
k3 clng(money.item(varCode))しているかアイテムの内容は数値
k4 キー(p1)を持つアイテムがなければDBにinsertあればupdate

moneyコレクション
m1 たぶんkansu1プロシージャの内で要素が設定されるんだろう (ただし、Call kansu1 =(money)という構文はありえない)
m2 clng(money.item(varCode))としているから、アイテムは数値でキーはp1

こんなコード必死にみたって何にもならない。
業務上やらなければならない既存コードだから見ているのなら仕方ないが、言語やプログラムングを習得するためにみているならやめたほうがいい。

id:moon-fondu

ごろえもんさんありがとうございます。
For each構文、そうだったんですね。

collectionがあるということは、どこかに「collectionXX.Add(itemXX,keyXX)」という形式で、
コレクションにアイテムが追加されている記述があるはずですね。

質問ですとシステムから一部抜粋して、そのシステムが特定されないように変数名などを変えているので、
わかりにくく不完全な部分も恐らく生じておりまして、すみません。

でも少しだけ、コレクションとアイテムの関係性がわかったような気がします。
プログラミングを習得するために、読んでいてわからなかった部分を質問しております。

それぞれのコレクションにアイテムをaddしている部分を探して、"()"で囲まれている
キーも探してみます。

2020/05/19 03:20:00
  • id:tobeoscontinue
    横やりですが

    > ①についてですが、personnelはなぜcollection型で大丈夫なのでしょうか?
    > For Eachステートメントが「バリアント型もしくはオブジェクト型で指定する必要がある」
    これはFor Eachで使う変数がバリアント型もしくはオブジェクト型で指定する必要があるということです。
    配列やCollectionの中にどんな型のものが入っているのかわからないので受け取る変数はバリアント型に
    ならざるおえないのですが変数の宣言は省略可能です。

    > varcodeをキーにしてitemを取り出している…varcodeが引数になっているようなので「itemメソッド?」だと、自分は考えております(間違っておりましたらご指摘ください)。
    item()と()があればメソッド。無ければプロパティと覚えています。

    > ただこのitemメソッドは、どのような処理を行うのでしょうか?
    引数のvarcodeをキーにしてコレクションの中から該当するitemを取り出す。

    > varcodeというコレクションの中から、何を取り出すのでしょうか?
    varcodeはコレクションじゃない。ただの変数。
    varcodeをキーにしてコレクションの中から、何を取り出すのでしょうか?ということなら
    それぞれのpersonnel、m_kazu、moneyに何を格納しているかによる。

    > 今回のケースでは、Itemの定義などは行われず、いきなり「.Item」と使われております。
    VBAのコレクションはItemとCountを必ず持つ:エクセルマクロ・Excel VBAの使い方
    とあるようにコレクションがItemを定義しているのでいきなり使うことができます。
    逆に言うとプログラマーはコレクションなどでどういうメソッドやプロパティがあるか知っておく必要があります。
    Visual Studio Codeでは使えるメソッドやプロパティが補完されますがその動作や意味を知らないと使えないので
    結局覚えておく必要があります

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません