Excel (VBA)

Excel VBAに関するフォーラムです。
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
(指定なし : 指定なし)
setに関する疑問
投稿日時: 17/08/13 09:24:21
投稿者: hisayanxp

よろしくお願いします。
前回「記述の簡素化」のトピックで質問した際に、以下の記述を教えていただきました。
Sub Trace6()
    Dim cel As Range
    Dim i As Long, n As Long
        Set cel = Cells(10, 2)
    cel.Interior.Color = vbRed
        For i = 9 To 2 Step -1
        Application.Wait Now + TimeValue("0:0:01")
        cel.ClearFormats
        Set cel = Cells(i, 2)
        cel.Interior.Color = vbRed
    Next i
        For n = 3 To 4
        Application.Wait Now + TimeValue("0:0:01")
        cel.ClearFormats
        Set cel = Cells(2, n)
        Cells(2, n).Interior.Color = vbRed
    Next n
End Sub
 
<疑問点>
最初にオブジェクト変数として cel を Cells(10,2)を定義しているのに、以降の記述では
Set cel = Cells(i, 2)
Set cel = Cells(2, n)
のように変えてあります。
これはRangeオブジェクトにおいては許されているのでしょうか?
またCells(i,n)のようにして上記と同じ内容の記述ができるでしょうか?
 
よろしくお願いします。

回答
投稿日時: 17/08/13 09:51:57
投稿者: WinArrow
投稿者のウェブサイトに移動

hisayanxp さんの引用:

<疑問点>
最初にオブジェクト変数として cel を Cells(10,2)を定義しているのに、以降の記述では
Set cel = Cells(i, 2)
Set cel = Cells(2, n)
のように変えてあります。
これはRangeオブジェクトにおいては許されているのでしょうか?

文法的には問題ありません。
あくまでもご自身の使い方の問題です。
 
 
hisayanxp さんの引用:

またCells(i,n)のようにして上記と同じ内容の記述ができるでしょうか?

 
この意味は理解できません。
どのようなことを想定しているのでしょう?

回答
投稿日時: 17/08/13 09:57:14
投稿者: WinArrow
投稿者のウェブサイトに移動

追加レス
>最初にオブジェクト変数として cel を Cells(10,2)を定義しているのに
この認識は、ちと、違うんではないかな?
 
オブジェクト変数として cel を定義は
 
Dim cel As Range
 
の個所です。
 
>Set cel = Cells(10,2)
は、定義ではなく、代入です。

回答
投稿日時: 17/08/13 10:00:25
投稿者: WinArrow
投稿者のウェブサイトに移動

>またCells(i,n)のようにして上記と同じ内容の記述ができるでしょうか?
 
意味が分かりました。
 
戸お場合、2重ループすることになります。
 
For i = 9 To 2 Step -1
    For n = 3 To 4
       Set cel = Cells(i n)
 
    Next n
Next i
 
というような具合です。

回答
投稿日時: 17/08/13 10:20:41
投稿者: simple

補足です。
 
変数を巡っては、mutable(変更可能)、immutable(変更不能)と言う考え方があります。
変数の指す内容を変更しうるかどうかという話です。
ある種の言語では、変数はimmutable(変更不能)に限定するものもあります。
"mutable immutable"などとネットで検索してみてください。
  
VBAはすべての変数がmutableです。(定数がimmutableに相当するのだろうか)
ですからこの場合問題はありません。

回答
投稿日時: 17/08/13 11:00:03
投稿者: mattuwan44

>これはRangeオブジェクトにおいては許されているのでしょうか?
Rangeオブジェクトに限った話しではありません。
「変数」の普通の使い方だと思います。
 
今回の場合は、
色を新たに塗るときに、
「前に処理したセル」を覚えておきたいために、
変数に仮に記録しているだけですよね?
 
そして、処理が終わったら、次に覚えておくセルを記録しなおす。
それを繰り返しているだけですね^^

投稿日時: 17/08/13 11:58:49
投稿者: hisayanxp

WinArrowさん、simpleさん、matuwan44さん
ありがとうございました。納得しました。
教えていただいた中の式を作って下記の記述をしてみましたが、「アプリケーション定義またはオブジェクト定義のエラーです」とでます。
どこに問題があるのでしょうか?
 
Sub trace7()
Dim n, i As Long
Dim cell As Range
    Set cel = Cells(i, n)
    For i = 9 To 2 Step -1
    For n = 3 To 4
 cell.Interior.Color = vbRed
    Application.Wait Now + TimeValue("00:00:01")
 cel.ClearFormats
    Next n
    Next i
End Sub
 
よろしくお願いします。

回答
投稿日時: 17/08/13 12:40:04
投稿者: simple

参考までに
>これはRangeオブジェクトにおいては許されているのでしょうか?
と考えるに至った経緯を教えてもらえませんか?
 
変数を箱のように考えているところからきているのでしょうか?
今後、色々な方に回答をしていく上で、理由について大変興味があります。
是非教えて下さい。
 
