海外旅行から帰ってきたら、まず何を食べる?

野球の投打の成績がエクセルの集計表の形でまとめられています。40~50チームがあり、トーナメントですので、出場45チームなら44試合で、エクセル集計表が44個になります。
大会が終わるとその総合成績、個人の投打成績やチーム成績を出しています。
その最初のエクセル操作の手続きとして、44個の試合ごとエクセルを順番に開いて、総合成績を出すためのエクセルにコピペしています。
操作は同じことの繰り返しのため、マクロを作りました。
一つ目のファイルオープン→コピペなど→ファイルクローズ、
二つ目のファイルオープン→コピペなど→ファイルクローズ、
…44個目のファイルオープン→コピペなど→ファイルクローズ
といった感じです。マクロに多少の項目の追加変更はあっても基本同じで、10年以上前から運用していますが、パソコンを買い替えると、そのマクロが急に遅くなりました。感覚的ですが1~2分で終わっていたのが、20分かかりました。ただ、20分と言っても大会の途中で試合数(エクセル集計表の数は20個)ですので44個になったら単純に倍の40分程度かかるのかなと推測です。
ネット検索で、マクロの処理が遅いのは、プログラムの作り方の問題との記載があり、それなりに経験もしました。
今のパソコンは起動、普通の入力操作は、決して遅くありません。

 cellに値を入れるのも、一つずつ入れるのではなく、配列を用意して配列から、cellに範囲を決めて入れること。

Application.ScreenUpdating = False '画面表示固定
Application.ScreenUpdating = True '画面表示固定解除
を命令の前後に入れることで画面の動きの手続きがなくなり早くなる。(これは既に組み込み済み)

Sheets("Sheet1").Select
みたいな、シートを変える手続きを繰り返しの中に頻繁に入れないこと。

 今回、Excelファイルを閉じる際に、メモリ解放することのアドバイスが書かれた
https://qiita.com/AkiUnleash/items/fc8f783a94282 …
のURLも見つけ、「DoEvents」というメモリ解放する命令を見つけ試行しました。
が、早くなりましたが、時間にすると半分ですが10分かかりました。それでも遅いです。

 1~2分の処理時間が10分も掛かるようになってしまったのは、エクセルの仕様が変わったのでしょうか。今のエクセルは、「Microsoft Office Home and Business 2021」でした。少なくともこれまで使ってきた1~2分で処理するパソコンはVista以降です。Windows8、Windows10です。エクセルのバージョンは分かりませんが。

 マクロの一部ですが、以下にコピペしました。

 他に何かプログラムを工夫すれば良いのか、パソコンの設定の問題なのか、少しでもわかる方、ご助言下さい。

Sub 集計表から取込作業()
Worksheets("ファイル名").Cells(2, 8) = Time$
Dim セル値(113, 85)
Dim 背番号対応(2, 20, 20) '1:先攻、2:後攻
Dim 登板(30)
Application.ScreenUpdating = False '画面表示固定
p = 1
j = 2
j2 = 2

Do Until Worksheets("ファイル名").Cells(p, 1) = ""
Sheets("貼り付け").Select
Range("E1:AY112").Select
Range("E112").Activate
Selection.ClearContents

ドライブ元 = ThisWorkbook.Path
ファイル名 = Worksheets("ファイル名").Cells(p, 1)
読込ファイル名 = ドライブ元 & "\" & ファイル名
Workbooks.Open Filename:=読込ファイル名
For x = 1 To 113
For y = 1 To 85
セル値(x, y) = Cells(x, y)
Next y
Next x
ActiveWorkbook.Close

'Close待機
DoEvents

For x = 1 To 113
For y = 1 To 85
If セル値(x, y) <> "" Then
Worksheets("貼り付け").Cells(x, y) = セル値(x, y)
End If
Next y
Next x

(途中、だらだらと長いので省略)

p = p + 1
Loop
Worksheets("ファイル名").Cells(3, 8) = Time$
Application.ScreenUpdating = True '画面表示固定解除
End Sub

質問者からの補足コメント

  • お礼の欄は、一度投稿したら、二度目のお礼欄がありませんので、こちらから。
    ◆「高速スタートアップ」の無効化方法を試行錯誤していた結果、うまく設定できたかどうか分かりませんが、マクロが速く動くようになりました。#1~#3の方のプログラムを変更する助言もいただき、その結果から速くなったと思いましたが、プログラムを元に戻してもマクロは速いままでした。
    設定変更を試行した際に、不要なメモリの内容がクリアされたのかなと憶測します。
    有難うございました。

    No.5の回答に寄せられた補足コメントです。 補足日時:2024/09/22 22:25

