• ベストアンサー

VBAのマクロで、複数行を1行に集計

お世話になります。VBA初心者です。 下記のような表があった場合、請求書番号が同じものをVBAで1行に集計するにはどうしたらよろしいのでしょうか? 請求書No.|顧客名|摘要|金額 111111  |鈴木 | A |100 111111 |鈴木 | S |160 222222 |佐藤 | F |500 555555 |山田 | A |150 555555 |山田 | D |200 888888 |鈴木 | S |160  ↓下記のように集計 請求書No.|顧客名|摘要|金額 111111 |鈴木 | A |260 222222 |佐藤 | F |500 555555 |山田 | A |350 888888 |鈴木 | S |160 摘要は各請求書番号の最初の行を使います。重複は2行とは限りません。また、最終的に何枚の請求書があるのかも計算させたいのです。ただしこれはどこかに関数"=counta()"を使えばVBAでなくても出来るのですが。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.5

#4の回答者です。 >請求書No.はA列には無くまだ確定では何いのですがH列以降になる予定です。 それは、 Set myData = sh1.Range("A1").CurrentRegion ここで決めていきます。CurrentRegion ですと、地続きの範囲ということになって、A列から含まれてしまいますので、 Set myData = sh1.Range("H1", sh1.Range("H65536").End(xlUp).Offset( ,4)) というスタイルになります。 Offset( ,4) というのは、H列を含めて右へ4列 という範囲を示します。 sh1.Range("H65536").End(xlUp) というのは、H列の一番下のデータという意味です。 しかし、統合することは可能でも、出力のレイアウト自体が決まっていかないと、今のコードから、そんなに簡単に直せるとは言いにくいですね。 >金額はH列より後の列に入ります(予定ではI列)。 H列を基準に統合すると、現在のマクロですと、その隣の列に、集計の金額が出てきてしまいます。 また、数式は、以下の部分を直せばよいのですが……。 > sh2.Range(.Cells(2, 2), .Cells(.Rows.Count, 3)).FormulaLocal = _ >   "=VLOOKUP($A2," & sh1.Name & "!" & myData.Address(1, 1) & ",COLUMN(B1),0)" >  .Value = .Value =VLOOKUP($A2,Sheet1!$H$1:$K$7,COLUMN(C1),0) 例えば、こんな風にするには、  sh2.Range(.Cells(2, 3), .Cells(.Rows.Count, 4)).FormulaLocal = _    "=VLOOKUP($A2," & sh1.Name & "!" & myData.Address(1, 1) & ",COLUMN(C1),0)"   .Value = .Value となります。 それを自由に出力列を変更できるようにするには、全面的にマクロコードを変更しなくてはならないような気がします。 今の段階では、例えば、こういうスタイルなら、 請求書No.  金額  顧客名  摘要 こういうスタイルで出てきてしまうことになってしまいます。

TENSAW
質問者

お礼

いつも本当にありがとうございます。 細かい丁寧な説明なので本当に助かっております。 結局、請求書番号をA列に持ってきて、集計をした後に前回教わったマクロを使い、さらに新しいシートに並べ替えることにしました。 今後ともよろしくお願いいたします。

その他の回答 (4)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんばんは。 例えば、集計をSheet2 に出すように作ってみました。 これは、フィルタオプションと統合を組み合わせれば簡単に出来ます。 他の方法もありますが、記録マクロの延長の方法です。ただ、空白部分の補完の方法などは、多少の技術は必要になってきます。 '標準モジュール Sub Test1() Dim sh1 As Worksheet Dim sh2 As Worksheet Dim myData As Range Dim tmpData As Range Set sh1 = Worksheets("Sheet1") Set sh2 = Worksheets("Sheet2") Set myData = sh1.Range("A1").CurrentRegion '出力する場所を削除しておく sh2.Range("A1").CurrentRegion.ClearContents 'フィルタオプションで、1列目のユニーク番号を取り出す   myData.Columns(1).AdvancedFilter _   Action:=xlFilterCopy, _   CopyToRange:=sh1.Range("AA1"), _   Unique:=True '出力場所 Set tmpData = sh1.Range("AA1").CurrentRegion '統合 sh2.Range("A1").Consolidate _     Array(sh1.Name & "!" & myData.Address(1, 1, xlR1C1), _     sh1.Name & "!" & tmpData.Address(1, 1, xlR1C1)), _     xlSum, False, True, False 'VLOOKUPで、データの補完  myData.Rows(1).Copy sh2.Range("A1")  With sh2.Range("A2").CurrentRegion   sh2.Range(.Cells(2, 2), .Cells(.Rows.Count, 3)).FormulaLocal = _    "=VLOOKUP($A2," & sh1.Name & "!" & myData.Address(1, 1) & ",COLUMN(B1),0)"   .Value = .Value '件数の出力   .Cells(1, .Columns.Count + 1).Value = "=""件数:""&COUNT(" & .Columns(4).Address(0, 0) & ")"  End With  tmpData.ClearContents  Set myData = Nothing  Set tmpData = Nothing  Set sh1 = Nothing  Set sh2 = Nothing End Sub

