エクセルVBAーーーSPLIT編(Split)メールから項目の抜き出し(2)

具体的な手順として,メール文面の空白・改行を除いて,buffer 等の変数に入れるのは同じです。

buffer="————————————————————▼送信内容————————————————————お名前=佐藤太郎ご所属=自宅ご所属先電話=00000000000メールアドレス=xxxyyy@dummy.com申し込み種別=会員所属支部=ロサンゼルス県登録番号=00999会員番号=10000999————————————————————送信日時:2024/09/28(Sat) 19:22:00"

次に,必要のない頭とお尻の部分を次のようにして除きます。

buffer1="------------------------------------------------------------送信日時"
buffer = Mid(Honbun, InStr(Honbun, "お名前=")) '「お名前=」以前の項目を消す
buffer = Left(buffer, InStr(buffer, buffer1) - 1) 'buffer1の部分を消去

 ’ buffer1に当てはまる部分を消去

これで,buffer の中身は,

buffer="お名前=佐藤太郎ご所属=自宅ご所属先電話=00000000000メールアドレス=xxxyyy@dummy.com申し込み種別=会員所属支部=ロサンゼルス県登録番号=00999会員番号=10000999"

になります。これをさらに,「=」を区切りで,split で分割して,配列にいれます。

preArray = Split(buffer, "=")

こうすると,preArray の配列に次のように格納されます。項目の値は架空のものです。

preArray(0)="お名前"
preArray(1)="佐藤太郎ご所属"
preArray(2)="自宅ご所属先電話"
preArray(3)="00000000000メールアドレス"
preArray(4)="xxxyyy@dummy.com申し込み種別"
preArray(5)="会員所属支部"
preArray(6)="ロサンゼルス県登録番号"
preArray(7)="00999会員番号"
preArray(8)="10000999"

この格納の様子を見ると,目的の項目の値,例えば「お名前」はpreArray(0)に入ってますが,その値は「お
名前」の入ってる次の配列(preArray(1))に格納されています。つまり項目の値を見るには,配列の
引数+1にすればいいことになります。そこで,あらかじめ予想される項目を入れた配列をもとに,preArray 
の配列のどこに項目があるか検索します。項目の順番を催しによって変更する可能性があるからです。

koumokuArray = Array("お名前", "ご所属", "電話", "メールアドレス", "申し込み種別", "所属支部", "登録番号", "会員番号", "住所", "郵便番号", "参加資格")
For j = LBound(koumokuArray) To UBound(koumokuArray)
 If InStr(preArray(i), koumokuArray(j)) > 0 Then
  nukidasi = preArray(i + 1) '目的の項目の値は +1の配列に格納されている
  koumoku = koumokuArray(j)
  Exit For '見つかった時ループを抜ける
 End If
Next j

検索して該当する引数が見つかったら,引数+1して,項目の値を取得して,一時変数 nukidasi に格納し
ます。同時に検索した項目も,koumoku に格納します。ただ,まだ,nukidasi には,

佐藤太郎ご所属

のように,次番の項目も一緒に格納されいているので,

 For k = LBound(koumokuArray) To UBound(koumokuArray) '余分な項目を除く
  nukidasi = Replace(nukidasi, koumokuArray(k), "")
 Next k

のようにして,該当する項目を削除します。その後,koumoku に応じた外部変数に Select Case にて
記憶します。それぞれのケースでは,「県」「支部」「都」を除く処理や,文字長を制限する処理もしてあり
ます。

Select Case koumoku
  Case "お名前"
    simei = nukidasi
  Case "ご所属"
    syozoku = nukidasi
     If Len(syozoku) > 20 Then
       syozoku = Mid(syozoku, 1, 20)
     End If
  Case "電話"
    denwa = nukidasi
  Case "メールアドレス"
     adoresu = nukidasi
  Case "申し込み種別"
     syubetu = nukidasi
  Case "所属支部"
     sibu = nukidasi
     sibu = Replace(sibu, "支部", "")
     sibu = Replace(sibu, "県", "")
     If sibu <> "京都" Then
      sibu = Replace(sibu, "都", "")
     End If
  Case "登録番号"
    bangou = nukidasi
  Case "会員番号"
    kaiin_bangou = nukidasi
  Case "郵便番号"
    yubin = nukidas
  Case "住所"
    jyuusyo = nukidasi
  Case "参加資格"
    sanka_sikaku = nukidasi
