[[20220810111636]] 『動的配列はpublicで宣言できないのでしょうか?』(イヨ) ページの最後に飛ぶ

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

 

『動的配列はpublicで宣言できないのでしょうか?』(イヨ)

こんにちは
ご覧いただき有難うごさいます。

動的配列はpublicで宣言できないのでしょうか?
もしできるのであれば配列をpublicで扱えるようにしたいです。

少し気になったので質問してみました。
宜しくお願いします。

< 使用 Excel:Office365、使用 OS:Windows10 >


 >動的配列はpublicで宣言できないのでしょうか?

 なんで自分で試してみようとか思わないのか不思議。
 甘えすぎでは。
(まだ16) 2022/08/10(水) 11:27

でわ、早速、実験を。。。^^
使えましたよ。(*^^*)v
Excel 2016 365タイプ
Win  10
でした。
(隠居Z) 2022/08/10(水) 11:33

もちろん自分でも試しました。
できなかったのでここで質問させて頂いております。

該当のコードは長くてほかのコードに繋がってるので要点だけ伝えるのには
上記の質問の仕方が良いかもと思い、そう書き込みました。
(イヨ) 2022/08/10(水) 11:37


↑ 取消おねがいいたします。
無視してください。
だめっぽいですね。^^;
m(__)m
(隠居Z) 2022/08/10(水) 11:38

隠居Zさんコメントありがとうごさいます。
ローカルウィンドウを見ると変数は初期値になぜか戻ってしまいますよね?

初期値に戻らず回避するやり方とかないか自分も模索中です。

(イヨ) 2022/08/10(水) 11:40


 Option Explicit
Public v() As Variant
Sub OneInstanceMain()
    Dim i As Long
    For i = 0 To 9
        ReDim Preserve v(i)
        v(i) = "X" & CStr(i + 1)
    Next
    MsgBox Join(v, Chr(13))
End Sub
だと、どうなりますでせう。m(__)m
(隠居Z) 2022/08/10(水) 11:44

 あら、かぶりましたが、そのまま

 隠居Zさんのマクロうごきます。

 以下のものもうごきます。  

 ' -- Module 1

 Public Ary() As String

 Sub Test1()
   Call Test2
   ReDim Preserve Ary(2)
   Ary(2) = "Hage"
   Debug.Print Join(Ary)
 End Sub

 '-- Module2

 Sub Test2()
   ReDim Ary(0)
   Ary(0) = "Hoge "
 End Sub
(´・ω・`) 2022/08/10(水) 11:48

以下で動きましたが。
逆に、動かないコードがどういうものか知りたいですね。

    Option Explicit
    Public arr() As String

    Sub sample()
        ReDim arr(1)
        arr(0) = 1
        arr(1) = 2
        proc1
        Debug.Print Join(arr)
    End Sub

    Private Sub proc1()
        ReDim Preserve arr(UBound(arr) + 1)
        arr(UBound(arr)) = 3
    End Sub

(tkit) 2022/08/10(水) 11:50


 >ローカルウィンドウを見ると変数は初期値になぜか戻ってしまいますよね?
 ローカルウィンドウ見ると、アクティブなモジュールからのツリーになってますからね。

 ウォッチウインドウで、ウォッチ式を追加すれば見れるでしょ
(´・ω・`) 2022/08/10(水) 11:51

>>逆に、動かないコードがどういうものか知りたいですね。
わたしが二度目に試したとき、エラー出てたのですが。
何か、ミスってたかもしれません。おかしいと思いシンプルなもので
試すと、動きましたので↑のようなコメントになりました。
今、ダメな場合を模索中。。。^^;。。。。。見つからないかもm(__)m

(隠居Z) 2022/08/10(水) 11:56


 >今、ダメな場合を模索中
 回答者がそんな事する必要ないでしょ

 回答者する側は、皆短くて簡単なテストコードかいて、うまくいくよっていってます。

 >該当のコードは長くてほかのコードに繋がってるので要点だけ伝えるのには
 >上記の質問の仕方が良いかもと思い、そう書き込みました。
 そんなこといってないで、短くて簡単で「できないこと」が伝わるコード書いて示すべきです
 回答する側にばかり負担かけさせんなって話ですよ
(´・ω・`) 2022/08/10(水) 12:13

(´・ω・`)さん tkitさん有難うございました。

()
を省くと、ご案内の様に、最初に初期化しないと
型違いになります。が問題なく動きます。
イヨさんのコードと、エラー番号、エラーメッセージ
をお待ちいたします。^^
>>回答者がそんな事する必要ないでしょ
お怒り、ごもっともで御座います。
只、最初のテスト時に、インデックスが有効範囲に無いエラーが出ましたもので
あれ〜不思議だな〜とか思いましたので。何の間違いだったのか、私自身が
納得いかなくて、勉強と、楽しみで、探していました。^^;
お許しを
m(__)m
(隠居Z) 2022/08/10(水) 12:28


