Em chào các Anh/Chị
Em có 1 file excel. Em muốn các Anh/Chị Vào Modul có tên là "Show" trong file ở dưới và chạy Sub "hello"
Nhập 1 số bất kỳ vào form và nhấn ok . Câu hỏi :
Cho em hỏi là tại sao ô A10 nó không hiện giá trị mình vừa điền ạ . Có thể cho em cách khắc phục thì càng tốt ạ
Em cảm ơn rất nhiều <3
Nôm na như bài #24 đã nói, là bạn nhập dữ liệu vào đâu thì sẽ lấy dữ liệu từ đó gán xuống ô A1, cụ thể là bạn nhập vào txttuoi thì sẽ lấy từ txttuoi để gán xuống ô A1, do đó sau dấu bằng không phải là Me.txttuoi thì ô A1 sẽ không nhận được dữ liệu mà bạn nhập vào txttuoi.
Anh ơi! Nhưng mà tại sao Age lại không được ạ chẳng phải mình đang code trên userform đấy sao với mình cũng đã đặt tên userform đó là Age rồi . Cái thuộc tính getage nó cũng là txttuoi.Value rồi . Nếu như anh bảo sao mình không viết là txttuoi.getage đi . Nếu viết như thế sẽ bị trùng đúng không ạ nên chắc chắn cái Age và Me nó đều biểu thị cho userform . Nhưng khác nhau của 2 đứa naỳ là thế nào ạ . Mong anh giải thích kĩ giúp em với
Anh ơi! Nhưng mà tại sao Age lại không được ạ chẳng phải mình đang code trên userform đấy sao với mình cũng đã đặt tên userform đó là Age rồi . Cái thuộc tính getage nó cũng là txttuoi.Value rồi . Nếu như anh bảo sao mình không viết là txttuoi.getage đi . Nếu viết như thế sẽ bị trùng đúng không ạ nên chắc chắn cái Age và Me nó đều biểu thị cho userform . Nhưng khác nhau của 2 đứa naỳ là thế nào ạ . Mong anh giải thích kĩ giúp em với
Đoạn này thì ngoài khả năng của mình mất rồi. Bạn chịu khó chờ xem có thành viên nào nắm được sẽ giải thích cho bạn, hoặc bạn thử tìm tài liệu nghiên cứu thêm vậy.
Đoạn này thì ngoài khả năng của mình mất rồi. Bạn chịu khó chờ xem có thành viên nào nắm được sẽ giải thích cho bạn, hoặc bạn thử tìm tài liệu nghiên cứu thêm vậy.
Vậy mình cũng cố gắng kiên nhẫn giải thích cho bạn.
- Khi bạn nhập các ký tự là nhập vào TextBox có tên là txttuoi chứ không phải là nhập vào userfom có tên là age, sau đó dữ liệu đó được gán từ txttuoi xuống ô A1 trong trang tính.
Anh ơi! Nhưng mà tại sao Age lại không được ạ chẳng phải mình đang code trên userform đấy sao với mình cũng đã đặt tên userform đó là Age rồi . Cái thuộc tính getage nó cũng là txttuoi.Value rồi . Nếu như anh bảo sao mình không viết là txttuoi.getage đi . Nếu viết như thế sẽ bị trùng đúng không ạ nên chắc chắn cái Age và Me nó đều biểu thị cho userform . Nhưng khác nhau của 2 đứa naỳ là thế nào ạ . Mong anh giải thích kĩ giúp em với
Cái sai của bạn như tôi trình bầy kỹ ở bên dưới. Nói tóm tắt thì là bạn không hiển thị form Age. Bạn tạo 1 phiên bản của Age (frm As New Age) rồi hiển thị nó (frm.Show). Bạn nhập dữ liệu vào textbox của "phiên bản" khác của Age nên trong textbox đó có dữ liệu. Nhưng khi nhập xuống sheet thì bạn không lấy từ <phiên bản>.getAge mà bạn lấy từ Age.getAge, mà bản thân Age không được hiển thị (chỉ phiên bản frm được hiển thị), textbox trên Age RỖNG, vậy không có gì được nhập xuống sheet. Dễ hiểu. Nếu thay vì Age.getAge mà bạn dùng Me.getAge thì khi frm được hiển thị thì Me.getAge = frm.getAge, khi form Age được hiển thị thì Me.getAge = Age.getAge. Tức dùng Me.getAge thì luôn là đọc từ texbox txttuoi của Form HIỆN HÀNH.
------------
Ta xét code của bạn ở tập tin #1.
Mã:
Sub hello()
Dim frm As New Age
frm.Show
If frm.Cancel = True Then
MsgBox "Cancelled"
Else
Debug.Print frm.getAge
End If
End Sub
Mã:
Public Property Get getAge() As Variant
getAge = txttuoi.Value
End Property
Private Sub Ok_Click_Click()
ThisWorkbook.Sheets("Sheet1").Range("A10").Value = Age.getAge
Me.Hide
End Sub
Về mặt cú pháp và lôgíc thì nhìn qua thấy được. Ta xét hoạt động.
Có một cái khuôn mẫu là Age. Khi chạy Sub hello thì một "người em sinh đôi" của Age được tạo (frm As New Age) và hiển thị. Nó không phải là Age mà là một "phiên bản" của Age. Ta gọi tạm là "một phiên bản của Age". Chỉ có "một phiên bản của Age" được hiển thị chứ bản thân Age không được hiển thị. Khi "một phiên bản của Age" đang hiển thị và bạn nhập "Ngày mai em đi" rồi nhấn OK thì cái gì sảy ra? Bạn nhập "Ngày mai em đi" vào textbox của "một phiên bản của Age", còn textbox của Age thì vẫn trống vì chỉ "một phiên bản của Age" hiển thị chứ Age có hiển thị đâu.
Age.getAge = Age.txttuoi.Value = "". Do Age.textbox trống nên A10 = "RỖNG".
Thế nếu sửa thành
Private Sub Ok_Click_Click()
ThisWorkbook.Sheets("Sheet1").Range("A10").Value = Me.getAge
Me.Hide
End Sub
Cái sai của bạn như tôi trình bầy kỹ ở bên dưới. Nói tóm tắt thì là bạn không hiển thị form Age. Bạn tạo 1 phiên bản của Age (frm As New Age) rồi hiển thị nó (frm.Show). Bạn nhập dữ liệu vào textbox của "phiên bản" khác của Age nên trong textbox đó có dữ liệu. Nhưng khi nhập xuống sheet thì bạn không lấy từ <phiên bản>.getAge mà bạn lấy từ Age.getAge, mà bản thân Age không được hiển thị (chỉ phiên bản frm được hiển thị), textbox trên Age RỖNG, vậy không có gì được nhập xuống sheet. Dễ hiểu. Nếu thay vì Age.getAge mà bạn dùng Me.getAge thì khi frm được hiển thị thì Me.getAge = frm.getAge, khi form Age được hiển thị thì Me.getAge = Age.getAge. Tức dùng Me.getAge thì luôn là đọc từ texbox txttuoi của Form HIỆN HÀNH.
------------
Ta xét code của bạn ở tập tin #1.
Mã:
Sub hello()
Dim frm As New Age
frm.Show
If frm.Cancel = True Then
MsgBox "Cancelled"
Else
Debug.Print frm.getAge
End If
End Sub
Mã:
Public Property Get getAge() As Variant
getAge = txttuoi.Value
End Property
Private Sub Ok_Click_Click()
ThisWorkbook.Sheets("Sheet1").Range("A10").Value = Age.getAge
Me.Hide
End Sub
Về mặt cú pháp và lôgíc thì nhìn qua thấy được. Ta xét hoạt động.
Có một cái khuôn mẫu là Age. Khi chạy Sub hello thì một "người em sinh đôi" của Age được tạo (frm As New Age) và hiển thị. Nó không phải là Age mà là một "phiên bản" của Age. Ta gọi tạm là "một phiên bản của Age". Chỉ có "một phiên bản của Age" được hiển thị chứ bản thân Age không được hiển thị. Khi "một phiên bản của Age" đang hiển thị và bạn nhập "Ngày mai em đi" rồi nhấn OK thì cái gì sảy ra? Bạn nhập "Ngày mai em đi" vào textbox của "một phiên bản của Age", còn textbox của Age thì vẫn trống vì chỉ "một phiên bản của Age" hiển thị chứ Age có hiển thị đâu.
Age.getAge = Age.txttuoi.Value = "". Do Age.textbox trống nên A10 = "RỖNG".
Thế nếu sửa thành
thì sao?
Me luôn ám chỉ class (module) mà ở đó từ khóa ME được sử dụng. Vd. trong module của Sheet13 thì Me chính là Sheet13 - Me.Range("A7") có nghĩa là Sheet13.Range("A7"). Trong mudule của đối tượng Age thì Me chính là Age - Me.getAge có nghĩa là Age.getAge. Trong mudule của đối tượng frm ("một phiên bản của Age") thì Me chính là frm - Me.getAge có nghĩa là frm.getAge. Do bạn nhập "Ngày mai em đi" vào textbox của frm nên Me.getAge = frm.getAge = frm.txttuoi.Value = "Ngày mai em đi". Vậy A10 = "Ngày mai em đi". Thế thôi.
Thực ra bạn tạo thuộc tính getAge cho Age cũng được nhưng không tạo cũng được. Lúc đó thay cho Me.getAge thì là Me.txttuoi.Value.
Mà tôi không hiểu dụng ý bạn dùng frm As New Age để làm gì. Nếu không dùng frm thì thay frm.Show bằng Age.Show thôi.
Dạ vâng ạ ! Em cảm ơn anh batman1 nhiều lắm .
Thật ra việc em tạo một "Phiên bản khác của Age" cũng chỉ là em muốn thử . Em muốn được gặp lỗi (em muốn code mình tạo ra không chạy) càng nhiều càng tốt ^^ Câu hỏi:
(1) Nhưng mà anh ơi! . Khi mà mình đang code trên userform . Thì mình dùng từ khóa Me trên userform thì nó ám chỉ cả việc dùng cho userform Age và một phiên bản khác của Age đúng không ạ .
(2) Nếu mà khi tạo một phiên bản khác của userform Age thì tất cả các bảng điều khuyển mà mình sử dụng trong userform Age (textBox , commandBox) đều có "Name" giống nhau nhưng mà thật ra có có 2 phiên bản đúng không ạ hay nói cách khác . Việc mình tạo ra một phiên bảng khác của userform Age ( Dim frm As New Age ) thì tất cả bảng điều khuyển ở trong Age cũng có một phiên bản khác nhưng tên giống nhau . Điều này có đúng không ạ
(1) Nhưng mà anh ơi! . Khi mà mình đang code trên userform . Thì mình dùng từ khóa Me trên userform thì nó ám chỉ cả việc dùng cho userform Age và một phiên bản khác của Age đúng không ạ .
Đúng rồi. Thực ra cái code mà bạn viết có thể hiểu là "mẫu" là "khuôn". Khi chạy code thì trên cơ sở "mẫu" hay "khuôn" đó ĐỐI TƯỢNG mới được tạo. "Mẫu" thì chỉ có 1 nhưng trong run-time bạn có thể tạo rất rất nhiều ĐỐI TƯỢNG. Bạn có thể hiểu nôm na code nó như là công thức làm bánh ấy: bao nhiêu bột, bột gì, bột nở gì, dầu thơm, đường, nho khô ... Từ công thức đó có thể tạo ra 100 chiếc bánh - 100 ĐỐI TƯỢNG. Vd. code của Dictionary chỉ có 1, nó nằm trong thư viện từ khi cài hệ điều hành Windows cơ, nhưng chả có ĐỐI TƯỢNG nào được tạo. Chỉ tới khi chạy code của bạn thì code đó mới tạo ra vd. 100 ĐỐI TƯỢNG Dictionary.
Code trong module Form cũng thế. Bạn dùng Me nhưng nó là gì thì phải đợi tới khi form đượ̣c hiển thị. Nếu form đang hiển thị là Age thì Me ám chỉ Age, còn nếu form đang hiển thị là frm thì Me ám chỉ frm.
------------
Thì tôi đã viết rõ rồi mà
Trong mudule của đối tượng Age thì Me chính là Age - Me.getAge có nghĩa là Age.getAge. Trong mudule của đối tượng frm ("một phiên bản của Age") thì Me chính là frm - Me.getAge có nghĩa là frm.getAge. Do bạn nhập "Ngày mai em đi" vào textbox của frm nên Me.getAge = frm.getAge = frm.txttuoi.Value = "Ngày mai em đi". Vậy A10 = "Ngày mai em đi". Thế thôi.
2. Chạy hichic -> nhấn OK -> bạn nhìn thấy thông báo: "Toi là Age". Tại sao? Bởi bạn lấy Caption của đích thân Age (MsgBox Age.Caption), mà Caption đó được thiết lập là "Toi là Age" trong hichic.
1. Chạy hello -> nhấn OK -> bạn nhìn thấy thông báo: "Your Age". Tại sao? Bởi bạn lấy Caption của đích thân Age (MsgBox Age.Caption), mà Caption đó được thiết lập trong design-time bằng tay là "Your Age" (trong hello bạn thiết lập Caption cho frm, Caption của Age vẫn là Your Age)
Tóm lại:
1. Nếu trong code của form dùng Age thì LUÔN LUÔN là Age cho dù form đang hiển thị có là Age hay chỉ là "phiên bản của Age"
2. Nếu trong code của form dùng Me thì nó là Age khi form đang hiển thị là Age, hoặc là "phiên bản của Age" nếu form đang hiển thị là "phiên bản của Age".
Tức Me luôn là form HIỆN HÀNH đang HIỂN THỊ. Do "từ xưa tới nay" nhiều người chả bao giờ tạo và hiển thị "phiên bản" của Age nên nhiều người nghĩ là Age.getAge và Me.getAge là như nhau, dùng cái nào cũng được. Nhưng bạn đã thấy là nếu bạn lúc dùng Age lúc thì dùng "phiên bản của Age" thì code trong form: Age.getAge và Me.getAge là 2 cái hoàn toàn khác nhau. Cái đầu luôn là truy cập đích thân tới form cụ thể là Age bất luận form đang hiển thị có là Age hay không, trong khi đó cái thứ 2 luôn truy cập tới form hiện hành đang hiển thị. Tùy cái đang hiển thị là gì thì truy cập tới nó.
Private Sub Ok_Click_Click()
MsgBox Age.Caption
Unload Me
End Sub
Khi bạn chạy hichic thì chỉ có 1 form là Age, 1 textbox txttuoi và 1 OK trên Age.
Khi bạn chạy hello thì có 2 form: form đang hiển thị là frm. Nhưng khi nhấn OK thì do có truy cập tới thuộc tính (Caption) của Age - Age.Caption, nên đối tượng kiểu Age được tạo nhưng bị ẩn. Tức trong trường hợp này ở thời điểm hiển thị form thì chỉ có frm. Nhưng ở thời điểm nhấn OK thì Age được tạo nhưng bị ẩn (chả có chỗ nào có Age.Show). Trên frm có 1 textbox txttuoi và 1 OK, trên Age đang bị ẩn cũng tương tự có 1 textbox txttuoi và 1 OK. Tức tổng cộng ở thời điểm click OK trên frm có 2 textbox txttuoi và 2 OK - 1 textbox txttuoi và 1 OK trên frm đang hiển thị và 1 textbox txttuoi và 1 OK trên Age đang bị ẩn.
(2) Nếu mà khi tạo một phiên bản khác của userform Age thì tất cả các bảng điều khuyển mà mình sử dụng trong userform Age (textBox , commandBox) đều có "Name" giống nhau nhưng mà thật ra có có 2 phiên bản đúng không ạ hay nói cách khác . Việc mình tạo ra một phiên bảng khác của userform Age ( Dim frm As New Age ) thì tất cả bảng điều khuyển ở trong Age cũng có một phiên bản khác nhưng tên giống nhau . Điều này có đúng không ạ
...
Thật ra việc em tạo một "Phiên bản khác của Age" cũng chỉ là em muốn thử . Em muốn được gặp lỗi (em muốn code mình tạo ra không chạy) càng nhiều càng tốt ^^
...
Do đâu bạn có cái ý tưởng là "càng nhiều càng tốt"?
Muốn thử, muốn học nhanh thì học cách debug code, cách đổ stack và heap memory ra xem. Có như vậy, bạn mới thức ngộ được những cái như "Me" là cái gì, lúc nào thì đối tượng nào đang nắm tiền tố.
2. Chạy hichic -> nhấn OK -> bạn nhìn thấy thông báo: "Toi là Age". Tại sao? Bởi bạn lấy Caption của đích thân Age (MsgBox Age.Caption), mà Caption đó được thiết lập là "Toi là Age" trong hichic.
1. Chạy hello -> nhấn OK -> bạn nhìn thấy thông báo: "Your Age". Tại sao? Bởi bạn lấy Caption của đích thân Age (MsgBox Age.Caption), mà Caption đó được thiết lập trong design-time bằng tay là "Your Age" (trong hello bạn thiết lập Caption cho frm, Caption của Age vẫn là Your Age)
Tóm lại:
1. Nếu trong code của form dùng Age thì LUÔN LUÔN là Age cho dù form đang hiển thị có là Age hay chỉ là "phiên bản của Age"
2. Nếu trong code của form dùng Me thì nó là Age khi form đang hiển thị là Age, hoặc là "phiên bản của Age" nếu form đang hiển thị là "phiên bản của Age".
Tức Me luôn là form HIỆN HÀNH đang HIỂN THỊ. Do "từ xưa tới nay" nhiều người chả bao giờ tạo và hiển thị "phiên bản" của Age nên nhiều người nghĩ là Age.getAge và Me.getAge là như nhau, dùng cái nào cũng được. Nhưng bạn đã thấy là nếu bạn lúc dùng Age lúc thì dùng "phiên bản của Age" thì code trong form: Age.getAge và Me.getAge là 2 cái hoàn toàn khác nhau. Cái đầu luôn là truy cập đích thân tới form cụ thể là Age bất luận form đang hiển thị có là Age hay không, trong khi đó cái thứ 2 luôn truy cập tới form hiện hành đang hiển thị. Tùy cái đang hiển thị là gì thì truy cập tới nó.
Private Sub Ok_Click_Click()
MsgBox Age.Caption
Unload Me
End Sub
Khi bạn chạy hichic thì chỉ có 1 form là Age, 1 textbox txttuoi và 1 OK trên Age.
Khi bạn chạy hello thì có 2 form: form đang hiển thị là frm. Nhưng khi nhấn OK thì do có truy cập tới thuộc tính (Caption) của Age - Age.Caption, nên đối tượng kiểu Age được tạo nhưng bị ẩn. Tức trong trường hợp này ở thời điểm hiển thị form thì chỉ có frm. Nhưng ở thời điểm nhấn OK thì Age được tạo nhưng bị ẩn (chả có chỗ nào có Age.Show). Trên frm có 1 textbox txttuoi và 1 OK, trên Age đang bị ẩn cũng tương tự có 1 textbox txttuoi và 1 OK. Tức tổng cộng ở thời điểm click OK trên frm có 2 textbox txttuoi và 2 OK - 1 textbox txttuoi và 1 OK trên frm đang hiển thị và 1 textbox txttuoi và 1 OK trên Age đang bị ẩn.
1. Nếu bạn có Age.Show thì chỉ có 1 form là Age và 1 textbox txttuoi và 1 OK trên Age.
2. Nếu bạn có frm.Show thì ở thời điểm hiển thị frm thì chỉ có 1 đối tượng là frm được tạo và trên nó có 1 textbox txttuoi và 1 OK. Nếu trong code không có chỗ nào truy cập đích thân tới Age thì tới tận khi đóng frm thì vẫn chỉ có 1 đối tượng frm với 1 textbox txttuoi và 1 OK trên nó. Nhưng nếu có 1 chỗ nào đó truy cập tới thuộc tính hay gọi phương thức của Age, vd. Age.txttuoi, thì ở thời điểm truy cập tới thuộc tính hay gọi phương thức của Age ở "chỗ ấy" thì đối tượng Age được tạo nhưng ở trạng thái ẩn. Và từ lúc đó trở đi có 2 đối tượng là frm (đang hiển thị) và Age (ẩn) và 2 textbox txttuoi và 2 OK.
Nếu muốn truy cập tới textbox của form HIỆN HÀNH bất luận nó là frm hay Age thì bắt buộc phải dùng Me.txttuoi.Value. Thế thôi.
Đọc bài viết của anh thật sự rất lâu . Nhưng nó rất xứng đáng và thật sự rất hứng thú . Nhưng em vẫn muốn anh kiểm tra những lời em nói sau đây để cho chắc ^^ .
Em cảm ơn anh nhiều lắm <3
Giả sử mình có
Mã:
Private Sub Ok_Click_Click()
MsgBox Me.Caption
Unload Me
MsgBox Age.Caption
End Sub
có Sub hello:
Mã:
Sub hello()
Dim frm As New Age
frm.Caption = "Toi la frm"
frm.Show
End Sub
Các dòng code bên trong sub hello là "Mẫu" , "Khuôn" hay "Công Thức" .
Sau Khi chạy xong Sub hello thì cái đối tượng Me bên trong sub Ok_Click_Click nó mới được tạo nhờ "Công Thức" đó . Tại Thời điểm mình nhấn nút Ok thì sự kiện Click xảy ra . Đối tượng Me đã được thay bằng frm :
Mã:
Private Sub Ok_Click_Click()
MsgBox frm.Caption
Unload frm
MsgBox Age.Caption
End Sub
Cũng tại thời điểm sau khi nhấn nút Ok thì hiện tại mình có 2 form
Một là : frm và trong đó có 1 textbox txttuoi và 1 OK
Hai là : Age và trong có cũng có 1 textbox txttuoi và 1 OK nhưng bị ẩn
Do đâu bạn có cái ý tưởng là "càng nhiều càng tốt"?
Muốn thử, muốn học nhanh thì học cách debug code, cách đổ stack và heap memory ra xem. Có như vậy, bạn mới thức ngộ được những cái như "Me" là cái gì, lúc nào thì đối tượng nào đang nắm tiền tố.
Em cảm ơn anh ạ . Em là người mới nên chắc cách đổ stack và heap memory thì để một thời gian sau đi ạ . Bởi vì bây giờ em nghe tên vẫn còn chưa biết là gì nữa
Đọc bài viết của anh thật sự rất lâu . Nhưng nó rất xứng đáng và thật sự rất hứng thú . Nhưng em vẫn muốn anh kiểm tra những lời em nói sau đây để cho chắc ^^ .
Em cảm ơn anh nhiều lắm <3
Giả sử mình có
Mã:
Private Sub Ok_Click_Click()
MsgBox Me.Caption
Unload Me
MsgBox Age.Caption
End Sub
có Sub hello:
Mã:
Sub hello()
Dim frm As New Age
frm.Caption = "Toi la frm"
frm.Show
End Sub
Các dòng code bên trong sub hello là "Mẫu" , "Khuôn" hay "Công Thức" .
Sau Khi chạy xong Sub hello thì cái đối tượng Me bên trong sub Ok_Click_Click nó mới được tạo nhờ "Công Thức" đó . Tại Thời điểm mình nhấn nút Ok thì sự kiện Click xảy ra . Đối tượng Me đã được thay bằng frm :
Mã:
Private Sub Ok_Click_Click()
MsgBox frm.Caption
Unload frm
MsgBox Age.Caption
End Sub
Cũng tại thời điểm sau khi nhấn nút Ok thì hiện tại mình có 2 form
Một là : frm và trong đó có 1 textbox txttuoi và 1 OK
Hai là : Age và trong có cũng có 1 textbox txttuoi và 1 OK nhưng bị ẩn
Bài đã được tự động gộp:
Em cảm ơn anh ạ . Em là người mới nên chắc cách đổ stack và heap memory thì để một thời gian sau đi ạ . Bởi vì bây giờ em nghe tên vẫn còn chưa biết là gì nữa