[[20170718221341]] 『パブリックでのワークシートのSet』(ろでっち) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『パブリックでのワークシートのSet』(ろでっち)

パブリックで変数を設定すると、モジュール内で共用の変数で使えるのは知っています。
なので、これと同じことを、ワークシートでもやりたいと思っています。

Public ws1 as Worksheets

      set ws1 = WorkSheets("A")

これができませんでした。

これをするにはどのようにすればよろしいでしょうか?

ご教授のほどをよろしくお願いいたします。

< 使用 Excel:Excel2010、使用 OS:Windows7 >


 Public ws1 as Worksheets 
 だとワークシートの集まりにならないか?

 Public ws1 as Worksheet
 ではどうか。

(ねむねむ) 2017/07/18(火) 22:32


すいません、端末が前になかったので、単なる書き間違えでした(申し訳ありません)。

例文・・・というかほぼそのままです。
Public ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet, ws4 As Worksheet

    Set ws1 = Worksheet("A")
    Set ws2 = Worksheet("B")
    Set ws3 = Worksheet("C")
    Set ws4 = Worksheet("D")

Option Explicit

Sub Size()

    If ws1.Range("A1") = "小" Then
        Call Mini()
    ElseIf ws1.Range("A1") = "中" Then
        Call Midle()
    ElseIf ws1.Range("A1") = "大" Then
        Call Big()
    Else
        MsgBox "サイズ欄に「大」「中」「小」のいずれかを入力してください", vbCritical
        Exit Sub
    End If

End Sub

Sub Mini()

    Msgbox WS2.name & "です"
End sub

Sub Middle()

    Msgbox WS3.name & "です"
End sub

Sub Big()

    Msgbox WS4.name & "です"
End sub

すいません、よろしくお願いします。

(ろでっち) 2017/07/19(水) 10:07


 それを実行しようとすると
 Set ws1 = Worksheet("A")
 の部分で
 プロシージャの外では無効です。
 と出ないか?
 メッセージどおりの意味だが。
(ねむねむ) 2017/07/19(水) 10:11

 ステートメントはプロシージャ内でしか使えない。
 ThisWorkbookモジュールのWorkbook_Open()イベントにでも
 >Set ws1 = Worksheet("A")
 >Set ws2 = Worksheet("B")
 >Set ws3 = Worksheet("C")
 >Set ws4 = Worksheet("D")
 を移動させてくれ。
 あと、羹に懲りてなますを吹くになっているが
 Worksheet(〜)
 は
 Worksheets(〜)
 で。

(ねむねむ) 2017/07/19(水) 10:18


 ねむねむさん
 >ThisWorkbookモジュールのWorkbook_Open()イベントにでも
 とのことですが、こけた時に変数の値消えてしまうので、都度Setしたほうが、私は、よいと思います。

 ろでっちさん
 例文であれば、変数を使わず、引数として渡すというのはどうですか?
    Sub test()
        With Sheets("A")
            Select Case .Range("A1").Value
                Case "大"
                    Call Size(Sheets("B"))
                Case "中"
                    Call Size(Sheets("C"))
                Case "小"
                    Call Size(Sheets("D"))
                Case Else
                    MsgBox "サイズ欄に「大」「中」「小」のいずれかを入力してください", vbCritical
            End Select
        End With
    End Sub
    Sub Size(ByVal ws As Worksheet)
        MsgBox ws.Name & "です"
    End Sub

(稲葉) 2017/07/19(水) 10:53


ねむねむ様
稲葉様

貴重な意見ありがとうございます。

稲葉様kら頂きましたコードで動きました。

ただ、なんでうまく動いているのかを理解しておきたくて・・・。
すいませんが教えていただけないでしょか。

    Call Size(Sheets("B"))

この部分で、ワークシートオブジェクト自体を渡している?のでしょうか?

よろしくお願い申し上げます。

(ろでっち) 2017/07/19(水) 11:15


 技術的なことについて詳しく説明できる自信はありません。

