web-dev-qa-db-ja.com

VBAを使用してExcelユーザーフォームの複数列リストボックスにヘッダーを追加する方法

ソースとしてワークシート範囲を使用せずに複数列リストボックスのヘッダーを設定することは可能ですか?

以下は、リストボックスのリストプロパティに割り当てられたバリアントの配列を使用し、ヘッダーは空白で表示されます。

Sub testMultiColumnLb()
    ReDim arr(1 To 3, 1 To 2)

    arr(1, 1) = "1"
    arr(1, 2) = "One"
    arr(2, 1) = "2"
    arr(2, 2) = "Two"
    arr(3, 1) = "3"
    arr(3, 2) = "Three"


    With ufTestUserForm.lbTest
        .Clear
        .ColumnCount = 2
        .List = arr
    End With

    ufTestUserForm.Show 1
End Sub
13
vzczc

いいえ。リストボックスの上にヘッダーとして機能するラベルを作成します。 lisboxが変更されるたびにラベルを変更するのは大変なことだと思うかもしれません。あなたは正しいでしょう-それは苦痛です。初めて設定するのは面倒で、変更がはるかに少なくなります。しかし、私はもっと良い方法を見つけていません。

17
Dick Kusleika

これが問題を解決するための私のアプローチです:

このソリューションでは、2番目のListBox要素を追加し、最初の要素の上に配置する必要があります。

このような:

Add an additional ListBox

次に、CreateListBoxHeader関数を呼び出して、配置を正しくし、ヘッダー項目を追加します。

結果:

Call the function CreateListBoxHeader

コード:

  Public Sub CreateListBoxHeader(body As MSForms.ListBox, header As MSForms.ListBox, arrHeaders)
            ' make column count match
            header.ColumnCount = body.ColumnCount
            header.ColumnWidths = body.ColumnWidths

        ' add header elements
        header.Clear
        header.AddItem
        Dim i As Integer
        For i = 0 To UBound(arrHeaders)
            header.List(0, i) = arrHeaders(i)
        Next i

        ' make it pretty
        body.ZOrder (1)
        header.ZOrder (0)
        header.SpecialEffect = fmSpecialEffectFlat
        header.BackColor = RGB(200, 200, 200)
        header.Height = 10

        ' align header to body (should be done last!)
        header.Width = body.Width
        header.Left = body.Left
        header.Top = body.Top - (header.Height - 1)
End Sub

使用法:

Private Sub UserForm_Activate()
    Call CreateListBoxHeader(Me.listBox_Body, Me.listBox_Header, Array("Header 1", "Header 2"))
End Sub
7
Jonas_Hess

私は今この問題を見ていましたが、この解決策を見つけました。 RowSourceがセルの範囲を指す場合、複数列リストボックスの列見出しは、RowSourceのすぐ上のセルから取得されます。

ここに示した例を使用すると、リストボックス内で、単語SymbolおよびNameがタイトル見出しとして表示されます。セルAB1の単語名を変更し、フォームをVBEで再度開くと、列見出しが変更されました。

Screenshot displaying a named range and the column headings outside the range.

この例は、S。クリスチャンオルブライトによるVBA For Modelersのワークブックからのもので、私は彼がリストボックスに列見出しを表示する方法を理解しようとしていました:)

6
Rick Henderson

複数列のリストボックスの上部にヘッダーを表示する非常に簡単な解決策があります。デフォルトでfalseである「columnheads」のプロパティ値を「true」に変更するだけです。

その後、プロパティ「rowsource」でデータ範囲について言及し、データ範囲からヘッダーを除外すると、ヘッダーはデータ範囲の最初の最上行にあるはずです。そうすると、ヘッダーが自動的に選択され、ヘッダーがフリーズします。

範囲「A1:H100」のデータと最初の行である「A1:H1」にヘッダーがある場合、データ範囲は「rowsource」プロパティで言及する必要がある「A2:H100」である必要があります。 "columnheads"のperperty値はtrueである必要があります

よろしく、Asif Hameed

5
Asif Hameed

簡単な答え:いいえ。

私が過去に行ったことは、見出しを行0に読み込み、フォームを表示するときにListIndexを0に設定することです。これにより、「見出し」が青色で強調表示され、ヘッダーの外観が得られます。 ListIndexがゼロのままの場合、フォームアクションボタンは無視されるため、これらの値を選択することはできません。

もちろん、別のリストアイテムが選択されるとすぐに、見出しはフォーカスを失いますが、このときまでにその仕事は完了です。

