ほっとひといき給湯室

ほっとひといき給湯室の掲示板です。お気軽にどうぞ!
  • 掲示板への投稿には会員登録(無料)が必要です。会員登録がまだの方はこちら
  • 掲示板ご利用上のお願い」に反するご記入はご遠慮ください。
  • Q&A掲示板の使い方はこちらをご覧ください
トピックに返信
質問

 
Q&A掲示板の議論にひとこと
投稿日時: 18/01/04 20:44:26
投稿者: simple

Q&A掲示板の議論にひとこと
 
・Q&A掲示板の議論で言い残したことを補足したい、
・議論について自分はこう思う、自分ならこうするぞ
・よくわからなかったので詳しく教えて(こっそり)
・ともかく発言したい
という方は、どうぞふるって投稿願います。
 
「雑談スレだよ」だと本当に雑談したいひとの邪魔になるかもと思い、
こちらにスレッドを建てました。

投稿日時: 18/01/04 20:54:49
投稿者: simple

(昨年雑談スレッドに投稿した古い記事です。移動させておきます)
 
[入力規則の設定について ]
http://www.moug.net/faq/viewtopic.php?t=76593
ですけど、
A1形式とR1C1形式の参照設定の使い分けの話だと思ったのですが、
 少し違ったのかな。
  
書き忘れた論点がありました。
  
複数のセル範囲に同一種類の入力規則を設定する場合、
そもそも繰り返しをする必要はなくて、手作業で一括設定可能です。
 (マクロ記録をとればりっぱなマクロになります)
  
 [A1:D10]に対して入力規則を設定する場合を例にとると、
(1)R1C1参照形式にしている場合は
   "=LENB(RC)<=10"
    ですし、
(2)A1参照形式にしている場合も、
   "=LENB(A1)<=10"
    と指定すれば、他のセルも自動的に参照を調節してくれるはずです。
  
ですから、マクロにする必要すらない、
というのが実際のところかもしれません。
  
わざわざスレッドを建ててまで追いかける必要もないかと思っていますが、
 案外、盲点になっているかもしれませんね。
 

投稿日時: 18/01/06 08:51:26
投稿者: simple

シート指定を省略した場合の取扱について、下記に書きました。
http://www.moug.net/faq/viewtopic.php?t=76636
 
混乱してもいけないと思い、こちらに書きます。
下記のコードは、どんな結果をもたらすか予想できますか?

Sub test()
    Dim r As Range
    
    Sheet1.Select
    Set r = Range(Sheet2.Range("A1"), Sheet2.Range("B2"))
End Sub

 
RangeのシートはアクティブなシートであるSheet1 だから
例の論法で、エラーになるんじゃないか?と思いきや、
エラーにはなりません。
 
というのは、このRangeは ApplicationオブジェクトのRangeプロパティであり、
ワークシートの指定を要しません。
 
ですから、上記のような指定もExcelVBAの仕様の範囲内ではあるわけです。
 
しかし、通常こういう書き方は余り見ません。
それは、シート指定の無いRangeは(特に複数シートを相手にする場合は特に)
避けられるという実務的観点からでしょう。
つまり、「Rangeの前のシートは省略するな」という教育的配慮を優先しているものと
理解しています。
 
ご参考まで。
 
# 反応が無いので、質問型をやめて提案型に書き直しました。

回答
投稿日時: 18/01/07 00:17:13
投稿者: LMK

こんばんは
 

Sub test()
    Dim r As Range
    
    Sheet1.Select
    Set r = Range(Sheet2.Range("A1"), Sheet2.Range("B2"))
End Sub

 
ところで、この同じコードを Sheet1 のシートモジュールに書いたらエラーになりますね。
 
シートを省略した場合の解釈が、
 
 標準モジュール⇒ アクティブなシート
 シートモジュール⇒ 当該シート
 
となると同時に、
 
 標準モジュール⇒ 「原則」アクティブなシートと解釈
 シートモジュール⇒ 「必ず」当該シートと解釈
 
とでも言えばいいんでしょうか、解釈の厳密性に差があるように見えます。

投稿日時: 18/01/07 08:37:19
投稿者: simple

なるほど、そういうことかもしれませんね。ありがとうございます。
 
シート指定を二重に求めるとは何事か陣営ww の人たちからすると、
こんな書き方をすると、エラー回避できるかもしれませんね。
 

