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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

VBA

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

Q&A

1回答

3820閲覧

【Excel】【VBA】Chart オブジェクト の MouseDown イベント・BeforeDoubleClick イベント で発生する、メモリ不足エラーの原因 を突き止めたい

vvvpp

総合スコア4

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

VBA

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

0グッド

0クリップ

投稿2020/04/15 11:56

編集2020/05/12 11:33

まえがき

文字数制限にひっかかってしまったため、一部のコードを消去しました。
消去したコードにつきましては、編集履歴 の方からご確認いただけます。

前提・実現したいこと

先日、VBA(Excel)で、アクティブなChart の名前を取得するべく、
Chart オブジェクト の MouseDownイベント を用いたプラグラム を組みました。

しかし、そのイベントが連続的に実行された場合、
以下のエラーメッセージが発生してしまいます。

このエラーを回避するコードは組めたのですが、
結局、エラーが発生する原因は分かりませんでした。

今後、同様のエラーを発生させないためにも、
このエラーの原因を突き止めたいです。

エラーメッセージ(Microsoft Excel)

MicrosoftExcel

1この操作を完了するにはメモリが不足しています。 2扱うデータ量を減らすか、他のアプリケーションを終了してください。 3使用できるメモリを増やすには、以下を検討してください。 4- 64ビット版の Microsoft Excel を使う。 5- デバイスのメモリを増設する。

エラーメッセージ(イベント ビューアー)

障害が発生しているアプリケーション名: EXCEL.EXE、バージョン: 16.0.4966.1000 障害が発生しているモジュール名: oart.dll、バージョン: 16.0.4900.1000 例外コード: 0xc0000005

該当のソースコード

ここには エラー発生の原因となるコードを載せます。
全体のコードは【ソースコード(全体)】に載せてあります。

VBA

1 2' TestChart 3Public WithEvents TargetChart As Chart 4 5Private Sub TargetChart_MouseDown(ByVal Button As Long, ByVal Shift As Long _ 6 , ByVal x As Long, ByVal y As Long) 7 8 Debug.Print sheet_.ChartObjects(ActiveChart.Parent.Index).Name ' エラー発生 9 10End Sub

【ソースコード(全体)】

VBAModule

1 2Public sheet_ As Worksheet 3Private class_ As New TestChart 4 5Sub Set_Data() 6 7 Set sheet_ = ThisWorkbook.Sheets("Main") 8 Set class_.TargetChart = sheet_.ChartObjects("Chart 1").Chart 9 10End Sub

VBAClass

1 2' TestChart 3Public WithEvents TargetChart As Chart 4 5Private Sub TargetChart_MouseDown(ByVal Button As Long, ByVal Shift As Long _ 6 , ByVal x As Long, ByVal y As Long) 7 8 Debug.Print sheet_.ChartObjects(ActiveChart.Parent.Index).Name ' エラー発生 9 10End Sub

VBAThisWorkbook

1 2Private Sub Workbook_Open() 3 Call Set_Data 4End Sub

エラー発生の経緯

(シート上には、空のChart(種類:2-D 集合縦棒, 名前:グラフ 1)が一つ 存在しています)

上記ソースコードのイベントが実行された場合、
私は 次のように出力されると予測しました。

immediate

1Chart 1 ' 予測した結果

実際には、次のように出力されました。

immediate

1Chart 1 ' 実際の結果

予想した通りの結果となったため、デバッグ作業に移りました。

デバッグとして、Chart を連続的にクリックし、MouseDown イベントを発生させ続けたところ、
上記のエラーが発生してしまったのです。

タスク マネージャー

タスク マネージャー の 【アクティブなプロセスで使用されている物理メモリ】

  • エラー発生前:68 %
  • エラー発生後:69 %

32bitアプリのメモリ上限は2GB…であってますよね?
vbaが2GBフルで使用できるわけではないかと思いますが(Excel本体の機能の分があるため)、
それにしても Excelに割り当てられているメモリが少なすぎるように感じます。

