エクセルのバグ「図が大きすぎます。入りきらない部分は切り捨てられます」エラー処理に関する小技


エクセルのVBAでソフト書いていたら「図が大きすぎます。入りきらない部分は切り捨てられます」と言うポップアップが急に出るようになりました。




ユーザーフォームを使ったほとんど同じ内容で2種類のVBAを作ったのですが「ユーザーフォーム画面を終了」→「エクセルを終了」しようとすると1個は何事もなく、もう1個はこの問題のポップアップが発生します。

ネットで調べるとどうも、クリップボードにデータが残っているのが原因のようです。私の書いたVBAで一度画像をコピーする動作をさせると出るみたいですが...

一般的なエクセルのエラー処理で対応できると思って試してみたけど、エラーではないので駄目でした。私が試したエラー処理は


①エラーが起きたらジャンプ

これは、一般的なエラー処理で元々はコマンドとして用意されているのでVBAの本などにも書かれています。

On Errorステートメントの「On Error GoTo」 と「On Error Resume Next」は、このステートメント以降でOn Error GoTo 」が出てくるか「プロシージャが終了」するまでがの有効範囲になります。

  On Error GoTo Err_Label
   . . . . . . .
   . . . . . . .
  Err_Label :

エラーが発生すると、Err_Labelの行ラベル位置へジャンプします。但し、On error go to ~は1回しか処理されないのでループで何回もエラーが発生する場合は使うことはできないようです。その場合は「On Error Resume Next」を利用します。

②エラーを無視

  On Error Resume Next
   . . . . . . .
   . . . . . . .

エラーが発生しても、エラーが発生したステートメントの次のステートメントから実行を継続します。



次に試したのが、コピーコマンドをキャンセルすることですが、これも駄目でした。

    Application.CutCopyMode = False


良く調べてみるとエクセルのマクロ処理ではデータの受け渡しはできますが、クリップボード自体は制御できない事がわかりました。




なので、エクセルのVBAではなくてVBA経由でWindowsのAPIを利用してクリップボートを制御する方法で対処する事にしました。

エクセルでAPIを利用する方法は以前、『エクセルで「数列」を自動演奏してみる』で試しています。


今回、問題となった動作はユーザーフォーム右上の「×」ボタンを動作させると発生するので「UserForm1」にマクロで以下のステートメントを挿入します。

APIを利用するので最初に宣言文を配置しておきます。以後にVBAのマクロでクリップボードを制御するコマンドを書くと自動的に認識して動作してくれます。


Private Declare Function apiOpenClipboard Lib "user32" Alias "OpenClipboard" (ByVal hwnd As Long) As Long
Private Declare Function apiEmptyClipboard Lib "user32" Alias "EmptyClipboard" () As Long
Private Declare Function apiCloseClipboard Lib "user32" Alias "CloseClipboard" () As Long

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)

    Call apiOpenClipboard(0&)
    Call apiEmptyClipboard
    Call apiCloseClipboard
'ユーザーフォームを閉じて通常のエクセル画面を立ち上げる
    Application.WindowState = xlNormal

End Sub


ネットでも書かれているようにバグに近い現象みたいなので、同じVBAでもエクセルのバージョンや設定によって発生したり、しなかったりするようです。安全のためにすべてに入れて挿入して対策してもいいのですが、なんか面倒ですね~~~