-------------------------------------
さて、今回の件。
以前のスレッド
http://www.moug.net/faq/viewtopic.php?t=75616
で、
> それと、実行時エラーになっているわけですが、これまでのトピで
> 指摘されていた Option Explicit 記述、まだ、やっていないんですね?
とありますが、前に戻ってしまっていませんか?
 

私の回答用テンプレート さんの引用:
Option Explicit
をモジュールの一行目に挿入するようにして下さい。
そうすれば、今回のような未宣言の変数には警告が出て、
しかも場所を特定してくれますから、原因が直ぐに判明します。
 
http://officetanaka.net/excel/vba/beginner/06.htm
 
なお、
ツール − オプション − 編集 で
「変数の宣言を強制する」にチェックを入れておけば、
モジュールを作成した時点で、Option Explicitが自動的に挿入されるので、
手間が省けます。
一度だけチェックを入れておけば、以後、気にする必要はありません。

 
それとインデントをしっかりつけるようにしてください。
これは読んでいるひとの便宜ではなく、あなたにとって益があるのです

回答
投稿日時: 17/08/13 14:31:28
投稿者: WinArrow
投稿者のウェブサイトに移動

エラーの原因は
> Set cel = Cells(i, n)
の記述場所が間違っています。
 
For 〜 Next のループの中に入れなくちゃ
 
デバッグには、ステップ実行を使いましょう。
 
何度も言われないように、
回答者からのアドバイスをキチンと受け入れましょうね・・・

回答
投稿日時: 17/08/13 15:28:12
投稿者: simple

私の最初の質問は後回しで結構です。
 
で、手を入れると、こうなりますね。

Sub trace7()
    Dim n, i As Long
    Dim cell As Range
    
    Set cell = Cells(i, n)      '    (1)
    For i = 9 To 2 Step -1
        For n = 3 To 4
            cell.Interior.Color = vbRed
            Application.Wait Now + TimeValue("00:00:01")
            cell.ClearFormats
        Next n
    Next i
End Sub

まず、(1)のところで i,n はどうなっていますか?
本当は、 Dim n As Long, i As Long と書くべきです。
今のままだと n は Variant型ですから。
0 でも Emptyでもおなじですが、セル位置の指定としては不適切です。
だから、エラーになります。
 
(1) で Set cell = Cells(i, n)としておいても、
iやnが変わったら自動的に内容が変わるわけではありません。
きちんと
For i
   For n
       
  Next
Next
のループのなかで更新しなければいけません。
 
以上のことを念頭において修正してください。
# かぶりましたが、そのまま上げます。

投稿日時: 17/08/14 08:56:28
投稿者: hisayanxp

WinArrowさん、simpleさんmありがとうございます。
simpleさんへ
「Rangeオブジェクトにおいては許されているのでしょうか?」は自分で改めて読み直して全くトンチンカンでした。Option Explicitの設定はしてあるのに消していました。私のミスです。
 
WinArrowさん、次のように修正してF8でステップイン実行すると
Application.Wait Now + TimeValue("00:00:01")の行で止まります。
どうしてこういう結果になるのかが分かりません。
 
Sub trace7()
 
   Dim n As Long, i As Long
   Dim cell As Range
       
   For i = 9 To 2 Step -1
      For n = 3 To 4
        Set cel = Cells(i, n)
        cell.Interior.Color = vbRed
        Application.Wait Now + TimeValue("00:00:01")
        cel.ClearFormats
      Next n
   Next i
End Sub
 
 
 
 

回答
投稿日時: 17/08/14 09:23:48
投稿者: WinArrow
投稿者のウェブサイトに移動

引用:

Application.Wait Now + TimeValue("00:00:01")の行で止まります。
どうしてこういう結果になるのかが分かりません。

 
>止まります。
って、
どのような状態ですか?
 
ところで、ここで Wait する必要があるんですか?
セルの個数が、60個あると、1分間も処理時間が余計にかかってしまいます。

回答
投稿日時: 17/08/14 10:02:28
投稿者: MMYS

Sub trace7()
  
   Dim n As Long, i As Long
   Dim cell As Range
        
   For i = 9 To 2 Step -1
      For n = 3 To 4
        Set cel = Cells(i, n)
        cell.Interior.Color = vbRed
        Application.Wait Now + TimeValue("00:00:01")
        cel.ClearFormats
      Next n
   Next i
End Sub
 
ステップ実行は可能ですと書かれてますけど。エラーで実行不可能ですけど。
変数は、1文字でも違えば別物です。
cell はSetされていため値はNothingです。なので
cell.Interior.Color = vbRed はエラーです。
 
Option Explicitの認識をhisayanxpさんの言葉で説明してもらえますか。
 
 

WinArrow さんの引用:

ところで、ここで Wait する必要があるんですか?

このコード、C9〜D2までアニメーションさせるコードです。
ウエイトは必要でしょう。
 
 

回答
投稿日時: 17/08/14 18:47:09
投稿者: mattuwan44

>Set cell = Cells(i, n) ' (1)
 
