- ベストアンサー
エクセルVBAのSetステートメントについて(長文)
Sub PlusA002() Dim myTgCell As Range Dim myCounter As Integer Set myTgCell = Range("E2") Do Until myTgCell.Value = Empty If myTgCell.Value >= 80 Then myTgCell.Offset(0, 1).Value = "優" ElseIf myTgCell.Value < 80 And myTgCell.Value > 50 Then myTgCell.Offset(0, 1).Value = "良" Else myTgCell.Offset(0, 1).Value = "追試" End If Set myTgCell = myTgCell.Offset(1, 0) Loop End Sub このプログラムを例にして、Setステートメントについて質問します。Set myTgCell = Range("E2")を削除して実行すれば実行エラーという文言がでるし、またSet myTgCell = myTgCell.Offset(1, 0)を削除すればエクセルが固まるし、Setがこのプログラムに対して必要なのは判ります。しかし、Setがどのような役割を果たしているのかVisualBasicEditorのヘルプを見ても判りません。 どのような場面で使えるものなのですか?どなたか教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 私も、ちょっと参加させてもらいます。 Set myTgCell = Range("E2") Rangeオブジェクト というのは、セルの位置情報など、もろもろを含めたオブジェクトなので、VBAでは、Set で、変数に渡してあげます。 そして、これは、最初のポイントですよね。Loop で条件を検索したら、次は、どうするのかって言ったら、次のセルに進むのですから、本来は、ActiveCell.Offset(1,0).Select なんですね。だけども、Range("E2")からみていくと、ひとつずつ、下に行くなら、単に、Offset で、+1 足せばよいわけです。 Do ~Loop は、Until 終了条件や、While ループ条件を立てます。 myTgCell.Offset(i, 0).Value = Empty (本来は、こういう書き方はよくありません) IsEmpty(myTgCell.Offset(i, 0)) の方がよいです。 サンプルコード Sub TestEmpty() If ActiveCell.Value = Empty Then MsgBox "ActiveCell.Value = Empty" If IsEmpty(ActiveCell) Then MsgBox "IsEmpty(ActiveCell)" If ActiveCell.Value = "" Then MsgBox "ActiveCell.Value =""""" End Sub 例えば、セルに「=""」と入れて、試してみると、IsEmpty(ActiveCell) 以外は、True を返していることが分ります。だから、本当に、Emptyではないことが分ります。 私の考えてみたサンプルコードです。 With ステートメントで、最適化を施しています。 '----------------------------------------- Sub PlusA002R() Dim myTgCell As Range Dim i As Long '最初のセルの設定 Set myTgCell = Range("E2") '画面の動きを押さえて、コードを速くする Application.ScreenUpdating = False 'Empty になったらループを離脱 Do Until IsEmpty(myTgCell.Offset(i, 0)) With myTgCell.Offset(i, 0) If .Value >= 80 Then .Offset(0, 1).Value = "優" ElseIf .Value < 80 And .Value > 50 Then .Offset(0, 1).Value = "良" Else .Offset(0, 1).Value = "追試" End If 'インクリメント i = i + 1 End With Loop '画面の動きを戻す Application.ScreenUpdating = True '設定を解除する。 Set myTgCell = Nothing End Sub '-----------------------------------------
その他の回答 (3)
- imogasi
- ベストアンサー率27% (4737/17070)
色々難しい理論はありますが ソースレベルで、文字列の置き換えをするのだと、要領的に覚えるのはどうでしょう。 Worksheets("Sheet1").Range("A1")と諸所に何度も書き表すかわりに、それを Set Sh1=Worksheets("Sheet1")として、その後は Sh1.Range("A1")と短く表現できるので、便利であるという風に。 質問の例では別名(Alias)をつけたような利用の仕方ですが、私の例では 包含関係・階層関係を含めてオブジェクトの階層構造が顔を出しています。 一段上に本当はワークブックの階層を前に付け加えるべきなのですが。Set Sh1=WorkBooks("aaa.xls").Worksheets("Sheet1") よく例えでいわれるように、東京都「の」渋谷区「の」南平台を「南平台」で表すことにしようと言ったようなことです。 定数に定数名、変数に変数名、オブジェクトにオブジェクト名をつける、 オブジェクトだけはSetが必須です。 DosのBasic以前では変数への値の代入は Let A=1とかく約束でしたね。 これはVBでも使えるようです。LetとSetが対を成しているのかな。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
Integer とか基本的な型以外の型(オブジェクト型?)の場合に 変数にオブジェクト(の参照)をセットする場合に使います。 Range型のような自体にさまざまなプロパティやメソッドを持っているようなものは、単純に代入ができない(それぞれを代入しないといけなくなる)ので、参照(それを見に行く)ように設定するというような感じ。
お礼
まだまだ未熟なもので、これから勉強が必要だという事を認識しました。回答有難うございました。
- hana-hana3
- ベストアンサー率31% (4940/15541)
>Set myTgCell = Range("E2") Range("E2") が myTgCell に変身したのです。 set 文以降は、myTgCell と記述すれば Range("E2") の事になります。 >Set myTgCell = Range("E2")を削除して実行 myTgCell が空になっているので、参照先が見つからないのでエラーになります。 >Set myTgCell = myTgCell.Offset(1, 0)を削除すればエクセルが固まるし これは、セルの内容を比較して任意の判定を記入したあと、この文で「myTgCell を一つ下のセルに変更」して「空欄」があるまで実行されていたものが、同じセルを参照し続ける事になったために「無限ループ」に陥っているためです。
お礼
回答有難うございました。
お礼
プログラムにも良くない書き方とかもあるんですね。しりませんでした。回答有難うございました。