オブジェクト

初級VBA

オブジェクトとは

VBAのオブジェクトとは、いわばExcelの持つ部品を指します。ブックシートセルユーザーフォームやそれらに張り付いているボタンテキストボックスなど、Excelにはたくさんのオブジェクト(=部品)が存在します。
それらの実体は、クラスで出来ています。クラスの概念は初心者には難しいので漠然とした印象を持ってもらうしかありません。すごく簡単に言うと変数と関数をひとまとまりにして使えるようにしたような感じです。ただひとまとめにしただけでなく、色々な機能が使えるようになっています。

ブック、シート、セル、ユーザーフォーム、ボタン、テキストボックスなどあらゆるものがオブジェクト。オブジェクトはVBAで操作できるから、これらはプログラムで操作できるってことになる!

 オブジェクトを配列にしたものをコレクションと呼びます。

 例えば Worksheet と Worksheets が、オブジェクトコレクションの関係です。
(複数形の s が付いている事に注目!)
ActiveSheet は現在開いているシートというオブジェクト
Worksheets(“Sheet1”) は、Worksheetsコレクションの中にあるSheet1という名前のシートオブジェクトということになります。

 これまで、変数、演算子、関数、繰返し処理、条件分岐とみてきましたが、実は、VBAではオブジェクトやコレクションに対して何をするかがキモになります。
「シート上のセルの値を別のシートのセルに転記する」
「条件に合ったセルの背景色を変える」
「シートを印刷する」

このような事は、オブジェクトに対して操作することで実現できるようになります。

オブジェクトを変数として扱う

 オブジェクトを変数に代入するときは Set を付けます。【重要!】
これは、普通の変数と違う所です。Set を忘れるとエラーが出ますが最初のうちは Set を忘れていることに気付かずハマってしまう事がありますので注意しましょう。

Dim myRange As Range
Set myRange = Range("A1")

 このように書きます。これで、A1セルをmyRangeとして扱えるようになります。
開放するときは、同じようにSetを付けて Nothing(何もない)とすることができます。

Set myRange = Nothing

ただし、最終的にはオブジェクトは自動解放されますので書かない事の方が多いです。

プロパティ

 オブジェクトにはプロパティメソッドがあります。これらは名詞動詞の関係に似ています。
 プロパティはオブジェクトが持つ属性値なので、取得したり設定したり出来ます。
例えば、ワークシートの数を取得したければ、

   c = Worksheets.Count

というように オブジェクト.プロパティ名 としてやればOKです。

セルに値をセットしたければ、

   Range("A1").Value = "a"

このようにします。ただし、この場合は、Valueを省略しても良いことになっているので、

   Range("A1") = "a"

こうしてもOKです。

メソッド

 メソッドはオブジェクトに対して割り当てられた操作です。
例えば、A1のセルを選択したければ、

   Range("A1").Select

このように、 オブジェクト.メソッド名 としてやればOKです。
メソッドでは、引数を持つ物もあります。引数が2つ以上ある場合はカンマで区切ります。

str = InputBox(prompt:="input", Title:="title")

インプットボックスを表示させるにはこのようにします。
 Title:=”title” という書き方は、Titleという項目は”title”にしなさいという意味です。

イベント

 イベントとは、システムがオブジェクトに対して操作や処理を行った際に送られてくる信号のようなものです。
 イベントはオブジェクトとは直接関係ありませんが、ブック、シート、セルの動作や操作に対してシステムがイベントを発生させることがありますので、ここで触れておきます。

 イベントとは、これまでのようにプログラマーが書いた一連の流れとは別で、システムから送られてくる信号に対して何らかの処理をさせたい時に、プログラムを書いて用意しておくという感じです。

イベント(システムから送られてくる信号)には、「シートが変更した」「セルが変更された」などたくさん種類がありますが、それらはあらかじめ用意された関数があり、ここにプログラムを書く事になります。
 このような関数をイベントプロシージャと言いますが、イベントプロシージャは、標準モジュールではなく、各シートモジュールThisWorkbookモジュールなどに書くことになります。

オブジェクトを使ってみる(セル編)

 セルを使った転記について取り上げてみたいと思います。転記作業は初心者が最初に取り組むのに最適だと思います。
 業務改善の方法は色々あると思いますが、こっちのセルの値をあっちに貼り付けるというのが基本だと感じるからです。
 また、これが出来ずに他の事が出来るわけないという程基本中の基本なので特に初心者の方はじっくり取り組んでみてください。