End Select

以上が処理の流れですが,これをサブとして呼び出せるようにしてあります。以下が全文です。


Private Sub mail_koumoku_nukidasi(Honbun As String)
    Dim preArray As Variant
    Dim koumokuArray() As Variant
    Dim buffer, buffer1, nukidasi,koumoku As String
    Dim i, j, k As Integer
    
    '最終項目の後の文字
    buffer1 = "------------------------------------------------------------送信日時"
    '予想される項目
    koumokuArray = Array("お名前", "ご所属", "電話", "メールアドレス", "申し込み種別", "所属支部", "登録番号", "会員番号", "住所", "郵便番号", "参加資格")
  
    '本文前処理
    buffer = Mid(Honbun, InStr(Honbun, "お名前="))              '「お名前=」以前の項目を消す
    buffer = Left(buffer, InStr(buffer, buffer1) - 1)           '最終項目以下を消す
    buffer = Replace(buffer, "ご所属先電話", "電話")            '「ご所属」と「ご所属先電話」検索で区別が付かないので,置き換え
    
    preArray = Split(buffer, "=")                              '"="を区切りで分割
     
    For i = LBound(preArray) To UBound(preArray) - 1
       For j = LBound(koumokuArray) To UBound(koumokuArray)
        If InStr(preArray(i), koumokuArray(j)) > 0 Then
                    nukidasi = preArray(i + 1)                    '目的の項目は +1の配列に格納されている
                    koumoku = koumokuArray(j)          '項目の保持
                    Exit For                                      '見つかった時ループを抜ける
           Exit For
        End If
       Next j
       
       For k = LBound(koumokuArray) To UBound(koumokuArray)        '余分な項目を除く
            nukidasi = Replace(nukidasi, koumokuArray(k), "")
       Next k
        '項目に応じた変数に格納する
        Select Case koumoku
            Case "お名前"
                simei = nukidasi
            Case "ご所属"
                syozoku = nukidasi
                If Len(syozoku) > 20 Then
                    syozoku = Mid(syozoku, 1, 20)
                End If
            Case "電話"
                denwa = nukidasi
            Case "メールアドレス"
                adoresu = nukidasi
            Case "申し込み種別"
                syubetu = nukidasi
            Case "所属支部"
                sibu = nukidasi
                sibu = Replace(sibu, "支部", "")
                sibu = Replace(sibu, "県", "")
                If sibu <> "京都" Then
                    sibu = Replace(sibu, "都", "")
                End If
            Case "登録番号"
                bangou = nukidasi
            Case "会員番号"
                kaiin_bangou = nukidasi
            Case "郵便番号"
                yubin = nukidas
            Case "住所"
                jyuusyo = nukidasi
            Case "参加資格"
                sanka_sikaku = nukidasi
        End Select
        
    Next i
    
End Sub

自分なりに作成しましたが,きっと,もっとうまい方法があるんでしょうね。

エクセルVBAーーーSPLIT編(Split)メールから項目の抜き出し(1)

お仕事お手伝いの関係で,引き続きVBAをいじってます。

ある催しの受付処理をするのにHPのスクリプトから送られてくるメールを半自動で処理しています。処理に
は,エクセルのVBAを使ってます。次のようなメールが送られてきます。

