VBA UserFormのテキストボックス文字列縦位置を調整する

前回記事で、「ユーザーフォームに配置したテキストボックスの文字列が上付き固定配置になっているのを矯正したい」と思いました。ということで、何とか縦位置の「上下中央揃え」や「下揃え」にならないか検討していきたいと思います。

くるみこ
くるみこ

今回は「テキストボックス」文字列の縦配置をどうすれば変更できるようになるのかを一緒に検討していきましょう! Webで検索して調べていると、色々な情報を知ることができて勉強になりますよ(^^)/

ワークシートに設置した「テキストボックス」の文字列は縦配置を変更できるのに「ユーザーフォーム」ではダメなんですよね。よろしくお願いします!

【この記事でわかること
・ユーザーフォームに設置したテキストボックス文字列の縦上下中央揃え方法
・TypeName関数の使い方とTextBoxの特定方法がわかります
・ループ処理中にコントロール(TextBox)を配列に入れる方法がわかります

前回記事のおさらいは、下のカードをクリックすれば開きます(^^ゞ

くるみこ
くるみこ

前回記事は、ユーザーフォームに設置したテキストボックスの利用方法について解説しています。よければ覗いてみてね(^^)/

テキストボックスの文字列縦表示位置を変更したい

初めに文字列表示に関するプロパティを確認しましょう。

テキストボックス文字列表示に関するプロパティを確認します

Fontプロパティ

・テキストボックスで使用する文字列のフォントを設定します。
・項目の右端にあるボタンをクリックすると、フォント設定ウインドウが表示されます。
・フォント名やスタイル、サイズなどを設定できます。
・初期値のフォントサイズは「9」です。

TextAlignプロパティ

・テキストボックス内の文字列の配置を(横方向のみ)設定できます。

定数配置
fmTextAlignLeft1左揃え(既定値)
fmTextAlignCenter2中央揃え
fmTextAlignRight3右揃え

テキストボックスの配置とサイズのプロパティ

プロパティ内容
Heightテキストボックスの高さをポイント単位で設定します
Leftユーザーフォームの左端からの位置をポイント単位で設定します
Topユーザーフォームの上端からの位置をポイント単位で設定します
Widthテキストボックスの幅をポイント単位で設定します

テキストボックス文字列をフォントサイズで調整

前回記事のフォントをサイズ変更して縦位置を調整してみます。

・上の画像が調整前です。フォントサーズは「11です。上側に寄っています。
・下の画像がフォントサイズを縦位置が中央になるように「14」に変更した画像です。

・どうですか、縦位置はOKですが、文字列がはみ出しちゃってますね(-_-;)
・全部表示するためには、テキストボックスやフォームのサイズを広げないとダメです!
・または、フォントは「11」のままでテキストボックスの高さを低く調整するか。
・いずれにしても、縦位置を中央揃えにしたい場合、全体のスタイルを変更する必要があるということです。
この場合の結論としては、設計の段階から使用したいフォントサイズに合わせてスタイルなどの構成を考えようにした方が良いということですね

Webで調べてみました

[Excel VBA ユーザーフォーム テキストボックス 文字列縦中央揃え]というような文字列で検索してみました。

APIを使って何とかできないか

・VBAのUserFormのプロパティにウィンドウハンドルが無いので、Win32APIを使って自前でhWndを取得するしかありません。
・同じく配置したコントロールもウインドウではないのでハンドルはつかめません。
・いろいろ試したら、なんとかUserForm のハンドルはつかめたけど、テキストボックスの特定は簡単には無理でした。
・もっと時間をかければ何とかなるかもしれませんが、この方法は諦めることにしました。
・昔、VBで(VBAではない)LHA(昔は主流だった)を使った「圧縮バックアップツール」や「ファイルを分割するツール」とかのフリーソフトを作っていました。その時にVisualBasicのフォームではウィンドウハンドルのプロパティがあったので、何とかなるだろうと思ったのが間違いでした。

ダミーのラベルを使って表示する方法

・一所懸命ググっていたら、そういえば昔ラベルを見た目テキストボックスのようにして使っていたことを思い出しました。(ソフトの効率化目的でラベルを使っていました。テキストボックスよりラベルの方が軽量で速いんですよね確か^^)
・ただ、ラベルの文字列表示も「縦中央配置」はできないんですよね。
・手動だけど縦位置中央にあるように見せる方法の記事をどこかで見たなぁ。
・やり方は言葉で言うと次のような感じです。

・テキストボックスの位置にラベルを配置して、余計なキャプションは消します。
・「SpecialEffect」を「2-fmSpecialEffectSunken」でテキストボックス風にします。
・BackColorはテキストボックスと同じ色に合わせます。
・テキストボックスは、そのラベルの上に配置します。
・テキストボックスの「SpecialEfect」は「0-fmSpecialEffectFlat」にします。
・最後にラベル縦位置の中間になるように「テキストボックス」の位置を調整します。
・外枠が「ラベル」でその中に「テキストボックス」があるイメージです。

VBAでコントロールを自動配置させてみる

・テキストボックスを基準に「ラベル」を自動配置してプロパティーを調整するようにします。
・ユーザーフォームの表示直前に発生するイベント「UserForm_Initialize」に記載します。

Option Explicit
Private Const nbox = 4  '配置TextBoxの数を定数指定
'最初(表示前)に実行される
Private Sub UserForm_Initialize()
    Dim dmyL As msforms.Label   'ダミーのラベル作成用
    Dim i As Long
    Dim textNo As Variant       'TextBox用
    For i = 1 To nbox           'TextBox数をループ
        Select Case i
            Case 1: Set textNo = fmPW_Make.txtSet1
            Case 2: Set textNo = fmPW_Make.txtSet2
            Case 3: Set textNo = fmPW_Make.txtSet3
            Case 4: Set textNo = fmPW_Make.txtPW
        End Select
        'ダミーラベルを追加
        Set dmyL = Controls.Add("Forms.Label.1")
        With textNo
            .Font.Size = 11     'フォントサイズ指定
            .Height = .Font.Size + 10   '高さ調整
            .MultiLine = False  '改行無しで
            'TextBoxのプロパティをラベルに適用させる
            dmyL.Top = .Top
            dmyL.Left = .Left
            dmyL.Height = .Height
            dmyL.Width = .Width
            dmyL.BackColor = .BackColor '背景色
            'TextBox風のエフェクトに
            dmyL.SpecialEffect = fmSpecialEffectSunken
            dmyL.ZOrder 1 '1=fmBottom 最背面に表示(0=fmTopで最前面)
            'TextBoxのプロパティ調整
            .SpecialEffect = fmSpecialEffectFlat 'フラットに変更
            .Width = .Width - 3     'ラベルの内側になるように
            .Height = .Height - 4   '高さも同様
            .Left = .Left + 1.5     'Widthの3の半分
            .Top = .Top + 4         'ここで表示位置を微調整する
        End With
        Set textNo = Nothing
        Set dmyL = Nothing
    Next
End Sub

・下の画像が設定後に実行したものです。いかがですか?

・コードの説明は、コメントを入れているので簡単に説明します。
・2行目、配置してあるTextBoxの数を定数指定します。
・8行目から2行目で指定したTextBox数の分ループ処理開始です。
・9~14行目で、処理対象のTextBoxを選択しています。
・16行目で、ダミーで使う「ラベル」を追加しています。
・17~36行間で、ラベルとテキストボックスのプロパティ調整をしています。
位置調整のキモは35行目の「Top」です。ここの数値で縦位置が決まります。
今回は「上下中央揃え」ですが「下揃え」にすることだって可能です。

これだけでも十分なんですが、もう少し効率化を考えてみます。

イニシャライズの処理をプロシージャ化

・最初だけちょっと調整が必要ですが、なんとか縦位置の上下中央揃えにすることができました。
・でも、このイニシャライズでの処理をプロシージャ化することもできます。
・定数で指定している TextBox の数をカウントすることもできそうです。
TextBox を配列に入れて処理することを考えます。

TypeName 関数でコントロールをカウントする

・テキストボックスをカウントする方法は、VBAの場合「TypeName関数」を使います。
TypeNameは引数で指定された変数に関する情報を文字列で返す関数です
【構文】
TypeName(varname)   引数varnameには、任意の変数を指定します。

【解説】
TypeName 関数は、引数varnameで指定された変数に関する「情報」を返します。
・varnameに配列を渡す場合は、変数の後ろに空の括弧()を付けます。
・ユーザー定義型は指定できません。
・コントロールを調べて TextBoxの数を数えるようにします。

プロシージャの処理に変更したコード

'最初(表示前)に実行される
Private Sub UserForm_Initialize()
   'TextBoxをイニシャライズするプロシージャを呼び出す
    Call TextBox_Initialize
End Sub
Option Explicit
'TextBoxをイニシャライズする
Sub TextBox_Initialize()
    Dim dmyL As msforms.Label   'ダミーのラベル作成用
    Dim i As Long
    Dim textNo() As Variant     'TextBox用
    Dim nbox As Long            'TextBox用カウンター
    Dim ctl As Control          'コントロール用
    '配列初期化
    ReDim Preserve textNo(0)
    For Each ctl In fmPW_Make.Controls
        If TypeOf ctl Is msforms.TextBox Then
            nbox = nbox + 1
            '配列に要素を追加(コントロール)
            ReDim Preserve textNo(nbox)
            Set textNo(nbox) = ctl
        End If
    Next
    For i = 1 To nbox
        'ダミーラベルを追加
        Set dmyL = fmPW_Make.Controls.Add("Forms.Label.1")
        With textNo(i)
            .Font.Size = 11     'フォントサイズ指定
            .Height = .Font.Size + 10   '高さ調整
            .MultiLine = False  '改行無しで
            'TextBoxのプロパティをラベルに適用させる
            dmyL.Top = .Top
            dmyL.Left = .Left
            dmyL.Height = .Height
            dmyL.Width = .Width
            dmyL.BackColor = .BackColor '背景色
            'TextBox風のエフェクトに
            dmyL.SpecialEffect = fmSpecialEffectSunken
            dmyL.ZOrder 1 '1=fmBottom 最背面に表示(0=fmTopで最前面)
            'TextBoxのプロパティ調整
            .SpecialEffect = fmSpecialEffectFlat 'フラットに変更
            .Width = .Width - 3     'ラベルの内側になるように
            .Height = .Height - 4   '高さも同様
            .Left = .Left + 1.5     'Widthの3の半分
            .Top = .Top + 4         'ここで表示位置を微調整する
        End With
        Set textNo(i) = Nothing
        Set dmyL = Nothing
    Next
End Sub

「UserForm_Initialize()」イベントプロシージャは、Call TextBox_Initialize でプロシージャを呼び出すだけになりました。
TextBox_Initialize」の処理はつぎのとおりです。
・10行目は、TextBoxを格納する配列を初期化しています。
・11~18行目で、UserForm内のコントロールをループ処理しています。
・12行目で、コントロールの TypeTextBox かどうか判定しています。
・13行目は、TexBox数をカウントアップしています。
・15~16行目で、配列の要素数を追加して、TextBoxそのものを代入しています。
・これ以降の処理は、Texbox が配列になっただけで変更ありません。

・動作テストでも正常に動くことが確認できました(^^♪
・今回はここで終了します。

スポンサーリンク

まとめ(おわりに)

・いかがでしたでしょうか?
「いつも汎用でだれでも使えて活用できるように考えてVBAを使う」というポリシーを念頭に記事を書いています。
・今回も、記事内で使用したコードのサンプルファイルを登録していますのでご利用ください。
今までの記事のサンプルも登録していますのでよろしければお使いください(^^)

まとめと感想など

くるみこ
くるみこ

どうでしたか?

なんとか縦上下中央揃えのように見えるようになりましたね(^^)

「テキストボックス」と「ラベル」でこんなことができるなんてすごくおもしろかったです(^^♪ 新しくTypeName関数も覚えることができました!

くるみこ
くるみこ

Win32APIを使うのは今回は諦めましたが、時間があるときにまたチャレンジしてみます(^^; 次回はコンボボックスの使い方について勉強しましょう!

【今回わかったことは】
・テキストボックス文字列の縦上下中央揃えをTextBoxとラベルを使ってダミー表示させる方法がわかりました
・TypeName関数でコントロール(TextBox)を特定する方法がわかりました
・ループ処理中にコントロール(TextBox)を配列に入れる方法がわかりました

今後の記事について

今回の記事はいかがだったでしょうか。皆さまのお役に立てたなら幸いです(^^;
「汎用でだれでも使えて活用できるように考えてVBAを使う」というポリシーで、記事を継続して書いていきたいと思っています。どうぞよろしくお願いしますm(_ _)m

【検討中の今後の記事内容は・・・・・】
・実務に役立つものを提供できるよう常に検討しています(^^ゞ
・その他雑記的に「プチネタなど」もいろいろ考えていきたいと思います・・・・・
・今後の記事にもご期待ください(^^)/

記事のサンプルファイルをダウンロードできます

今回の記事のサンプルをダウンロードできるようにしています
過去の記事で使用したサンプルファイルがダウンロードできるページを設置しています
こちら(このリンク先)からご利用ください