• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VBAで複数Excelの複数条件を満たすもの抽出)

VBAで複数Excelの複数条件を満たすもの抽出

このQ&Aのポイント
  • VBAを使用して複数のExcelファイルから複数の条件を満たすデータを抽出する方法について質問があります。
  • 具体的には、「1月顧客別商品別.xls」と「顧客別管理.xlsx」の2つのExcelファイルにおいて、顧客コードと商品コードの双方が一致しているデータの売上高と粗利を、「顧客別管理.xlsx」の対応する欄に入力するVBAを作成したが、正しく動作しているかどうか分からないとのことです。
  • 質問者は大量のデータがあるため、Dictionaryを使用してデータを管理していますが、コードが重たくなってしまっているようです。もし修正ポイントがあれば教えて欲しいとのことです。

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

  • ベストアンサー
  • HohoPapa
  • ベストアンサー率65% (455/693)
回答No.5

ごめんなさい、注3の位置を間違えたので差し替えます。 SQLを一部で使ったコードとしてみました。 よかったら試してみてください。 ただし、 顧客コードが文字列の場合は注1を生かし、注2をコメントアウトしてください。 また、 顧客別管理.xlsxのA9,B9以下とA39,B39以下が上詰めではない場合は 注3をコメントアウトしてください。 なお >"1月顧客別商品別.xls":”集計”シートのA~E列に >”顧客コード”、”顧客名”、”商品コード”、”売上高”、”粗利”が2行目以降並んでいます。 これは、顧客コードと商品コード組み合わせでは重複がないということでいいですよね? これを前提としたコードです。 それとも、重複があり、"顧客別管理.xlsx"に合計転記しますか? また、課題のブック2つとは別にマクロブック専用ブックを使うことを想定しています。 更に、 "1月顧客別商品別.xls"、こちらにあって、 "顧客別管理.xlsx"にない商品コードは想定していません。 つまり、マッチングしなかったものは、無視しています。 想定するのであれば、どのように扱えばいいのかを説明してみてください。 Option Explicit  Const SRowA = 9  Const ERowA = 32  Const SRowB = 39  Const ERowB = 62    Dim cn As Object  Dim rs As Object  Dim wb As Workbook Sub MainJob()  Dim ShCnt As Long  Dim KCode As String  Set wb = Workbooks.Open(ThisWorkbook.Path & "\" & "顧客別管理.xlsx")  'SQL環境を準備  Set cn = CreateObject("ADODB.Connection")  Set rs = CreateObject("ADODB.Recordset")  cn.Provider = "Microsoft.ACE.OLEDB.12.0"  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1"  cn.Open ThisWorkbook.Path & "\1月顧客別商品別.xls"  For ShCnt = 4 To wb.Sheets.Count - 2   KCode = wb.Sheets(ShCnt).Name   Call Tenki(KCode, 11) '11列目に出力  Next ShCnt    Set rs = Nothing '以下後処理  cn.Close  Set cn = Nothing End Sub Sub Tenki(KCode As String, PutCol As Long)  Dim SQL As String  Dim i As Long    'SQL全文を組み立てて実行  SQL = "SELECT *" & vbCrLf  SQL = SQL & "FROM [" & "集計$A1:E1000]" & vbCrLf  'SQL = SQL & "Where [顧客コード] = " & "'" & KCode & "'" & vbCrLf '注1  SQL = SQL & "Where [顧客コード] = " & KCode & vbCrLf       '注2  rs.Open SQL, cn  With wb.Sheets(KCode) 'マッチングして売上げ、粗利を転記   If Not rs.EOF Or Not rs.Bof Then    rs.MoveFirst    Do     If rs.EOF = True Then Exit Do     For i = SRowA To ERowA      If .Cells(i, 1).Value = "" Then Exit For  '注3      If .Cells(i, 1).Value = rs("商品コード") Then       .Cells(i, PutCol).Value = rs("売上高")      End If     Next i     rs.MoveNext    Loop      rs.MoveFirst    Do     If rs.EOF = True Then Exit Do              For i = SRowB To ERowB      If .Cells(i, 1).Value = "" Then Exit For  '注3      If .Cells(i, 1).Value = rs("商品コード") Then       .Cells(i, PutCol).Value = rs("粗利")      End If     Next i     rs.MoveNext    Loop     End If  End With    rs.Close '後処理   End Sub

その他の回答 (5)

  • chayamati
  • ベストアンサー率41% (260/624)
回答No.6

>2つのExcelファイル(1月顧客別商品別.xlsと顧客別管理.xlsx)で 顧客コードと商品コードの双方が一致しているものの売上高と粗利を  顧客別管理.xlsxの対応欄(商品別になっている) ★どのように回答するのか、分りませんが以下がヒントに成りませんか  >印があなたの分で、★印が回答です >(1月の売上高の入力欄:K9~K32、粗利の入力欄:K39~62)に入力  させるVBAを作りたく ★入力の制御はVBAでなくセルの書式の保護のロックと  書式の保護ツールです   (1月の売上高の入力欄:A1に「売上高」、B1に「粗利」と入力して   「A2~A22」に1月の売上高の入力欄   「B2~B22」に1月の粗利の入力欄 >なお、前提条件として、  1月顧客別商品別.xls:集計シートのA~E列に顧客コード、  顧客名、商品コード、売上高、粗利が2行目以降並んでいます。  顧客別管理.xlsx:左から4枚目~最後から数えて3ページ目までの  シートがそれぞれ顧客別のシートで、それぞれシート名が  顧客コードになっていて、B列に売上高の商品一覧(B9~B32)・粗利の  商品一覧(B39~B62)が並んでおり、検索しやすくなるために  それぞれ対応する行のA列に商品コードを入力してあります。 ★これもVBAでなく、文字列結合(=C2&B2)とSUMIF()関数で  処理します。添付をご覧ください  何れにしろ他の回答者様の仰る通り、私もAccessをお勧めします。  利用料も他の宛名作成ソフト、セキュリティーソフトと大差有りません

  • HohoPapa
  • ベストアンサー率65% (455/693)
回答No.4

SQLを一部で使ったコードとしてみました。 よかったら試してみてください。 ただし、 顧客コードが文字列の場合は注1を生かし、注2をコメントアウトしてください。 また、 顧客別管理.xlsxのA9,B9以下とA39,B39以下が上詰めではない場合は 注3をコメントアウトしてください。 なお >"1月顧客別商品別.xls":”集計”シートのA~E列に >”顧客コード”、”顧客名”、”商品コード”、”売上高”、”粗利”が2行目以降並んでいます。 これは、顧客コードと商品コード組み合わせでは重複がないということでいいですよね? これを前提としたコードです。 それとも、重複があり、"顧客別管理.xlsx"に合計転記しますか? また、課題のブック2つとは別にマクロブック専用ブックを使うことを想定しています。 更に、 "1月顧客別商品別.xls"、こちらにあって、 "顧客別管理.xlsx"にない商品コードは想定していません。 つまり、マッチングしなかったものは、無視しています。 想定するのであれば、どのように扱えばいいのかを説明してみてください。 Option Explicit  Const SRowA = 9  Const ERowA = 32  Const SRowB = 39  Const ERowB = 62    Dim cn As Object  Dim rs As Object  Dim wb As Workbook Sub MainJob()  Dim ShCnt As Long  Dim KCode As String  Set wb = Workbooks.Open(ThisWorkbook.Path & "\" & "顧客別管理.xlsx")  'SQL環境を準備  Set cn = CreateObject("ADODB.Connection")  Set rs = CreateObject("ADODB.Recordset")  cn.Provider = "Microsoft.ACE.OLEDB.12.0"  cn.Properties("Extended Properties") = "Excel 12.0;HDR=Yes;IMEX=1"  cn.Open ThisWorkbook.Path & "\1月顧客別商品別.xls"  For ShCnt = 4 To wb.Sheets.Count - 2   KCode = wb.Sheets(ShCnt).Name   Call Tenki(KCode, 11) '11列目に出力  Next ShCnt    Set rs = Nothing '以下後処理  cn.Close  Set cn = Nothing End Sub Sub Tenki(KCode As String, PutCol As Long)  Dim SQL As String  Dim i As Long    'SQL全文を組み立てて実行  SQL = "SELECT *" & vbCrLf  SQL = SQL & "FROM [" & "集計$A1:E1000]" & vbCrLf  'SQL = SQL & "Where [顧客コード] = " & "'" & KCode & "'" & vbCrLf '注1  SQL = SQL & "Where [顧客コード] = " & KCode & vbCrLf       '注2  rs.Open SQL, cn  With wb.Sheets(KCode) 'マッチングして売上げ、粗利を転記   If Not rs.EOF Or Not rs.Bof Then    rs.MoveFirst    Do     If rs.EOF = True Then Exit Do     For i = SRowA To ERowA      If .Cells(i, 1).Value = "" Then Exit For  '注3      If .Cells(i, 1).Value = rs("商品コード") Then       .Cells(i, PutCol).Value = rs("売上高")      End If     Next i     rs.MoveNext    Loop      rs.MoveFirst    Do     If rs.EOF = True Then Exit Do         '注3     For i = SRowB To ERowB      If .Cells(i, 1).Value = "" Then Exit For      If .Cells(i, 1).Value = rs("商品コード") Then       .Cells(i, PutCol).Value = rs("粗利")      End If     Next i     rs.MoveNext    Loop     End If  End With    rs.Close '後処理   End Sub

  • HohoPapa
  • ベストアンサー率65% (455/693)
回答No.3

他の方のコメントに同意であり、 さすがに厳しいデータ構成と思いますし、 DBを使った仕組みが望ましいものの、 簡単に移行できるわけではないでしょう。 なので、現データ構成まま、若干泥臭いものの、 また、実用に耐えるかどうかはわかりませんが 若干効率のよさそうなコードを提示したいと思っています。 そこで、コーディングするにあたり、以下を教えてください。 ・1月顧客別商品別.xlsにはどの程度のレコード数がありますか? ・顧客別管理.xlsxにはどの程度のシート数がありますか? ・顧客コード、商品コードは数値ですか?、文字列ですか? ・顧客別管理.xlsxのA9,B9以下とA39,B39以下には、  上詰めでコードと商品名が埋まっていますか?  それとも、空行が途中に含まれますか?

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

(1)アクセスで処理されることを勧めます。SQLが使えるソフトを使うことですね。 >2つのExcelファイル("1月顧客別商品別.xls"と"顧客別管理.xlsx")においてをキーで結合し、結合したものを処理する。データをアクセスにエクスポートやエクセルにインポートは各1行で済むだろう。 そのキーは「顧客コードと商品コード」の2つでしょう。 こういうことに頭が行かないのは、エクセルしかやってなくて、データベースの処理の本途を知らないからです。見聞を広く持つべきです。 ーー (2)VBAで、SQL無しで、やるなら、両ファイルを、2つのキーでMatching(俗語の意味でなく、コンピュターの昔から使われたアルゴリズムの1つの名称)して、両ファイルの2つのキーが一致した、レコード(行データ)を捉えて項目(売上高と粗利)をどちらかファイルに、情報追加(項目追加)します。 このアルゴリズムは、情報処理の試験のアルゴリズムに出てきます。 マッチングはファイル情報結合の1つのやり方なのです。 ーー これは両ファイル(=両シートのデータ)をキー(顧客コード+商品コード(列))でソートしておいて処理に入ります。 そのためDictionary的なものを作らなくても済みます。昔は内部メモリーが少なく、Dictionary作成は 避けられた。効率のよい、ソートのソフトだけは、マシン・メーカーが全力で開発してくれていた。 ==== どちらかに考え直すことを、質問者の将来の仕事のため、スキルの拡充のために、勧める。 Googleで「マッチング アルゴリズム フローチャート」などで照会してみて。

  • bardfish
  • ベストアンサー率28% (5029/17766)
回答No.1

まず大前提。 ExcelではVBAを使用した対利用のデータ処理は不向きです。 データベースみたいにキーやインデックスがないんだからサーチはもの凄く遅い。改善の余地はない。 改善できるとしたら作業用のシートに処理しやすい形でデータを整理したモノを事前に作っておきそれを対象とする。 似たようなことで単純な内容(でもないけどw)をVBAでやったことありますが、本番データでのテストに時間がかかりすぎて、でも与えられた時間は少ないためぶち切れそうになったのでAccessで作り直しました。 処理にかかる時間が10分の1以下に短縮。 数百万行のデータ処理だったのでExcelだけでは(*>д<*)ムリー! Excelはデータを眺める目的なら最高のツールですけど、VBAを使用したデータ処理には剥いていない、と言うのをExcel95の時に悟りました。 Access2.0が出たら早速乗り換え。 Access95?だったかな、の頃にはOracleとSQL Serverに乗り換えました。 VBAが使えたのでプログラミング言語はVisual Basic。 VBは今なら無料で使えるモノがダウンロードできます。だけどマニュアルはない。ないけど普通に使ってSQLServerと組み合わせてデータ処理してます。 SQLServerも無料で使えるモノがダウンロードできる。もちろん説明書はない。だけどSQLServer4の時に覚えたことが今でも使えるのはある意味凄い。

関連するQ&A

専門家に質問してみよう