Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


953 / 13645 ツリー ←次へ | 前へ→

【77316】実行時エラー91について ぴょん 15/7/5(日) 17:27 質問[未読]
【77317】Re:実行時エラー91について β 15/7/5(日) 18:03 発言[未読]
【77318】Re:実行時エラー91について β 15/7/5(日) 19:26 発言[未読]
【77319】Re:実行時エラー91について ichinose 15/7/5(日) 19:51 発言[未読]
【77321】Re:実行時エラー91について ぴょん 15/7/5(日) 22:29 発言[未読]
【77325】Re:実行時エラー91について ichinose 15/7/5(日) 23:18 発言[未読]
【77320】Re:実行時エラー91について β 15/7/5(日) 20:56 発言[未読]
【77322】Re:実行時エラー91について ichinose 15/7/5(日) 22:31 発言[未読]
【77323】Re:実行時エラー91について ぴょん 15/7/5(日) 22:34 発言[未読]
【77324】Re:実行時エラー91について β 15/7/5(日) 23:18 発言[未読]
【77326】Re:実行時エラー91について β 15/7/5(日) 23:26 発言[未読]
【77327】Re:実行時エラー91について ぴょん 15/7/6(月) 20:29 質問[未読]

【77316】実行時エラー91について
質問  ぴょん  - 15/7/5(日) 17:27 -

引用なし
パスワード
   ”実行時エラー:91 オブジェクト変数またはWithブロック変数が設定されていません”が出る時があります。

・オブジェクト型変数はプロジェクト内で共通参照できるように、Publicで宣言。
ブックオープン時に1回だけSetを実施。
・ワークシート2に2つあるボタン(チェックボックスの作成、削除)を、交互に動かすと早い時は1往復くらいで、たまに3往復目くらいまで行く時がありますが上記エラーになってしまいます。
(エラーが発生する回数、エラーが発生する場所とも不特定。場所はいずれもWsを参照している箇所ですが、複数個所あります)

何か解放漏れとかですか?

ちなみに、Workbook_BeforeClose時に、Set Wb = Nothing、Set Ws1 = Nothing、Set Ws2 = Nothingはしてます。

力不足のため、ご教授のほどよろしくお願いします。

■標準モジュール
Public Wb As Workbook       'ワークブック
Public Ws1 As Worksheet       'ワークシート
Public Ws2 As Worksheet       'ワークシート

■ワークブックプロシージャ
Private Sub Workbook_Open()

  Set Wb = Workbooks("Book.xlsm")
  Set Ws1 = Wb.Worksheets("Sheet1")
  Set Ws2 = Wb.Worksheets("Sheet2")

  Ws1.Cells(1, 1).Value
  Ws2.Cells(1, 1).Value

End Sub

■ワークシート2
Private Sub チェックボックス作成_Click()
  For CheckBoxIndex = 1 To XX
    
    'チェックボックスを作成する
    With Ws2.OLEObjects.Add(ClassType:="Forms.CheckBox.1", Link:=False, DisplayAsIcon:=False)
      .Object.Caption = Ws2.Cells(省略)
      以下省略
    End With
    
  Next CheckBoxIndex

End Sub

Private Sub チェックボックス削除_Click()

  For Each tCtrl In Ws2.Shapes
    
    If Left(tCtrl.Name, 8) = "CheckBox" Then
      Ws2.Shapes(tCtrl.Name).Delete
    End If
  
  Next

End Sub

【77317】Re:実行時エラー91について
発言  β  - 15/7/5(日) 18:03 -

引用なし
パスワード
   ▼ぴょん さん:

だめもとで、

>    With Ws2.OLEObjects.Add(ClassType:="Forms.CheckBox.1", Link:=False, DisplayAsIcon:=False)

この後に、DoEvents をいれてみてください。
何往復かして、確かめていただけませんか。

【77318】Re:実行時エラー91について
発言  β  - 15/7/5(日) 19:26 -

引用なし
パスワード
   ▼ぴょん さん:

あぁ、エラーの場所は、様々なところで特定はされていないんですね。
じゃぁ、↑のDoEvents 手当ては無意味ですので無視してください。

ウォッチ式をいれて監視してみましょうか。

・標準モジュールのws1をマウスでクリック
・デバッグ->ウォッチ式の追加
・式を ws1 Is Nothing 、ウォッチの種類を 式がTrueの時に中断
・プロシジャを すべてのプロシジャ、モジュールも すべてのモジュール
・OKボタン

ws2 についても同様。

これで、実行中、ws1やws2が Nothing になった瞬間に、その次のコードでとまるはずです。