〓このメールは自動送信でお送りしています。
以下のとおりフォームメールより送信がありました。
————————————————————
▼送信内容
————————————————————
お名前 = 佐藤太郎
ご所属 = 自宅
ご所属先電話 = 00000000000
メールアドレス = xxxyyy@dummy.com
申し込み種別 = 会員
所属支部 = ロサンゼルス県
登録番号 = 00999
会員番号 = 10000999
————————————————————
送信日時 : 2024/09/28(Sat) 19:22:00

このメールから,VBAで,お名前等に該当する佐藤太郎等を切り出し,エクセルの一覧表にしていました。
各項目を取り出しをするのに,次のようにしていました。

simei = Mid(Honbun, InStr(Honbun, "お名前=") + 4, InStr(Honbun, "ご所属=") - InStr(Honbun, "お名前=") - 4)

前処理で,空白と改行を除いたメール文面を Honbun に文字列として取り込み,該当する項目と次の項目
ではさむようにして目的のものをとりだしてました。
送られてくるメールの項目の順番や項目が同じならいいのですが,今回のように,項目の順番が変わってし
まうと,VBAのプロシャージャの方も変更しなくてはいけません。
そこで,メールの項目・順番が変わってもも,プロシャージャを変更しなくてもいいようにできないかとあ
れこれ,なやんでました。
昨日あれこれ悩んで,検索して,たどりついて解決にむすびついた,Split を使ってできそうなアルゴリズ
ム(そんな大それたものではないのですが・・・),手順をおもいつきましたので,備忘録がてら,まとめ
ておきたいと思います。

エクセルVBA-エラー処理

プログラムを作り始めて何年になるでしょうかね。就職して,2年目からですから,結構な年月になります。
当時は,PCのはじめで,やりたいことのほとんどは,BASIC と呼ばれる言語で,自作しないといけませんでし
た。そのうち,MS-DOS上で動くマルチプランやらwindoesで動くロータス123等がでてきました。確か,
ロータス123は,当時68000円か78000円ぐらいしたと記憶していました。おまけに,123は,
プロテクトがかけられていて,バックアップができませんでした。その後,コピーツール等がでてきて,バッ
クアップはできるようになりました。
それにしても,高かったです。ただ,自分でもプログラムを作ってましたので,それが作成されるまでの労力
を考えると,決して高くないと思ってました。素人の自分が作るプログラムと,その高いプログラムはどこが
ちがうのでしょうか。もちろん完成度もあるのですが,素人とプロでは,エラー処理が格段に違います。プロ
は,考えるすべてのエラー処理をしていますが,素人の私が作るものは,動けばいい,というレベルのもので
す。
ただ,作るにあたっては,最低限の処理が必要になります。たとえは今,仕事のお手伝い関係で自作している
エクセルvbaのサーチのプロシャージャ(プログラム)でも,目的の項目がサーチできなかった時は,どうす
るかの処理ぐらいは必要になってきます。
そんな訳でエラーの時に,

XFD1048576

を返すものを作りました。この数字はなにかというと,
エクセルの表の最右列・最下段のセルということで,一番端っこのセルの番地を表す数字です。なぜ,この
この数字を使ったのかと言うと,昔BASICでプログラムをくんでいた時のなごりで,エラー処理に普段
出てこない,9999とか言う数字を使った名残です。(確か何年構えに2000年問題ということで,
話題になりましたね。これも。エラー処理に1999という数字を使っていて,ためですね)
ところが,デバックしているときにまたまた,はまりました。わざとエラーを起こしても,XFDが返って
こないのです。返ってくるのは,16384という数字が返ってきてしまいます。あれこれやりましたが,
肝心なこと忘れてました。使ったのは,Column というプロパティですが,当たり前ですが,このプロパテ
ィは,数字を返すものでした。ネット検索で,

Split(Columns(列番号).Address, “$”)(2)

のようにやって,やっと目的のXFDが返ってきました。長かったです。

下記がXFD1048576を返す,関数です,といってもぱくりです。

