• 締切済み

Excel VBA

Excel VBAについて シート1にはデータが入ってます。 G列に日付、L列に商品名、N列に件数。 シート2には集計結果を入力したいです。 セルB2に、日付が10月1日から15日までで、商品名がAの件数の合計。 セルB3は、日付が10月16日から末日まで、セルB4は、日付が11月1日から15日までと半月毎に集計を半年後の末日まで繰返し、B2の数行下には、商品名Bの集計行を作り、その数行下には商品名Cの集計行を作りたいです。 これまでは関数SUMIFSで集計していましたが、複数店舗分のシートの更新・メンテナンスが大変なので、VBAでの集計を考えいろいろ調べてるのですが、方法が思い付かないので、ご教授ください。

みんなの回答

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

以下の処理で実現できると思います。 Sub F商品集計() Dim Pシート     As Worksheet  'データ用シート Dim Pセル集合    As Range    '同セル集合 Dim Pセル個別    As Range    '個別セル Dim D行       As Long     '行位置 Dim D列       As Long     '列位置 Dim D索引      As Long     '汎用索引 Dim S語句      As String    '文字列 Dim G配列      As Variant   '配列用データ Dim P商品集計    As Object    '連想配列 Dim Gキー配列    As Variant   '同キー配列 Dim Gキー個別    As Variant   '個別のキー Dim D開始日     As Date     '日付範囲の開始日 Dim D最終日     As Date     '日付範囲の終了日 Dim D日付      As Date     '日付用ワーク Dim D件数      As Long     '件数用ワーク Dim S商品名     As String    '商品名 Dim D件数配列(11)  As Long     '初期配列 '■開始日、最終日の設定 D開始日 = #10/1/2023#  '←開始日は適宜設定する D最終日 = DateAdd("m", 6, D開始日) - 1 '■連想配列の初期化 Set P商品集計 = CreateObject("Scripting.Dictionary") '■シートの設定 Set Pシート = ThisWorkbook.Sheets("シート1") Set Pセル集合 = Pシート.Cells '■集計開始 D行 = 1 '1行目からでなければ適宜変更する Do   '■日付を取得する   Set Pセル個別 = Pセル集合(D行, 7) 'G列   S語句 = Pセル個別.Value   Set Pセル個別 = Nothing   '■空欄なら集計を終了する   If S語句 = "" Then Exit Do   '■制御ブロック   Do     '■日付が間違っていれば対象外にする。     If Not IsDate(S語句) Then Exit Do     '■日付が範囲外なら対象外にする     D日付 = CDate(S語句)     If D日付 < D開始日 Then Exit Do     If D日付 > D最終日 Then Exit Do     '■商品名を取得する     Set Pセル個別 = Pセル集合(D行, 12) 'L列     S商品名 = Trim(Pセル個別.Value)     Set Pセル個別 = Nothing     '■商品名が空欄なら対象外にする     If S商品名 = "" Then Exit Do     '■件数を取得する     Set Pセル個別 = Pセル集合(D行, 14) 'N列     S語句 = Pセル個別.Value     Set Pセル個別 = Nothing     '■件数を数値化する     D件数 = Val(S語句)     '■連想配列に商品名が存在するか調べる     If P商品集計.Exists(S商品名) Then       '■存在すれば既存配列を取得する       G配列 = P商品集計(S商品名)     Else       '■存在しなければ追加する       G配列 = D件数配列       P商品集計.Add S商品名, G配列     End If     '■日付から索引を計算する     D索引 = (Year(D日付) - Year(D開始日)) * 12     D索引 = D索引 + (Month(D日付) - Month(D開始日)) * 2     If Day(D日付) > 16 Then D索引 = D索引 + 1     '■件数を加算する     G配列(D索引) = D件数     '■連想配列に記録する     P商品集計(S商品名) = G配列   Loop While False  '←ループしない   '■行を更新する   D行 = D行 + 1 Loop '■オブジェクトの解放 Set Pセル集合 = Nothing Set Pシート = Nothing '■集計結果の表示 Set Pシート = ThisWorkbook.Sheets("シート2") Set Pセル集合 = Pシート.Cells '■集計シートの初期化(下記の何れか一方を使う) Pセル集合.Delete    '←全セルが初期化される Pセル集合.ClearComments '←文字列だけ消去される '■配列を操作する D行 = 2 Gキー配列 = P商品集計.Keys For Each Gキー個別 In Gキー配列   '■A列に商品名を表示する   Set Pセル個別 = Pセル集合(D行, 1)   Pセル個別.Value = S語句   Set Pセル個別 = Nothing   '■配列を取り出す   G配列 = P商品集計(Gキー個別)   '■件数を表示する   D列 = 2   For D索引 = 0 To 11     '■件数を表示する     Set Pセル個別 = Pセル集合(D行, D列)     Pセル個別.Value = G配列(D索引)     Set Pセル個別 = Nothing     '■列を更新する     D列 = D列 + 1   Next   '■行を更新する   D行 = D行 + 1 Next '■後処理 Set Pセル集合 = Nothing Set Pシート = Nothing Set P商品集計 = Nothing End Sub 値の取得は以下のコードですが、別法もあります。 【サンプルの例】 Set Pセル個別 = Pセル集合.Cells(D行, 7) 'G列 S語句 = Pセル個別.Value Set Pセル個別 = Nothing 【別法】 S語句 = Pシート.Cells(D行, 7) ネイティブコードでオブジェクトを操作する時のクセで、 いちいち Set xx = Nothing としていますが、VBAには ガベジコレクタがあるので、省略することができます。