このようにすることで、水平方向にスクロールする見出しを使用することもできます。これは、リストボックスの上に浮かぶ個別のラベルで行うのは困難/不可能です。逆に、リストボックスを垂直方向にスクロールする必要がある場合、見出しは表示されないままです。

基本的に、これは私がこれまで行ってきた状況で機能する妥協策です。

5
Lunatik

CboBxがワークシートから読み込まれていないComboBoxのヘッダーに次のアプローチを使用したい(たとえば、sqlからのデータ)。ワークシートからではないことを指定する理由は、RowSourceを機能させる唯一の方法は、ワークシートからロードする場合だと思うからです。

これは私にとってはうまくいきます:

  1. ComboBoxを作成し、レイアウトは同じで行が1つだけのListBoxを作成します。
  2. ListBoxをComboBoxの上に直接配置します。
  3. VBAで、必要なヘッダーを含むListBox row1をロードします。
  4. アクションyourListBoxName_ClickのVBAに、次のコードを入力します。

    yourComboBoxName.Activate`
    yourComboBoxName.DropDown`
    
  5. リストボックスをクリックすると、コンボボックスがドロップダウンして正常に機能し、リストボックス内の見出しはリストの上に残ります。

2
RR_CodeSlinger

ヘッダー用とデータ用の2つのリストボックスを使用するだけです

  1. ヘッダー用-RowSourceプロパティを最上行に設定します。インシデント!Q4:S4

  2. データの場合-行ソースプロパティをインシデントに設定します!

"3-frmSpecialEffectsEtched"へのSpecialEffects enter image description here

0
Bhanu Sinha

別のシートを使用せずにヘッダーを追加し、すべてをユーザーフォームにコピーするソリューションを探していました。

私の解決策は、最初の行をヘッダーとして使用してif条件を実行し、その下に項目を追加することです。

そのように:

If lborowcount = 0 Then
 With lboorder
 .ColumnCount = 5
 .AddItem
 .Column(0, lborowcount) = "Item"
 .Column(1, lborowcount) = "Description"
 .Column(2, lborowcount) = "Ordered"
 .Column(3, lborowcount) = "Rate"
 .Column(4, lborowcount) = "Amount"
 End With
 lborowcount = lborowcount + 1
End If
        
        
With lboorder
 .ColumnCount = 5
 .AddItem
 .Column(0, lborowcount) = itemselected
 .Column(1, lborowcount) = descriptionselected
 .Column(2, lborowcount) = orderedselected
 .Column(3, lborowcount) = rateselected
 .Column(4, lborowcount) = amountselected
 
 
 End With

lborowcount = lborowcount + 1

その例では、lboorderはリストボックスです。lborowcountは、次のリストボックス項目を追加する行をカウントします。 5列のリストボックスです。理想的ではありませんが、機能し、水平方向にスクロールする必要がある場合、「ヘッダー」は行の上に留まります。

0
J. G.

リストボックスの上部にラベルを追加するだけでなく、変更が必要な場合、プログラムで変更する必要があるのはラベルだけです。

0
Jim

あなたはこれを試してみることができます。私はフォーラムに非常に新しいですが、過去にこのサイトから多くの助けを得たので、私に役立つ何かを提供したいと思いました。これは本質的に上記のバリエーションですが、私はそれがより簡単であることがわかりました。

これをユーザーフォームコードのUserform_Initializeセクションに貼り付けるだけです。ユーザーフォームにリストボックスが既にあるか、このコードの上に動的に作成されている必要があります。また、配列は見出しのリスト(「Header1」、「Header2」など)であることに注意してください。これらを独自の見出しに置き換えます。このコードは、リストボックスの列幅に基づいて上部に見出しバーを設定します申し訳ありませんが、スクロールできません-固定ラベルです。

より上級のコーダー-遠慮なくコメントまたはこれを改善してください。

    Dim Mywidths As String
    Dim Arrwidths, Arrheaders As Variant
    Dim ColCounter, Labelleft As Long
    Dim theLabel As Object                

    [Other code here that you would already have in the Userform_Initialize section]

    Set theLabel = Me.Controls.Add("Forms.Label.1", "Test" & ColCounter, True)
            With theLabel
                    .Left = ListBox1.Left
                    .Top = ListBox1.Top - 10
                    .Width = ListBox1.Width - 1
                    .Height = 10
                    .BackColor = RGB(200, 200, 200)
            End With
            Arrheaders = Array("Header1", "Header2", "Header3", "Header4")

            Mywidths = Me.ListBox1.ColumnWidths
            Mywidths = Replace(Mywidths, " pt", "")
            Arrwidths = Split(Mywidths, ";")
            Labelleft = ListBox1.Left + 18
            For ColCounter = LBound(Arrwidths) To UBound(Arrwidths)
                        If Arrwidths(ColCounter) > 0 Then
                                Header = Header + 1
                                Set theLabel = Me.Controls.Add("Forms.Label.1", "Test" & ColCounter, True)

                                With theLabel
                                    .Caption = Arrheaders(Header - 1)
                                    .Left = Labelleft
                                    .Width = Arrwidths(ColCounter)
                                    .Height = 10
                                    .Top = ListBox1.Top - 10
                                    .BackColor = RGB(200, 200, 200)
                                    .Font.Bold = True
                                End With
                                 Labelleft = Labelleft + Arrwidths(ColCounter)

                        End If
             Next