A 回答 (5件)

No2です。



>ちなみに一試合のエクセルファイルの容量は56KBです
その程度の容量であれば、ごく一般的であろうと思われます。
ちなみに当方の環境であれば、そのくらいのファイルをOpenするのには1秒かからない程度の時間で済みます。
(環境依存なので一概には言えませんけれど)

>ここもセル以外の配列を作って、その配列から一括して
>代入するように書き換えれば早くなると思いますが
No1に書きましたけれど・・・
質問文にご提示の処理は1セルずつ処理する方式なので、配列を使ってはいても、処理速度の観点から言うと決して早くはありません。
むしろ配列を使わない方が速い可能性もあります。
(メモリ上でのアクセスなので、メモリ不足でない限りは、差は微々たるものですが・・)

「配列を使う」ことが速度向上の本質ではありません。
速度向上に関して、このあたりの意味を理解なさっていないのではないかと懸念されます。
具体的な方策についてはNo1に述べた通りなので、省略します。
    • good
    • 0
この回答へのお礼

多くの助言をいただきました。有難うございます。

お礼日時:2024/09/24 16:06

パソコンを再起動してはいかがでしょうか?


「高速スタートアップ」が有効になっている可能性があります。
※再起動時には「高速スタートアップ」になりません。

Windowsの設定で「高速スタートアップ」が有効になっていると、実際にはシャットダウンされずメモリ上の一時ファイルや不要なプロセスがクリアされておらず、遅くなる原因になります。
どちらかというと、メモリの内容がストレージに保存される『休止状態』に近い状態で電源オフになります。

◆「高速スタートアップ」の無効化方法
スタート
⇒設定
⇒システム
⇒「電源とスリープ」
⇒「関連設定」欄から「電源の追加設定」
⇒「電源ボタンの動作の選択」
⇒「現在利用可能ではない設定を変更します」をクリック
⇒「シャットダウン設定」欄の「高速スタートアップを有効にする」のチェックを外して、「変更の保存」をクリック
この回答への補足あり
    • good
    • 0
この回答へのお礼

この方法で、処理時間短縮になる気がします。
が、この問題のパソコンは、ご回答いただいた設定の画面とは異なります。
スタート
⇒設定
⇒システム この次に「電源とバッテリー」があり、
⇒「電源とスリープ」←ここまでたどり着きましたが、次の項目は、

バッテリー起動時に、次の時間が経過した後に画面の電源を切る
電源接続時に、次の時間が経過した後に画面の電源を切る
バッテリー起動時に、次の時間が経過した後にデバイスをスリープ状態にする
電源接続時に、次の時間が経過した後にデバイスをスリープ状態にする

の4つの設定画面のみで、「高速スタートアップを有効にする」のところには行けませんでした。このキーワードを使って、「高速スタートアップを有効にする」でグーグルやヤフーで検索しましたが、見つけられません。(今のところですが…。)
助言をいただけましたので、少し設定画面を試行錯誤に探してみます。

お礼日時:2024/09/22 13:30

シート内に関数式が埋め込まれているなら、シートの更新ごとに自動計算を行い、その結果遅くなります。



以下を試してみてはいかがでしょうか。
①マクロの先頭に
Application.Calculation = xlCalculationManual
を追加し
②最後に
Application.Calculation = xlCalculationAutomatic
を追加します。

①で自動計算を手動計算にし(自動計算を行わないようにする)
②で自動計算に戻しています。

マクロ実行中に、異常停止などがあると、手動計算のままになります。
その場合は、自動計算に戻しておいてください。
自動計算/手動計算については、下記URLが参考になるかと思います。
https://offisu-soft.com/post/detail/1336
https://www.isa-school.net/blog/office-excel20/

シート内に関数式が埋め込まれていない場合は、無視してください。
    • good
    • 0
この回答へのお礼

コメント有難うございます。関数は入っています。関数の結果で、if関数で条件式入れてますので誤動作する可能性あります。一つ学習しました。

お礼日時:2024/09/17 16:45

No1です。



連投すみません。

書き忘れましたが、データファイルを順にOpenしてゆく処理なので、これにかかる時間の分は短縮できません。
手動で1ファイルを開く際にどのくらいの時間がかかっているでしょうか?

例えば、重いファイルで開くのに1分かかるのなら、概ね「1分×ファイル数」だけの時間は最低でもかかってしまうことになるので、マクロの処理を効率化しても全体としての効果はあまり期待できないことになってしまいます。

