[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『オートフィルタのマクロ』(sachi)
マクロ初心者です。
オートフィルタで抽出したデータをコピーして別シートに貼り付ける
作業をマクロの自動記録でやってみましたがうまく応用できないので教えて下さい。
「計算用シート1」シートに4人分のデータが並んでいます。
1人目→D4:I183 2人目→J4:O183 3人目→P4:U183 4人目→V4:AA183
このデータをまず見積業務という項目に該当するもののみに絞込み、「Sheet1」にコピペする作業を
4人分行う。4人分のコピペが終わったら「Sheet1」のデータをフィルタのオプション設定で重複するレコードを除き、抽出されたデータを「計算用シート見積り」シートに貼り付ける
次に予測業務という項目に該当するもののみに絞込み、同じ作業をして抽出されたデータを「計算用シート予測」に貼り付ける
以上の作業を毎月行いたいのですが、「計算用シート1」で抽出したデータのコピペの
範囲は毎回変わるので、オートフィルタで抽出された範囲を指定できるようにしたい
のですが、どのように直したらいいのかわかりません。
また見積業務と予測業務は人によって該当無しの場合があります。今回の場合は3人目と
4人目が予測業務無しです。毎月状況が変わるのですが、次月3人目と4人目に予測業務が
発生した時に同じ処理をするためにはどうしたらいいのでしょうか。
わかりにくい説明ですみませんが、よろしくお願い致します。
Sub Macro1()
Selection.AutoFilter Field:=1, Criteria1:="見積業務" ActiveWindow.SmallScroll Down:=-3 Range("D22:G136").Select Selection.Copy Sheets("Sheet1").Select Range("A2").Select ActiveSheet.Paste Sheets("計算用シート1").Select Application.CutCopyMode = False Selection.AutoFilter Field:=1 Selection.AutoFilter Field:=7, Criteria1:="見積業務" Range("J4:M4").Select Selection.Copy Sheets("Sheet1").Select ActiveWindow.SmallScroll Down:=12 Range("A31").Select ActiveSheet.Paste Sheets("計算用シート1").Select Application.CutCopyMode = False Selection.AutoFilter Field:=7 Selection.AutoFilter Field:=13, Criteria1:="見積業務" ActiveWindow.SmallScroll ToRight:=8 Range("P4:S30").Select Selection.Copy Sheets("Sheet1").Select Range("A32").Select ActiveSheet.Paste Sheets("計算用シート1").Select Application.CutCopyMode = False Selection.AutoFilter Field:=13 Selection.AutoFilter Field:=19, Criteria1:="見積業務" Range("V22:Y144").Select Selection.Copy Sheets("Sheet1").Select ActiveWindow.SmallScroll Down:=15 Range("A44").Select ActiveSheet.Paste ActiveWindow.SmallScroll Down:=-45 Range("A1:D9").Select Range(Selection, Selection.End(xlDown)).Select Application.CutCopyMode = False Range("A1:D86").AdvancedFilter Action:=xlFilterInPlace, Unique:=True Range("A2:D77").Select Selection.Copy Sheets("計算用シート見積り").Select Range("D4").Select Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _ False, Transpose:=False Sheets("Sheet1").Select Application.CutCopyMode = False ActiveSheet.ShowAllData Selection.ClearContents Sheets("計算用シート1").Select ActiveWindow.SmallScroll Down:=-42 ActiveWindow.LargeScroll ToRight:=0 Selection.AutoFilter Field:=19 ActiveWindow.LargeScroll ToRight:=-1 Selection.AutoFilter Field:=1, Criteria1:="予測業務" Range("D172:G173").Select Selection.Copy Sheets("Sheet1").Select Range("A2").Select ActiveSheet.Paste Sheets("計算用シート1").Select Application.CutCopyMode = False Selection.AutoFilter Field:=1 Selection.AutoFilter Field:=7, Criteria1:="予測業務" Range("J40:M41").Select Selection.Copy Sheets("Sheet1").Select Range("A4").Select ActiveSheet.Paste Sheets("計算用シート1").Select Application.CutCopyMode = False Selection.AutoFilter Field:=7 ActiveWindow.SmallScroll ToRight:=10 Sheets("Sheet1").Select Range("A1:D5").Select Range("A1:D5").AdvancedFilter Action:=xlFilterInPlace, Unique:=True Range("A2:D3").Select Selection.Copy Sheets("計算用シート予測").Select Range("D4").Select Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _ False, Transpose:=False Sheets("Sheet1").Select Application.CutCopyMode = False Selection.ClearContents ActiveSheet.ShowAllData Range("A4:D5").Select Selection.ClearContents Sheets("計算用シート1").Select End Sub
Excel2000 Windows
言葉だけではシートのデータの状態がわからないので質問のポイントがわかりません。
各シートのレイアウトと簡単で良いので実際に近いデータを掲示できませんか? もちろん社内情報や個人情報には配慮していただく形で。
(momo)
momo様
シートの状態ですが、「計算用シート1」シートに下記の表があります。
D E F G H I 3行目 区分 部品名 段階 詳細 予測工数 実績工数 ←見出し 4行目 予測業務 AAA 試作 検証作業 2.00 2.50 ←以降183行目まで該当項目入力
D4からD183の区分に入力されるのが、見積業務もしくは予測業務でこれをキーにオートフィルタで データを抽出し、DからG列をコピーして「Sheet1」に貼り付けます。 「計算用シート1」にはH列以降に同様の項目が3人分あるので、オートフィルタでのデータ抽出と 「Sheet1」へのコピペを人数分繰り返します。 区分から詳細の組み合わせが2000件ほどあり、重複することもあるので、重複したものを削除してから 見積業務は「計算用シート見積り」シートへ、予測業務は「計算用シート予測」へコピペ。
計算用シート見積りと計算用シート予測は下記の通り
1人目 2人目 A B D E F G H I J K 3行目 区分 部品名 段階 詳細 予測工数 実績工数 予測工数 実績工数
D4セルに抽出データを貼り付けるとH列以降に関数式を入れてあるので、各担当者の工数合計が表示 され、A、B列で予測と実績工数の総合計を出します。
これでおわかりになるでしょうか?すみませんが、よろしくお願い致します。
(sachi)
要するに「計算用シート1」シートのD:G列の重複の無いリストを 見積業務と予測業務別に作りたい。という事でよろしいでしょうか?
だとして オートフィルターですと項目ごとに探さなければならないので結構大変ですよね? Dictionaryオブジェクトを使って処理する方法にしてみてはどうでしょうか?
最初はコードを見てもわからないかもしれませんが ヘルプやネットで調べていくうちに解るようになると思います。 非常に使いやすくて便利なオブジェクトなので勉強してみてください。
Sub test() Dim myDic(1 To 2) As Object Dim i As Long, j As Long Dim tbl As Variant, buf As String For i = 1 To 2 Set myDic(i) = CreateObject("Scripting.Dictionary") Next i For i = 4 To 22 Step 6 With Worksheets("計算用シート1") tbl = .Range(.Cells(4, i), .Cells(183, i + 4)).Value End With For j = 1 To UBound(tbl) buf = tbl(j, 1) & vbTab & tbl(j, 2) & vbTab & tbl(j, 3) & vbTab & tbl(j, 4) Select Case tbl(j, 1) Case "見積業務" If Not myDic(1).Exists(buf) Then myDic(1).Add buf, "" End If Case "予測業務" If Not myDic(2).Exists(buf) Then myDic(2).Add buf, "" End If End Select Next j Next i With Worksheets("計算用シート見積り").Range("D4").Resize(myDic(1).Count) .Value = Application.Transpose(myDic(1).keys) .TextToColumns Destination:=.Cells(1), DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _ ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, Comma:=False, Space:=False, Other:=False, _ FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1)), TrailingMinusNumbers:=True End With With Worksheets("計算用シート予測").Range("D4").Resize(myDic(2).Count) .Value = Application.Transpose(myDic(2).keys) .TextToColumns Destination:=.Cells(1), DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _ ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, Comma:=False, Space:=False, Other:=False, _ FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1)), TrailingMinusNumbers:=True End With End Sub
(momo)
momo様
教えて頂いたコードを貼り付けて試してみましたが、下記のところでアプリケーション定義または オブジェクトの定義エラーですというエラーが出ました。 .TextToColumns Destination:=.Cells(1), DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, _ ConsecutiveDelimiter:=False, Tab:=True, Semicolon:=False, Comma:=False, Space:=False, Other:=False, _ FieldInfo:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1)), TrailingMinusNumbers:=True
ヘルプを見てみたりしたのですが、どこをどう修正したらいいのかわかりません。 それから「計算用シート1」シートのD:G列に加えてJ:M列とP:S列とV:Y列の重複の無いリストを 作りたい(計算用シート見積りと計算用シート予測で4人分の合計工数を計算する為)のですが、 その場合は、どの辺りを修正すればいいのでしょうか?頼りきりですみません…
(sachi)
エラーはエクセル2000だからですかね データ区切りの引数の違いがあるかもしれませんが、私が2000の環境が無いので 少しお待ち下さい。 依存しないコードに書き換えてみます。
あとJ:M P:S V:Y についてはすでに対応済みのコードです。
ちょっと待ってくださいね。 (momo)
なるべくバージョンに依存しないように書いてみましたので テストしてみてください。
Sub test() Dim myDic(1 To 2) As Object Dim i As Long, j As Long Dim tbl As Variant, buf As String For i = 1 To 2 Set myDic(i) = CreateObject("Scripting.Dictionary") Next i For i = 4 To 22 Step 6 With Worksheets("計算用シート1") tbl = .Range(.Cells(4, i), .Cells(183, i + 3)).Value End With For j = 1 To UBound(tbl) buf = tbl(j, 1) & vbTab & tbl(j, 2) & vbTab & tbl(j, 3) & vbTab & tbl(j, 4) Select Case tbl(j, 1) Case "見積業務" If Not myDic(1).Exists(buf) Then myDic(1).Add buf, Application.Index(tbl, j, 0) End If Case "予測業務" If Not myDic(2).Exists(buf) Then myDic(2).Add buf, Application.Index(tbl, j, 0) End If End Select Next j Next i Worksheets("計算用シート見積り").Range("D4").Resize(myDic(1).Count, 4).Value = _ Application.Transpose(Application.Transpose(myDic(1).Items)) Worksheets("計算用シート予測").Range("D4").Resize(myDic(2).Count, 4).Value = _ Application.Transpose(Application.Transpose(myDic(2).Items)) End Sub
(momo)
momo様
試してみたらうまくいきました、大変助かりました。本当にありがとうございます!! ちなみにJ:M P:S V:Y についてはすでに対応済みというのはFor i = 4 To 22 Step 6 のコードになるのでしょうか? せっかく教えて頂いたので、これから活用できるようにコードを勉強します。
(sachi)
>ちなみにJ:M P:S V:Y についてはすでに対応済みというのはFor i = 4 To 22 Step 6 >のコードになるのでしょうか?
そのとおりです。 変数iの可変範囲をD列(Column(4)という事)からV列(22)まで6列おきに変化させて .Range(.Cells(4, i), .Cells(183, i + 3)).Value というコードでiが1の時はD4:G183 2の時はJ4:M183 ・・・ というように範囲指定して値を取得しています。
Dictionaryオブジェクト以外の部分は特に変わったコードではないので 普通にヘルプで理解を進められると思います。
中でも解らない事があればまた質問してください。 可能な範囲でお付き合いしますので、頑張ってください。 (momo)
momo様
わかりやすい説明ありがとうございました。 最初は???の状態でしたが、ちょっとずつわかってきました。
また疑問点がありましたら質問させてください、よろしくお願い致します。
(sachi)
momo様
すみませんが、この件でもう1点教えてください。 月によっては予測業務が発生しない可能性があるのですが、「計算用シート1」の区分(D,J,P,V列) に予測業務が無い場合、型が一致しませんというエラーが出ました。 このエラーを回避するためにはどうしたらいいのでしょうか?
(sachi)
>Worksheets("計算用シート見積り").Range("D4").Resize(myDic(1).Count, 4).Value = _ > Application.Transpose(Application.Transpose(myDic(1).Items)) >Worksheets("計算用シート予測").Range("D4").Resize(myDic(2).Count, 4).Value = _ > Application.Transpose(Application.Transpose(myDic(2).Items))
の部分を、myDicのCountが0以上の時に実行するようにIf分岐します。
If myDic(1).Count > 0 Then Worksheets("計算用シート見積り").Range("D4").Resize(myDic(1).Count, 4).Value = _ Application.Transpose(Application.Transpose(myDic(1).Items)) End If If myDic(2).Count > 0 Then Worksheets("計算用シート予測").Range("D4").Resize(myDic(2).Count, 4).Value = _ Application.Transpose(Application.Transpose(myDic(2).Items)) End If
とする事で0個の場合に処理を飛ばす事ができます。 (momo)
momo様
教えて頂いたコードでエラーが消えました。ありがとうございました!
(sachi)
momo様
上記で計算用シート見積りと計算用シート予測に表示されたデータの並び替えしたいのですが、 下記のようなコードを追加してみたらエラーにはならないものの、並び替えがされません。 (マクロの新しい記録で試してみたコードを見よう見真似で修正してみたのですが・・・) コードをどのように直したらいいのでしょうか? 各シートのD4:U56のデータをE列をキーに昇順で並び替えたいと思っています。 何度もすみませんが、教えてください。よろしくお願い致します。
Worksheets("計算用シート見積り").Select Range("D4:U56").Sort Key1:=Range("E4"), Order1:=xlAscending, Header:=xlGuess, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom Worksheets("計算用シート追加").Select Range("D4:U56").Sort Key1:=Range("E4"), Order1:=xlAscending, Header:=xlGuess, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom
(sachi)
ソートも範囲内に値が無いとエラーになると思いますので 前回のIf分の中にソートを置く感じで あとはSheetをSelectして実行するのではなくてSheetオブジェクトに対して実行できるように 少し修正します。 前回と同じ部分を以下のようにしてみてください。
If myDic(1).Count > 0 Then With Worksheets("計算用シート見積り") .Range("D4").Resize(myDic(1).Count, 4).Value = _ Application.Transpose(Application.Transpose(myDic(1).Items)) .Range("D3").CurrentRegion.Sort Key1:=.Range("E4"), Order1:=xlAscending, Header:=xlYes, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ SortMethod:=xlPinYin, DataOption1:=xlSortNormal End With End If If myDic(2).Count > 0 Then With Worksheets("計算用シート予測") .Range("D4").Resize(myDic(2).Count, 4).Value = _ Application.Transpose(Application.Transpose(myDic(2).Items)) .Range("D3").CurrentRegion.Sort Key1:=.Range("E4"), Order1:=xlAscending, Header:=xlYes, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ SortMethod:=xlPinYin, DataOption1:=xlSortNormal End With End If
(momo)
momo様
教えて頂いたコードで試してみたところ、並び替えはできたのですが、見出しが入っていた 2行目、3行目まで並び替えられてしまいました。(A2からすべて対象範囲になっているようです。) D4:U56までのみを並び替えの対象とするにはどうしたらいいのでしょうか? 何度もすみません。
(sachi)
そうでしたか、見出しは1行だけだと思っていたので。 では2ヶ所あるソートメソッドの
> .Range("D3").CurrentRegion.Sort Key1:=.Range("E4"), Order1:=xlAscending, Header:=xlYes, _ > OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ > SortMethod:=xlPinYin, DataOption1:=xlSortNormal
の部分を
.Range("D4:U56").Sort Key1:=.Range("E4"), Order1:=xlAscending, Header:=xlNo, _ OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _ SortMethod:=xlPinYin, DataOption1:=xlSortNormal
に変更してみてください (momo)
momo様
こちらの説明不足によるエラーだったようで、失礼致しました。 試したところ、「実行時エラー1004 アプリケーション定義または オブジェクト定義のエラー」 になったのですが、DataOption1:=xlSortNormalのところを消してみたらうまくいきました。 (昨夜は違うPCで試したので、このエラーは出ませんでした。) ご対応頂き、ありがとうございました。
(sachi)
過去の話ですみませんが、再度質問させて下さい 教えて頂いた上記のコードですが、「計算用シート1」シートのD:G列の重複の無いリストを 別シートにコピーしていたのが、1列分減って、D〜F列の重複のないリストをコピーしようと しています。 また対象人数が4人から10人に増えたため、そこも対応できるようにコードの下記の部分を 修正してみました。
(修正前) For i = 4 To 22 Step 6 ’D列からV列まで6行おき With Worksheets("計算用シート1") tbl = .Range(.Cells(4, i), .Cells(183, i + 3)).Value 'iが1の時はD4:G183 (修正後) For i = 4 To 49 Step 5 ’D列からAW列まで5行おき With Worksheets("計算用シート1") tbl = .Range(.Cells(4, i), .Cells(183, i + 2)).Value 'iが1の時はD4:F183
これでマクロを実行してみたところ、インデックスが有効範囲にないというエラーになりました。 コードの修正が間違っているのか、他の部分の修正が必要なのか、すみませんが教えて下さい。 よろしくお願いします。
(sachi)
すみません、自分で解決できました。 失礼致しました。
(sachi)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.