Public Function Search(ByVal rng As Range, ByVal keyWord As Variant, ByVal Whole As Boolean)
   Dim r As Range
    If Whole Then
        For Each r In rng
            If r.Value = keyWord Then
                Set Search = r
                Exit Function
            End If
        Next
    Else
        For Each r In rng
            If InStr(r.Value, keyWord) > 0 Then
                Set Search = r
                Exit Function
            End If
        Next
    End If

    Set Search = Range("XFD1048576")←←エラー処理です。
            
End Function

デバックに使ったプロシャージャです。

MsgBox Split(Columns(Search(rng, "******", True).Column).Address, "$")(2)

エクセル(関数 文字列の分割 空白区切り)

手伝いでやっている仕事関連で,エクセルをいじっています。疑問点があったので,「教えてGoo」の記事を
みていました。
すると,空白区切りの文字列を分割するには,どうすればいいのか,という,投稿
がありました。

写真のように,一つのセルに入っているデータを空白を区切りに,セルごとに分割したいとのことでした。
VBAを使って,

  〇空白の数を数える。
  〇空白が先頭から何番目にあるか調べる。
  〇先頭から,最初の空白の前までの文字を切り出す。
  〇2番目と3番目の空白の間にある文字を切り出す。
  〇3番目を4番目の空白の間にある文字を切り出す。
  〇4番目と5番目の空白の間にある文字を切り出す。
  〇5番目の空白以降の文字をきりだす。

というようなことをやればできそうに思えましたが,なんと,この作業を1行の関数でおこなってる諸兄がい
ました。

  =TRIM(MID(SUBSTITUTE($B2, ” “, REPT(” “,LEN($B2))),(COLUMN(A1)-1)*LEN($B2)+1, LEN($B2)))

この1行の関数をC2のセルにいれて,Hのセルまでドラグしてコピーすると分割ができてしまうのです。

何をやっているのか,関数をしげしげと並べて,自分なりに解釈してみました。

 REPT(“ ”,LEN($B2))

で,元々文字列分の空白を作ります。
その後,一文字の空白と,文字列長分の空白を入れ替えます。

SUBSTITUTE($B2, ” “, REPT(” “,LEN($B2)))

この入れ替えた,文字列の先頭から,文字をきりだします。

MID(SUBSTITUTE($B2, ” “, REPT(” “,LEN($B2))),(COLUMN(A1)-1)*LEN($B2)+1, LEN($B2))

切り出す際に,

(COLUMN(A1)-1)*LEN($B2)+1

で,どこから切り出すかを決めています。うまい具合に,COLUMN(A1)のA1の部分は,コピーするたびに,

A1→B2→C2→D3→E5

のように,エクセルの方で,相対的に移動してくれます。結果,切り出し開始位置が,文字長分だけずれてくれます。
結果

COLUMN(A1)→1
COLUMN(B1)→2
COLUMN(C1)→3
COLUMN(D1)→4

のようにCOLUMNの値が増えていきますので,切り出し開始位置が文字長だけずれていきますので,一番目,2番目
と切り出すことができるようです。

最後に

TRIM( )

で,余分な空白を削除すれば,完成です。

写真は,空白を「*」に置き換えて表示しています。

しかし,頭の良い方は,考え方がちがうのですね。余分な空白をいれて,一気に切り出して,余分なものを取
り除くことで目的をはたしているのですごいと思いました。

ユーザーフォーム SetFocus VBA エクセル 検索 (2)

間に合わせて作ったVBAが25日の仕事で役に立ちました。いくつか改良点が必要だったので,改良を加えま
した。やはり,複数検索対応が必要で,アクティブセルを目立たせることも使いやすくするためには必要でし
た。どうしようかと思いましたが,リストボックスと組み合わせることで,懸念だった,検索結果の複数項目
を保持することにしました。