TENSAW
質問者

補足

実は例としてあげたものと実際のものとでは少し違いがありまして、請求書No.はA列には無くまだ確定では何いのですがH列以降になる予定です。A~Gまでにはその他の数値・記述(日付やメモ書き)が入り、集計したい金額はH列より後の列に入ります(予定ではI列)。 このような場合はどこをどう変えればよろしいのでしょうか? 毎回すみませんが、よろしくお願いいたします。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

VBAで (1)WorkSheetFunction.SUMIFを使う (2)総なめで11111(など)を探して足しこむ (3)請求書NOでソートして、並びがブレークするまで足しこむ (4)Find、FindNextで111111(など)を探して足しこむ。 人間が電卓で目で見て足す場合はこれでしょう。 などあるが(1)、(2)、(4)は請求書Noのユニークな(重複の無い)一覧がシート上に無いと、出てきた都度集計していると複数回同じこと(111111を集計)をしてしまう。 結局(2)が優れていると思う。ただデータ順序を崩すたくない場合は、作業シートにコピーしてそちらでやるか、初めに連番を振っておき、当初の並ぶ順にソートで戻す必要があるが。 (3)のロジックは、前行の請求書番号を変数に記録し、常に前行と現在行を比較し、 ・変わらない同じとき、合計変数に足しこみーー>次行へ ・変わったとき、前の行のA-C列を書き出しセルに代入(A)        合計の書き出し(B)        書き出し行を+1(下行を指す)        合計に現在行の計数足しこみ(0にして現在行の計数足しこみ)        前行変数に現在行データを書く        -->次行へ 終わり行の後だけ、特別に(A)(B)を行う。 上記の意味が読んでわかったらすごいが。

TENSAW
質問者

お礼

早速のご回答に感謝いたします。 おっしゃるとおり私にはもう少し勉強が必要なようです。 現在の私には難しすぎますので、知識がつきましたら再度読み返させていただきます。 ありがとうございました。

  • Golmore
  • ベストアンサー率33% (1/3)
回答No.2

「ツール」→「統合」機能を使う方法もあります。 例)元データがA列~D列に記述されていると過程して、VBAで書くとこんな感じになります。 Range("F1").Consolidate Sources:="C1:C4", Function:=xlSum, LeftColumn:=True の1行を実行しただけで、請求番号ごとに集計された結果が、F列~I列 に出力されます。 ※顧客名・摘要列は無視されるので、G~H列は空白列になります。 あとは、CountIfで個数・VLookupで顧客名引っ張ってくればおおよそ 完成ですね。マクロでセル内に関数を書くのでもいいですし。

TENSAW
質問者

お礼

まず、びっくりしております。 まさにやりたいことが、こんなにシンプルに出来るとは思っても降りませんでした。サンプルデータで試してみましたが、本当にびっくりしました。 ただし、コラムが上記のサンプルと違い必要なデータがA列から4つ綺麗に並んでおりません。また、これ以外のマクロも色々と組んでおり、すこしフォーマットも考え直さないといけません。 現状ではこのまま使わせていただくことは出来ないのですが、このシンプルさはとても魅力に思っております。私はド素人なのでゴチャゴチャとくっつけては切捨ての繰り返しのためとても複雑なものを作りがちです。とっても参考になりました。本当にありがとうございました。

  • kuma3f
  • ベストアンサー率63% (28/44)
