エクセル2007 VBA シート内のデータを項目名で検索し、その列を新規シートにコピーする方法

このQ&Aのポイント
  • エクセル2007 VBAを使用して、シート内のデータを項目名で検索し、その列を新規シートにコピーする方法についての質問です。
  • VBA初心者の方が、グーグルで調べながら作成したコードで、コピー後のペーストがうまくできないという問題が発生しています。
  • 質問者は、最後まで処理を行うための方法と、コードの改善点を教えて欲しいとしています。
回答を見る
  • ベストアンサー

エクセル2007 VBA シート内のデータを項目名で検索し、その列を新

エクセル2007 VBA シート内のデータを項目名で検索し、その列を新規シートにコピーする方法についてです。 VBAについては初心者で、グーグルで調べながら作ったのですが、コピー後のペーストが上手く出来ません。どうすれば最後まで処理できるのかを教えて下さい。 それと、全体的に書き方がおかしいところがありましたら指摘・改善方法を教えて下さい。 よろしくお願いします。 Sub 配列並べ替え() Dim myArray As Variant '1項目名希望順配列格納 Dim strArray As Variant '2検索用1の配列格納 Dim LastCol1 As Long '3最終列数格納 Dim LastCol2 As Long '4新規シートの最終列数格納 Dim DefSheetname As Variant '5初期のシート名取得 Dim i As Long Dim j As Long '初期シート名を取得。 DefSheetname = ActiveSheet.Name '初期シートの最終列数取得。 LastCol1 = Worksheets(DefSheetname).Range("A1").End(xlToRight).Column 'シート名:レポートの新規シート追加。 Worksheets.Add.Name = "レポート" '初期シートを選択。 Worksheets(DefSheetname).Select '項目名希望順配列格納。 myArray = Array("得意先C", "取引先名1", "製番", "相手管理NO", "品目C", _ "製品名1", "受注数", "受注残数", "納期", "受注単価", _ "受注金額", "出荷数", "出荷金額", "出荷先名1", "郵便番号", "住所1", "TEL", "FAX") '配列要素数分繰り返し処理。 For i = LBound(myArray) To UBound(myArray) '検索用の配列(項目名)格納。 strArray = myArray(i) 'A1:LastCol1範囲で配列(項目名)検索し、番号で返す。 j = WorksheetFunction.Match(strArray, Worksheets(DefSheetname).Range(Cells(1, 1), Cells(1, LastCol1)), 0) 'シート名:レポートに変数jの列数目の値を入力。 Columns(j).Copy 'シート名:レポートの最終列数取得。 LastCol2 = Worksheets("レポート").Range("A1").End(xlToRight).Column 'シート名:レポートを選択。 Worksheets("レポート").Select Range(Cells(1, 1), Cells(1, "LastCol2")).Past Next i End Sub

  • msnok
  • お礼率18% (5/27)

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

  • ベストアンサー
  • end-u
  • ベストアンサー率79% (496/625)
回答No.1

