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

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

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

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

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

最適化

最適化とはメソッドやデザインの最適な処理方法を選択することです。パフォーマンスの向上を目指す為に行われます。プログラミングにおける最適化は、アルゴリズムのスピードアップや、要求されるリソースを減らすことなどを指します。

Q&A

解決済

5回答

782閲覧

変数への代入処理を高速化したい

K-iwata

総合スコア19

VBA

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

VBScript

VBScript(Visual Basic Scripting Edition)はMicrosftが開発したスクリプト言語であり、Visual Basicのサブセットです。

最適化

最適化とはメソッドやデザインの最適な処理方法を選択することです。パフォーマンスの向上を目指す為に行われます。プログラミングにおける最適化は、アルゴリズムのスピードアップや、要求されるリソースを減らすことなどを指します。

0グッド

0クリップ

投稿2021/04/18 00:46

下記のようなエクセルVBAを作成しています。for next文について営業日が多くなればなるほど、処理が重くなるのでうまく纏めて高速化を図りたいと考えています。うまくまとめる方法をご教授いただけませんでしょうか?

vba

1 2 '変数をセット 3 Dim a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 As Long 4 5 '変数に値を入力 6 a0 = ActiveCell.Offset(0, -2).Value '当日の値 7 Dim workday As Long 8 Dim code As Long 9 workday = ActiveCell.Offset(0, -11).Value 10 code = ActiveCell.Offset(0, -9).Value 11 12 Dim i As Long, B As Variant 13 B = Range("A1:J295680") 14 For i = 1 To 295680 15 If B(i, 1) = workday - 1 And B(i, 3) = code Then a1 = B(i, 10) '1営業日前の値 16 If B(i, 1) = workday - 2 And B(i, 3) = code Then a2 = B(i, 10) '2営業日前の値 17 If B(i, 1) = workday - 3 And B(i, 3) = code Then a3 = B(i, 10) '3営業日前の値 18 If B(i, 1) = workday - 4 And B(i, 3) = code Then a4 = B(i, 10) '4営業日前の値 19 If B(i, 1) = workday - 5 And B(i, 3) = code Then a5 = B(i, 10) '5営業日前の値 20 If B(i, 1) = workday - 6 And B(i, 3) = code Then a6 = B(i, 10) '6営業日前の値 21 If B(i, 1) = workday - 7 And B(i, 3) = code Then a7 = B(i, 10) '7営業日前の値 22 If B(i, 1) = workday - 8 And B(i, 3) = code Then a8 = B(i, 10) '8営業日前の値 23 If B(i, 1) = workday - 9 And B(i, 3) = code Then a9 = B(i, 10) '9営業日前の値 24 If B(i, 1) = workday - 10 And B(i, 3) = code Then a10 = B(i, 10) '10営業日前の値 25 If B(i, 1) = workday - 11 And B(i, 3) = code Then a11 = B(i, 10) '11営業日前の値 26 If B(i, 1) = workday - 12 And B(i, 3) = code Then a12 = B(i, 10) '12営業日前の値 27 If B(i, 1) = workday - 13 And B(i, 3) = code Then a13 = B(i, 10) '13営業日前の値 28 If B(i, 1) = workday - 14 And B(i, 3) = code Then a14 = B(i, 10) '14営業日前の値 29 If B(i, 1) = workday - 15 And B(i, 3) = code Then a15 = B(i, 10) '15営業日前の値 30 If B(i, 1) = workday - 16 And B(i, 3) = code Then a16 = B(i, 10) '16営業日前の値 31 If B(i, 1) = workday - 17 And B(i, 3) = code Then a17 = B(i, 10) '17営業日前の値 32 If B(i, 1) = workday - 18 And B(i, 3) = code Then a18 = B(i, 10) '18営業日前の値 33 If B(i, 1) = workday - 19 And B(i, 3) = code Then a19 = B(i, 10) '19営業日前の値 34 35 Next i 36    ActiveCell.Offset(0, 2) = Application.WorksheetFunction.Average(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) 37

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

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

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

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

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

guest

回答5

0

当日の値も同じ範囲内にあると勝手に仮定してますが、
選択した行の日付を起点に19営業日前までの平均をとりたいのだとすると、
AVERAGEIFS関数を使ってこんな風に書けるのではないかと想像しました。
(場合によってはVBAにせずともセル上に数式を書くだけで用を足したりするかも、とか)