【このプロセスで使用されているため別のプロセスでは使用できない物理メモリの量(中断された UWP プロセスを除く)】の推移

(EXCEL.EXE)

・【' エラー発生 の コード】:増える。

クリック回数物理メモリの量
038,112 K
139,264 K
239,640 K
339,860 K
440,932 K
5(エラー発生)41,088 K

・【' 問題なし の コード】:増えない。
・イベントを無効にした状態(コメントアウト)で検証:増えない。

解決方法

上記コードを次のように変更したところ、
エラーは発生しなくなりました。

before

1Debug.Print sheet_.ChartObjects(ActiveChart.Parent.Index).Name ' エラー発生

after

1Debug.Print ActiveChart.Parent.Name ' 問題なし

しかし、エラー発生の原因は分からないままだったため、
原因の追究をすることにしました。

試したこと(1)

【sheet_.ChartObjects(ActiveChart.Parent.Index).Name ' エラー発生】

【ActiveChart.Parent.Name ' 問題なし】
という結果から、**【.(ピリオド)】**の個数に注目しました。

VBAメモリーリークについて

こちらを参考にして、次のコードを組んでみました。

VBA

1編集履歴をご参照ください。

結果は変わらず、同じエラーが発生しました。

次に、【sheet_.ChartObjects(ActiveChart.Parent.Index).Name】
に原因があるのかを調べるため、次のコードを実行してみました。

VBA

1編集履歴をご参照ください。

結果は問題なし。

【sheet_.ChartObjects(ActiveChart.Parent.Index).Name】
でもエラーが発生しないということは、【MouseDown イベント】に問題がある と考え、
そちらに注目し、原因の追究をすることにしました。
(【試したこと(2)】に続きます)

試したこと(2)

まずは、【MouseDown イベント】以外のイベントだとどうなるのか、
検証してみました。

ただし、【空のActiveChart】という前提 に合わないイベントは、
検証するイベントから除いています。

結果は次の通りです。

イベントDebug.Print sheet_.ChartObjects(ActiveChart.Parent.Index).NameDebug.Print ActiveChart.Parent.Name
MouseDownエラー発生問題なし
BeforeDoubleClickエラー発生問題なし
Activate問題なし問題なし
MouseMove問題なし問題なし
Resize問題なし問題なし

検証の結果、【MouseDown イベント】だけではなく、
【BeforeDoubleClick イベント】でも同じエラーが発生する ことを確認できました。

そこで、次は【BeforeDoubleClick イベント】から、次のコードを検証してみました。

VBA

1編集履歴をご参照ください。

結果は、【MouseDown イベント】と同様のエラーが発生しました。
(【試したこと(3)】に続きます)

試したこと(3)

Chart クリック → 適当なセルをクリック

というのを繰り返した結果、エラーが発生しませんでした。

これに注目し、イベント間に何かしらの処理を挟んでみる ことにしました。
次は、検証用のコードとなります。

VBA

1編集履歴をご参照ください。

上記コードを実行し、Chart クリック → sheet_.Range("F2").Select

というのを繰り返した結果、エラーが発生しませんでした。

検証を深めるため、上記コードを次のように変更してみました。

VBA

1編集履歴をご参照ください。

上記コードを実行し、Chart クリック → sheet_.Range("F2") = boolean_

というのを繰り返した結果、エラーが発生しました。
(【試したこと(4)】に続きます)

試したこと(4)

次に、Chart 1 クリック → Chart 2 クリック

というのを繰り返した結果、エラーが発生しませんでした。

VBA

1編集履歴をご参照ください。

これに注目し、次のコードを検証してみました。

VBA

1編集履歴をご参照ください。

上記コードを実行し、
Chart 1 クリック → sheet_.ChartObjects("Chart 2").Chart.ChartArea.Select

というのを繰り返した結果、エラーが発生しませんでした。
(Chart 一つに使用できるメモリの量が決められていて、そのメモリが、
【セル や 他のChart の Select】が行われるまで解放されない…ということでしょうか?)
(【試したこと(5)】に続きます)

