質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

1025閲覧

VBA 条件抽出が遅い

hajihaji

総合スコア18

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2020/05/01 04:46

編集2020/05/01 10:48

2つのブックがありそれぞれ総当たり表の間で条件抽出を行おうとしているのですが、動作が遅いため早くする方法などお教えいただければ幸いです。

| A B C a c
a あ え つ B
b い じ か C
c お さ き

  Sub 条件() Dim bk1, bk2 As Workbook Dim sh1, sh2 As Worksheet Dim Keyval, keyval2 As String Dim i, s, x, y, z As Long Dim str As String, del As String Set bk1 = Workbooks("A") Set bk2 = Workbooks("B") Set sh1 = bk1.Worksheets("情報") Set sh2 = bk2.Worksheets("結果") On Error Resume Next R1 = sh1.Cells(Rows.Count, "A").End(xlUp).Row R2 = sh2.Cells(Rows.Count, "A").End(xlUp).Row C1 = sh1.Range("A1").End(xlToRight).Column C2 = sh2.Range("A1").End(xlToRight).Column For i = 2 To R1 For s = 2 To R2 For x = 17 To C1 For y = 3 To C2 If sh1.Cells(1, x) = sh2.Cells(s, 2) And sh1.Cells(i, 1) = sh2.Cells(1, y) Then sh2.Cells(s, y) = sh1.Cells(i, x) End If Next y Next x Next s Next i  end sub

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsu99

2020/05/01 08:21 編集

1."情報"、”結果”シートのレイアウトの画像を提示してください 2.条件抽出の内容を(業務的な意味を)日本語で提示して下さい。及び結果をどのように格納したいのかも提示してください。 そうすれば、良い回答が得られやすくなります。
hajihaji

2020/05/01 10:48

ご指摘ありがとうございました。
tatsu99

2020/05/01 11:26

補足ありがとうございました。シートのレイアウトが画像でないので、回答欄に画像のサンプルを提示しておきます。(回答ではありません)
guest

回答3

0

一度配列に入れてから処理することで速度UPが期待できます。
また、ご存じだとは思いますが処理の前後に下記をつけてもよろしいかと思います。

Application.ScreenUpdating = False

'処理
Application.ScreenUpdating = true

記事:配列を使う(Excel高速化テクニック)

http://officetanaka.net/excel/vba/speed/s11.htm

をご覧いただくとよいかと思います。

投稿2020/05/01 05:18

編集2020/05/01 05:38
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hajihaji

2020/05/01 05:40

ご回答ありがとうございます。参考にさせていただきます。
guest

0

ベストアンサー

VBAでは1行で変数宣言する場合も型宣言は省略できません。(省略するとVariant型になり速度的に不利。)

配列を使って高速化する場合のコード例
情報 も 結果 も表はA1から始まっているとする。

vba

1Sub 条件() 2 '1行で書く場合、型省略不可 3 Dim bk1 As Workbook, bk2 As Workbook 4 Dim sh1 As Worksheet, sh2 As Worksheet 5 Dim i As Long, s As Long, x As Long, y As Long, z As Long 6 7 Set bk1 = Workbooks("A") 8 Set bk2 = Workbooks("B") 9 10 Set sh1 = bk1.Worksheets("情報") 11 Set sh2 = bk2.Worksheets("結果") 12' On Error Resume Next '動作確認ができたらコメントを外す 13 14 Dim R1 As Long, R2 As Long, C1 As Long, C2 As Long 15 R1 = sh1.Cells(Rows.Count, "A").End(xlUp).Row 16 R2 = sh2.Cells(Rows.Count, "A").End(xlUp).Row 17 C1 = sh1.Range("A1").End(xlToRight).Column 18 C2 = sh2.Range("A1").End(xlToRight).Column 19 20 'セル範囲を配列に格納 21 Dim a1(), a2() 22 a1 = sh1.Range(sh1.Cells(1, 1), sh1.Cells(R1, C1)).Value 23 a2 = sh2.Range(sh2.Cells(1, 1), sh2.Cells(R1, C1)).Value 24 25 For i = 2 To R1 26 For s = 2 To R2 27 For x = 2 To C1 28 For y = 2 To C2 29 If a1(1, x) = a2(s, 1) And a1(i, 1) = a2(1, y) Then 30 a2(s, y) = a1(i, x) 31 End If 32 Next y 33 Next x 34 Next s 35 Next i 36 37 sh2.Range("A1").Resize(R2, C2).Value = a2 38End Sub