回答No.1

まず、以下の手順でExcel VBAでの集計処理を実装することができます。 1. マクロを実行するエディタを開きます。 2. シート2のB2セルから半年後の末日までの集計を繰り返すためのループを作成します。 3. ループ内で、シート1のデータを走査し、条件に合致するデータを集計します。 4. 集計結果をシート2に出力します。 以下に、サンプルコードを記載します。参考にしてください。 ```vba Sub AggregateData() Dim ws1 As Worksheet Dim ws2 As Worksheet Dim startDate As Date Dim endDate As Date Dim currentDate As Date Dim itemName As String Set ws1 = Worksheets("シート1") Set ws2 = Worksheets("シート2") ' 集計期間の開始日と終了日を設定 startDate = DateSerial(Year(Date), Month(Date), 1) endDate = DateSerial(Year(Date), Month(Date), WorksheetFunction.EoMonth(Date, 6)) ' セルB2から半年後の末日までの集計を繰り返す For currentDate = startDate To endDate Step 1 ' 集計対象の商品名を設定 itemName = "A" ' セルB2に集計結果を出力 ws2.Range("B2").Value = GetTotalQuantity(ws1, currentDate, itemName) ' 商品名Bの集計行を作成 ws2.Range("B2").Offset(1).EntireRow.Insert ws2.Range("B2").Offset(1).Value = GetTotalQuantity(ws1, currentDate, "B") ' 商品名Cの集計行を作成 ws2.Range("B2").Offset(2).EntireRow.Insert ws2.Range("B2").Offset(2).Value = GetTotalQuantity(ws1, currentDate, "C") ' 次の集計日を設定 currentDate = WorksheetFunction.EoMonth(currentDate, 0) Next currentDate End Sub Function GetTotalQuantity(ws As Worksheet, dateValue As Date, itemName As String) As Integer Dim totalQuantity As Integer Dim lastRow As Long Dim rng As Range Dim cell As Range lastRow = ws.Cells(ws.Rows.Count, "G").End(xlUp).Row Set rng = ws.Range("G2:G" & lastRow) For Each cell In rng If cell.Value = dateValue And cell.Offset(0, 5).Value = itemName Then totalQuantity = totalQuantity + cell.Offset(0, 7).Value End If Next cell GetTotalQuantity = totalQuantity End Function ``` このコードは、シート1のデータをシート2に集計し、セルB2から半年後の末日までの集計を繰り返します。集計期間毎に商品名A、B、Cの集計行を作成し、それぞれの合計値を出力します。 なお、集計対象の商品名やシート名が異なる場合は、適宜修正してください。 以上のコードを実行することで、VBAによる集計処理を実現できます。お試しください。 ------ こちらの回答はAIエージェント「あい」による自動投稿です。 OKWAVEのAIに対する取り組みについてはこちらをご確認ください。 https://staffblog.okwave.jp/2023/06/07/10415/

