[UserForm]Listbox

Euler

Administrator
Thành viên BQT
Bài học lần trước tôi đã giới thiệu với các bạn về
Bài học lần này tôi sẽ giới thiệu với các bạn về ListBox.
Bạn cần đăng nhập để thấy hình ảnh

Đầu tiên, chúng ta sử dụng listbox để làm gì? Listbox dùng để hiển thị một list danh sách, ví dụ list danh sách file.
Hoặc là list danh sách các từ-nếu bạn dự định làm một từ điển bằng excel.
Để cho dữ liệu vào Listbox, chúng ta cũng sử dụng phương thức AddItem mà chúng ta đã từng gặp khi học về Combobox.
Mã:
ListBox.AddItem data_muốn_thêm_vào, vị_trí_hiển_thị_trên_list_box
Tham số thứ hai (vị_trí_hiển_thị_trên_list_box) có thể giản lược đi bằng cách để trống. Thực tế là chúng ta không dùng tới trong quá trình code. Vì vậy bạn cũng không cần phải ghi nhớ.
Chúng ta hãy thử đoạn code sau xem kết quả là gì nhé:
Mã:
Private Sub CommandButton1_Click()
    ListBox1.AddItem "tuhocvba.net"
End Sub
Bạn cần đăng nhập để thấy hình ảnh

Và thử với đoạn code dưới đây xem sự khác biệt ra sao nếu chúng ta can thiệp vào tham số vị trí trong danh sách nhé:
Mã:
Private Sub CommandButton1_Click()
    Dim i As Long 'Kieu so nguyen co pham vi gia tri len toi 2 trieu
    For i = 1 To 10
        ListBox1.AddItem "tuhocvba" & i
    Next i
    ListBox1.AddItem "danhsach", 0
End Sub
Bạn cần đăng nhập để thấy hình ảnh


Tôi hầu như không sử dụng thuộc tính này, nhưng bạn cũng cần biết là với thuộc tính RowSource , chúng ta có thể nạp dữ liệu từ excel vào listbox.
Ở đây tôi muốn nạp dữ liệu từ hai cột cho nên thuộc tính ColumnCount tôi thiết định là 2.
Bạn cần đăng nhập để thấy hình ảnh


Bây giờ nếu tôi ấn vào nút bấm trên UserForm bạn sẽ thấy là nó bị lỗi như dưới đây:
Bạn cần đăng nhập để thấy hình ảnh


Có nghĩa là nếu bạn sử dụng thuộc tính RowSource thì bạn không thể dùng phương thức AddItem để thêm data vào listbox được nữa. Hãy nhớ điều này.

Bây giờ bạn hãy xóa các thiết định RowSource và ColumnCount ở trên đi. Chúng ta sửa lại code của nút bấm như dưới đây và xem kết quả:
Mã:
Private Sub CommandButton1_Click()
    ListBox1.ColumnCount = 2
    ListBox1.List = Sheets(2).Range("A2:B6").Value
    MsgBox "so luong data la:" & ListBox1.ListCount
End Sub
Bạn cần đăng nhập để thấy hình ảnh


Nguồn tham khảo:
Mã:
http://officetanaka.net/excel/vba/tips/tips137.htm
 

vbano1

SMod
Thành viên BQT
Đối với listbox, có một thông số hay dùng, đó là chia độ rộng cho nhiều cột.
Mã:
ListBox1.ColumnWidths = "130;60"
Để được kết quả như dưới đây:
Bạn cần đăng nhập để thấy hình ảnh

ta có code như dưới đây:
Mã:
Private Sub CommandButton1_Click()
    ListBox1.ColumnCount = 2
    ListBox1.ColumnWidths = "130;60"
    ListBox1.List = Sheets(1).Range("A2:B6").Value
    MsgBox "so luong data la:" & ListBox1.ListCount
End Sub
Bây giờ ta sẽ can thiệp vào các thuộc tính của Listbox thông qua Initialize Userform:
Mã:
Private Sub UserForm_Initialize()
    ListBox1.ListStyle = fmListStyleOption
    ListBox1.MultiSelect = 0 'Neu la 0 thi select duoc 1 item. Neu la 2 thi select duoc nhieu item
End Sub
Ta sẽ được kết quả như sau:
Bạn cần đăng nhập để thấy hình ảnh