上記のようなユーザーフォームで,検索結果をリストボックスに表示するようにしました。結果が単数の場合
はそのまま選択し,複数の場合は,リストボックスで選択するようにしました。
前回・今回のプロシャージャで,使ったのが,Find(keyWord, LookAt:=xlPart) というものですが,これ
は,最初にでてきたものしかヒットしません。前回のプロシャージャでは,FindNext(myCell)との組み合わせ
で,あらかじめ複数検索の対象を把握しておいて,複数検索の対象の場合は,別な検索キーで検索するとい
う,手間をかけてました。リストボックを使うことで,検索結果を全部リストボックスに表示することで,プ
ログラム的にはすっきりしました。検索結果が単数の場合は,リストボックスに表示する必要なないのです
が,複数か単数かの判別をする必要が面倒なので,一律リストボックスに表示して,

複数→選択(手動),単数→プログラムで選択

のようにしました。便利な命令があるのもので,今回のプロシャージャ作成で初めて使いましたが,

sendkeys

というもので,キーボードを押した状態をプログラムで作ることができるものです。今回初めてわかりました
が,もし,以前から分かっていたら,以前作ったプロシャージャももっと楽に作れたかもしれないと思います。
次のような動作をします。ここで使ってる名前は,データ用の架空の名前です。

名前を入力して,リターンキーを押すと,検索結果がリストボックスに表示されると同時に,選択されたセル
が見えるようになります。名前のとなりの数字は,その名前ある行番号です。

ここで矢印キーで選択する項目を移動すると,それにつれて,選択状態になったセルが見えるようになりま
す。選択してリターンキーを押すと,該当する名前のセルが選ばれ,背景が黄色になります。

単数の場合は,リストボックスに表示するのですが,表示と同時にリターンキーを送るので,リストボックは
見えず選択されたなまえの背景が黄色になります。文字の背景をその都度変えているのは,どの項目がアク
ティブになるかの表示でデバック用も兼ねてます。

合わせて,上記のように,アクティブセルの色を変えて,他のセルと区別できるようにしてます。次回,操作
の様子と全プロシャージャを掲載します。

ユーザーフォーム SetFocus VBA エクセル 検索 (3)

動作の様子です。使ってる名前は,データ作成サイトで作成した架空のものです。

以下,プロシャージャの全文です。

 

 

-ThisWorkbook-
Private Sub Workbook_Open()'************************************************
  Application.OnKey "{F3}",   "BK_clere"
End Sub

このサブは,背景色をクリアーする機能を F3キー に割り当てる部分です。

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
  Application.ScreenUpdating = True
End Sub

この部分は,アクティブセルを強調するための記述で,条件付き書式と合わせて設定してます。

-UserForm1-
Dim keyWord As String
Dim myRange As Range
Dim myObj As Range

Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)'***********************************************
  If KeyCode = vbKeyReturn Then
    If ListBox1.ListCount = 0 Then
      UserForm1.TextBox1.SetFocus
      Exit Sub
    Else
     Range(Cells(ListBox1.List(ListBox1.ListIndex, 1), 4).Address).Interior.ColorIndex = 6 (br /)
     'Rangで単一セルを指定の時はaddressが必要
     Cells(ListBox1.List(ListBox1.ListIndex, 1), 4).Select
     Label1.Caption = "検索結果=" & ListBox1.List(ListBox1.ListIndex, 0)
     ListBox1.Clear
     UserForm1.TextBox1.SetFocus
    End If
  End If
  If KeyCode = vbKeyF1 Then
    Range(Cells(ListBox1.List(ListBox1.ListIndex, 1), 4).Address).Interior.ColorIndex = 0
    Cells(ListBox1.List(ListBox1.ListIndex, 1), 4).Select
    Label1.Caption = "検索結果=" & ListBox1.List(ListBox1.ListIndex, 0)
    ListBox1.Clear
    UserForm1.TextBox1.SetFocus
  End If