ただ単にコードを書くモジュールの問題なのでは
(ngk) 2022/08/10(水) 13:04

 常に使えないのか、使えないときもあるということなのか、どちらでしょう。

 Public変数は時々、リセットがかかる時がありますよね。
 たとえば、プロシージャから抜ける時に、
 普通は Exit Subとしますが、End で抜ける人が時々います。
 これはPublic変数が初期化される原因になります。
 そのほかいくつか原因があるようです。

(γ) 2022/08/10(水) 16:37


 勿論、使えると私自身は思っています。念のため。
 (すでに指摘がありますが、Publicは標準モジュールだけでしか宣言できません。
 詳しいメッセージが出ますから、気づかないことはないとは思いますが。)
(γ) 2022/08/10(水) 16:42

皆様コメントありがとうございます。

結果として、解決しました。
書き込んでいただいたコードと自分のコードを照らし合わせどこが間違っているのか
確認しました所、プロッシーシャーの中でDim宣言をしていたことが原因でした。

2重で宣言をしてしまい、初期化になっていたみたいです。

皆様のコードや言葉からどこに注目して確認すればいいか大変勉強になりました。
特にYさんの
>普通は Exit Subとしますが、End で抜ける人が時々います。
自分はxit SubとEndの違いがいまいちわからず調べるきっかけになったので
とても素晴らしい気づきを与えてくれた言葉でした。
有難うごさいます。

隠居Zさん
コード有難うごさいます
他の方が言われていた
>>>回答者がそんな事する必要ないでしょ
について。
コードを書くことが楽しいという気持ちはだれにも否定できませんから
気にしないで下さい。探求心ががるのはとてもいいことなのです。
そして素直に私はうれしかったです。有難うごさいます。
一緒に楽しくやっていきましょう。
隠居Zさんのお言葉通りにコードをここに乗せますね。

Public ws1 As Worksheet
Public ws2 As Worksheet
Public ws3 As Worksheet

Public xlLastRow As Long
Public CLastRow As Long

Public xxlLastRow As Long
Public LLastRow As Long

Public arr() As Variant
Public arr2() As Variant

Sub aaa()
Dim strNames() As String

'Sub パブリックの設定()

 Set ws1 = Worksheets("1")
 Set ws2 = Worksheets("2")
 Set ws3 = Worksheets("3")

        ws3.Activate
    xlLastRow = ws3.Cells(Rows.Count, 1).Row
    CLastRow = ws3.Cells(xlLastRow, 1).End(xlUp).Row
    Dim arr() As Variant: arr = ws3.Range(Cells(CLastRow, 1), Cells(2, 1))

       ws1.Activate
    xxlLastRow = ws1.Cells(Rows.Count, 1).Row
    LLastRow = ws1.Cells(xxlLastRow, 1).End(xlUp).Row
    Dim arr2() As Variant: arr2 = ws1.Range(Cells(LLastRow, 1), Cells(2, 1))

    Debug.Print ws1.Name & "の最終行は『" & LLastRow & "』です"
    Debug.Print ws3.Name & "の最終行は『" & CLastRow & "』です"
    Debug.Print ws2.Name
End Sub

Sub 検索方法()
Call aaa

    For i = LBound(arr, 1) To UBound(arr, 1)
    For j = LBound(arr2, 1) To UBound(arr2, 1)
    Dim sWord As String: sWord = arr2(j, 1)

  Select Case "完全一致"
         Case "完全一致"
            If arr(i, 1) = sWord Then
             Debug.Print sWord & "完全一致" & j
            End If

         Case "部分一致"
            If InStr(sWord, arr(i, 1)) > 0 Then
            Debug.Print sWord & "部分一致" & j
            End If

    End Select
    Next j
    Next i
End Sub

(イヨ) 2022/08/11(木) 14:38


γさんコメントありがとうごさいます。
じぶんが求めていた答えで、できるのか、できないのか。
きっぱり言ってくださって助かりました。

その言葉が欲しかったのと、
自分で気づきたかったので。
結果として粘って解決できたので感謝します。

(イヨ) 2022/08/11(木) 14:43


 うーん、私が申し上げたこととは全く別の話なので、
 誤解があるように思います。

 コメントを拝見すると、
 Public変数と同名のプロシージャレベルの変数arrを使っていたということですか?

 そのプロシージャの中では、プロシージャレベルの変数が優先されますし、
 Public変数には影響を及ぼさないと思います。全く別の変数ですから。

 つまり、aaaプロシージャで操作しているのは、あくまでプロシージャレベルの変数arrです。
 Public変数arrは宣言されたままの状態ですね。

 そういう理解に達したということでしょうか。

(γ) 2022/08/11(木) 15:24


