[[20220311165942]] 『EndSubでメモリ不足になる』(傘) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『EndSubでメモリ不足になる』(傘)

マクロの終了時にメモリ不足でエクセルが落ちるので困っています。
問題が起きているマクロは

 Sub
 ※1 別のブックを開いて1×20セルのデータを書き込んで閉じる
 ※2 シートの1つをMoveメソッドで新規ブックに分けて保存
 ※3 ユーザーフォームを表示して終了するかしないか選択
 End Sub

というのが大まかな流れです。
これがEndSubまで行くとメモリ不足のエラーが出て強制終了します。(体感8割くらい)
※3の後にブレークポイントを入れてステップ実行したところ
EndSubの直前までは問題なく動作しますがEndSubが実行されるとエラーになります。
ブックを閉じる操作が処理に追いつかないことがあるのでClose後にDoEventsを入れると良いという記事を読んだので
各※の間に入れてみたのですがだめでした。
メモリ不足の対策もしくは原因の心当たりが何かあれば教えてください。

< 使用 Excel:Office365、使用 OS:Windows10 >


たぶんこれ
※2 シートの1つをMoveメソッドで新規ブックに分けて保存
シートのデータ量を少なくして試してみれば・・・。
(perhaps) 2022/03/11(金) 18:18

事象が再現するできるだけ短いコードを一式提示できませんか?
そうすれば、皆さん方に、検証・検討ができ、
有用な情報提供となると思います。
(γ) 2022/03/11(金) 19:37

>perhaps さん
分離してるシートはA4で1〜2枚程度のサイズで画像を貼ってたりもしないので
そんなに重いファイルではないと思うんですが…
かといって※1も※3も原因になるとは思えないのでやはりそこですかね?
単独で動かしてもエラー落ちするか確認してみます。

>γ さん
すみません、やはり実コードがあったほうがいいですよね。
申し訳ありませんが会社で作成しているファイルで今は手元にないので
週明けにあらためて追記します。
(傘) 2022/03/11(金) 20:55


※2単独でもエラーになったのでやはりそこが悪いようです。
問題部分のコードの抜粋を載せます。
スマホからなのでミスがあるかもしれません。

 Sub 確認シート_申請確定()

 If ActiveSheet.Name <> "確認" Then Beep: Exit Sub
 Dim anlNum As Long

 Application.EnableEvents = False
 Application.DisplayAlerts = False
 Application.ScreenUpdating = False

 '※1 Call データベース書き込み

 anlNum = 9999
 '本来は※1内で取得

 Worksheets("申請シート").Visible = True
 Worksheets("申請シート").Select

 Call 個別ブック作成(anlNum)

 Application.EnableEvevts = True
 Application.DisplayAlerts = True
 Application.ScreenUpdating = True

 End Sub

 Sub 個別ブック作成(ByVal anlNum As Long)

 Dim fName As String, saveName As String
 Dim shp As Shape

 With ThisWorkbook.Worksheets("確認")
     .Unprotect
     .EnableSelection = xlNoRestrictions
     .Range("B4") = anlNum
     For Each shp In .Shapes
         shp.Delete
     Next shp
     .Range("O4:T7").Locked = False
     .EnableSelection = xlUnlockedCells
     .Protect DrawingObjects:=False
 End With

 fName = Format(DateAdd("m", -3, Now), "yy") & "-" & Format(anlNum, "0000")
 saveName = ThisWorkbook.Path & "\データベース\分析票\" & fName & ".xlsm"
 ChDir ThisWorkbook.Path

 Worksheets("確認").Name = fName
 Worksheets(fName).Move

 ActiveWorkbook.SaveAs fileName:=saveName, FileFormat:=xlOpenXMLWorkbookMacroEnabled
 Workbooks(fName).Close
 DoEvents

 End Sub
(傘) 2022/03/14(月) 09:43

Application.EnableEvevts = True → Application.EnableEvents = True
Workbooks(fName).Close → Workbooks(fName & ".xlsm").Close
の二点を修正しましたが、特段エラーにはなりませんでした。
# まったくの新しいブックであることが差異でしょうか。
当方 OS Windows10,Excel2019 の環境です。
他の方からの回答をお待ちください。
(γ) 2022/03/14(月) 10:04

シートのデータ量を少なくして試してみれば・・・。
これやってませんよね。

>そんなに重いファイルではないと思うんですが…

自分でそう思っているだけですよね。
極端にに減らしてみてください。
エクセルのシートコピー、移動はかなりヘボいです。
(perhaps) 2022/03/14(月) 10:17


 デバッグ方法のアドバイスを。

 エラーの原因となる箇所を絞り込むため、
 それぞれ処理のブロックをコメントアウトして
 実行していく。

 例えば、Withで囲っているところ等

 結果不再現であれば、複合的なものでしょう。

 もし、やられていたら、その結果も欲しいですね。

