アプリ版:「スタンプのみでお礼する」機能のリリースについて

VBAの配列について質問があります。
以下のような配列Aと配列Bがあったとします。
やりたいことは、配列Cを作成して、配列Aと配列Bを結合したいです。
-----------------------------------------
Dim 配列A(3)
配列A(0) = 10
配列A(1) = 11
配列A(2) = 12

Dim 配列B(3)
配列B(0) = 100
配列B(1) = 110
配列B(2) = 120
----------------------------------------

Dim 配列C(6)
配列A(0) = 10
配列A(1) = 11
配列A(2) = 12
配列A(3) = 100
配列A(4) = 110
配列A(5) = 120
----------------------------------------

配列Cを作るために、配列Aを拡張して、配列Bを挿入すれば可能
でありますが、関数のようなもので簡単に表現できないもので
しょうか?

何かご存知でしたが、ご教授願います。

A 回答 (3件)

> 関数のようなもので簡単に表現できないものでしょうか?



PHP なんかだと array_push 関数があるんですけどねー・・
VB6/VBA には同等機能をもった関数はありませんから、
無いものは作るしかないです。

以下のソースを標準モジュールに貼り付けます。全部添え字は
0 から始まる 0 オリジンです。

  # もっと短く簡単に書けますけど、なるべく汎用的に
  # 使えるようにしてます


' // 各引数の要素を1次元配列化し、引数 args の要素を追加する
'
Public Function Array_Push(ByRef src As Variant, _
              ParamArray args() As Variant _
) As Variant

  Dim vBuf As Variant
  Dim vTmp As Variant
  Dim nCnt As Long
  Dim arg As Variant
  Dim v  As Variant
  Dim i  As Long

  vBuf = Array_Convert1DArray(src)
  
  For Each arg In args()
    vTmp = Array_Convert1DArray(arg)
    nCnt = Array_GetElementCount(vTmp)
    i = UBound(vBuf)
    ReDim Preserve vBuf(i + nCnt)
    i = i + 1
    For Each v In vTmp
      vBuf(i) = v
      i = i + 1
    Next
  Next
  Array_Push = vBuf

End Function

' // 引数 src の値を1次元配列で返す
'
Public Function Array_Convert1DArray(ByRef src As Variant) As Variant

  Dim vBuf As Variant
  Dim v  As Variant
  Dim i  As Long
  
  If Array_GetDimension(src) = 0 Then
    Array_Convert1DArray = Array(src)
  Else
    ReDim vBuf(Array_GetElementCount(src) - 1)
    For Each v In src
      vBuf(i) = v
      i = i + 1
    Next
    Array_Convert1DArray = vBuf
  End If

End Function

' // 配列の次元数を返す
'
Public Function Array_GetDimension(ByRef src As Variant) As Long

  Dim i As Long
  Dim j As Long

  If IsArray(src) Then
    On Error Resume Next
    While Err.Number = 0
      i = i + 1
      j = UBound(src, i)
    Wend
    On Error GoTo 0
    Array_GetDimension = i - 1
  Else
    Array_GetDimension = 0
  End If

End Function

' // 配列の要素数を返す
'
Public Function Array_GetElementCount(ByRef src As Variant) As Long

  Dim nDimension As Long
  Dim nUpper   As Long
  Dim nLower   As Long
  Dim i     As Long
  Dim j     As Long

  If IsArray(src) Then
    nDimension = Array_GetDimension(src)
  Else
    nDimension = 1
  End If
  j = 1
  For i = 1 To nDimension
    nLower = LBound(src, i)
    nUpper = UBound(src, i)
    j = j * (nUpper - nLower + 1)
  Next i
  Array_GetElementCount = j

End Function

一度定義(貼り付け)てしまえば、後はこれを呼び出すだけ。
例えば、こんな感じ。

Sub test()

  Dim 配列A(2) ' 通常は 0 オリジンなので添え字は2ですね
  配列A(0) = 10
  配列A(1) = 11
  配列A(2) = 12

  Dim 配列B(2)
  配列B(0) = 100
  配列B(1) = 110
  配列B(2) = 120

  Dim 配列C
  配列C = Array_Push(配列A, 配列B, Array(1, 2, 3), _
            "XXX", "YYY", "ZZZ")

  ' 以下確認用
  Dim i As Long
  Dim s As String
  For i = 0 To UBound(配列C)
    s = s & "配列C(" & CStr(i) & ") = " _
      & 配列C(i) & vbNewLine
  Next
  MsgBox s

End Sub

余談になりますが、数値(可変長文字列やオブジェクト以外)
だけを扱うのであれば、CopyMemory API を使った方法もあります。
    • good
    • 0

少し形は変わりますがArray関数を使って、このように結合することが出来ます。



Dim 配列C
配列C = Array(配列A, 配列B)

'結果
配列C(0)(0) '→10
配列C(1)(0) '→100
配列C(1)(2) '→120
    • good
    • 0

スパッとできる良い方法は無いようだ。


VB.NETでは方法があるようだが。
Sub test01()
Dim a(3)
Dim b(4)
a(1) = 10: a(2) = 30: a(3) = 50
b(1) = 10: b(2) = 30: b(3) = 50: b(4) = 40
s1 = Join(a, " ")
s2 = Join(b, " ")
s3 = Trim(s1 & s2)
MsgBox s3
c = Split(s3, " ")
For i = 0 To UBound(c)
MsgBox c(i)
Next
End Sub
しかし上記は、2つの配列をFor Nextで読んで別の新しい配列にデータを順次入れる(再構成する)コード行数と変わらないと思う。
配列にデータが全て埋まってないとさらにややこしくなるようだし。
例 Dim a(10)で上記をやるとおかしくなる。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!