家計簿アプリを、より使いやすく自分仕様に改造していきましょう!
以前の投稿で、家計簿アプリとして最低限の機能を持たせることができました。
(その6までをご確認いただいていない方は、まずは下記まとめをご確認ください。)
ただ、これは本当に最低限の機能しかなく、勘定科目も『固定費』と『変動費』しかないので、
各家庭に合った勘定科目を自由に追加できるように、
このマクロのデコレーションをしていく必要があります。
前回、【配列】の概念について説明しました。
ただ、前回は「配列とは?」という点しか説明できていませんでしたので、
今回は実際にプログラミングで配列を使う場合はどう使うのか、といった点について説明していこうと思います。
【配列】を使いこなせるようになると、ExcelVBA以外の他のプログラミング言語でも応用が可能になってきますので、プログラミングスキルが大幅に向上します。
頑張って慣れていきましょう!
【本記事の目標】
プログラミングで配列を使う準備をしていこう
簡単なイメージは下記記事に記載していますので、イメージづくりや今回以降の流れの参考に。
また、前回までの記事については下記をご確認ください。
配列の種類
前回の記事で【配列】のイメージは『複数のデータを入れられる間仕切りのある大きな箱』という点を説明しました。
じゃあ、この配列を実際にプログラミングで使うにはどう使っていけばいいのか?
そもそも一言で【配列】と言ってもいくつか種類がありますので、まずはそれを説明していきます。
動的配列と静的配列
【配列】は、データを入れるための箱という意味では「変数」の仲間ですので、プログラミングで使う際には事前に【配列】を定義する必要があります。
「変数」の場合は特に気にせず、
Dim
Private
Public
を使って変数を定義することができました。
【配列】も同じように定義することができますが、「変数」を定義する際と大きな違いがあり、
配列のサイズを可変にするか、不変にするか
(間仕切りを変更できるようにするか、固定してしまうか)
という点を定義の段階で指定する必要があります。
ここで、
サイズが可変な配列(間仕切り数が変更可能):動的配列
サイズが不変な配列(間仕切り数が固定):静的配列
と言います。
データ形式による分類
「変数」は定義する際に、どんなデータを入れるかも含めて定義します。
例えば文字列データを入れる「変数」の場合
Dim A as String
整数データを入れる変数の場合
Dim B as Integer
【配列】も「変数」の仲間ですので、同じように定義の際にどんなデータを入れるかを含めて定義する必要があります。
例えば、
文字列データを入れる【配列】の場合:文字列配列
数値データを入れる【配列】の場合:数値配列
といった言い方をする場合があります。
この時注意しないといけないのは、
配列を定義する際に、データ形式を指定して定義した場合は
その配列の中にあるデータは全て指定したデータ形式にする必要がある
という点です。
なので、「文字列配列」として定義した配列の中に一部だけでも数値データを入れることはできませんし、
「数値配列」として定義した配列の中に一部だけでも文字列データを入れることはできません。
厳密にいうと、「文字列配列」の中に数値データを入れることは可能です。
ただしその場合、入力した数値データは「数値」ではなく「文字列」として入ります。
逆に「数値配列」の中には文字列データを入れることはできません。
配列の定義
配列の種類が分かったので、じゃあ実際に配列の定義をプログラミングで行っていきましょう。
静的配列の定義
静的配列(配列のサイズが不変)を定義する場合は、
定義するタイミングで配列のサイズも指定する
ということが必要です。
そのため、配列を定義するタイミングで必要な配列のサイズを把握しておく必要があります。
具体的に静的配列を定義する際の文言の例を下記に示します。
Dim TestArrayS1(5) As String
Dim TestArrayS2(5,3) As Integer
Dim TestArrayS3(2 to 8) As Double
Dim TestArrayS4(2 to 8, 1 to 5) As String
静的配列を定義する際は、
・各次元の最大数を入力する(この場合、0~最大値の配列になる)
・各次元の最初~最後の数を『2 to 8』といった形で表現する
のどちらかを選んで記載する必要があります。
動的配列の定義
動的配列(配列のサイズの変更が可能)を定義する場合は、静的配列とは異なり、
定義するタイミングでの配列サイズの指定は不要
です。
ただし、配列であることを明示するため配列名の後ろに『()』を付ける必要があります。
具体的に動的配列を定義する際の文言の例を下記に示します。
Dim TestArrayD1() As String
Dim TestArrayD2() As Integer
データ形式の1つで【Variant】というものがあります。
データ形式を宣言せずに変数を定義した場合のデータ形式もこの【Variant】型になります。
この【Variant】型というのは、どんなデータ形式にもなれるデータ形式です。
ですので、この形式で宣言した変数には、文字列データでも、数値データでも、
またRangeやWorksheetといったオブジェクトであっても入れることができます。
(オブジェクトの場合は別途『Set』を使用する必要があります)
さらにこの【Variant】型は単一のデータだけでなく、配列にもすることもできます。
そのため、【Variant】型として変数を定義した場合、動的配列として宣言する場合のような変数名の後ろの「()」を付けていなかったとしても、動的配列として再定義して使用することが可能です。
非常に汎用性が高いデータ形式ですが、汎用性が高すぎるが故に、プログラミングをした本人以外の可読性が大幅に損なわれる危険があります。
また、どんなデータも入れられるため、意図した形でないデータが入る可能性があり、よくわからないエラーが出る懸念もあります。
それらデメリットを認識した上であれば、この【Variant】型というのは非常に有用なデータ形式です。
動的配列の再定義(ReDim)
動的配列の定義はこれだけなのですが、静的配列のと異なり、
動的配列はこのままでは使用できません。
というのも、この定義だけでは動的配列であることは定義していますが、
まだそのサイズを明示していません。
ですので、プログラム中でこの配列を使う前に、
再定義して配列のサイズを明示する必要があります。
再定義の際に使うのが【ReDim】です。
【ReDim】の使用方法は【Dim】と基本的に同じで
ReDim 変数名(配列サイズ)
という形で定義します。
ただ【Dim】と異なり、最初にDimでデータ形式を定義していますので、
【ReDim】ではデータ形式の宣言は不要です。
そもそも【Dim】で宣言したデータ形式を、【ReDim】で変更することはできません。
配列のサイズの記載方法は静的配列の定義での書き方と全く同じです。
具体的に動的配列を再定義する際の文言の例を下記に示します。
ReDim TestArrayD1(5)
ReDim TestArrayD2(5,3)
ReDim TestArrayD3(2 to 8)
ReDim TestArrayD4(2 to 8, 1 to 5)
【ReDim】を使った動的配列の再定義は、
プログラム中であれば基本的にいつでもどんなサイズにでも変更可能です。
5行の1次元配列を10行に拡張
8行10列の2次元配列を3行2列に縮小
1次元配列を3次元配列に変更
2次元配列を1次元配列に変更
非常に自由度の高い動的配列ですが、1つだけ注意が必要な点があります。
それは、
【ReDim】で再定義するとその配列の
中にあったデータが全て消えてしまう
という点です。
中にあるデータを残しながら配列のサイズを変更したい場合は【Preserve】を使う必要があります。
データを残した動的配列の再定義(Preserve)
【ReDim】だけで再定義すると、動的配列の中にあったデータは一度全て削除されてしまいます。
それを避けてデータを残して再定義をするときに使うのが【Preserve】です。
これはReDimの後ろに付けて使用します。
具体的に使用する際の文言の例を下記に示します。
ReDim Preserve TestArrayD1(5)
ReDim Preserve TestArrayD2(5,3)
ReDim Preserve TestArrayD3(2 to 8)
ReDim Preserve TestArrayD4(2 to 8, 1 to 5)
この【Preserve】を付けるだけでデータを残して再定義することができますが、
【Preserve】を付けた場合、配列のサイズ変更にいくつか制約がかかります。
【Preserve】を使った場合の配列サイズ変更の制約は2つ。
1.配列の次元の変更はできない
2.サイズ変更ができるのは最終次元の部分だけ
ここで「1.配列の次元の変更はできない」というのはイメージがつくと思います。
1次元配列を2次元配列や3次元配列に変更できない、という感じです。
少しわかりづらいのが「2.サイズ変更ができるのは最終次元の部分だけ」かと思います。
これは配列のサイズを記載するときに、一番右側の部分しか変更できない、という意味です。
このように【Preserve】を使うと【ReDim】単体の場合に比べるとできることが大幅に制限されますのでご注意ください。
配列の定義のまとめ
ここまでの内容をまとめて表にすると下記のようになります。
配列へのデータの受け渡し
上記までで配列の定義はできるようになりました。
じゃあ、あとはこれを使っていくだけです。
ただ、使っていくといっても、基本的には「変数」と同じ使い方になりますので、
1.データの代入
2.データの貼り付け
の大きく2つの使い方だけかと思います。
配列へのデータの代入
配列にデータを代入する際は、基本的には通常の変数と同じように「=」でデータを代入します。
ただ、配列の中には複数のデータが入っている、もしくは入れることができますので、配列のどこに入れるのかということも明示しながら代入していく必要があります。
具体的には下記のようにデータを入れていきます。
Dim NumA(3) As Integer
NumA(0) = 5
NumA(1) = 10
NumA(2) = 15
NumA(3) = 20
このように1つずつ代入していくでも良いですし、For文を使って連続で代入していくこともできます。
Dim i As Integer
Dim NumA(3) As Integer
For i = 0 To 3
NumA(i) = 5 * i
Next i
配列は特にこういった繰り返し動作との相性が非常に良いです。
配列を使用する場合は、こういった繰り返しの動作を駆使していくことで、
より端的でわかりやすく、かつプログラムの動きも早いプログラムを作ることができます。
静的配列の場合は上記のように1つ1つの要素ごとにデータを代入していく必要がありますが、
動的配列の場合は配列にそのまま配列を代入することができます。
Dim i As Integer
Dim NumA(3) As Integer
Dim NumB() As Integer
For i = 0 To 3
NumA(i) = 5 * i
Next i
NumB = NumA
この場合、配列の中のデータだけでなく配列のサイズも含めて代入されるため、
もともと中に入っていたデータはもちろん全て消えますし、
事前に配列のサイズを定義していたとしても、そのサイズも代入元の配列サイズに変更されます。
そのため、サイズの異なる配列のデータを、サイズを変えず、元のデータも削除せずに代入する場合は、要素を1つ1つ代入していく必要があります。
配列データの貼り付け
配列のデータをExcelシートに貼り付ける場合、1つ1つのセルを指定して、そこに配列のどのデータを入れていくのかを指定する必要があります。
Dim i As Integer
Dim NumA(3) As Integer
For i = 0 To 3
NumA(i) = 5 * i
Next i
For i = 0 To 3
With ThisWorkbook.Worksheets(1)
.Cells(i + 1, 1).Value = NumA(i)
End With
Next i
ただ2次元配列の場合、配列をそのまま貼り付けることができます。
その場合、貼り付け先は配列と同じサイズを指定しておく必要があります。
配列よりも小さい範囲を指定していた場合、そこまでのデータしか貼り付けられません。
Dim i As Integer
Dim j As Integer
Dim NumA(1 To 5, 1 To 3) As Integer
For i = 1 To 5
For j = 1 To 3
NumA(i, j) = i + j
Next j
Next i
With ThisWorkbook.Worksheets(1)
.Range("A1:C5").Value = NumA
End With
また2次元配列をExcelシートに貼り付ける場合、
1次元目(配列の左の数値)が【行】になり、
2次元目(配列の右の数値)が【列】になります。
配列の主な概念や、基本的な使い方の説明は以上です。
ただこれだけを聞いてもなんとなくでしか理解ができないと思います。
ですので、次回以降で実際に配列を使ってデータの抽出や貼り付けのプログラムを確認していき、
分からなくなったら、またここに戻ってきて概念や基本を再度確認する、というのを繰り返し、
少しずつ理解していっていただけたらと思います。
次の記事へ
コメント