複数ブックからデータを抽出してリストを作成する方法

このQ&Aのポイント
  • VBAを使用して、複数のブックから指定のデータを抽出し、リストを作成する方法を紹介します。
  • 各地域ごとに分かれた複数のブックから、「一覧」シートを参照して商品名、メーカー、合計を抽出します。
  • 月によって商品が増減するため、各地域別のブックを更新すると自動的にリストも更新されます。開かずにデータを抽出する方法も紹介します。
回答を見る
  • ベストアンサー

複数ブックから指定のデータを抽出してリストにしたい

VBAで複数のブックから指定のデータを抽出してリストを作りたいです。 ・地域ごとに分かれたブックが複数あります。(全て同一フォルダ内、リストも同フォルダに作ります) ・シートの構成は「原本」「一覧」「商品名A」「商品名B」(※5~20シート位) ・商品は月替わりで増減がある。 「一覧」…商品名のシートから月の販売個数を集計した物を一覧表にしてあります。      必ず各ブックの2枚目のシートになります。 ・各地域のブックから「一覧」のシートを参照して「商品名」「メーカー」「合計」を抽出する。 ・リストには地域別でメーカー毎に一覧を表示したい。 別ブックの特定のセルを参照して一覧にするのは簡単なのですが、商品が毎月増減します。 なので各地域別のブックを更新したら、リストの方も自動的に反映されるようにしたいのです。 色々検索してみて各ブックの指定のシート、指定のセルからマクロで自動的に読み込むというのは見つかりましたが、セルの範囲が一定ではない場合はどうすれば良いのか解りません。 出来ればリスト以外のブックは開かずにデータを抽出したいです。 (※実際に入力作業を行うスタッフは本当に入力しか出来ないので、このブックを先に開いて~とかは混乱して出来ないようです。マクロで全てのファイルを開く等も勝手に閉じてしまったりするので避けたいです。)

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

  • ベストアンサー
  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.2

回答の続きです。 マクロ本体の動作に必要なFunctionプロシージャです。 これもリストのあるブックの標準モジュールに置いて下さい。 'リストに新しい地区を挿入し、その領域を返す Function InsArea(ByVal ListSheet As Worksheet, ByVal AreaName As String, _ ByVal RowPosition As Long, ByVal DataRowsCount As Long) As Range Dim RU As Long Dim RL As Long RU = RowPosition RL = RowPosition + DataRowsCount ListSheet.Range("b" & RU & ":d" & RL).Insert xlShiftDown ListSheet.Range("b" & RU & ":d" & RU).Merge ListSheet.Range("b" & RU).Value = AreaName If DataRowsCount <= 0 Then Set InsArea = ListSheet.Range("b" & RU & ":d" & RU) Else Set InsArea = ListSheet.Range("b" & RU + 1 & ":d" & RL) End If End Function '地区のデータ領域を返す。 '引数はデータ領域左上のセル '最下行は、下に結合セルがあればその前、 'なければデータが入力されている最下行のセルの1つ下 '列数は3 Function GetDataArea(DataAreaUL As Range) As Range Dim MergedCells As Range Dim Lowest As Range Dim r As Range Dim cc As Long Dim Sh As Worksheet cc = 3 Set Sh = DataAreaUL.Parent Set MergedCells = FindMergedAll(DataAreaUL.EntireColumn) If MergedCells Is Nothing Then 'set Lowest = GetLowest(DataAreaUL) Set Lowest = Sh.Cells(Sh.Cells.Rows.Count, _ DataAreaUL.Column).End(xlUp).Offset(1) Else Set r = Intersect(Sh.Range(DataAreaUL, _ Sh.Cells(Sh.Cells.Rows.Count, _ DataAreaUL.Column)), MergedCells) If r Is Nothing Then 'set Lowest = GetLowest(DataAreaUL) Set Lowest = Sh.Cells(Sh.Cells.Rows.Count, _ DataAreaUL.Column).End(xlUp).Offset(1) Else Set Lowest = r(1).Offset(-1) End If End If Set GetDataArea = Sh.Range(DataAreaUL, _ Sh.Cells(Lowest.Row, Lowest.Column + cc - 1)) End Function '結合セルの検索 'セル範囲を引数にするとその範囲で検索開始、引数なしで次を検索 'IsMissing(Range1)使用のためRange1はVariant Function FindMergedInRange(Optional ByVal Range1 As Variant) As Range Static First As Range Static Previous As Range Static RangeToFind As Range Dim Found As Range If Not IsMissing(Range1) Then Application.FindFormat.Clear Application.FindFormat.MergeCells = True Set RangeToFind = Range1 Set First = RangeToFind.Find(What:="", SearchFormat:=True) If First Is Nothing Then Set FindMergedInRange = Nothing Else Set FindMergedInRange = First.MergeArea End If Set Previous = First Else Set Found = RangeToFind.Find(What:="", after:=Previous, _ SearchFormat:=True) If Found.Address = First.Address Then Set FindMergedInRange = Nothing Else Set FindMergedInRange = Found.MergeArea Set Previous = Found End If End If End Function '結合セルをすべて検索 Function FindMergedAll(ByVal Range1 As Range) As Range Dim AllFound As Range Dim Found As Range Set AllFound = FindMergedInRange(Range1) If Not AllFound Is Nothing Then Do Set Found = FindMergedInRange() If Found Is Nothing Then Exit Do Else Set AllFound = Union(AllFound, Found) End If Loop End If Set FindMergedAll = AllFound End Function 'すべて検索した結合セルの中の文字列を検索 Function FindStrInMergedAll(ByVal Str As String, ByVal Range1 As Range, _ Optional ByVal LookAt As XlLookAt = xlWhole) Dim MergedAll As Range Set MergedAll = FindMergedAll(Range1) If MergedAll Is Nothing Then Set FindStrInMergedAll = Nothing Else Application.FindFormat.Clear Set FindStrInMergedAll = MergedAll.Find(What:=Str, LookAt:=LookAt) End If End Function

