Excel集計表作成マクロの悩みと解決方法

このQ&Aのポイント
  • エクセルの集計表を作成するマクロの作成方法に悩んでいます。日付ごとにシート別に分かれたデータを集めるため、新しいシートを作成し、日付ごとのデータを下方向に集計したいと考えています。現在、試しているVBAコードでは、全ての情報がコピーされてしまい、うまく集計できません。しかし、VBAの理解が浅いため、改善方法がわかりません。
  • エクセルの集計表を作成するマクロで悩んでいます。データが日付ごとにシート別に分かれているため、新しいシートに集計する方法を模索しています。現在のVBAコードでは、全ての情報をコピーしてしまい、正しい集計ができません。VBAを始めたばかりで理解が浅いため、改善策が分かりません。
  • エクセルで集計表を作成するマクロで悩んでいます。日付ごとにシート別に分かれたデータを新しいシートに集めるためのVBAを作成中ですが、全ての情報がコピーされてしまい、うまく集計できません。VBAの理解が不足しており、改善策を教えていただければと思います。
回答を見る
  • ベストアンサー

エクセルで集計表を作成するマクロで悩んでいます。

エクセルで集計表を作成するマクロで悩んでいます。 日付ごとにシート別に分かれたデータを「集計表」として新しいシートに集めたいと思っています。 ●元データに関して  1行目は空欄  2行目は表の名前  3行目は日付  4~7行目は番号・数量などの項目  8行目から多い場合で50行目くらいまで番号ごとの情報が並んでいます。  AC列まで並んでいます。・・・・・・●画像左上が元データ ●このファイルから、(1)集計表という新しいシートを作成して(2)そのファイルに日付ごとの データが下方向に集まるように集計したいと思っています。 そこで、次のVBAを作成しました。 Sub 集計表() Dim ws As Worksheet For Each ws In Worksheets ’AD列にシート名を入れる ws.Range("AD1:AD100").Value = ws.Name Next ws Dim newSh As String Dim Sh As Worksheet, myFlag As Boolean newSh = "集計表" myFlag = False For Each Sh In ThisWorkbook.Worksheets If Sh.Name = newSh Then myFlag = True '----全データシートのデータをクリアし、先頭へ移動します Worksheets(newSh).Cells.ClearContents Worksheets(newSh).Move before:=Sheets(1) Exit For End If Next Sh '----全データシートを先頭へ追加します If myFlag = False Then ActiveWorkbook.Worksheets.Add(before:=Worksheets(1)).Name = newSh End If Worksheets(2).Select Rows("1:1").Select Application.CutCopyMode = False Selection.Copy Sheets("集計表").Select ActiveSheet.Paste Dim i As Integer Dim lRow As Long, lCol As Long, lRow2 As Long Application.ScreenUpdating = False '----列見出しをコピーします Worksheets(2).Range("1:1").Copy Worksheets(1).Range("A1") For i = 2 To Worksheets.Count With Worksheets(i) lRow = .Cells(Rows.Count, 1).End(xlUp).Row lCol = .Cells(1, Columns.Count).End(xlToLeft).Column '----シートのデータが8行以上の場合にコピーします If lRow >= 8 Then lRow2 = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1 .Activate .Range(Cells(2, 1), Cells(lRow, lCol)).Copy Worksheets(1).Cells(lRow2, 1) End If End With Next i Worksheets(1).Activate Range("A1").Select Application.ScreenUpdating = True End Sub この方法だと、「番号」などを含むシートごとの全ての情報がコピーされてしまいます。 ●左下画像 これを「(1)1枚目のシートの1行目から7行目(2)1枚目シートの8行目からA列に1以上の番号が 入っている行(3)2枚目シートの8行目からA列に1以上の番号が入っている行(4)3枚目シートの・・・」というように全てのシートに対して集計することはできないでしょうか。 ●右下画像 VBAを始めたばかりなので、まだ、あまり理解できていません。

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

  • ベストアンサー
  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.2

