Add TextBox trên form! (1 người xem)

  • Thread starter Thread starter ThuNghi
  • Ngày gửi Ngày gửi
Liên hệ QC

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

ThuNghi

Hãy cho rồi sẽ nhận!
Thành viên đã mất
Tham gia
16/8/06
Bài viết
3,808
Được thích
4,449
Tôi có sh Data gồm 3 cột
- MaHH
- TenHH
- DVT
Tôi muốn tạo 1 form để nhập vào, thay vì vào form add từng textBox (TB) và đặt tên là: TB_Mahh, TB_TenHH ... thì hơi lâu, trường hợp có 50 cột mà add 50 TB thì copy và paste lâu quá.
Nhờ các bạn viết cho code add và đặt tên các TB đó.
Xin cám ơn.
Có thấy đâu đó trên GPE nhưng tìm bài của NDU thì viết bài mới hỏi nhanh hơn. (nhiều quá).
Đính kèm file.
 

File đính kèm

Tôi có sh Data gồm 3 cột
- MaHH
- TenHH
- DVT
Tôi muốn tạo 1 form để nhập vào, thay vì vào form add từng textBox (TB) và đặt tên là: TB_Mahh, TB_TenHH ... thì hơi lâu, trường hợp có 50 cột mà add 50 TB thì copy và paste lâu quá.
Nhờ các bạn viết cho code add và đặt tên các TB đó.
Xin cám ơn.
Có thấy đâu đó trên GPE nhưng tìm bài của NDU thì viết bài mới hỏi nhanh hơn. (nhiều quá).
Đính kèm file.
Có nghĩa là xem tiêu đề có bao nhiêu cell thì Add bấy nhiêu TextBox, đúng không?
Làm vụ này chẳng có vấn đề gì. Ví dụ:
PHP:
Private Sub AddtbFormRange(ByVal SrcRng As Range)
  Dim Clls As Range, dH As Double, dW As Double, i As Long
  dH = 30: dW = 130
  For Each Clls In SrcRng
    With UserForm1.Controls.Add("forms.TextBox.1")
      .Left = 10: .Top = i * dH + 10
      .Width = dW: .Height = dH
      .Name = "TextBox" & i + 1
    End With
    With UserForm1.Controls.Add("forms.Label.1")
      .Left = 10 + dW: .Top = i * dH + 10
      .Width = dW: .Height = dH
      .Caption = Clls.Value
    End With
    i = i + 1
  Next
End Sub
PHP:
Private Sub UserForm_Initialize()
  AddtbFormRange Range("A1:C1")
End Sub
Có điều tôi đang nghĩ Add xong, để mấy TextBox này hoạt động được ta phải viết code sao đây?
Tham khảo thêm bài này:
http://www.giaiphapexcel.com/forum/showthread.php?43681-Tạo-và-xóa-UserForm&p=285242#post285242
 
Upvote 0
Ah... hình như tôi hiểu ý bạn... Có lẽ bạn muốn thiết kế form mà khỏi cần.. vẽ (nhờ code vẽ giùm). Còn code cho các control thì tự mình viết lấy, Đúng không?
Thế thì dùng code này:
PHP:
Private Sub AddtbFormRange(ByVal SrcRng As Range)
  Dim i As Long, Clls As Range, dH As Double, dW As Double
  dH = 30: dW = 130
  With ThisWorkbook.VBProject.VBComponents.Add(3)
    .Properties("Width") = 300: .Properties("Height") = 190
    For Each Clls In SrcRng
      With .Designer.Controls.Add("forms.TextBox.1")
        .Left = 10: .Top = i * dH + 10
        .Width = dW: .Height = dH
        .Name = "TextBox" & i + 1
      End With
      With .Designer.Controls.Add("forms.Label.1")
        .Left = 20 + dW: .Top = i * dH + 18
        .Width = dW: .Height = dH - 8
        .Caption = Clls.Value
        .Font.Size = 10
      End With
      i = i + 1
    Next
  End With
