- ベストアンサー
マクロ実行が遅い・・・
皆さんにおしえてもらいながら下記のようなマクロを組みました。 しかし、マクロを実行すると計算中が長いのです。 もしこのマクロに原因があれば教えてください。 よろしくお願いします。 -------------------------- Sub 見積書作成() Sheets("見積書").Select '見積書シートを選択 For i = ActiveSheet.UsedRange.Rows.Count To 1 Step -1 If Cells(i, 5).Value = "0" Then '工数が「0」のときは Rows(i).RowHeight = 0 '行高さ「0」 End If Next For i = ActiveSheet.UsedRange.Rows.Count To 1 Step -1 Range("E8:E55") = Application.Round(Range("E8:E55"), 0) '工数を四捨五入 Next Dim Rng As Range Const Retu = "C" '<--- ここで「小計」の列を指定します。 For Each Rng In Range(Retu & "1", Range(Retu & "65536").End(xlUp)) If Trim(Rng.Value) = "小 計" And _ Rng.Offset(, 6) = 0 Then Rng.EntireRow.Hidden = True End If Next Rng End Sub
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
行いたいことは、下のようなことでしょうか。以下、気がついた点を・・・ ●"E8:E55"を判定基準に使いたいように見えたので、UsedRangeや For Each Rng を書き換えてみました。 3種類の書き方のFORループがあって何か見づらいですね。 ●セルの表現を .Cells に統一。 ●RowHeight = 0 と EntireRow.Hidden = True は同じことを意図している? Hiddenに統一。 ●Application.Round をこの順に行うと、工数=0 になってしまうかもしれない。 その前で、工数=0 を非表示にしていることと齟齬をきたす? が、そのままにしてある。 Forループは削除。 ●Application.ScreenUpdatingを入れたが、この程度の行数なら影響は些細か。 多分、計算時間はほとんどかからないはずです。ご参考に。 Sub 見積書作成() Sheets("見積書").Select '// 見積書シートを選択 Application.ScreenUpdating = False Dim rw As Integer '行カウンタ With Range("E8:E55") For rw = 1 To .Rows.Count '// 工数が「0」のときは行を表示しない If .Cells(rw, 1) = 0 Then .Cells(rw, 1).EntireRow.Hidden = True End If Next .Value = Application.Round(.Value, 0) '// 工数を四捨五入 For rw = 1 To .Rows.Count '// 小計が「0」のときは行を表示しない If Trim(.Cells(rw, -1)) = "小 計" And .Cells(rw, 5) = 0 Then .Cells(rw, 1).EntireRow.Hidden = True End If Next End With Application.ScreenUpdating = True End Sub
その他の回答 (5)
- papayuka
- ベストアンサー率45% (1388/3066)
まず、Sub 見積書作成() の次に Application.ScreenUpdating = False を入れる。これで結構違うのでは? 後は他の方の回答にあるように、2番目の For i は不要 シート構成が不明なので明確に断言は出来ませんが、1番目の For i と3番目 For Each のループはちょっと工夫して同一ループ内で出来そう。
- imogasi
- ベストアンサー率27% (4737/17069)
・#3でご指摘のFor NextのLoopの中で、iと言う変数が含まれた処理が無いと、通常では意味が無いですよ。繰り返して時間を過ごすとか、音を連続するように見せるとかの例外を除いて。 For i = 5 To 55 Cells(i, "E") = Round(Cells(i, "E"), 0) Next i ・Worksheets("sheet4").Range("a1:a10") = 10 はA1:A10のセルに10が入ります。 特殊な場合以外は使えないでしょう。 ・また複数セルRangeに対し一度にRound関数は使えるたかしら。 ・WorksheetFunctionにRoundは使えたでしょうか それやこれやで、Range("E8:E55") = Application.Round(Range("E8:E55"), 0)はおかしくないですか。 ・For Each の繰り返しはNextだけで良くて、その後のRngは不要では。
- ja7awu
- ベストアンサー率62% (292/464)
For i = ActiveSheet.UsedRange.Rows.Count To 1 Step -1 Range("E8:E55") = Application.Round(Range("E8:E55"), 0) '工数を四捨五入 Next このFor~Nextは、意味が無いと思いますよ。 空回り!! しかし、tawsさん 連続してこういう質問の仕方をしても、どうも思いませんか? 全く、信じられません。 ちょっと考えてほしいですね。
詳しくはないのですが、 できるだけ、IF文や変数の数、処理を減らす、のがよいと思います。 1)For i = ActiveSheet~という文が2行ありますが、一緒に計算させることはできませんか?ループが2周すると結構時間がかかると思います。 2)step -1って、小さい数に減算しているんですよね。「数を減らす」ほうが、遅いかもしれません。小さい数から数を増やして処理するようにできませんか? 3)Retu = "C" って使っていますが、変数を使うより、直接「”C”」書き込んだほうが早いと思います。 4)if ~ and ~ then(両方のif文を処理してから判定する)のほうが、 if ~ then if ~ thenより処理が遅い可能性があります。片方のif文で条件に合わなければ、その時点でループから抜け出ることができると思います。 5)65536行目まで処理する必要がありますか?ここが一番時間かかりそうですね。ある程度の行で妥協してはどうでしょうか。 反対に処理が遅くなる。。。ってことにならなければいいのですが。。。
- hana-hana3
- ベストアンサー率31% (4940/15541)
一応、毎日マクロを組むのを仕事にしています。 でも、経験が浅いのでテクはありませんが・・・。 > Rows(i).RowHeight = 0 '行高さ「0」 ですが、対象になるのは何行くらいかわかりませんが、これは結構時間を食う仕事です。 オートフィルタで工数が「0」以外の物抽出して、それを別のシートにコピーしてから作業を始めてみたらいかがですか?