VBA

1 Dim workday As Long 2 Dim code As Long 3 workday = ActiveCell.Offset(0, -11).Value 4 code = ActiveCell.Offset(0, -9).Value 5 6 Dim R As Range 7 Set R = Range("A1:J295680") 8 With Application.WorksheetFunction 9 ActiveCell.Offset(0, 2) = .AverageIfs(.Index(R, 0, 10), .Index(R, 0, 3), code, .Index(R, 0, 1), "<=" & workday, .Index(R, 0, 1), ">=" & workday - 19) 10 End With

投稿2021/04/18 13:45

編集2021/04/18 13:55
jinoji

総合スコア4592

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

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

K-iwata

2021/04/29 08:52

私のコードから実施しようとしている内容の意図をくみ取っていただきありがとうございます。Agebareifs関数にIndexを組み合わせる仕方は大変勉強になり、実際に一番高速化できました。
guest

0

「for next文について営業日が多くなればなるほど、処理が重くなる」とのことですが、
提示のコードではFor i = 1 To 295680と処理数は固定なので関係ないですね。

入力してある範囲だけを対象にするようにすればいいでしょう。CurrentRegionでデータ範囲を取得できます。これで無駄な処理を省略できます。

vba

1 B = Range("A1").CurrentRegion 2 For i = 1 To UBound(B)

あとy-waiwaiさんも回答されているように複数の変数を配列にすればコードはシンプルになります。

配列利用サンプルコード

vba

1 '配列 2 Dim a(0 To 19) As Long 3 '配列に値を入力 4 a(0) = ActiveCell.Offset(0, -2).Value '当日の値 5 Dim workday As Long 6 Dim code As Long 7 workday = ActiveCell.Offset(0, -11).Value 8 code = ActiveCell.Offset(0, -9).Value 9 10 Dim i As Long, B As Variant 11 B = Range("A1").CurrentRegion.Value 12 For i = 1 To UBound(B) 13 If B(i, 3) = code Then 14 Dim diff As Long 15 diff = workday - B(i, 1) 16 If diff > 0 And diff < 20 Then a(diff) = B(i, 10) 17 End If 18 Next i 19 ActiveCell.Offset(0, 2) = Application.WorksheetFunction.Average(a)

また、営業日がどんだけあろうと、コードを見るかぎりは対象は当日から19営業日前までの20個だけなので、データが営業日の昇順(あるいは降順)になっているなら、Index関数で開始位置を取得してそこから20個分のデータを取得すればそもそもForループ自体が不要になりますね。
データ例の提示がないので推測ですが。

投稿2021/04/18 03:08

編集2021/04/18 03:55
hatena19

総合スコア34075

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

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

0

みんな勘違いするのですが、VBAにおいては
Dim a0, a1, a2 As Long
という書き方だと、
Dim a0 As Variant, a1 As Variant, a2 As Long
と書いたのと同じ意味になります。

投稿2021/04/18 14:12

iruyas

総合スコア1067

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

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

0

ベストアンサー

ぱっと見て思う事は

vba

1If B(i, 1) = workday - 1 And B(i, 3) = code Then a1 = B(i, 10) '1営業日前の値

の And B(i, 3) = code の同じ判定がずらっと並んでいますが、ここが成立しないと代入しないなら、最初に別のIfで判定してしまえばよいと思います。
If文をAndで括って判定する場合、If~Thenまで間の全ての条件を判定するのでここで無駄に判定が増えます。

vba

1 For i = 1 To 295680 2 If B(i, 3) = code Then 3 If B(i, 1) = workday - 1 Then a1 = B(i, 10) '1営業日前の値 4 56 7 If B(i, 1) = workday - 19 Then a19 = B(i, 10) '19営業日前の値 8 End If 9 Next

これで、If判定の回数が半分程度になります。
データの並びによっては、If B(i, 1) = workday - 1~19 のIf判定も、If B(i, 1) = workday - 1だけでよいかもしれませんし、hatena19さんの回答のようにForの処理自体がそもそも要らなくなる可能性もあります。

投稿2021/04/18 03:30

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

K-iwata

2021/04/29 07:50

シンプルにわかりやすいアドバイスありがとうございました。
guest

0

変数をたくさん作るんでなくて、配列にしてしまいませんか

投稿2021/04/18 00:49

y_waiwai

総合スコア88042

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問