End Sub
PHP:
Sub CreateForm()
 AddtbFormRange Range("A1:C1")
End Sub
Lưu ý:
- Hai đoạn code này nằm trong Module
- UserForm và các controls do code tạo ra, khỏi cần phải vẽ trước UserForm làm gì
- Sau khi chạy Sub CreateForm, vào cửa số code sẽ thấy form thiết kế sẳn
 
Upvote 0
Trước hết mình tham gia cách Add các điều khiển bằng cách chọn các ô tiêu đề. Các Label và Textbox có độ rộng dựa vào cột rộng nhất và tiêu đề dài nhất. Nếu trên 10 ô thì chia thành 2 cột
Nói chung tạm thời vậy để tham khảo còn khi viết còn phải khống chế lỗi.
Ta viết sẵn 1 số code điều khiển để khi add Command gọi nó để điều khiển
 

File đính kèm

Upvote 0
Trước hết mình tham gia cách Add các điều khiển bằng cách chọn các ô tiêu đề. Các Label và Textbox có độ rộng dựa vào cột rộng nhất và tiêu đề dài nhất. Nếu trên 10 ô thì chia thành 2 cột
Nói chung tạm thời vậy để tham khảo còn khi viết còn phải khống chế lỗi.
Ta viết sẵn 1 số code điều khiển để khi add Command gọi nó để điều khiển
Lúc đầu em cũng tưởng giống như anh nhưng sau nghĩ lại hình như không hợp lý. ThuNghi vì lười nên muốn nhờ code vẽ hộ. Sau khi vẽ xong thì các control này vẫn còn tồn tại chứ ---> trường hợp code của anh, sau khi nhìn thấy form, thoát ra thì mấy control mất tiêu, chả được lợi ích gì
Ẹc... Ẹc...
 
Upvote 0
Lúc đầu em cũng tưởng giống như anh nhưng sau nghĩ lại hình như không hợp lý. ThuNghi vì lười nên muốn nhờ code vẽ hộ. Sau khi vẽ xong thì các control này vẫn còn tồn tại chứ ---> trường hợp code của anh, sau khi nhìn thấy form, thoát ra thì mấy control mất tiêu, chả được lợi ích gì
Ẹc... Ẹc...
Không thể như vậy được, nếu dùng code sẽ vất vả hơn nhiều lần so với các Vizard đã tạo sẵn cho việc thiết kế, nhất là quản lý và điều khiển các Ctr trong hoạt động.
 
Upvote 0
CHỉ có ndu là đoán đúng ThuNghi, y ta độ rày làm biếng đến nỗi không muốn vẽ control nữa rồi.
Có điều, chả biết khi vẽ vài chục cái xong có quản lý nổi nó không nữa. Sao không dùng listbox, listview, và sheet shiếc gì đó?
Đoán thêm 1 cái, y ta muốn vẽ trong access!
Mà trong access thì cần gì vẽ? nắm cổ 30 thằng từ Field List lôi vào form 1 lượt, là có ngay 30 labels và 30 textbox.
 
Upvote 0
CHỉ có ndu là đoán đúng ThuNghi, y ta độ rày làm biếng đến nỗi không muốn vẽ control nữa rồi.
Có điều, chả biết khi vẽ vài chục cái xong có quản lý nổi nó không nữa. Sao không dùng listbox, listview, và sheet shiếc gì đó?
Đoán thêm 1 cái, y ta muốn vẽ trong access!
Mà trong access thì cần gì vẽ? nắm cổ 30 thằng từ Field List lôi vào form 1 lượt, là có ngay 30 labels và 30 textbox.
Bác Mỹ chỉ tội nói đúng, vì vẽ 30 textbox mà dùng ctr C và V thì cũng lâu, nên muốn hệ thống.
NDU hiểu đúng ý mình. Cám ơn anh Sealand, NDU và Bác Mỹ.
 