ご質問文を読むと、旧い時代から継続的に利用なさっているようですが、旧いエクセルでは、使用しているうちにゴミが溜まって肥大化するという欠点がありました。
(現在は改善されているようですが)
もしも、ずっと継続的に利用なさっているデータファイルの場合は、一度ファイルの容量を調べてみてください。
肥大化している様なら、必要部分だけを新しいファイルにコピペすることでスリム化が可能と思います。
データの内容にもよりますので一概には言えませんけれど、A1:CG113に固定値が入っている程度のファイルなら、せいぜい100kB前後であろうと推測できます。
    • good
    • 0
この回答へのお礼

何度もコメント有難うございます。
職場に少し古いデスクトップパソコン(Windows10)があります。
さっき、このエクセルマクロを動かしました。本日、試合が3試合ありましたので、オープン・クローズの手続きが3つ増えます(21個が24個に増えた)が、1~2分で処理が終わりました。
ちなみに一試合のエクセルファイルの容量は56KBです。このエクセルファイルが今は24個あります。
最近、買ったパソコンで、このマクロを実行すると20分、「DoEvents」命令を入れると時間が短縮されますが10分の待ち時間になっています。
マクロのソースを途中のところを書いていませんが、何カ所も、セルからセルに値を代入する命令はあります。ここもセル以外の配列を作って、その配列から一括して代入するように書き換えれば早くなると思いますが、沢山ありすぎでソースを直すことが容易ではありません。
パソコンが新しくなっても環境が変われば処理が遅くなるケースがあるのだと納得いきませんが、従うしかないのかなと感じます。

お礼日時:2024/09/15 19:39

こんにちは



遅くなった理由はハッキリとはわかりませんけれど、環境の違いでしょう。
CPUの能力差や、エクセルで使える空きメモリの差などの影響であろうと考えられます。


一方で、
>cellに値を入れるのも、一つずつ入れるのではなく、
>配列を用意して配列から、cellに範囲を決めて入れること。
ご提示の方法では、結局1セルずつ処理しているので配列を使っても使わなくても同じことですね。
エクセルマクロの場合、時間がかかるのはセル(シート)へのアクセスです。
この回数を減ずることで速度向上を期待できます。

ただし、ご提示の処理だと同じシートに順にコピペして行っているので、シートに関数等が設定されていて、データの値に基づいてその計算結果を更にどこかに集計しているのかと想像しました。
実際のシートの仕組みがどのようになっているのか不明ですけれど、データをコピペしているA1:CG113の範囲内の一部である、E1:AY112だけを毎回クリアしている理由も不明ですね・・
(ご提示のコードだけからだと、不要な処理のように思えます)

また、値を転記する際に
 >If セル値(x, y) <> "" Then
として、空白値をペーストしないようにしているのは、そこに関数等が設定されているからなのでしょうか?
(その割には、元データに依存と言うのも不可思議ですが・・)
もしそうなら、関数等はA1:CG113の範囲外に設定しておく仕組みにしておく方が賢い方法と考えられます。
そうすることで、A1:CG113をまとめてペーストできるようになりますので。

ご提示の部分の処理に関して言うなら、上記のような仕組みにしておくことで、
 コピー先シート.Range("A1:CG113").Value = _
 コピー元シート.Range("A1:CG113").Value
の1センテンスで処理できるようになりますし、シートへのアクセスも2回で済むので、大幅に速度向上ができるのではと考えらえます。
    • good
    • 1
この回答へのお礼

変更箇所(1)

For x = 1 To 113
For y = 1 To 85
セル値(x, y) = Cells(x, y)
Next y
Next x

↑この手続きを ↓に変える
For x = 1 To 113
For y = 1 To 85
セル値(x - 1, y - 1) = Cells(x, y)
Next y
Next x


変更箇所(2)

For x = 1 To 113
For y = 1 To 85
If セル値(x, y) <> "" Then
Worksheets("貼り付け").Cells(x, y) = セル値(x, y)
End If
Next y
Next x

↑この手続きを ↓に変える
Range(Cells(1, 1), Cells(113, 85)).Value = セル値

これで1分以内で動作しました。ご助言有難うございました。

手続き上、ファイルオープン→元ファイルにペーストの際、複数のブックが開いた状態で、ペースト先のシートを選択する際の指定方法がブックとシートの指定が必要になるため、苦肉の策でファイルオープン→一時保存ための配列に複写→ファイルクローズ→時保存ための配列から指定シートに複写をしていました。空白を飛ばす手続きは、処理時間の短縮です。(10年以上前に組んだマクロです)
セルに値を入れる時間がかかる点をあまり分からずに組んだものでした。

お礼日時:2024/09/22 18:10

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A