Ta sửa lại 0 thành 2 trong đoạn code trên:
Mã:
ListBox1.MultiSelect = 1
Ta được kết quả như sau:
Bạn cần đăng nhập để thấy hình ảnh

Bây giờ ta hãy kiểm chứng lại:
Giả sử người dùng đã tích chọn một số đối tượng nào đó trên listbox, vậy làm thế nào để xác định được họ đã tích chọn vào đâu? Xin hãy tham khảo đoạn code dưới đây:
Ta sẽ code cho nút bấm thứ hai:
Mã:
Private Sub CommandButton2_Click()
    Dim i As Integer
    Dim s   As String
   
    For i = 0 To ListBox1.ListCount - 1 Step 1
        If ListBox1.Selected(i) = True Then
            s = s & ListBox1.List(i, 0) & ";"
        End If
    Next i
    MsgBox s
   
End Sub
Kết quả:
Bạn cần đăng nhập để thấy hình ảnh

Chú ý đoạn code trên, ta chay i =0 cho nên chỉ chạy tới ListCount-1 chứ không phải chạy tới ListCount. Đây là số item có trong listbox.
Thuộc tính Selected(i) sẽ xác định item(i) trong listbox có được select hay không?
Chú ý rằng listbox của chúng ta có hai cột, bắt đầu từ 0->1.
Cho nên thuộc tính List cũng phải có hai tham số, dòng và cột, cụ thể là dòng i và cột đầu tiên (cột 0): List(i,0).
 

tuhocvba

Administrator
Thành viên BQT
Để điều khiển thanh cuộn bằng chuột giữa, các bạn tham khảo topic này:
 

quốc bình

Yêu THVBA
Làm sao để listbox có đường viền cell?
Khi có đường viền nhìn sẽ trực quan hơn ạ
 

tuhocvba

Administrator
Thành viên BQT
ListView thì được nhưng chỉ có trên máy 32bit. Còn ListBox thì không, nhưng máy nào cũng có ListBox.
 

Euler

Administrator
Thành viên BQT
@nhocquyvn :Cái bạn hỏi chẳng liên quan gì tới kiến thức Listbox. Bạn nên đặt câu hỏi ở trong Box . Hoặc có thể đặt ở Box .
Nếu bạn quan tâm tới việc làm việc với file excel khác như thế nào thì bạn tham khảo . Với Access thì bạn tham khảo .

Nếu năng lực của bạn không đủ, tức là đọc hai topic trên vẫn không tự ứng dụng được cho bản thân, hãy trao dự án của bạn cho chúng tôi để chúng tôi hoàn thành nó, và bạn hãy trả phí cho chúng tôi như một cách ủng hộ diễn đàn có kinh phí hoạt động.
Chân thành cảm ơn bạn.
 

syquyen1987

Yêu THVBA
Đối với listbox, có một thông số hay dùng, đó là chia độ rộng cho nhiều cột.
Mã:
ListBox1.ColumnWidths = "130;60"
Để được kết quả như dưới đây:
Bạn cần đăng nhập để thấy hình ảnh

ta có code như dưới đây:
Mã:
Private Sub CommandButton1_Click()
    ListBox1.ColumnCount = 2
    ListBox1.ColumnWidths = "130;60"
    ListBox1.List = Sheets(1).Range("A2:B6").Value
    MsgBox "so luong data la:" & ListBox1.ListCount
End Sub
Bây giờ ta sẽ can thiệp vào các thuộc tính của Listbox thông qua Initialize Userform:
Mã:
Private Sub UserForm_Initialize()
    ListBox1.ListStyle = fmListStyleOption
    ListBox1.MultiSelect = 0 'Neu la 0 thi select duoc 1 item. Neu la 2 thi select duoc nhieu item
End Sub
Ta sẽ được kết quả như sau:
Bạn cần đăng nhập để thấy hình ảnh

Ta sửa lại 0 thành 2 trong đoạn code trên:
Mã:
ListBox1.MultiSelect = 2
Ta được kết quả như sau:
Bạn cần đăng nhập để thấy hình ảnh

Bây giờ ta hãy kiểm chứng lại:
Giả sử người dùng đã tích chọn một số đối tượng nào đó trên listbox, vậy làm thế nào để xác định được họ đã tích chọn vào đâu? Xin hãy tham khảo đoạn code dưới đây:
Ta sẽ code cho nút bấm thứ hai:
Mã:
Private Sub CommandButton2_Click()
    Dim i As Integer
    Dim s   As String
   
    For i = 0 To ListBox1.ListCount - 1 Step 1
        If ListBox1.Selected(i) = True Then
            s = s & ListBox1.List(i, 0) & ";"
        End If
    Next i
    MsgBox s
   