Sub シートモジュールsample()
    Dim r As Range
    
    Sheet1.Select
    Set r = Excel.Range(Sheet2.Range("A1"), Sheet2.Range("B2"))
End Sub
Applicationでもよいけど長いので。

回答
投稿日時: 18/01/07 12:56:13
投稿者: LMK

もちろん実務的には、
 1.それなりの理由がなければわざわざシートモジュールに書かない
 2.With で参照をまとめることもできる
わけですが。
 
 

Sub test()
    Dim r As Range
    Set r = Sheet2.Range("範囲")
End Sub

似たような「シートモジュールの寛容度が低い」問題ですが、上は Sheet1 のシートモジュールに書かれたコードです。
他シートのセル範囲を名前で参照する場合も、シート指定がないとエラーになりますね。
名前のスコープが「ブック」なんだからそこは適宜解釈してほしい、と言いたくなるところです。

回答
投稿日時: 18/01/07 14:36:45
投稿者: LMK

なるほど、Excel.Range または Application.Range と書けば、あたかも標準モジュールに書いたかのようにエラー回避できるわけですね。
 

Sub testExcel()
    Dim r As Range
    Set r = Excel.Range("範囲")
End Sub

 
次は Sheet2 のモジュールに書く例です。
最初の例はあたかも標準モジュールに書いたかのようにアクティブなシートの範囲が取得されますが、
2番目の例ではモジュールの既定値が優先され、Sheet2 の範囲が取得されますね。
勉強になります。
 
Sub Sheet2モジュールに書くサンプル1()
    Dim r As Range
    
    Sheet1.Select
    With Application
        Set r = .Range(.Range("A1"), .Range("B2"))
    End With
    MsgBox r.Address(External:=True) '⇒ Sheet1(アクティブなシート)の範囲が返る
End Sub

 
Sub Sheet2モジュールに書くサンプル2()
    Dim r As Range
    
    Sheet1.Select
    With Application
        Set r = .Range(Range("A1"), Range("B2"))
    End With
    MsgBox r.Address(External:=True) '⇒ Sheet2(モジュールの既定値)の範囲が返る
End Sub

投稿日時: 18/01/07 23:12:29
投稿者: simple

貴重な材料の提供、ご指摘、ありがとうございます。
 
余談です:
Excel.Rangeや Application.Rangeなどの使い方は、
将棋の格言にある「敵の打ちたいところに打て」というのを想起させますねえ。

回答
投稿日時: 18/01/12 15:38:32
投稿者: mattuwan44

Sub Sheet2モジュールに書くサンプル3()
    Dim r As Range
    
    Sheet1.Select
    With Me
        Set r = Application.Range(.Range("A1"), .Range("B2"))
    End With
    MsgBox r.Address(External:=True)
End Sub

 
Meでちゃんとどのシートの話か明示したいかな。。。

回答
投稿日時: 18/01/15 02:47:10
投稿者: baoo

う〜ん。
私の場合、自分のコードではブックも省略しないですね。
サンプル提示では省略したりしますけど。
それでWithを使うかSet sht=Workbooks("hoge").Worksheets("fuga")を
よく使います。

投稿日時: 18/01/16 23:05:57
投稿者: simple

baooさんの疑念はもっともで、こうした書法を推奨しているのではないんですね。
 
18/01/06 08:51:26 で私が持ち出した議論は、
Range(Cells(1,1),Cells(2,3))
で普通はRangeにもCellsにもシート指定をつけることが推奨されています。
Rangeのシートだけ特定しても、Cellsは(標準モジュールだからアクティブシートが前提となるので、
アクティブシートとRangeで指定したシートが異なる時はエラーになります。
というよく知られた、間違い易いポイントに関する前提があって、
では、標準モジュールで、

    Sheet1.Select
    Set r = Range(Sheet2.Range("A1"), Sheet2.Range("B2"))
などとしたとき、必ずRangeにもアクティブシートが補足されて、
エラーになると思うでしょう?上の理屈からすると。
でもそうでもないんですね、という注意喚起をしたかっただけなんですね。
昔こちらの掲示板であった議論を想い出して、知ったかぶりをしたということです。
(ですから、本体の議論ではたぶん閲覧者が混乱するだろうと考えて遠慮しておりました。)
 
そこでも書きましたように、どちらのシート指定もすることが可読性にもすぐれているので、
それを推奨します。(しかし、仕様として上記のような考え方も許容されているようですね、
ということを申し上げたかったのです)
 
混乱を招いたですかね。

トピックに返信