モジュールを作成するには?

解決


TAKE  2003-07-08 14:21:46  No: 78556

作成したプログラムを使い回しが聞くようにするために、プログラムを独立したモジュールにしたいのですが、そのプログラムの中にフォームのオブジェクト(と、いうのでしょうか?)が含まれている場合、どのようにモジュールとして、分割するべきなのかわかりません。

これは、ツリービューのノードを利用している時や、リストビューのリストアイテムを利用している時などに頻繁に起こり、今まではあきらめてきました。

以下のプログラムは以前の質問でのものですが、もし、ご面倒でなければ、これからの参考としたいので、これを元に  sortNumList()  の部分をモジュールに分割していただけないでしょうか?

Option Explicit

Dim isAsc As Boolean

Private Sub Form_Load()
    Dim li As ListItem
    
    Set li = lvwList.ListItems.Add(, , "Test")
        li.SubItems(1) = FormatCurrency(25.25)
        
    Set li = lvwList.ListItems.Add(, , "TAKE")
        li.SubItems(1) = FormatCurrency(10.25)
    
    Set li = lvwList.ListItems.Add(, , "AAAA")
        li.SubItems(1) = FormatCurrency(35.55)
    
    Set li = lvwList.ListItems.Add(, , "BBB")
        li.SubItems(1) = FormatCurrency(5.55)
        
    Set li = lvwList.ListItems.Add(, , "ZZZ")
        li.SubItems(1) = FormatCurrency(125.55)
    
End Sub

Private Sub lvwList_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader)
    
    If ColumnHeader.Index = 1 Then
        lvwList.Sorted = True
        sortList (ColumnHeader.Index)
    Else
        lvwList.Sorted = False
        sortNumList
    End If
    
End Sub

Private Sub sortNumList()

    Dim i As Integer                'index
    Dim j As Integer                'index
    Dim li As ListItem              'list item
    Dim intMin As Double            'minimum value
    Dim intMax As Double            'maximum value
    Dim intRemovedRow As Integer    'row number to be removed
    Dim intCount As Integer         'the number of row listed

    intCount = lvwList.ListItems.Count

    If isAsc = False Then
    
        For i = 1 To lvwList.ListItems.Count
        
            'Set dammy minimum value
            intMin = 100000
            
            For j = 1 To intCount
            
                'Check if the item is minimum
                If lvwList.ListItems(j).SubItems(1) < intMin Then
                    intMin = lvwList.ListItems(j).SubItems(1)
                    intRemovedRow = j
                End If
                
            Next
            
            isAsc = True
        
            'Add new list item
            Set li = lvwList.ListItems.Add(, , lvwList.ListItems(intRemovedRow))
                li.SubItems(1) = lvwList.ListItems(intRemovedRow).SubItems(1)
            
            'Remove old list item
            lvwList.ListItems.Remove (intRemovedRow)
            
            intCount = intCount - 1
            
        Next
        
    Else
    
        For i = 1 To lvwList.ListItems.Count
        
            'Set dammy maximum value
            intMax = 0
            
            For j = 1 To intCount
            
                'Check if the item is minimum
                If lvwList.ListItems(j).SubItems(1) > intMax Then
                    intMax = lvwList.ListItems(j).SubItems(1)
                    intRemovedRow = j
                End If
                
            Next
            
            isAsc = False
    
        
            'Add new list item
            Set li = lvwList.ListItems.Add(, , lvwList.ListItems(intRemovedRow))
                li.SubItems(1) = lvwList.ListItems(intRemovedRow).SubItems(1)
            
            
            'Remove old list item
            lvwList.ListItems.Remove (intRemovedRow)
            
            intCount = intCount - 1
            
        Next
    
    End If

End Sub

Private Sub sortList(ColumnHeaderIndex As Integer)

    If lvwList.SortKey = ColumnHeaderIndex - 1 Then
        If lvwList.SortOrder = lvwAscending Then
            lvwList.SortOrder = lvwDescending
        Else
            lvwList.SortOrder = lvwAscending
        End If
    Else
        lvwList.SortKey = ColumnHeaderIndex - 1
        lvwList.SortOrder = lvwAscending
    End If

End Sub


Loreley  2003-07-08 17:36:05  No: 78557

ちょっとコードがながいんで、
勝手に変えますが、たとえば
List1というListBoxが存在するのが前提です。
(Form1.frm)
Option Explicit

Dim isAsc As Boolean

Private sub AddData()

   if isAsc=False then
       List1.Additem "a"
   Else
       List1.Additem "b"
   End if

end sub

private sub command1_click()
   call AddData()
end sub

というプログラムのがあったとします。

これを分割するとしたら
(Form1.frm)
Option Explicit

Dim isAsc As Boolean

private sub command1_click()
   call AddData(List1,isAsc) '引数が追加される
end sub

