🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

VBA

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

1回答

1817閲覧

セルに入力された条件に基づいてファイルからデータを抽出する

ichigo15

総合スコア14

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

VBA

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2019/12/10 04:27

編集2019/12/11 00:47

前提・実現したいこと

同じフォルダ内の複数のファイルから抽出先シートに入力したセルの条件に応じてデータを抽出する。

◆条件が入力されているセル番地
a)商品名:B4
b)期間:B6(以降)B7(以前)
c)抽出するシート名:F4
d)抽出すべき項目:F6~F10
e)抽出しない項目:F12~F16

イメージ説明

◆複数のファイル
A列~J列までデータがあります。
a)はB列
b)はC列
d)とe)はD列を参照してます。

イメージ説明

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

前任者が作成したコードです。
マクロの知識が低いため1.2.を追加するためにアドバイスをお願いいたします。

1.抽出先をF4に入力されたシートにすることができない。
2.抽出すべき項目と抽出しない項目をF6~F10、F12~F16に入力された条件に基づいて抽出できない。

該当のソースコード

Sub OneInstance01() Dim dstSheet As Worksheet Dim Ns As Worksheet Dim mPath As String Dim buf As String Dim i As Long Dim y As Long Dim srcBook As Workbook Dim Base Dim Namae As String Dim Sd As Date Dim Ed As Date Dim WF As Object Set WF = WorksheetFunction Set dstSheet = ThisWorkbook.Worksheets("抽出条件") If Not Evaluate("=ISREF(抽出先シート!A1)") Then Sheets.Add.Name = "抽出先シート" Set Ns = Worksheets("抽出先シート") Ns.UsedRange.Clear mPath = ThisWorkbook.Path & "\" buf = Dir(mPath & "*.xls*") y = 2 With dstSheet Namae = .Range("B4").Value Sd = .Range("B6").Value Ed = .Range("B7").Value End With Do While buf <> "" If buf <> ThisWorkbook.Name Then Set srcBook = Workbooks.Open(mPath + buf) Base = Intersect(srcBook.Worksheets("Sheet1").UsedRange, srcBook.Worksheets("Sheet1").Range("A:J")) For i = 1 To UBound(Base, 1) If Base(i, 1) = Namae And Base(i, 3) >= Sd And Base(i, 3) <= Ed Then Ns.Cells(y, 2).Resize(, UBound(WF.Index(Base, i, 0))) = WF.Index(Base, i, 0) y = y + 1 End If DoEvents Next srcBook.Close False End If buf = Dir() 'Erase Base Loop Set dstSheet = Nothing Set srcBook = Nothing Set Ns = Nothing Set WF = Nothing End Sub

追記

・必ず入力するセル
a)商品名:B4
b)期間:B6(以降)B7(以前)
c)抽出するシート名:F4

※ 抽出すべき項目と抽出しない項目は入力しない場合があります。 
入力しない場合は商品名と期間の条件で全て抽出します。

※ 抽出すべき項目と抽出しない項目はどちらか一方のみ入力します。
同時に入力することはありません。
100項目のうち、抽出すべき項目が99件、抽出しない項目が1件の場合に抽出しない項目1件を
入力するようにしております。

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

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

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

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

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

y_waiwai

2019/12/10 04:34

このままではコードが読みづらいので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
ichigo15

2019/12/10 04:54

コードが読みづらく申し訳ございません。 編集してみましたのでご確認ください。
KazuSaka

2019/12/10 10:41 編集

質問です。 商品名と期間は必ず入力されますよね? 抽出項目と抽出対象外の項目が未入力の場合、商品名と期間の条件ですべて抽出する感じですか? 抽出項目と抽出対象外項目が同時に入力されることはないですよね? (両方入力だと、抽出対象項目のみを設定するのと同じになりますよね?) 以上
ichigo15

2019/12/11 00:47

ご指摘ありがとうございます。 説明が不足しており申し訳ございません。 追記しましたのでご確認ください。
KazuSaka

2019/12/11 02:03

それでしたら、私が回答した内容で、問題ないかと思います。ご確認ください。
guest

回答1

0

ベストアンサー

※初期回答から少し修正しました.回答修正箇所は【回答修正】とつけました.
###回答
プログラム修正させて頂きました。
お困りの以下の2点を追加しました。
>>1.抽出先をF4に入力されたシートにすることができない。
以下のコードが抽出先シートを決定している箇所なので、この部分をF4のセルの値に変更しましょう。

Set Ns = Worksheets("抽出先シート")

>>2.抽出すべき項目と抽出しない項目をF6~F10、F12~F16に入力された条件に基づいて抽出できない。
ItemInc関数を新しく作り、その内部で抽出対象の有無を判定するようにしました。

###仕様
仕様ですが、以下のようにつくりました。
1.商品名と期間で抽出候補を抽出
2.抽出候補から[抽出][削除]の条件で絞り込んで、終了
2-1.[抽出][削除]が未入力の場合、1の条件に合うものを全て出力
2-2.[抽出][削除]どちらか一方入力の場合、1の条件からさらに絞り込み出力【回答修正】
2-3.[抽出][削除]が両方入力されている場合は、[抽出]のみ条件で出力
([抽出][削除]両方入力することはないと思いますが・・・)

[抽出・削除]項目の考え方が正しいか分かりませんが、間違ってたら教えてください。

###プログラム
私が追加した箇所は[追加]or[変更]とコメントしておきました。
また、私なりに他のコードにもコメントをつけておきました。

VBA

