ワークシートは2次元配列

配列って言葉はプログラム用語です。英語でArrayです。そのままのArray関数がVBAにもあります。

さて、ワークシートは二次元配列です。プログラムの二次元配列とワークシートの違いは、配列はメモリ内にあり、ワークシートは見えることです。プログラムでは、ワークシートのセルに入れるために2次元配列を返す関数に慣れましょう。という話です。

自作の関数を活かすには、ワークシートのセルは2次元配列と扱うことと配列数式が必要です。

カテゴリー: 9 セルの中で使うユーザー定義関数の作成 <VBA> | コメントする

myLookup関数

mySUM関数に続いて第二弾。数式バーにカッコがいっぱい書いてませんか。プログラムだと限界はありませんし、スキルアップになります。

ワークシート関数を数式バーに3つ以上書く力をプログラム開発に向けましょう。プログラムのスキルアップの方が効率的です。

'自作VLOOKUP関数。完全一致専用
Function myLookUp(検索値これは検索範囲の一番左列, 検索範囲 As Range, 列番号 As Long)
    Dim ar()
    ar = 検索範囲
    Dim i As Integer '行だけ
    For i = 1 To UBound(ar, 1) '行の処理
        If 検索値これは検索範囲の一番左列 = ar(i, 1) Then
                myLookUp = ar(i, 列番号)
                Exit Function
        End If
    Next
End Function
'?myLookUp("ken", Range("e4:h12"), 2)

ややこしい関数も自作でいこう!。これは自作でないとできない。それにとっても自由。

'自作VLOOKUP関数
Function myLookUp2(検索値, 検索列番号, 全範囲 As Range)
    Dim ar()
    ar = 全範囲
    Dim i As Integer, j As Integer
    ReDim arr(1 To 100, 1 To 100)'10000とかすると飛びます
    Dim ii As Integer 'arrの行番号用、列はjを使う
    For i = 1 To UBound(ar, 1)
        j = 1
        If VBA.CStr(ar(i, 検索列番号)) Like 検索値 Then
            ii = ii + 1
            For j = 1 To UBound(ar, 2)
                arr(ii, j) = ar(i, j)
            Next
        End If
    Next
    myLookUp2 = arr
End Function
'?myLookUp2("*k*", 3,Range("e4:h12"))(0,0)

以下は、データ作成用。

Sub 表作成()
'
' Macro1 Macro
'
    If VBA.MsgBox("選択しているワークシートが無くなります!!!", vbOKCancel) = VBA.vbCancel Then Exit Sub
    
    Columns("A:h").Delete Shift:=xlToLeft
    
      Range("H3").Select
    ActiveCell.FormulaR1C1 = "phone"
    Range("H4").Select
    ActiveCell.FormulaR1C1 = "'0311111"
    Range("H5").Select
    ActiveCell.FormulaR1C1 = "'0751111"
    Range("H6").Select
    ActiveCell.FormulaR1C1 = "'061123"
    Range("H7").Select
    ActiveCell.FormulaR1C1 = "'075222"
    Range("H8").Select
    ActiveCell.FormulaR1C1 = "'0322222"
    Range("H9").Select
    ActiveCell.FormulaR1C1 = "'0521111"
    Range("H10").Select
    ActiveCell.FormulaR1C1 = "'0622222"
    Range("H11").Select
    ActiveCell.FormulaR1C1 = "'0753333"
    Range("H12").Select
    ActiveCell.FormulaR1C1 = "'063333"
    Range("H13").Select


    Range("E3").Select
    ActiveCell.FormulaR1C1 = "no"
    Range("F3").Select
    ActiveCell.FormulaR1C1 = "name"
    Range("G3").Select
    ActiveCell.FormulaR1C1 = "address"
    Range("E4").Select
    ActiveCell.FormulaR1C1 = "1"
    Range("E4:E10").Select
    ActiveWindow.SmallScroll Down:=-6
    Range("E4").Select
    Selection.AutoFill Destination:=Range("E4:E12"), Type:=xlFillSeries
    Range("E4:E10").Select
    ActiveWindow.SmallScroll Down:=-9
    Range("F4").Select
    ActiveCell.FormulaR1C1 = "tom"
    Range("F5").Select
    ActiveCell.FormulaR1C1 = "ken"
    Range("F6").Select
    ActiveCell.FormulaR1C1 = "emi"
    Range("F7").Select
    ActiveCell.FormulaR1C1 = "bob"
    Range("F8").Select
    ActiveCell.FormulaR1C1 = "bill"
    Range("F9").Select
    ActiveCell.FormulaR1C1 = "ben"
    Range("F10").Select
    ActiveCell.FormulaR1C1 = "sam"
    Range("F11").Select
    ActiveCell.FormulaR1C1 = "may"
    Range("f12").Select
    ActiveCell.FormulaR1C1 = "ron"


    Range("G4").Select
    ActiveCell.FormulaR1C1 = "tokyo"
    Range("G5").Select
    ActiveCell.FormulaR1C1 = "kyoto"
    Range("G6").Select
    ActiveCell.FormulaR1C1 = "osaka"
    Range("G7").Select
    ActiveCell.FormulaR1C1 = "kyoto"
    Range("G8").Select
    ActiveCell.FormulaR1C1 = "tokyo"
    Range("G9").Select
    ActiveCell.FormulaR1C1 = "nagoya"
    Range("G10").Select
    ActiveCell.FormulaR1C1 = "osaka"
    Range("G11").Select
    ActiveCell.FormulaR1C1 = "osaka"
    Range("G12").Select
    ActiveCell.FormulaR1C1 = "kyoto"
    
    Range("A1").Select
    ActiveCell.FormulaR1C1 = "1"
    Range("A1").Select
    Selection.AutoFill Destination:=Range("A1:F1"), Type:=xlFillSeries
    Range("A1:F1").Select
    Range("A4").Select
    ActiveCell.FormulaR1C1 = "1"
    Range("A4").Select
    Selection.AutoFill Destination:=Range("A4:A12"), Type:=xlFillSeries
    Range("A4:A10").Select
    Range("B4").Select
    ActiveCell.FormulaR1C1 = "tom"
    Range("B5").Select
    ActiveCell.FormulaR1C1 = "ken"
    Range("B6").Select
    ActiveCell.FormulaR1C1 = "emi"
    Range("B7").Select
    ActiveCell.FormulaR1C1 = "bob"
    Range("B8").Select
    ActiveCell.FormulaR1C1 = "bill"
    Range("B9").Select
    ActiveCell.FormulaR1C1 = "ben"
    Range("B10").Select
    ActiveCell.FormulaR1C1 = "sam"
    Range("B11").Select
    ActiveCell.FormulaR1C1 = "may"
    Range("B12").Select
    ActiveCell.FormulaR1C1 = "ron"
    
    Application.CutCopyMode = False
    ActiveSheet.ListObjects.Add(xlSrcRange, Range("$E$3:$h$12"), , xlYes).Name = _
        "myTable"