(Module1.bas)
Public Function AddData(ByRef ocxList As Listbox,isAsc As Boolean)
'外から呼べるようにPublic宣言である
'引数としてオブジェクトと、ここで必要な変数を宣言

   if isAsc=False then
       ocxList.Additem "a"
   Else
       ocxList.Additem "b"
   End if

end Function

//////////////////////////
こんなかんじです。
まず、lvwListがなんなのかわかりませんが、
そのコントロールの型に合う引数、
外で宣言されているのに中で使っている変数(isAscがそうですね)を

Public Function SortNum(ByRef ocxList As ????, ByRef isAsc As Boolean)

というように宣言してやります(????には、正しい型を入れてください。
As Controlとかでもいけますけど、しっかり指定したほうが良いでしょう。)

あとは、SortNum内の lvwListをocxListと置換してあげれば
いけると思います。

基本的には引数としてコントロールを、参照渡しするだけです。


TAKE  2003-07-09 12:04:09  No: 78558

大変ありがとうございました。とてもうまくいきました。
結構簡単なことだったんですね。

これで、これからのプログラムを整理しやすくなりました。


魔界の仮面弁士  2003-07-09 13:24:04  No: 78559

> 基本的には引数としてコントロールを、参照渡しするだけです。

私の場合は、このような要件では、ocxList、isAscのいずれも
参照渡し(ByRef)にはせず、値渡し(ByVal)を使う事が
多かったりします。(^-^A
(ByRefは、戻りを返す時ぐらいしか利用しないようにしているので…)

まぁ、コーディング規則は人それぞれ違うでしょうし、
今回のコードではどちらでも同じような結果になりますから、
参照渡しのままでも、動作的には問題無いですけれどね。
http://support.microsoft.com/?kbid=161308

> まず、lvwListがなんなのかわかりませんが、
lvwという接頭辞は、ListViewコントロールに使われる事が多いですね。
http://www.microsoft.com/japan/developer/library/VBCon98/vbconobjectnamingconventions.htm


TAKE  2003-07-09 16:56:33  No: 78560

魔界の仮面弁士さん、追加説明ありがとうございます。

まだByValとByRefの使い分けが完全には把握しきれていませんが、
できるだけ、それ相応の使い方をしていけるように心がけるようにしますね。


Loreley  2003-07-09 18:17:41  No: 78561

>ocxList、isAscのいずれも参照渡し(ByRef)にはせず、
>値渡し(ByVal)を使う事が多かったりします。(^-^A

isAscに関しては、関数内で代入を行っていたので参照渡しにしたんですよ
で、まぁForm中のグローバル変数だったので、返しておいたわけです

コントロールって値渡しでも操作できるんですねぇ。
ハンドルもコピーされるから当然といえば当然か・・・

私の場合も戻りを返す・・・というか「値の変更を適用させたい時」
という基準でやっているのと、
コントロールのような大き目のものを渡すときは
値渡しではメモリを多く食いそうという勝手な解釈で
(Cのポインタのような気持ちで)
やってたもので

と、いうか、規定値がByRefというのを忘れてました(笑)
なので、私のリストボックスでのサンプルにおいて、
isAscは気持ちだけ値渡しです(笑)


魔界の仮面弁士  2003-07-09 19:09:30  No: 78562

# なんだか、重箱の隅をつついてるようで申し訳無いですが、
# Functionの戻り値の型指定が抜けているのも、気になっていたり。。。

> isAscに関しては、関数内で代入を行っていたので参照渡しにしたんですよ
あぁ、なるほど。そういうわけですか。
それならば、ByRefでないと駄目ですね。

> isAscは気持ちだけ値渡しです(笑)
ん? ocxListではなく?(^^;)

> 値渡しではメモリを多く食いそうという勝手な解釈で
少し難しい話になりますが、メモリ使用量や処理手順という点から言えば、
ByRefの方が「重い」事もありますし、逆に「軽く」なる場合もありえます。
http://www.microsoft.com/japan/developer/library/VBCon98/vbconinprocessoutofprocesscodecomponents.htm


Loreley  2003-07-09 19:29:22  No: 78563

> isAscは気持ちだけ値渡しです(笑)
私の(最初の)例ではisAscは値変更不要なので、指定無しの(気持ちだけ)値渡しということです。
ocxListは、きっとそっちの方がいいと信じていたので、ByRefです(笑)

># Functionの戻り値の型指定が抜けているのも、気になっていたり。。。
たしかにそうですね。
戻り値返さないなら、手続きにしたほうがいいですし。
私も以前、人のコードを見たとき、同じ感想を持ちました・・・それなのに・・・ごにょごにょ(笑)

>ByRef を指定するのは、メソッドで、クライアントのオブジェクト参照がほかのオブジェクトへの参照に置き換わる場合のみです。

なるほどー
メソッド内で違うものにSetしなおすならByRefの方がいいということでしょうか。
というか内部的にByRefは単純なアドレス参照ではなさそうですね。
書き換えるたびにゴッソリコピーみたいな感じなんでしょうか
面白そうなので、今度もうちょっと調べてみようっと。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加