3日がかりのその仕事、3分で終わらせる方法教えます!
パソコンスキルの心技体

二次元配列の要素について、 Instr 関数を使って調査する – Excel マクロ・VBA

2012年1月1日
  • このエントリーをはてなブックマークに追加
  • follow us in feedly

エクセルマクロ・VBA達人養成塾 小川です。

キューバ旅行記、その72です。

キューバ屈指の外人向けリゾート地、バラデロにて。

むっちゃくちゃステキな、朝のカリブ海のビーチ。

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ

エクセルマクロ達人養成塾塾長ブログ
塾長のキューバ旅行記、最初から読みたい方はこちらから


二次元配列の要素について、 Instr 関数を使って調査する – Excel マクロ・VBA

というわけで。

前回まで書いてきたいろいろを考慮して、シリーズの最終版です。

「If True Then」なんて書き方でテスト

一行の中に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列に含むリストの一覧を取得したいということで。

受講生が添削希望ということで送ってきたマクロは、以下のようなものでした。

Option Explicit

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

これでも、目的はきちんと達成できているのだからこれでもよいのですが。

僕が提案した形は、以下のものでした。

Option Explicit

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] のところは、同様の比較をする箇所が何度も登場するわけではないので、

If InStr(myData(0, c), txtSearchText.Text) + InStr(myData(0, c), txtSearchText.Text) > 0 Then ‘[1]

End If

と書いてしまえば済むところではあったのですが。(そうすると、Functionプロシージャは不要になる)

今後、いろいろ応用の利く力をつけていただければ、と思いまして。

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

の、[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文の中がすっきりする分、添削例のほうが若干可読性が高い感じがします。

(とはいえ、それも、好みかとも思いますが…。)

キーワード

コメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

最新の記事

人気記事

最新記事

カテゴリ

最新コメント

タグクラウド