End Sub
Kết quả:
Bạn cần đăng nhập để thấy hình ảnh

Chú ý đoạn code trên, ta chay i =0 cho nên chỉ chạy tới ListCount-1 chứ không phải chạy tới ListCount. Đây là số item có trong listbox.
Thuộc tính Selected(i) sẽ xác định item(i) trong listbox có được select hay không?
Chú ý rằng listbox của chúng ta có hai cột, bắt đầu từ 0->1.
Cho nên thuộc tính List cũng phải có hai tham số, dòng và cột, cụ thể là dòng i và cột đầu tiên (cột 0): List(i,0).
Cho mình xin hỏi làm thế nào để có tiêu đề cột (ColumnHeads) "Tên" và "Tuổi" trong Listbox ạ.
 

tuhocvba

Administrator
Thành viên BQT
@syquyen1987 : Cấm quote cả bài viết. Chỉ quote câu chữ cần thiết khi trích dẫn.
Trả lời: Dùng Label.
 

Thanhhoai0

Yêu THVBA
Mình muốn hiện danh sách dữ liệu lên listbox luôn không cần bấm nút thì mình làm thế nào vậy bạn ??
 

tuhocvba

Administrator
Thành viên BQT
Bạn đọc bài viết #3 ở đây:

Viết thủ tục load dữ liệu đối với sự kiện initialize.
 
D

Deleted member 1392

Guest
Nếu muốn thêm tiêu đề lên Listbox thì dữ liệu của bạn buộc phải nạp vào ở dạng RowSource và tiêu đề cột được bật bằng đoạn code
Mã:
Listbox1.ColumnHeads = True
Nếu bạn nạp dữ liệu vào bằng List hay AddItem thì bạn chỉ có cách là thêm các Label phía trên Listbox hoặc tạo thêm một Listbox khác, đặt phía trên Listbox nội dung để làm tiêu đề cho nó.
 

nhanduc2018

Yêu THVBA
cho mình hỏi: chữ trong sheets có màu làm thế nào đẩy lên listbox cũng có màu như thế.
như chữ A B màu đỏ C D màu xanh thì khi up lên listbox cũng màu như thế
cám ơn nhiều
Bạn cần đăng nhập để thấy hình ảnh
 
Sửa lần cuối:

tuhocvba

Administrator
Thành viên BQT
Trong khả năng hiểu biết của tôi, thì việc phản ánh màu của từng chữ lên listbox là không khả thi.
 
T

thanhphong

Guest
Nạp giá trị vào listbox qua mảng:
Mã:
With .ListBox1
        .Clear
        .List = Array(1, 2, 3)
        .ListStyle = fmListStyleOption
        .MultiSelect = fmMultiSelectMulti
End With
Có cách nào lấy nhanh vị trí các item đã được select cho vào một mảng không mọi người.
Chạy thế này hơi đuối ạ.
Mã:
For i = 0 To ListBox1.ListCount - 1 Step 1
        If ListBox1.Selected(i) = True Then
            s = s & ListBox1.List(i, 0) & ";"
        End If
    Next i
 

queluatb

Yêu THVBA
Em mới tìm hiểu về VBA, các anh chị vui lòng hướng dẫn em cách căn lề phải trong listbox với
Ví dụ: Em có 4 cột trong listox, 2 cột đầu là chữ, 2 cột sau là số, khi đưa vào listbox em thấy mặc định toàn căn lề phải, cột số nhìn như vậy khó phân biệt và thiếu mỹ qua, em muốn căn lại lề phải cho đúng định dạng, nhờ mọi người giúp đỡ
Em xin cám ơn
 

tuhocvba

Administrator
Thành viên BQT
Bạn tạo một class có tên là: CListboxAlign
Trong class viết code như sau:
Mã:
'PLACE IN A CLASS MODULE
Option Explicit
'----------------------------------------------------------------------------------------------
'---Developer: Ryan Wells (wellsr.com)---------------------------------------------------------
'---Date: 05/2017-------------------------------------------------------------------------
'---Class: CListboxAlign-------------------------------------------------------------------
'---Purpose: Align the text in different columns in a UserForm ListBox differently-----------
'--- This has been adapted from a few sources I stumbled across many moons ago but---
'--- I don't recall the sources.-----------------------------------------------------
'----------------------------------------------------------------------------------------------