End Sub

Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)'*************************** 
  Dim K As Integer   
  keyWord = TextBox1.Text

  If KeyCode = vbKeyF1 Then'F1が押されたとき
    ActiveCell.Interior.ColorIndex = 0
    Label1.Caption = "検索結果の削除"
  End If

  If KeyCode = vbKeyReturn Then 'リターンキーが押されたとき
    If keyWord <> "" Then

      K = fukusu_kensaku(keyWord)

      If K > 1 Then
        Label1.Caption = "検索結果=" & "複数該当"
        UserForm1.ListBox1.ListIndex = 0
      Else
        Label1.Caption = "検索結果=" & "一人該当"
        UserForm1.ListBox1.ListIndex = 0
      End If
    UserForm1.TextBox1.Text = ""
    End If

   UserForm1.TextBox1.SetFocus
  End If
End Sub

Private Sub UserForm_Initialize()'************************************************ 
  TextBox1.Text = ""
  With ListBox1
    .ColumnCount = 2
    .ColumnWidths = "120;50"
  End With

  With TextBox1
    .BackColor = RGB(204, 255, 255)
  End With
End Sub

Private Sub UserForm_Activate()'************************************************ 
  UserForm1.TextBox1.SetFocus
End Sub

Private Sub TextBox1_Change()'************************************************ 
  keyWord = TextBox1.Text
End Sub

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)'************************************************ 
  With TextBox1
    .BackColor = RGB(255, 255, 255)
  End With
  With ListBox1
    .BackColor = RGB(204, 255, 255)
  End With
End Sub

Private Sub ListBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'*********************************************
  With TextBox1
    .BackColor = RGB(204, 255, 255)
  End With
  With ListBox1
    .BackColor = RGB(255, 255, 255)
  End With
End Sub

Private Sub ListBox1_Change()'***********************
  If ListBox1.ListCount >= 1 Then
    Cells(ListBox1.List(ListBox1.ListIndex, 1), 4).Select
  End If
End Sub

-Module1-
Sub macro2()'***********************
  UserForm1.Show vbModeless
End Sub

Function fukusu_kensaku(key_word As String) As Integer'***********************
  Dim myRange As Range
  Dim myObj As Range
  Dim keyWord As String
  Dim K As Integer
  Set myRange = Range(Range("D2"), Cells(Rows.Count, 4).End(xlUp))
  keyWord = key_word
  Set myObj = myRange.Find(keyWord, LookAt:=xlPart)
  K = 0

  If myObj Is Nothing Then
    MsgBox "'" & keyWord & "'はありませんでした"
    Exit Function
  End If
  Dim msg As String
  Dim myCell As Range
  Set myCell = myObj
  Do
    K = K + 1

    With UserForm1.ListBox1
      .AddItem myCell.Value
      .List(K - 1, 1) = myCell.Row
    End With
    myCell.Offset(0, -3).Value = keyWord & K '■■■■欄外に記入

    Set myCell = myRange.FindNext(myCell)
  Loop While myCell.Row <> myObj.Row

  If K > 1 Then
    UserForm1.ListBox1.SetFocus
    Call SendKeys("{DOWN}")
    Call SendKeys("{UP}")
  End If
  If K = 1 Then
    UserForm1.ListBox1.SetFocus
    Call SendKeys("{Enter}")
  End If
  fukusu_kensaku = K
End Function

Private Sub BK_clere()'***********************
  ActiveCell.Interior.ColorIndex = 0
End Sub

Public Sub SendKeys(Keys As String, Optional Wait As Boolean = False)'***********************
  Static w As Object '// WshShellオブジェクト
// WshShellオブジェクトが生成されていない場合
  If w Is Nothing Then
'// WshShellオブジェクトを生成
    Set w = CreateObject("WScript.Shell")
  End If

  Call w.SendKeys(Keys, Wait)
End Sub

 

ユーザーフォーム SetFocus VBA エクセル 検索 (1)

お手伝いの仕事?を楽にするため,また,簡単なVBAを作りました。簡単にできるかと思ったのですが,意外
に難航。なかなか思った動作をしてくれません。意図した動作とは,


