• ベストアンサー

いい方法を教えてください(VBAについての質問)

よろしくお願いします。 ある処理についてプロシージャを作成しました。 それは「毎回データの行数・列数の異なるデータから必要な列のデータだけを取り出して別のシートにコピーして貼り付ける」処理です。 具体的にはセルのA2以下にデータを貼り付けて必要な列の1行目空白セルに1を、不要な列は0を入れ、必要なデータ(1を入れた列にあるデータ)だけ取り出すという処理です。  Do Until ActiveCell.Value = ""   If Selection.Value = "1" Then   Selection.Offset(1, 0).Select   Range(Selection, Selection.End(xlDown)).Copy _   Destination:=mySht.Range("IV1").End(xlToLeft).Offset(0, 1)   Selection.End(xlUp).Offset(0, 1).Select   Else   Selection.Offset(0, 1).Select   End If  Loop ↑こんな感じで書きました。 myShtは変数で、必要データ貼り付け用に作成したシートです。 使ってみて穴に気付きました。 データに空白があった時に、空白以後のデータがコピーされないのです。そういう書き方なので当然ですが・・・。 範囲の指定をその列のデータの最初から空白関係なくデータのある最終行までにしようとあれこれと試しましたがことごとくうまくいきません。 これが1つ目の悩みです。 もう1つは   Range(Selection, Selection.End(xlDown)).Copy _   Destination:=mySht.Range("IV1").End(xlToLeft).Offset(0, 1) の部分、取り出した列のコピーを別のシート(mySht)に左寄せで順番に詰めてコピーしていくようにしたのですが、この記述だと1列目が空いてしまいます。 ですから実際はこの後1列目を削除する処理をしています。 この1列目の削除というのが本来不要な作業なので、なんだかイヤなのです。 何かいい方法を教えてください。 ヒントみたいなものでもうれしいです。

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

  • ベストアンサー
  • KenKen_SP
  • ベストアンサー率62% (785/1258)
回答No.1

こんにちは。KenKen_SP です。 > 範囲の指定をその列のデータの最初から空白関係なくデータのある > 最終行までにしようと... いろいろありますが、UsedRange や CurrentRegion でデータ範囲を 取得して、最終列を求めるといいでしょう。 > この記述だと1列目が空いてしまいます。 End(xlToLeft).Column の戻り値が 1 のときは Offset しなければ良い です。下記のコードは多少記述が違いますが、考え方は一緒です。 こんな感じ。 Sub SampleMacro()   Dim mySht As Worksheet   Dim lngC As Long   Dim lngR As Long   Dim i   As Long      With ThisWorkbook     '貼り付け先シート定義     Set mySht = .Sheets("Sheet2")     '貼り付け先列番号取得     lngC = mySht.Cells(1, "IV").End(xlToLeft).Column     If lngC <> 1 Then       '既存データが在れば1列横に再設定       lngC = lngC + 1     End If   End With      '元データ(アクティブシート)の最大行番号を取得   lngR = ActiveSheet.UsedRange.Rows.Count      With ActiveSheet     '元データの最大列番号までループ処理     For i = 1 To .UsedRange.Columns.Count       If .Cells(1, i).Value = 1 Then         'コピー&ペースト         .Range(.Cells(1, i), .Cells(lngR, i)).Copy _         Destination:=mySht.Cells(1, lngC)         '次の貼り付け先となる列番号にカウントアップ         lngC = lngC + 1       End If     Next i   End With   Set mySht = Nothing End Sub

baritsu
質問者

お礼

ああっスゴい!・・・しかも回答が早い・・・。 ありがとうございました。 以前も回答者様には教えていただきましたが、おかげさまで今回のは前よりはどういう構造かがわかります! 早速、実際のブックに組み込ませてもらって試してみます。 一番ショックだったのは自分の書いたものと処理速度が全然違う事です。沢山のデータを処理するんだから仕方が無いと思っていましたが・・・。 はあ、奥が深い・・・。

その他の回答 (1)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.2

こんにちは。 ちょっと最初の出だしがよく見えていない部分がありますが、 >データに空白があった時に、空白以後のデータがコピーされないのです。そういう書き方なので当然ですが・・・。 それは、 Range(Selection, Selection.End(xlDown)).Copy  これが理由だからですね。下から上にというのは、こういう書き方ですと、ややこしくなりますからね。でも、それ以外は、コードとしては、私は良くできていると思いますね。 一応、私なりに、オプションをつけたりして、移植しているつもりではいるのですが、失敗していたら、すみませんね。 それから、Selection は、ActiveCell のほうが、無難ですね。 >左寄せで順番に詰めてコピーしていくようにしたのですが、この記述だと1列目が空いてしまいます。 なかなか、きれいにそのロジックを立てるのは難しいですね。Excel VBAを書く人は、それぞれ、自分の方法を持って書いているようです。 '-------------------------------------------- Sub FindOneAndCopyColumn()   Dim c As Range   Dim mySht As Worksheet   Dim PasteRng As Range   Dim i As Integer   Dim j As Integer   Dim k As Integer   Set mySht = Worksheets("Sheet2")     'mySht の1行目のチェック・ロジック   'ここは、列全体に及ばせることも可能です。   Set PasteRng = mySht.Range("IV1").End(xlToLeft)   i = mySht.Range("IV1").End(xlToLeft).Column   j = WorksheetFunction.CountA(PasteRng.EntireRow)   If j > 0 And i <> j Then    MsgBox "空の列が存在していますので中止します。", vbInformation    Exit Sub   ElseIf j = 0 Then    k = 0   Else    k = 1   End If     With ActiveSheet    For Each c In .Range("A1", .Range("IV1").End(xlToLeft))      If c.Value = 1 Then       .Range(c.Offset(1), .Cells(65536, c.Column).End(xlUp)).Copy _       PasteRng.Offset(, k)       k = k + 1      End If    Next c   End With     Set mySht = Nothing: Set PasteRng = Nothing End Sub

baritsu
質問者

お礼

回答ありがとうございます。 お礼が遅くなりました。 これもまた試したところキチンとすばやく動作しました。 今回は#1様の記述をプロシージャの中にはまるように少し修正して使わせていただきました。 ですが同じ結果を求めるやり方でも色々なやり方があるのだなと勉強になりました。どうやら自分はまだ変数をうまく使いこなすのが不慣れなようです。課題ですね。 ありがとうございます。