http://vbae.odyssey-com.co.jp/column/no29_1.html
http://excel-ubara.com/excelvba4/EXCEL218.html
http://www.239-programing.com/excel-vba/basic/basic017_5.html

 引数の渡し方については上記サイトを参照していただくとわかりやすいと思います。

 今回ByValで宣言してしまいましたが、変数ではなくオブジェクトそのものを渡してるのでByRefでも
 結果は変わらないと思います。
 が、今後活用される場合に注意が必要と思ってByValで宣言してあります。
 ByValで受け取った場合と、ByRefで受け取った場合の違いを実感してみてください。

    Sub test2()
        Dim ws1 As Worksheet
        Set ws1 = Sheets("A")
        MsgBox ws1.Name
        Call test3(ws1)
        MsgBox ws1.Name
        Call test4(ws1)
        MsgBox ws1.Name
    End Sub
    Sub test3(ByVal ws As Worksheet)
        Set ws = Sheets("B")
    End Sub
    Sub test4(ByRef ws As Worksheet)
        Set ws = Sheets("B")
    End Sub

(稲葉) 2017/07/19(水) 12:08


今回のご質問は、WorkSheetオブジェクトも共通変数にできるの?、というところですが、処理内容だけ見ると、無理にサププロシジャ化せずとも良いかもです。

 Sub Size()
    Dim iw As Long
    Dim cw As String

    iw = InStr("大中小", Sheets("A").Range("A1"))
    If 0 < iw Then
        cw = Array("B", "C", "D")(iw - 1)
        MsgBox Sheets(cw).Name & "です"
    Else
        MsgBox "サイズ欄に「大」「中」「小」のいずれかを入力してください", vbCritical
    End If
 End Sub
(???) 2017/07/19(水) 17:25

稲葉様
ご解説ありがとうございます。
確かに、ByvalとByREFの違いが判りました。
ByREFは呼び出し元の値まで変えてしまうわけですね。

