タイトルの通り、行挿入の高速化方法について質問です。
Excelのシートに、仕様の一部として、例えばA列のセルにデータがある場合、その行に2行ずつ行追加しなければならないような処理を実現しなければならないのですが、レコード件数が多く、該当シートにはオートシェイプも多数存在しており、行挿入の処理でかなり処理時間がかかってしまいます。
現在はループでデータがある場合のみ2行挿入、という処理をしていますがデータ件数は常に同じではないので、大量のデータ(試しているのは200~300件、それ以上もありえる)だった場合に2分以上かかってしまい、全体の処理として4分以上かかってしまいます。
これを高速化する手段はありますでしょうか。
アドバイスや代替案などご教授お願い致します。
【参考:簡略した現在のコード】
VBA
1Application.ScreenUpdating=False 2Application.Calculation = xlManual 3 4Dim i As Long 5i=2 6Do While i <> 最終行+1 7 If Cells(i,1).Value <> "" Then 8 Rows(i+1).Insert Shift:=xlDown 9 Rows(i+1).Insert Shift:=xlDown 10 End If 11Loop 12 13Application.Calculation = xlAutomatic 14Application.ScreenUpdating=True 15
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
サンプルコードについて
記載いただいたソースは(おそらく簡略化した影響だと思いますが)iのインクリメントがなく無限ループにはまってしまいました。
また、最下行も行挿入するたびに+2ずつ増やしていく必要がありそうですが、これも簡略化してしまったためか、指定した最下行まで処理が回らないコードとなっているようです。
本題
さて、ここから本題です。
当方の環境で200行程度のテストデータを作成しサンプルコードを実行したところ、ものの数秒で処理終了しました。
オートシェイプも各行5つくらいずつ貼り付けておきましたが、サイズが小さすぎるのか、負荷とはならなかったようです。
というわけで、速度改善案となるかはわかりませんが、参考までにアドバイスさせていただきます。
まず行挿入や削除を行う処理を作成する場合、私なら最下行から処理を開始します。
サンプルコードをベースに改修するならこんなかんじです。
Dim sht As Worksheet Set sht = Sheet1 '←対象シートを特定しないと、処理中にアクティブでなくなったときに異常動作の原因となります。 Application.ScreenUpdating = False Application.Calculation = xlManual Dim i As Long i = 最下行 Do While i > 1 If sht.Cells(i, 1).Value <> "" Then '2行は1回で挿入 sht.Range(CStr(i + 1) & ":" & CStr(i + 2)).Insert Shift:=xlDown End If i = i - 1 Loop Application.Calculation = xlAutomatic Application.ScreenUpdating = True
わかりやすく小さなデータで説明すると、
今回の処理で2、3、4行目に対象データがあり、それぞれの下に2行ずつ行挿入することを考えます。
普通に上から順に処理していくと、
①2行目に対して3・4行目となる空行を挿入。
②5行目に対して6・7行目となる空行を挿入。
③8行目に対して9・10行目となる空行を挿入。
とう流れになります。
これを逆から行うと
①4行目に対して5・6行目となる空行を挿入。
②3行目に対して4・5行目となる空行を挿入。⇒4~6行目は6~8行目になる
③2行目に対して3・4行目となる空行を挿入。⇒3~8行目は5~10行目になる
となります。
どうでしょう?
上の行は、それ以降の行を追加・削除した影響で行番号がずれたりしないので、こちらの方が管理しやすくなると思います。
一括挿入も視野に入れられるのではないでしょうか?
参考になれば幸いです。
投稿2016/11/28 05:09
編集2016/11/28 05:12総合スコア3013
0
ご提示頂いたコードを一部変更して500件ほどで試してみましたが、一瞬で行挿入が完了いたしました。
私が使用したソースは以下のものです。
VBA
1Private Sub CommandButton1_Click() 2 Application.ScreenUpdating = False 3 Application.Calculation = xlManual 4 5 Dim i As Long 6 Dim lngLastRow As Long 7 8 lngLastRow = Cells(Rows.Count, 1).End(xlUp).Row 9 10 i = 2 11 Do While i <> lngLastRow 12 If Cells(i, 1).Value <> "" Then 13 Rows(i + 1).Insert Shift:=xlDown 14 Rows(i + 1).Insert Shift:=xlDown 15 End If 16 i = i + 1 17 lngLastRow = Cells(Rows.Count, 1).End(xlUp).Row 18 Loop 19 20 Application.Calculation = xlAutomatic 21 Application.ScreenUpdating = True 22 23 MsgBox ("完了しました。") 24 25End Sub
データがあるのと同シート内にボタンを作って実施しました。
よって、行追加に時間がかかるというよりは、別のところに原因があるのではないかと思いました。
例えば改善案として、
案1
ご提示頂いたソースを見た限りですと自シート内にボタンがあるように思えますが、
もしソースがあるファイルと、データがあるファイルが別ならば同一ファイル内で実行してみる。
(これで早くなった場合は、別ファイル操作に問題があると言える)
案2
オートシェイプはただの画像貼り付けでしょうか。
もし、ご提示頂いたソース以外でオートシェイプ操作がありましたらそれを見直す。
(Selectの多使用は遅延の原因の1つです)
案3
これは難しいかもしれませんが、Excelのバージョンを変更することで早くなることがまれにあります。
(例:現在EXCEL2007をご使用ならEXCEL2010で試す)
私の環境は
・windows7
・Excel2010
となっております。
最後にすみません、質問なのですが、
大量のデータ(試しているのは200~300件、それ以上もありえる)だった場合に2分以上かかってしまい、全体の処理として4分以上かかってしまいます。
大量のデータだった場合に2分以上かかり、全体の処理として4分以上かかる、というのは大量のデータに改行を入れる以外に何か2分ほどの別な処理があるということでしょうか?
少しの修正で劇的によくなることがありますので、原因追究には根気が必要ですね^^;
投稿2016/11/28 04:08
総合スコア247
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/28 07:57
退会済みユーザー
2016/11/28 08:01
2016/12/04 06:17
0
ベストアンサー
VBA を使うときは
・画面の更新を停止する
・自動再計算を停止する
ということをいつもやっています。
下記サイトが参考になります。
VBAシステム開発: 2.6.3 画面描画と数式再計算を止める
紹介したサイトにも書いてありますが、
停止させたものは元に戻す必要があるのでご注意ください。
上記の対策は最初におこなわれていましたね。
申し訳ありませんでした。
Insert を 1 回だけ呼ぶようにするだけでも
だいぶ変わるんじゃないでしょうか。
サンプルコードを下記に掲載します。
VBA
1Sub test() 2 Dim i As Long 3 Dim r As Long 4 Const 追加行数 As Long = 4 5 r = Range("A" & Rows.Count).End(xlUp).Row 6 Application.ScreenUpdating = False 7 For i = r To 2 Step -1 8 If Range("A" & i).Value <> "" Then 9 Range("A" & i + 1).Resize(追加行数).EntireRow.Insert 10 End If 11 Next 12 Application.ScreenUpdating = True 13 End Sub
他にも Range による飛び飛びの行を複数指定することで一度に挿入することもできます。
例えば次のようなコードになります。
Range("2:3,6:7").Insert
kpiyohiko さんへのコメントで、指定数に上限があったり、
処理を分けると行情報がずれてしまったりなど問題があるとのことですが、
行を挿入する処理を最下行からおこなえば
行情報がずれることはないと思うので、
その問題に関しては工夫次第でなんとかなると思います。
投稿2016/11/28 00:52
編集2016/11/28 04:11総合スコア217
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/28 02:05 編集
2016/11/28 03:32
2016/12/04 06:13
0
画面の更新は切っておられますか?
相当な高速化が見込めるようです
このリンクの第1位に記載があります
行列の挿入について記載があります
投稿2016/11/28 00:41
総合スコア658
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/28 02:06
2016/11/28 02:14
2016/11/28 02:48
2016/11/28 03:05
2016/11/28 03:50
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/12/04 07:10