Upvote 0
Vẫn còn 1 cách khác để Add các control vào 1 UserForm có sẳn (các control sẽ được bảo toàn sau khi code chạy)
PHP:
Private Sub AddtbFormRange(ByVal SrcRng As Range)
  Dim i As Long, Clls As Range, dH As Double, dW As Double
  dH = 30: dW = 130
  With ThisWorkbook.VBProject.VBComponents("UserForm1")
    For Each Clls In SrcRng
      With .Designer.Controls.Add("forms.TextBox.1", "tbx_" & i + 1)
        .Left = 10: .Top = i * dH + 10
        .Width = dW: .Height = dH
      End With
      With .Designer.Controls.Add("forms.Label.1", "lbl_" & i + 1)
        .Left = 20 + dW: .Top = i * dH + 18
        .Width = dW / 2: .Height = dH - 8
        .Caption = Clls.Value
        .Font.Size = 10
      End With
      i = i + 1
    Next
  End With
End Sub
PHP:
Sub CreateControls()
 AddtbFormRange Range("A1:G1")
End Sub
Sự khác biệt code này với code ở bài 3 là ở chổ:
PHP:
With ThisWorkbook.VBProject.VBComponents.Add(3)
và:
PHP:
With ThisWorkbook.VBProject.VBComponents("UserForm1")
1 cái vừa tạo UserForm vừa tạo các control và 1 cái là tạo control trên UserForm có sẳn
 

File đính kèm

Upvote 0
Vẫn còn 1 cách khác để Add các control vào 1 UserForm có sẳn (các control sẽ được bảo toàn sau khi code chạy)
...
PHP:
With ThisWorkbook.VBProject.VBComponents.Add(3)
và:
PHP:
With ThisWorkbook.VBProject.VBComponents("UserForm1")
1 cái vừa tạo UserForm vừa tạo các control và 1 cái là tạo control trên UserForm có sẳn
Vậy tiện đây nhờ NDU làm thêm 1 bước, để sau này mình có tìm thì thấy trọn gói luôn.
File trên là tại những TBX_ & i
Vậy mình có 1 Array gồm i cột và n dòng.
NDU viết cho 1 code lấy giá trị tại dòng x của array vào các TBX_ & i. Dùng for ... next thay vì
Tbx_DVT=arr(x,1)
Cám ơn nhiều.
 
Upvote 0
Lại nhõng nhẽo nữa rồi!
Khi tạo control bằng code thì thường là các control sẽ mang số theo thứ tự tạo, nghĩa là control tạo đầu tiên sẽ là controls(1), kế tiếp là controls(2), ...

Vậy thứ tự tạo giống thứ tự cột thì cứ thế mà phang:
PHP:
For i = 1 to 30
Me.Controls(i - 1) = Arr(x, i)
Next
Tuy nhiên có xem cả label, nên thứ tự bị cách quãng ra:

PHP:
For i = 1 to 60 Step 2
Me.Controls(i - 1) = Arr(x, i)
Next
Xem lại code bài 9 của ndu, các textbox đã có số rồi, ẹc ẹc:

PHP:
For i = 1 to 30
Me.controls("tbx_" & i) = Arr(x, i)
Next
 
Lần chỉnh sửa cuối:
Upvote 0
Lại nhõng nhẽo nữa rồi!
Khi tạo control bằng code thì thường là các control sẽ mang số theo thứ tự tạo, nghĩa là control tạo đầu tiên sẽ là controls(1), kế tiếp là controls(2), ...
Vậy thứ tự tạo giống thứ tự cột thí cứ thế mà phang: (Giả định là tạo 30 textbox trước, label sau)

PHP:
For i = 1 to 30
Me.Controls(i) = Arr(x, i)
Next
Nhưng em không dùng tbx_i mà dùng tbx_ & tiêu đề cột, vd: tbx_maHH
Và các tiêu đề này em đã cho vào 1 Arr như là
Arr=Array("maVT","TenVT",,,)
Mày mò thì lâu, nhờ các sư phụ chỉ thì làm rất nhanh.
 