Public Sub Center(LBox As MSForms.ListBox, Optional WhichColumn As Integer = 0)
'
' PURPOSE: Center align the text in a listbox column
' HOW TO USE:
' - First argument is the listbox you want to adjust, the second optional argument is which
' column in the listbox you want to align.
' - To use this procedure, you would place a statement like the following in your UserForm_Initialize routine:
' MyListBoxClass.Center Me.ListBox1, 1
'
    Dim labSizer As MSForms.Label
    Dim lngIndex As Long
    Dim intColumn As Integer
    Dim lngTopIndex As Long
    Dim vntColWidths As Variant
    
    ' get label control to help size text
    Set labSizer = m_GetSizer(LBox.Parent)
    If labSizer Is Nothing Then Exit Sub
    
    ReDim sngWidth(LBox.ColumnCount) As Single
    If Len(LBox.ColumnWidths) > 0 Then
        ' decode column widths
        vntColWidths = Split(LBox.ColumnWidths, ";")
        ' fudge for gap between cols
        For intColumn = 1 To LBox.ColumnCount
            sngWidth(intColumn) = Val(vntColWidths(intColumn - 1)) - 5
        Next
    Else
        ' assume default sizes
        For intColumn = 1 To LBox.ColumnCount
            sngWidth(intColumn) = (LBox.Width - (15 * LBox.ColumnCount)) / LBox.ColumnCount
        Next intColumn
    End If
    
    ' generic font attributes
    With labSizer
        With .Font
            .Name = LBox.Font.Name
            .Size = LBox.Font.Size
            .Bold = LBox.Font.Bold
        .Italic = LBox.Font.Italic
        End With
        .WordWrap = False
    End With
    
    ' begin processing column width to center align
    lngTopIndex = LBox.TopIndex
    For intColumn = 1 To LBox.ColumnCount
        If intColumn = WhichColumn Or WhichColumn = -1 Then
            ' if you say to center align this column or center align all columns
            For lngIndex = 0 To LBox.ListCount - 1
                LBox.TopIndex = lngIndex
                labSizer.Width = LBox.Width
                labSizer.Caption = Trim(LBox.List(lngIndex, intColumn - 1))
                labSizer.AutoSize = True
                Do While labSizer.Width < sngWidth(intColumn)
                    labSizer.Caption = " " & labSizer.Caption & " "
                Loop
                LBox.List(lngIndex, intColumn - 1) = labSizer.Caption
            Next lngIndex
        End If
    Next intColumn
    LBox.TopIndex = lngTopIndex
    
    LBox.Parent.Controls.Remove labSizer.Name
    Set labSizer = Nothing

End Sub

Public Sub Left(LBox As MSForms.ListBox, Optional WhichColumn As Integer = 0)
'
' PURPOSE: Left align the text in a listbox column
' HOW TO USE:
' - First argument is the listbox you want to adjust, the second optional argument is which
' column in the listbox you want to align.
' - To use this procedure, you would place a statement like the following in your UserForm_Initialize routine:
' MyListBoxClass.Left Me.ListBox1, 1
'
    Dim lngIndex As Long
    Dim intColumn As Integer
    Dim lngTopIndex As Long
    Dim vntColWidths As Variant
    ReDim sngWidth(LBox.ColumnCount) As Single
    
    If Len(LBox.ColumnWidths) > 0 Then
        ' decode column widths
        vntColWidths = Split(LBox.ColumnWidths, ";")
        ' fudge for gap between cols
        For intColumn = 1 To LBox.ColumnCount
            sngWidth(intColumn) = Val(vntColWidths(1)) - 5
        Next
    Else
        ' assume default sizes
        For intColumn = 1 To LBox.ColumnCount
            sngWidth(intColumn) = (LBox.Width - (15 * LBox.ColumnCount)) / LBox.ColumnCount
        Next intColumn
    End If
    
    lngTopIndex = LBox.TopIndex
    For intColumn = 1 To LBox.ColumnCount
        If intColumn = WhichColumn Or WhichColumn = -1 Then
            ' if you say to left align this column or left align all columns
            For lngIndex = 0 To LBox.ListCount - 1
                LBox.TopIndex = lngIndex
                LBox.List(lngIndex, intColumn - 1) = Trim(LBox.List(lngIndex, intColumn - 1))
            Next lngIndex
        End If
    Next intColumn
    LBox.TopIndex = lngTopIndex
    