0
Peter Winn

これが私の解決策です。

VBEのプロパティウィンドウでリストボックスの行ソースを指定すると、ヘッダーが問題なくポップアップすることに気付きました。 VBAコードを使用して行ソースを定義しようとしたときにのみ、ヘッダーが失われます。

したがって、最初に定義済みのリストボックス行ソースを、プロパティウィンドウを介してVBEの名前付き範囲として指定しました。その後、VBAコードで行ソースをリセットできます。ヘッダーは毎回表示されます。

これをlistobjectの高度なフィルターマクロと組み合わせて使用​​しています。これにより、rowsourceのベースとなる別の(フィルターされた)listobjectが作成されます。

これは私のために働いた

0
JamesSA

(ワークシートの)リストボックスの各列の上にラベルを自動作成する1つの方法を次に示します。

リストボックスに水平スクロールバーがない限り、(非常にきれいではありませんが)機能します。

Sub Tester()
Dim i As Long

With Me.lbTest
    .Clear
    .ColumnCount = 5
    'must do this next step!
    .ColumnWidths = "70;60;100;60;60"
    .ListStyle = fmListStylePlain
    Debug.Print .ColumnWidths
    For i = 0 To 10
        .AddItem
        .List(i, 0) = "blah" & i
        .List(i, 1) = "blah"
        .List(i, 2) = "blah"
        .List(i, 3) = "blah"
        .List(i, 4) = "blah"
    Next i

End With

LabelHeaders Me.lbTest, Array("Header1", "Header2", _
                     "Header3", "Header4", "Header5")

End Sub

Sub LabelHeaders(lb, arrHeaders)

    Const LBL_HT As Long = 15
    Dim T, L, shp As Shape, cw As String, arr
    Dim i As Long, w

    'delete any previous headers for this listbox
    For i = lb.Parent.Shapes.Count To 1 Step -1
        If lb.Parent.Shapes(i).Name Like lb.Name & "_*" Then
            lb.Parent.Shapes(i).Delete
        End If
    Next i

    'get an array of column widths
    cw = lb.ColumnWidths
    If Len(cw) = 0 Then Exit Sub
    cw = Replace(cw, " pt", "")
    arr = Split(cw, ";")

    'start points for labels
    T = lb.Top - LBL_HT
    L = lb.Left

    For i = LBound(arr) To UBound(arr)
        w = CLng(arr(i))
        If i = UBound(arr) And (L + w) < lb.Width Then w = lb.Width - L
        Set shp = ActiveSheet.Shapes.AddShape(msoShapeRectangle, _
                                         L, T, w, LBL_HT)
        With shp
            .Name = lb.Name & "_" & i
            'do some formatting
            .Line.ForeColor.RGB = vbBlack
            .Line.Weight = 1
            .Fill.ForeColor.RGB = RGB(220, 220, 220)
            .TextFrame2.TextRange.Characters.Text = arrHeaders(i)
            .TextFrame2.TextRange.Font.Size = 9
            .TextFrame2.TextRange.Font.Fill.ForeColor.RGB = vbBlack
        End With
        L = L + w
    Next i
End Sub
0
Tim Williams

Lunatikの応答の別のバリエーションは、ローカルのブール値と変更イベントを使用して、初期化時に行を強調表示し、ユーザーが選択を変更した後に行を選択解除してブロックすることです。

Private Sub lbx_Change()

    If Not bHighlight Then

        If Me.lbx.Selected(0) Then Me.lbx.Selected(0) = False

    End If

    bHighlight = False

End Sub

リストボックスが初期化されたら、bHighlightとlbx.Selected(0)= Trueを設定します。これにより、選択したヘッダー行を初期化できます。その後、最初の変更により選択が解除され、行が再び選択されなくなります...

0
ChE Junkie