エクセルマクロ・VBA達人養成塾 小川です。
キューバ旅行記、その72です。
キューバ屈指の外人向けリゾート地、バラデロにて。
むっちゃくちゃステキな、朝のカリブ海のビーチ。
というわけで。
前回まで書いてきたいろいろを考慮して、シリーズの最終版です。
一行の中に2回イコール「 = 」を書くと – Excel VBA
文字列内にある文字列を含んでいるかどうかの判定には、 Instr 関数を! – マクロ・VBA
複数のInstr関数の結果を上手に利用するには – Excel マクロ・VBA
エクセル上に展開された以下のリストを元にして作った二次元配列 myData がある。
|A列 |B列 | --------------------------------------------------------------------------------------------------- 2 行目 |Silver |銀 | --------------------------------------------------------------------------------------------------- 3 行目 |20-day ema |20日移動平均線 | --------------------------------------------------------------------------------------------------- 4 行目 |Gold |ゴールド | --------------------------------------------------------------------------------------------------- 5 行目 |Measured targets $40 & $43 |想定目標値 40ドルと43ドル | --------------------------------------------------------------------------------------------------- 6 行目 |Support $1320 to $1290 |支持線は1320ドル~1290ドルで形成 | --------------------------------------------------------------------------------------------------- 7 行目 |Municipal Bond ETF(NPI) |地方債ETF(NPI) | --------------------------------------------------------------------------------------------------- 8 行目 |Inverted Spring Alert |飛び込み台警報 | --------------------------------------------------------------------------------------------------- 9 行目 |Resistance $13.50 to $13.80 |抵抗線は13.50ドル~13.80ドルで形成 | --------------------------------------------------------------------------------------------------- 10行目 |"Muni Bond Troubles Ahead" |「地方債危機が目前に」 | --------------------------------------------------------------------------------------------------- 11行目 |House of Cards, the US sub-prime mortgage meltdown|楼閣の城、米国サブプライムローン崩壊| ---------------------------------------------------------------------------------------------------
このとき、フォームで入力した文字列を、A列かB列に含むリストの一覧を取得したいということで。
受講生が添削希望ということで送ってきたマクロは、以下のようなものでした。
Dim myData() As String
Private Sub cmdSearch_Click()
Dim c As Long
Dim addRow As Integer
Dim Flag1 As Boolean
Dim Flag2 As Boolean
lsbSearchResult.Clear
If txtSearchText.Value = “” Then
MsgBox “検索する文字列を入力してください”, vbExclamation, “入力エラー”
txtSearchText.SetFocus
&nb
sp;Exit Sub
End If
For c = LBound(myData, 2) To UBound(myData, 2)
‘英語の検索
If InStr(1, myData(0, c), txtSearchText.Text) > 0 Then
Flag1 = True
Else
Flag1 = False
End If
‘日本語の検索
If InStr(1, myData(1, c), txtSearchText.Text) > 0 Then
Flag2 = True
Else
Flag2 = False
End If
‘英語列(Flag1)または日本語列(Flag2)でヒットしている場合、リストボックスにデータを追加する
If Flag1 = True Or Flag2 = True Then
lsbSearchResult.AddItem myData(0, c)
addRow = lsbSearchResult.ListCount – 1
lsbSearchResult.List(addRow, 1) = myData(1, c)
End If
Next
End Sub
これでも、目的はきちんと達成できているのだからこれでもよいのですが。
僕が提案した形は、以下のものでした。
Dim myData() As String
Private Sub cmdSearch_Click()
Dim c As Long
Dim addRow As Integer
lsbSearchResult.Clear
If txtSearchText.Value = “” Then
MsgBox “検索する文字列を入力してください”, vbExclamation, “入力エラー”
txtSearchText.SetFocus
Exit Sub
End If
For c = LBound(myData, 2) To UBound(myData, 2)
If func(c, myData, txtSearchText.Text) Then ‘[1]
lsbSearchResult.AddItem myData(0, c)
addRow = lsbSearchResult.ListCount – 1
lsbSearchResult.List(addRow, 1) = myData(1, c)
End If
Next
End Sub
Private Function func(idx As Long, ary() As String, st As String) As Boolean
func = InStr(ary(0, idx), st) + InStr(ary(1, idx), st) > 0 ‘[2]
End Function
変数 addRow への値の格納のロジックや変数 myData の宣言等、追求すればまだいろいろ直すところはありますが…。
まずはこんな感じ。
もっとも、[1] のところは、同様の比較をする箇所が何度も登場するわけではないので、
End If
と書いてしまえば済むところではあったのですが。(そうすると、Functionプロシージャは不要になる)
今後、いろいろ応用の利く力をつけていただければ、と思いまして。
func = InStr(ary(0, idx), st) + InStr(ary(1, idx), st) > 0 ‘[2]
End Function
の、[2]のような書き方を学んでもらうべく、あえて趣向を凝らして、こんな提案をしてみました。
Boolean型の戻り値を返す Function プロシージャが、比較演算の結果を取得してすぐにその結果を返す、というのがここでのポイント(笑
受取人の If 文は、すぐにその戻り値を使って処理を継続。
受講生の方からは、
先生のFunctionプロ―シージャーを見て、心の中で「うぉぉ!」と叫んでしまいました。(笑
とのことでした (^^;
あと、別の考え方として。
[1] のところは、
If func(myData(0, c), myData(1, c), txtSearchText.Text) Then
End If
として、呼び出される関数は、
Private Function func(s1 As Long, s2 As String, st As String) As Boolean
func = InStr(s1, st) + InStr(s2, st) > 0
End Function
としてもよいと思います。
処理速度的にどっちのほうが早いかはよく分かりませんが、なんとなく、こちらのほうが早い気はします。
ただ、ゴチャゴチャしたお願いごとは、サブルーチンに渡してしまったほうがメインプロシージャの可読性が高くなりますし。
呼び出し元のIf文の中がすっきりする分、添削例のほうが若干可読性が高い感じがします。
(とはいえ、それも、好みかとも思いますが…。)