Các câu hỏi về Form trong Excel VBA (2 người xem)

Liên hệ QC

Người dùng đang xem chủ đề này

Tường_Vi

Thành viên tiêu biểu
Tham gia
19/4/10
Bài viết
482
Được thích
121
Nghề nghiệp
Luôn tìm kiếm một vị trí tốt hơn
Private Sub UserForm_Initialize()
.......................
.......................
.......................
End Sub


Em xin hỏi, sự kiện khí nào mình dùng sự kiện này Initialize

Cám ơn
 
Bác chịu khó viết các declare lại đi. Lỗi do declare sai thôi, nên call API sai. Gộp vào 1 module.
 
Upvote 0
gạch đá càng nhiều càng tốt !
miễn là có thể khắc phục lỗi là được rồi,
cám ơn các bác chỉ dẫn nhiệt tình
Thì tôi đã chỉ tận nơi rồi còn gì?

Nếu chỉ là vấn đề icon thì trong code của UserForm1:

1. Sửa thành
Mã:
#If VBA7 Then
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
  (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
  
' các khai báo còn lại như cũ
#Else
' các khai báo  như cũ
#End If

Đấy là tối thiểu để có icon. Ngoài ra trong phần #IF còn phải sửa khai báo của GetWindowLong và SetWindowLong.

Trong UserForm_Initialize cho lnghWnd vào #If ... #End If, tức sửa thành
Mã:
#If VBA7 Then
    Dim lngIcon As LongPtr
    Dim lnghWnd As LongPtr
#Else
    Dim lngIcon As Long
    Dim lnghWnd As Long
#End If

2. Tôi đã nói rất rõ là không có icon không phải là lỗi của ExtractIcon. Lỗi do truyền tham số không "khớp" với khai báo của hàm SendMessage.
a - Nếu để nguyên khai báo SendMessage như bây giờ thì trong UserForm_Initialize phải có
SendMessage lnghWnd, WM_SETICON, False, ByVal lngIcon

b - Nếu giữ nguyên như bây giờ lệnh gọi SendMessage
Mã:
SendMessage lnghWnd, WM_SETICON, False, lngIcon

thì phải sửa khai báo thành
#If VBA7 Then
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
' khai báo còn lại như cũ
#Else
' 2 khai báo như cũ
#End If

Tức có 2 khả năng. Hãy chọn 1 để sửa
 
Upvote 0
1. Khai báo lộn xộn.

2. Khai báo không chính xác. Vd.
Không thể là


Mà phải là As LongPtr.

3. Không nhất quán. Đã bầy trò #If ... #Else ... #End If thì phải nhất quán, chơi trò đó đến cùng.
Không thể khai báo như ở trên (vd. FindWindow) rồi sau đó
Mã:
Dim lnghWnd As Long
Đã chơi #If ... #Else ... #End If thì chơi đến cùng.

4. Về code thì sai không phải do ExtractIcon. Parameter cuối cùng không phải là ID (identifier) mà là index - chỉ số thôi. 0 có nghĩa là icon đầu tiên có trong EXE, DLL. Excel.exe rõ ràng có ít nhất 1 icon.

Sai do cách dùng hàm SendMessage. Nếu ở trên là

thì khi chạy trên Office 2016 sẽ có lỗi ở
Mã:
SendMessage lnghWnd, WM_SETICON, False, lngIcon

Lúc đó phải là


Lúc đó sẽ nhìn thấy ICON.

Ngoài ra nên khai báo nhất quán. Hoặc cùng ANY hoặc cùng không ANY. Tức hoặc (lParam truyền bởi reference)

hoặc (lParam truyền bởi giá trị)


Với phiên bản 1 bắt buộc phải có ByVal lngIcon. Với phiên bản 2 thì ByVal lngIcon hay lngIcon đều được.

Nói tóm lại là code hổ lốn.
làm theo hướng dẫn của bác với Office 2007+2016 (32 bit) đều Ok rồi
nhưng vẫn còn Office 2010 -64 bit báo lỗi
vậy lại lên đây để "Kiện" bác @batman1 thôi. :D
220554
 

File đính kèm

Upvote 0
Vậy thì hWnd khai báo sai hay FindWindow declare sai.
Tôi kg có down file của bác, nhưng nhìn là thấy ngay
 
Upvote 0
làm theo hướng dẫn của bác với Office 2007+2016 (32 bit) đều Ok rồi
nhưng vẫn còn Office 2010 -64 bit báo lỗi
vậy lại lên đây để "Kiện" bác @batman1 thôi. :D
View attachment 220554
Thử lại thế này lần nửa xem sao.
Mã:
Private Sub UserForm_Initialize()
    Dim strIconPath As String
#If VBA7 Then
    Dim lngIcon As LongPtr
    Dim lnghWnd As LongPtr
#Else
    Dim lngIcon As Long
    Dim lnghWnd As Long
#End If
    
 
'----------------------------------------------
    AllowResize = True
    OldWidth = Width
    OldHeight = Height
    If Val(Application.Version) < 9 Then
        lnghWnd = FindWindow("ThunderXFrame", Caption)  'XL97
    Else
        lnghWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
    End If

    PrevStyle = GetWindowLong(lnghWnd, GWL_STYLE)
    SetWindowLong hWnd, GWL_STYLE, PrevStyle _
                                Or WS_SIZEBOX _
                                Or WS_MINIMIZEBOX _
                                Or WS_MAXIMIZEBOX
'----------------------------------------------
#If VBA7 Then
    lngIcon = ExtractIcon(Application.HinstancePtr, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#Else
    lngIcon = ExtractIcon(Application.Hinstance, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#End If


    SendMessage lnghWnd, WM_SETICON, True, lngIcon
    SendMessage lnghWnd, WM_SETICON, False, ByVal lngIcon

  
    SetUniText Me, "Caption hi" & ChrW(7875) & "n th" & ChrW(7883) & " Ti" & ChrW(7871) & "ng Vi" & ChrW(7879) & "t"
    
End Sub
 
Upvote 0
làm theo hướng dẫn của bác với Office 2007+2016 (32 bit) đều Ok rồi
nhưng vẫn còn Office 2010 -64 bit báo lỗi
vậy lại lên đây để "Kiện" bác @batman1 thôi. :D
View attachment 220554
Thì tôi đã viết rất rõ
Nếu chỉ là vấn đề icon thì trong code của UserForm1:

Tức phần
Mã:
#If VBA7 Then
    lngIcon = ExtractIcon(Application.HinstancePtr, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#Else
    lngIcon = ExtractIcon(Application.Hinstance, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#End If
    lnghWnd = FindWindow("ThunderDFrame", Me.Caption)

Debug.Print lngIcon
Debug.Print lnghWnd
'    SendMessage lnghWnd, WM_SETICON, True, lngIcon
    SendMessage lnghWnd, WM_SETICON, False, ByVal lngIcon

Còn bạn đang nói tới phần đọc ra handle của Form vào hWnd (sao không đọc 1 lần như ở dưới, tức như tôi trích ở trên, vào lnghWnd???). Tức phần không liên quan tới ICON
Mã:
If Val(Application.Version) < 9 Then
        hWnd = FindWindow("ThunderXFrame", Caption)  'XL97
    Else
        hWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
    End If
Debug.Print hWnd
    PrevStyle = GetWindowLong(hWnd, GWL_STYLE)
    SetWindowLong hWnd, GWL_STYLE, PrevStyle _
                                Or WS_SIZEBOX _
                                Or WS_MINIMIZEBOX _
                                Or WS_MAXIMIZEBOX

hWnd ở trên không được khai báo trong module UserForm1 mà ở module RUN
Mã:
Public hWnd&

Không thể thế được. Đã chơi các phiên bản thì phải #If ... #Else ... #End If.

Mà cũng lạ. hWnd được khai báo tại RUN nhưng lại chỉ dùng trong UserForm_Initialize.

Chữa cháy:
1. Xóa
Mã:
Public hWnd&
ở đầu module RUN

2. Trong UserForm_Initialize khai báo
Mã:
#If VBA7 Then
    Dim hWnd As LongPtr
#Else
    Dim hWnd As Long
#End If

Nhưng tại sao phải làm thế khi đã có biến lnghWnd rồi??? Vậy thì không khai báo thêm hWnd nữa là dùng lnghWnd thôi. Tức
Mã:
If Val(Application.Version) < 9 Then
    lnghWnd = FindWindow("ThunderXFrame", Caption)  'XL97
Else
    lnghWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
End If

Và xóa dòng
Mã:
lnghWnd = FindWindow("ThunderDFrame", Me.Caption)
Nhưng tôi cũng đã viết ở bài trước là phải khai báo lại GetWindowLong và SetWindowLong. Nếu không sẽ lỗi tiếp tại dòng dùng GetWindowLong và SetWindowLong

Tất nhiên có ICON và hết lỗi kia nhưng text trên thanh tiêu đề không hiển thị tiếng Việt do code trong FormCaptionUnicode sai toe tua. Tôi không đủ dũng cảm để nhìn code trong module đó nữa nên bỏ dùng SetUniText.

Tóm lại tôi đã sửa hộ bạn. Hãy xóa toàn bộ code hiện có trong UserForm và thay bằng code sau
Mã:
'-----------------------------------------
'****************************************************
'Author: Nguyen Duy Tuan - duytuan@bluesofts.net
'Tel: 0904.210.337
'website: www.bluesofts.net
'         www.atoolspro.com
'****************************************************
Option Explicit

Private Const GWL_STYLE = (-16)
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_THICKFRAME = &H40000
Private Const WS_SIZEBOX = WS_THICKFRAME
Private Const WM_SETICON = &H80
Private Const WM_SETTEXT As Long = &HC
'Private Const WS_MAXIMIZE = &H1000000
'Private Const WS_MINIMIZE = &H20000000
'
'Private Const SW_ERASE = &H4
'Private Const SW_HIDE = 0
'Private Const SW_INVALIDATE = &H2
'Private Const SW_MAX = 10
'Private Const SW_MAXIMIZE = 3
'Private Const SW_MINIMIZE = 6
'Private Const SW_NORMAL = 1
'Private Const SW_OTHERUNZOOM = 4
'Private Const SW_OTHERZOOM = 2
'Private Const SW_PARENTCLOSING = 1
'Private Const SW_PARENTOPENING = 3
'Private Const SW_RESTORE = 9
'Private Const SW_SCROLLCHILDREN = &H1
'Private Const SW_SHOW = 5
'Private Const SW_SHOWDEFAULT = 10
'Private Const SW_SHOWMAXIMIZED = 3
'Private Const SW_SHOWMINIMIZED = 2
'Private Const SW_SHOWMINNOACTIVE = 7
'Private Const SW_SHOWNA = 8
'Private Const SW_SHOWNOACTIVATE = 4
'Private Const SW_SHOWNORMAL = 1
    
#If VBA7 Then
    Private Declare PtrSafe Function DefWindowProcW Lib "user32" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hWnd As LongPtr, ByVal nCmdShow As LongPtr) As LongPtr
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
      
    Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
    Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare PtrSafe Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hInst As LongPtr, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As LongPtr
    Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
#Else
    Private Declare Function DefWindowProcW Lib "user32" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
      
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If

Dim PrevStyle&
Dim OldWidth As Double, OldHeight As Double
Dim AllowResize As Boolean

Private Sub UserForm_Initialize()
#If VBA7 Then
    Dim lngIcon As LongPtr
    Dim lnghWnd As LongPtr
#Else
    Dim lngIcon As Long
    Dim lnghWnd As Long
#End If
Dim sUniText As String
'----------------------------------------------
    AllowResize = True
    OldWidth = Width
    OldHeight = Height
    If Val(Application.Version) < 9 Then
        lnghWnd = FindWindow("ThunderXFrame", Caption)  'XL97
    Else
        lnghWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
    End If

    PrevStyle = GetWindowLong(lnghWnd, GWL_STYLE)
    SetWindowLong lnghWnd, GWL_STYLE, PrevStyle Or WS_SIZEBOX Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
'----------------------------------------------
#If VBA7 Then
    lngIcon = ExtractIcon(Application.HinstancePtr, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#Else
    lngIcon = ExtractIcon(Application.Hinstance, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#End If
    
'    SendMessage lnghWnd, WM_SETICON, True, lngIcon
    SendMessage lnghWnd, WM_SETICON, False, lngIcon

    sUniText = "Caption hi" & ChrW(7875) & "n th" & ChrW(7883) & " Ti" & ChrW(7871) & "ng Vi" & ChrW(7879) & "t"
    DefWindowProcW lnghWnd, WM_SETTEXT, 0, StrPtr(sUniText)
   
'    SetUniText Me, "Caption hi" & ChrW(7875) & "n th" & ChrW(7883) & " Ti" & ChrW(7871) & "ng Vi" & ChrW(7879) & "t"
End Sub
Bài đã được tự động gộp:

Thử lại thế này lần nửa xem sao.
Thì sẽ được thông báo tiếp là sai tại GetWindowLong. Rồi sai ở SetWindowLong. Vì hiện thời trong khai báo của Set(Get)WindowLong thì hwnd As Long cả ở #If. Phải sửa thành As LongPtr.

Đã nói rồi. Code sai rất nhiều chỗ chứ không chỉ chỗ hWnd đâu. Sửa xong Set(Get)WindowLong thì sẽ thấy tiêu đề tiếng Việt không có do code trong FormCaptionUnicode cũng sai.
 
Lần chỉnh sửa cuối:
Upvote 0
Thì tôi đã viết rất rõ


Tức phần
Mã:
#If VBA7 Then
    lngIcon = ExtractIcon(Application.HinstancePtr, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#Else
    lngIcon = ExtractIcon(Application.Hinstance, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#End If
    lnghWnd = FindWindow("ThunderDFrame", Me.Caption)

Debug.Print lngIcon
Debug.Print lnghWnd
'    SendMessage lnghWnd, WM_SETICON, True, lngIcon
    SendMessage lnghWnd, WM_SETICON, False, ByVal lngIcon

Còn bạn đang nói tới phần đọc ra handle của Form vào hWnd (sao không đọc 1 lần như ở dưới, tức như tôi trích ở trên, vào lnghWnd???). Tức phần không liên quan tới ICON
Mã:
If Val(Application.Version) < 9 Then
        hWnd = FindWindow("ThunderXFrame", Caption)  'XL97
    Else
        hWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
    End If
Debug.Print hWnd
    PrevStyle = GetWindowLong(hWnd, GWL_STYLE)
    SetWindowLong hWnd, GWL_STYLE, PrevStyle _
                                Or WS_SIZEBOX _
                                Or WS_MINIMIZEBOX _
                                Or WS_MAXIMIZEBOX

hWnd ở trên không được khai báo trong module UserForm1 mà ở module RUN
Mã:
Public hWnd&

Không thể thế được. Đã chơi các phiên bản thì phải #If ... #Else ... #End If.

Mà cũng lạ. hWnd được khai báo tại RUN nhưng lại chỉ dùng trong UserForm_Initialize.

Chữa cháy:
1. Xóa
Mã:
Public hWnd&
ở đầu module RUN

2. Trong UserForm_Initialize khai báo
Mã:
#If VBA7 Then
    Dim hWnd As LongPtr
#Else
    Dim hWnd As Long
#End If

Nhưng tại sao phải làm thế khi đã có biến lnghWnd rồi??? Vậy thì không khai báo thêm hWnd nữa là dùng lnghWnd thôi. Tức
Mã:
If Val(Application.Version) < 9 Then
    lnghWnd = FindWindow("ThunderXFrame", Caption)  'XL97
Else
    lnghWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
End If

Và xóa dòng
Mã:
lnghWnd = FindWindow("ThunderDFrame", Me.Caption)
Nhưng tôi cũng đã viết ở bài trước là phải khai báo lại GetWindowLong và SetWindowLong. Nếu không sẽ lỗi tiếp tại dòng dùng GetWindowLong và SetWindowLong

Tất nhiên có ICON và hết lỗi kia nhưng text trên thanh tiêu đề không hiển thị tiếng Việt do code trong FormCaptionUnicode sai toe tua. Tôi không đủ dũng cảm để nhìn code trong module đó nữa nên bỏ dùng SetUniText.

Tóm lại tôi đã sửa hộ bạn. Hãy xóa toàn bộ code hiện có trong UserForm và thay bằng code sau
Mã:
'-----------------------------------------
'****************************************************
'Author: Nguyen Duy Tuan - duytuan@bluesofts.net
'Tel: 0904.210.337
'website: www.bluesofts.net
'         www.atoolspro.com
'****************************************************
Option Explicit

Private Const GWL_STYLE = (-16)
Private Const WS_MAXIMIZEBOX = &H10000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_THICKFRAME = &H40000
Private Const WS_SIZEBOX = WS_THICKFRAME
Private Const WM_SETICON = &H80
Private Const WM_SETTEXT As Long = &HC
'Private Const WS_MAXIMIZE = &H1000000
'Private Const WS_MINIMIZE = &H20000000
'
'Private Const SW_ERASE = &H4
'Private Const SW_HIDE = 0
'Private Const SW_INVALIDATE = &H2
'Private Const SW_MAX = 10
'Private Const SW_MAXIMIZE = 3
'Private Const SW_MINIMIZE = 6
'Private Const SW_NORMAL = 1
'Private Const SW_OTHERUNZOOM = 4
'Private Const SW_OTHERZOOM = 2
'Private Const SW_PARENTCLOSING = 1
'Private Const SW_PARENTOPENING = 3
'Private Const SW_RESTORE = 9
'Private Const SW_SCROLLCHILDREN = &H1
'Private Const SW_SHOW = 5
'Private Const SW_SHOWDEFAULT = 10
'Private Const SW_SHOWMAXIMIZED = 3
'Private Const SW_SHOWMINIMIZED = 2
'Private Const SW_SHOWMINNOACTIVE = 7
'Private Const SW_SHOWNA = 8
'Private Const SW_SHOWNOACTIVATE = 4
'Private Const SW_SHOWNORMAL = 1
  
#If VBA7 Then
    Private Declare PtrSafe Function DefWindowProcW Lib "user32" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
    Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hWnd As LongPtr, ByVal nCmdShow As LongPtr) As LongPtr
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    
    Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
    Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare PtrSafe Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hInst As LongPtr, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As LongPtr
    Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
#Else
    Private Declare Function DefWindowProcW Lib "user32" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Private Declare Function ExtractIcon Lib "shell32.dll" Alias "ExtractIconA" (ByVal hInst As Long, ByVal lpszExeFileName As String, ByVal nIconIndex As Long) As Long
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#End If

Dim PrevStyle&
Dim OldWidth As Double, OldHeight As Double
Dim AllowResize As Boolean

Private Sub UserForm_Initialize()
#If VBA7 Then
    Dim lngIcon As LongPtr
    Dim lnghWnd As LongPtr
#Else
    Dim lngIcon As Long
    Dim lnghWnd As Long
#End If
Dim sUniText As String
'----------------------------------------------
    AllowResize = True
    OldWidth = Width
    OldHeight = Height
    If Val(Application.Version) < 9 Then
        lnghWnd = FindWindow("ThunderXFrame", Caption)  'XL97
    Else
        lnghWnd = FindWindow("ThunderDFrame", Caption)  'XL2000
    End If

    PrevStyle = GetWindowLong(lnghWnd, GWL_STYLE)
    SetWindowLong lnghWnd, GWL_STYLE, PrevStyle Or WS_SIZEBOX Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
'----------------------------------------------
#If VBA7 Then
    lngIcon = ExtractIcon(Application.HinstancePtr, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#Else
    lngIcon = ExtractIcon(Application.Hinstance, Application.Path & "\Excel.exe", 0) ' HinstancePtr
#End If
  
'    SendMessage lnghWnd, WM_SETICON, True, lngIcon
    SendMessage lnghWnd, WM_SETICON, False, lngIcon

    sUniText = "Caption hi" & ChrW(7875) & "n th" & ChrW(7883) & " Ti" & ChrW(7871) & "ng Vi" & ChrW(7879) & "t"
    DefWindowProcW lnghWnd, WM_SETTEXT, 0, StrPtr(sUniText)
 
'    SetUniText Me, "Caption hi" & ChrW(7875) & "n th" & ChrW(7883) & " Ti" & ChrW(7871) & "ng Vi" & ChrW(7879) & "t"
End Sub
Bài đã được tự động gộp:


Thì sẽ được thông báo tiếp là sai tại GetWindowLong. Rồi sai ở SetWindowLong. Vì hiện thời trong khai báo của Set(Get)WindowLong thì hwnd As Long cả ở #If. Phải sửa thành As LongPtr.

Đã nói rồi. Code sai rất nhiều chỗ chứ không chỉ chỗ hWnd đâu. Sửa xong Set(Get)WindowLong thì sẽ thấy tiêu đề tiếng Việt không có do code trong FormCaptionUnicode cũng sai.
Quá tuyệt diệu !!
học lập trình đúng là càng đi sâu càng hay :D.
Cám ơn bác nhiều.
 
Upvote 0
Kính chào các bác . em có 1 form nhập liệu , tại ComboBox1 có giá trị là ngày tháng . ComboBox2 sẽ phụ thuộc vào ComboBox1, iem chạy câu lệnh thì nó báo lỗi Range .
Mong các bác chỉ giáo
 

File đính kèm

Upvote 0
Kính chào các bác . em có 1 form nhập liệu , tại ComboBox1 có giá trị là ngày tháng . ComboBox2 sẽ phụ thuộc vào ComboBox1, iem chạy câu lệnh thì nó báo lỗi Range .
Mong các bác chỉ giáo
"a4" & Rows.Count = "a41048576"
Excel không có ô a41048576
Sửa
Mã:
"a4" & Rows.Count
Thành
Mã:
"a" & Rows.Count
Tôi chỉ debug đến đó.
 
Upvote 0
Anh chị em cho mình hỏi làm sao để ẩn form (chứ không phải thoát) và mình có thể làm việc trên bảng tính của excel
 
Upvote 0
Phải vầy không bạn?
Mã:
UserForm1.Hide
Cảm ơn anh. Em tim được bài theo yêu cầu của mình rồi.
 
Upvote 0
Mình theo dõi các trang về "VẤN ĐỀ FORM" nhưng chưa thấy bài viết nào nói về cách nhập dữ liệu là đoạn text vào TextBox trên Form, để chép vào 1 cell trên Sheet. Nên mình muốn nhờ các ACE giúp mình vấn đề này nhé.
Mình tạo một form (như hình - có file đính kèm)
form.png
.
Mình muốn nhập đoạn text từ word (xem hình)
văn thử.png
nếu ...
copy.png
.
Nên mình mong các ACE có thể giúp mình - code hay sửa thuộc tính của textBox "BẢNG NHẬP THÊM NỘI DUNG" - để có thể chép vào textBox trên Form này thì toàn bộ được chép vào 1 cell trong cột "C" thuộc sheetNH
Xin cám ơn nhiều
 

File đính kèm

Upvote 0
Mình theo dõi các trang về "VẤN ĐỀ FORM" nhưng chưa thấy bài viết nào nói về cách nhập dữ liệu là đoạn text vào TextBox trên Form, để chép vào 1 cell trên Sheet. Nên mình muốn nhờ các
Văn bản từ Word có nhiều dòng trong khi textbox hiện tại không phục vụ nhiều dòng.

Vào VBE -> chọn TextBox -> trong cửa sổ Properties chuyển thuộc tính MultiLine thành True.textbox.JPG
 
Upvote 0
rất cám ơn anh Batman1!
Hỏi nhờ thêm anh:
Nếu muốn đưa hình vào textBox đó, thì phải viết lệnh code để chép hình vào ôCell trong cột "C" của Sheet
Hay chỉ cần chỉnh thuộc tính trong properti?
thanks you
 
Lần chỉnh sửa cuối:
Upvote 0
rất cám ơn anh Batman1!
Hỏi nhờ thêm anh:
Nếu muốn đưa hình vào textBox đó, thì phải viết lệnh code để chép hình vào ôCell trong cột "C" của Sheet
Hay chỉ cần chỉnh thuộc tính trong properti?
Cảm ơn you
Bạn muốn thêm hình vào đâu? Vào TextBox? Để làm gì? Vào cell? Vào cell nào, lấy hình từ đâu?
Hãy tập nói rõ, nói chi tiết, nói cả câu thay vì nửa câu.

Hỏi mà như đánh đố người khác thì bó tay.

Bạn chắc cám ơn batman1 chứ không phải cám ơn bạn you nào đó?
 
Upvote 0
Bạn muốn thêm hình vào đâu? Vào TextBox? Để làm gì? Vào cell? Vào cell nào, lấy hình từ đâu?
Hãy tập nói rõ, nói chi tiết, nói cả câu thay vì nửa câu.

Hỏi mà như đánh đố người khác thì bó tay.

Bạn chắc cám ơn batman1 chứ không phải cám ơn bạn you nào đó?
xin lỗi -gõ chữ "t-h-a-n-k-s you" mà tự động ra chữ CÁM ƠN - tiếng việt, còn chữ YOU vẫn giữ nguyên.
Ý mình muốn hỏi nhờ anh xem:
vì trong khi copy đoạn văn có hình/bảng table số liệu từ word để chèn vào ô cell, bằng cách dán vào textBox của Form, thì hình không thấy hiển thị và bảng table thì không còn đường viền bảng nữa, trong Ô cell của sheet
Nhờ anh xem hình:cop hinh.png
Vậy như hình và bảng biểu, muốn add vào textBox, thì cần viết CODE hay thủ thuật nào khác không?
Nếu được anh cho giúp code/thủ thuật này.
Xin cám ơn anh nhiều
 
Upvote 0
vậy trong form có tool nào nhận hình ảnh không? tool nào nhận bảng biểu vậy - anh Batman1?
xin cám ơn
Có thể nhập ảnh vào Image. Không nhập text được. Mọi cái phải ở dạng ảnh mới nhập vào Image được.
Tốt nhất hãy cho biết mục đích cuối cùng là gì. Đừng chọn một đường đi nhất định (Form+TextBox) rồi hỏi mọi người làm sao đi được.
Hãy cho biết chi tiết các trình tự thao tác. Vd. đã có Word mở? Người dùng sẽ chuyển qua lại giữa Excel và Word? Tức: chuyển sang Word -> chọn một "đoạn" (chỉ chọn hay chọn và nhấn Ctrl + C để copy vào ClipBoard?) -> chuyển sang Excel -> nhấn Ctrl + V để "dán" vào sheet?. Hoặc là thay cho Ctrl + V, vì nó cho kết quả không đúng ý, thì cần làm gì đó để được kết quả mong muốn?

Kết quả mong muốn là gì? Có cần chỉnh sửa cái vừa copy vào không? Nếu có thì văn bản phải được dán ở dạng văn bản. Nếu không có nhu cầu chỉnh sửa cái vừa dán vào thì toàn bộ có thể dán ở dạng ảnh.

Hãy mô tả tỉ mỉ để người giúp có thể chọn hướng đi thích hợp.
 
Upvote 0
Có thể nhập ảnh vào Image. Không nhập text được. Mọi cái phải ở dạng ảnh mới nhập vào Image được.
Tốt nhất hãy cho biết mục đích cuối cùng là gì. Đừng chọn một đường đi nhất định (Form+TextBox) rồi hỏi mọi người làm sao đi được.
....
Hãy mô tả tỉ mỉ để người giúp có thể chọn hướng đi thích hợp.
Rất cám ơn anh đã quan tâm điều mình đang muốn thực hiện.
Trong văn bản word, có bảng biểu (dạng cột hay biểu đồ) và hình ảnh (dạng vẽ hay dạng chụp) nhằm minh họa, rất khó đưa vào các Ô trong bảng table của word - phải làm thủ công, nên khi tổng hợp báo cáo phải thủ công lại. (xem minh họa)
1570416863611.png
Nên mình nghĩ tạo một form NHẬP LIỆU trong excel, để nhập vào form các loại hình (vẽ/chụp/biểu đồ), các loại bảng (table cột/ngang), chuyển đến trang sheet.
sau đó khi thống kê, sẽ trích xuât qua sheet khác từ sheet này.
Nguồn dữ liệu là các loại hình (vẽ/chụp/biểu đồ), các loại bảng (table cột/ngang) có thể trong một file word nào đó, hay excel nào đó, hay từ phần mềm khác (như ChemBioOffice, MatLab..)
Mục tiêu mình muốn là: từ các nguồn dữ liệu có được [các loại hình (vẽ/chụp/biểu đồ), các loại bảng (table cột/ngang)], mình sẽ Ctrl+C toàn bộ đoạn văn/hình/bảng .... đó, đem qua Form Nhập Liệu, Ctrl+V vào một tool nào đó của Form Nhập liệu này, để up dữ liệu này vào được 1 ô cell trong sheet (như form vừa gửi, mình đặt vào các ô tại cột "C").
Mong anh giúp dùm
Xin cảm ơn nhiều
 

File đính kèm

Upvote 0
Rất cám ơn anh đã quan tâm điều mình đang muốn thực hiện.
Tóm lại bạn muốn trong quá trình làm việc: chuyển sang một ứng dụng nào đó vd. Word -> chọn 1 vùng -> Ctrl + C -> chuyển sang Excel Form -> Ctrl + V vào một control nào đó -> chuyển sang ứng dụng nào đó vd. ChemBioOffice, MatLab -> chọn 1 vùng -> Ctrl + C -> chuyển sang Excel Form -> Ctrl + V vào một control nào đó -> chuyển sang ứng dụng nào đó ... vân vân và mây mây?
Nếu như trên thì tôi đã viết rồi. Nếu bạn chọn vùng có cả ảnh và/hoặc text thì khi dán vào TextBox sẽ mất ảnh. Nếu dán vào Image thì chỉ dán được ở dạng ảnh, tức cả text cũng chỉ là ảnh (một phần của ảnh gồm text và ảnh). Tức text trong ảnh không chỉnh sửa về sau được. Trong VBA không có control nào vừa viết được văn bản vừa chèn được ảnh.
 
Upvote 0
Trong Form tìm kiếm, lưu tạm thời những những mặt hàng đã chọn trong List và sắp xếp theo thứ tự đã chọn

Anh chị giúp em như sau
Ví dụ : em có đơn hàng cần phải nhập vào sheet TH (giả sử đơn hàng có 3 mặt hàng )
1/ Mặt hàng 08
2/ Mặt hàng 10
3/ Mặt hàng 01

Khi nhập em làm như sau:
Mở form rồi tìm Mặt hàng 08 -> chọn nó -> bấm nút Chọn -> cho nó gán xuống sheet TH
Rồi tiếp tục mở form để tìm Mặt hàng 10
Và tiếp tục cho đến hết
Như vậy rất mất thời gian

Bây giờ em muốn thế này
1/ Sau khi tìm được Mặt hàng 08 thì tích (chọn ) vào ô vuông bên trái và tạm lưu mặt hàng này vào đâu đó, Rồi em tiếp tục tìm Mặt hàng 10 và tích chọn vào ô vuông, sau đó tiếp tục tìm …Tìm hết những mặt hàng trong đơn hàng thì bấm CommandButton “Chọn” để nó gán các mặt hàng đã chọn gán xuống sheet TH

2/ Những mặt hàng chọn trước thì ưu tiên đứng trước trước khi gán xuống sheet TH
(giả sử 3 mặt hàng trong đơn hàng trên sẽ gán xuống sheet TH ở các dòng 10, 11, 12
Thì dòng 10 = Mặt hàng 08 (do chọn đầu tiên)
dòng 11 = Mặt hàng 10 (do chọn thứ 2)
dòng 12 = Mặt hàng 01 (do chọn thứ 3)

3/ Và sau khi gán xuống sheet TH thì trong Form sẽ xóa các mặt hàng đã lưu tạm trên để có thể tìm cho đơn hàng mới

From này do em sưu tầm
Em nhờ các anh chị giúp em, em cảm ơn
 

File đính kèm

Upvote 0
From này do em sưu tầm
Em nhờ các anh chị giúp em, em cảm ơn
Tập tin tên là Form_batman1.xlsm nhưng tôi e rằng code không là của tôi hoặc chỉ một vài chỗ là của tôi.
Nhìn vd.
EndR = .Cells(65000, 8).End(xlUp).Row
Arr = .Range(.Cells(10, 8), .Cells(EndR, 10)).Value
thì chắc chắn không là của tôi vì:
- tôi thường dùng lastRow
- tôi thường dùng Cells(Rows.Count, "H"), Cells(10, "H"), Cells(lastRow, "J")
- tôi thường kiểm tra xem có dữ liệu hay không. Nếu có mới nhập vào Arr.

Gọi là Form_batman1.xlsm thì tôi không dám nhận là của mình.
 
Upvote 0
Tập tin tên là Form_batman1.xlsm nhưng tôi e rằng code không là của tôi hoặc chỉ một vài chỗ là của tôi.
Nhìn vd.

thì chắc chắn không là của tôi vì:
- tôi thường dùng lastRow
- tôi thường dùng Cells(Rows.Count, "H"), Cells(10, "H"), Cells(lastRow, "J")
- tôi thường kiểm tra xem có dữ liệu hay không. Nếu có mới nhập vào Arr.

Gọi là Form_batman1.xlsm thì tôi không dám nhận là của mình.

Form này do em sưu tầm trên mạng, nhưng vừa rồi anh có giúm em sửa form ở
Em thường hay sửa = cách thêm tên người sửa vào tiêu đề code hay file mà các thành viên đã chỉnh sửa giúp để em dễ phân biệt mà thôi
Thành thật xin lỗi anh
 
Upvote 0
.............
Nếu như trên thì tôi đã viết rồi.......
Tức text trong ảnh không chỉnh sửa về sau được. Trong VBA không có control nào vừa viết được văn bản vừa chèn được ảnh.
Sory anh Batman1
nếu anh cho xin đường link bài viết mà anh đã viết rồi, cho mình tham khảo - được không?
mình có tìm trong :".. Các câu hỏi về Form trong Excel VBA"
mà không thấy!
Xin cám ơn
 
Upvote 0
Trong Form TK, lưu tạm thời những những mặt hàng đã chọn trong List và sắp xếp theo thứ tự đã chọn
Anh chị giúp em như sau
Ví dụ : em có đơn hàng cần phải nhập vào sheet TH (giả sử đơn hàng có 3 mặt hàng )
PHP:
1/ Mặt hàng 08                2/ Mặt hàng 10
3/ Mặt hàng 01
Khi nhập em làm như sau:
Mở form rồi tìm Mặt hàng 08 -> chọn nó -> bấm nút Chọn -> cho nó gán xuống sheet TH; Rồi tiếp tục mở form để tìm Mặt hàng 10
Và tiếp tục cho đến hết . . . Như vậy rất mất thời gian
Bây giờ em muốn thế này
1/ Sau khi tìm được Mặt hàng 08 thì tích (chọn ) vào ô vuông bên trái và tạm lưu mặt hàng này (1) vào đâu đó, Rồi em tiếp tục tìm Mặt hàng 10 và tích chọn vào ô vuông, sau đó tiếp tục tìm …Tìm hết những mặt hàng trong đơn hàng thì bấm CommandButton “Chọn” để nó gán các mặt hàng đã chọn gán xuống sheet TH
. . . . . . . .
(1) Chắc đó nên là 1 ListBox thứ 2
Về việc này bạn đến đây tham khảo xem sao: https://www.giaiphapexcel.com/diend...a-nội-dung-trên-litsbox-vào-file-đóng.115020/
 
Upvote 0
Sory anh Batman1
nếu anh cho xin đường link bài viết mà anh đã viết rồi, cho mình tham khảo - được không?
mình có tìm trong :".. Các câu hỏi về Form trong Excel VBA"
mà không thấy!
Ý tôi là "đã viết rồi" ở những bài trước. Cụ thể là ở bài #319 và bài #321
TextBox chỉ nhận văn bản thôi. Ảnh thì quên đi.
...
Có thể nhập ảnh vào Image. Không nhập text được. Mọi cái phải ở dạng ảnh mới nhập vào Image được.
 
Upvote 0
Em thường hay sửa = cách thêm tên người sửa vào tiêu đề code hay file mà các thành viên đã chỉnh sửa giúp để em dễ phân biệt mà thôi
Thao tác:
1. Sau mỗi lần tìm kiếm thì chọn trong ListBox 1 hoặc nhiều kết quả rồi nhấn Chọn. Lúc đó các mục được chọn sẽ được nhớ vào mảng chisochon. Nếu không nhấn Chọn thì không gì được nhớ.
2. Sau khi nhấn Chọn thì focus lại ở TextBox để tìm kiếm tiếp.
3. Sau một hồi tìm kiếm và Chọn thì nhấn nút Nhập để nhập xuống sheet. Dữ liệu sẽ được ghi xuống sheet. Tiếp theo lại có thể thực hiện Tìm -> Chon -> Nhap mới.
4. Khi muốn đóng Form thì nhấn Thoát. Nếu sau một hồi Tìm -> Chọn mà không muốn ghi xuống shett (nghĩ lại, bập bập?) thì nhấn Thoát để đóng Form.

Cách thức code phải hoạt động như thế. Nhưng có như thế hay không thì tự kiểm tra.

Xóa toàn bộ code trong Form.

Dán code sau vào Form
Mã:
Private somuc As Long, Arr(), chisochon()

Private Sub CB_Tim_Click()
Dim lastRow As Long, r As Long, c As Long, count As Long
Dim arrKQ(), chiso() As Long
Dim MaHHTim As String, timthay As Boolean
    MHList.Clear
    count = 0
    MaHHTim = UCase(Me.NhomHang.Value)
    For r = 1 To UBound(Arr) - 1
        timthay = InStr(UCase(Arr(r, 1)), MaHHTim) > 0
        If Not timthay Then
            timthay = InStr(UCase(Arr(r, 2)), MaHHTim) > 0
            If Not timthay Then timthay = InStr(UCase(Arr(r, 3)), MaHHTim) > 0
        End If
        If timthay Then
            count = count + 1
            ReDim Preserve chiso(1 To count)
            chiso(count) = r
        End If
    Next r
    If count Then
        ReDim arrKQ(1 To count, 1 To 4)
        For r = 1 To count
            c = chiso(r)
            arrKQ(r, 1) = Arr(c, 1)
            arrKQ(r, 2) = Arr(c, 2)
            arrKQ(r, 3) = Arr(c, 3)
            arrKQ(r, 4) = c
        Next r
        MHList.List = arrKQ
    Else
        MsgBox "No noi dung"
    End If
End Sub

Private Sub cmdChon_Click()
Dim k As Long
    For k = 0 To MHList.ListCount - 1
        If MHList.Selected(k) Then
            somuc = somuc + 1
            ReDim Preserve chisochon(1 To somuc)
            chisochon(somuc) = MHList.List(k, 3)
        End If
    Next
    MHList.Clear
    NhomHang.Value = Empty
    NhomHang.SetFocus
End Sub

Private Sub cmdNhap_Click()
Dim lastRow As Long, k As Long, r As Long, result()
    If somuc < 1 Then Exit Sub
    ReDim result(1 To somuc, 1 To 3)
    lastRow = ThisWorkbook.Worksheets("TH").Cells(Rows.count, "AH").End(xlUp).Row + 1
    For k = 1 To UBound(chisochon)
        r = chisochon(k)
        result(k, 1) = Arr(r, 1)
        result(k, 2) = Arr(r, 2)
        result(k, 3) = Arr(r, 3)
    Next k
    ThisWorkbook.Worksheets("TH").Cells(lastRow, "AH").Resize(UBound(result), UBound(result, 2)).Value = result
    somuc = 0
    Erase chisochon
    MHList.Clear
    NhomHang.Value = Empty
    NhomHang.SetFocus
End Sub

Private Sub Thoat_Click()
    Unload Me
End Sub

Private Sub UserForm_Initialize()
Dim lastRow As Long
    With Sheets("Note1")
        lastRow = .Cells(Rows.count, "H").End(xlUp).Row
        Arr = .Range("H10:J" & lastRow + 1).Value
    End With
    
    With Me.MHList
        .ColumnCount = 3
        .List = Arr
    End With
    somuc = 0
    Erase chisochon
    NhomHang.SetFocus
End Sub

Private Sub NhomHang_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 40 Then MHList.SetFocus
End Sub

Private Sub CB_Tim_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 40 Then MHList.SetFocus
End Sub
 
Upvote 0
Bạn tham khảo cách này, có vẻ trực quan hơn nè:
 

File đính kèm

Upvote 0
Khi nhập em làm như sau:
Mở form rồi tìm Mặt hàng 08 -> chọn nó -> bấm nút Chọn -> cho nó gán xuống sheet TH
Rồi tiếp tục mở form để tìm Mặt hàng 10
Và tiếp tục cho đến hết
Như vậy rất mất thời gian
Chỉ mở Form 1 lần và đóng khi chán Tim - Nhap.

Thực ra cũng chả cần ListBox hay mảng tạm thời. Cứ chọn xong trong ListBox thì nhấn Nhap để ghi xuống sheet thôi. Còn nếu nghĩ lại không muốn ghi thì lại tìm mới thôi. Khi nào chán thì đóng Form.

Lưu ý: Trên Form phải có 3 nút: Nút Chon của bạn đổi tên thành cmdNhap và có caption = Nhap .
Code
Mã:
Private Arr()

Private Sub CB_Tim_Click()
Dim lastRow As Long, r As Long, c As Long, count As Long
Dim arrKQ(), chiso() As Long
Dim MaHHTim As String, timthay As Boolean
    MHList.Clear
    count = 0
    MaHHTim = UCase(Me.NhomHang.Value)
    For r = 1 To UBound(Arr) - 1
        timthay = InStr(UCase(Arr(r, 1)), MaHHTim) > 0
        If Not timthay Then
            timthay = InStr(UCase(Arr(r, 2)), MaHHTim) > 0
            If Not timthay Then timthay = InStr(UCase(Arr(r, 3)), MaHHTim) > 0
        End If
        If timthay Then
            count = count + 1
            ReDim Preserve chiso(1 To count)
            chiso(count) = r
        End If
    Next r
    If count Then
        ReDim arrKQ(1 To count, 1 To 4)
        For r = 1 To count
            c = chiso(r)
            arrKQ(r, 1) = Arr(c, 1)
            arrKQ(r, 2) = Arr(c, 2)
            arrKQ(r, 3) = Arr(c, 3)
        Next r
        MHList.List = arrKQ
    Else
        MsgBox "No noi dung"
    End If
End Sub

Private Sub cmdNhap_Click()
Dim lastRow As Long, count As Long, k As Long, result()
    ReDim result(1 To MHList.ListCount, 1 To 3)
    For k = 0 To MHList.ListCount - 1
        If MHList.Selected(k) Then
            count = count + 1
            result(count, 1) = MHList.List(k, 0)
            result(count, 2) = MHList.List(k, 1)
            result(count, 3) = MHList.List(k, 2)
        End If
    Next
    If count Then
        With ThisWorkbook.Worksheets("TH")
            lastRow = .Cells(Rows.count, "AH").End(xlUp).Row + 1
            .Cells(lastRow, "AH").Resize(count, UBound(result, 2)).Value = result
        End With
    End If
    MHList.Clear
    NhomHang.Value = Empty
    NhomHang.SetFocus
End Sub

Private Sub Thoat_Click()
    Erase Arr
    Unload Me
End Sub

Private Sub UserForm_Initialize()
Dim lastRow As Long
    With Sheets("Note1")
        lastRow = .Cells(Rows.count, "H").End(xlUp).Row
        Arr = .Range("H10:J" & lastRow + 1).Value
    End With
    
    With Me.MHList
        .ColumnCount = 3
        .List = Arr
    End With
    NhomHang.SetFocus
End Sub

Private Sub NhomHang_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 40 Then MHList.SetFocus
End Sub

Private Sub CB_Tim_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    If KeyCode = 40 Then MHList.SetFocus
End Sub
 
Upvote 0
Cám ơn các anh, em sẽ nghiên cứu từng bài, nếu có thêm thắc mắc em nhờ các anh giải thích
 
Upvote 0
Bạn tham khảo cách này, có vẻ trực quan hơn nè:
Các anh cho em hỏi:
1/ Để người nhập có cơ hội sửa sai là: ví dụ người nhập vô tình chọn sai mã từ MHList gán xuống ListBox lbSelec (giả sử ListBox lbSelec có Mặt hàng08 và nhiều mặt hàng khác) bây giờ người ta muốn xóa Mặt hàng 08 thì code viết cho CommandButton "Xoa" như thế nào
2/ Tại sao anh tạo được cái Liststyle hình tròn còn em chỉ làm hình vuông (cái này không quan trọng mà em chỉ tò mò)
Các anh viết code bổ sung giùm (do cái này em điếc), em cảm ơn!
 

File đính kèm

Upvote 0
2/ Tại sao anh tạo được cái Liststyle hình tròn còn em chỉ làm hình vuông (cái này không quan trọng mà em chỉ tò mò)
Thì người ta thiết lập cho ListBox (ở trên) MultiSelect là fmMultiSelectSingle nên nó là Option (tròn). Hậu quả là ở ListBox (ở trên) chỉ chọn được 1 - chọn cái này thì cái kia mất. Nhưng do người ta dùng Click nên mỗi lần click thì mục được chọn sẽ nhập luôn vào ListBox dưới. Do vậy dù chỉ chọn được 1 nhưng không ảnh hưởng. Tuy nhiên đẻ ra vấn đề là nếu tay run run và click nhầm mục ở trên/dưới thì nó đã được nhập vào ListBox dưới rồi. Lúc này lại phải tìm cách xóa đi.
Còn bạn thiết lập MultiSelect là fmMultiSelectMulti nên nó là CheckBox. Tức có thể chọn nhiều CheckBox.

Option: chọn 1 có 1. Chọn tiếp 2 thì 2 được chọn và 1 bị mất chọn.
CheckBox: chọn 1 có 1. Chọn tiếp 2 thì có 2 và 1 vẫn được chọn.
Các anh viết code bổ sung giùm (do cái này em điếc), em cảm ơn!
Cái này bạn nhờ tác giả thôi.
 
Upvote 0
Tạm thời bạn thử 3 cách sau:
(1) (Chắc dễ làm nhất): Xóa toàn bộ dữ liệu trong ListBox lbSelect & "làm" lại thôi;
Nhớ đưa tham biến Sel về trị thích hợp & tạo lại 3 tiêu đề cột cho ListBox đó
(2) Duyệt các dòng trong ListBox này & đưa dữ liệu các dòng vô mảng (trừ dòng đang được chọn)
(Cách loại trừ dữ liệu dòng đang được chọn lại phải tham khảo cách mà ListBox MHList chọn 1 dòng)
Sau khi duyệt xong thì đưa mảng vừa có được trở thành lbSeLect.List
(3) Cùng nhau nghiên cứu tiếp hay chờ ai đó giúp cho . . . . cách nào đó hay hơn
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn bác đã chia sẻ, sự thật là lúc nhỏ cháu ăn nhiều chân gà lém, nên tay nó run run bẩm sinh luôn, đang bấm mà NTLH nhắn tin thì nó còn run gấp vạn ấy chứ. Để di chuyển các dòng dữ liệu có mấy cách: thêm nút bâm để ra lệnh di chuyển, click đúp vào dòng muốn di chuyển, hoặc dùng chức năng kéo thả ( cái này thấy hay mà ít người làm).
 
Upvote 0
Cảm ơn bác đã chia sẻ, sự thật là lúc nhỏ cháu ăn nhiều chân gà lém, nên tay nó run run bẩm sinh luôn, đang bấm mà NTLH nhắn tin thì nó còn run gấp vạn ấy chứ.
Ơ, tưởng đã về với nhau một nhà từ lâu rồi chứ. Hóa ra vẫn "cò cưa" thế à?
 
Upvote 0
Tay run nên cháu cưa không đổ, dạo này đang đi mài lại cưa, mài cưa còn khó hơn cả code cho chủ thớt này.
Thế thì lỗi là do tay run chứ đâu phải do cưa cùn mà phải mài lại cưa? Chữa không đúng bệnh rồi. Thảo nào mài đi mài lại cưa mà cưa vẫn không đổ. :D
 
Upvote 0
Thiết tưởng tay run cưa mới dễ . . . mọi chuyện

Thôi thì thấy viết Code dễ hơn thì nhường cho người khác cưa đi & viết Code cho chủ bài đăng (CBĐ) đi vậy!

/-(a, Ha, ha,. . . . . & CBĐ lưu ý chuyện này dùm nha!
 
Upvote 0
Thì ông bà )(ưa khuyên: 1 nghề cho chín hơn chín mười nghề mà!
 
Upvote 0
Cũng còn tùy, nghề chín và chưa chín đem lại lợi ích cho mình hay cho ai. Cứ cho là nghề kiếm tiền chưa chín, nhưng tốt hơn là vẫn làm nghề kiếm tiền (cho vợ con) hay làm nghề chín "ăn cơm nhà vác tù và hàng tổng" (cho ai đó)?
 
Upvote 0
Xin chào mọi người,
mình mới tập tành học vba
- mình có 1 file cần sửa lại dữ liệu sau khi đã cập nhật dữ liệu bên" sheet thông tin chuyển máy", mình muốn sửa lại dữ liệu tổng trên "sheet data MMTB". Để cập nhật lại thông tin nhà máy đang sử dụng máy cho đúng sau khi đã chuyển máy.
nhưng tới đây lại ko ra đúng .
Mong mọi người giúp e phần code này.

Cảm ơn mọi người nhiều./.
 

File đính kèm

Upvote 0
Private Sub Textcaphanmem_Change()
On Error Resume Next
Textcaphanmem.Text = Format(Textcaphanmem.Text, "#,##0")
End Sub

em dùng hàm này trong userfrom mà trong textbox thì hiện đúng nhưng trong file nhập excel thì bị thiều mất 3 số 0
VD như trong textbox nhập 2000000 textbox sẽ hiện 2,000,000 trong execl là 2.000.000
nhưng khi nhập 200000 texbox hiện 200.000 exel chỉ hiện 200
em đã chỉnh lại trong Format cells/Number/Custome đung như trong textbox rồi :(
 
Upvote 0
a6bb4d62ade54bbb12f4.png

ACE nào biết lỗi chỗ này chỉ hộ Mình được ko?
Số tấm = 1
Độ Dài = 1
Khổ Tôn = 1,08 (cái này mình gọi từ Worksheets ra)
txtKhoiLuong = txtDoDai * txtSoTam* txtKho phải chia cho 100 mới ra đúng kết quả mình cần.
txtThanhTien = txtKhoiLuong*txtDonGia/100 mới ra kết quả mà rõ bên trên mình đã chia trước rồi.
Con đây là Hình Ảnh khi không chia cho 100
acc.png
 
Lần chỉnh sửa cuối:
Upvote 0
Thay vì các tấm ảnh, sao bạn không đưa file lên để nhanh hơn có giải đáp từ công đồng;
 
Upvote 0
Sory mọi người, khi mình muốn gửi lên đây phần nhờ giúp đỡ về ChartOnForm:
Mình đã lục tìm các bài viết trên GPE về cách vẽ Biểu đồ Tương tác, và chèn các biểu đồ này lên Form
(bài #11: của Bác ndu96081631
)
(bài #1: của Bác ndu96081631
)
Nhưng tất cả không phải là nhiều biểu đồ tương tác khác trục, khác đơn vị với nhau lên chung 1 ChartOn Form
(xin xem file đính kèm)
http://www.mediafire.com/file/sl9hdeuuow7fkoe/Hoi-ChartOnForm.xlsm/file
Rất mong các anh chị giúp dùm cách chèn các biểu đồ tương tác khác nhau lên cùng 1 Chart On Form
Xin cám ơn
 

File đính kèm

Upvote 0
Em nhờ các bác giúp 4 trường hợp sau giúp:


1/ Code VBA để coppy sau VD: Sheet 1
Khi ta dang Mở File A ở Sheet 1 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet1 File C những cột A,B,C,D Nếu thỏa cột B có chữ "nhà xe" vào Sheet1 File A


2/ Code VBA để coppy sau VD: Sheet 2
Khi ta dang Mở Sheet2 File A ở Sheet 2 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet2 File C những cột A,B,C,D,E,F,G,H,I,K Nếu thỏa cột C Không có chữ "HQ" vào Sheet2 File A

3/ Code VBA để coppy sau VD: Sheet 3
Khi dang lam viec o Sheet3 FileA có các hàng dữ liệu liền nhau có các cột A,B,C,D,E và trong sheet đó có nút Coppy. Nếu Click vào nút Coppy mà thỏa mãn 2 điều kiện sau:
- Dieu kien 1: cột A trong Sheet3 FileC và cột A Sheet3 FileA (sheet và file hiện thời làm việc) có số số liệu trùng nhau.
- Dieu kien 2: cột F trong Sheet3 FileC không có dấu "x"
thì sẽ coppy các dữ liệu của các hàng ở Cột C,D,E của Sheet3 FileC sang các cột C,D,E của Sheet3 FileA
(lưu ý giúp: dữ liệu hãng ở Sheet3 FileA có thể ko liền nhau)

4/ Code VBA trong Form VD: Sheet 4
Trong 1 Form có 2 text boxt sau:
Text boxt 1, Text boxt 2
Khi nhập dữ liệu vào Text boxt 1 bấm enter thì Text boxt 2 ktra 3 ký tự đầu của
Text boxt 1 nếu có 3 chữ "kle" thì Text boxt 2 sẽ tự điền là "kh" còn ko có Text boxt 2 sẽ điền "nhà xe"
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
AE cho mình xin Code khi Gõ vào trong Combobox sẽ tìm kiếm theo điều kiện
giống với mã Hàng bên Cột A.
Mình nghỉ là ComboBox không dành cho bạn gõ vô, mà bạn có thể sẽ phải chọn 1 trong những dòng dữ liệu từ nó mà thôi.
 
Upvote 0
. . . . . . . . . . . .:D
 

File đính kèm

Upvote 0
Em nhờ các bác giúp 4 trường hợp sau giúp:


1/ Code VBA để coppy sau VD: Sheet 1
Khi ta dang Mở File A ở Sheet 1 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet1 File C những cột A,B,C,D Nếu thỏa cột B có chữ "nhà xe" vào Sheet1 File A


2/ Code VBA để coppy sau VD: Sheet 2
Khi ta dang Mở Sheet2 File A ở Sheet 2 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet2 File C những cột A,B,C,D,E,F,G,H,I,K Nếu thỏa cột C Không có chữ "HQ" vào Sheet2 File A

3/ Code VBA để coppy sau VD: Sheet 3
Khi dang lam viec o Sheet3 FileA có các hàng dữ liệu liền nhau có các cột A,B,C,D,E và trong sheet đó có nút Coppy. Nếu Click vào nút Coppy mà thỏa mãn 2 điều kiện sau:
- Dieu kien 1: cột A trong Sheet3 FileC và cột A Sheet3 FileA (sheet và file hiện thời làm việc) có số số liệu trùng nhau.
- Dieu kien 2: cột F trong Sheet3 FileC không có dấu "x"
thì sẽ coppy các dữ liệu của các hàng ở Cột C,D,E của Sheet3 FileC sang các cột C,D,E của Sheet3 FileA
(lưu ý giúp: dữ liệu hãng ở Sheet3 FileA có thể ko liền nhau)

4/ Code VBA trong Form VD: Sheet 4
Trong 1 Form có 2 text boxt sau:
Text boxt 1, Text boxt 2
Khi nhập dữ liệu vào Text boxt 1 bấm enter thì Text boxt 2 ktra 3 ký tự đầu của
Text boxt 1 nếu có 3 chữ "kle" thì Text boxt 2 sẽ tự điền là "kh" còn ko có Text boxt 2 sẽ điền "nhà xe"
nhờ các bác giúp em với, em cần quá
 
Upvote 0
nhờ các bác giúp em với, em cần quá
Đối với trường hợp 1, 2, 3 Anh có thể tham khảo Advance Filter. Nhưng Anh đã hỏi trong này em sẽ trình bày bằng VBA, Anh tham khảo.
(Lưu ý, cần mở song song 2 file)
Bài đã được tự động gộp:
 

File đính kèm

Upvote 0
Đối với trường hợp 1, 2, 3 Anh có thể tham khảo Advance Filter. Nhưng Anh đã hỏi trong này em sẽ trình bày bằng VBA, Anh tham khảo.
(Lưu ý, cần mở song song 2 file)
Bài đã được tự động gộp:
em cảm ơn anh rất nhiều.
1/ nhưng nếu FileA và FileC lưu ở 2 Folder khác nhau thì đường dẫn mình thay như nào ? và ở chỗ nào vậy anh ?
2/ ở mục 2 có vấn đề là coppy điều kiện là: Không có chữ "HQ"
Khi ta dang Mở Sheet2 File A ở Sheet 2 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet2 File C những cột A,B,C,D,E,F,G,H,I,K Nếu thỏa cột C Không có chữ "HQ" vào Sheet2 File A
3/ Em đã thử nhưng coppy lần 1 thì ok nhưng nếu click tiếp thì nó lại coppy lần nữa. Giờ nếu trùng nhau thì nó không coppy nữa có được không ạ ?

em cảm ơn
 
Lần chỉnh sửa cuối:
Upvote 0
em cảm ơn anh rất nhiều. nhưng nếu FileA và FileC lưu ở 2 Folder khác nhau thì đường dẫn mình thay như nào ? và ở chỗ nào vậy anh ?
em cảm ơn
Em không đặt đường dẫn trong file đó. Nếu anh cần đặt đường dẫn thì tải lại file này nhé.
 

File đính kèm

Upvote 0
Em không đặt đường dẫn trong file đó. Nếu anh cần đặt đường dẫn thì tải lại file này nhé.
Em cảm ơn. còn 3 mục dưởi nhà anh giúp
1/ ở mục 2 có vấn đề là coppy điều kiện là: Không có chữ "HQ"
Khi ta dang Mở Sheet2 File A ở Sheet 2 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet2 File C những cột A,B,C,D,E,F,G,H,I,K Nếu thỏa cột C Không có chữ "HQ" vào Sheet2 File A
2/ Em đã thử nhưng coppy lần 1 thì ok nhưng nếu click tiếp thì nó lại coppy lần nữa. Giờ nếu trùng nhau thì nó SẼ coppy ĐÈ lên cái cũ có được không ạ ?
3/
Code VBA để coppy sau VD: Sheet 3
Khi dang lam viec o Sheet3 FileA có các hàng dữ liệu liền nhau có các cột A,B,C,D,E,F,G,H,I,J,K và trong sheet đó có nút Coppy. Nếu Click vào nút Coppy mà thỏa mãn 2 điều kiện sau:
- Dieu kien 1: cột A trong Sheet3 FileC và cột A Sheet3 FileA (sheet và file hiện thời làm việc) có số số liệu trùng nhau.
- Dieu kien 2: cột F trong Sheet3 FileC không có dấu "x"
thì sẽ coppy các dữ liệu của các hàng ở Cột C,D,E của Sheet3 FileC sang các cột C,D,E của Sheet3 FileA
Cũng tương tự như vậy cùng 1 nút Click trên cũng kiểm tra cả phần thanh toán lần 2:
- Dieu kien 1: cột A trong Sheet3 FileC và cột A Sheet3 FileA (sheet và file hiện thời làm việc) có số số liệu trùng nhau.
- Dieu kien 2: cột K trong Sheet3 FileC không có dấu "x"
thì sẽ coppy các dữ liệu của các hàng ở Cột G,H,I của Sheet3 FileC sang các cột H,I,J của Sheet3 FileA
(lưu ý giúp: dữ liệu hãng ở Sheet3 FileA có thể ko liền nhau)
Em có gửi file sửa đổi thêm kèm theo đây ạ
em cảm ơn anh nhiều
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Em cảm ơn. còn 3 mục dưởi nhà anh giúp
1/ ở mục 2 có vấn đề là coppy điều kiện là: Không có chữ "HQ"
Khi ta dang Mở Sheet2 File A ở Sheet 2 có 1 nút "coppy" Khi click vào Nút "Coppy" thì Coppy tất cả các hàng trong Sheet2 File C những cột A,B,C,D,E,F,G,H,I,K Nếu thỏa cột C Không có chữ "HQ" vào Sheet2 File A
2/ Em đã thử nhưng coppy lần 1 thì ok nhưng nếu click tiếp thì nó lại coppy lần nữa. Giờ nếu trùng nhau thì nó SẼ coppy ĐÈ lên cái cũ có được không ạ ?
3/
Code VBA để coppy sau VD: Sheet 3
Khi dang lam viec o Sheet3 FileA có các hàng dữ liệu liền nhau có các cột A,B,C,D,E,F,G,H,I,J,K và trong sheet đó có nút Coppy. Nếu Click vào nút Coppy mà thỏa mãn 2 điều kiện sau:
- Dieu kien 1: cột A trong Sheet3 FileC và cột A Sheet3 FileA (sheet và file hiện thời làm việc) có số số liệu trùng nhau.
- Dieu kien 2: cột F trong Sheet3 FileC không có dấu "x"
thì sẽ coppy các dữ liệu của các hàng ở Cột C,D,E của Sheet3 FileC sang các cột C,D,E của Sheet3 FileA
Cũng tương tự như vậy cùng 1 nút Click trên cũng kiểm tra cả phần thanh toán lần 2:
- Dieu kien 1: cột A trong Sheet3 FileC và cột A Sheet3 FileA (sheet và file hiện thời làm việc) có số số liệu trùng nhau.
- Dieu kien 2: cột K trong Sheet3 FileC không có dấu "x"
thì sẽ coppy các dữ liệu của các hàng ở Cột G,H,I của Sheet3 FileC sang các cột H,I,J của Sheet3 FileA
(lưu ý giúp: dữ liệu hãng ở Sheet3 FileA có thể ko liền nhau)
Em có gửi file sửa đổi thêm kèm theo đây ạ
em cảm ơn anh nhiều
Xin hỏi cả nhà câu lệnh này có gì sai mà hệ thống bao lỗi như hình ảnh ở dưới

Mã:
Sub Ktoan_thanhtoan()
Dim Rng As Range, vData1, i As Integer, lr As Integer, vData, vRs

lr = ThisWorkbook.Sheets(2).Range("L" & Rows.Count).End(xlUp).Row

For i = 2 To lr
vData = ThisWorkbook.Sheets(2).Cells(i, 42)
    If vData <> "x" Then
        vData1 = ThisWorkbook.Sheets(2).Cells(i, 1)
On Error GoTo b
        ThisWorkbook.Sheets(2).Cells(i, 39) = Application.WorksheetFunction.VLookup(vData1, Workbooks("KToan_Lich_xe_T10_den_T12_2019.xlsx").Sheets(3).Range("L5:BA" & Workbooks("KToan_Lich_xe_T10_den_T12_2019.xlsx").Sheets(3).Range("L" & Rows.Count).End(xlUp).Row), 39, False)
        ThisWorkbook.Sheets(2).Cells(i, 40) = Application.WorksheetFunction.VLookup(vData1, Workbooks("KToan_Lich_xe_T10_den_T12_2019.xlsx").Sheets(3).Range("L5:BA" & Workbooks("KToan_Lich_xe_T10_den_T12_2019.xlsx").Sheets(3).Range("L" & Rows.Count).End(xlUp).Row), 40, False)
        ThisWorkbook.Sheets(2).Cells(i, 41) = Application.WorksheetFunction.VLookup(vData1, Workbooks("KToan_Lich_xe_T10_den_T12_2019.xlsx").Sheets(3).Range("L5:BA" & Workbooks("KToan_Lich_xe_T10_den_T12_2019.xlsx").Sheets(3).Range("L" & Rows.Count).End(xlUp).Row), 41, False)

GoTo c
b:
        ThisWorkbook.Sheets(2).Cells(i, 39) = "Nothing"
        ThisWorkbook.Sheets(2).Cells(i, 40) = "Nothing"
        ThisWorkbook.Sheets(2).Cells(i, 41) = "Nothing"

c:
    End If
     

Next i
End Sub
 

File đính kèm

  • Untitled.png
    Untitled.png
    4.1 KB · Đọc: 9
  • Untitled1.png
    Untitled1.png
    25.1 KB · Đọc: 11
Upvote 0
Đối với trường hợp 1, 2, 3 Anh có thể tham khảo Advance Filter. Nhưng Anh đã hỏi trong này em sẽ trình bày bằng VBA, Anh tham khảo.
(Lưu ý, cần mở song song 2 file)
Bài đã được tự động gộp:
trong trường hợp 3 ở FileC mình coppy cả 1 sheet3 thành Sheet6 thì báo lỗi (nghĩa là có thêm 1 sheet có dữ liệu tương tự như sheet3 ở FileC thì hệ thống báo lỗi). Vậy nếu dữ liệu ở FileC là Sheet6 thì sao ??
 
Upvote 0
Cho em hỏi lỗi không hiển thị được hết chiều rộng phải sửa như nào, xuất ra thì vẫn đủ chữ "TCVN 4447:2012: Công tác đất. Thi công và nghiệm thu"
 

File đính kèm

  • Untitled.png
    Untitled.png
    34.4 KB · Đọc: 20
Upvote 0
Hic OT loay hoay mãi đã thử để thuộc tính ColumnHeads = True mà không thể hiển thị được tiêu đề cột cho listbox ở bài này:


Các bạn xem có cách nào không giúp đỡ OT với ạ.
 
Upvote 0
Hic OT loay hoay mãi đã thử để thuộc tính ColumnHeads = True mà không thể hiển thị được tiêu đề cột cho listbox ở bài này:


Các bạn xem có cách nào không giúp đỡ OT với ạ.
Em vào đề tài sau tham khảo nhé.
 
Upvote 0
Em vào đề tài sau tham khảo nhé.
Hic, OT không biết cách vận dụng code của bác Siwtom vào bài này, nên khi bấm nút mở form đã bị báo lỗi.
Phiền anh Hai Lúa xem giúp với ạ.
Nêu bác Siwtom (@batman1 ) có ghé qua dọc bài này. Bác xem giúp con "hiển thị được tiêu đề cột cho listbox " với ạ.
 

File đính kèm

Upvote 0
Hic, OT không biết cách vận dụng code của bác Siwtom vào bài này, nên khi bấm nút mở form đã bị báo lỗi.
Phiền anh Hai Lúa xem giúp với ạ.
Nêu bác Siwtom (@batman1 ) có ghé qua dọc bài này. Bác xem giúp con "hiển thị được tiêu đề cột cho listbox " với ạ.
Của bạn thiếu máy cái lb với cái sự kiện Frame

sdfsdfsdf.png
 
Lần chỉnh sửa cuối:
Upvote 0
Hic, OT không biết cách vận dụng code của bác Siwtom vào bài này, nên khi bấm nút mở form đã bị báo lỗi.
Phiền anh Hai Lúa xem giúp với ạ.
Nêu bác Siwtom (@batman1 ) có ghé qua dọc bài này. Bác xem giúp con "hiển thị được tiêu đề cột cho listbox " với ạ.
Tôi hướng dẫn để bạn tự làm chứ nếu tôi làm hộ bạn thì rồi với tập tin khác bạn lại hỏi thì ai đâu có thời gian trả lời.

Các lưu ý:
1. Với ListBox trong Properties hãy thiết lập ColumnCount (của bạn là 3), ColumnWidths (của bạn là 3 giá trị)

2. Có bao nhiêu cột trong ListBox thì đặt bấy nhiêu Label xuống Form. Của bạn là 3 Label. Do có những Label khác không là tiêu đề cột của ListBox, vd. như Label1 = "NHập điều kiện lọc cho cột code", nên để phân biệt thì phải đổi tên 3 Label vừa thêm sao cho chúng có tiền tố khác "Label", vd. cho tiền tố là "lb". 3 Label vừa thêm phải có số thứ tự từ 1 đến 3, tổng quát là từ 1 tới n, với n là số cột trong ListBox. Tóm lại trong trường hợp của bạn thì đổi tên thành lb1, lb2 và lb3. Lưu ý là bạn chỉ thêm Label thôi còn không phải thiết lập Top, Left, Width, Height, vì code trong sub CalculateControls sẽ làm việc này.

3. 3 Label vừa thêm ở điểm 2 phải nằm trọn trong Frame. Nếu cần thì kéo 3 Label vào trong Frame, của bạn là vào trong Frame2.

4. Trong module UserForm1 phải có code của Sub CalculateControls và Sub Frame2_Scroll. Lưu ý là ListBox nằm trong Frame2 nên phải là Sub Frame2_Scroll chứ không phải là Sub Frame1_Scroll. Và do ListBox có tên là ListBox1 nên trong Sub Frame2_Scroll phải là ListBox1.Width.

5. Hãy đọc chú thích trong sub CalculateControls để biết cách truyền tham số. Cách gọi thì bạn làm đúng rồi, tức CalculateControls Frame2, ListBox1, "lb", "ID;Code;Price"

Mã:
Private Sub CalculateControls(ByVal FrameList As Object, ByVal listbox As Object, ByVal lbName As String, ByVal colNames As String)
'    FrameList: nhập tên của Frame, vd. Frame2
'    listbox: nhập tên của ListBox.
'    Các Label có số thứ tự từ 1 tới n, với n là số các cột trong ListBox. Nếu các Label có tiền tố là "lb" (lb1, lb2, ..., lbn) thì lbName = "lb"
'    colNames: tất cả tên các cột ngăn cách bởi dấu chấm phẩy
Dim index As Long, s As String, cWidths As String, lblLeft As Double, Arr, lb As msforms.Label, colWidths As Double
Dim captionArr
    captionArr = Split(colNames, ";")
    If listbox.ColumnCount <> UBound(captionArr) + 1 Then
        Err.Raise vbObjectError + 513, , "So tieu de cot khac so cot trong ListBox"
    End If
    cWidths = listbox.ColumnWidths
    s = Replace(cWidths, "pt", "")
    s = Replace(s, ";", "+")
    With FrameList
        colWidths = Evaluate(s)
        If colWidths > listbox.Width Then
            .ScrollBars = fmScrollBarsHorizontal
            .ScrollLeft = 0
            .ScrollWidth = colWidths
        Else
            listbox.Width = colWidths
        End If
        .Width = listbox.Width + 3
        .Height = listbox.Top + listbox.Height
    End With
    Arr = Split(s, "+")
    For index = LBound(Arr) To UBound(Arr)
        Set lb = Me(lbName & index + 1)
        If Not lb Is Nothing Then
            With lb
                .Left = lblLeft
                .Top = 0
                .Width = Arr(index)
                .Height = listbox.Top - 1
                .Caption = captionArr(index)
            End With
        End If
        lblLeft = lblLeft + Arr(index)
    Next
    On Error Resume Next
    For index = index To Me.Controls.Count
        Set lb = Me.Controls(lbName & index + 1)
        If Err Then Exit For
        lb.Top = FrameList.Height
    Next

    If listbox.ListStyle = fmListStyleOption Then
        listbox.ColumnWidths = Replace(cWidths, Arr(0), Arr(0) - 12, , 1)
    End If
End Sub

Private Sub Frame2_Scroll(ByVal ActionX As msforms.fmScrollAction, ByVal ActionY As msforms.fmScrollAction, ByVal RequestDx As Single, ByVal RequestDy As Single, ByVal ActualDx As msforms.ReturnSingle, ByVal ActualDy As msforms.ReturnSingle)
    If ActualDx <> 0 Then ListBox1.Width = ListBox1.Width + ActualDx
End Sub
 
Upvote 0
Tôi hướng dẫn để bạn tự làm chứ nếu tôi làm hộ bạn thì rồi với tập tin khác bạn lại hỏi thì ai đâu có thời gian trả lời.

Các lưu ý:
1. Với ListBox trong Properties hãy thiết lập ColumnCount (của bạn là 3), ColumnWidths (của bạn là 3 giá trị)

2. Có bao nhiêu cột trong ListBox thì đặt bấy nhiêu Label xuống Form. Của bạn là 3 Label. Do có những Label khác không là tiêu đề cột của ListBox, vd. như Label1 = "NHập điều kiện lọc cho cột code", nên để phân biệt thì phải đổi tên 3 Label vừa thêm sao cho chúng có tiền tố khác "Label", vd. cho tiền tố là "lb". 3 Label vừa thêm phải có số thứ tự từ 1 đến 3, tổng quát là từ 1 tới n, với n là số cột trong ListBox. Tóm lại trong trường hợp của bạn thì đổi tên thành lb1, lb2 và lb3. Lưu ý là bạn chỉ thêm Label thôi còn không phải thiết lập Top, Left, Width, Height, vì code trong sub CalculateControls sẽ làm việc này.

3. 3 Label vừa thêm ở điểm 2 phải nằm trọn trong Frame. Nếu cần thì kéo 3 Label vào trong Frame, của bạn là vào trong Frame2.

4. Trong module UserForm1 phải có code của Sub CalculateControls và Sub Frame2_Scroll. Lưu ý là ListBox nằm trong Frame2 nên phải là Sub Frame2_Scroll chứ không phải là Sub Frame1_Scroll. Và do ListBox có tên là ListBox1 nên trong Sub Frame2_Scroll phải là ListBox1.Width.

5. Hãy đọc chú thích trong sub CalculateControls để biết cách truyền tham số. Cách gọi thì bạn làm đúng rồi, tức CalculateControls Frame2, ListBox1, "lb", "ID;Code;Price"

Mã:
Private Sub CalculateControls(ByVal FrameList As Object, ByVal listbox As Object, ByVal lbName As String, ByVal colNames As String)
'    FrameList: nhập tên của Frame, vd. Frame2
'    listbox: nhập tên của ListBox.
'    Các Label có số thứ tự từ 1 tới n, với n là số các cột trong ListBox. Nếu các Label có tiền tố là "lb" (lb1, lb2, ..., lbn) thì lbName = "lb"
'    colNames: tất cả tên các cột ngăn cách bởi dấu chấm phẩy
Dim index As Long, s As String, cWidths As String, lblLeft As Double, Arr, lb As msforms.Label, colWidths As Double
Dim captionArr
    captionArr = Split(colNames, ";")
    If listbox.ColumnCount <> UBound(captionArr) + 1 Then
        Err.Raise vbObjectError + 513, , "So tieu de cot khac so cot trong ListBox"
    End If
    cWidths = listbox.ColumnWidths
    s = Replace(cWidths, "pt", "")
    s = Replace(s, ";", "+")
    With FrameList
        colWidths = Evaluate(s)
        If colWidths > listbox.Width Then
            .ScrollBars = fmScrollBarsHorizontal
            .ScrollLeft = 0
            .ScrollWidth = colWidths
        Else
            listbox.Width = colWidths
        End If
        .Width = listbox.Width + 3
        .Height = listbox.Top + listbox.Height
    End With
    Arr = Split(s, "+")
    For index = LBound(Arr) To UBound(Arr)
        Set lb = Me(lbName & index + 1)
        If Not lb Is Nothing Then
            With lb
                .Left = lblLeft
                .Top = 0
                .Width = Arr(index)
                .Height = listbox.Top - 1
                .Caption = captionArr(index)
            End With
        End If
        lblLeft = lblLeft + Arr(index)
    Next
    On Error Resume Next
    For index = index To Me.Controls.Count
        Set lb = Me.Controls(lbName & index + 1)
        If Err Then Exit For
        lb.Top = FrameList.Height
    Next

    If listbox.ListStyle = fmListStyleOption Then
        listbox.ColumnWidths = Replace(cWidths, Arr(0), Arr(0) - 12, , 1)
    End If
End Sub

Private Sub Frame2_Scroll(ByVal ActionX As msforms.fmScrollAction, ByVal ActionY As msforms.fmScrollAction, ByVal RequestDx As Single, ByVal RequestDy As Single, ByVal ActualDx As msforms.ReturnSingle, ByVal ActualDy As msforms.ReturnSingle)
    If ActualDx <> 0 Then ListBox1.Width = ListBox1.Width + ActualDx
End Sub
Con chào Bác Siwtom,
Cảm ơn Bác đã dành thời gian hướng dẫn và giải thích cho con ạ.
Theo hướng dẫn của Bác con đã làm được rồi ạ, và con cũng đã copy các lưu ý vào trong code để sau này gặp phải nếu có quên cách làm con đọc lại ạ.
Con chúc Bác nhiều sức khỏe ạ.
 
Upvote 0
Con chào Bác Siwtom,
Cảm ơn Bác đã dành thời gian hướng dẫn và giải thích cho con ạ.
Theo hướng dẫn của Bác con đã làm được rồi ạ, và con cũng đã copy các lưu ý vào trong code để sau này gặp phải nếu có quên cách làm con đọc lại ạ.
Con chúc Bác nhiều sức khỏe ạ.
Bạn sửa xong rồi có thể cho mình xin file nghiên cứu được không? Mình thử mà chưa được
 
Upvote 0
Bạn sửa xong rồi có thể cho mình xin file nghiên cứu được không? Mình thử mà chưa được
Cảm ơn bạn đã quan tâm.
Bạn muốn thử mình hay sao ấy chứ, hihi. Bài #368 Bác Siwtom hướng dẫn rất chi tiết mà.
Có một vấn đề như Bác Siwtom ( @batman1 ) có nêu ở trên:
"ColumnWidths (của bạn là 3 giá trị) " chỗ này hình như phải nhập tay và căn ke hơi thủ công thì from mới đẹp được ạ.
Còn mấy cái Lable thì tự nó co giãn theo các ColumnWidths rồi thì phải vì OT vẽ nó xong không cần phải co kéo đặt đúng vị trí tiêu đề (chỉ đặt áng chừng).
Bạn tham khảo nhé.
 

File đính kèm

Upvote 0
Tối hôm qua định đưa lên rồi mà thấy anh @batman1 hướng dẫn kỹ quá nên mình không đưa lên. với lại thường máy cái File mình ít lưu lắm

các bạn có thể dùng Code thiết lập
Mã:
    ListBox1.ColumnCount = 3
    ListBox1.ColumnWidths = "70pt;70pt;70pt"
hay là tự động tạo Lable hay Button làm tiêu đề cũng được, kể cả kéo thay đổi độ của Lisbox cũng được
 

File đính kèm

Upvote 0
các bạn có thể dùng Code thiết lập
Mã:
    ListBox1.ColumnCount = 3
    ListBox1.ColumnWidths = "70pt;70pt;70pt"
hay là tự động tạo Lable hay Button làm tiêu đề cũng được, kể cả kéo thay đổi độ của Lisbox cũng được
Xin chào thuyyeu99,
Giả sử tiêu đề là các ô A1,B1,C1,...,N1 => Vùng tiêu đề là A1:N1
Như vậy cái đoạn: "lb", "ID;Code;Price" trong câu lệnh:
Mã:
CalculateControls Frame2, ListBox1, "lb", "ID;Code;Price"
Có thể tự động thêm số Lable & đặt tên "lb1,lb2,...." & lấy tên tiêu đề ứng với các ô trong vùng A1:N1 được phải không bạn?
Nếu được mong bạn & các bạn chỉ dẫn & giúp đỡ ạ.
 
Upvote 0
Xin chào thuyyeu99,
Giả sử tiêu đề là các ô A1,B1,C1,...,N1 => Vùng tiêu đề là A1:N1
Như vậy cái đoạn: "lb", "ID;Code;Price" trong câu lệnh:
Mã:
CalculateControls Frame2, ListBox1, "lb", "ID;Code;Price"
Có thể tự động thêm số Lable & đặt tên "lb1,lb2,...." & lấy tên tiêu đề ứng với các ô trong vùng A1:N1 được phải không bạn?
Nếu được mong bạn & các bạn chỉ dẫn & giúp đỡ ạ.
gọi sub Addlabel này, tuy nhiên mình đang loay hoay để khi thêm label thì nó nằm trong frame2
Mã:
Sub addLabel()

Dim theLabel As Object
Dim labelCounter As Long

For labelCounter = 1 To 3
    Set theLabel = UserForm1.Controls.Add("Forms.Label.1", "lb" & labelCounter, True)
    With theLabel
        .Caption = "lb" & labelCounter
        .Left = 10
        .Width = 50
        .Top = 10 * labelCounter
    End With
Next
End Sub
 
Upvote 0
Xin chào thuyyeu99,
Giả sử tiêu đề là các ô A1,B1,C1,...,N1 => Vùng tiêu đề là A1:N1
Như vậy cái đoạn: "lb", "ID;Code;Price" trong câu lệnh:
Mã:
CalculateControls Frame2, ListBox1, "lb", "ID;Code;Price"
Có thể tự động thêm số Lable & đặt tên "lb1,lb2,...." & lấy tên tiêu đề ứng với các ô trong vùng A1:N1 được phải không bạn?
Nếu được mong bạn & các bạn chỉ dẫn & giúp đỡ ạ.
gọi sub Addlabel này, tuy nhiên mình đang loay hoay để khi thêm label thì nó nằm trong frame2
Mã:
Sub addLabel()

Dim theLabel As Object
Dim labelCounter As Long

For labelCounter = 1 To 3
    Set theLabel = UserForm1.Controls.Add("Forms.Label.1", "lb" & labelCounter, True)
    With theLabel
        .Caption = "lb" & labelCounter
        .Left = 10
        .Width = 50
        .Top = 10 * labelCounter
    End With
Next
End Sub
Đây chỉ cẩn thêm cái Frame2
Mã:
Private Sub AddLabel()
    Dim i, numberLabel As Long
    Dim lbl As Object ' or Dim lbl As Control
    numberLabel = 3
        For i = 1 To numberLabel
            Set lbl = Frame2.Controls.Add("forms.label.1") 'Controls.Add("Forms.Label.1")
            With lbl
                .Caption = "Label" & i
                .Name = "lb" & i
                .Height = 20
                .Width = 50
                .Left = 20 * i * 1
                .Top = 0
            End With
        Next i
End Sub
 
Upvote 0
Đây chỉ cẩn thêm cái Frame2
Mã:
Private Sub AddLabel()
    Dim i, numberLabel As Long
    Dim lbl As Object ' or Dim lbl As Control
    numberLabel = 3
        For i = 1 To numberLabel
            Set lbl = Frame2.Controls.Add("forms.label.1") 'Controls.Add("Forms.Label.1")
            With lbl
                .Caption = "Label" & i
                .Name = "lb" & i
                .Height = 20
                .Width = 50
                .Left = 20 * i * 1
                .Top = 0
            End With
        Next i
End Sub
Híc, OT không hiểu code của hai bạn ạ: không thấy trong code đề câpj gì đến nội dung vùng tiêu đề là A1:N1 ạ?
 
Upvote 0

File đính kèm

Upvote 0
Chắc là tùy biến chút xíu kiểu này nè bạn
Cảm ơn bạn, một cách làm với ý tưởng rất hay,
"numberLabel = rst.Fields.Count"
Như vậy là tiêu đề sẽ lấy luôn các trường trong câu lệnh truy vấn:
Str = "Select*from [Sheet1$]"
Thay vì là lấy trực tiếp dưới bảng tính, như vậy chỉ cần xử lý câu lệnh truy vấn theo ý là được, hihi
 
Upvote 0
đang tìm tài liệu làm cái tiêu đề cho Listbox khi xài SQL nó lấy dữ liệu lên mà phân vân nên chọn Hình 1 hay hình 2
Hình số 1
TeiDe1.PNG
Hình số 2 code bài 380
TeiDe2.PNG

tất nhiên mọi cái là tự động hết rồi đấy
 
Upvote 0
Chào các thầy cô và anh chị ạ.
Hiện tại em đang có vấn đề muốn nhờ mọi người chỉ giúp.
Em có đưa dữ liệu vô listbox trên Userform rồi. Có 2 vấn đề muốn hỏi thầy cô anh chị:
1. Làm thế nào List box nó vẫn có tiêu đề tương ứng như dưới sheet Data
2. Khi mà Kích chọn trong listbox. Nó sẽ trả thẳng xuống dữ liệu xuống 1 sheet khác (sheet Form) như hình ạ
1608357312834.png
Em xin cám ơn nhiều ạ
 

File đính kèm

Upvote 0
Chào các thầy cô và anh chị ạ.
Hiện tại em đang có vấn đề muốn nhờ mọi người chỉ giúp.
Em có đưa dữ liệu vô listbox trên Userform rồi. Có 2 vấn đề muốn hỏi thầy cô anh chị:
1. Làm thế nào List box nó vẫn có tiêu đề tương ứng như dưới sheet Data
2. Khi mà Kích chọn trong listbox. Nó sẽ trả thẳng xuống dữ liệu xuống 1 sheet khác (sheet Form) như hình ạ
View attachment 251498
Em xin cám ơn nhiều ạ
1. Lấy luôn dòng tiêu đề vào data cho listbox thì nó sẽ có tiêu đề :D
2. _)()(-
 
Upvote 0
1. Dữ liệu ngày tháng của bạn không chuẩn. Vẫn cộng trừ được nhưng rất có thể dùng với vài hàm Excel sẽ bị lỗi. Nhìn hình bạn sẽ thấy tôi nhập ngày tháng hiện tại vào C2. Nó có dạng 19.12.2020 vì trên máy tôi thiết lập như thế, và được căn phải. Dữ liệu cột C của bạn lại là dạng dd/mm/yyyy với ký tự "/", và được căn trái.

listbox.jpg

Hãy chuẩn hóa dữ liệu: chọn cột C -> Data -> Text to columns -> Next -> Next -> chọn option Date -> bên cạnh chọn DMY -> Finish.

2. Tôi đề nghị trong Sub timkiem_Click
sửa
Mã:
Res(k, 3) = sArr(i, 3)
thành
Mã:
Res(k, 3) = Format(sArr(i, 3), "Short Date")
Mục đích là để trên những máy khác như máy tôi thì nhìn thấy vd. 07.01.1974 (y như thiết lập trong system) chứ không phải là 07/01/1974 (quái dị, vì trên sheet là 07.01.1974)
Em có đưa dữ liệu vô listbox trên Userform rồi. Có 2 vấn đề muốn hỏi thầy cô anh chị:
1. Làm thế nào List box nó vẫn có tiêu đề tương ứng như dưới sheet Data
ListBox của bạn chỉ có 5 cột nên tôi đề nghị kéo rộng UserForm chút và thiết lập Width của ListBox bằng 750. Lúc này chỉ thêm 5 Label nối đuôi nhau ngay trên ListBox để làm tiêu đề.
2. Khi mà Kích chọn trong listbox. Nó sẽ trả thẳng xuống dữ liệu xuống 1 sheet khác (sheet Form) như hình ạ
Vd. thêm code
Mã:
Private Sub Lbdulieu_Click()
Dim k As Long, chiso
    If Lbdulieu.ListIndex < 0 Then Exit Sub
    chiso = Array(2, 3, 4, 6, 8)    ' chi so dong cua C2, C3, C4, C6, C8
    For k = 0 To UBound(chiso)
        If k = 2 Then
            ThisWorkbook.Worksheets("Form").Cells(chiso(k), "C").Value = CDate(Lbdulieu.List(Lbdulieu.ListIndex, k))
        Else
            ThisWorkbook.Worksheets("Form").Cells(chiso(k), "C").Value = Lbdulieu.List(Lbdulieu.ListIndex, k)
        End If
    Next k
End Sub
 
Upvote 0
@batman1 con xin cảm ơn những góp ý của chú. Chú giải thích con thấy rất dễ hiểu. Thật sự là làm việc với ngày tháng. Nó tạo cho con cảm giác hơi sợ. Những gì chú chỉ con cảm thấy cảnh giác với dữ liệu của mình rất nhiều. Do con đang tìm hiểu về userform nên cứ ngáo ngơ thế nào ấy ạ.
Những lưu ý của chú con sẽ tìm cách khắc phục.
Một lần nữa xin cảm ơn chú rất nhiều.
 
Upvote 0
Chào các thầy cô và anh chị ạ.
Hiện tại em đang có vấn đề muốn nhờ mọi người chỉ giúp.
Em có đưa dữ liệu vô listbox trên Userform rồi. Có 2 vấn đề muốn hỏi thầy cô anh chị:
1. Làm thế nào List box nó vẫn có tiêu đề tương ứng như dưới sheet Data
2. Khi mà Kích chọn trong listbox. Nó sẽ trả thẳng xuống dữ liệu xuống 1 sheet khác (sheet Form) như hình ạ
View attachment 251498
Em xin cám ơn nhiều ạ
Tôi đang làm vài thứ có liên quan tới cái Listbox ... áp dụng cho bài của bạn tôi gợi ý cho mà làm he ... nó sẻ rất đẹp đấy
1/ qua link sau xem bài số 26 mục số 1 có file đính kèm ở dưới ... làm cái tiêu đề cho Listbox
LẤY DỮ LIỆU TỰ NGUỒN VÀO LISTBOX | Page 2 | Giải Pháp Excel (giaiphapexcel.com)
2/ Format cột listbox thì bài 386 đã nói rồi
3/ Mò cách tự đông fix cột cho nó vừa với dữ liệu hiện có trên Listbox nữa là đẹp đấy

Vui lòng google Or .... nhé

Chịu khó mà học đi mai mốt tự mà làm lấy nó mới vui
 
Upvote 0
1/ qua link sau xem bài số 26 mục số 1 có file đính kèm ở dưới ... làm cái tiêu đề cho Listbox
LẤY DỮ LIỆU TỰ NGUỒN VÀO LISTBOX | Page 2 | Giải Pháp Excel (giaiphapexcel.com)
Bạn có xem tập tin của người ta không vậy? Ai cũng biết là nếu lấy dữ liệu từ sheet bằng RowSource thì chuyện tiêu đề nó nhỏ như con thỏ, còn nhỏ hơn con thỏ rất nhiều. Chủ thớt có vấn đề với tiêu đề vì chủ thớt có dữ liệu từ việc tìm kiếm, và kết quả được trả về trong MẢNG. Chủ thớt dùng LIST để nhập dữ liệu từ MẢNG vào ListBox. Nếu nói là phải đập dữ liệu từ MẢNG kết quả xuống sheet để có thể dùng RowSource thì vấn đề tầm thường quá. Vì với RowSource tiêu đề là chuyện nhỏ như con thỏ. Cái thú vị hơn là có cách nào không phải đập kết quả từ mảng xuống sheet không thôi.
 
Upvote 0
Bạn có xem tập tin của người ta không vậy? Ai cũng biết là nếu lấy dữ liệu từ sheet bằng RowSource thì chuyện tiêu đề nó nhỏ như con thỏ, còn nhỏ hơn con thỏ rất nhiều. Chủ thớt có vấn đề với tiêu đề vì chủ thớt có dữ liệu từ việc tìm kiếm, và kết quả được trả về trong MẢNG. Chủ thớt dùng LIST để nhập dữ liệu từ MẢNG vào ListBox. Nếu nói là phải đập dữ liệu từ MẢNG kết quả xuống sheet để có thể dùng RowSource thì vấn đề tầm thường quá. Vì với RowSource tiêu đề là chuyện nhỏ như con thỏ. Cái thú vị hơn là có cách nào không phải đập kết quả từ mảng xuống sheet không thôi.
em đang tìm cách lấy dữ liệu vào 1 Array xong làm cái tiêu đề xịn như RowSource mà ko xong .... nó chỉ có như hình ===> ko giống cái gì cả :D

1608818310271.png
 
Lần chỉnh sửa cuối:
Upvote 0
em đang tìm cách lấy dữ liệu vào 1 Array xong làm cái tiêu đề xịn như RowSource mà ko xong .... nó chỉ có như hình ===> ko giống cái gì cả :D
Nếu trong mảng dòng đầu tiên là tiêu đề thì đương nhiên là nó cũng được nhập vào ListBox khi dùng LIST. Bạn ngạc nhiên à? Nhưng tất nhiên cái tiêu đề kia là "nhái" vì đối với ListBox nó cũng chỉ là 1 dòng dữ liệu như các dòng khác. Thế thôi.
 
Upvote 0
Nếu trong mảng dòng đầu tiên là tiêu đề thì đương nhiên là nó cũng được nhập vào ListBox khi dùng LIST. Bạn ngạc nhiên à? Nhưng tất nhiên cái tiêu đề kia là "nhái" vì đối với ListBox nó cũng chỉ là 1 dòng dữ liệu như các dòng khác. Thế thôi.
Em đang sử dụng code sau để AutoFit Cột trong listbox thấy chạy khá tốt . tuy nhiên nếu có cái tiêu đề xịn như RowSource thì nó ko có hiểu ... mà nó chỉ fix cột lý do nó duyệt qua ListBox.ColumnCount ...vấn đề này cũng ko có quan trọng lắm nhưng nhìn vào nó ko có đẹp

vậy Em muốn hỏi
1/ có cách nào viết lại hàm đó cho nó Fix cả cái tiêu đề cột trong RowSource không anh ?!

2/ khi em chuyển code đó vào VB6 thử thì thấy chạy nó lỗi
- lỗi thứ nhất là ko tạo được label ... cái này khả năng do cách khởi tạo trên vb6 nó khác vba ( Control trên vb6 em chưa rành lắm )
- khi em xóa tự động tạo label đi thử chèn 1 cái lable thủ công xong chạy code thì nó cũng lỗi ...
- vậy em muốn hỏi có cách gì viết lại hàm sau cho nó chạy trên VB6 Như trên VBA không Anh ?!

Mong anh chỉ dùm em

Mã:
Public Sub AutofitColumnListbox(ByVal FormName As Object, ByRef ListBox As MSForms.ListBox)
    Dim Zeile As Long, Spalte As Long
    Dim SpaltenBreiten As String, MaxBreite As Double
    Dim Lbl As MSForms.Label
    Set Lbl = FormName.Controls.Add("Forms.label.1", "label1", False)
    Lbl.WordWrap = False
    Lbl.AutoSize = True
    For Zeile = 0 To ListBox.ColumnCount - 1
        MaxBreite = 0
        For Spalte = 0 To ListBox.ListCount - 1
            Lbl.Caption = ListBox.Column(Zeile, Spalte) & ",,,"         
            If MaxBreite < Lbl.Width Then
                MaxBreite = Lbl.Width
            End If
        Next Spalte
        SpaltenBreiten = SpaltenBreiten & CLng(MaxBreite + 1) & ";"
    Next Zeile
    ListBox.ColumnWidths = SpaltenBreiten
    Set Lbl = Nothing
End Sub

Code sau cho Bạn nào đam mê tham khảo thêm của tây
vba - Automatically adapt listbox column width - Stack Overflow
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Em đang sử dụng code sau để AutoFit Cột trong listbox thấy chạy khá tốt . tuy nhiên nếu có cái tiêu đề xịn như RowSource thì nó ko có hiểu ... mà nó chỉ fix cột lý do nó duyệt qua ListBox.ColumnCount ...vấn đề này cũng ko có quan trọng lắm nhưng nhìn vào nó ko có đẹp

vậy Em muốn hỏi
1/ có cách nào viết lại hàm đó cho nó Fix cả cái tiêu đề cột trong RowSource không anh ?!
Tôi tư duy đơn giản thôi. Để luôn luôn nhìn trọn tiêu đề thì độ rộng của mỗi cột không thể nhỏ hơn, tức ít nhất là bằng, độ rộng của tiêu đề tương ứng. Tức vào thời điểm "chào buổi sáng" thì không thể có MaxBreite = 0 mà phải MaxBreite = <độ rộng của tiêu đề cột hiện hành>
Ngoài ra mặc định thì Label và ListBox có phông chữ là "Tahoma" với độ lớn bằng 8. Vậy label Lbl có phông chữ là "Tahoma" với độ lớn bằng 8, nhưng trong trường hợp cụ thể thì ListBox có thể bị thay phông chữ bằng vd. "Times New Roman" với độ lớn bằng 10. Code tổng quát tạo Label Lbl với phông chữ "Tahoma" 8. Hậu quả là độ rộng tối thiểu của mỗi cột được tính bằng code sẽ không khớp với độ rộng cần có. Bởi thay đổi tên phông chữ và độ lớn phông chữ của ListBox sẽ thay đổi độ rộng của cột. Label Lbl phải có phông chữ với tên và độ lớn y như cho ListBox. Vậy tôi đề nghị:
1. Thêm
Mã:
Dim tieude
2.
Sau
Mã:
Lbl.AutoSize = True
thêm cụm
Mã:
Lbl.Font.Name = ListBox.Font.Name
    Lbl.Font.Size = ListBox.Font.Size
    If ListBox.ColumnHeads And (ListBox.RowSource <> "") Then
        With Range(ListBox.RowSource)
            tieude = .Offset(-1).Resize(1, .Columns.Count + 1).Value
        End With
    End If
3. Thay
Mã:
MaxBreite = 0
bằng
Mã:
If IsArray(tieude) Then
    Lbl.Caption = tieude(1, Zeile + 1) & ",,,"
    MaxBreite = Lbl.Width
Else
    MaxBreite = 0
End If
2/ khi em chuyển code đó vào VB6 thử thì thấy chạy nó lỗi
- lỗi thứ nhất là ko tạo được label ... cái này khả năng do cách khởi tạo trên vb6 nó khác vba ( Control trên vb6 em chưa rành lắm )
- khi em xóa tự động tạo label đi thử chèn 1 cái lable thủ công xong chạy code thì nó cũng lỗi ...
- vậy em muốn hỏi có cách gì viết lại hàm sau cho nó chạy trên VB6 Như trên VBA không Anh ?!
Trong VB6 làm gì có cái gọi là VBA?
Nếu muốn tôi xem hộ thì đính kèm code VB6. Tôi không phán chỉ trên cơ sở nước bọt.
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi tư duy đơn giản thôi. Để luôn luôn nhìn trọn tiêu đề thì độ rộng của mỗi cột không thể nhỏ hơn, tức ít nhất là bằng, độ rộng của tiêu đề tương ứng. Tức vào thời điểm "chào buổi sáng" thì không thể có MaxBreite = 0 mà phải MaxBreite = <độ rộng của tiêu đề cột hiện hành>
Ngoài ra mặc định thì Label và ListBox có phông chữ là "Tahoma" với độ lớn bằng 8. Vậy label Lbl có phông chữ là "Tahoma" với độ lớn bằng 8, nhưng trong trường hợp cụ thể thì ListBox có thể bị thay phông chữ bằng vd. "Times New Roman" với độ lớn bằng 10. Code tổng quát tạo Label Lbl với phông chữ "Tahoma" 8. Hậu quả là độ rộng tối thiểu của mỗi cột được tính bằng code sẽ không khớp với độ rộng cần có. Bởi thay đổi tên phông chữ và độ lớn phông chữ của ListBox sẽ thay đổi độ rộng của cột. Label Lbl phải có phông chữ với tên và độ lớn y như cho ListBox. Vậy tôi đề nghị:
1. Thêm
Mã:
Dim tieude
2.
Sau
Mã:
Lbl.AutoSize = True
thêm cụm
Mã:
Lbl.Font.Name = ListBox.Font.Name
    Lbl.Font.Size = ListBox.Font.Size
    If ListBox.ColumnHeads And (ListBox.RowSource <> "") Then
        With Range(ListBox.RowSource)
            tieude = .Offset(-1).Resize(1, .Columns.Count + 1).Value
        End With
    End If
3. Thay
Mã:
MaxBreite = 0
bằng
Mã:
If IsArray(tieude) Then
    Lbl.Caption = tieude(1, Zeile + 1) & ",,,"
    MaxBreite = Lbl.Width
Else
    MaxBreite = 0
End If

Trong VB6 làm gì có cái gọi là VBA?
Nếu muốn tôi xem hộ thì đính kèm code VB6. Tôi không phán chỉ trên cơ sở nước bọt.
Cảm ơn Anh
Trên VBA theo chỉ dẫn của Anh ... code chạy tốt đúng yêu cầu

1609065656815.png

Trên VB6 code như sau nhưng khi chạy thì cột Listbox nó ko fit lại được
Mã:
Private Sub Form_Load()
    Dim a(1 To 2, 1 To 3) As String
    a(1, 1) = "AAAAAAAAAA"
    a(1, 2) = "BBBB999"
    a(1, 3) = "CCCCCCC2312313131321321"
    a(2, 1) = "AA897979797kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
    a(2, 2) = "BBBBBBBBBBBBBBB"
    a(2, 3) = "CCC"
    Me.ListBox1.List = a
    Me.ListBox1.ColumnCount = 3
    Call AutofitColumnListbox(Me, ListBox1)
End Sub

Public Sub AutofitColumnListbox(ByVal FormName As Object, ListBox As Object)
    Dim Zeile As Long, Spalte As Long, tieude
    Dim SpaltenBreiten As String, MaxBreite As Double
    Dim Lbl As Object
    Set Lbl = Me.Controls.Add("VB.Label", "Label1")
    Lbl.WordWrap = False
    Lbl.AutoSize = True
    For Zeile = 0 To ListBox.ColumnCount - 1
        MaxBreite = 0
        For Spalte = 0 To ListBox.ListCount - 1
            Lbl.Caption = ListBox.Column(Zeile, Spalte) & ",,,"
            If MaxBreite < Lbl.Width Then
                MaxBreite = Lbl.Width
            End If
        Next Spalte
        SpaltenBreiten = SpaltenBreiten & CLng(MaxBreite + 1) & ";"
    Next Zeile
    ListBox.ColumnWidths = SpaltenBreiten
    Set Lbl = Nothing
End Sub

File đính kèm là code trên VB6 Em chưa làm đúng đươc yêu cầu ... mong Anh chỉnh sửa dùm Em
trên VB6 chỉ fit lại cột listbox cho nó vừa với dữ liệu hiện có của từng cột còn cái tiêu đề xịn như RowSource thì nó cũng không có hổ trợ

cái này em thử nghỉ cách làm giả như cách Anh làm trên VBA xem có được hay ko ... nếu được em sẻ viết chung nó vào 1 hàm vừa tạo tiêu đề giả + fit cột

Mong anh xử lý cho em cái Fit cột listbox trước còn viết tạo tiêu đề giả kèm vào chung 1 hàm nếu có thêm càng tốt nếu ko để em mò thử sức xem sao

kẹt quá lại nhờ tiếp :D

Em cảm ơn Anh
 

File đính kèm

Upvote 0
Trên VB6 code như sau nhưng khi chạy thì cột Listbox nó ko fit lại được
File đính kèm là code trên VB6 Em chưa làm đúng đươc yêu cầu ... mong Anh chỉnh sửa dùm Em
Ý bạn là thế nào? Là code chạy được nhưng chưa đúng yêu cầu? Tôi hỏi vì trên máy tôi không chạy được. Mà tôi nghĩ là không chạy được cũng phải. Vì cái gọi là ListBox1 của bạn chẳng qua là bạn cố tình đặt tên là ListBox1 thôi, còn đó là control PictureBox.

listbox.jpg

Tôi thử làm cho bạn dùng ListBox. Theo tôi code phải như tập tin đính kèm. Bạn có thể test phiên bản khác bỏ 4 dòng từ (A) tới (D).

Fit chuẩn 100% hay không thì tôi cũng kết thúc.

Nên nhớ là ListBox trong VB6 không có cái gọi là List, Column, ColumnCount, ColumnWidths nên viết code không nhẹ nhàng sung sướng như trong VBA.

Bạn tự tìm tòi thêm, tôi dừng ở đây.
 

File đính kèm

Upvote 0
chắc tại mình ko được học hành code két có trường có lớp nên nhiều khi câu từ thuật ngữ code két hay trình bày nó cứ chéo cánh vịt hay sao ý
Untitled.png
 

File đính kèm

  • 1609116063340.png
    1609116063340.png
    62.8 KB · Đọc: 20
Lần chỉnh sửa cuối:
Upvote 0
chắc tại mình ko được học hành code két có trường có lớp nên nhiều khi câu từ thuật ngữ code két hay trình bày nó cứ chéo cánh vịt hay sao ý
Bạn hãy cho tôi biết. Rõ ràng tôi tải tập tin ở bài #394 về và thấy bạn dùng PictureBox. Bây giờ tải lại thì thấy bạn dùng ListBox.
 
Upvote 0
Bạn hãy cho tôi biết. Rõ ràng tôi tải tập tin ở bài #394 về và thấy bạn dùng PictureBox. Bây giờ tải lại thì thấy bạn dùng ListBox.
em mới tải lại file bài 394 nè anh
bài đó còn y trang mà anh em có chỉnh sửa gì đâu trong file bài 394 em có chụp cái ảnh use Form 2.0.PNG mà

em biết hỏi anh thì phải chi tiết + rõ ràng nên làm rất cẩn thận đấy :D chứ hỏi người khác nhiều lúc ẩu em chấm mấy cái à ...

1609152551244.png
 
Upvote 0
em mới tải lại file bài 394 nè anh
bài đó còn y trang mà anh em có chỉnh sửa gì đâu trong file bài 394 em có chụp cái ảnh use Form 2.0.PNG mà

em biết hỏi anh thì phải chi tiết + rõ ràng nên làm rất cẩn thận đấy :D chứ hỏi người khác nhiều lúc ẩu em chấm mấy cái à ...
Tôi đã tải lại tập tin. Tôi chỉ trả lời về vấn đề chủ yếu.

ColumnWidths tính bằng Point, Width của Label trên Form bên VBA cũng tính bằng Point. Bên VB6 thì Width của Label có giá trị thay đổi tùy theo ScaleMode của Form. Mặc định thì Form có ScaleMode = Twip. Tức Width của Label được tính bằng Twip. Cũng cùng một Label có Width = 100 Point thì tính bằng Twip là 2000. 2000 là con số cực lớn, đúng không? Lấy con số 2000 làm ColumnWidths thì toi rồi.

Thế nếu dùng API thì trong nhiều hàm phải truyền tham số tính bằng Pixel, mà lại truyền Width của Label, ListBox, CommandButton trong khi ScaleMode = Twip thì teo rồi. Thay vì truyền 133 (pixel) thì lại truyền 2000 (Twip)?

Tóm lại chỉnh ScaleMode của Form thành Point là được. Lúc đó code sẽ lấy 100 làm ColumnWidth. Như thế là chuẩn.

Học VB mà vấn đề cơ bản ScaleMode không biết?
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi đã tải lại tập tin. Tôi chỉ trả lời về vấn đề chủ yếu.

ColumnWidths tính bằng Point, Width của Label trên Form bên VBA cũng tính bằng Point. Bên VB6 thì Width của Label có giá trị thay đổi tùy theo ScaleMode của Form. Mặc định thì Form có ScaleMode = Twip. Tức Width của Label được tính bằng Twip. Cũng cùng một Label có Width = 100 Point thì tính bằng Twip là 2000. 2000 là con số cực lớn, đúng không? Lấy con số 2000 làm ColumnWidths thì toi rồi.

Tóm lại chỉnh ScaleMode của Form thành Point là được. Lúc đó code sẽ lấy 100 làm ColumnWidth. Như thế là chuẩn.

Học VB mà vấn đề cơ bản ScaleMode không biết?
Control em xin chịu ... có viết mấy đâu

1609155495153.png
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom