質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

1574閲覧

【Excel VBA】データ集計ツール作成時の配列Buffer処理について

退会済みユーザー

退会済みユーザー

総合スコア0

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2019/02/19 11:36

はじめまして。
超がつくほどのVBA初心者のものです^^

2枚のシート、[A 会員データ]シート、[B 集計結果]シート
があります。

[A 会員データ]シートのデータリストはこのような感じになっています。

|氏名漢字|氏名かな|性別|mail|TEL|住所|
|:--|:--:|--:|
|田中太郎|たなかたろう|1|tarou.bbb.orjp|011-266-**|東京都北区2-41-*
|鈴木恵子|すずきけいこ|2|suzuki.bbb.orjp|011-345-**|北海道札幌市2-41-*

上記のようなデータが約10万件あります。
ちなみに性別欄の1は「男性」で2は「女性」を表しています。

BのシートにAの会員データを下記のように集計した2つのリストの
作成を目指しています。

1.都道府県別、且つ、男女別の人数
2. 男女の内訳人数

出力結果は下記のようなリストをイメージしています。

1.都道府県別、且つ、男女別の人数

都道府県性別人数
鹿児島県男性45
鹿児島県女性12
〇〇県男性45
〇〇県女性12
××県女性12

2

内訳人数
男性46
女性12

配列Buffer処理にて高速処理を目指しています。

配列での実装経験がなくVBAの知識も乏しいので
誠に恐縮なのですが熟練者の方ご教授頂ければ幸いです。

宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

配列で実装するということは、高速化のためだと思いますが、
配列にすればなんでも高速になるとは限らないです。
ピボットテーブルでできるならことなら、VBAでピボットテーブルで集計、出力を実装するのが高速だと思う(たぶん)(VBAはインタプリタなのでそもそも遅い)。

あるいは、ADOをつかってSQLで集計して、CopyFromRecordset で書き出すというのは、シンプルなコードで高速な処理が実現できそうです(SQLが分かるなら)。

エクセルのシートをデータベースのテーブルとして扱うとめちゃくちゃ簡単にデータを加工できる!|エクセルVBA - ぼくLog

配列を使うなら、
ttyp03さんの回答のように Scripting.Dictionary を使って集計していくことになりそうですね。

いろいろ、やってみて一番高速なのを選択すればいいでしょう。

投稿2019/02/20 07:18

hatena19

総合スコア33715

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

流れ的にはこんな感じかと思います(1の集計の場合)
Rangeで範囲を配列に取り込む。

VBA

1Dim r As Variant 2r = Range("範囲")

For文で行数分配列を回す。
各行から都道府県・性別を取得。
※都道府県は住所から都道府県名に変換するテーブルなどが必要です。
ハッシュテーブルで人数をカウント。
イメージ的にはこんな感じ。
Hash("都道府県名")("性別") = 人数
※ハッシュテーブルはScripting.Dictionaryなどでよいでしょう。

集計結果をシートに出力。

配列を使って速くなるのは、最初の取り込むところだけですね。
それもどれだけ速くなるかは実際にやってみないとわかりません。

2の集計も同じ要領でできます。

追記
ハッシュのサンプルを追記します。

VBA

1Dim sexstr(2) As String 2Dim all As Object 3Dim place As String 4Dim sex As Integer 5Dim cnt As Object 6Dim pkey As Variant 7Dim skey As Variant 8 9' 全体を管理する連想配列 10Set all = CreateObject("Scripting.Dictionary") 11 12' 集計対象 13place = "鹿児島県" 14sex = 1 15 16' 地名のキーが作成されているか 17If all.Exists(place) Then 18 ' 作成されているので性別毎のカウントアップ 19 Set cnt = all(place) 20 cnt(sex) = cnt(sex) + 1 21Else 22 ' 作成されていないので地名毎・性別毎のカウント用連想配列を作成 23 Set cnt = CreateObject("Scripting.Dictionary") 24 cnt(sex) = 1 25 Set all(place) = cnt 26End If 27 28' 出力 29sexstr(1) = "男" 30sexstr(2) = "女" 31For Each pkey In all 32 For Each skey In all(pkey) 33 Debug.Print pkey & " " & sexstr(skey) & " " & all(pkey)(skey) 34 Next 35Next 36