End Sub

カテゴリー: 9 セルの中で使うユーザー定義関数の作成 <VBA> | コメントする

プロシージャ内で自分のセルの番地 ThisCell

以下の関数を標準モジュールに書いて、ワークシート関数のようにセルの中に書く。

ThisCellプロパティは、ユーザー定義関数内で使うことで自分セル位置を取得できる。使う場合は、Excel.Application.ThisCellまたはApplication.ThisCellとApplicationを付ける必要がある。型はRangeなのでRow、CollumnやOffsetも使える。

Function myAddress()
    myAddress = Excel.Application.ThisCell.Address(0, 0) '0はFalseでも同じ。0が無いと絶対表示$A$1になる
End Function

Function myCells()
    myCells = "Cells(" & Excel.Application.ThisCell.Row & "," & Excel.Application.ThisCell.Column & ")"
End Function

Rowは行、Columnは列のこと。

AceitveCellやSelectionもアドレスを表示することができるが、これらは選択しているセルの位置であり、ユーザー定義関数が入っているセルの位置ではない。もし、ActiveCellやSelectionを使うと上図の場合は、セルA1を選択しているので左のmyAddress()は、A1:D5のすべてがA1に、右もすべてCells(1,1)になる。

ユーザー定義関数を作る時に自分のセルを扱いたい場合はThisCellを使う。

カテゴリー: 9 セルの中で使うユーザー定義関数の作成 <VBA> | コメントする

配列の()?コレクションの()?関数の()?

VBでは、配列、コレクション、プロシージャも同じ記号の()を使う。ややこしいですね。他の言語では配列は[ ]を使う。

VBAの()の使い方3つ。

  1. 配列変数(要素番号)
  2. コレクション(名前またはインデックス番号) Range
  3. プロシージャ名(引数1,引数2)

ここでは、とりあえず2番目のRangeを説明します。

まず、XXXX(??, ??,??)とカッコを付けると戻り値がある。つまり、変数名=XXXX(??, ??,??)やDebug.Print XXXX(??, ??,??)( Debug.Print の出力が値)ができる。配列も関数も同じような書き方をする。イミディエイトで?とする場合は、戻り値を期待しているので()がいる。「変数=」の右辺に書く場合も変数に代入したいのだから()がいる。

ExcelのオブジェクトであるRange(“A1”)()のカッコは、配列ように見えるがItemの省略。Item関数は感覚的には配列のように考えればいい。以下は、イミディエイトウィンドウで、?はPrintのこと。?から始まる行は入力。次の行は出力結果。

set kk=range("a1:b2")
?vba.TypeName(kk)
Range
?kk(1)
A1
?kk(2)
B1
?kk(3)
A2
?vba.TypeName(range("a1:b2"))
Range
?range("a1:b2").Item(1)=range("a1:b2")(1)
True
?range("a2:b3")(1)
A2

配列でもオブジェクトでも関数でも()のカッコは、戻り値を受け取るためと理解すればいい。最もよく使うのがコレクションの中の一つを取り出すために使う()。

カテゴリー: 3 習熟のためにイミディエイウィンドウを使う | コメントする

VBA.Now関数とVBA.Date関数の違い

VBAの関数の話しです。

Date関数は時間が無いことがイミディエイトで実行するとわかる。関数の調査ができると例えばHour(Date)は常に0になることが確認できる。 ?から始める文字列の行が入力する。他は出力行。

?vba.Now
2018/08/26 1:16:41 
?date
2018/08/26 
?vba.Hour(date)
 0 
?hour(now)
 1

Now、Date関数どちらも引数が無い。セルの中で使うワークシート関数のDateは引数がいる。

https://youtu.be/RTt3iXGGOJo
カテゴリー: 3 習熟のためにイミディエイウィンドウを使う | コメントする