回答No.1

思われていることと違っていましたらすみませんが参考までに試してみてください。 Altキー押しながらF8キーを押します。  ↓ マクロのダイアログが表示されたらマクロ名に自由に名前を入力してください。(例:集計)  ↓ 名前を入力しましたら、「作成」をクリック  ↓ Microsoft Visual Basicの画面が開きますのでSub 集計()の下に次のコードをコピーして貼り付けてください。 Dim シート1カウント, 集計シートカウント, シート1件数, 金額, スイッチ As Long Dim シート名, 請求NO, 顧客名, 摘要 As String シート名 = ActiveSheet.Name スイッチ = 0 On Error GoTo skip1 Sheets("集計シート").Select スイッチ = 1 skip1: If スイッチ = 0 Then '集計シートが無かったら作成する Sheets.Add ActiveWorkbook.ActiveSheet.Name = "集計シート" End If Sheets("集計シート").Cells.ClearContents '集計 Sheets(シート名).Select シート1件数 = Application.WorksheetFunction.CountA(Worksheets(シート名).Range("A1:A65536")) シート1カウント = 1 集計シートカウント = 1 請求NO = Sheets(シート名).Cells(シート1カウント, 1) 顧客名 = Sheets(シート名).Cells(シート1カウント, 2) 摘要 = Sheets(シート名).Cells(シート1カウント, 3) 金額 = Sheets(シート名).Cells(シート1カウント, 4) シート1カウント = シート1カウント + 1 Do If 請求NO = Sheets(シート名).Cells(シート1カウント, 1) Then 金額 = 金額 + Sheets(シート名).Cells(シート1カウント, 4) Else Sheets("集計シート").Cells(集計シートカウント, 1) = 請求NO Sheets("集計シート").Cells(集計シートカウント, 2) = 顧客名 Sheets("集計シート").Cells(集計シートカウント, 3) = 摘要 Sheets("集計シート").Cells(集計シートカウント, 4) = 金額 集計シートカウント = 集計シートカウント + 1 請求NO = Sheets(シート名).Cells(シート1カウント, 1) 顧客名 = Sheets(シート名).Cells(シート1カウント, 2) 摘要 = Sheets(シート名).Cells(シート1カウント, 3) 金額 = Sheets(シート名).Cells(シート1カウント, 4) End If シート1カウント = シート1カウント + 1 Loop Until シート1カウント > シート1件数 Sheets("集計シート").Cells(集計シートカウント, 1) = 請求NO Sheets("集計シート").Cells(集計シートカウント, 2) = 顧客名 Sheets("集計シート").Cells(集計シートカウント, 3) = 摘要 Sheets("集計シート").Cells(集計シートカウント, 4) = 金額 集計シートカウント = 集計シートカウント + 1 Sheets("集計シート").Cells(集計シートカウント, 2) = "請求書枚数 = " & 集計シートカウント - 2 & "枚" Sheets("集計シート").Select MsgBox "集計しました。 請求書枚数 = " & 集計シートカウント - 2 & "枚です。" '****コピー貼り付けはここまで **** Microsoft Visual Basicの画面を×で閉じます。 使い方は、Altキー押しながらF8キーを押します。 マクロのダイアログが表示されるので先ほど名前を付けたマクロを選択して「実行」をクリック。 (選択されている状態でしたら、そのままEnterキーで実行されます。) 集計シートに結果が集計されていると思います。

TENSAW
質問者

お礼

>思われていることと違っていましたら… まさにこれがやりたかったことです。ありがとうございました。 色々な方法があるのですね、丁寧な補足説明付ですので色々とアレンジが出来そうです。 また、それぞれのマクロも他で流用できそうなものがございますので、ぜひ使わせていただきます。 本当にありがとうございました。

関連するQ&A

  • 集計マクロ

    こんにちは。 早速ですが、例えばこんなカンジです。 [元データ(Sheet1)] [1] 鈴木| 佐藤| 山田|・・・ [2] 茶 | 水 |    | [3] 魚 |    | 酒 | [4]    | 肉 | 茶 | [5] 肉 | 茶 | 魚 | 上記のようなデータから↓↓↓ 1.行ごとに種類別に並べ替え 2.'=count(A2:D2)のような種類別の行集計列([数])を追加 3.[数]を基準に降順に並べ替え ↓↓↓ [集計データ(Sheet2)] [1] 鈴木| 佐藤| 山田|・・・| 数 [2] 茶 | 茶 | 茶 |・・・| 3 [3] 肉 | 肉 |    |・・・| 2 [4] 魚 |    | 魚 |・・・| 2 [5]    | 水 |    |・・・| 1 [6]    |    | 酒 |・・・| 1 お解かりいただけますでしょうか(・_・;)? 今までは作業列(商品名)を挿入し、[VLOOKUP]→[COUNT]→値貼付→並べ替え→不要な商品名(行・列)を削除していましたが、度々では面倒に思い、マクロを組もうと試みました。 ですが、まだまだマクロ勉強中の私自身の頭が整理しきれず、行き詰ってしまいました。 アドバイスでも結構です。お力をお貸しください。 よろしくお願いいたします。

  • エクセル・マクロで、請求書番号ごとに集計する方法

    請求書毎に集計した表をマクロで作りたいと思っています。 例えば、 取引先  請求書No  商品   売上 山田    0001   りんご  100   山田    0001   なし   200   山田    0001   みかん  300   鈴木    0002   りんご  100 鈴木    0002   バナナ  200 山田    0003   みかん  100   というデータがあるとします。 その場合 取引先  請求書No  売上 山田    0001   600 鈴木    0002   300 山田    0003   100 というように、請求書毎に、売上の合計と取引先名などが分かるように集計した表を作成したいと思っています。 請求書番号は、基本的には連番ですが、すこし飛ぶ可能性がありますし、 毎月、どのくらいの番号まで付番するのかははっきりしません。 また、請求書毎に、どれだけの種類の製品を出荷するのか(請求書毎に、何行になるのか)も不確定です。 ピポットですと、取引先名が表示されません。 また、所定の表を作って自動集計するというよりは、マクロで請求書毎に集計したほうが良いかと思っています。 基本的なコードや考え方を教えて頂けないでしょうか。 宜しくお願い致します。

  • エクセル アンケート集計について

    回答者 問 回答 鈴木 Q1 F 鈴木 Q2 50 鈴木 Q3 東北 山田 Q1 M 山田 Q2 30 山田 Q3 関東 佐藤 Q1 F 佐藤 Q2 40 佐藤 Q3 中国 ↓      Q1  Q2   Q3 鈴木   F   50   東北 山田   M   30   関東 佐藤   F   40   中国 このように集計したいです。 どのようにしたら簡単にできるのでしょうか?? お分かりの方おしえてください~~

  • データの集計についてVBAマクロを組んでください。

    下記のようにA列に金額 B列に欄No.があります。VBAマクロで集計した結果を出すマクロの記述の仕方を教えてください。 金額  欄No. 232     1 1005    1 812     2 425     2 193     1

  • 桐の集計(集計行設定のこと)について教えて下さい

    こんにちは。 Winで桐8を使ってます。 集計(集計行)のことを教えて下さい。 データを、小計・中計・大計と行集計をかけました。 このときの中計の集計行に、小計の行数を入れることは可能でしょうか? 例)顧客番号、顧客種別、月、金額・・・・ のように同じ顧客が月別に、複数回入金します。 (入金されたデータは月別で複数行になります。) 小計は「顧客毎」に集計。 中計は「顧客種別毎」に集計。 このときに、中計の欄に、顧客種別毎の顧客数の実数(小計の行数)を入れたいのです。 今の私の知恵では、データ行の個数が出てしまい、同一の顧客番号が複数行あると複数でカウントしてしまうのです。 上手く説明できず恐縮ですが、ご教授くださると有り難いです。 よろしくお願いします。

  • エクセルで自動入力をマクロで・・・(No.1798323の応用編)

    応用が効かなくて申し訳ありません。 1798323で素敵なご回答をいただいたのですが、 状況が進展して変わってくるとVBAの書き換えがわからなくなりました。もう一度教えてください。 ※変更点は、入力元がAI列、『入力先をQ~V列に限定』したい点です。   Q    R    S    T   U V・・ AI 1 田中 鈴木 佐藤          山田 2 鈴木 山田              海岡 3 田中 佐藤              佐藤 というような表があり、T1に「山田」、S2「海岡」と、その行に関してAI列に新規の名前が入力されたときに自動入力することをVBAでどのように書けばよいのか、ご教授お願いいたします。 尚、3行目には「佐藤」さんがすでいるので入力不要です。 よろしくお願いします。

  • 重複するidをデータごとにまとめるvbaのコード

    excel vbaで次のようなコードを作りたいです。 シート1に元データが4000件ほどあります。 シート2に、シート1のidが同じものを、3行ずつ横に表示したいです。 idと名前は1度のみ、それ以降は都道府県名と数字のみ表示します。 同じidを持つものが3行に満たないのであれば、改行します。 同じidを持つものが3行以上ある場合は、3行ごとに改行します。 1 佐藤 東京 1000 1 佐藤 千葉 2100 1 佐藤 青森 1300 2 鈴木 東京 5600 2 鈴木 千葉 3500 3 山田 三重 2910 3 山田 長野 3820 3 山田 山口 8760 3 山田 沖縄 6560 4 : ↓ 1 佐藤 東京 1000 千葉 2100 青森 1300 2 鈴木 東京 5600 千葉 3500 3 山田 三重 2910 長野 3820 山口 8760 3 山田 沖縄 6560 4 : どなたかこのような動作を行うvbaのコードを教えてください。 よろしくお願いします。

  • 複数のシートのセル内容をひとつにまとめたい

    複数のシートのセル内容をひとつにまとめたいと思っています。 Sheet1        Sheet2      Sheet3 1 山田 ¥100  1 山田 ¥80  3 鈴木 ¥80 2 佐藤 ¥130  2 佐藤 ¥55  4 田中 ¥150 3 鈴木 ¥110  4 田中 ¥60 こんなデータを Sheet4 1 山田 2 佐藤 3 鈴木 4 田中 とまとめたいんです。 金額は必要ないので、番号と名前だけをまとめたいんです。 どうすれば良いか、教えてください。 よろしくお願いします。

  • エクセルの表の集計について

    エクセルの『集計』や『ピボットテーブル』を使わずに、関数でやる方法があれば教えてください。 1 名前  住所  りんご  みかん 2 山田 東京   1    3 3 鈴木 神奈川  3   8 4 佐藤 埼玉   4    10 5 山田 東京   5    5 6 佐藤 埼玉   6    5 とエクセルに表があるとします。 (7行目以降はデータが追加されるとします。) 別シートに下記のように名前ごとにりんご・みかんの数の合計を表に反映するようにしたいのです。 1 名前 住所  りんご  みかん 2 山田 東京   6   8 3 鈴木 神奈川  3  8 4 佐藤 埼玉   10  15 説明不足のところがありましたら補足いたしますので、お願いいたします。

  • エクセル 複数行にまたがっているデーターを一つの行

    以前に似たようなVBAの質問を元にさらにやりたいVBAがあるのですが、 (前の質問者のURL:http://okwave.jp/qa/q4955096.html)       A列  B列   C列   D列   E列 ~ R列 1行目  佐藤 北海道 りんご S 100 105 2行目  佐藤 北海道 ばなな M 100 105   3行目 伊藤  東京  いちご S 100 105 4行目  伊藤  東京  ばなな M 100 105 上記のようなデーターがあります。これを2行目と4行目を削除し下記のようにしたいのですが       A列  B列      C列      C列 1行目  佐藤 北海道  りんご,ばなな  S,M 2行目  伊藤  東京   いちご,ばなな  S,M A列とB列とE列~R列のデーターが同じでC列,D列,のデータが異なる場合、上記のように一行にまとめたいのです。関数やVBAで上記の処理を出来る方法がありますでしょうか。 

専門家に質問してみよう