|
▼うさちゃん さん:
こんばんは。
>実は私は、一度もマクロとかVBAを触ったことがなかったのですが、
ということを伺って、ちょっと前回のコードを提示したことを後悔しました。
プログラミング初心者の方には難しかったかもしれません。
やっちんさんが提示された
http://www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=35915;id=excel
結果はうさちゃん さんのご希望とは違ったかもしれませんが、
考え方はこれです。
これが理解できないとこの種類の処理(他にも組合せや順列など)を
作成する事ができませんよ!!
↑このコードをじっくり理解してみて下さい。
で、コードを提示してしまったので途中で止めるのもなんなので・・・。
>1.例では、3つのセルとも1〜20の値とさせていただきましたが、
>これが、A1は1〜5、B1は11〜20、C1は51〜75、
>のように、バラバラの場合は、どのように記述すればよいのですか?
>
>2.例えば、1〜200のような場合でも、
>(1, 2, 3, 4, 5, 6、...中略...197, 198, 199, 200)と記述することになるのですか?
まず、総当たりリストを取得するプロシジャーを大きく変更しました。
標準モジュールに
'====================================================================
Private c_myarray() As Variant
Private c_idx() As Long
Private c_max() As Long
'===================================================================
Function init_totalhit(ParamArray 標本() As Variant) As Double
'総当たりデータをセットする
'input : 標本 総当たりリストを作成する標本配列
'Output: init_totalhit 総あたり数
Dim g0 As Long, g1 As Long
Dim tarray As Variant
Erase c_myarray()
Erase c_idx()
Erase c_max()
ReDim c_idx(1 To UBound(標本()) - LBound(標本()) + 1)
ReDim c_max(1 To UBound(標本()) - LBound(標本()) + 1)
init_totalhit = 1
For g0 = LBound(標本()) To UBound(標本())
c_max(g0 + 1) = UBound(標本(g0)) - LBound(標本(g0)) + 1
init_totalhit = init_totalhit * c_max(g0 + 1)
Next g0
ReDim c_myarray(1 To Application.Max(c_max()), 1 To UBound(標本()) - LBound(標本()) + 1)
For g0 = LBound(標本()) To UBound(標本())
tarray = 標本(g0)
For g1 = LBound(tarray) To UBound(tarray)
c_myarray(IIf(LBound(tarray) = 0, g1 + 1, g1), g0 + 1) = tarray(g1)
Next g1
Next g0
For idx = LBound(c_idx()) To UBound(c_idx())
c_idx(idx) = 1
Next
c_idx(UBound(c_idx())) = 0
End Function
'======================================================================
Sub term_totalhit()
'総当たり処理の終了処理
Erase c_myarray()
Erase c_idx()
Erase c_max()
End Sub
'======================================================================
Function get_totalhit(ans()) As Long
'総当たりメンバーを配列に出力する
'output: ans() メンバの配列 添え字は必ず1から始まる配列を用意する
' get_totalhit:0 -- 正常に配列取得
' 1 -- メンバの終わり
get_totalhit = 1
For i = UBound(c_idx()) To LBound(c_idx()) Step -1
If c_idx(i) + 1 <= c_max(i) Then
c_idx(i) = c_idx(i) + 1
get_totalhit = 0
Exit For
Else
c_idx(i) = 1
End If
Next
If get_totalhit = 0 Then
For i = LBound(c_idx()) To UBound(c_idx())
ans(i) = c_myarray(c_idx(i), i)
Next
End If
End Function
別の標準モジュールに
'====================================================================
'A1に1〜5、B1に11〜20 C1に51〜75の場合
Sub main1()
Dim idx As Long
Dim ans(1 To 3)
' ↑総当たりメンバーを取得する配列
Call init_totalhit(Array(1, 2, 3, 4, 5), _
Array(11, 12, 13, 14, 15, 16, 17, 18, 19, 20), _
Array(51, 52, 53, 54, 55, 56, 57, 58, 59, 60, _
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, _
71, 72, 73, 74, 75))
idx = 1
Do While get_totalhit(ans()) = 0
Range("a1:c1").Value = ans()
Range(Cells(idx, "h"), Cells(idx, "i")).Value = Range("e1:f1").Value
idx = idx + 1
Loop
Call term_totalhit
End Sub
'=======================================================================
'A1,B1,C1共に1〜20の場合
'つまり、前回のコードと同じ結果をだすためには
Sub main2()
Dim idx As Long
Dim ans(1 To 3)
' ↑総当たりメンバーを取得する配列
Dim ss(0 To 19) As Variant
For idx = 0 To 19
ss(idx) = idx + 1
Next
Call init_totalhit(ss(), ss(), ss())
idx = 1
Do While get_totalhit(ans()) = 0
Range("a1:c1").Value = ans()
Range(Cells(idx, "h"), Cells(idx, "i")).Value = Range("e1:f1").Value
idx = idx + 1
Loop
Call term_totalhit
End Sub
main1、main2のコードの中でご質問にお答えしています。
試してみて下さい。
|
|