n-junです。 >I列とJ列・K列とL列など、結合されたセルがあることが問題でしょうか? 元のコードでは問題なかったんですよね? それであれば支障はないはずなのですが。 結合セルは見た目をよくするには便利ですけど、 集計などを行なうには余りよいものではない感じはします。

donald1982
質問者

補足

>'----列見出しをコピーします >'----1~7行目をコピペ >Worksheets(2).Range("1:7").Copy Worksheets(1).Range("A1") 原因は分かりませんが、「Range("1:7")」を「Range("1:1")」にするとエラーが消えました。 1~7行目をコピーする部分を削除したら、集計表シートの2行目から下方向に その他シートの情報が続けてコピーされたので、後ろに以下のVBAを加えて 対応できました。 Worksheets(2).Select Rows("2:7").Select Selection.Copy Sheets("集計表").Select Rows("2:2").Select Selection.Insert Shift:=xlDown Range("A3:f3").Select Selection.ClearContents Range("A1").Select

その他の回答 (1)

  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.1

検証はしていないのですが。 Worksheets(2).Select Rows("1:1").Select Application.CutCopyMode = False Selection.Copy Sheets("集計表").Select ActiveSheet.Paste ここは不要だと思うんです。 あとは最初に1~7行目を貼付け、 その後は各シートの8~最終行を貼付ければ良いのでは? Sub 集計表_Test() Dim ws As Worksheet For Each ws In Worksheets 'AD列にシート名を入れる ws.Range("AD1:AD100").Value = ws.Name Next ws Dim newSh As String Dim Sh As Worksheet, myFlag As Boolean newSh = "集計表" myFlag = False For Each Sh In ThisWorkbook.Worksheets If Sh.Name = newSh Then myFlag = True '----全データシートのデータをクリアし、先頭へ移動します Worksheets(newSh).Cells.ClearContents Worksheets(newSh).Move before:=Sheets(1) Exit For End If Next Sh '----全データシートを先頭へ追加します If myFlag = False Then ActiveWorkbook.Worksheets.Add(before:=Worksheets(1)).Name = newSh End If Dim i As Integer Dim lRow As Long, lCol As Long, lRow2 As Long Application.ScreenUpdating = False '----列見出しをコピーします '----1~7行目をコピペ Worksheets(2).Range("1:7").Copy Worksheets(1).Range("A1") For i = 2 To Worksheets.Count With Worksheets(i) lRow = .Cells(Rows.Count, 1).End(xlUp).Row lCol = .Cells(1, Columns.Count).End(xlToLeft).Column '----シートのデータが8行以上の場合にコピーします If lRow >= 8 Then lRow2 = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1 .Activate '----8~最終行までをコピーする .Range(Cells(8, 1), Cells(lRow, lCol)).Copy Worksheets(1).Cells(lRow2, 1) End If End With Next i Worksheets(1).Activate Range("A1").Select Application.ScreenUpdating = True End Sub コードは質問の範囲だけ変更してます。 ご参考になれば。

donald1982
質問者

補足

8行目から最終行までをコピーするところがうまく行きません。 「.Range(Cells(8, 1), Cells(lRow, lCol)).Copy Worksheets(1).Cells(lRow2, 1)」 に「結合されたセルの一部を変更することはできません。」というエラーが出てしまいます。 I列とJ列・K列とL列など、結合されたセルがあることが問題でしょうか?

