|
> 返事遅れてすいません構文が難しく悩んでいて八方ふさがりになっていました。
>とりあえず処理自体は希望どうりの動きと結果でした。
>自分も勘違いしていた部分もあり理解した部分もあるのですが理解できない
>部分は、いまだにインターネット又本等で調べているのですがわからず
>あつかましのですがもう一度教えてください
私も説明が下手で恐縮している所ですが、
解らなければ、遠慮しないで何度でも聞いて下さい
先ず、くどく成って申し訳ありませんが?
今回のコードのに就いて
目的:Listの中の、各行(レコード)でKeyが重複する場合
その行の或るフィールドの値を、Key重複する先頭行のフィールドに集計し
Key重複する先頭行以外は、行削除する
条件:ListはA1を左隅とし、列数はA〜D列の4列、データ行数は実行する毎に違う
Keyと成るのは、A列(品番)、B列(納期)の2Keyで、
集計するのは、C列(計画数)とする
此れを目的、条件をガチガチに守って組んだコードが「Sub Ver2maedaosi_4」です
しかし、もし目的その物は変わらないが、対象と成るListの位置を変えなければ成らない
Keyの位置が変わった、Keyの数が変わった等の変更
または、同じ目的なので、違うListに使い回したい等の場合
例えば、List先頭がB2から始まり、列数がB〜F列の5列、KeyがB列、C列、E列の3列と成り
集計列が、F列とした場合
「Sub Ver2maedaosi_4」では、コードの中身を大幅に変更しなければ成りません
しかし、「Sub Ver2maedaosi_2」では
'Listのデータ列数(B列〜F列)
Const clngColumns As Long = 5
'「計画数」列の在る位置(品番列を0番目と勘定する)
Const clngItems As Long = 4
'Listのデータ先頭セル位置を基準とする
Set rngList = Worksheets("展開").Range("B2")
'整列Keyを作成(B列順のC列順のE列順)
vntKeys = Array(0, 1, 3)
と4箇所の値を変更すれば済みます
それ故、コードが回りくどく成っている事をお詫びして置きます
さて、
>vntKeys = Array(0, 1)
>
>カンマがついていたので2次元配列と勘違いしていました。
>Array関数は1次元配列のバリアント型なのは納得しましたが、Arrayで列を格納する場合
>Array(”A”、”B”、”C”、”D”)又は数字の場合Array(Array(0,1)・・・・
>見たいな感じかとおもっていました?
>上記文だと
>Vntkeys(0)=0’VntKeys(0)に0を格納する
>vntKeys(1)=1’VntKeys(1)に1を格納する
>と自分は解釈していまあしたが、これで2列をキーとできるのがとても不思議です?
「vntKeys = Array(0, 1)」の理解は、上記で合って居ます
詰まり、vntKeys(0)=0、vntKeys(1)=1の意味でしか有りません
しかし、これがなぜKeyの位置を示すかと言うと
別のプロシージャ等で行われているので、直接は書いて有りませんが
以下の様な使われ方がされています(意味として)
rngList.Offset(0, vntKeys(0)):rngList.Offset(0, 0)と成り、
rngListがA1なら、A列を示します
rngList.Offset(0, vntKeys(1)):rngList.Offset(0, 1)と成り、
同様に、B列を示します
>後Private Subの構文も処理がわからず
>
>特に
>lngNum = -Int(-(UBound(vntK) + 1) / 3) * 3 - 1 ’///この構文がわからない?
「-Int(-実数)」と言う構文は、切り上げ計算をするのBasicの定石です
行っている意味は、vntK(基底0の配列)を後で出てくるSortメソッドの為に
vntKの要素数を超える最小の3の倍数の要素数にvntKの要素数を拡張する為の
数を出して居ます
UBound(vntK) + 1:配列vntKの要素上限(基底0なので要素数は+1)から要素数を出している
例えば、Keyが2個なら、UBound(vntK)の要素上限は1、要素数は2
因って、
lngNum = -Int(-2 / 3) * 3 - 1:2/3は、0.666・・と成るので切り上げて1、
1*3で3、-1するのでlngNumは2と成ります
後で、配列vntKを拡張しますので、
配列vntKは、要素0〜2の3要素数と成ります
また、Keyが1個の場合、「UBound(vntK) + 1」は1と成り、0.33・を切り上げ1、
1*3-1で、配列vntKは、要素0〜2の3要素数と成ります
同様に、Keyが3個の場合、「UBound(vntK) + 1」は3と成り、3/3で1、
1*3-1で、配列vntKは、要素0〜2の3要素数と成ります
此れは、コードの都合上、形だけ常に3Keyで整列するコードにしている為に
行って居ます
Range.Sortのメソッドは、引数Key2:、Key3:にEmptyを与えた場合Keyを無視する様です
ただこの時、無視させる場合でもOrder2:、Order3:にはxlAscending(1)xlDescending(2)を
入れなければ成らない様です
>
> ReDim Preserve vntK(lngNum), vntO(lngNum)
> For i = UBound(vntOrders) + 1 To lngNum ’動的配列宣言範囲VntOrdersに1’を足した数字〜lngNumまで
> vntO(i) = xlAscending ’vnt0で繰り返し参照している部分を昇順にする
> Next i iに処理を移行
上記で説明した様に
配列vntK、配列vntOを値を保持したまま、要素数を3の倍数に拡張し
配列vntOは、拡張した分にxlAscending詰まり1を代入しています
> With rngScope rngScopeに対して同じ処理を行う
> For i = lngNum To 0 Step -3 ’///なんでステップ3ずつ?
> .Sort _
> Key1:=.Cells(1, vntK(i - 2) + 1), _
> Key2:=IIf(IsEmpty(vntK(i - 1)), vntK(i - 1), .Cells(1, vntK(i - 1) + 1)), _
> Key3:=IIf(IsEmpty(vntK(i)), vntK(i), .Cells(1, vntK(i) + 1)), _
> Order1:=vntO(i - 2), _
> Order2:=vntO(i - 1), _
> Order3:=vntO(i), _
> Header:=xlNo, OrderCustom:=1, MatchCase:=False, _
> Orientation:=xlTopToBottom, SortMethod:=xlStroke
Range.Sortのメソッドの引数Key1:、Key2:、Key3:と引数Order1:、Order2:、Order3:に
配列vntK、 vntOの値を後ろから3個づつ与えてSortします
(この時、Keyは無視させる場合Emptyを、実行させる場合は、Rangeに直して与える)
尚、「vntKeys = Array(0, 1)」で与えるKey数が3個以内なら1回整列が行われ
「vntKeys = Array(0, 1, 2, 3)」と4Keyなら、「3」列で1回、「0, 1, 2」列で1回の
2回整列が行われます
>後上記配列を使用しないコードを処理してみましたがこちらも処理結果はOKですが
>ステップごとに動かして見ましたがE列に連番を振っている部分は確認できましたが
>その後は処理が早すぎるため動きが確認できませんでした。
>一応報告まで
先ず、
'画面更新を停止
Application.ScreenUpdating = False
をコメントアウトして下さい(画面更新をする様にして置く)
次に、1行実行(F8キーで進める)したら「Worksheets("展開")」を見て下さい
書き込まれるセルの値が変更されている筈です
尚、Testは20〜30行位のテストデータの方が解りやすいかと思います
|
|