同じシート内でセルの値を転記

 同じシート内のセルの操作であれば、シートの指定を省略できます。
なので、A1のセルの値をG1にコピーしたければ、

Range("G1") = Range("A1")

とすればOKですね。
 ただ、For文を使って値をコピーしていきたいなら、Cellsを使った方が都合が良いかもしれません。
Cells を使うなら、

Cells(1,"G") = Cells(1,"A") 

となります。Rangeで指定したときと列と行が逆になる点に注意です。
Cellsでは行,列となります。また、列も数値にした方がFor文では有利です。

Cells(1, 5) = Cells(1, 1)

このようにも書けますので覚えておきましょう。

では今回は下の図のような日付のある表を、右側に転記してみましょう。
転記は行列が入れ替わって、なおかつ2段に分かれています。

まず名前をコピー

 最初は名前を転記してみましょう。
佐藤さんは、B2 から G2、G8 にコピーします。

Cells(2, 5) = Cells(1, 2)
Cells(8, 5) = Cells(1, 2)

 高橋さんは、

Cells(3, 5) = Cells(1, 3)
Cells(9, 5) = Cells(1, 3)

 田中さんは、

Cells(4, 5) = Cells(1, 4)
Cells(10, 5) = Cells(1, 4)

 何となく規則性がありますが、コピー量は少ないのでそのまま書くことにしましょう。

日付と値をコピー

 さて今度は日付と値をコピーしていきます。
方針は2つあると思います。一つはブロックで考えて、行列を入れ替えて一気に貼り付ける方法。もう一つは、ひとつづつ値を貼り付けていく方法です。

 初心者向けなのは後者なので、今回はひとつづつ貼り付けていくことにします。
 方針としては、まずは起点となるセルをコピーするコードを書いて、規則性を見つけることにしましょう。
 規則性を見つけたらFor文を使って繰返し処理を行います。

起点の値をコピー

 日付からコピーしてみます。最初の日付から3日分のコピーは、

Cells(1, 8) = Cells(2, 1)
Cells(1, 9) = Cells(3, 1)
Cells(1, 10) = Cells(4, 1)

 これで規則性が見えてきました。コピー元は行が2,3,4,,,,, コピー先は列が 8,9,10,,,と増えていきます。コピー元を基準にしてFor文を組んでみます。

 字下げを忘れずに!

    Dim i  As Long
    For i = 2 To 17
        Cells(1, i + 6) = Cells(i, 1)
    Next i

 For文の 2 To 17 は 1日~16日までの期間を示しています。
コピー先で i + 6 としているのは、コピー元との差が 6 なのでそれを足しています。値に関しては起点となる日付から割り出します。
 まず佐藤さんの値はコピー元で列が1つ増えいますので、Cells(i, 1+1) なので Cells(i, 2) となります。
次にコピー先の日付との差は、行に1つ増えていますので、 Cells(1+1, i + 6) なので Cells(2, i + 6) となります。
これを先程のfor文につなげます。

    Dim i  As Long
    For i = 2 To 17
        Cells(1, i + 6) = Cells(i, 1)
        Cells(2, i + 6) = Cells(i, 2)
    Next i

 ここまで解れば、高橋さんと田中さんは簡単ですね。

    Dim i  As Long
    For i = 2 To 17
        Cells(1, i + 6) = Cells(i, 1)
        Cells(2, i + 6) = Cells(i, 2)
        Cells(3, i + 6) = Cells(i, 3)
        Cells(4, i + 6) = Cells(i, 4)
    Next i

下段へのコピー

 次は下段へのコピーです。起点となる日付の位置を確認しておきましょう。

        Cells(7, 8) = Cells(18, 1)

 For文のループ範囲は変更になって、

    For i = 18 To 32

 ですので、コピー先の列に関しては、18-8=10 で 10を引くことになります。

 続いて上段と下段の差を足します。上段と下段は行方向に6つです。
コピー先に6を加えればいいですね。
 ただ、これを変数にしておけば、上段と下段の差に変更があった時にすぐに対応できるようになります。なので今回は変数にして足すことにします。

    Dim span As Long
    span = 6
    For i = 18 To 32
        Cells(1 + span, i - 10) = Cells(i, 1)
        Cells(2 + span, i - 10) = Cells(i, 2)
        Cells(3 + span, i - 10) = Cells(i, 3)
        Cells(4 + span, i - 10) = Cells(i, 4)
    Next i

 では、全体のコードです。変数の宣言を上にして span も設定しやすいように上に書きます。