関連するQ&A

  • VBA 任意のシートからコピーを始める。

    教えてください。 全てのシートをコピーして一つのシートにまとめるプログラムシートを作成しました。 1番目のシートからコピーを始める場合は For i = 2 To Worksheets.Count 2番目のシートからコピーを始める場合は For i = 3 To Worksheets.Count とすればよいのですがこれだといちいちモジュールコードを出して数字を変更しなければならず面倒です。 そこでユーザーフォームのコンボボックスに任意の数字を入れてクリックを押せば希望するシートからコピーを始めるプログラムを作成してみましたがうまくいきません。どなたか教えてくださいませんか。 Sub matome() Dim i As Integer Dim lRow As Long, lCol As Long, lRow2 As Long, lRow3 As Long, SNo As Integer '----何番目からコピーを始めるかを決定します With UserForm2 SNo = .ComboBox1.value End With For i = 1 + SNo To Worksheets.Count With Worksheets(i) lRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1 lCol = .Cells(1, Columns.Count).End(xlToLeft).Column '----シートのデータが2行以上の場合にコピーします If lRow >= 2 Then lRow2 = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1 If lRow2 < Worksheets(1).Cells(Rows.Count, 5).End(xlUp).Row + 1 Then lRow2 = Worksheets(1).Cells(Rows.Count, 5).End(xlUp).Row + 1 .Activate .Range(Cells(2, 1), Cells(lRow, lCol)).Copy Worksheets(1).Cells(lRow2, 1) End If End With Next i

  • エクセルのマクロについて

    下記のようなプログラム組んでいます。 Sub 張付() Sheets("一覧表").Select Dim i As Long Dim ws1, ws2 As Worksheet Set ws1 = Worksheets("一覧表") Set ws2 = Worksheets("データー") For i = 5 To ws2.Cells(Rows.Count, 1).End(xlUp).Row ws1.Range("B5") = ws2.Cells(i, 2)    'セルB5に氏名を入力 ws1.Range("C5") = ws2.Cells(i, 3)    'セルC5に年齢を入力 ws1.Range("D5") = ws2.Cells(i, 4)    'セルD5に電話番号を入力 この後、 ws1.Range("B5")のB5をB6にまた、C5はC6に改行してそれぞれデーターを移していきたい のですが、B5をB6に順次プラスする方法を教えて下さい。 よろしくお願いいたします。

  • エクセルののマクロについて教えてください

    Sub search() Dim i As Long, lastCol As Long, c As Range, str As String, wS As Worksheet Set wS = Worksheets("sheet2") wS.Cells.Clear str = Application.InputBox("検索内容を入力") Application.ScreenUpdating = False With Worksheets("sheet1") lastCol = .Cells(1, Columns.Count).End(xlToLeft).Column .Columns(lastCol + 1).Insert For i = 2 To .Cells(Rows.Count, "A").End(xlUp).Row Set c = Range(.Cells(i, "A"), .Cells(i, lastCol)).Find(what:=str, LookIn:=xlValues, lookat:=xlWhole) If Not c Is Nothing Then .Cells(i, lastCol + 1) = 1 End If Next i If WorksheetFunction.CountIf(.Columns(lastCol + 1), 1) > 0 Then .Range("A1").AutoFilter field:=lastCol + 1, Criteria1:=1 .Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Copy wS.Range("A1") wS.Columns.AutoFit wS.Columns(lastCol + 1).Delete wS.Activate .Columns(lastCol + 1).Delete .AutoFilterMode = False Else MsgBox "該当データなし" End If End With Application.ScreenUpdating = True End Sub エクセルで上のシステムをネットから持ってきました。 上から5行目のinputboxを"Sheet3"のA列からデータを持ってきてプルダウンで表示させたいのですがユーザーフォームでオブジェクトを組まないで表示させる方法を教えてください

  • エクセルで在庫表を作ろうとしています

    エクセルで在庫表を作ろうとしているのですが、躓いてしまって困っています。 TEST1 コードを手入力した後実行 TEST2 出庫数を入力した後実行 Option Explicit Option Base 1 Sub TEST1() 'コードを手入力した後実行 Dim ws1 As Worksheet Dim ws2 As Worksheet Dim r&, i& Dim vL1 As String Dim vL2 As Long Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") r = ws1.Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To r vL1 = Application.WorksheetFunction.VLookup(ws1.Cells(i, 1), ws2.Range("A2:IV65536"), 2, False) ws1.Cells(i, 1).Offset(, 1) = vL1 vL2 = Application.WorksheetFunction.VLookup(ws1.Cells(i, 1), ws2.Range("A2:IV65536"), 3, False) ws1.Cells(i, 1).Offset(, 2) = vL2 Next i End Sub Sub TEST2() '出庫数を入力した後実行 Dim ws1 As Worksheet Dim ws2 As Worksheet Dim r&, i& Dim vL2 As Long Dim vL3 As String Dim syukko As Long Dim fnd As Range Dim zaiko As Long Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") r = ws1.Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To r If ws1.Cells(i, 4) > 0 Then syukko = ws1.Cells(4, 1).Offset(, 3).Value vL2 = Application.WorksheetFunction.VLookup(ws1.Cells(3, 2), ws2.Range("A2:IV65536"), 3, False) Set fnd = ws2.Range("A:A").Find(ws1.Cells(i, 1)) If fnd Is Nothing = False Then zaiko = vL2 - syukko fnd.Offset(, 2) = zaiko End If MsgBox ws1.Cells(i, 2) & "を" & syukko & "出庫します" & vbLf & "在庫は" & zaiko & "になります。" Else MsgBox "出庫数を入力して下さい" Exit Sub End If Next i ws1.Range("A2:D65536").ClearContents End Sub ここまでは作りました。 ですが、プロシージャの外では無効です と出てしまいます。 どうすればよいのでしょうか。 教えて下さい。 シート1のB2にコード・C3に名前・D2に現在個数・E2に出庫数を入力します。 実際にはB3からすうじを入力し、コードを入力すれば自然に名前と現在個数を シート2から探してくるようにしたいです。 シート2にはA列にコード、B列に名前、C列に現在庫数が載っている表があります(量が半端ではないです) 出来れば、1度出庫数を入れたら、次開いた時にシート2のC列にある現在個数が自然に減っていて、シート1にはフォームしか残らない状態にしたいです。 お願いします<m(__)m>

  • Excel 2007 マクロのIF構文について

    Excel 2007 マクロのIF構文について Sheet1からSheet2にIF構文を使用して、 必要な情報を転記するマクロです。 下記マクロで実現できているのですが、IF構文が多く もっと効率的なマクロがあるのではないかと考えています。 IF構文が2つありますが、1つにまとめるマクロがありましたら お教えください。 Sub Rist() Dim i, j As Long Dim ws1, ws2 As Worksheet Set ws1 = Worksheets("Sheet1") Set ws2 = Worksheets("Sheet2") '「Sheet1」シートを更新 Worksheets("Sheet1").Range("A1").ListObject.QueryTable.Refresh BackgroundQuery:=False '「Sheet1」シートから「Sheet2」シートに転記 For i = 2 To ws1.Cells(Rows.Count, 1).End(xlUp).Row For j = 2 To ws2.Cells(Rows.Count, 13).End(xlUp).Row '「Sheet1」シートのL列から「Sheet2」シートのS列に転記 If ws2.Cells(j, "M") = ws1.Cells(i, "A") Then ws2.Cells(j, "S") = ws1.Cells(i, "L") End If '「Sheet1」シートのG列から「Sheet2」シートのQ列に転記 If ws2.Cells(j, "M") = ws1.Cells(i, "A") Then ws2.Cells(j, "Q") = ws1.Cells(i, "G") End If Next j Next i End Sub

  • VBA sumifで計算できません

    集計シートに入力シートから抽出した重複しない検索データの合計値を入力シートでSUMIFで書いてみましたが  「オブジェクトはこのプロパティまたはメソッドをサポートしていません。」とエラーになります。 何がいけないのか調べてみましたがVBA初心者でわからず困っています。 教えてください。よろしくお願いします。 Dim 集計データ数 As Long Dim 入力シートデータ数 As Long Dim データ行 As Long 集計データ数 = Cells(Rows.Count, 38).End(xlUp).Row 入力シートデータ数 = Worksheets("入力").Cells(Rows.Count,29).End(xlUp).Row For データ行 = 11 To 集計データ数 Cells(データ行, 11).Value = Application.WorksheetFunction.SumIf(Worksheets("入力").Range(Cells(11, 29), Cells(入力シートデータ数, 29)),Cells(データ行, 2), Worksheets("入力").Range(Cells(11, 21), Cells(データ行, 21))) Next データ行 End Sub

  • VBA一定の範囲内からデータが入っている行を検索

    現在VBAにて作成中です。 内容は、各シートの全く同じ範囲内から1シートへ自動で貼り付けを行い日付順に並べ替えるということです。 各シートは全て同じ表になっていますので、コピー範囲のセル番地は全シート同じです。 コピー範囲は、BF4:BM81で、BF4に日付が入っています。 81行までありますが、82行には、合計行が入っていることや、その下行もデータが入っている為、範囲指定をしています。また、81行設けていますが、上から順にデータは入っているものの、81行まで全て埋まっているとは限りません。 その為、下記のVBAにすると、各シートの81行までのデータが反映され1シートに全てのシート分が貼り付けられるので、かなりの行数になり、空白や0の行が出てしまいます。 範囲内から日付(列BF)のデータが入っている行までを検索し選択、貼り付けを行えるようにしたいと思っています。 どなたかご教授頂ければと思いますのでよろしくお願い致します。 見よう見まねで下記を作成しました。 Sub matome() Dim i As Integer Dim lRow As Long, lCol As Long, lRow4 As Long Application.ScreenUpdating = False '----全データシートの有無をチェックします sh_check '----列見出しをコピーします Worksheets(2).Range("bf1:bm3").Copy Worksheets(1).Range("A1") For i = 2 To Worksheets.Count With Worksheets(i) 左上 = "Bf4" 右下 = "bm81" 範囲 = 左上 & ":" & 右下 lRow = .Cells(Rows.Count, 1).End(xlUp).Row lCol = .Cells(58, Columns.Count).End(xlToLeft).Column '----シートのデータが4行以上の場合にコピーします If lRow >= 4 Then lRow4 = Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1 .Activate Range(範囲).Select Selection.Copy Worksheets(1).Cells(lRow4, 1).PasteSpecial Paste:=xlPasteValues End If End With Next i End Sub 説明に不足がありましたら、追って書き込みさせていただきます。

  • エクセル マクロ シートの集計

    エクセル・マクロについての質問です。1つのブックに、複数の単票と集計表があります。単票の名称はすべて「○課△係」で、2~10シート程度でシート数は変動します。集計表は1シートで、名称は”「集計」です(その他に1シート有り)。単票と集計表のA列が一致した行(の特定の列)に、単票から集計表へデータを転記します。単票ごとに処理を繰り返し、集計表を完成させたいのですが、エラーが出て実行できません。お忙しいところ誠に恐縮ですが、ご教授方宜しくお願いいたします。 Sub 集計() Dim T As Worksheet Dim p As Long, q As Long, n As Long, m As Long, y As Long T.Name = "*課*係" For Each T In Worksheets For n = 10 To 50 ' p = T.Cells(n, 1) For m = 2 To 550 If Sheets("集計").Cells(m, 1) = p Then y = 5 + T.Range("B4") Sheets("集計").Cells(m, y).Value = q Exit For End If Next End Sub

  • EXCEL VBA: 次の処理のマクロボタン作成

    ConvertシートのA列にあるフルパス付きファイル名を B列から右方向に最大L列までパス区切り文字(\)で分割済みです。 (但し、1行目は見出し行) 列方向(横方向)の分割部分を、横_縦シートの5行目から行方向(下方向)にそのままの順番で配置換え テスト目的で以下のコードを考えて、1行分(i=2)は配置換え出来るのを確認しています。 ここから横_縦シートのどこかにマクロボタンを配置して クリックすると以下を処理したいです。 1)range(”A5”)以下の書き出し分を削除 > 次の書き出しに備える 2)i=3 として 次の書き出しを行う イメージとしては、1行分は配置換えして確認して、ボタンクリックで次を表示して確認を繰り返す ボタンに登録するコードを教えてください。 可能なら、前を表示や処理停止のボタンも作成したいと思っていますのでご指導下さい。 Sub フルパス分割() Dim tmp As Variant Dim Ln As Long, i As Long, ii As Long Dim ws1 As Worksheet, ws3 As Worksheet Set ws1 = Worksheets("Everything") Set ws3 = Worksheets("Convert") Ln = ws1.Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To Ln ws3.Cells(i, 1) = ws1.Cells(i, 1) tmp = Split(ws3.Cells(i, 1), "\") For ii = LBound(tmp) To UBound(tmp) ws3.Cells(i, ii + 2) = tmp(ii) Next Next End Sub Sub 並べ替え() Dim Ln As Long, i As Long Dim Worksheet, ws3 As Worksheet, ws4 As Worksheet Dim tmp As Variant Set ws3 = Worksheets("Convert") Set ws4 = Worksheets("横_縦") Ln = ws3.Cells(Rows.Count, 1).End(xlUp).Row For i = 2 To Ln tmp = Split(ws3.Cells(i, 1), "\") ws3.Range(Cells(i, 2), Cells(i, UBound(tmp) + 2)).Copy ws4.Cells(i + 3, 1).PasteSpecial Transpose:=True Stop Next End Sub

  • 配列のフリーズを解消してください。

    Sub データ原本() Dim wsAll As Worksheet Set wsAll = Worksheets("All(5)") Dim lRow As Long, lCol As Long Dim i As Long, j As Long, cnt As Long With Worksheets("データ原本") '日付S行を日付に変更(「.」を「/」に置換) lRow = .Cells(Rows.Count, 1).End(xlUp).Row Dim MyArray As Variant MyArray = Range(.Cells(10, 1), .Cells(lRow, 1)) For i = 1 To lRow - 9 MyArray(i, 1) = Replace(MyArray(i, 1), ".", "/") Next Range(.Cells(10, 1), .Cells(lRow, 1)) = MyArray Erase MyArray '配列の初期化 '「天気」両サイドの &「内・外」両サイドの空白スペースを削除 lRow = .Cells(Rows.Count, 1).End(xlUp).Row MyArray = Range(.Cells(10, TNK), .Cells(lRow, TNK)) For i = 1 To lRow - 9 MyArray(i, 1) = Trim(MyArray(i, 1)) Next Range(.Cells(10, TNK), .Cells(lRow, TNK)) = MyArray Erase MyArray '配列の初期化 '数値0のデータ行の行削除 lRow = .Cells(Rows.Count, 1).End(xlUp).Row lCol = .Cells(9, Columns.Count).End(xlToLeft).Column Dim arr_A As Variant, arr_B As Variant arr_A = Range(.Cells(9, 1), .Cells(lRow, lCol)).Value ReDim arr_B(1 To lRow - 8, 1 To lCol) cnt = 0 For i = 1 To lRow - 8 If arr_A(i, 18) <> 0 Then cnt = cnt + 1 For j = 1 To lCol arr_B(cnt, j) = arr_A(i, j) Next j End If Next i .Range("A9").Resize(lRow, lCol).Value = arr_B End With End Sub  上記のコードを2回実行すると2回目には、 MyArray(i, 1) = Replace(MyArray(i, 1), ".", "/")のところで「型が一致しません。」とフリーズします。かと言って 「 '数値0のデータ行の行削除」コードを一括削除して、実行ボタンを何度押してもフリーズすることはありません。どこに不具合が生じているのかわからないのですが、どなたか名回答を宜しくお願いします。

専門家に質問してみよう