現在のコードで取り敢えず動くようにするなら Sub 配列並べ替え()  Dim myArray   As Variant '1項目名希望順配列格納  Dim strArray   As Variant '2検索用1の配列格納  Dim LastCol1   As Long  '3最終列数格納  Dim LastCol2   As Long  '4新規シートの最終列数格納  Dim DefSheetname As Variant '5初期のシート名取得  Dim i      As Long  Dim j      As Long  Dim k      As Long  '初期シート名を取得。  DefSheetname = ActiveSheet.Name  '初期シートの最終列数取得。  LastCol1 = Worksheets(DefSheetname).Range("A1").End(xlToRight).Column  'シート名:レポートの新規シート追加。  Worksheets.Add.Name = "レポート"  '初期シートを選択。  Worksheets(DefSheetname).Select  '項目名希望順配列格納。  myArray = Array("得意先C", "取引先名1", "製番", "相手管理NO", _          "品目C", "製品名1", "受注数", "受注残数", _          "納期", "受注単価", "受注金額", "出荷数", _          "出荷金額", "出荷先名1", "郵便番号", "住所1", _          "TEL", "FAX")  k = 1  '配列要素数分繰り返し処理。  For i = LBound(myArray) To UBound(myArray)   '検索用の配列(項目名)格納。   strArray = myArray(i)   j = 0   With Worksheets(DefSheetname)    On Error Resume Next    'A1:LastCol1範囲で配列(項目名)検索し、番号で返す。    j = WorksheetFunction.Match(strArray, .Range(.Cells(1, 1), .Cells(1, LastCol1)), 0)    On Error GoTo 0    If j > 0 Then     'シート名:レポートに変数jの列数目の値を入力。     .Columns(j).Copy Worksheets("レポート").Cells(k)     k = k + 1    End If   End With  Next i End Sub ..こんな感じです。見比べてください。 でもちょっと効率悪そうですので myArrayの項目名が元データに【必ずある】事が保障される場合は[フィルタオプション]が使えます。 Sub test1()  Dim myArray As Variant  Dim r    As Range  On Error GoTo extLine  myArray = VBA.Array("得意先C", "取引先名1", "製番", "相手管理NO", _            "品目C", "製品名1", "受注数", "受注残数", _            "納期", "受注単価", "受注金額", "出荷数", _            "出荷金額", "出荷先名1", "郵便番号", "住所1", _            "TEL", "FAX")  Set r = ActiveSheet.UsedRange  With Worksheets.Add   .Name = "レポート"   With .Range("A1").Resize(, UBound(myArray) + 1)    .Value = myArray    r.AdvancedFilter Action:=xlFilterCopy, _             CopyToRange:=.Cells, _             Unique:=False   End With  End With extLine:  Set r = Nothing  If Err.Number <> 0 Then MsgBox Err.Number & "::" & Err.Description End Sub

msnok
質問者

補足

返信遅くなりすみません。 3種類もサンプルありがとうございました。 >・・・【必ずある】事が保障される場合・・・ 配列の項目があるかどうかを判別してから処理するべきですね^^; 一番最初に記入していただいたサンプルを元に、判別処理など一部追記して使える様になりました。 最後に記入していただいたサンプルは、まだ理解できない部分が多いので勉強の参考にします。 ありがとうございました。 この後、VBAで別の質問をするのでよろしければ、また力を貸して下さい。 よろしくお願いします。

その他の回答 (2)

回答No.3

おかしいところがいくつかありますのでご指摘させていただきます。 シート名:レポートの新規シート追加してますよね? Worksheets.Add.Name = "レポート" なのに・・シート名:レポートの最終列数取得してますよね? 下記コードは一番右の列を見に行っている為、新規時点で256行となるはず。 LastCol2 = Worksheets("レポート").Range("A1").End(xlToRight).Column ↓ LastCol2 = Worksheets("レポート").cells(1,256).End(xlToLeft).Column またコピー、貼り付けのコードもおかしいです。 コピーのときは一行をコピーしてますが、貼り付け時は範囲指定がおかしい・・ あと、『LastCol2』は変数なのに””でくくってしまったら文字列として判断してしまいますよ。 シート名:レポートに変数jの列数目の値を入力。 Columns(j).Copy Range(Cells(1, 1), Cells(1, "LastCol2")).Past ↓ Columns(LastCol2).paste

msnok
質問者

補足

返信遅くなりすみません。 ご指摘ありがとうございました。 あやふやなところが多い為、参考になりました。 また質問をするつもりなので、よろしければまた力を貸して下さい。 よろしくお願いします。

  • end-u
  • ベストアンサー率79% (496/625)
回答No.2

もしくは、丸ごとコピーして順番をセットし、列単位で並べ替えたあとに不要な列を削除したほうが良さそうです。 Sub test2()   Dim myArray As Variant   Dim r    As Range   Dim tmp   As Range      On Error GoTo extLine   myArray = Array("得意先C", "取引先名1", "製番", "相手管理NO", _           "品目C", "製品名1", "受注数", "受注残数", _           "納期", "受注単価", "受注金額", "出荷数", _           "出荷金額", "出荷先名1", "郵便番号", "住所1", _           "TEL", "FAX")   Set r = ActiveSheet.UsedRange   With Worksheets.Add     .Name = "レポート"     r.Copy .Range("A2")     Set r = .Range("A2").CurrentRegion.Rows(1).Offset(-1)     r.Value = Application.Match(r.Offset(1), myArray, 0)     r.CurrentRegion.Sort Key1:=.Range("A1"), _                Order1:=xlAscending, _                Header:=xlNo, _                OrderCustom:=1, _                MatchCase:=False, _                Orientation:=xlLeftToRight, _                SortMethod:=xlStroke     On Error Resume Next     Set tmp = r.SpecialCells(xlCellTypeConstants, xlErrors)     On Error GoTo 0     If Not tmp Is Nothing Then       tmp.EntireColumn.Delete     End If     .Rows(1).Delete   End With extLine:   Set tmp = Nothing   Set r = Nothing   If Err.Number <> 0 Then MsgBox Err.Number & "::" & Err.Description End Sub