schalke_04
質問者

お礼

お礼が遅くなって申し訳ありません。 詳細な回答、有難うございました。 いただいた回答を丸写しで終わらないように、しっかり勉強させていただこうと思います。

その他の回答 (1)

  • queuerev2
  • ベストアンサー率78% (96/122)
回答No.1

どこまで御希望に添えるかわかりませんが回答いたします。 ブックを開かずに内容を読む方法はありました。 http://officetanaka.net/excel/vba/tips/tips28.htm 今回初めて使ったのですが、低機能ではありますがある程度のことはできます。 今回は行数が一定しない表を読むのですが、開始位置が決まっていて途中に空行がないものとしました。 データの行か空行かの判別は、4行目以下で列Cに何か記入されているかどうかで行うことにしました。 (途中に空行があって、その数が特定できない場合などはブックを開くしかないと思います。それでもブックが開いているかどうか判定すればいいとは思いますが。) 書き込むリストの方ですが、その地域のデータを一旦すべて削除し、地域別ブックから読み込んだデータ数に応じてセルを挿入することにします。 リストに地域がない場合は追加するかどうかを質問したうえでリストの一番上に追加(挿入)することにします。 地域の判定ですが、まず地域別ブックのB2を読み、右4文字の「販売??」を削除し、リストの地区名(列B)と比較して同じものがあればそこがその地域のデータであるとします。 リストにおいて、地区名はセルが結合されており、それ以外の列Bのセルは結合されていないものとしました。 質問画像のリストでは異なるメーカーの間に空行が入っていますが、今回のコードでは簡単のため入れていません。 読み込む地区のブックは開いていてもいなくてもいいのですが、できるだけExcelの複数起動は避けた方が無難です。 (通常は複数のブックを開いてもExcelは1つなので問題ありませんが) コードはリストのあるブックの標準モジュールに置いて下さい。 リストのシート名は"Sheet1"としました。 地区のブック名はコードに直接書いていますので質問者様の状況に合わせて書き換えてください。 あとは実行するなりコードを読むなりしてみてください。 わからないところやうまくいかないところは補足いただければ、と思います。 コードを書いてみたのですがとても長くなってしまったので2つの回答に分けます。 すべてリストのあるブックの標準モジュールに置いて下さい。 以下はマクロ本体です。 Option Explicit Sub ExtractToList1() Dim AreaBooks As Variant Dim BPath_d As String Dim e, f, i As Long, j As Long Dim Ex1 As Variant Dim ExAN As String Dim ExC As Collection Dim ExRCn As String Dim ABRow As Long Dim LSh As Worksheet Dim AreaA2() As Variant Dim LP As Range Dim r As Range Dim RowsDA As Long '初期化 'リストのあるシートを指定 Set LSh = ThisWorkbook.Sheets("Sheet1") 'ここに地区のブック名を書く AreaBooks = Array("area1.xlsx", "area2.xls") 'フォルダ指定 BPath_d = ThisWorkbook.Path If Right(BPath_d, 1) <> "\" Then BPath_d = BPath_d & "\" End If '地区のブックを1つずつ処理 For Each e In AreaBooks 'データを読む ABRow = 4 Set ExC = New Collection Do ExRCn = "'" & BPath_d & "[" & e & "]一覧'!R" & ABRow & "C" Ex1 = ExecuteExcel4Macro(ExRCn & "3") If Ex1 = 0 Or Ex1 = "" Then Exit Do End If ExC.Add Array(Ex1, ExecuteExcel4Macro(ExRCn & "4"), _ ExecuteExcel4Macro(ExRCn & "9")) ABRow = ABRow + 1 Loop ReDim AreaA2(1 To ExC.Count, 2) For i = 1 To ExC.Count For j = 0 To 2 AreaA2(i, j) = ExC(i)(j) Next Next ExAN = ExecuteExcel4Macro("'" & BPath_d & "[" & e & "]一覧'!R3C2") ExAN = Trim(ExAN) If ExAN Like "*販売??" Then ExAN = Left(ExAN, Len(ExAN) - 4) End If 'データを書き込む場所の準備 Set LP = FindStrInMergedAll(ExAN, LSh.Range("b:b"), xlWhole) RowsDA = UBound(AreaA2, 1) - LBound(AreaA2, 1) + 2 If LP Is Nothing Then 'リストに地区がなければ尋ねてYesなら一番上に挿入 Select Case MsgBox("地区「" & ExAN & "」はリストにありません。" _ & vbNewLine & "新たに書き込みますか?", vbYesNoCancel) Case vbNo GoTo EndOfAreaBook: Case vbCancel Exit Sub End Select Set r = InsArea(LSh, ExAN, 2, RowsDA) Set r = r.Resize(r.Rows.Count - 1) Else 'リストに地区があるので一旦セルを削除してから挿入し直す Set r = GetDataArea(LP(1).Offset(1)) If r.Rows.Count >= 2 Then Set r = r.Resize(r.Rows.Count - 1) r.Delete shift:=xlUp End If Set r = GetDataArea(LP(1).Offset(1)) r.Resize(RowsDA - 1).Insert shift:=xlDown Set r = GetDataArea(LP(1).Offset(1)) Set r = r.Resize(RowsDA - 1) End If 'リストにデータを書き込む r.Value = AreaA2 'メーカーをキーにソート With LSh.Sort .SortFields.Clear .SortFields.Add Key:=Intersect(LSh.Range("C:C"), r), _ SortOn:=xlSortOnValues, Order:=xlAscending, _ DataOption:=xlSortNormal .SetRange r .Header = xlGuess .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With EndOfAreaBook: Next End Sub