Upvote 0
Vậy tiện đây nhờ NDU làm thêm 1 bước, để sau này mình có tìm thì thấy trọn gói luôn.
File trên là tại những TBX_ & i
Vậy mình có 1 Array gồm i cột và n dòng.
NDU viết cho 1 code lấy giá trị tại dòng x của array vào các TBX_ & i. Dùng for ... next thay vì
Tbx_DVT=arr(x,1)
Cám ơn nhiều.
Thì đoạn này
Mã:
With .Designer.Controls.Add("forms.TextBox.1", "tbx_" & i + 1)
  .Left = 10: .Top = i * dH + 10
  .Width = dW: .Height = dH
End With
Sửa thành:
Mã:
With .Designer.Controls.Add("forms.TextBox.1", "tbx_" & i + 1)
  .Left = 10: .Top = i * dH + 10
  .Width = dW: .Height = dH
  [B].Text = Clls([COLOR=red]3[/COLOR], 1).Value[/B]
End With
Số 3 màu đỏ là chỉ số dòng mà bạn muốn.
Đoán thôi, không biết có đúng ý bạn không nữa
 
Upvote 0
Lại nhõng nhẽo nữa rồi!
Khi tạo control bằng code thì thường là các control sẽ mang số theo thứ tự tạo, nghĩa là control tạo đầu tiên sẽ là controls(1), kế tiếp là controls(2), ...
Vậy thứ tự tạo giống thứ tự cột thí cứ thế mà phang: (Giả định là tạo 30 textbox trước, label sau)

PHP:
For i = 1 to 30
Me.Controls(i) = Arr(x, i)
Next
Xem lại code bài 9 của ndu, các textbox đã có số rồi, ẹc ẹc:


PHP:
For i = 1 to 30
Me.controls("tbx_" & i) = Arr(x, i)
Next

Theo mình, cách thêm và đồng thời chủ động đặt tên như Ndu sẽ dễ dàng cho việc load dữ liệu từ Range lên cũng như nhập từ Form trở về Range. Việc này giống như 1 số bài mình viết cho nick KhamHa trên Form có đến khoảng 60 textbox, combobox, checkbox ... để load và down dữ liệu.
 
Upvote 0
Vẫn còn 1 cách khác để Add các control vào 1 UserForm có sẳn (các control sẽ được bảo toàn sau khi code chạy)
PHP:
Private Sub AddtbFormRange(ByVal SrcRng As Range)
  Dim i As Long, Clls As Range, dH As Double, dW As Double
  dH = 30: dW = 130
  With ThisWorkbook.VBProject.VBComponents("UserForm1")
    For Each Clls In SrcRng
      With .Designer.Controls.Add("forms.TextBox.1", "tbx_" & i + 1)
        .Left = 10: .Top = i * dH + 10
        .Width = dW: .Height = dH
      End With
      With .Designer.Controls.Add("forms.Label.1", "lbl_" & i + 1)
        .Left = 20 + dW: .Top = i * dH + 18
        .Width = dW / 2: .Height = dH - 8
        .Caption = Clls.Value
        .Font.Size = 10
      End With
      i = i + 1
    Next
  End With
End Sub
PHP:
Sub CreateControls()
 AddtbFormRange Range("A1:G1")
End Sub
Sự khác biệt code này với code ở bài 3 là ở chổ:
PHP:
With ThisWorkbook.VBProject.VBComponents.Add(3)
và:
PHP:
With ThisWorkbook.VBProject.VBComponents("UserForm1")
1 cái vừa tạo UserForm vừa tạo các control và 1 cái là tạo control trên UserForm có sẳn

Sao tải File của Thầy về nó lại báo lỗi 1004 thế này nhỉ?

Programmatic access to Visual Basic Project is not trusted

Và nó tô vàng tại dòng này:

With ThisWorkbook.VBProject.VBComponents("UserForm1")
 