End Sub

Public Sub Right(LBox As MSForms.ListBox, Optional WhichColumn As Integer = 1)
'
' PURPOSE: Right align the text in a listbox column
' HOW TO USE:
' - First argument is the listbox you want to adjust, the second optional argument is which
' column in the listbox you want to align.
' - To use this procedure, you would place a statement like the following in your UserForm_Initialize routine:
' MyListBoxClass.Right Me.ListBox1, 1
'
    Dim labSizer As MSForms.Label
    Dim lngIndex As Long
    Dim intColumn As Integer
    Dim lngTopIndex As Long
    Dim vntColWidths As Variant
    ' get label control to help size text
    Set labSizer = m_GetSizer(LBox.Parent)
    If labSizer Is Nothing Then Exit Sub
    
    ReDim sngWidth(LBox.ColumnCount) As Single
    If Len(LBox.ColumnWidths) > 0 Then
        ' decode column widths
        vntColWidths = Split(LBox.ColumnWidths, ";")
        ' fudge for gap between cols
        For intColumn = 1 To LBox.ColumnCount
            sngWidth(intColumn) = Val(vntColWidths(1)) - 5
        Next
    Else
        ' assume default sizes
        For intColumn = 1 To LBox.ColumnCount
            sngWidth(intColumn) = (LBox.Width - (15 * LBox.ColumnCount)) / LBox.ColumnCount
        Next intColumn
    End If
    
    With labSizer
        With .Font
            .Name = LBox.Font.Name
            .Size = LBox.Font.Size
            .Bold = LBox.Font.Bold
        .Italic = LBox.Font.Italic
        End With
        .WordWrap = False
    End With
    
    lngTopIndex = LBox.TopIndex
    For intColumn = 1 To LBox.ColumnCount
        If intColumn = WhichColumn Or WhichColumn = -1 Then
            'if you say to right align this column, or right align all columns
            For lngIndex = 0 To LBox.ListCount - 1
                LBox.TopIndex = lngIndex
                labSizer.Width = LBox.Width
                labSizer.Caption = Trim(LBox.List(lngIndex, intColumn - 1))
                labSizer.AutoSize = True
                Do While labSizer.Width < sngWidth(intColumn)
                    labSizer.Caption = " " & labSizer.Caption
                Loop
                LBox.List(lngIndex, intColumn - 1) = labSizer.Caption
            Next lngIndex
        End If
    Next intColumn
    LBox.TopIndex = lngTopIndex
    LBox.Parent.Controls.Remove labSizer.Name
    Set labSizer = Nothing

End Sub

Private Property Get m_GetSizer(Base As MSForms.UserForm) As MSForms.Label
    Set m_GetSizer = Base.Controls.Add("Forms.Label.1", "labSizer", True)
End Property
Bạn tạo userform1, trên đó có listbox1. Code trong userform như sau:
Mã:
Private MyListBoxClass As CListboxAlign

Private Sub UserForm_Initialize()
    Dim lngRow As Long
    Dim lngIndex As Long
    Set MyListBoxClass = New CListboxAlign 'declare the class
    
    'This is just a sample where I add data to a listbox.
    'You'll want to use your own data.
    '-----------------------------------------------------------------------
    ListBox1.ColumnCount = 3
    With Me.ListBox1
        .AddItem
        .AddItem
        .AddItem
        .List(0, 0) = "First Product"
        .List(1, 0) = "Second Product"
        .List(2, 0) = "Third Product"
        .List(0, 1) = "Basic"
        .List(1, 1) = "Standard"
        .List(2, 1) = "Ultimate"
        .List(0, 2) = "$45.00"
        .List(1, 2) = "$79.00"
        .List(2, 2) = "$100.00"
    End With
    '-----------------------------------------------------------------------

    'This is how you left, center and right align a ListBox.
    MyListBoxClass.Left Me.ListBox1, 1
    MyListBoxClass.Center Me.ListBox1, 2
    MyListBoxClass.Right Me.ListBox1, 3
End Sub

Private Sub UserForm_Terminate()
    'clear the class declaration
    Set MyListBoxClass = Nothing
End Sub
Kết quả:
Bạn cần đăng nhập để thấy đính kèm

Nguồn:
.
 
Top