のようなユーザーフォームで,クリックをしなくても,テキストボックスに入力できるようにするというもの
です。入力できるようにするには,TextBox1.SetFocus という表現をするのですが,どう書き換えても入力
できるようになりませんでした。ネットでくぐってもこの SetFocus のトラブルは結構あるみたいで,いく
つも出てきますが,明確な解決法には,あたりませんでした。 

最初 Private Sub TextBox1_Change() というイベントに関係することを記載していましたが,だめでした。

そこで,

Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)

のイベント処理のところに書いたら,やっと思った動作ができました。
SetFocus の命令は,どこに書いても正しい動作をするのではない,ということが,おぼろげながら分かりま
した。

思った動作とは,

 ユーザフォームを自動で表示(クリックしなくても,テキストボックスに入力できる状態に)
 入力後所定の動作が終わったら,また,テキストボックスに入力できる状態に

ということで,次のようなコードで,思った動作ができました。

Dim keyWord As String
Dim myRange As Range
Dim myObj As Range

Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    Set myRange = Range("D5:D98")
    keyWord = TextBox1.Text
    If KeyCode = vbKeyReturn Then
    Set myObj = myRange.Find(keyWord, LookAt:=xlPart)
    Label1.Caption = "検索結果=「" & myObj.Offset(0, 0).Value & "」" & myObj.Row & "行目"
    myObj.Offset(0, -3).Interior.ColorIndex = 6
    UserForm1.TextBox1.Text = ""
    UserForm1.TextBox1.SetFocus
    End If
    If KeyCode = vbKeyF1 Then
    myObj.Offset(0, -3).Interior.ColorIndex = 0
    Set myObj = Nothing
    Label1.Caption = "検索結果="
    UserForm1.TextBox1.Text = ""
    UserForm1.TextBox1.SetFocus
    End If
   End Sub

Private Sub UserForm_Initialize()
    TextBox1.Text = ""
End Sub

Private Sub UserForm_Activate()
    UserForm1.TextBox1.SetFocus
End Sub

Private Sub TextBox1_Change()
    keyWord = TextBox1.Text
End Sub

 

やっていることは,単に,テキストボックに検索する文字を入力して,検索後,あれば,あった場所の左側の
背景の色を変えるということで,なんのことはありません。エンターキーを押すと,検索して,F1 を押すと
直前に変えた背景をもとに戻すという,単純な動作です。

ただ,今回のものは,検索の対象が,複数ある場合には,対応していません。複数検索に対応させるには,検
索自体はそれほど複雑ではないのですが,背景色を変える対象も複数になるので,それをもとにに戻すとなる
と,背景を変えた場所を何らかの形で記憶していないとだめで,プロシャージャが複雑になりますので,今回
はやめようかと思います。

エクセルVBA(シート選択のエラー処理)–(5)

ファイル名を取得するのに、文字列関数を操作して取り出しましたが、一発で取り出せる関数もあるようで
す。
FSO と呼ばれるものを使う方法で、詳細は、諸兄のHPに譲りたいと思いますが,

fPath は目的のファイルまでのファイル名を含んだフルパス)
  Dim FSO, PathName As String, FileName As String
  Set FSO = CreateObject(“Scripting.FileSystemObject”)

  FileName = FSO.GetFileName(fPath)・・・・・・ファイル名だけを取り出す。
  PathName = FSO.GetParentFolderName(fPath)・・・・・・パスだけ取り出す。

ただ自分自身(マクロを記載したBOOK)の場合は次のようにして求めるようです。

  ThisWorkbook.Name・・・・自分自身のファイル名
  ThisWorkBook.FullName・・・自分自身のフルパス

ちなみに、

   FileName = FSO.GetFileName(ThisWorkbook)・・・・エラー

のようにファイル名を求めようとするとエラーになります。VBA が良く分かっている方ならこんなことなさ
らないのでしょうがまだまだ勉強中の私にとって、ちょっと ? になります。ただ、下記のようにするとき
ちんとファイル名を求められます。でも、ThisWorkbook.Name でファイル名を求めることができるので、
意味ないですね。

   FileName = FSO.GetFileName(ThisWorkbook.FullName)・・・取得可