投稿2019/02/20 03:01

編集2019/02/21 00:06
ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/02/20 11:46 編集

コメントありがとうございます。 ハッシュテーブルというのがいまいち良く分かっていません。 Scripting.Dictionaryを使って今回のような ケースの場合はどのようにコードを書けば良いのでしょうか?
ttyp03

2019/02/21 00:07

基本的な部分だけ書いてみました。 参考にしてください。
退会済みユーザー

退会済みユーザー

2019/02/21 15:01

ありがとうございます! 参考にさせて頂きます!
guest

0

目的が二つの集計表を作ることであり、会員データシートに列を追加してもかまわなければ、私なら、集計表示用に性別数値を文字に置換えた列と都道府県名を切り出した列を加え、VBAを使わずにピボットテーブルで済ませます。

EXCEL

1性別 2=IF(C2=1,"男","女") 3都道府県(3文字目が「都道府県」のどれかなら3文字、そうでないなら4文字切り出す) 4=LEFT(F2,3+ISERROR(FIND(MID(F2,3,1),"都道府県")))

これを使い、ピボットテーブルを作成します。
データのある列を選択しておき、挿入リボンのピボットテーブルを選び、票を入れたいシートを選びOKします。

フィールドリストで表の集計項目と集計値にする列を選びます。
表1ならば行ラベルに都道府県と性別を、に適当な(全行にデータのある)列を入れます。

投稿2019/02/19 13:41

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/02/19 13:52

回答ありがとうございます! 私もVBAを使わなければピボットでやってしまうと思います^^ ただ急に配列で実装することになってしまいまして。トホホです(;´д`)トホホ
退会済みユーザー

退会済みユーザー

2019/02/19 15:55

ピボットテーブルはご存じだったのですね。失礼しました。 Buffer処理での高速処理といわれているのは、Cellへのアクセスに配列を使うと早くなるという理解(指示?)によるものだとしたら、それは誤解がある気がします。 大量(多数)のセルへの出力は、ループ処理でちまちま出力せずに、範囲で一気にやった方が速いということであって、配列を使えば何でも速いってことではありません。読み取り目的で表全体を配列に代入しても大した効果は期待できないと思います。 Office TANAKA:配列を使う http://officetanaka.net/excel/vba/speed/s11.htm 出力したい要件が、今回の質問の内容だけならば、大きくても94行*3列程度の大きさの表と2行2列の表になるだけですから、出力処理をループ処理で行っても誤差程度の差しか出ないでしょう。 もしかして、10万行の行処理毎にセルに出力していて遅いので、処理中の値を配列で保持するようにしたいと言うことなんでしょうか…。
退会済みユーザー

退会済みユーザー

2019/02/20 03:11

コメントありがとうございます。 >もしかして、10万行の行処理毎にセ>ルに出力していて遅いので、処理中>の値を配列で保持するようにしたい>と言うことなんでしょうか…。 はい。出力が遅いので、配列で値を保持したいとの事です。
退会済みユーザー

退会済みユーザー

2019/02/20 11:48

Scripting.Dictionaryを使って今回のような ケースの場合はどのようにコードを書けば良いのでしょうか? 連想配列というのがいまいち良く分かっていません。。。
退会済みユーザー

退会済みユーザー

2019/02/21 02:50

具体的なことはttyp03さんのサンプルにお任せするとして、連想配列の基本的なことだけ。 ふつうの配列は、各要素へのアクセスに番号を使いますが、連想配列では、番号の代わりにキーと呼ばれる任意の文字列を使用します。この文字列が同じなら同じ要素となるので、今回ならば都道府県名をキーにする事で、都道府県別の集計が簡単にできるという事になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問