試したこと(5)

その他、次のことを試してみましたが、
結果は変わらず、同じエラーが発生するだけでした。

  • 【ハードウェアグラフィックスアクセラレータを無効にする】を選択する
  • 違う種類のChart(円・折れ線)を使用する
  • book の修復
  • アドイン の無効化
  • Debug.Print sheet_.ChartObjects(ActiveChart.Parent.Index).Name

を、Sub プロシージャ に移し、イベントから、そのプロシージャを呼び出すようにする

  • ステップイン実行【イベント処理終了時(End Sub 到達後、[F8 キー]押下)、エラー発生】

(これにより、処理の終了前に次の処理が開始される → 処理が追いつかなくなってエラー
…という可能性もない、と考えてよさそうです。正直、一番ありえそうな原因だったのですが…

同様の症状について探していたところ、次の質問が見つかりました。
Excel vba でメモリが不足しています。っと表示されて処理が完了できない。

エラーメッセージ はドンピシャだったのですが…
私は、【カメラ 機能】も【リンクされた図】も【数式】も【名前の定義】も
使用(追加)していません。
(そもそも、Excelファイル新規作成 → 空のChartを挿入 → 上記ソースコード を記入
…しか行っていないファイルのため、肥大化とかはしていない…はずです。
念のため、上の手順で同じファイルを作成してみましたが、何も変わりませんでした)

また、次の環境で試してみたところ、エラーは発生しませんでした

Windows 7 Home Premium
メモリ:8.00 GB
Excel 2010 64bit(14.0.7237.5000)

追記:試したこと(6)

sazi 様 からのご指摘を受け、次のコードの検証を行いました。

VBA

1 2Public sheet_ As Worksheet 3Public flag_ As Boolean 4Private class_ As New TestChart 5Private class2_ As New TestChart _ 6 7Sub Set_Data() 8 9 Set sheet_ = ThisWorkbook.Sheets("Main") 10 Set class_.TargetChart = sheet_.ChartObjects("グラフ 3").Chart 11 Set class2_.TargetChart = sheet_.ChartObjects("グラフ 1").Chart 12 flag_ = False 13 14End Sub

VBA

1 2Private Sub TargetChart_BeforeDoubleClick(ByVal ElementID As Long, ByVal Arg1 As Long, 3ByVal Arg2 As Long, Cancel As Boolean) 4 5 DoEvents 6 7 If flag_ = False Then 8 9 flag_ = True 10 11 Debug.Print sheet_.ChartObjects(ActiveChart.Parent.Index).Name ' エラー発生 12 13 flag_ = False 14 15 DoEvents 16 17 End If 18 19End Sub

検証の結果、エラーが発生しました。

ステップイン実行 でもエラーが発生していることもあり、
イベント処理中に他のイベントが邪魔をしている、のではなく、
イベント終了時の処理 のどこかに**【エラー発生の原因】**が
ひそんでいるのではないか、と疑っております。
(【試したこと(5)】のステップイン実行でも、
End Sub 到達後の[F8 キー]押下により、エラーが発生しています)
(【追記:試したこと(7)】に続きます)

追記:試したこと(7)

クリックに間をおくとどうなるか、検証してみました。

・【 1 分 間隔 で Chart を クリック 】

クリック回数物理メモリの量
037,316 K
135,972 K
235,524 K
335,516 K
4(エラー発生)34,348 K

・【 2 分 間隔 で Chart を クリック 】

クリック回数物理メモリの量
032,672 K
135,240 K
234,320 K
334,292 K
434,364 K
535,308 K
6(エラー発生)33,344 K

クリック間に時間をおいても、エラーは発生しました。
また、メモリの方もよくわからない結果になってしまいました。
メモリ不足のエラーの割に、メモリはあまり関係なかったりするのでしょうか?

最後に

まとめると次のようになります。

同じ Chart を 連続的にクリックして、
【MouseDown イベント】や【BeforeDoubleClick イベント】で
特定のコードを実行し続けた場合、エラーが発生する。

【同じ Chart 】というのが、エラーが発生する原因のポイントではないか、と疑っているのですが…

情けない話ですが、私ではこれ以上どう検証していけばいいのか、皆目見当もつきません。

(検証にかけた時間の割に 分かったことが少なすぎて、泣きそうです)

エラー発生の原因について、情報いただけますと幸いです。
よろしくお願いします。

できないこと

わけあって、次の事項を行うことはできません。

・インストール
・管理者権限の必要な設定の閲覧・変更
・レジストリキーの値の変更
・Office アプリケーションの修復
・保護ビューの設定 の 変更(現在、3つの項目すべてに チェックがついている状態 です)

補足情報

Windows 10 Pro
メモリ:4.00 GB
Excel 2016 32bit(16.0.4966.1000)

ファイルサイズ 22 KB

Sheet1(Main)
空のChart(種類:2-D 集合縦棒, 名前:グラフ 1)

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

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

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

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

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

guest

回答1

0

原因究明に役立つか分かりませんが、取りあえずコメントします。
VBAはイベントドリブン(イベント駆動型)で、それらのイベントは時系列を保って制御されるわけではありません。

なので、イベント処理中に他のイベントが動作する事もあり得ます。
そうすると予期しない動作が発生します。

回避方法としては、
・グローバルなイベント実行中のフラグを準備し、イベント開始/終了でフラグのセット/リセット。
イベント処理内では、セット/リセットの前に判定し、実行中であれば処理しないようにする。
・処理実行後や処理前にDoeventsを実行しイベント処理の実行を促す。

等が考えられます。

投稿2020/05/01 07:54

sazi

総合スコア25184

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

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

vvvpp

2020/05/01 11:17

sazi 様、ご回答ありがとうございます。 大変 申し訳ございませんが、現在 1・2週間ほど検証ができない状況でして… 頂いた方法を検証でき次第、改めてまたご連絡いたします。
vvvpp

2020/05/12 11:45

ご報告が遅くなり、大変失礼いたしました。 頂いた方法に対する検証を行いましたので、質問文の方に追記いたしました。
sazi

2020/05/12 13:00

イベントがどのように実行されるかはご存じですか? 以下参考 【C#】マウスダウンとダブルクリックで処理を分ける https://zawapro.com/?p=1001
vvvpp

2020/05/12 13:54

マウスボタンを押す、サイズを変更する、といった、 ユーザーの行為をイベントとしてキャッチし、 それに対応したプログラムを実行する……といった認識です。 今回、その対応したプログラムについて記載してあるイベントは 【MouseDown イベント】のみのため、通常のクリック(ダブルクリックではない)で 検証した場合、頂いたURLでいうと、 ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー マウスボタンを一回クリックしたときのイベントは次のような順序で発生する。 1-1.MouseDown 1-2.Click 1-3.MouseClick 1-4.MouseUp また、マウスボタンをダブルクリックしたときは次のような順序でイベントが発生する。 2-1.MouseDown 2-2.Click 2-3.MouseClick 2-4.MouseUp 2-5.MouseDown 2-6.DoubleClick 2-7.MouseDoubleClick 2-8.MouseUp ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 【1-1.MouseDown】でのみ イベントがキャッチされ、プログラムが実行される。 ……でしょうか。申し訳ありませんが、ちょっと自信ないです……。 (浅学なため、分かり辛く曖昧な回答となってしまいました。申し訳ございません。  誤って認識している部分がありましたら、ご指摘いただけますと幸いです)
sazi

2020/05/12 14:13 編集

厄介なのは、発生したイベントの順番通りに制御が廻ってくるとは限らないところです。 イベントリスナーの機能が備わっていないものでは、イベント処理は極力組み込まない方が無難です。 例えば、「実行」ボタンで纏めて処理するようにするとか。 私自身も過去に懲りたので、イベント処理は極力作らないようにしています。
vvvpp

2020/05/12 14:29

なるほど……勉強になりました。 今度からは、そのようなイベント処理を組み込まなくてすむような設計をしていきます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問