1Sub OneInstance01() 2 Dim dstSheet As Worksheet 3 Dim Ns As Worksheet 4 Dim mPath As String 5 Dim buf As String 6 Dim i As Long 7 Dim j As Integer 8 Dim y As Long 9 Dim srcBook As Workbook 10 Dim Base As Variant 11 Dim Namae As String 12 Dim Sd As Date 13 Dim Ed As Date 14 Dim Included As Variant '//[追加]抽出項目用 15 Dim NotIncluded As Variant '//[追加]抽出外項目用 16 Dim WF As Object 17 Set WF = WorksheetFunction 18 Set dstSheet = ThisWorkbook.Worksheets("抽出条件") 19 'If Not Evaluate("=ISREF(抽出先シート!A1)") Then Sheets.Add.Name = "抽出先シート" '//[削除]【回答修正】 20 'Set Ns = Worksheets("抽出先シート") '//[削除] 21 '//F4で指定したシートがない場合は作成【回答修正】 22 If Not Evaluate("=ISREF(" + dstSheet.Range("F4").Value + "!A1)") Then Sheets.Add.Name = dstSheet.Range("F4").Value '//[追加] 23 Set Ns = Worksheets(dstSheet.Range("F4").Value) '//[追加]抽出先シートはセルF4の値に基づく 24 25 Ns.UsedRange.Clear '//抽出先シートのデータを削除 26 mPath = ThisWorkbook.Path & "\" '//マクロ保存しているファイルのフォルダパス 27 buf = Dir(mPath & "*.xls*") '//フォルダ内のxlsファイル名をひとつ取得(マクロファイルも含む) 28 y = 2 29 With dstSheet 30 Namae = .Range("B4").Value '//商品名 31 Sd = .Range("B6").Value '//以降 32 Ed = .Range("B7").Value '//以前 33 Included = WorksheetFunction.Transpose(.Range("F6:F10")) '//[追加]抽出対象項目を配列化 34 NotIncluded = WorksheetFunction.Transpose(.Range("F12:F16")) '//[追加]抽出対象外項目を配列化 35 End With 36 Do While buf <> "" '//取得したファイルをひとつずつ実行 37 If buf <> ThisWorkbook.Name Then '//マクロファイルは処理しない 38 Set srcBook = Workbooks.Open(mPath + buf) '//処理対象のワークブック 39 Base = Intersect(srcBook.Worksheets("Sheet1").UsedRange, srcBook.Worksheets("Sheet1").Range("A:J")) '//値が存在する範囲を2次元配列化 40 For i = 1 To UBound(Base, 1) '//Base配列の1次元インデックスの最大まで 41 If Base(i, 1) = Namae And Base(i, 3) >= Sd And Base(i, 3) <= Ed And ItemInc(Included, NotIncluded, Base(i, 4)) Then '//[変更] 42 '//(右辺)WF.Index(Base, i, 0) -> Base(2次元配列)のi行目を配列で取得(第3引数が0だから). 43 '//(左辺).Resize(, UBound(WF.Index(Base, i, 0))) -> Cells(y,2)を列方向に10列分拡張. 44 Ns.Cells(y, 2).Resize(, UBound(WF.Index(Base, i, 0))) = WF.Index(Base, i, 0) 45 y = y + 1 46 End If 47 DoEvents 48 Next 49 srcBook.Close False '//ワークブックを閉じる 50 End If 51 buf = Dir() '//次のxlsxファイルを取得(全て処理したら、while文終了) 52 'Erase Base 53 Loop 54 Set dstSheet = Nothing 55 Set srcBook = Nothing 56 Set Ns = Nothing 57 Set WF = Nothing 58End Sub 59 60'//[追加]項目が抽出対象ならTRUE、削除対象ならFALSE 61Function ItemInc(Included As Variant, NotIncluded As Variant, Item As Variant) As Boolean 62 Dim Bool As Boolean '//戻り値 63 Dim Value As Variant 64 65 '//項目が空ならFalse 66 If Item = Empty Then 67 ItemInc = False '//戻り値 68 Exit Function '//処理終了 69 End If 70 71 If Join(Included, "") = "" And Join(NotIncluded, "") = "" Then 72 '//[抽出、削除]未設定なら全部True 73 ItemInc = True 74 Exit Function 75 ElseIf Join(Included, "") <> "" And Join(NotIncluded, "") = "" Then 76 '//[抽出]の項目のみ設定されている場合 77 Bool = False 78 For Each Value In Included 79 If Value = Item Then 80 Bool = True 81 End If 82 Next Value 83 ElseIf Join(Included, "") = "" And Join(NotIncluded, "") <> "" Then 84 '//[削除]の項目のみ設定されている場合 85 Bool = True 86 For Each Value In NotIncluded 87 If Value = Item Then 88 Bool = False 89 End If 90 Next Value 91 Else 92 '//[抽出、削除]の両方に条件設定されている場合 93 '//[抽出]項目のみの設定と同じ 94 Bool = False 95 For Each Value In Included 96 If Value = Item Then 97 Bool = True 98 End If 99 Next Value 100 End If 101 102 ItemInc = Bool '//戻り値 103 104End Function

###補足
質問文に商品名はB列を参照しているとありますが、プログラムを見る限り、A列を参照しています。
以下のコードの「Base(i, 1) = Namae」の部分です。
Base(i, 1)はA列のi行目という意味ですので。

If Base(i, 1) = Namae And Base(i, 3) >= Sd And Base(i, 3) <= Ed Then

以上です。

投稿2019/12/10 11:55

編集2019/12/11 04:00
KazuSaka

総合スコア640

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

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

ichigo15

2019/12/11 07:12

KazuSakaさん 色々と教えていただき感謝します。 希望通りの結果になりました。 コメントが遅くなりまして申し訳ございません。 時間がかかってしまいましたが理解できました。 どのコードを修正すべきか丁寧に分かりやすく説明いただいたので助かりました。 とても勉強になりました。
KazuSaka

2019/12/11 14:00

うまくいったみたいでよかったです!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問