関連するQ&A

  • VBA 類似シート名 処理

    シート名が、「一覧 (2)」、「一覧 (3)」、・・・・・「一覧 (n)」、と連続する各シートの表データを「一覧」という名前のシートにまとめたいのですが、やり方が分かりません。 For Each を使えば出来るんじゃないかと調べましたが、見付けられませんでした。 シート処理以外は、   Dim CoR As Long, PaR As Long, PaR2 As Long CoR = Worksheets(???).Cells(Rows.Count, 1).End(xlUp).Row PaR = Worksheets("一覧").Range(Rows.Count, 1).End(xlUp).Row PaR2 = CoR + PaR + 1 Worksheets(???).Range(Cells(2, 1), Cells(CoR, 12)).Copy Worksheets("一覧").Range(Cells(PaR, 1), Cells(PaR2, 12)).PasteSpecial Paste:=xlPasteValues こんな感じで作っています。 作り方、もしくは参考になるサイトがありましたら、教えていただければありがたいです。 よろしくお願いします。

  • Excel VBA でVLookUPの質問

    教えてください。 Excel VBA でVLookUPを使用したいのですが 毎回シート名も数も変わります。 そのため、検索範囲 のシート名をセル値が取得したいのですが どうすればよいでしょうか? 検索値 = AシートB列 検索範囲=BシートM列 書出し範囲=AシートU列 下記のコード作成しましたが ws = Worksheets("②価格集計").Range("U2").Value 検索用格納配列(i, 1) = "=VLOOKUP(B" & i + 1 & ",ws!A:M,13,0)" でエラーがでます。 他に方法があれば教えてください。 宜しくお願い致します。 Sub test() Dim 検索値 As Range '検索値 Dim 検索用格納配列 As Variant '検索用格納配列 Dim 出力範囲 As Range '出力範囲 Dim i As Long Dim 検索範囲 As Range Dim endrow As Long Dim ws As Worksheet endrow = Sheets("①SPOT売却明細貼付").Range("B" & Rows.Count).End(xlUp).Row Set 検索値 = Worksheets("②価格集計").Range("B3:B302") Set 出力範囲 = Worksheets("②価格集計").Range("U3:U302") ws = Worksheets("②価格集計").Range("U2").Value 検索範囲 = Worksheets(社名).Range("A:M") 検索用格納配列 = Range(検索値, 出力範囲) For i = 1 To endrow 検索用格納配列(i, 1) = "=VLOOKUP(B" & i + 1 & ",ws!A:M,13,0)" Next 出力範囲 = 検索用格納配列 End Sub

  • ExcelのVBAの配列に関する質問です。

    ExcelのVBAの配列に関する質問です。 sheet1のデータをsheet2に表示するVBAを作成しています。。 sheet1のデータは7行目からスタートし、sheet2のデータは26行目からスタートしています。。 sheet1とsheet2の列は同じ並びではないため、それぞれのシートの列番号をCellsを用いて指定しています。 Sub test1() Dim endrow As Long endrow = Worksheets("sheet1").Range("A65536").End(xlUp).Row Dim i As Long Dim j As Long For i = 7 To endrow j = i + 19 Worksheets("sheet2").Cells(j, 1) = Worksheets("sheet1").Cells(i, 2) Worksheets("sheet2").Cells(j, 8) = Worksheets("sheet1").Cells(i, 28) Worksheets("sheet2").Cells(j, 9) = Worksheets("sheet1").Cells(i, 31) Worksheets("sheet2").Cells(j, 10) = Worksheets("sheet1").Cells(i, 32) ・ ・ ・ ※長いので省略 Next i End Sub 上記のtest1は正常に動くのですが、データ量が多いため、処理に時間がかかってしまいます。 高速化できないかと、以下のように変更しました。 Sub test2() Dim dataRange1 As Variant Dim dataRange2 As Variant dataRange1 = Worksheets("sheet1").Range("A1:GI10006") dataRange2 = Worksheets("sheet2").Range("A1:DZ10018") Dim endrow As Long endrow = Worksheets("sheet1").Range("A65536").End(xlUp).Row Dim i As Long Dim j As Long For i = 7 To endrow j = i + 19 dataRange2(j, 1) = dataRange1(i, 2) dataRange2(j, 8) = dataRange1(i, 28) dataRange2(j, 9) = dataRange1(i, 31) dataRange2(j, 10) = dataRange1(i, 32) ・ ・ ・ ※長いので省略 Next i End Sub test2は、エラーメッセージ等は表示されませんが、sheet2にデータが表示されません。 ちなみに、以下のようにsheet1のみ配列化した場合は、正常に表示されました。 Worksheets("sheet2").Cells(j, 1) = dataRange1(i, 2) Worksheets("sheet2").Cells(j, 8) = dataRange1(i, 28) Worksheets("sheet2").Cells(j, 9) = dataRange1(i, 31) Worksheets("sheet2").Cells(j, 10) = dataRange1(i, 32) test2は、どこが間違っているのでしょうか? ご教示ください。 よろしくお願いいたします。

  • エクセルVBAについて

    前回質問させていただきました件の追加機能になります。以前質問させていただきましたマクロが下記のものです。 Sub TESTa() Dim A As Long Dim B As Long Dim C As Long Dim D As Long Dim E As Long Dim F As Long '表の行数を調べる A = Worksheets("sheet1").Range("C65536").End(xlUp).Row - 1 For C = 1 To A For B = 4 To 7 'Sheet1のデータをSheet2に複写する Worksheets("Sheet2").Cells(B - 3 + D, 15) = Worksheets("Sheet1").Cells(C + 1, 1) Worksheets("Sheet2").Cells(B - 3 + D, 6) = Worksheets("Sheet1").Cells(C + 1, B) Worksheets("Sheet2").Cells(B - 3 + D, 14) = Worksheets("Sheet1").Cells(C + 1, 3) Worksheets("Sheet2").Cells(B - 3 + D, 10) = Worksheets("Sheet1").Cells(1, B) Worksheets("Sheet2").Cells(B - 3 + D, 13) = Worksheets("Sheet1").Cells(C + 1, 2) Next D = C * 4 Next 'Sheet2の表の行数を調べる Sheets("Sheet2").Select E = Worksheets("sheet2").Range("F65536").End(xlUp).Row '0欄の確認 For F = E To 1 Step -1 If Worksheets("Sheet2").Cells(F, 6) = 0 Then '0の場合は行を削除する Cells(F, 1).EntireRow.Delete End If Next End Sub カウントするとデータ個数がSheet1で約120件になりSheet2においては、4倍になりますので約480件になります。 そこで Sheet1において12件ごとに、Sheet2,3,4...としたいのです。 Sh1 NO.1~12がSheet2 Sh1 NO.13~24がSheet3 ... 10枚のシートにしたいのですが、このマクロにどのような命令を加えればよろしいでしょうか? お手数ですがよろしくお願いいたします。

  • Excel 文字列を検索して全て置換するマクロ

    当方VBA初心者なのですが、ExcelのVBAで作ったマクロでうまく動かなくて困っています。 もしおわかりになる方がいらっしゃったら是非よろしくお願いいたします。 *実現したいこと '”reference”という名前のシートに、次のようなデータが入っています。 (1) りんご (2) みかん (3) キウイ ・・・ これを、配列を2つ用意し、 (1)を配列Listに、(2)を配列List2へ格納して行きます。 '"data"という名前のシートには、A列の1~10行目までに文章が入っていて、 "家には、(1)があります。" "冬になるとよく(2)を食べます。" ・・・・ この全文をcというRangeに設定し、そのcの中において、 もし、配列1((1)等)のキーワードがあったら、 'そのキーワードを配列2(りんご等)の内容に書き換える。 'キーワードは、データシートに複数回出てくる場合もある。 *困っていること 下記のマクロだと、一度目のObjFindまでは成功するのですが、 List(i)を探しているはずが、2回目から、その変更後の文字列が含まれた全文を検索するようになってしまいます。 以下マクロです。 よろしくお願いいたします。 Sub TEST() Dim List() As String, List2() As String 'List Dim i As Integer Dim iRow As Integer iRow = Worksheets("reference").Cells(Rows.Count, 1).End(xlUp).Row ReDim List(iRow) ReDim List2(iRow) For i = 1 To iRow List(i) = Worksheets("reference").Cells(i, 1).Value List2(i) = Worksheets("reference").Cells(i, 2).Value Next i Dim lngYLine As Long Dim intXLine As Integer Dim objFind As Object Dim strAddress As String Dim strSamp As String Dim objRange As Range Dim c As Range For i = 1 To iRow Set objRange = Worksheets("data").Range("A1:A331") Set objFind = objRange.Cells.Find(List(i)) If Not objFind Is Nothing Then For Each c In objRange If c.Value = objFind Then lngYLine = objFind.Cells.Row intXLine = objFind.Cells.Column strSamp = Worksheets("data").Cells(lngYLine, 1) strSamp = Replace(strSamp, List(i), List2(i)) Worksheets("data").Cells(lngYLine, 1) = strSamp MsgBox List(i) + "は" + List2(i) + "に変更されました" Set objFind = Cells.FindNext(objFind) End If Next c Else MsgBox List(i) + "は見つかりませんでした" End If Next i End Sub

  • 異なるシートの配列を参照し、相関係数を求める方法

    visual basicを学んでまだ1週間です。 Sheet1とSheet2に配列が格納されているのですが、これらを用いて相関係数が求めたいのですが、うまくいきません。 どのように書いているかというと、 Sub 2つのシート間の配列から相関係数を求める() Dim correlation as Double correlation = Application.WorksheetFunction.Correl(Worksheets("Sheet1").Range(Cells(1, 2), Cells(1, 567)), Worksheets("Sheet2").Range(Cells(1, 2), Cells(1, 567))) Cells(2,1).Value = correlation End 添削よろしくおねがいします。

  • VBA 新データ行のみ元のデータシートにコピーする

    OSは、XP Excelは、2003 を使用しています。 シート1には元のデータ、シート2には追加データと元データが混じってあります。 元データシートに、追加データシートから追加データ行のみをコピペしたく、 マクロを組んでいます。 下記、 C列の売上番号を見比べて、C列のみ追記するまでは出来たのですが、 1行にデータはA列~X列まであるので、そのデータも一緒にコピペするには どの様にすれば良いのか教えて下さい。 よろしくお願いします。 ****************** Sub 追加データ追記マクロ() Dim motows As Worksheet '元データシート名を格納 Dim tsuikaws As Worksheet '追加データシート名を格納 Dim tsuikamax As Long '追加データの最終行 Dim motomax As Long '元データの最終行 Dim tsuikaNum As Range '追加売上番号 Dim motoNum As Variant '元売上番号 Dim i As Long     '書き込み行 Set motows = Worksheets(1).Name '元シート名を格納 Set tsuikaws = Worksheets(2).Name    '追加シート名を格納 tsuikamax = tsuikaws.Cells(Rows.Count, 1).End(xlUp).Row  '追加データの最終行を格納 motomax = motows.Cells(Rows.Count, 1).End(xlUp).Row '元データの最終行を格納 i = motomax + 1       '書き込み行は元データ最終行+1 For Each tsuikaNum In tsuikaws.Range("C1:C" & tsuikamax)        '追加データ売上番号格納 Set motoNum = motows.Range("C:C").Find(tsuikaNum, lookat:=xlWhole) '元データ売上番号格納 If motoNum Is Nothing Then '元データになかったら With motows .Cells(i, 3) = tsuikaNum i = i + 1 End With End If Next tsuikaNum End Sub

  • 行列で検索をかけてその結果を転記するVBAは

    早速ですが質問させていただきます。 sheet1のA列に月日、2行目に製品名をとり製品個数を記した表があります。(列数150行数1000です)これをsheet3のCells(2, 6)に記入した月日とCells(2, 4)に記入した製品名(文字)の2つでsheet1の行と列から当てはまるセルの検索をコマンドボタンを押すことにより行い、そのセルにsheet3のCells(2, 7)に記入した製品個数を転記するようなVBAを書きました。 Private Sub CommandButton1_Click() Dim LastA, idxA As Long, trgA, trgB With Worksheets("Sheet3") LastA = .Range("A1000").End(xlUp).Row trgA = Application.Match(.Cells(2, 6), Worksheets("Sheet1").Range("A:A"), 0) For idxA = LastA To 3 Step -1 trgB = Application.Match(.Cells(2, 4), Worksheets("Sheet1").Range("2:2"), 0) Worksheets("Sheet1").Cells(trgA, trgB) = .Cells(2, 7) Next idxA End With End Sub 以前質問して教えていただいたものを参考に、少し変更してみたのですがこれで正しいでしょうか?実行するとうまく転記するのですがかなり時間がかかってしまい、もう少し何とかならないものかと思っています。どなたかご指導お願いします。

  • 対象のシートが3行目からになった修正について

    対象のシートが3行目からになってしまったのですが、修正したいのですが、どこを修正したらよいかが分からず、困っています。お教え頂けませんか。よろしくお願いします。初心者で申し訳ありません。 Sub 統合() Dim J As Long Dim r As Long Dim s As Long Dim Sh As Worksheet Dim MaxRow As Long Dim MaxCol As Long Dim MyArray As Variant Dim JoinSh As Worksheet Set JoinSh = Worksheets("統合") '統合シートを変数に格納 JoinSh.Cells.Delete 'すでに統合シートが存在する場合は一旦セルを削除 s = 1 '最大行を超えた場合次の統合シートを作成するための番号 For i = s + 1 To Worksheets.Count 'シートを統合シートの次~末尾までループ With Worksheets(i) '各月シート If J = 1 Then r = 1 '最初だけ項目も取得 Else r = 1 '最初以外は2行目から取得 End If MaxRow = .Cells(Rows.Count, 10).End(xlUp).Row '9列目で最終行を取得 MaxCol = .Cells(1, Columns.Count).End(xlToLeft).Column '1行目で最終列を取得 MyArray = Range(.Cells(r, 10), .Cells(MaxRow, MaxCol)) 'A1~データ末尾まで配列に格納 End With With JoinSh '統合シート MaxRow = .Cells(Rows.Count, 10).End(xlUp).Row '統合シートの9列目で最終行取得 If MaxRow + UBound(MyArray) > Rows.Count Then '最大行を超える場合の処理 s = s + 1 '統合シートの番号を加算 Worksheets.Add Before:=Worksheets(s) '新規に統合シートを追加 ActiveSheet.Name = "統合" & s '名前が同じにならないように番号を追加 Set JoinSh = ActiveSheet '統合シートを変数に格納 MaxRow = JoinSh.Cells(Rows.Count, 10).End(xlUp).Row '統合シートの9列目で最終行取得 End If If .Cells(1, 1) = "" Then '最初だけ1行目から貼り付け Range(.Cells(1, 1), .Cells(UBound(MyArray), MaxCol)) = MyArray Else '最初以外は最終行の次に貼り付け Range(.Cells(MaxRow + 1, 1), .Cells(MaxRow + UBound(MyArray), MaxCol)) = MyArray End If End With Next i End Sub

  • vba変数のファイル名

    Cells(2, 3)にjを変数として、j.txtと書きたいのですが上手くいきません。 わかる方教えてください。 コードは以下のようになっています。よろしくお願いします。 Dim j As Integer For j = 1 To 8760 a = ThisWorkbook.Worksheets("Sheet2").Cells(j, "A").Value Worksheets("Sheet1").Range("1:26").Insert Worksheets("Sheet1").Cells(1, 1) = "void brightdata sky_dist" Worksheets("Sheet1").Cells(2, 1) = 7 Worksheets("Sheet1").Cells(2, 2) = "corr" Worksheets("Sheet1").Cells(2, 3) = " & j & ".txt” Next j

専門家に質問してみよう