• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:二つのシートで同一IDのものをまとめる方法2)

二つのシートで同一IDのものをまとめる方法2

このQ&Aのポイント
  • エクセルで作成された二つの製品表を一つにする作業にてこずっています。
  • 製品表1には、同一のIDが二つ以上存在しません。
  • 製品表2には、同一のIDが1~3存在します。

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

  • ベストアンサー
  • mpro-gram
  • ベストアンサー率74% (170/228)
回答No.1

マクロは解らないけど、対応させるためのカラムを追加して、セルに式を構築していけば、Vlookup 関数でいけそうだけど。 Vlookupの参照は、先頭の1カラム対応だから、 1.まず、表2(Sheet2とする)の方に、A列手前にもう一つカラムを足して、ID+codename を作る =CONCATENATE(B2,C2) A列2行目に上記の式を入れたら、コピーして下方の行全部にペースト(以下の作業は皆一行作ったらそれをコピーして下方の行にペーストすると、全部すぐ計算される) Sheet2 は、以下の列になる A列( 式 =CONCATENATE(B2,C2) )、B列(id)、C列(codename)、D列(各番号) ちなみに、一行目には、カラムの項目名が入ってることとして、2行目以降をデータとして説明しています。 2.Sheet2を、上記で追加したA列で並べ替えしておく 3.表1(Sheet1とする)へ戻り、各行の M,N,O列に、比較用に id+"Unit" などの文字列を作る M列( 式 =CONCATENATE($A2,"Unit") )、N列( 式 =CONCATENATE($A2,"Box") )、O列( 式 =CONCATENATE($A2,"Pallet") ) ※ コード数が4つ以上有るなら、その分を、P,Q列などにも作成しておきます。コード数増加に対応するなら、X列からとか、AA列からの方がいいかも 4.Sheet1!C列2行目にVlookup計算式を入れる、範囲指定のところは、Sheet2 の2行目以降全部が入るようにする。つまり$80のところは適宜書き換えること =VLOOKUP(M2,Sheet2!$A$2:$D$80,4,FALSE) 同じく sheet1のD,E列同じ行に上記コピーペーストすると以下のデータが入る D列 =VLOOKUP(N2,Sheet2!$A$2:$D$80,4,FALSE) E列 =VLOOKUP(O2,Sheet2!$A$2:$D$80,4,FALSE) コードの数だけ、コピーペーストで列を作ります。 ※ Sheet2!D 列で、データがないと、上記計算結果は 0 が入ってしまうので、空文字列としたいなら、Sheet2!D 列で、データがないセルには、先頭に ' のみを入れて空文字列としておいて下さい 5.仕上げに、Sheet1のA列からL列まで全体をコピーして、Sheet3 または別のファイルに、「形式を選択して貼り付け」→「値」にチェックしてペースト実行  こちらの 値だけ貼り付けた物は、元のSheet2のデータ変更が反映されないが、Sheet1 のM列以降がない表として使える Vlookupでマッチするデータがないと、 #N/A と表示されるが、これは、値コピーしたシートでなら、マクロで消せるだろう。

その他の回答 (1)

回答No.2

初歩的なことですが Dim ID1, ID2, Code, EAN, VL, PU As String ではなく、 Dim ID1 As String, ID2 As String, Code As String, EAN As String, VL As String, PU As String と書きます。 ID1, ID2, Code, EAN, VL は型指定を省略したとみなされ Variant 型になります。 次に、 Dim row1, row2, c1, c2 As Integer ではなく、 Dim row1 As Long, row2 As Long, c1 As Long, c2 As Long と書きます。 Integer 型は -32768 から 32767 の範囲しか表現できません。つまり、 32767 行までしか処理できません。 Long 型を使用して下さい。 -2147483648 から 2147483647 の範囲を表現できるのですべての行を処理できます。 要約すると VB は Pascal ではありません。 VB の言語仕様(わりとひどい。といっても古い言語で古いPC(16ビット時代)との互換性だからしかたない)を確認して下さい。(とは言っても、公式資料も何年も修正されていない間違いがあるので注意が必要なんですが・・・。まあ、マイクロソフトが .NET を押しているからしかたないですね。 「VBA なんて使わず .NET 使ってね」な感じですからね。) あと、用語が一般的でないのが気になりますが・・・。 一般的には row = 行 で、段ではあまり数えません。 Word の場合には paragraph = 段 とするのが適当ですが・・・。 本題ですが Excel DB 状態なので、データ接続(SQL)を使うのが一般的だと思います。 以下の手順の説明はExcel2007です。 まず、製品表1(Items シート)に ITEM_TABLE と名前を定義します。 手順は、製品表1の範囲を選択して(列名を含めて選択します)、数式タブの定義された名前グループの名前の定義をクリックします。新しい名前ダイアログで名前欄に「ITEM_TABLE」と入力してOKで名前を定義します。 次に、製品表2(uom シート)に UOM_TABLE と名前を定義します。 手順は同様です。 ファイルを保存します。(仮に W:\Excel DB.xlsb とします。バイナリ形式です。) データタブの外部データの取り込みグループのその他のデータソースをクリックします。データ接続ウィザードをクリックします。 「ODBC DSN」を選択し次へ、「Excel Files」を選択し次へ、このファイルを選択します。 次へ、完了。 データのインポートダイアログでプロパティをクリック 接続のプロパティダイアログで「使用」タブの「バックグラウンドで更新する」のチェックを外します。 「定義」タブの「コマンド文字列」にSQLを指定します。 製品表1(ITEM_TABLE)は ID と NAME の2つの列を持ちます。以下、テストデータ ID NAME 000128 product1 0KV502 product2 製品表2(UOM_TABLE)は ID, CODE, QTY, EAN, VL, WEIGHT, PU と PP の8つの列を持ちます。以下、テストデータ ID CODE QTY EAN VL WEIGHT PU PP 000128 UNIT 000128 U QTY 000128 U EAN 000128 U VL 000128 U WEIGHT 000128 U PU 000128 U PP 000128 BOX 000128 B QTY 000128 B EAN 000128 B VL 000128 B WEIGHT 000128 B PU 000128 B PP 000128 PALLET 000128 P QTY 000128 P EAN 000128 P VL 000128 P WEIGHT 000128 P PU 000128 P PP 0KV502 UNIT 0KV502 U QTY 0KV502 U EAN 0KV502 U VL 0KV502 U WEIGHT 0KV502 U PU 0KV502 U PP 0KV502 PALLET 0KV502 P QTY 0KV502 P EAN 0KV502 P VL 0KV502 P WEIGHT 0KV502 P PU 0KV502 P PP 上記の構成に対して下のSQL文をコマンド文字列に指定します。 SELECT i.ID AS ITEM_ID, i.NAME AS ITEM_NAME, MAX(IIF(u.CODE = 'UNIT', u.CODE, null)) As Unit_Code, MAX(IIF(u.CODE = 'UNIT', u.EAN, null)) As Unit_EAN, MAX(IIF(u.CODE = 'UNIT', u.VL, null)) As Unit_VL, MAX(IIF(u.CODE = 'UNIT', u.PU, null)) As Unit_PU, MAX(IIF(u.CODE = 'UNIT', u.QTY, null)) As Unit_QTY, MAX(IIF(u.CODE = 'UNIT', u.WEIGHT, null)) As Unit_WEIGHT, MAX(IIF(u.CODE = 'UNIT', u.PP, null)) As Unit_PP, MAX(IIF(u.CODE = 'BOX', u.CODE, null)) As Box_Code, MAX(IIF(u.CODE = 'BOX', u.EAN, null)) As Box_EAN, MAX(IIF(u.CODE = 'BOX', u.VL, null)) As Box_VL, MAX(IIF(u.CODE = 'BOX', u.PU, null)) As Box_PU, MAX(IIF(u.CODE = 'BOX', u.QTY, null)) As Box_QTY, MAX(IIF(u.CODE = 'BOX', u.WEIGHT, null)) As Box_WEIGHT, MAX(IIF(u.CODE = 'BOX', u.PP, null)) As Box_PP, MAX(IIF(u.CODE = 'PALLET', u.CODE, null)) As Pallet_Code, MAX(IIF(u.CODE = 'PALLET', u.EAN, null)) As Pallet_EAN, MAX(IIF(u.CODE = 'PALLET', u.VL, null)) As Pallet_VL, MAX(IIF(u.CODE = 'PALLET', u.PU, null)) As Pallet_PU, MAX(IIF(u.CODE = 'PALLET', u.QTY, null)) As Pallet_QTY, MAX(IIF(u.CODE = 'PALLET', u.WEIGHT, null)) As Pallet_WEIGHT, MAX(IIF(u.CODE = 'PALLET', u.PP, null)) As Pallet_PP FROM `W:\Excel DB.xlsb`.ITEM_TABLE i, `W:\Excel DB.xlsb`.UOM_TABLE u WHERE i.ID = u.ID GROUP BY i.ID, i.NAME 「このブックの接続先は~」が表示されたら「はい」をクリックします。 出力先はとりあえず新規シートにでもしておいて下さい。 備考 XML形式よりもバイナリ形式の方がパフォーマンスがいいはずです。 SQL文のファイルパスを指定(変更)する箇所が2カ所なので注意して下さい。 ここまで、解説しておいてなんですが、Excelファイル(ADO、ODBC)に対してSQL文を実行するのではなく大本のデータベースに対してSQL文を実行してExcelにデータを返すようにしてください。 まあ、セキュリティの都合でExcelファイルにダウンロードしたデータベースのデータしか操作できないなら別ですが・・・。

関連するQ&A

専門家に質問してみよう