質問するログイン新規登録
VBA

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

Q&A

解決済

1回答

638閲覧

Excel VBA csv読込→ランキング形式で出力

Ymnaik

総合スコア1

VBA

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

0グッド

0クリップ

投稿2022/10/24 03:23

0

0

前提

Excel VBAにてcsvファイルを1行ずつ読み込み、
その内容をまとめたものをエクセルに出力する処理を作成しております。

実現したいこと

出力されるエクセルには売上個数が多い順にランキング形式に並べたいです。
また、csvファイルを1行ずつ読み込んだ際に、
「果物」「地域」が一致する場合は「売上個数」と「値段」に加算するようにしたいです。

読取csvファイルの例、出力したいエクセルファイルのイメージは以下の通りです。

・csvファイル
|果物|地域|売上個数|値段|
|みかん|A地域|10|1000|
|みかん|A地域|20|2000|
|みかん|B地域|15|1500|
|りんご|A地域|8|800|
|りんご|A地域|9|900|
|メロン|C地域|1|3500|

・出力したいエクセルファイル
|順位|果物|地域|売上個数|値段|
|1|みかん|A地域|30|3000|
|2|りんご|A地域|17|1700|
|3|みかん|B地域|15|1500|
|4|メロン|C地域|1|3500|

発生している問題・エラーメッセージ

If文の複雑化の解消方法
別の記述方法模索中

該当のソースコード

Excel VBA Dim i As Long Dim csvData() As Variant 'csvファイルを1行ずつ読取 For i = 2 To Ubound(csvData, 1) '出力するエクセル側のA2(果物の最初の列)とB2(地域の最初の列)がブランクの場合 If sheet.Range("A2").Value = "" And sheet.Range("B2").Value = "" Then 'csvファイルの1行目のカラムを取得し、それぞれのセルに値を代入 ※順位1の行に値を代入 '果物 sheet.Range("A2").Value = csvData(i, 1) '地域 sheet.Range("B2").Value = csvData(i, 2) '売上個数 sheet.Range("C2").Value = csvData(i, 3) uVal = sheet.Range("C2").Value '値段 sheet.Range("D2").Value = csvData(i, 4) nVal = sheet.Range("D2").Value '出力するエクセル側のA2(果物の最初の列)とB2(地域の最初の列)とcsvファイルのカラム1(果物),2(地域)列目が一致した場合 ElseIf sheet.Range("A2").Value = csvData(i, 1) And sheet.Range("B2").Value = csvData(i, 2) Then '売上個数(果物名と地域名が一致した場合は売上個数を加算) ※順位1の行に値を代入 uVal = uVal + csvData(i, 3) sheet.Range("C2").Value = uVal '値段(果物名と地域名が一致した場合は値段を加算) nVal = nVal + csvData(i, 4) sheet.Range("D2").Value = nVal '出力するエクセル側のA2(果物の最初の列)とB2(地域の最初の列)とcsvファイルのカラム1(果物),2(地域)列目がどちらかが一致しない場合 ElseIf sheet.Range("A2").Value <> csvData(i, 1) Or sheet.Range("B2").Value <> csvData(i, 2) Then 'それぞれの項目を一つ下の行に代入 ※順位2の行に値を代入 '果物 sheet.Range("A3").Value = csvData(i, 1) '地域 sheet.Range("B3").Value = csvData(i, 2) '売上個数 sheet.Range("C3").Value = csvData(i, 3) '値段 sheet.Range("D3").Value = csvData(i, 4) ElseIf... (果物名または地域名が異なるたびにIf文作成が必要) EndIf

試したこと

上記のコードのようにIf文でエクセル側の値とcsvの値を比較して一致不一致を判断しておりましたが、
果物名または、地域名どちらかが異なる場合や両方とも異なる場合に都度If文を作成し、代入するセルを指定しなければなりません。

また、エクセルファイルの2行目以降の項目で、果物名と地域名が一致した際に加算する方法も不明です。
(上記例の2位りんごのような場合)

上記以外の方法でマクロ処理内で実行する方法はございますでしょうか。

ご回答をお願いいたします。

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

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

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

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

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

hatena19

2022/10/24 03:43

エクセルの機能を活かして、OpenBook でCSVファイルを読み込んで、あとは、関数や並べ替えの機能で簡単にできると思いますが、それではだめですか。あるいは、パワークエリでもできますね。 VBAのみでというなら、Dictionary を使うといいでしょう。
hatena19

2022/10/24 04:02

あと、「csvファイルを1行ずつ読み込み」とのことですが、 csvData という二次元配列にすでに読み込み済みということでしょうか。
sk.exe

2022/10/24 04:11

https://teratail.com/questions/8avgve7q3txv5f 上記のスレッドと全く同じ内容の質問をされているようですが、同じ人物が違うアカウントで投稿されているのでしょうか。
Ymnaik

2022/10/24 04:23

>hatena19さん ご回答いただきありがとうございます。 VBAのみで処理をさせたいので、Dictionaryについて調べてみます。 [あと、「csvファイルを1行ずつ読み込み」とのことですが、 csvData という二次元配列にすでに読み込み済みということでしょうか。] はい。csvファイルは既に読み込み済です。
Ymnaik

2022/10/24 04:24

>sk.exeさん はい。上記の通りです。 以前のアカウントにログインできなくなったため、別で質問させていただきました。
hatena19

2022/10/24 09:55

エクセルのバージョンはなんでしょうか。質問に追記してください。
Ymnaik

2022/10/24 10:03

バージョンは016を使用しております。
Ymnaik

2022/10/24 12:21

訂正します。 バージョン2016の誤りです。 失礼いたしました。
guest

回答1

0

ベストアンサー

下記でどうでしょう。

グループ毎の集計は、Dictionaryを使いました。
並べ替えと順位はエクセルの機能を使いました。

vba

1Sub Sample() 2 Dim csvData() As Variant 3 'csvファイルを1行ずつ読取 4 '略 5 6 Dim dic As Object 7 Set dic = CreateObject("Scripting.Dictionary") 8 9 Dim i As Long, sKey As String, Ary 10 For i = 2 To UBound(csvData, 1) 11 sKey = csvData(i, 1) & csvData(i, 2) 12 If dic.exists(sKey) Then 13 Ary = dic(sKey) 14 Ary(2) = Ary(2) + csvData(i, 3) 15 Ary(3) = Ary(3) + csvData(i, 4) 16 dic(sKey) = Ary 17 Else 18 dic(sKey) = Array(csvData(i, 1), csvData(i, 2), csvData(i, 3), csvData(i, 4)) 19 End If 20 Next 21 Range("G1").Resize(1, 4).Value = WorksheetFunction.Index(csvData, 1) 22 Range("G2").Resize(dic.Count, 4).Value = WorksheetFunction.Index(dic.Items, 0) 23 Range("F1").Value = "順位" 24 With Range("F1").CurrentRegion 25 .CurrentRegion.Sort Key1:=Range("I1"), Order1:=xlDescending, Header:=xlYes 26 Range("F2").Value = 1 27 Range("F2").AutoFill Destination:=Range("F2:F" & .Rows.Count), Type:=xlFillSeries 28 End With 29End Sub

投稿2022/10/24 13:02

hatena19

総合スコア34367

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

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

Ymnaik

2022/10/25 08:48

ありがとうございました。 こちら解決できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問