Upvote 0
Nó báo not trusted, thì bây giờ set trust nó trong security
 
Upvote 0
Sao tải File của Thầy về nó lại báo lỗi 1004 thế này nhỉ?

Programmatic access to Visual Basic Project is not trusted

Và nó tô vàng tại dòng này:

With ThisWorkbook.VBProject.VBComponents("UserForm1")
Cái này nói hoài, tưởng chú Learning_Excel này đã biết rồi chứ
Hic... Khi gặp thông báo lỗi, bấm nút Help là biết liền
 
Upvote 0
Minh hoạ cách đặt tên textbox theo field name, và gán giá trị từ Data vào textbox:
1. Đặt tên:

PHP:
For Each Clls In SrcRng
      With .Designer.Controls.Add("forms.TextBox.1", Clls)
      ....

2. Gán giá trị từ Data vào textbox:

Cách 1: Controls(i), áp dụng cho code mở form:

PHP:
Private Sub UserForm_Initialize()
Arr = Range("A1:J5").Value
j = 1
For i = 1 To Me.Controls.Count - 1 Step 2
Me.Controls(i - 1) = Arr(2, j)
   j = j + 1
Next
End Sub

Cách 1 này khó sử dụng khi trên form có thêm các control khác như Label, Command Button (được, nhưng khó kiểm soát, không phải khó làm)

Cách 2: Controls(CtrlName) áp dụng cho nút nhấn Next:

PHP:
Private Sub CommandButton1_Click()
Arr = Range("A1:J5").Value
k = k + 1
For i = 1 To UBound(Arr, 2)
    Me.Controls(Arr(1, i)) = Arr(k + 1, i)
Next
If k > 3 Then k = 0
End Sub

Cách này thì khó gán ngược giá trị xuống sheet!

Nói chung, đặt tên control theo số là dễ kiểm soát nhất, và dễ xử lý Up, down, như Sealand đã nói.

Note:
Sửa code của ndu 1 tí tẹo:

.Top = i * dH + 18
sửa thành:
.Top = i * (dH + 5) + 10

với 10 là khoảng cách textbox đầu tiên đến mép trên, 5 là khoảng cách 2 textbox liền kề

Ngoài ra, tạo label bên trái, textbox bên phải. ThuNghi làm ngược và đưa form mẫu ngược rồi.
 

File đính kèm

Upvote 0
Vậy còn mình muốn trong userform hiện ngang 3 textbox, xuống 3 textbox... tiếp tiếp xuống 3 nữa giống bài của anh Sealand vậy là sao Thầy??? Thanks
 
Upvote 0
Cách 1: Controls(i), áp dụng cho code mở form:
..................

Cách 2: Controls(CtrlName) áp dụng cho nút nhấn Next:
..................
Mỗi người thích mỗi kiểu khác nhau. Theo em, để dung hòa thì làm vầy:
- Tên của các Control cứ đặt tùy ý
- Việc đánh dấu ta sẽ nhờ Tag properties

Như vầy:
Mã:
With .Designer.Controls.Add("forms.TextBox.1", Clls)
  .Left = 30 + dW / 2: .Top = i * (dH + 5) + 10
  .Width = dW: .Height = dH
  [COLOR=red][B].Tag = i + 1[/B][/COLOR]
End With
Còn code trên UserForm thì vầy:
PHP:
Private Sub tbGetVal(ByVal SrcRng As Range, ByVal iR As Long)
  Dim Ctl As Control, Arr
  Arr = SrcRng.Value
  For Each Ctl In Me.Controls
    If TypeOf Ctl Is MSForms.TextBox Then
      Ctl.Text = Arr(iR, Ctl.Tag)
    End If
  Next
End Sub
PHP:
Private Sub UserForm_Initialize()
  tbGetVal Sheet1.Range("A1:J5"), 2
End Sub
PHP:
Private Sub CommandButton1_Click()
  tbGetVal Sheet1.Range("A1:J5"), 3
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom