VBAを使用して複数シートから別ブックのシートにデータ抽出するために色々と調べ自作したのですが、処理速度が遅く困っております。
マスターデータには仕入れリスト2月~12月、品目コード、拠点担当者名一覧のシートがあります。
別ブックのシート1に抽出する際下記の方が早いでしょうか。
マスターデータの仕入れリスト2月~12月シートからI列に品名の記載がある場合、
マスターデータのC~E列、I列、L列、N~O列を、シート1のA~G列に順に抽出
2月抽出データの下に3月データ、4月データと続くように抽出
現状は
マスターデータの仕入れリスト2月~12月シートからI列に品名の記載がある場合、
指定セルに順に抽出している状況です。
ファイル添付しますので、
処理速度が今より早くなる方法があれば、ご教授頂きたいです。
※添付ファイルですが質問用に変更したため、シート名の抽出が異なります。
下記に実際のコードも添付させていただきます。
___________________________________________
Option Explicit
Sub マスターデータ取込01() '指定したファイルを取り込み、別のファイルに貼り付ける。
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False
Dim SetFile As String
Dim wbMoto, wbSaki As Workbook
Dim wstData As Worksheet
Dim wstAnsw As Worksheet
Dim lngWRow As Long
Dim lngRRow As Long
Dim r As Long
Dim wsname As String
wsname = "仕入れリスト"
Set wbMoto = ActiveWorkbook 'マスターデータ取り込み元をブック名をセット(取り込み元)
Set wstData = wbMoto.Worksheets("Sheet1")
With wstData
.Rows("2:" & .Rows.Count).ClearContents
End With
lngWRow = 2
Application.DisplayAlerts = False
SetFile = 販売リスト.xlsx" 'マスターデータファイルの取り込み場所をセット(取り込み先)
Workbooks.Open Filename:=SetFile, ReadOnly:=True, UpdateLinks:=0 'マスターデータファイルを読み取り専用で開きます()
Set wbSaki = Workbooks.Open(SetFile) '開いたマスターブック名とセット(取り込み先)
For Each wstAnsw In Worksheets
With wstAnsw
If .Name Like "*" & wsname & "*" Then
For r = 6 To .Cells(Rows.Count, 10).End(xlUp).Row 'シートの6行目から最終行目までのレコードを読み取る処理
If .Cells(r, 9) <> "" Then '「品目」に記載がある場合
wstData.Cells(lngWRow, 1) = .Cells(r, 3) '担当名転記
wstData.Cells(lngWRow, 2) = .Cells(r, 4) '仕入先転記
wstData.Cells(lngWRow, 3) = .Cells(r, 5) '仕入先担当転記
wstData.Cells(lngWRow, 4) = .Cells(r, 9) '品目転記
wstData.Cells(lngWRow, 5) = .Cells(r, 12) 'ステイタス転記
wstData.Cells(lngWRow, 6) = .Cells(r, 14) '仕入れ日転記
wstData.Cells(lngWRow, 7) = .Cells(r, 15) '販売店舗転記
wstData.Cells(lngWRow, 8) = .Name 'シート(仕入れた月)名転記
lngWRow = lngWRow + 1 '書込み行を次の行へ進める
Application.DisplayAlerts = True
Exit For
End If
Next
End If
End With
Next
wbSaki.Close False 'マスターデータ取り込み先のファイルを閉じる
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
No.2
- 回答日時:
こんばんは
エクセル環境が手元にないので、考え方だけになってしまいますが・・・
きちんとは見ていませんが、ざっとみたところ各シートの一部のセル値をシート1に転記してまとめているだけと解釈しました。
(I列の項目名に関しては後述します)
一方で、VBAの実行速度はシートへのアクセス回数に大きく影響されます。
ご提示のコードでは、セルひとつひとつを転記していますが、列単位で(連続している列は複数列まとめて)転記することで、大幅に短縮が可能と思います。
セル範囲の計算に若干の手間がかかるかも知れませんが、速度的には圧倒的に速くなるはずです。
セル範囲をまとめるため、この時にはI列の判断をせずに列全体を転記してしまいます。
(まとめシートの行数がオーバーフローしないと仮定できることが条件)
最後に、まとめシート上でI列に値のない行を、全シート分まとめて削除します。
この処理を行う際も、1行ずつ削除するのではなく、
Cmlumns(9).SpecialCells(xlcelltypeblanks)
などで空白セルをまとめて、その行を削除してしまえばシートへのアクセスは2回で済んでしまいます。
このようにすることで、シートへのアクセス回数が大幅に減少すると考えられますので、実行速度の向上が見込めるはずと思います。
お返事いただきありがとうございます!上記参考に再度作成したいと思います。VBA初心者でして、またご質問するかもしれませんが、その際にご返答頂けると嬉しいです。
No.3
- 回答日時:
No2です
回答した手前、簡略化したものを作成してみました。
ご提示のコードから正しく読み取れているかわかりませんが、もし違っていても若干の調整で可能ではないかと想像します。
※ セル位置等を誤解しているかもしれませんので、テスト用のデータでテストしてみてください。
※ 簡略化の為、データの転記をコピペで行っていますが、関数等が入っているなどでコピペではまずい場合は、Value値を代入する方法に変える必要があります。
※ 以下のコードでは、データブックは開いていないものとしてOpenし、作業終了後閉じています。
(データファイルは同じフォルダ内にあるものと仮定しています)
※ ScreenUpdating = False などの処理は除いてあります。
入れれることで若干速くなることが期待できます。
Sub Sample_11987039()
Dim wb As Workbook, sht As Worksheet
Dim rDest As Range, n As Long
Const wstData = "Sheet1" 'まとめ記入用シート名
Const wsname = "*仕入れリスト*" 'データ対象シート識別子
Const dataPath = "hoge.xlsx" 'データファイルのファイル名
Set rDest = Worksheets(wstData).Range("A2")
rDest.Worksheet.UsedRange.Offset(1).ClearContents
Set wb = Workbooks.Open(ThisWorkbook.PATH & "\" & dataPath, 0, 1)
For Each sht In wb.Worksheets
If Not sht.Name Like wsname Then GoTo continue
n = sht.Cells(Rows.Count, 10).End(xlUp).Row - 5
If n < 1 Then GoTo continue
Intersect(sht.Range("C:E,I:I,L:L,N:O"), sht.Range("A6:O6").Resize(n)).Copy Destination:=rDest
rDest.Offset(, 7).Resize(n).Value = sht.Name
Set rDest = rDest.Offset(n)
continue:
Next sht
wb.Close False
Set rDest = rDest.Worksheet.Range("D2").Resize(rDest.Row - 1)
rDest.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
No.4ベストアンサー
- 回答日時:
No3です
>支障なくデータ転記することが出来ました!
肝心の、速度の向上は実現できたのたでしょうか??
>Value値を代入する方法に変える場合を宜しければお教えいただきたいです。
ご質問のコードでもお示しのように
Range.Value = Range.Value
の形式で行うのが普通だと思います。
ただし、この場合は、右辺はもちろんですが、左辺のRangeの範囲もきちんと設定しておくことが必要になります。
(コピペの場合は、元のサイズと同じ大きさの範囲にペーストされるので、気にしなくても良いのですが)
また、こちらの場合は、飛び飛びのセル範囲の値をまとめて転記はできませんので、連続するセル範囲毎に転記してゆく必要があります。
(結果的に、シートへのアクセス回数は少し増加する傾向にあります)
No3のコードの例で言えば、
rDest.Resize(n, 3).Value = sht.Range("C6:E6").Resize(n).Value
rDest.Offset(, 3).Resize(n).Value = sht.Range("I6").Resize(n).Value
・・・・・・
といった感じで記してゆけばよろしいかと。
別の方法としては、セルをコピーしておいてから「値をペースト」でまとめてペーストする方法も考えられます。
rDest.PasteSpecial (xlPasteValues)
の一行で済むことは済むのですが、クリップボード経由のコピペになってしまうため、CutCopyMod=Falseにしておかないと、ブックを閉じる際に警告が出るなどの可能性が高くなります。
また、手操作とほぼ同じ処理になるので、(コードに明示しなくても)対象シートが(勝手に)アクティブになってしまうなどもあります。
>肝心の、速度の向上は実現できたのたでしょうか??
※ ScreenUpdating = False などの処理はどちらも同条件で
20秒→25秒
速度に関しては以前より少し時間がかかってしまうようです。
元のデータに関数や条件書式が多く使われているのが原因かもしれません。
>Value値を代入する方法に変える場合・・・
お教えいただいたValue値を代入する方法に修正させていただいたところ、
※ 同条件で
14秒まで改善されました。
>rDest.PasteSpecial (xlPasteValues)
教えて頂く前に試していたのですが、ご回答いただいたように警告が出てしまっていたので、上記方法教えて頂けてありがたいです。
何度もご丁寧にご回答いただきありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(Microsoft Office) マクロVBAについて 1 2022/09/06 18:12
- Visual Basic(VBA) 【前回の続き続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/24 20:49
- Visual Basic(VBA) 【ご教示ください】VBAの記述方法がわかりません。 2 2022/08/12 21:28
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) 前回ご教授いただいたコードに覚えたてのループ処理で品名りんごAから順に20回for nextでループ 7 2023/01/13 22:01
- Visual Basic(VBA) 【前回の続きです、ご教示ください】VBAの記述方法がわかりません。 2 2022/08/16 16:44
- Visual Basic(VBA) VBA 別ブックからの転記の高速化について VBA 別ブックからの転記の高速化についてご教授下さい。 19 2022/07/26 13:07
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
マクロの「SaveAs」でエラーが...
-
VBA 空白行に転記する
-
100万件越えCSVから条件を満た...
-
EXCELのSheet番号って変更でき...
-
マクロ実行後に別シートの残像...
-
Count Ifのセルの範囲指定に変...
-
グラフマクロで系列を変数にす...
-
Unionでの他のシートの参照につ...
-
楽天RSSからエクセルVBAを使用...
-
Changeイベントで複数セルへの...
-
VBA 最終行を選んだシートにコ...
-
VBAで質問ですが、皆さんはどの...
-
複数シートの複数列に入力され...
-
VB2005でExcelのグラフのデータ...
-
【VBA】データを各シートに自動...
-
Excel2013で切り取り禁止
-
VBA 実行時エラー1004 rangeメ...
-
RemoveDuplicatesメソッドにつ...
-
VBAでEXCELから固定長...
-
VBA シリアル値から月日への変換
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
マクロの「SaveAs」でエラーが...
-
VBA 空白行に転記する
-
EXCELのSheet番号って変更でき...
-
マクロ実行後に別シートの残像...
-
VBA 別ブックからの転記の高速...
-
VBA別シートの最終行の次行へ転...
-
【VBA】特定の条件でセルをコピー
-
Count Ifのセルの範囲指定に変...
-
100万件越えCSVから条件を満た...
-
楽天RSSからエクセルVBAを使用...
-
VBAコードについて
-
Changeイベントで複数セルへの...
-
VBAで変数の数/変数名を動的に...
-
Excel2013で切り取り禁止
-
グラフマクロで系列を変数にす...
-
VBA 実行時エラー1004 rangeメ...
-
ExcelのVBマクロを、バックグラ...
-
Unionでの他のシートの参照につ...
-
Excel VBA オートフィルターで...
-
アクセスからエクセルへ出力時...
おすすめ情報
作成頂きありがとうございます!作成頂いたもので支障なくデータ転記することが出来ました!ありがとうございます。
お聞きするばかりで大変申し訳ないのですが、Value値を代入する方法に変える場合を宜しければお教えいただきたいです。