【77319】Re:実行時エラー91について
発言  ichinose  - 15/7/5(日) 19:51 -

引用なし
パスワード
   ▼ぴょん さん:
>”実行時エラー:91 オブジェクト変数またはWithブロック変数が設定されていません”が出る時があります。
>
>・オブジェクト型変数はプロジェクト内で共通参照できるように、Publicで宣言。
>ブックオープン時に1回だけSetを実施。
変数が初期化される現象

www.vbalab.sakura.ne.jp/vbaqa/c-board.cgi?cmd=one;no=7011;id=excel

私も以前、経験しました。

原因はこれと同じだと思います。

モジュールレベルの変数は、十分注意が必要です。

今回の場合なら、

Function Wb() as workbook
  set wb=Workbooks("Book.xlsm")
end function

辺りで回避はできますが、Workbooks("Book.xlsm")でもいいのでは と思います。


それから、問題とは直接関係ないですが、Public変数を標準モジュールにおくのは、
なるべく止めた方がよいです。
というか そうしない習慣を付けた方がよいですよ

【77320】Re:実行時エラー91について
発言  β  - 15/7/5(日) 20:56 -

引用なし
パスワード
   ▼ぴょん さん:

報告だけです。

ichinoseさんのご指摘通り、私もモジュールレベル変数については、いつも、おっかなびっくりで
どきどきしながら使っています。
プロジェクトリセット時の値の消滅というより、プログラム構成としての堅牢性も気になりますので。

でも、使った方が楽ということもありますので、ケースバイケース。

こちらの xl2010,xl2013 で、ボタンクリックを、5回ずつ実行。
1回あたり100個のチェックボックスを生成していて、だんだん遅くはなるんですが
エラーにはならず、それぞれ、500個のチェックボックスが作られました。


Private Sub Workbook_Open()
  Set Wb = Workbooks("Book.xlsm")
  Set Ws1 = Wb.Worksheets("Sheet1")
  Set Ws2 = Wb.Worksheets("Sheet2")
End Sub

Private Sub CommandButton1_Click()
  Dim x As Long
  Dim xx As Long
  
  xx = 100
  
  For x = 1 To xx
  
     'チェックボックスを作成する
    With Ws2.OLEObjects.Add(ClassType:="Forms.CheckBox.1", Link:=False, DisplayAsIcon:=False)
     End With
  
   Next x

End Sub

■標準モジュール
Public Wb As Workbook       'ワークブック
Public Ws1 As Worksheet       'ワークシート
Public Ws2 As Worksheet       'ワークシート

【77321】Re:実行時エラー91について
発言  ぴょん  - 15/7/5(日) 22:29 -

引用なし
パスワード
   ▼ichinose さん:
返信ありがとうございます。

下記は、標準モジュールに記述して、保存しようとすると”名前が適切ではありません WB”とコンパイルエラーになってしまいます。
未熟なものですいませんが、よろしくお願いします。

>Function Wb() as workbook
>  set wb=Workbooks("Book.xlsm")
> end function

【77322】Re:実行時エラー91について
発言  ichinose  - 15/7/5(日) 22:31 -

引用なし
パスワード
   >でも、使った方が楽ということもありますので、ケースバイケース。
モジュールレベルの変数を否定している訳ではありません。
そんなこと言ったらクラスを否定しなければなりません。

標準モジュールのPublic変数を作らないほうが良い と言っています。


>
>こちらの xl2010,xl2013 で、ボタンクリックを、5回ずつ実行。
>1回あたり100個のチェックボックスを生成していて、だんだん遅くはなるんですが
>エラーにはならず、それぞれ、500個のチェックボックスが作られました。
>
これに関しては、私の認識不足がありました。作成するActiveXControlが
アクティブシートでなければ、変数が初期化されませんでした。


こんな手順で初期化が再現されました。


新規ブック(Sheet1 Sheet2 というシートが存在する)にて、
Sheet1にActiveXControlのコマンドボタンを二つ配置してください。
(CommandButton1 CommandButton2)。

標準モジュールに 私が否定しているPublic変数の宣言

Option Explicit
Public Wb As Workbook        'ワークブック
Public Ws1 As Worksheet       'ワークシート
Public Ws2 As Worksheet       'ワークシート


ThisworkBookのモジュールに

Option Explicit
Private Sub Workbook_Open()
  Set Wb = Me
  Set Ws1 = Wb.Worksheets("Sheet1")
  Set Ws2 = Wb.Worksheets("Sheet2")
End Sub


Sheet1のモジュールに