(イヨ)さんご提示の 2022/08/11(木) 14:38 コードですが←ご提供、有難う御座いますm(__)m
当方では確かにエラーになります。
再定義部分を消し、実行で正常作動します。更に、その後
再度、再定義された修正已前のコードを実行すればエラーになりません。
しかし、保存して終了後再読込すると、同じ現象が再現致します。??;
不可解ですが。。。そのぉ。。。^^;
ご報告まで。m(_ _)m
(隠居Z) 2022/08/11(木) 15:54

 tes1を実行した後、他のマクロ(別ブック可)を実行後
 時間をあけてもいいけど、tes2を実行。
 多分、値は保持されていると思います。(リセット信号が入らなければ)

 Public hh As String

 Sub tes1()
 hh = "WWWW"
 End Sub

 Sub tes2()
 MsgBox hh
 End Sub

 後
 Public ws1 As Worksheet
 これらは、幽霊プロジェクトの怪だっけ?かの問題があるとは思いますが
 別問題なので。
(まだ16) 2022/08/11(木) 19:46

(γ) さん、2022/08/11(木) 15:24。。。のご案内のとおりみたいですね。
やっと、理由が解ったよぉな気がいたします。
お騒がせいたしました。二つのプロシージャに分かれているのが原因のようですね
最初はプロシジャー変数を使用、なので抜けると値は破棄されます。
お次はいきなり、何も使用を宣言する処理されていないパブリック変数を参照したのが
原因のようです。当たり前と云えばあたりまえのような事で、汗顔のいたりです。

勉強させて戴きましたし、楽しませて戴きました。ありがとうございました。
まだ16さんのコードも試させて戴きます。
m(__)m
(隠居Z) 2022/08/11(木) 20:20

 私が申し上げたかったことは下記の記事の内容です。(米国の有名なアーカイブです。怪しいところではありません)
 「Public 宣言された変数の有効期間」
http://web.archive.org/web/20090909235324/http://support.microsoft.com/kb/408871/ja 
 (少し古い記事で、現在、ネット上に無いようですけど、この仕様が変更になったとは思えません。)

 Public変数も処理が終わってからもずっと残ることは保証されず、
 これを避けるには、それをシートに書き込むといった原始的方法が確実だということです。

 # Public変数とプロシージャレベル変数を重複して使っていましたという話は、
 # 正直言って想定していませんでした。

(γ) 2022/08/11(木) 20:57


イヨさん、すみません。場所お借りしてます。m(__)m
↑ γさまへ
以前にも一度、教えて戴きましたので、個人的には
必要が有れば、大域変数用にアドインブックを作成後、参照設定し、
マクロ本体のブックと対にして、使用したり、テキスト、数値等、
セルで間に合えば、作業用セルを用意したり、プロシジャ変数を参照渡しで
引数として変化させたり、たまに、iniファイル作成したりで対応する様に
致しております。ご案内、ありがとうございました。
さすがに、私のスキルでは。。。レジストリはいじらない様にしています。^^;
m(_ _)m
(隠居Z) 2022/08/11(木) 22:58

隠居Zさん、色々なテクニックの紹介ありがとうございました。
アドインの利用とか、やったことのない方法ばかりでした。
余り大掛かりなものは作ったことはありませんので、今後の参考にさせていただきます。
ありがとうございました。
(γ) 2022/08/12(金) 06:55

[[20100731000846]]
↑諸先輩に教えて戴いた、対処法の検索代行[パクリ^^;]でした。。。
m(_ _)m...あれ?↑、γさんじゃないですよね←。。。多分。。。A^^;
(隠居Z) 2022/08/12(金) 08:21

 >結果として、解決しました。

「動けばいい」のか、
「今後このような間違いを防ぎたい」のか、
どっち?

提示のコードは、変数の使い方に多々、勘違いが存在しているように感じます。
とりあえず、各プロシージャ間で共有したいのは、
Public arr() As Variant
Public arr2() As Variant
の2つだと思うので、それ以外はプロシージャ内で宣言したらよいかと。

やりたいことがよくわかりませんが、参考まで。
(動作確認をしてませんので、バグがあってもご容赦を)

Option Explicit

Private mList1 As Variant
Private mList2 As Variant

Private Sub test()

    With Worksheets("1").Range("A1").CurrentRegion
        With Intersect(.Offset(1), .Columns(1))
            mList1 = WorksheetFunction.Transpose(.Cells)
            mList2 = WorksheetFunction.Transpose(Worksheets("3").Range(.Address))
        End With
    End With
End Sub

Public Sub 検索()

    Dim i As Long
    Dim s As String

    test

    For i = LBound(mList1) To UBound(mList1)
        If mList1(i) = mList2(i) Then
            s = "完全一致"
        ElseIf InStr(1, mList1(i), mList2(i)) > 0 Then
            s = "部分一致"
        Else
            s = "不一致"
        End If

        Debug.Print i & "行目:", mList1(i) & " " & s
    Next
End Sub
(まっつわん) 2022/08/12(金) 11:15

コメント返信:

[ 一覧(最新更新順) ]


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