ただ、自分自身(マクロが書かれているファイル)のファイル名を求める場面は、それほど多くないかなと思います。

エクセルVBA(シート選択のエラー処理)–(4)

作ったプロシャージャを動かして、シートを選択している様子です。リストボックスのシート名をクリックすると、クリックしたシートに移動します。

どのシートが選ばれたかは、リストボックスの IndexID でわかります。Worksheets( IndexID).Name で、選択されたシート名を表示できます。それほど使う場面はないかとは思いますが、使う時は、便利な機能のよ
うな気がします。

エクセルVBA(シート選択のエラー処理)–(3)

以下は、VBA 標準モジュールに記載したプロシャージャです。
Sub ボタン2_Click() は、シートに貼り付けてある、マクロ起動用のものです。
Function sheets_set(Wb As Workbook) の中身は、本来ユーザーフォームの _Initialize()の項目に記入すべきでしょうが、Wb の引き渡し方法がわからないので、こちらに書きました。

---------------
Sub ボタン2_Click()
  Call Select_sheet
End Sub
---------------
Function Select_sheet()
  ‘====読み込みフルパスファイル名の取得====
  Dim fPath As Variant
  Dim fType, prompt As String

  fTyp = “Excelファイル(*.xlsm),*.xlsm,Excelファイル(*.xlsx),*.xlsx,Excelファイル(*.xls),*.xls”
  prompt = “Excelファイルを選択してください”
  fPath = Application.GetOpenFilename(fTyp, , prompt)

  If fPath = False Then
    MsgBox “ファイルが選択されていません。”
    Exit Function
  End If

  ‘====読み込みのファイル名取り出し====
  Dim STR As String
  Dim t_file_name As String

  STR = StrReverse(fPath)
  t_file_name = Right(fPath, InStr(STR, “\”) – 1)

  ‘====ファイルを開く処理====
  Dim Wb As Workbook

  If ThisWorkbook.FullName <> fPath Then
    If fPath <> “” Then

    For i = 1 To Workbooks.Count
      If Workbooks(i).Name = t_file_name Then
        BookFlag = True
      End If
    Next i

    If BookFlag <> True Then
      MsgBox “ファイルを開きます。”
      Set Wb = Workbooks.Open(fPath, UpdateLinks:=Ture, ReadOnly:=Ture)

      Call sheets_set(Wb)
      UserForm1.Show vbModeless
    Else
      MsgBox “すでに開いているファイルを開こうとしてます。”
      Exit Function
    End If
    End If
  Else
    MsgBox “自分自身を開こうとしてます。”
    Exit Function
  End If
End Function
-------------------------------------------
Function sheets_set(Wb As Workbook)
  Dim i As Integer

  With UserForm1.ListBox1
    ‘一つだけ選択
    .MultiSelect = fmMultiSelectSingle
  End With

  For i = 1 To Wb.Worksheets.Count
    UserForm1.ListBox1.AddItem (Wb.Worksheets(i).Name)
  Next

  UserForm1.ListBox1.ListIndex = 0
End Function


以下は、ユーザーフォームの方に記載したものです。

-------------------------
Private Sub CommandButton1_Click()
  ThisWorkbook.Activate
  Unload UserForm1
End Sub
-------------------------
Private Sub ListBox1_Click()
  sh_name = ListBox1.List(ListBox1.ListIndex)
  TextBox1.Text = sh_name
  Worksheets(sh_name).Activate
End Sub
----------------------------------------------
Private Sub ListBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
  If KeyCode = vbKeyReturn Then
    KeyCode = 0
    ThisWorkbook.Activate
    Unload Me
  End If
End Sub
----------------------------------------------
Private Sub UserForm_Initialize()
  With ListBox1
  ‘一つだけ選択
  .MultiSelect = fmMultiSelectSingle
  End With
End Sub