関連するQ&A

  • excel VBAの検索マクロを、OOo CALCで動かしたいのですが

    excel VBAの検索マクロを、OOo CALCで動かしたいのですが、、、 お助けください。VBA素人で、OOo BASICは全くわからない者です。よろしくおねがいします。 シート1を検索データの入力及び検索結果の表示画面として使い、 シート2に検索先のデータが入力されています。 検索先のデータは乱雑に入力されており、探したいデータが複数の列に点在し、 かつ、ひとつのセルにふたつのデータが入っていることもあります。 部分一致検索で、EXCELの検索機能の「次を検索」ボタンと同じ機能を果たすように作ったつもりです。 データが見つかった場合、シート2のデータをシート1にコピーするようになっています。 ソフトウェアのバージョンはcalc2.0と3.0です。 Excelでは動いているのですが、どう変えればcalcで使えるようになりますでしょうか? --------------------------------------------- Sub kensaku() 'sheet1のC4に検索したいデータを入力済 Dim A Set A = Range("sheet1!C4") Dim B As Range 'シート2を選択。 Sheets("sheet2").Select 'A1:S800の範囲をAの値で検索。 Set B = Range("A1:S800").Find(What:=A, _ after:=ActiveCell, SearchDirection:=xlNext, _ LookAt:=xlPart, MatchCase:=False, _ MatchByte:=False, SearchFormat:=False) '分岐 '見つからなかった場合、シート1の関数参照先のセルをクリアしてリセット。 If B Is Nothing Then MsgBox "見つかりません" Sheets("sheet1").Select Range("C2").ClearContents '見つかった場合、処理を続行する。 Else B.Activate 'A列へ移動。場合により空白セルを超える必要があるため10回繰り返す。 Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select Selection.End(xlToLeft).Select 'A列からC列へ移動すると目的のデータが入った列に到達。 Selection.Offset(0, 2).Select 'その値をコピーしてシート1のC2へ貼付(関数の参照先) Selection.Copy Sheets("sheet1").Select Range("C2").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _ SkipBlanks:=False, Transpose:=False '範囲選択を解除 Application.CutCopyMode = False 'sheet2のアクティブセルを次の検索開始位置(16列右)へ移動 (条件に一致する次のデータを検索するため) Sheets("sheet2").Select Selection.Offset(0, 16).Select 'シート1に戻る Sheets("sheet1").Select End If End Sub

  • マクロでシート2~6のデータをシート1に転記したい

    マクロでシート2~6のデータをシート1に転記したいです。 シート2~6のデータを シート1に順番に転記したくてマクロの記録を利用して作成しました。 シート2~6は列は同じですが行数は異なります。 また行数は作業の都度異なります。 同じ記述が繰り返されているので もう少し記述が短くできるのではと思うのですが どうすればいいでしょうか? Sub データ更新() 'シート1の前回データをクリア Sheets("シート1").Select Range("A2:Q2").Select Range(Selection, Selection.End(xlDown)).Select Range(Selection, Selection.End(xlDown)).Select Selection.ClearContents Range("A2").Select Sheets("シート1").Select Range("A1").Select Sheets("シート2").Select Range("A1").Select 'ヘッダーも合わせて取得 Range(Selection, Selection.End(xlToRight)).Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("シート1").Select ActiveSheet.Paste Application.CutCopyMode = False Selection.End(xlDown).Select Selection.Offset(1, 0).Select Sheets("シート3").Select Range("A2").Select 'データのみ取得 Range(Selection, Selection.End(xlToRight)).Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("シート1").Select ActiveSheet.Paste Application.CutCopyMode = False Selection.End(xlDown).Select Selection.Offset(1, 0).Select Sheets("シート4").Select Range("A2").Select Range(Selection, Selection.End(xlToRight)).Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("シート1").Select ActiveSheet.Paste Application.CutCopyMode = False Selection.End(xlDown).Select Selection.Offset(1, 0).Select Sheets("シート5").Select Range("A2").Select Range(Selection, Selection.End(xlToRight)).Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("シート1").Select ActiveSheet.Paste Application.CutCopyMode = False Selection.End(xlDown).Select Selection.Offset(1, 0).Select Sheets("シート6").Select Range("A2").Select Range(Selection, Selection.End(xlToRight)).Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("シート1").Select ActiveSheet.Paste Application.CutCopyMode = False Selection.End(xlDown).Select Selection.Offset(1, 0).Select End Sub

  • エクセルVBAでの質問です。

    エクセル2003での質問です。 book1のシート1からbook2のシート18セルC30へ 表のコピーを行い、C30が空白セルだったらそのまま貼り付け、 非空白だったら表最下部から2行あけて表のコピー操作を行う。 としたいのですが以下の箇所でエラーがでてしまいます。 book1.Activate sheet1.Range("C8:E24").Copy book2.Activate If sheet18.Range("C30") = "" Then sheet18.Range("C30:E46").Select Selection.PasteSpecial.xlPasteValues ←実行時エラー424発生 Else sheet18.Range("C30").End(xlDown).Offset(2).Select Selection.PasteSpecial.xlPasteValues ←実行時エラー424発生 End If 以上、解決策をご教示願います。

  • エクセルVBAの貼付けについて

    エクセルVBAの貼付けについて シートAとBがあって、シートBの1~7列をコピーし、シートAの最終行に貼り付ける方法を教えて下さい。 下記のように書いてみたのですがダメでした。 Sheets("B").Select Rows("1:7").Select Selection.Copy Sheets("A").Select With Range("A1").End(xlDown).Offset(1, 0) .ActiveSheet.Paste End With

  • vba  

    VBAはじめたばかりで、躓きました。 下記を実行すると、”Nextに対するForがありません。”とでます。 なぜこうなるのか教えてください。  G2~列2000の間が空白になるまで、  下記の処理を続けるようにしたいと思っています。  Dim i As Integer For i = 7 To 2000 Do If Cells(2, i) = "" Then Range("G2").End(xlToRight).Select ActiveCell.CurrentRegion.Resize(6, 5).Select Selection.Cut Range("B2").End(xlDown).Select ActiveCell.Offset(1).Select ActiveSheet.Paste Exit Do End If Next i Loop  よろしくお願いします。

  • Excel VBA offset()関数で質問

    Excel VBA offset()関数で質問です。 現在集計のマクロを作成しております。 ■処理内容 各sheetの特定の範囲を"copy" して集計sheetに順に貼り付け… といった処理をさせようと作成中です。 以下がソースになります。 Sub 集計() Dim ws As Worksheet i = 1 For Each ws In ActiveWorkbook.Sheets If ws.Name = "集計" Then Else Range("E1").Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy ★Worksheets("集計").Range("A1").Offset(, i).Select ActiveSheet.Paste i = i + 1 On Error Resume Next ActiveSheet.Next.Select End If Next End Sub ★マークのところで現在エラーになっています。 実行時エラー '1004': RangeクラスのSelectメソッドが失敗しました。 と表示されます。 offset関数の使用方法の確認ですが… (とあるWebから抜粋したのですが… (^^; ) 例> Range("C3").Offset(,1).Selectとすれば、 行はそのままで、列が1列右に移動し、D3を選択します。 アドバイスよろしくお願い致します。

  • ExcelのVBAです。

    先日お答えいただいたVBAなんですが、 Sub Macro1() Sheets("Sheet1").Select Range("A1").Select Range(Selection, Selection.End(xlDown)).Select Selection.Copy Sheets("Sheet3").Select Range("A1").Select ActiveSheet.Paste Selection.End(xlDown).Select Application.CutCopyMode = False Do Selection.Insert Shift:=xlDown Selection.End(xlUp).Select Loop Until ActiveCell.Address = "$A$1" End Sub というのを使用させて頂いてます。 これを、コピー先のものを上書きせずに、コピーされたものがあれば表示させるといった風に出来ないでしょうか? 例  A    A 1 a 1 2 b → 2あ 3 c 3 右から左に一行間隔で別シートに表示させたいのですが、  A  1 a 2 あ 3 b 4 5 b という結果にしたいのです。 拙い文章で申し訳ないのですが、教えて頂きたいです。

  • VBA 右端列の削除

    このたび初めて質問させていただきます。 周囲にVBAを扱うひとがいないため、初歩的(たぶん?)な質問をさせてください。 以下のようなマクロを記録したのですが、一部を編集したいと考えております。 Columns("F:H").Select Selection.Insert Shift:=xlToRight Columns("A:B").Select Selection.Cut Range("F1").Select ActiveSheet.Paste Columns("J:J").Select→J列固定ではなく右端の列と設定したい。 Selection.Cut Range("H1").Select ActiveSheet.Paste Columns("A:B").Select Selection.Delete Shift:=xlToLeft Columns("J:J").SelectをJ列固定ではなく右端の列を1列設定し切り取りがしたいのです。Range("A2").End(xlToRight).Select ActiveCell.Offset(-1,0).End(xlDown).Select と書き換えてみたのですが、うまく作動しませんでした。 どなたか教えていただけませんでしょうか?

  • 複数シートの内容を1つのシートに集計するVBA

    お世話になります。 ExcelのVBAについて質問させていただきます。 集計.xlsというブックがあります。 この中に[集計]、[東京支店]、[名古屋支店]、[大阪支店]というシートがあります。 やりたい事は[東京支店]、[名古屋支店]、[大阪支店]のシート内容を[集計]シートに順番にコピペしていきたいのです。 下記のVBAを組んでみましたがうまくいきません。 [東京支店]はうまくコピペ出来ますが、[名古屋支店]がコピペされず、[大阪支店]はコピペされますが東京支店のデータのすぐ下ではなく、50行ぐらい下の位置にコピペされてしまいます。 各支店のシートの内容は次の通りです。この内容を[集計]シートにコピペしたいのです。 [日付] [担当者] [金額] 11/1 田中 100円 11/2 山田 500円 どなたかご教授いただけますでしょうか? 環境 Windows XP SP3 Excel2003 ****VBA**** Sub test() Dim 下 As Integer '東京支店 Sheets("東京支店").Select Range("A2").Select '東京支店シートの見出し以外の全データをコピー Range(Selection, Selection.End(xlDown)).Select Range(Selection, Selection.End(xlToRight)).Select Selection.Copy '集計シートに貼り付け Sheets("集計").Select Range("A2").Select ActiveSheet.Paste '次は名古屋支店 Sheets("名古屋支店").Select Range("A2").Select '名古屋支店シートの見出し以外の全データをコピー Range(Selection, Selection.End(xlDown)).Select Range(Selection, Selection.End(xlToRight)).Select Selection.Copy '集計シートの最下行を取得 Sheets("集計").Select 下 = Range("A1").CurrentRegion.Rows.Count + 1 '集計シートに貼り付け Range("A2").Select ActiveCell.Offset(下 & "," & 0).Select ActiveSheet.Paste '最後に大阪支店 Sheets("大阪支店").Select Range("A2").Select '大阪支店シートの見出し以外の全データをコピー Range(Selection, Selection.End(xlDown)).Select Range(Selection, Selection.End(xlToRight)).Select Selection.Copy '集計シートの最下行を取得 Sheets("集計").Select 下 = Range("A1").CurrentRegion.Rows.Count + 1 '集計シートに貼り付け Range("A2").Select ActiveCell.Offset(下 & "," & 0).Select ActiveSheet.Paste End Sub

  • エクセルVBAで値のカウントをしたい

    C列~AA列まで値が入っています 1行目にはタイトル 2行目からそれぞれ値が入っており、終了行は毎回ランダムです 各列毎に値の合計と1以上の値の合計数を表示するために下記のマクロを使用しているのですが、もっとスマートな方法は無いでしょうか? 現在のマクロだとマクロ行数がとても多いものになっています。 Sub Count() With Range("C2") .End(xlDown).Offset(1, 0) = _ "=SUM(" & Range(.Address, .End(xlDown)).Address(False, False) & ")" End With '本当はCの最終行に直接COUNTIFを書き込みたいが、他のセルを使用しないと0になる Range("A1") = "=COUNTIF(C2:C10000,"">=1"")" Range("A1").Select Selection.Copy Range("C1").End(xlDown).Offset(1, 0).Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Application.CommandBars("Stop Recording").Visible = False With Range("D2") .End(xlDown).Offset(1, 0) = _ "=SUM(" & Range(.Address, .End(xlDown)).Address(False, False) & ")" End With Range("A1") = "=COUNTIF(D2:D10000,"">=1"")" Range("A1").Select Selection.Copy Range("D1").End(xlDown).Offset(1, 0).Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False Application.CommandBars("Stop Recording").Visible = False '以降AAまでセルの位置を変えた同一マクロを繰り返す End Sub

専門家に質問してみよう