LoginSignup
0
0

More than 5 years have passed since last update.

スピル時代のExcel VBA(2)

Last updated at Posted at 2019-03-17

初期化関数の定義

前回からの続きです。SPILLがInsiderだけでなく、一般に使用できる様になったら、Excel VBAの書法は、
大きく変化していくのでしょう。それに伴い、入門書も大幅に書き換えて欲しいと思います。
(入門書には、Option Explicitが奨励されていますが、VBAには無意味なので、
以下のプログラムには変数定義を行っていません。)
 今もまだ一般的でない、テーブルと構造化参照、Rangeと、Rangeと同等に扱える2次元配列について
詳しく見て行く必要があります。
 2次元配列を生成する関数L_INITをコンパクトにする為に、
Polymorphismを使いたいのですが、VBAではサポートされていません。
Polymorphism風にしたいので、TypeNameを使った関数を前もって定義します。

Function TN_(R)
    TN_ = TypeName(R)
End Function

Function TR_(R, Optional T = "Range")
    TR_ = (TypeName(R) = T)
End Function

Function TV_(R, Optional T = "Variant()")
    TV_ = TR_(R, T)
End Function

Function TS_(M, Optional N = "", Optional T = "String")
    TS_ = TR_(M, T) * TR_(N, T)
End Function

関数L_INITは、自分自身を呼び出すことにより、下記の様に簡潔に定義できます。
L_PAIRを弄っていたら、タイトルを付けられるようにしたかったので、
途中で、Elseif TS_(L1) Then ... を追加しました。

Function L_INIT(M, N, Optional L1 = 1, Optional L2 = 1, Optional S = "")
    On Error Resume Next
    If TR_(M) Then
        S = L_INIT(M.Rows.Count, N, L1, L2)

    ElseIf TV_(M) Then
        S = L_INIT(UBound(M, 1), N, L1, L2)

    ElseIf TS_(M, N) Then
        L = Split(M, " "): M = UBound(L) - LBound(L) + 1
        T = Split(N, ","): N = UBound(T) - LBound(T) + 1
        S = L_INIT(M, N, 0, 0)
        For I = 1 To M: S(I, 0) = L(I - 1): Next I
        For J = 1 To N: S(0, J) = T(J - 1): Next J

    ElseIf TS_(N) Then
        T = Split(N, ","): N = UBound(T) - LBound(T) + 1
        S = L_INIT(M, N, 0, 1)
        For J = 1 To N: S(0, J) = T(J - 1): Next J

    ElseIf TS_(L1) Then
        T = Split(L1, ",")
        N = UBound(T, 1) + 1
        S = L_INIT(M, N, 0, 1)
        For J = 1 To N: S(0, J) = T(J - 1): Next J

    Else
        ReDim S(L1 To M, L2 To N)
        For J = L2 To N: For I = L1 To M: S(I, J) = "": Next I: Next J
    End If

    L_INIT = S
End Function

2次元配列を抽象的に扱う為の関数

定義した関数L_INITを使って、ここでは、2つのRange(または2次元配列)を
横につなげる関数L_PAIRと、縦につなげる関数L_CONSを定義します。
関数的プログラムで抽象的に配列を扱うのに、見えてはいけないFor文を関数中に閉じ込めます。


Function L_RMN(R, M, N, Optional S = "")
    S = R
    M = UBound(S, 1) - LBound(S, 1) + 1
    N = UBound(S, 2) - LBound(S, 2) + 1
    L_RMN = S
End Function


Function L_PAIR(R1, R2, Optional S = "")
    On Error Resume Next

    S1 = L_RMN(R1, M1, N1)
    S2 = L_RMN(R2, M2, N2)
    M = WorksheetFunction.Min(M1, M2)
    N = N1 + N2

    S = L_INIT(M, N, L1, L2)

    For I = 1 To M
        For J = 1 To N1: S(I, J) = S1(I, J): Next J
        For J = 1 To N2: S(I, J + N1) = S2(I, J): Next J
    Next I
    L_PAIR = S
End Function

Function L_CONS(R1, R2, Optional S = "")
    On Error Resume Next

    S1 = L_RMN(R1, M1, N1)
    S2 = L_RMN(R2, M2, N2)
    N = WorksheetFunction.Min(N1, N2)
    M = M1 + M2

    S = L_INIT(M, N)

    For J = 1 To N
        For I = 1 To M1: S(I, J) = S1(I, J): Next I
        For I = 1 To M2: S(I + M1, J) = S2(I, J): Next I
    Next J
    L_CONS = S
End Function

色々、説明が足りてないが、まずはメモなので。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0