正直ByREF使うと頭がぐちゃぐちゃになりそうですね(^^;

???様

コードの方ありがとうございます。
こちらの方も試してみます!。

とりあえず、こちらでアドバイスいただいた皆様のおかげで何とかなりそうです。
ありがとうございました!
(ろでっち) 2017/07/19(水) 22:31


PS:しかし、変数はPublicで定義してやると別プロシージャーでも使えるのに、なんでオブジェクト(SET)は使えないのかと不思議に思ってしまいます。

VBAは初心者の私から見ても、かなり柔軟性にとんでいると思うのですが、何か理由でもあるんでしょうかね。
(ろでっち) 2017/07/19(水) 22:37


 >PS:しかし、変数はPublicで定義してやると別プロシージャーでも使えるのに、
 >なんでオブジェクト(SET)は使えないのかと不思議に思ってしまいます。 

 ちょっと、意味が分からないです。

 (スカラー)変数とオブジェクト変数の何処が違うって言っているんでしょうか?

 片や初期値(Longなら0、VariantならEmpty)、片やNothingになっているだけじゃないですか?
 同じようなものと思うのですが?

 スカラー変数だって、
 こんなこと出来ないですよ?
  ↓
 Public aa, bb
     aa = "AA"
     bb = "BB"

 Sub Size()

 End Sub 

(半平太) 2017/07/19(水) 23:59


 別視点から
 >PS:しかし、変数はPublicで定義してやると別プロシージャーでも使えるのに、
 Publicは別「モジュール」で使える、のほうがしっくりきます
 同一モジュールであれば、Dimでもいいのですから。
http://www.239-programing.com/excel-vba/basic/basic033.html

(稲葉) 2017/07/20(木) 02:00


 定数と勘違いしているのだろうか?

(ねむねむ) 2017/07/20(木) 07:27


ども^^

 >定数と勘違いしているのだろうか?
 そうですね。

>(ろでっち) 2017/07/19(水) 10:07
↑の書き方を見ると、定数と混同されているようですね。

あと、

>パブリックで変数を設定すると、モジュール内で共用の変数で使えるのは知っています。
↑これも誤解ですよね?

「publicで変数を宣言すると、他のモジュールからでもその変数を使用できる。」

ですね?

もう一回、
「変数 スコープ 適用範囲」等で検索されて認識を確かにしてください。

で、動けばいいというものないでしょう?
「なんで、これだとだめなの?」
というとこを突き詰めないと。。。

そこで、
>(ろでっち) 2017/07/19(水) 10:07
↑このコードは、どのモジュールに書いているのですか?
で、どうやってマクロを起動したいのですか?

(まっつわん) 2017/07/20(木) 08:16


これで判りますかね?

 Public ws1 As Worksheet        'これは変数宣言文だから、プロシジャ外に書くと共通変数になる

 Sub test()
    Set ws1 = Worksheets("A")   'これは実行文だから、プロシジャ内にしか書けない
    Call testsub
 End Sub

 Sub testsub()
    MsgBox ws1.Name             'ws1は共通変数だから、プロシジャ内で宣言無しで使える
 End Sub

ちなみに、この例ではws1はモジュール内共通変数です。 更に、標準モジュール等に Publicを付けて変数宣言すると、ブック内全体での共通変数(共通関数)になります。 VBAでは、大きく分けて3種類のスコープがあるということ。

(1)プロシジャ内だけの変数
(2)モジュール内共通変数
(3)ブック内共通変数
(???) 2017/07/20(木) 09:24


 ???さん
 > Public ws1 As Worksheet        'これは変数宣言文だから、プロシジャ外に書くと共通変数になる
 >この例ではws1はモジュール内共通変数です。 更に、標準モジュール等に Publicを付けて変数宣言
 ということですが、Dim(Private)で宣言されたほうが、ろでっちさんも混乱されないかと思います。
(稲葉) 2017/07/20(木) 11:29

あ、しまった、確かに Public宣言のまま書いちゃいましたね。 ここは Dim にすべきでした。 まぁ、ろでっちさんがまた見てくれて、疑問に思ってくれたらフォローしましょう。
(???) 2017/07/20(木) 11:42

 人の粗探しが得意ですみませーん。
 自分の粗も簡単に見つけられたらいいのですが・・・。

 ろでっちさんが質問してくれたら、うれしいですね。
(稲葉) 2017/07/20(木) 11:45

ども^^

もう見てないのかな。。。ま、書いたので。。。
???さんとかぶってるかもですが書いちゃったので^^;

オブジェクトは「定数」として宣言できません。
なので「変数」として宣言し、後でプロシージャの中で「代入」という作業を書くことになります。
代入が出来てしまったら、「変数」でも「定数のように」扱うことができますね。

<標準モジュールに>

Option Explicit

'モジュールレベルで使用する変数の宣言
Private mWsh1 As Worksheet
Private mWsh2 As Worksheet
Private mWsh3 As Worksheet
Private mWsh4 As Worksheet

'メインのプロシージャ
Sub Size()

    'オブジェクトの取得
    Call GetObject

    '条件分岐
    If ws1.Range("A1").Value = "小" Then
        Call Mini
    ElseIf ws1.Range("A1").Value = "中" Then
        Call Midle
    ElseIf ws1.Range("A1").Value = "大" Then
        Call Big
    Else
        MsgBox "サイズ欄に「大」「中」「小」のいずれかを入力してください", vbCritical
    End If
End Sub

'オブジェクトの取得
Private Sub GetObject()

    With ThisWorkbook
        Set ws1 = .Worksheets("Sheet1")
        Set ws2 = .Worksheets("Sheet2")
        Set ws3 = .Worksheets("Sheet3")
        Set ws4 = .Worksheets("Sheet4")
    End With
End Sub

'各プロシージャ
Private Sub Mini()

    MsgBox mWsh2.Name
End Sub
Private Sub Middle()
    MsgBox mWsh3.Name
End Sub
Private Sub Big()
    MsgBox mWsh4.Name
End Sub

'*************************************************
でも、この程度ならあえてプロシージャを分ける必要はないですよね。
参考までに、、、
Sub test()

    Dim wsChoice As Sheets
    Dim wsInput As Worksheet
    Dim ix As Variant
    Dim sProm As String
    Dim lngBtn As Long

    Set wsChoice = Worksheets(Array("Sheet2", "Sheet3", "Sheet4"))
    Set wsInput = Worksheets("Sheet1")
    sProm = "サイズ欄に「大」「中」「小」のいずれかを入力してください"
    lngBtn = vbCritical

    On Error Resume Next
    ix = WorksheetFunction.Match(wsInput.Range("A1").Value, Array("小", "中", "大"), 0)
    On Error GoTo 0
    If ix > 0 Then
        sProm = wsChoice(ix).Name
        lngBtn = vbOKOnly
    End If

    MsgBox sProm, lngBtn
End Sub

※ポイントは「同じことを2度書かない」です。
提示されたコードは、一連の流れの中で最終的には
Msgbox 〜
と同じことが4回出て来てます。
そういう時は変数を上手く使って1回にまとめます。
そうやって同じことを書かないようにするために、
共通の部品としてサブルーチンを用意するなら、
プロシージャを分ける方が効率的ですね^^

(まっつわん) 2017/07/20(木) 13:06


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.