Sub 練習()
    Dim i  As Long
    Dim span As Long
    span = 6

    '佐藤
    Cells(2, 7) = Cells(1, 2)
    Cells(8, 7) = Cells(1, 2)
    '高橋
    Cells(3, 7) = Cells(1, 3)
    Cells(9, 7) = Cells(1, 3)
    '田中
    Cells(4, 7) = Cells(1, 4)
    Cells(10, 7) = Cells(1, 4)

    For i = 2 To 17
        Cells(1, i + 6) = Cells(i, 1)
        Cells(2, i + 6) = Cells(i, 2)
        Cells(3, i + 6) = Cells(i, 3)
        Cells(4, i + 6) = Cells(i, 4)
    Next i
    
    For i = 18 To 32
        Cells(1 + span, i - 10) = Cells(i, 1)
        Cells(2 + span, i - 10) = Cells(i, 2)
        Cells(3 + span, i - 10) = Cells(i, 3)
        Cells(4 + span, i - 10) = Cells(i, 4)
    Next i

End Sub

それでは、右部分を一旦削除して実行してみましょう。

失敗?

 あれれ。日付が変な数値に変わっていますね。
これは、ただコピーしたためシリアル値が貼り付けられたためです。
 直すためにでは2つ方法があります。
 一つはコピーした後、書式設定を行う。二つ目は日付型にしてコピーする方法です。
今回は、応用がききやすいので、書式設定を行う方法でやってみます。

さて、どうすればよいかはGoogleで調べてみます。
「excel vba セルの書式設定を変更」などとして検索してみてください。
Formatという関数がよく使われるので、これを使用してみます。

それと実行する前にセルの値をクリアするコードも追加しましょう。

Range("G1:W10").Clear

とすれば、右側の転記部分は消すことができます。

書き換えた全コードです。

完成版

Sub 練習()
    Dim i  As Long
    Dim span As Long
    span = 6
    
    Range("G1:W10").Clear’一旦消去
    '佐藤
    Cells(2, 7) = Cells(1, 2)
    Cells(8, 7) = Cells(1, 2)
    '高橋
    Cells(3, 7) = Cells(1, 3)
    Cells(9, 7) = Cells(1, 3)
    '田中
    Cells(4, 7) = Cells(1, 4)
    Cells(10, 7) = Cells(1, 4)

    For i = 2 To 17
        Cells(1, i + 6) = Format(Cells(i, 1), "m""月""d""日""")
        Cells(2, i + 6) = Cells(i, 2)
        Cells(3, i + 6) = Cells(i, 3)
        Cells(4, i + 6) = Cells(i, 4)
    Next i
    
    For i = 18 To 32
        Cells(1 + span, i - 10) = Format(Cells(i, 1), "m""月""d""日""")
        Cells(2 + span, i - 10) = Cells(i, 2)
        Cells(3 + span, i - 10) = Cells(i, 3)
        Cells(4 + span, i - 10) = Cells(i, 4)
    Next i

End Sub

お疲れ様でした

 さていかがだったでしょうか?最後の方は初心者の方には難しかったかもしれません。
しかし、どのようにプログラムを組んでいくのかという過程は理解できたのではないでしょうか。

是非、読むだけでなく自分でコードを打って確かめながらやってみてください。

 オブジェクトの理解は「習うより慣れろ」です。色々と使っていくうちにどういうものなのかが解ってくるでしょう。完全に理解しようとせず、部分的な知識を積み上げていく感じで取り組んだ方がいいでしょう。

次に進むための道しるべ

 このサイトでは、ここまでをExcelVBAの基礎部分として括っています。
他のプログラミング言語でも共通する、変数、繰り返し処理、条件分岐などに加えてVBAの部品であるオブジェクトをある程度理解したら、自分のやりたい事に挑戦してみましょう。

 更に高度な処理をしたい時は、配列やコレクション、クラスなど使用していくことになります。これらの中級、上級レベルは必要になったら身に付けていくようにしましょう。

これ以降でお勧めのコンテンツは以下の通りです。

タイトルとURLをコピーしました