(tkit) 2022/03/14(月) 10:26


試しに"確認"シートを申請確定マクロ実行用のボタン以外全部消して
マクロの中身もシートのMoveメソッドだけにしてもエラーになったので
どうやら本当にシートを移動して保存という操作だけが原因っぽいんですが
確認シートの中身を消さない状態で何十回連続でやってもエラーにならなかったり
中身を消したシートでファイルを開いて2回目でエラーになったりと
全く再現性が無くお手上げ状態です。

タスクマネージャーでエクセルのメモリの使用量を見てみましたが
大丈夫なときは130MBほど使用してても問題なく動いているのに
ダメなときは100MB程度でエラーになるので何も参考になりませんでした。

このファイルは自分個人が使うために作っているわけではないため
エクセルが落ちるようなエラーが起きるのは非常に困るので
今思い付く解決策としては
・あらかじめ確認シートをMoveメソッドで分離しておいて、確認シートで実行するのは保存して閉じるだけのマクロに変える
・確認シート分離の代わりに別ブックを開いて確認シートとして使用し、それを名前をつけて保存する
くらいなのですが、他に何か方法はあるでしょうか?
(傘) 2022/03/14(月) 11:53


メモリ不足限らず、よくある再現性が低いエラーの原因は、
ブック又はシートの指定をしていない場合に見られます。
まず、そこを改善してみましょう。

また、移動するシートオブジェクトにマクロの記述がある場合、
思わぬ動作となることも考えられますし、セルに記述している数式や、
他ブックの参照など、いろいろ考えられますね。

1つづつ潰していくことがデバッグの定石です。
(tkit) 2022/03/14(月) 12:01


同じ環境が用意できませんので的外れかもしれませんが気になった点など。

■1
↓最初のほう要らないような気がします。

 .EnableSelection = xlNoRestrictions
 .EnableSelection = xlUnlockedCells

■2
↓何の目的があるのですか?

 ChDir ThisWorkbook.Path

■3
↓マクロ付きブックじゃないとダメなんですか?

 FileFormat:=xlOpenXMLWorkbookMacroEnabled

■4
↓"選択"したい理由は何ですか?

 Worksheets("申請シート").Visible = True
 Worksheets("申請シート").Select

■5
ひな形的なものを考えていらっしゃるなら、MoveよりCopyのほうが安心ではないでしょうか?

 Worksheets(fName).Move

さらに↓はあらかじめひな形に設定しておけば済む話だったりしませんか?

   .Range("O4:T7").Locked = False
   .EnableSelection = xlUnlockedCells
   .Protect DrawingObjects:=False

■6
ということを踏まえると↓のようでもいいのではないかとおもいます。
興味があれば【ステップ実行】して研究の上、使えそうな部分をご自身のコードに組み込んでみてください。

    Sub 研究用()
        If ActiveSheet.Name <> "確認" Then
            Beep
            Exit Sub
        End If

        Dim anlNum As Long

        Stop 'ブレークポイントの代わり
        Application.EnableEvents = False

        'Call データベース書き込み
        anlNum = 9999 '本来は↑で取得

        ThisWorkbook.Worksheets("確認").Copy
        With Workbooks(Workbooks.Count)
            .Worksheets(1).Unprotect 'いらないかも
            .Worksheets(1).Range("O4:T7").Locked = False 'いらないかも
            .Worksheets(1).EnableSelection = xlUnlockedCells 'いらないかも
            .Worksheets(1).Protect DrawingObjects:=False 'いらないかも

            .Worksheets(1).Shapes.SelectAll
            Selection.Delete

            .Worksheets(1).Name = Format(DateAdd("m", -3, Now), "yy") & "-" & Format(anlNum, "0000")

            .SaveAs Filename:=ThisWorkbook.Path & "\データベース\分析票\" & .Worksheets(1).Name
            .Close
        End With

        Application.EnableEvents = True
    End Sub