↑これでオブジェクトを指定したら、
変数「i」と変数「n」の値を変えるだけで、
オブジェクト変数「Cell」の中身まで変わるわけではないですね。
 
変数「i」や変数「n」と同様に、
オブジェクト変数「Cell」にもその都度都度で、
対象のセルを代入してやる必要があります。
なんでそんなことをするのかは、メンテナンス性を重視した書き方です。
今の例題では、その有難さ(オブジェクト変数を使うありがたさ)が、実感できないと思いますので、
この例題でそこを突き詰めても理解ができないかと思いますので、
 
Sub test()
    Dim n As Long
    Dim i As Long
 
    For i = 9 To 2 Step -1
        For n = 3 To 4
            Cells(i, n).Interior.Color = vbRed
            Application.Wait Now + TimeValue("00:00:01")
            Cells(i, n).Interior.colorindex=xlnone
        Next
    Next
End Sub
 
この程度でわかりやすければそれでいいと思います。
も少し複雑な処理の流れになったり、半年後にメンテナンスの必要が出てきたときに実感したら、
その時に、改めて質問したらいいと思います。

投稿日時: 17/08/14 22:09:21
投稿者: hisayanxp

皆さん、ありがとうございます。
 
MMYSさん
Celは不注意でした。
Option Explicitは宣言されている変数以外はエラーを表示させるという風に考えています。
 
matuwan44さん
教えていただいた記述で納得しました。
ただ当初の動きと違うのが自分の中では釈然としませんでした。
 
WinArrowさん
Waitを入れたのは選択されてるセルが次々に移動するのを見せるようにしたかったからです。
 

回答
投稿日時: 17/08/15 07:49:26
投稿者: mattuwan44

>ただ当初の動きと違うのが自分の中では釈然としませんでした。
あぁ、そか。
 
作業の流れが違いますもんね。
こういうのは、書いててややこしいので、
ステップ実行とかしながら、変数の中身の増減が、
意図通りになっているか確認していかないと、
思い通りに動かないですね。
 
ループを2重にしたら、
縦と横と一度に変化するから、
分けないとだめですね。
で、色付けする部分は共通なので、
下請けに「お願い」って任す感じで別のプロシージャに分けて、
必要な時に呼び出します。
 
Sub test()
    Dim n As Long
    Dim i As Long
 
    '縦方向の移動
    n = 3
    For i = 9 To 2 Step -1
        色付け i, n
    Next
     
    '横方向の移動
    i = 2
    For n = 3 To 4
        色付け i, n
    Next
End Sub
 
Sub 色付け(ByVal ixRow As Long, ByVal ixCol As Long)
    Cells(i, n).Interior.Color = vbRed
    Application.Wait Now + TimeValue("00:00:01")
    Cells(i, n).Interior.ColorIndex = xlNone
End Sub

回答
投稿日時: 17/08/15 10:15:09
投稿者: MMYS

hisayanxp さんの引用:

Option Explicitは宣言されている変数以外はエラーを表示させるという風に考えています。

解釈はあっています。ただし、なぜそれが必要なのでしょう。
 
単純な打ち間違いはよくあることです。しかも、本人は気づかないのです。
で、どうして動かないのかと悩む。
 
単純ミスはシステムが指摘してくれるのだから活用しましょう。
 

投稿日時: 17/08/18 15:48:26
投稿者: hisayanxp

matuwan44さん
ありがとうございました。For Iの二重ループでセルがジグザグに進む理屈は理解できましたが、もうひとつの以下の記述は現時点では理解できませんでした。まだこの記述は正直なところ荷が重いです。
 
Sub test()
     Dim n As Long
     Dim i As Long
   
     '縦方向の移動
    n = 3
     For i = 9 To 2 Step -1
         色付け i, n
     Next
       
     '横方向の移動
    i = 2
     For n = 3 To 4
         色付け i, n
     Next
 End Sub
   
 Sub 色付け(ByVal ixRow As Long, ByVal ixCol As Long)
     Cells(i, n).Interior.Color = vbRed
     Application.Wait Now + TimeValue("00:00:01")
     Cells(i, n).Interior.ColorIndex = xlNone
 End Sub
 
MMYSさん
ありがとうございました。
Option Explicitとして宣言していない変数は使用不可にしておけば、ミスにすぐ気づくからではないかと思います。

回答
投稿日時: 17/08/18 16:21:04
投稿者: simple

荷が重いとのことですが、
Subプロシージャーとか、Functionプロシージャーといった文法事項について。
どの程度学習されていますか?
ExcelVBAのテキストはお持ちですよね。
 
なお、
確認ですが、
ツール − オプション − 編集 で
「変数の宣言を強制する」にチェック
は実行してもらいましたか?
 
以前にもこの件を申し上げたと思いますが、
どうも実行してもらっていないので、
今回のようなことになりました。
生涯に一度実行するだけで効果があるんですけども。
 
きちんと実行した、と明言してもらうと有り難い。

トピックに返信