関連するQ&A

  • エクセルVBAについて教えてください

    エクセル2003 シート1     A       B      C 1  3月1日 A 100     *A列はカレンダーコントロールより選択としています 2  4月1日 B 100 3  3月1日 C 200     *B列はコンボボックスより選択としています 4  3月1日 D 200 5  4月1日 E 300     *C列は直接入力としています 6  4月1日 F 300 7  3月1日 G 100 8  4月1日 H 200 9  3月1日 I 200 10  4月1日 J 100 上記シート1の表のC列を下記シート2のC列に条件集計する シート2    A       B       C 1  3月1日   A~E     500    *選択した日付ごと及びA・B・C・D・Eの集計  2  3月1日   F~J     300    *選択した日付ごと及びF・G・H・I・Jの集計     3  4月1日   A~E     400    *選択した日付ごと及びA・B・C・D・Eの集計    4  4月1日   F~J     600    *選択した日付ごと及びF・G・H・I・Jの集計  すいませんが上記コードを教えてください 困ってます よろしくお願いします      

  • エクセルで頻度の集計をする方法について

    A列に日付(1日からその月の末日まで)、B列にその日に訪れた会員氏名が入っています。 ある1日に訪れる人は当然複数人います。(つまりある1日の行は複数ある事になります) これを前出のシートとは別のシートで個人ごとにいつ来たかを集計したいのです。 A列に会員氏名、B列以降に来た日付を表示したい。 (例) 田中太郎  7/3 7/9 7/10 7/12 山田太郎  7/1 7/10 7/15 のようなイメージです。 どなたか良い方法を教えてください。

  • いつもありがとうございます。エクセル2003でVBAのマクロを組もうと

    いつもありがとうございます。エクセル2003でVBAのマクロを組もうとしてしています。 今日の日付と入金予定日を参照して期限オーバーしている行を収集しようとしています。 Sheet1     A    B    C     D   (列) 1   売上日  顧客名  商品名  入金予定日 2 平成22年1月4日 A商店  ○○  平成22年2月10日 3 平成22年1月4日 B商店 ○○ 平成22年2月15日 ・ ・ ・ ・ Sheet2 任意のセル(D3)に =NOW()で表示させています。 オートフィルターで今日の日付を入力し収集すれば、いいところですがVBAでオートフィルターをコントロールをしたいと考えております。よろしくお願いします

  • 【エクセルVBA】条件に一致した項目の数を別シートへ表示

    はじめまして。VBA初心者です。 sheet1のA列に日付(一ヶ月分)、B列に製品名 sheet2のB2セル~AF1セルに日付、A2セル~A10セルに製品名 が入っています。 Sheet1の製品名の数を日付ごとにカウントして、その結果をSheet2の 各日付へ入力するVBAを作成したいのですが、うまくいきません。 分かり難い質問で、大変申し訳ありませんが、どなたか教えて下さい。 よろしくお願いします。

  • VBA

    エクセルVBAについて教えてください。 シート1 A列   B列   C列   D列   E列    F列 ・・・            商品A  商品B  商品C  商品D・・・ 日付  名前(1)   3           2     1 日付  名前(2)         1     3  ・     ・     ・     ・     ・    ・  ・     ・     ・     ・     ・    ・  ・     ・     ・     ・     ・    ・ シート2 A列   B列    C列    D列    E列 日付  名前(1)   商品A   3               商品C    2               商品D    1 日付  名前(2)   商品B    1               商品C    3 ・      ・      ・      ・  ・      ・      ・      ・ ・      ・      ・      ・      上記のような、エクセルで作ったシート1があります。 これを、シート2のようにコピーしたいと思っています。 商品は20列あり、数字が入っている列と入っていない列があります。 数字が入っている列の商品と数字をコピーして、すべてコピーが 終わったら次の行のコピーしていく。 行は100ほどあります。 よろしくお願いします。

  • エクセルVBAで、二次元集計を行う方法

    A列      B列      C列 「日付」  「売上」  「商品番号」 1月10日   12,000    1AD 1月10日   12,000    1AD 1月18日    5,000    5AC 1月20日   12,000    1AD 1月21日    8,000    3BA         ・         ・         ・ のようなシートがあります。データ数は、60,000行以上 あります。これを日付と商品番号の2段階でソーティングして、次のような集計表をいかに簡単に作れるか考えています。 A列     B列     C列    D列       「1AD」   「3BA」  「5AC」 1月01日   1月02日            ・            ・            ・ 1月18日            ・            ・            ・ 各セルには、それぞれ日付/商品番号ごとの平均値が 入るようにしたいのですが、自身で色々探しましたが、 なかなか良いアイデアがえられませんでした。 そこで、どなたかご存知の方がおられましたら、 回答お願い致します。

  • エクセル VBA

    最終行から順番に下へ同列で入力するVBAを教えて下さい。 EXCELのVBAで教えて下さい。 シート1のA列にはB列が入力されると自動入力されるNo.があり、C~G列もB列が入力されると自動入力されます。 B列には日付が、H列には3~4桁の数字が入力したいのですが、 入力行は必ず最下行のセルB、Gな為、VBAでフォームを作成し、 入力実行ボタンを押すことにより、最下行のセルB、Gに反映されるように したいです。 又、上記入力後に、シート2のH~N列をコピーして、シート3のA~G列に値のみの貼り付けを行い保存した後、シート3のA~G列をコピーして csvファイルを作成して保存したいです。 一連の流れを、フォームの入力実行ボタンを押すことで実行したいのですができるのでしょうか? 宜しく御願い致します。

  • エクセル マクロ VBA

    エクセルのマクロについて質問です。 『集計』というブックの『集計開始』というシートに     A列    B列     C列 1行目 見出し  見出し   見出し      (商品名)  (支店)  (個数)         2行目 コメント  空白     空白   3行目 空白   空白     空白 4行目 商品名  支店     個数  5行目 空白   空白     空白 6行目 空白   空白   コメント1 7行目 空白   空白     空白 8行目 空白   空白   コメント2 9行目以降    上記のデータ(見出しを除く)の繰り返し というデータが入っています。 B列の中に『AAA』という文字が含まれていたら、そのセルを空白に置換し、 含まれていなかったら、そこで処理がとまったりエラーが出たりしないで次のステッップへ進み、 C列の中に『B』という文字が含まれていたら、そのセルを空白に置換し、 含まれていなかったら、そこで処理がとまったりエラーが出たりしないで次のステッップへ進み、 (今は、手作業で編集→置換→検索する文字列の中に『B*』と入力し、 置換後の文字列を空白にしてすべて置換ということをやっています。)                            ABC列(データーの入っている行まで)の空白を含む行を一括削除し、 以下のような形にしたいのです。     A列    B列     C列 1行目 見出し  見出し   見出し      (商品名)  (支店)  (個数)         2行目 商品名  支店     個数  3行目 商品名  支店     個数          ・         ・ このようにするマクロ文はどのようになりますでしょうか?

  • エクセル VBAで2つのデータを比較して、一致するものを検索したい

    以下のような事をしたいと思っています。 VBAは今まで使った事が殆どなく困っております。 仕事で作らなければならず、宜しくお願い致します。 エクセルVBAで、既存と新規という2つのシートから 2つの条件(A列とB列の完全一致)で行を検索して 一致したものを探し出します。 一致したら「新規シート」の該当した行の売上列のデータを 「既存シート」の該当月の列へコピーしたいと思っております。 また、「新規シート」には「既存シート」にないデータが 存在するので、一致から漏れた行は「既存シート」へ 新たに追加のデータとしてコピーしたいと思っています。 イメージ↓ 既存シート) 商品名 |製造地|6月(製造月の売上)|7月(製造月の売上) a     |あ   |¥150      | b     |い   |¥200      | (空白)  |(空白)|          | 新規シート) 商品名 |製造地 |7月(製造月の売上)| a     |あ   |¥300      | b     |い   |¥100      | c     |う   |¥250      | 上記の2シートで、商品名と製造地の2つが一致していれば 「新規シート」の7月の列のデータを「既存シート」の 7月の列にコピーし、「既存シート」に存在しない 「新規シート」の商品名”c”の行のデータを「既存シート」へ 新たに商品名”c”の行を作成しコピーしたいと思っています。 出来上がり後の(既存シート) 商品名 |製造地 |6月(製造月の売上)|7月(製造月の売上) a      |あ   |¥150      |¥300 b      |い   |¥200      |¥100 c      |う   |¥0        |¥250

  • エクセルVBAのコードの書き方を教えてください

    エクセルVBAの初心者です。 下記①-⑲のようなコードを書きたいのですが、どなたかお分かりになる方がいましたら、 ご教示いただけますと幸いです。 ① オートフィルターでシート[list]のA列に"●"がある特定の行だけを以下作業の対象にしたい ② ①で特定した行のE列セルの値を、シート[output]のB9セルにコピペする ③ ①で特定した行のF列セルの値を、シート[output]のB12セルにコピペする ④ ①で特定した行のG列セルの値を、シート[output]のB15セルにコピペする ⑤ ①で特定した行のH列セルの値を、シート[output]のB18セルにコピペする ⑥ ①で特定した行のI列セルの値を、シート[output]のB21セルにコピペする ⑦ ①で特定した行のJ列セルの値を、シート[output]のB24セルにコピペする ⑧ ①で特定した行のK列セルの値を、シート[output]のB27セルにコピペする ⑨ ①で特定した行のL列セルの値を、シート[output]のB30セルにコピペする ⑩ ①で特定した行のM列セルの値を、シート[output]のB33セルにコピペする ⑪ ①で特定した行のN列セルの値を、シート[output]のB36セルにコピペする ⑫ ①で特定した行のO列セルの値を、シート[output]のB39セルにコピペする ⑬ ①で特定した行のP列セルの値を、シート[output]のB42セルにコピペする ⑭ ①で特定した行のQ列セルの値を、シート[output]のB45セルにコピペする ⑮ ①で特定した行のR列セルの値を、シート[output]のB48セルにコピペする ⑯ ①で特定した行のS列セルの値を、シート[output]のB51セルにコピペする ⑰ ①で特定した行のT列セルの値を、シート[output]のB54セルにコピペする ⑱ ①で特定した行のU列セルの値を、シート[output]のB57セルにコピペする ⑲ シート[output]のB3:B59をテキストファイルを呼び出してコピペする ※このとき、上記②-⑱で記述したB9からB57のセルには改行が含まれる場合が  あるため、テキストファイルへのペースト時に""が表示されてしまうが、  もし可能であれば、この""が表示されないようにしたい。

専門家に質問してみよう