年賀状ソフトなどで良く見かける「ふりがな自動入力」です。ユーザーフォーム上で氏名や住所等のカナ漢字変換での入力したカナ文字を「横取り」して「フリガナ」の項目に表示します。
ふりがなの取得には複数の方法があります。
ユーザーフォーム上でのふりがな取得だとしても複数の方法が考えられます。
・このページのようにIMEを強引に操作する方法
・シート上で「PHONETIC関数」を使って代行させる方法
などです。
このページで紹介している方法は、IMEの種類やバージョンによって正しく動作しないことも考えられますのでご注意下さい。
表示されるフォームの「住所」にIMEで漢字を入力すると「フリガナ」が自動的に表示されます。(※Excel2000以降でのみ動作します。)

(この画像をクリックすると、ダウンロードができます。)
これもかなり込み入ったAPI利用ですが、「modPoneticTextBox」をインポートしてユーザーフォームの4カ所に呼び出す記述を加えるだけで利用可能です。
AddressOf演算子の利用例で、IMEから入力情報をフックします。作成は難しいですが、共通モジュール化しているので、モジュールをインポートすれば転用は簡単です。

これは、VBEのプロジェクトエクスプローラです。「modPoneticTextBox」が「ふりがな自動入力」部分です。ユーザーフォーム上のテキストボックスで処理するのであれば、このまま他にも利用できます。
ユーザーフォームのコードです。
'*******************************************************************************
' フリガナの取得 ※ユーザーフォームのイベント記述
'
' 作成者:井上治 URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'*******************************************************************************
Option Explicit
'*******************************************************************************
' 「住所」のEnterイべント
'*******************************************************************************
Private Sub TextBox2_Enter()
' フリガナ監視TextBoxの設定
Call GP_PoneticSetEdit(TextBox2, TextBox1) ' @
End Sub
'*******************************************************************************
' 「住所」のExitイべント
'*******************************************************************************
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' フリガナ監視TextBoxの解放
Call GP_PoneticResetEdit ' A
End Sub
'*******************************************************************************
' ユーザーフォームの初期化
'*******************************************************************************
Private Sub UserForm_Activate()
TextBox1.Text = ""
TextBox2.Text = ""
End Sub
'*******************************************************************************
' ユーザーフォームの初期処理
'*******************************************************************************
Private Sub UserForm_Initialize()
' フリガナ監視の開始
Call GP_PoneticInitialize(Me) ' B
End Sub
'*******************************************************************************
' ユーザーフォームの終了処理
'*******************************************************************************
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
' フリガナ監視の終了
Call GP_PoneticTerminate
' C
ThisWorkbook.Saved = True
End Sub
このように4つの「
Call」を行なうだけで実現できます。
- @
- 「住所」のテキストボックスのEnterイベントで、IME監視するテキストボックスとフリガナをセットするテキストボックスを指定します。(GP_PoneticSetEdit)
- A
- 「住所」のテキストボックスのExitイベントで、IME監視設定を解除します。(GP_PoneticResetEdit)
- B
- ユーザーフォームの初期化処理で、IME監視を立ち上げます。内部でウィンドウのハンドルを取得するため、ユーザーフォーム自身を引数としています。(GP_PoneticInitialize)
- C
- ユーザーフォームの終了処理で、IME監視を終了します。(GP_PoneticTerminate)
こちらが呼び出されている「
modPoneticTextBox」です。
'*******************************************************************************
' フリガナの取得 ※TextBoxのIME操作情報から半角フリガナを別のTextBoxに表示する
'
' 作成者:井上治 URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'*******************************************************************************
Option Explicit
Private Const WM_IME_COMPOSITION = &H10F
Private Const WM_CHAR = &H102
Private Const WM_KEYUP = &H101
Private Const GCS_RESULTREADSTR = &H200
Private Const GCS_RESULTSTR = &H800
Private Const GWL_WNDPROC = (-4)
Private Const g_cnsConvMode As Long = vbKatakana + vbNarrow ' 半角カナ
'Private Const g_cnsConvMode As Long = vbKatakana + vbWide ' 全角カナ
' ■IME,Ponetic操作関連関数
' 変換中の文字列の情報を取得
Private Declare Function ImmGetCompositionString Lib "IMM32.dll" _
Alias "ImmGetCompositionStringA" _
(ByVal hIMC As Long, _
ByVal dw As Long, _
lpv As Any, _
ByVal dw2 As Long) As Long
' IMEのOpenステータスを取得
Private Declare Function ImmGetOpenStatus Lib "IMM32.dll" _
(ByVal hIMC As Long) As Long
' IMEのハンドルを取得
Private Declare Function ImmGetContext Lib "IMM32.dll" _
(ByVal hWnd As Long) As Long
' 取得したIMEのハンドルを解放
Private Declare Function ImmReleaseContext Lib "IMM32.dll" _
(ByVal hWnd As Long, ByVal hIMC As Long) As Long
' ■ウィンドウ操作関数
' 指定ウィンドウの属性(プロシージャ)を書き換える
Private Declare Function SetWindowLong Lib "USER32.dll" _
Alias "SetWindowLongA" _
(ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
' Windowsメッセージを指定のウィンドウプロシージャに渡す(サブクラス化)
Private Declare Function CallWindowProc Lib "USER32.dll" _
Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, _
ByVal hWnd As Long, _
ByVal msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
' ウィンドウハンドルの取得
Private Declare Function FindWindow Lib "USER32.dll" _
Alias "FindWindowA" _
(ByVal lpClassName As Any, _
ByVal lpWindowName As Any) As Long
' 子ウィンドウのハンドルを取得(位置は利用しない)
Private Declare Function ChildWindowFromPoint Lib "USER32.dll" _
(ByVal hWndParent As Long, _
ByVal xPoint As Long, _
ByVal yPoint As Long) As Long
' フォーム側情報の格納関数
Private g_objSrcTextBox As MSForms.TextBox ' 日本語入力TextBox
Private g_objDstTextBox As MSForms.TextBox ' フリガナをセットするTextBox
Private g_lngSubHwnd As Long ' フォーム上サブウィンドウのハンドル
Private g_lngPrevWndFunc As Long ' 直前のウィンドウプロシージャ
Private g_blnPoneticSW As Boolean ' 処理開始スイッチ
Private g_blnDupSW As Boolean ' 処理輻輳抑制スイッチ
'*******************************************************************************
' Public処理
'*******************************************************************************
' ○フリガナ監視の初期化処理
'*******************************************************************************
Public Sub GP_PoneticInitialize(objForm As MSForms.UserForm)
Dim lngHwnd As Long
Dim lngHwnd_Sub As Long
' フォームウィンドウのハンドルを取得
lngHwnd = FindWindow("ThunderDFrame", objForm.Caption)
' フォーム上の透明サブウィンドウのハンドルを取得
lngHwnd_Sub = ChildWindowFromPoint(lngHwnd, 0&, 0&)
' IMEフリガナ監視開始処理
Call GP_StartPonetic(lngHwnd_Sub)
End Sub
'*******************************************************************************
' ○IMEフリガナ監視終了処理(引数はダミー → ツールバーの「マクロ」に表示させない)
'*******************************************************************************
Public Sub GP_PoneticTerminate(Optional strDummy As String)
' 現在「監視中」か判断
If g_blnPoneticSW = True Then
If ((g_lngPrevWndFunc <> 0&) And (g_lngSubHwnd <> 0&)) Then
' 直前のWindowProcessを呼び戻す(サブクラス化終了)
SetWindowLong
g_lngSubHwnd, GWL_WNDPROC, g_lngPrevWndFunc
DoEvents
End If
g_lngPrevWndFunc = 0&
g_lngSubHwnd = 0&
' 対象TextBoxの解放
Set g_objSrcTextBox = Nothing
Set g_objDstTextBox = Nothing
' 終了
g_blnPoneticSW = False
End If
End Sub
'*******************************************************************************
' ○処理対象TextBoxの設定(引数はSourceTextBox, DestinationTextBox)
'*******************************************************************************
Public Sub GP_PoneticSetEdit(objTxtSrc As MSForms.TextBox, _
objTxtDest As MSForms.TextBox)
' 対象TextBoxをモジュールレベル変数に格納
Set g_objSrcTextBox = objTxtSrc
Set g_objDstTextBox = objTxtDest
End Sub
'*******************************************************************************
' ○処理対象TextBoxの解除(引数はダミー → ツールバーの「マクロ」に表示させない)
'*******************************************************************************
Public Sub GP_PoneticResetEdit(Optional strDummy As String)
' フリガナの初期化判定
If Not ((g_objSrcTextBox Is Nothing) And _
(g_objDstTextBox
Is Nothing)) Then
' 漢字項目がブランクならフリガナもブランクにする
If g_objSrcTextBox.Text = "" Then g_objDstTextBox.Text = ""
End If
' 対象TextBoxの解放
Set g_objSrcTextBox = Nothing
Set g_objDstTextBox = Nothing
End Sub
'*******************************************************************************
' Private処理
'*******************************************************************************
' IMEフリガナ監視開始処理
'*******************************************************************************
Private Sub GP_StartPonetic(lngHwnd As Long)
' Terminateを忘れている場合の処理
If g_blnPoneticSW = True Then GP_PoneticTerminate
' フォームのサブウィンドウのハンドルをモジュール変数に格納
g_lngSubHwnd = lngHwnd
' モジュールレベル変数の初期化
Set g_objSrcTextBox = Nothing
Set g_objDstTextBox = Nothing
g_lngPrevWndFunc = 0&
If g_lngSubHwnd <> 0& Then
' IMEフリガナ監視起動(サブクラス化開始)
g_lngPrevWndFunc = SetWindowLong(g_lngSubHwnd,
_
GWL_WNDPROC,
_
AddressOf FP_PoneticWindowProc)
DoEvents
End If
' 「監視中」のスイッチセット
g_blnPoneticSW = True
End Sub
'*******************************************************************************
' CallBack(AddressOf関数)ウィンドウ処理(IMEフリガナ監視起動)
'*******************************************************************************
Private Function FP_PoneticWindowProc(ByVal lngHwnd As Long, _
ByVal lngMsg As Long, _
ByVal lngwParam As Long, _
ByVal lnglParam As Long) As Long
Dim lngHIMC As Long
Dim lngSize As Long
Dim tblByte() As Byte
Dim strTEXT As String
Dim strText1 As String
Dim strText2 As String
Dim strFurigana As String
Dim lngMode As Long
If g_blnDupSW = False Then
g_blnDupSW = True
If Not ((g_objSrcTextBox Is Nothing) And _
(g_objDstTextBox
Is Nothing)) Then
Select Case lngMsg
' IME入力中にフリガナを得る
Case WM_IME_COMPOSITION
' IMEのハンドルを取得
lngHIMC
= ImmGetContext(lngHwnd)
' 変換中の文字列のサイズを取得
lngSize
= ImmGetCompositionString(lngHIMC, _
GCS_RESULTSTR,
_
ByVal 0&, 0&)
ReDim tblByte(lngSize)
' 変換中の文字列を取得(バイト配列)
Call ImmGetCompositionString(lngHIMC, _
GCS_RESULTSTR,
_
tblByte(0), lngSize)
' バイト配列をテキストに変換
strTEXT
= tblByte()
strText1
= StrConv(strTEXT, vbUnicode)
' 入力された文字があるか判断
If Not strText1 = vbNullString Then
' 変換中の文字列のサイズを取得
lngSize
= ImmGetCompositionString(lngHIMC, _
GCS_RESULTREADSTR,
_
ByVal 0&, 0&)
ReDim tblByte(lngSize)
' 変換中の文字列を取得(バイト配列)
Call ImmGetCompositionString(lngHIMC, _
GCS_RESULTREADSTR,
_
tblByte(0), lngSize)
' バイト配列をテキストに変換
strTEXT
= tblByte()
strText2
= StrConv(strTEXT, vbUnicode)
' 追加する文字種の判断
If FP_CheckString(StrConv(strText1, vbNarrow)) Then
strTEXT
= strText1
Else
strTEXT
= strText2
End If
' 追加テキストを作成
strFurigana
= StrConv(Left$(strTEXT, Len(strTEXT) - 1), _
g_cnsConvMode)
' 挿入位置を判断(カーソル位置=中途での選択は末尾に追加となる)
If g_objSrcTextBox.SelStart > 0 Then
' 末尾に追加
g_objDstTextBox.Text = g_objDstTextBox.Text & strFurigana
Else
' 先頭に追加
g_objDstTextBox.Text
= strFurigana & g_objDstTextBox.Text
End If
End If
' 取得したIMEのハンドルを解放
ImmReleaseContext
lngHwnd, lngHIMC
'半角英数(直接入力)
Case WM_CHAR
' IMEのハンドルを取得
lngHIMC
= ImmGetContext(lngHwnd)
' 半角入力モード
If ImmGetOpenStatus(lngHIMC) = 0& Then
' 制御キャラクタは無視
If lngwParam >= 32 Then
' 変換モードが全角なら全角に変換
If g_cnsConvMode = vbNarrow Then
g_objDstTextBox.Text
= g_objDstTextBox.Text & _
Chr$(lngwParam)
Else
g_objDstTextBox.Text = g_objDstTextBox.Text & _
StrConv(Chr$(lngwParam),
vbWide)
End If
End If
End If
' 取得したIMEのハンドルを解放
Call ImmReleaseContext(lngHwnd, lngHIMC)
'操作キー(連動消去)
Case WM_KEYUP
If ((lngwParam = vbKeyBack) Or _
(lngwParam
= vbKeyDelete)) Then ' キーでの削除監視
If g_objSrcTextBox.Text = "" Then
g_objDstTextBox.Text
= ""
End If
End If
End Select
End If
g_blnDupSW = False
End If
' 自身のウィンドウプロシージャを呼び出す
FP_PoneticWindowProc = CallWindowProc(g_lngPrevWndFunc,
_
lngHwnd,
_
lngMsg,
_
lngwParam,
_
lnglParam)
End Function
'*******************************************************************************
' 全て半角文字かチェック
'*******************************************************************************
Private Function FP_CheckString(strTEXT As String) As Boolean
Dim IX As Long
Dim lngCode As Long
FP_CheckString = False
For IX = 1 To Len(strTEXT)
lngCode = Asc(Mid$(strTEXT,
IX, 1))
' 全角文字であればFalseで脱出
If ((lngCode < 0) Or (lngCode > 255)) Then Exit Function
Next IX
FP_CheckString = True
End Function
こちらの内容は理解しなくても、上のサンプルのように利用することができます。
これだけの記述でふりがな自動入力は実現します。
AddressOf演算子は
VisualBasicでも「6.0」以降でサポートされるようになったもので、Excelも
「97」以前では動作しません。
なお、
ワークシートでの「ふりがな自動入力」は、
Excel自身に「
PHONETIC関数」があるため、はるかに簡単に実現します。但し、計算式を置いてしまうとふりがな自身の修正ができないため、シートの
Changeイベントを利用して入力セルに転記させる必要があります。
 |
←HURIGANA1.EXE
(68KB) |