関連するQ&A

  • エクセルでフォルダ内のBookのセルの参照

    いつもお世話になっております。 決まったフォルダ内の複数のBook「個別情報(製品名)」のフルパスを別のBook「リスト」のA列に入れると、「個別情報(製品名)」のシート(規格)の指定のセルを「リスト」のシート(規格一覧)に行方向に引っ張ってくるようにしたいのですが。 1度に参照するシートは5-10枚。 参照するセル番地は決まっていて、多いと15個程度。 参照セルは「リスト」のシート(規格一覧)の最下行のセルに入るようにしたい。 閉じたままのBookのシートを指定して、セル参照が出来ることを少し前に知ったのですが、当方には難易度が高そうで躊躇していましたが最近コロナで時間が出来たのでチャレンジしてみようかと。 当方永遠のVBA初心者ですのでその辺もご配慮の上よろしくお願い致します。

  • 複数のExcelブックから特定シートの特定セル抽出

    同一フォルダ内にある複数のExcelブックから特定シートの特定セル値を抽出して一覧表にまとめるExcel マクロ(VBA)を教えてください。 よく似ている質問、回答を読んだのですが、私のレベルではとても応用できず質問させていただきます。 全く同じものがあれば、そのアドレスを回答いただくだけでも助かります。 【前提】 ・実行する端末のOSはWindows XP(SP3)、Excelは2003 ・対象フォルダはネットワーク接続フォルダ「\\share\target」  この中に、複数のExcelブックがあります。 ・抽出したい対象は、各ブック内の「概要」シートの「C3」セルで統一されています。 【抽出一覧作成イメージ】 ・「集約.xls」ブックの「Sheet1」の2行目から抽出した結果を一覧表示する。 ・表示はA列に抽出元ブック名(=ファイル名)、B列に抽出元C3セルの値。 ・C3セル値を「集約.xls」ブックの「Sheet1」に貼り付ける際には「値で貼り付ける」が望ましい。 というようなイメージです。 とても勝手なお願いではありますが、宜しくお願いいたします。

  • 複数のExcelブックから特定シートのセル範囲抽出

    同一フォルダ内にある複数のExcelブックから特定シートの特定セル範囲を抽出して一覧表にまとめるExcel マクロ(VBA)を教えてください。 このサイトで殆どよく似た回答を読んだのですがうまくいきません。VBA初心者です。 よろしくお願いします。 【前提】 ・実行する端末のOSはWindows 10 ExcelはOffice365 ProPlus ・対象フォルダはネットワーク接続フォルダ  この中に、複数のExcelブック(xlsx、xlsm)があります。 ・抽出したい対象は、各ブック内の「台帳」シートの「A3:Cの最終行」で  複数のブックの中には「台帳」シートが含まれていないブックも混在しています。 【抽出一覧作成イメージ】 ・「集約.xlsm」ブックの「集計」シートの2行目から抽出した結果を一覧表示する。 ・「集約.xlsm」ブックにマクロは登録する ・表示はA列に抽出元ブック名(=ファイル名)、B列からD列に抽出元「A3:Cの最終行」セルの値。 ・「A3:Cの最終行」セルの値を「集約.xlsm」ブックの「集計」に貼り付ける際には「値で貼り付ける」が望ましい。

  • 複数のエクセルブックから特定シートの特定セル抽出

    同一フォルダ内にある複数のExcelブックから特定シートの特定セル値を抽出して一覧表にまとめるExcel マクロ(VBA)を教えてください。 よく似ている質問、回答を読んだのですが、私のレベルではとても応用できず質問させていただきます。 【前提】 ・実行する端末のOSはWindows XP(SP3)、Excelは2003 ・対象フォルダはネットワーク接続フォルダ「\データ解析\データ」  この中に、複数のExcelブックがあります。 ・抽出したい対象は、各ブック内のシート(シート名はファイル名と同じ)の「BO6からBW16までの□の範囲」で統一されています。 【抽出一覧作成イメージ】 ・「集計.xls」ブックの「Sheet1」の2行目から抽出した結果を一覧表示する。 ・表示はA列に抽出元ブック名(=ファイル名)、B列に抽出元BO6セルの値。以降,C列・D列と 順に値を入れていきたい。 ・BO6~BW16までのセル値を「集計.xls」ブックの「Sheet1」に貼り付ける際には「値で貼り付ける」が望ましい。 というようなイメージです。 とても勝手なお願いではありますが、宜しくお願いいたします。

  • Excel ブック内の指定したデータのコピーマクロ

    よろしくお願いします。 エクセルで自動登録で自動化をしていますが、これだと限界があり今回こちらに書き込みさせていただきました。 流れとしては、マクロスタートでダイアログがでて(可能なら奥底に格納されるブックなのでそのフォルダの一個前辺りの階層指定されて)そこで指定した毎日新しく作られるブック内の指定したシートの指定したセルにあるデータをコピー(ブックは開かないで読み込み)してテンプレートととしている空のブックを開き(開いたまま)指定したシートの指定したセルにペーストするマクロを作りたいです。 (指定したシートと指定したセルの名前は常に同じです) 自動記録で指定したブックを開いて読み込む事は出来ましたが、毎回別のブックなのでそれでは事足りないのです。 ネットで探しましたが… ・ダイアログでファイルを開くマクロは見つけましたが、開いた後内部のデータを読み込むなどマクロは見つかりませんでした。 つながるところがわかりません。 ・(存在するブックの場所指定で)ブックを開かないでその中のデータを読み込むマクロは見つけましたが、ダイアログで選ぶけど開かないでと言う事が出来るマクロは見つけられませんでした これらは元々出来ないのでしょうか? 可能で有ればご教示下ださると助かります。 よろしくお願いします。

  • 【エクセル2010使用】違うブックから[データの入

    【エクセル2010使用】違うブックから[データの入力規則]→[入力値の数値]→[リスト]を参照することは、可能なのでしょうか? 現在、同じブック内の別のシートに会社で取り扱っている[商品一覧]を作って、別のシートでドロップダウンするなどという使い方をしています。 ただ、取引先ごとにブックを分けているため、[商品一覧]がひとつでも増えてしまうとその都度、修正せざるをえません。 そのため、違うブックに[商品一覧]を作って、リストからドロップダウンできれば、修正するにしても一ヶ所のみで済むと思ったのですが、いろいろ調べてもうまくいかず、こちらで質問させて頂きます。 ※ちなみに、VLOOKUP関数を用いて入力された商品名から値段が表示されるように設定しています。 ただ、関数はできても[データの入力規則]は違うブック間ではやり取りができないのかな…と頭を悩ませております。 どなたかエクセル2010で、上記の希望を叶えてくれる手順をご存じの方がいらっしゃいましたら、教えて頂けると幸いです。 宜しくお願い致します。

  • 複数のブックのデータを集めて、グラフを書きたいです

    Book1、Book2には、異なる行列のデータがあります この2つのブックのデータを参照してグラフを書くマクロをVBAで組んでいます Book1,Book2のシートをそれぞれグラフに書くところまでは出来ました 質問1. Book1のA1~An(Aのセルすべて)を、Book2の指定のセル(例えばC1~Cn)に コピーしたい 質問2. Book2のセルB1~B100のデータと Book1からコピーしたC1~C300のデータを 同じグラフ上にプロットしたい AのセルをX軸のデータとして使用する 宜しくお願いします

  • 複数のブックのデータを一つのブックにまとめたい

    http://t_shun.at.infoseek.co.jp/My_Page/Excel-VBA/vba_page1.htm ↑の 7. 指定したフォルダ内にあるExcelファイルを検索して開く の部分のマクロを利用して、集計.xlsというブックで、複数のブックを開くようにしましたが、そのブックを開いた時にそのブックのSheet2の中のデータのみコピーして、集計.xlsに貼り付けたいのですが、どのようにすればよいのか困っています。 指定したフォルダの中には、回答01.xls 回答02.xls ・・・と16個のブックがあります。順番に開いてコピーをするときに、どのようにブック名とシート名を指定すればよいのかわからず困っています。 何か参考になるものがあれば教えてください。 よろしくお願いします。

  • 複数のブックから必要な情報を一覧で抽出したい。

    エクセルで下記のような書類を作成したいのですが、いい方法があれば教えてください。 まず、 1)会社ごとに名簿リストのようなエクセルブックがあります。  (名前や年齢のほか、30項目以上ある内容に○などがついている状態) そして、 2)様式の指定された別のエクセルブックに名前を入力すれば、その様式で指定された情報を   1)の名簿から抽出して表示されるようにしたい。   ただし、2)の様式を指定されたエクセルに名前を入力する際には、1)の○○社の名簿のだれだれ、   △△社の名簿からだれだれ・・というようにその人を探します。 <問題点・疑問点> 様式が指定された表の行は隙間なく表示させたいが、抽出元が複数のブックなので、数式入力が 難しい? 同一人物が複数社にまたがっていることもあり、しかも内容は一致しない場合があるがどのように対応すればよいかわからない。 従って、現段階で考えているのは、 <方法案> (1) 1)の複数のブック(名簿リスト)をまず新しいエクセルブックに集計し一覧表示させる。    (その際には、○○会社というブック情報をA列に入れたい)    一覧集計した際に重複データには、エラー表示されるようにしておき、今回使用したい    データに修正する。 (2) 2)の様式の指定されたエクセルシートの横に追加シートを挿入して(1)を値貼付する。 (3) 一覧表の中から今回必要な人を選び出し、オートフィルタ―などで絞りだす。 (4) 様式の指定されたシートには追加シートで選び出した人の情報が表示されるようにする。 リンクデータの容量で重くなったりするのか、整合性の点が不安です。 何かいい方法があれば教えてください。

  • エクセルの複数ブックのシート名を全てリストにできるソフト探しています

    フォルダやブック名を取得してリストにしてくれるソフトは見つかったのですが、ブック名とシート名(フォルダ名などのパスもリストされても構いませんが)をリストにしてくれるソフトはないでしょうか?ひとつのブックのシート名ではなく複数のブックのシート名一覧です。ご存知の方いらっしゃったらよろしくお願いします。

専門家に質問してみよう