上記は元コードをそのまま配列用に修正してものですが、私がコーディングするなら下記のようなコードになります。

これなら、表がA1からでなくても、.Range("A1")の部分を書き換えるだけで済みます。

vba

1Sub 条件1() 2 Dim bk1 As Workbook, bk2 As Workbook 3 Set bk1 = ThisWorkbook 'Workbooks("A") 4 Set bk2 = ThisWorkbook 'Workbooks("B") 5 6 '表範囲取得 7 Dim rg1 As Range, rg2 As Range 8 Set rg1 = bk1.Worksheets("情報").Range("A1").CurrentRegion 9 Set rg2 = bk2.Worksheets("結果").Range("A1").CurrentRegion 10' On Error Resume Next 11 12 Dim a1(), a2() 13 a1 = rg1.Value 14 a2 = rg2.Value 15 16 Dim i As Long, s As Long, x As Long, y As Long, z As Long 17 For i = 2 To UBound(a1, 1) 18 For s = 2 To UBound(a2, 1) 19 For x = 2 To UBound(a1, 2) 20 For y = 2 To UBound(a2, 2) 21 If a1(1, x) = a2(s, 1) And a1(i, 1) = a2(1, y) Then 22 a2(s, y) = a1(i, x) 23 End If 24 Next y 25 Next x 26 Next s 27 Next i 28 29 rg2.Value = a2 30End Sub

投稿2020/05/02 02:44

編集2020/05/02 05:37
hatena19

総合スコア34075

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hajihaji

2020/05/04 03:42

ご教示ありがとうございます。 大変勉強になりました。 また速度も比べ物にならないぐらい速くなりました。
hajihaji

2020/05/07 05:05

なんども済みません。 例えば処理をしたいリストが空白行を一行はさみブロックとしてある場合、 Range("A1").の部分を変数として処理することは可能でしょうか。 以下のようなふうに目印を起点に処理をするようにしたいのですがうまくいきません。 可能でしたらご教示のほどよろしくお願いいたします。 Sub 条件1() Dim bk1 As Workbook, bk2 As Workbook Set bk1 = ThisWorkbook 'Workbooks("A") Set bk2 = ThisWorkbook 'Workbooks("B") Dim R2 As Long R2 = bk2.Worksheets("結果").Cells(Rows.Count, "A").End(xlUp).Row Dim b As Long For b = 2 To R2 Dim key As Variant '表範囲取得 Dim rg1 As Range, rg2 As Range Set rg1 = bk1.Worksheets("情報").Range("A1").CurrentRegion Set key = bk2.Worksheets("結果").Cells(b, 1).Find(what:="目印").Address Set rg2 = key.CurrentRegion ' On Error Resume Next Dim a1(), a2() a1 = rg1.Value a2 = rg2.Value Dim i As Long, s As Long, x As Long, y As Long, z As Long For i = 2 To UBound(a1, 1) For s = 2 To UBound(a2, 1) For x = 2 To UBound(a1, 2) For y = 2 To UBound(a2, 2) If a1(1, x) = a2(s, 1) And a1(i, 1) = a2(1, y) Then a2(s, y) = a1(i, x) End If Next y Next x Next s Next i Next b rg2.Value = a2 End Sub
guest

0

以下のような画像をを提示したいただけると、レイアウトが第三者にもよくわかると思います。
(少なくとも1行目は見出し行のように見えますが、そのようなことも提示されていません)

シートのレイアウト
尚、結果シートは、実行前と実行後の両方のイメージがあればわかりやすいです。

>総当たり表の間で条件抽出を行おうとしているのですが・・・
もっと、具体的にどのように、総当たりをするのか、どのように結果を設定するのかを書いていただけませんでしょうか。

投稿2020/05/01 11:32

tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hajihaji

2020/05/01 13:10

画像の添付がうまくいかなかったので文字で起こしました。 一行目は見出しです。 B列a行=”え”が該当しますので、a列B行でも同じ”え”を抽出するだけのものです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問