Option Explicit
Private Sub CommandButton1_Click()
  Dim x As Long
  Dim xx As Long
  xx = 5
  For x = 1 To xx
     'チェックボックスを作成する
    With Ws2.OLEObjects.Add(ClassType:="Forms.CheckBox.1", Link:=False, DisplayAsIcon:=False)
     End With
   Next x
End Sub
Private Sub CommandButton2_Click()
  Dim tctrl As Object
  For Each tctrl In Ws2.Shapes
    If Left(tctrl.Name, 8) = "CheckBox" Then
      Ws2.Shapes(tctrl.Name).Delete
    End If
  Next
End Sub

と殆ど ぴょんさんが提示されたコードと同じですが、同期がとれるように
再度、記述しておきます。

Sheet2のシートをアクティブにして セルA1を選択してください。
Sheet1のシートをアクティブにしてください。

これを 適当な場所に 変数初期化1.xlsm という名前で保存してください。


一度、このブックを閉じたのち、再度開いてください。


1 Commandbutton2をクリックしてください。
2 Commandbutton1をクリックしてください。
  Sheet2にチェックボックスが作成されます。

3 Sheet2をアクティブにしてください。
4 チェックボックスが作成されている事を確認し、この状態で上書き保存を行ってください。

5 保存後に Sheet1をアクティブにしてください。

この1〜5を繰り返してください。何度目かの2で
実行時エラー:91 オブジェクト変数またはWithブロック変数が設定されていません

が発生しました(殆ど2回目の2で発生します)。

【77323】Re:実行時エラー91について
発言  ぴょん  - 15/7/5(日) 22:34 -

引用なし
パスワード
   ▼β さん:

毎度、コメントありがとうございます。
下記βさんのコーディングと私のやつと違いがありますか?
ちなみに、EXCELは私も2010です。
試行錯誤してるんですが、なかなか難しくて(^^;

【77324】Re:実行時エラー91について
発言  β  - 15/7/5(日) 23:18 -

引用なし
パスワード
   ▼ぴょん さん:

>下記βさんのコーディングと私のやつと違いがありますか?
>ちなみに、EXCELは私も2010です。

同じです。

おそらく ichinoseさんが指摘される状況になっているんだと思うのですが
一方、同じ xl2010の、こちらでは少々のことなら(?)耐えられている???

ichinoseさんが紹介された議論は、かなり古いバージョンのエクセルのもとでの現象なので
今は、そういうこともないのかもしれません。

なので、もしかしたらアップされたコード以外のところの別の原因かもしれないということで
ウォッチ式の設定でのチェックを提案しました。

ところで、"Book.xlsm" は別ブックですか?
それとも、このマクロが書かれたブックですか?

私のテストは、別ブックとして実行しています。

【77325】Re:実行時エラー91について
発言  ichinose  - 15/7/5(日) 23:18 -

引用なし
パスワード
   ▼ぴょん さん:
>▼ichinose さん:
>返信ありがとうございます。
>
>下記は、標準モジュールに記述して、保存しようとすると”名前が適切ではありません WB”とコンパイルエラーになってしまいます。
>未熟なものですいませんが、よろしくお願いします。
>
>>Function Wb() as workbook
>>  set wb=Workbooks("Book.xlsm")
>> end function
Public変数は、消すんですよ そうしないと名前が重複してしまいます。

【77326】Re:実行時エラー91について
発言  β  - 15/7/5(日) 23:26 -

引用なし
パスワード
   ▼ぴょん さん:

あぁ、今、Book.xlsm を自ブック(このマクロブック)にして実行しましたら
一発でエラーになりました。

やはり、ichinoseさんが回答された通りですね。
紹介されたトピの中に、「自ブックに対する」OLEOBJECT の生成は、
プロジェクトのリセットのような状況、つまり、モジュールレベルの変数も
初期化されるという説明がありましたね。

回避方法としては、ichinoseさんが言われるように、Ws1 や Ws2 をファンクションプロシジャにする。
それが、コード修正を見にミニマイズする手立てだと思います。

【77327】Re:実行時エラー91について
質問  ぴょん  - 15/7/6(月) 20:29 -

引用なし
パスワード
   βさん、ichinoseさん色々ご指導ありがとうございました。

結論としまして、Public変数は使用せず、チェックボックスの作成と削除の各プロシージャでDim Ws As WorksheetとSet Ws = Wb.Worksheets("sheet1")するようにしました。
これだと10回以上チェックボックスの作成と削除を繰り返しても正しく動きました。

お二方とも本当にありがとうございました。

953 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free