(もこな2 ) 2022/03/14(月) 12:05


 ここでいう「メモリ不足」って、
 別に「ExcelがRAMを使い切っちゃってる」って意味ではないですからね。
 タスクマネージャーと睨めっこしても何も得られないと思いますよ。

 ニュアンス的には「一気に動かそうとする部品の数が多すぎます」みたいな感じで、
 例えば「スパークラインてんこもり」のシート上でオートフィルタで絞り込みした時とか
 マクロや物理メモリとは関係なく発生する場合もあります。

 エラーが出るだけまだマシな方で、以前、
 条件付き書式を設定した(複雑な)セル範囲をClearContentsしたら
 そこでマクロが終わる(エラーではなく終了)なんて現象に遭遇した事もありました。
 (↑これも確かシートの保護が絡んでたと記憶してます)

 構成部品が多くなればなるほど、よく分からない動きってのは出てくる様ですね。

 一度発生するとステータスバーの情報等、色々と動作がアテにならなくなるので
 私の場合は、素直にExcelを再起動する様にしてます。

 上記の例だと、
 「スパークラインてんこもり」の時点で不可避なので、
 「フィルタ使う時は覚悟する事!」って運用で誤魔化してますし、
 ClearContentsの方は .Value = Empty で処理すれば終了する現象は発生しませんでした。

 「これ」という定番の対策は無いと思った方が良いですよ。

 >Moveメソッドだけにしてもエラー
 と言うので思い付くのは、
 非表示の名前定義が山ほど潜んでたのが直接の原因で、
 その原因は過去に一時的に存在した外部リンク・グラフ・描画オブジェクトの無効な名前定義が
 シートのコピー等により増殖していって、とうとう許容量に達した
     ・・・とか、過去から原因を引きずってる可能性もあります。
                 この手の問題はもう、いろいろと試してみるしかないと思いますね。

(白茶) 2022/03/14(月) 14:49


状況が進展しました。根本の原因はこのマクロではなかったかもしれません。

そもそも"確認"シートは"申請シート"に入力した内容を、ひな形の非表示シート"元シート"をマクロでコピー・転記して作成するのですが
"確認"シート作成後に何故かCPUの使用率が60%くらいまで上がったままになるのを確認しました。
アクティブシートを"申請シート"に変えたらCPUの使用率は下がったので
非表示の"元シート"コピー→コピーしたシートを表示して名前を"確認"に変更→"申請シート"非表示→データ転記 という形だったのを
"元シート"コピー→名前変更して転記(アクティブシートは"申請シート"のまま)→転機が終わってから"確認"シートを表示→"申請シート"非表示 としたらCPU使用率が上がらなくなりました。

まだ解決したと断言はできませんが、"確認"シート作成の流れを上の形にしてからはまだメモリ不足のエラーは出ていないので
もしかするとこのCPU使用率の上昇が負荷になってエラーを引き起こしてたのかもしれません。
(傘) 2022/03/14(月) 15:03


もこな2さん
>■1,5
使用者には手操作で触られたくなくてロックしているところをマクロで操作する必要があるので記述しています。
ひな形については上記の通りです。
>■3
ブックとして分けた後にもシートモジュールのイベントを使用する予定があるのでマクロブックで保存しています。
(今は邪魔なので全てコメントアウトしていますが)
>■2,4
何か入れた方が良いと思った理由があって入れていたはずなんですが忘れてしまいました…

白茶さん
>別に「Excelが〜
PCのメモリ容量=エクセルが使えるメモリ量 ではないことは知っていましたが
エラーになるときとならないときで使用量に傾向があったりしないかを期待して確認していました。
結局メモリ使用量は何も関係なく、代わりにCPU使用率の異常に気づけはしたので結果オーライではあったのですが。

(傘) 2022/03/14(月) 16:19


う〜ん。。。。
違うかも知れませんが、、、、

名前の定義が異常に多い。
セルのスタイルが異常に多い。
セルの書式設定を個々のセルで設定している。
シート上の図形を頻繁に書いたり消したりしている。
ファイルが壊れている。
パソコンそのもののエクセルを動かせるメモリがそもそも足りない。

長く使っているファイルだと、不要に書いたり消したりを繰り返していると、
ファイルが壊れることがあるような気がします。

新規ファイルにセルの値とマクロコードだけをコピペして、
新しく作り直すと、エラーにならないような気がします。
めんどくさかったら、新規ブックにシートまるごとコピーして、
新しく名前を付けて保存で上手く行くかもです。

(まっつわん) 2022/03/14(月) 17:02


なんか、「提示されてなかった情報が原因だったかもなんて言われても…」みたいな話になっててすいません。

続報という訳でもありませんが、エラーが発生しなくなったマクロにセルのロックをするコードを追加したら
またメモリ不足のエラーが出るようになりました。
これについてはセルロック以外で対応するつもりなので問題はないのですが
白茶さんの話にもあるように、エクセルにとってセルのロックはかなりリソースを食う操作なのかもしれませんね。
既存のコードのセルロックも別のやり方を検討してみます。

動作確認のため何十回もシートをコピーして消してを繰り返しているので
新規ファイルへの引っ越しもやってみようと思います。
(傘) 2022/03/15(火) 09:27


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.