Đố vui về VBA!

Liên hệ QC

anhtuan1066

Thành viên gạo cội
Tham gia
10/3/07
Bài viết
5,802
Được thích
6,911
Nhằm cũng cố kiến thức về VBA cho các bạn mới bắt đầu và cả những bạn đang ứng dụng mà chưa hiểu nhiều về nó, tôi mở topic này với mong mõi qua những câu hỏi vui, các bạn sẽ nhận định lại sự hiểu biết cũa mình... (Kễ cã chính tôi cũng đang tập tành nên có rất nhiều cái chưa biết)
Mong rằng topic sẽ mang đến cho các bạn những khám phá thú vị với những cái tưỡng chừng như đã biết
Mong nhận dc bài viết về câu đố cũa các cao thủ! Còn các bạn mới thì đừng ngại khi đưa ra ý kiến cũa mình.. Có sai có sữa sẽ hoàn thiện!
Tôi xin mỡ màn trước bằng 1 câu hỏi đơn giãn
ANH TUẤN

CÂU HỎI 1: Tại sao biến K ko hoạt động?
Tôi muốn khi nhấn vào 1 button thì cell A1 sẽ tăng lên 1 đơn vị... Tôi đã làm như sau:
-Tạo 1 Command Button (nút nhấn thuộc thanh Control Toolbox), click phải chuột lên nút nhấn, chọn View code, rồi gõ vào đoạn code sau:
PHP:
Private Sub CommandButton1_Click()
   K = K + 1
   Range("A1").Value = K
End Sub
Ban đầu K chưa có gì, xem như =0, nhấn nút lần thứ nhất thì K dc tăng thêm 1, vậy K hiện tại sẽ bằng 1, và gán K vào cell A1 thì đương nhiên A1 sẽ =1... Nhấn nút lần 2, K lại dc tăng thêm 1 nên hiện tại K sẽ =2 và cell A1 cũng sẽ =2... vân vân.. từ đó diễn tiến tiếp...
Hi.. hi.. Điều này nghe qua có vẽ rất hợp lý, ấy thế mà khi nhấn nút nó chỉ hoạt động dc duy nhất 1 lần (A1 = 1) rồi thôi ko nhút nhít nữa...
Các bạn có thể giãi thích tại sao lại như thế ko? Tại sao những lần nhấn nút sau đó K lại ko tăng thêm tí nào (vì thực tế A1 vẫn cứ = 1 hoài) ?
ANH TUẤN
 
Thì cũng đúng! Vậy tùy trường hợp mà chọn lựa thôi



Chính vì sợ nó chạy liên tục nên tôi có đoạn If TypeName(cbox) = "Nothing" Then rồi đó. Bảo đảm chỉ chạy 1 lần
(không tin có thể dùng MsgBox đặt trong If để thử)
Vậy: Khi nào code gì đó bị lỗi thì cbox sẽ = Nothing và sự kiện MouseMove sẽ tự khởi tạo lại nó
------------------
Mà công nhận chú Nghĩa này tiếp cận vấn đề nhanh ghê! Gợi ý 1 chút đã làm trúng phốc!
Ẹc... Ẹc...


Em nhìn thấy code Thầy chứ! Tuy nhiên Thầy đặt con trỏ vào frame rồi để y đó, không cần rê đi đâu hết, Thầy sẽ thấy màn hình nó chớp chớp nhanh liên tục và dung lượng máy tăng lên thấy rõ rệt (theo máy em); Thầy thử test xem sao!
 
Upvote 0
Em có cảm giác thế này, mà hình như là đúng: Việc ta vẽ lên sheet 1 cái Frame rồi đặt Combobox lên đó thì ComboBox hiển thị được tiếng Việt Unicode, cũng giống như đặt ComboBox này lên trên Form vậy. Như vậy cái Frame này đóng vai trò như một "điểm tựa" cho anh ComboBox đặt chân. Từ đó có thể suy ra rằng ta có thể thay Frame bởi MultiPage cũng được.
 
Upvote 0
Em nhìn thấy code Thầy chứ! Tuy nhiên Thầy đặt con trỏ vào frame rồi để y đó, không cần rê đi đâu hết, Thầy sẽ thấy màn hình nó chớp chớp nhanh liên tục và dung lượng máy tăng lên thấy rõ rệt (theo máy em); Thầy thử test xem sao!
Thì cũng giống như khi ta dùng sự kiện Change hoặc SelectionChange thôi. Dù ta đã "rào" bằng dòng lệnh If Target.Address = ... hoặc If Not Intersect(....).... gì gì đó thì code sự kiện nó vẫn có công đoạn kiểm tra vậy? Kiểm tra đúng điều kiện thì nó làm, không thì... nghỉ
Vậy chẳng lẽ vì sợ cái vụ kiểm tra ấy mà ta nghỉ xài Change và SelectionChange?
---------------------------
Còn cái vụ chớp chớp giật giật gì đó thì máy tôi không bị, CPU trong Task Manager cũng không tăng (cần quay phim màn hình để chứng minh không?)
---> Suy ra: Máy Nghĩa cùi bắp? Ẹc... Ẹc...
 
Lần chỉnh sửa cuối:
Upvote 0
Còn cái vụ chớp chớp giật giật gì đó thì máy tôi không bị, CPU trong Task Manager cũng không tăng (cần quay phim màn hình để chứng minh không?)
---> Suy ra: Máy Nghĩa cùi bắp? Ẹc... Ẹc...
Hehehehe, đâu có cùi bắp lắm đâu! Mua từ năm 2009 tới giờ, chỉ mỗi thay bàn phím thôi!
 
Upvote 0
Ừ thì dễ! Nhưng code dài quá. Tôi làm bài này đúng 10 dòng code và chỉ gọn trong sheet1
Tải file về xem cả buổi mà chẳng hiểu cách làm thế nào để ra được như thế. Hic, tạm thời lưu file khi nào cần thì cứ đem ra xào nấu lại. Em nghĩ chắc cũng có người giống em thôi. Nếu không phải thì chắc là mình thuộc dạng .... nhất.

Cái vụ chớp màn hình gì đó thì máy tính mình cũng không bị. Anh Nghĩa thay máy tính đi nha
 
Upvote 0
Cái vụ chớp màn hình gì đó thì máy tính mình cũng không bị. Anh Nghĩa thay máy tính đi nha

Nó chớp rất nhẹ chứ không phải giật giật, ở trên Window Caption đấy, không chớp trong sheet đâu! Window7 cái caption nó gần như trong suốt nên dễ nhận ra điều này.

Còn đây là "hàng" của mình đây! Làm theo hướng MouseMove (canh rất chuẩn mới không thấy "em" Frame)! Xài bằng RowSource nên không Add List!

[GPECODE=vb]
Option Explicit
Private WithEvents Fra1Cbx1 As MSForms.ComboBox
Private IsCheck As Boolean


''---------------------------------------------------
'' New version!
''---------------------------------------------------
Private Sub Frame1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If IsCheck Then Exit Sub
Set Fra1Cbx1 = Sheet1.Frame1.Controls("ComboBox1")
IsCheck = True
End Sub


Private Sub Fra1Cbx1_Change()
MsgBox Fra1Cbx1
End Sub[/GPECODE]
 

File đính kèm

  • FrameCombo2.xls
    45.5 KB · Đọc: 30
Upvote 0
Đối tượng Combobox của bạn trong video này là đối tượng ở trên Userform, nhưng nó là một ActiveX Control, đặt trên Form thì không vấn đề gì rồi, nhưng bạn thử chèn nó lên Sheet xem nào. Lưu ý khi chèn trên Sheet có 2 loại đối tượng ComboBox đấy nhé, 1 cái thuộc Form Controls, 1 cái thuộc ActiveX Controls. Trong video trước của bạn tại bài #897 là ComboBox của Form Controls, mà với cái này thì cứ để thiết lập mặc định của Windows cũng hiển thị được tiếng Việt Unicode.
cái Anh hỏi là cái này chắc ko sai chứ ???? đưa file lên Youtube nó cứ đòi đợi xử lý lâu quá
[video=youtube;M7wvk_utY9g]http://www.youtube.com/watch?v=M7wvk_utY9g[/video]
 
Lần chỉnh sửa cuối:
Upvote 0
- Vẽ cái Frame
- Click chuột phải vào đó, chọn Frame Object --> Edit
- Tự nhiên sẽ thấy và.. biết liền
Bổ sung nha:

1) Vẽ Frame:

Mặc định là trong hộp ActiveX Controls là không có anh này rồi đó!

Vẽ tại đâu?

Bấm vào nút More Controls (cái biểu tượng cái búa và cái khóa chéo nhau).

Sau khi hộp More Controls hiện ra, chọn vào mục Microsoft Form 2.0 Frame, rồi OK, sau đó ta vẽ trên sheet cái Frame này.

2) Add Controls lên Frame:

Trong chế độ Design, Click phải chuột vào Frame, chọn Frame Objects > Edit

Lúc này ta sẽ có được một ToolBox để add vào Frame.

3) Tạo thuộc tính cho Controls:

Click phải vào control, lúc này có một menu hoàn toàn xa lạ, kệ nó, ta chọn vào mục Properties của nó.

Lưu ý, cái Properties này nó cũng khác với các Properties ta vẫn thường thấy, đó là ta chọn một thuộc tính bất kỳ trong đó, thì nó sẽ hiện giá trị lên trên một Combobox ở trên cùng, muốn thay đổi gì thì thay đổi tại ComboBox đó rồi bấm nút Apply.

4) Bước này là tạo sự kiện cho nó, tạo như thế nào thì đã có các bài nói về chúng rồi, mình không nói lại nữa.
 

File đính kèm

  • MoreCtrl.jpg
    MoreCtrl.jpg
    51.8 KB · Đọc: 78
Upvote 0
Mã:
Private Sub Frame1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
  If TypeName(cbox) = "Nothing" Then
    Set cbox = Sheet1.Frame1.Controls("ComboBox1")
    cbox.List() = Sheet1.Range("A1:A10").Value
  End If
End Sub

Với code trên, theo em nghĩ nó vẫn chưa tối ưu. Khi một code bị lỗi, ngay lập tức TẤT CẢ CÁC BIẾN sẽ giải phóng bộ nhớ hoàn toàn và trả về dạng mặc định của chúng (kể cả biến boolean cũng sẽ trả về dạng False). Vì thế việc Set lại cbox là hoàn toàn hợp lý. Nhưng việc nạp lại List cho cbox thì thừa là vì dù cho có lỗi cách nào đi chăng nữa thì List của nó không thay đổi, có nghĩa là list của nó không tự clear, cho nên ta mỗi lần Set là mỗi lần nạp list sẽ không hay. Nếu dữ liệu ngần ấy thì chả nói gì, còn như dữ liệu vài chục ngàn dòng, sau đó Filter, tính toán, Unique v.v... rồi mới tạo ra một cái Array để gán vào thì hơi ẹc ẹc ...

Theo em thì nên làm như vầy:

Mã:
Private Sub Frame1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If TypeName(cbox) = "Nothing" Then
        With Frame1.Controls("ComboBox1")
[B][COLOR=#0000ff]            If .ListCount = 0 Then .List = Range("A1:A10").Value[/COLOR][/B]
        End With
        Set cbox= Frame1.Controls("ComboBox1")
    End If
End Sub

Có như vậy thì ta chỉ việc Set cho cbox thôi mà không cần phải nạp lại list một lần nào nữa!
 
Lần chỉnh sửa cuối:
Upvote 0
Trong Help có nói:

Join Function

Description

Returns a string created by joining a number of substrings contained in an array.

Syntax:

Join(sourcearray[, delimiter])

sourcearray: Required. One-dimensional array containing substrings to be joined.

delimiter: Optional. String character used to separate the substrings in the returned string. If omitted, the space character (" ") is used. If delimiter is a zero-length string (""), all items in the list are concatenated with no delimiters.

Như vậy hàm Join là một hàm tách thành một chuỗi từ một mảng một chiều, cách thực hiện:

Phần tử trong mảng là dạng chuỗi:

Mã:
Sub Macro8()
    Dim Arr()
    Arr = Array([COLOR=#0000ff]"Giai", "phap", "Excel", ".", "com"[/COLOR])
    MsgBox [COLOR=#ff0000]Join(Arr, "")[/COLOR]
End Sub

Phần tử trong mảng là dạng số:

Mã:
Sub Macro9()
    Dim Arr()
    Arr = Array([COLOR=#0000ff]1, 2, 3, 4, 5[/COLOR])
    MsgBox [COLOR=#ff0000]Join(Arr, ", ")[/COLOR]
End Sub


Câu đố đặt ra, Nếu thực hiện đúng cấu trúc, thì khi nào hàm Join sẽ bị lỗi?

Chắc có lẽ không ai thèm trả lời câu hỏi này, vậy mình "tự sướng" luôn! (tự sướng nên chả thú vị gì cả).

Các kiểu khai báo mảng thuộc kiểu String, Variant, hoặc không khai báo loại nào đều không phát sinh lỗi:

Mã:
Sub Test1()
    Dim i As Byte
    Dim Arr(0 To 9)
    Dim sArr(0 To 9) As String
    Dim vArray(0 To 9) As Variant
    For i = 0 To 9
        Arr(i) = i
        sArr(i) = i
        vArray(i) = i
    Next
    MsgBox Join(Arr, ",")
    MsgBox Join(sArr, ",")
    MsgBox Join(vArray, ",")
End Sub

Nhưng những dạng khai báo là kiểu Numeric (Byte, Long, Double, Date, v.v...) thì sẽ bị "dính chưởng"!

Mã:
Sub Test2()
    Dim i As Byte
    [COLOR=#008000]'Tat ca bien kieu Numeric deu bi loi:[/COLOR]
    [B][COLOR=#0000cd]Dim Arr(0 To 9) As Long [/COLOR][COLOR=#008000]' Integer, Byte, Double, Currency, Date v.v...[/COLOR][/B][COLOR=#0000cd][/COLOR]
    For i = 0 To 9
        Arr(i) = i
    Next
    MsgBox Join(Arr, ",")
End Sub

Vì thế, khi thực hiện hàm Join thì người lập trình phải luôn luôn nằm lòng vấn đề này để mà tránh vì đôi khi mình đã làm đúng với cấu trúc rồi, nhưng tại sao lại phát sinh lỗi thì là do "kiểu nó như thế".
 
Upvote 0
Nhưng những dạng khai báo là kiểu Numeric (Byte, Long, Double, Date, v.v...) thì sẽ bị "dính chưởng"!

Mã:
Sub Test2()
    Dim i As Byte
    [COLOR=#008000]'Tat ca bien kieu Numeric deu bi loi:[/COLOR]
    [B][COLOR=#0000cd]Dim Arr(0 To 9) As Long [/COLOR][COLOR=#008000]' Integer, Byte, Double, Currency, Date v.v...[/COLOR][/B]
    For i = 0 To 9
        Arr(i) = i
    Next
    MsgBox Join(Arr, ",")
End Sub

Vì thế, khi thực hiện hàm Join thì người lập trình phải luôn luôn nằm lòng vấn đề này để mà tránh vì đôi khi mình đã làm đúng với cấu trúc rồi, nhưng tại sao lại phát sinh lỗi thì là do "kiểu nó như thế".

Bạn căn cứ vào đâu để nghĩ rằng: "vì đôi khi mình đã làm đúng với cấu trúc rồi"?. Bạn lấy cái gì ra làm chuẩn, tiêu chí nào để nghĩ là mình làm đúng?.

Người lập trình nào cũng phải đọc help. Dù là ngôn ngữ nào. Không chịu đọc help thì quên luôn chuyện lập trình đi.
Mà đọc help thì phải tìm mọi cách để hiểu. Có người cũng đọc help nhưng cóc hiểu hoặc không hiểu chính xác, không hiểu hết.

Bạn đã đọc về hàm Join trong VBA. Help nói với tôi:

Mã:
Join Function 

Description

Returns a string created by joining a number of [B][COLOR=#ff0000]substrings contained in an array[/COLOR][/B].

Syntax

Join(sourcearray[, delimiter])

The Join function syntax has these named arguments:

Part Description 
sourcearray Required. One-dimensional [B][COLOR=#ff0000]array containing substrings[/COLOR][/B] to be joined. 
delimiter Optional. String character used to separate the substrings in the returned string. If omitted, the space character (" ") is used. If delimiter is a zero-length string (""), all items in the list are concatenated with no delimiters.

Chỗ đỏ đỏ nói là tất cả những phần tử của cái Array kia đều là STRING. Nếu bạn tạo Array mà các phần tử là Numeric rồi bạn bắt Join làm việc thì đâu phải là bạn "đã làm đúng"? Rõ ràng bạn đã làm sai.

Bạn mặc váy cho cậu bé, ấn vào tay nó con búp bê rồi bắt nó chơi "mẹ ru con" mà bạn nghĩ là bạn làm đúng? he he
 
Upvote 0
Bạn căn cứ vào đâu để nghĩ rằng: "vì đôi khi mình đã làm đúng với cấu trúc rồi"?. Bạn lấy cái gì ra làm chuẩn, tiêu chí nào để nghĩ là mình làm đúng?.
Mã:
Returns a string created by joining a number of [B][COLOR=#ff0000]substrings contained in an array[/COLOR][/B].

Theo em câu trên dịch là:

Mã:
Trả về một chuỗi được tạo ra bằng cách kết hợp (tham gia) [COLOR=#ff0000][B]một số chuỗi con chứa trong một mảng[/B][/COLOR]

Theo em hiểu, khi hàm xử lý chuỗi, chuyển từ một chuỗi hay một số, thì việc trả kết quả về là một dạng chuỗi hoặc số trong dạng chuỗi.

Chẳng hạn:

Mã:
[COLOR=#0000cd]?ucase(1)[/COLOR]
[COLOR=#0000cd]1[/COLOR]
[COLOR=#ff0000]?ucase("1")[/COLOR]
[COLOR=#ff0000]1[/COLOR]

Trường hợp xanh là dạng số cũng trả kết quả là 1 và trường hợp đỏ là dạng số trong chuỗi, cũng trả kết quả là 1

Thêm nữa, 2 trường hợp mảng này, một dạng là số và một dạng số trong dạng chuỗi thì hàm Join vẫn cho ra kết quả:

Mã:
Sub Macro1()
    Dim Arr()
    Arr = Array(1, 2, 3, 4, 5)
    MsgBox Join(Arr, ", ")
End Sub

Sub Macro2()
    Dim Arr()
    Arr = Array("1", "2", "3", "4", "5")
    MsgBox Join(Arr, ", ")
End Sub

vậy cái Substring (chuỗi con) đâu nhất thiết phải là một chuỗi hay một số?

Và thủ tục này, i là biến kiểu Byte, nếu một biến X nào đó (không để kiểu) mà bằng i (X = i) thì X chính là dạng Byte, điều này ai cũng biết. Thế thì:

Mã:
Sub Test()
    Dim i As Byte
    Dim Arr(0 To 9)
    For i = 0 To 9
        Arr(i) = i
    Next
[B][COLOR=#0000ff]    MsgBox TypeName(Arr(1))[/COLOR][/B]
[COLOR=#ff0000][B]    MsgBox Join(Arr, ",")[/B][/COLOR]
End Sub

Nhưng Byte thì Byte hàm JOIN vẫn "xơi" tuốt luốt, không bị "mắc xương"!

Thêm nữa, trong HELP không nói rằng "không được dùng mảng một chiều có dạng Numeric Data Type". Chính vì điều này mới đố chứ (he he) và đương nhiên nếu nó đưa câu đó ra thì ai đố làm gì vì ai cũng có thể xem Help!
 
Lần chỉnh sửa cuối:
Upvote 0
Lạ thật, phải chi UNI lại xài được như VNI nhỉ!
VNI thì khỏi nói chắc lúc xưa Microsoft hỗ trợ bây giờ chưa có người VN làm trong đội ngũ của Office nên chưa hỗ trợ Unicode quá !!!!. Sao trên máy e thi ko có hiện tượng như anh nói khi chỉnh sang Script Vietnamese thì dữ liệu đầu vào phải là Unicode tổ hợp mới chấp còn unicode dựng sẵn là bị lỗi như hình anh Ndu đưa, cách Ndu thì mọi trường hợp điều không bị lỗi mà thấy hơi bất tiện sao sao đó vì khi viết code cũng khó khăn vì dân không chuyên mà. File này em test trên máy Win 8, office 2013 với kiểu gõ unicode tổ hợp thì không bị lỗi các Bạn, Anh ,Chị xem có bị lỗi không. Cảm ơn
 

File đính kèm

  • Combobox.xls
    35 KB · Đọc: 10
Upvote 0
Theo em câu trên dịch là:

Mã:
Trả về một chuỗi được tạo ra bằng cách kết hợp (tham gia) [COLOR=#ff0000][B]một số chuỗi con chứa trong một mảng[/B][/COLOR]

Theo em hiểu, khi hàm xử lý chuỗi, chuyển từ một chuỗi hay một số, thì việc trả kết quả về là một dạng chuỗi hoặc số trong dạng chuỗi.

Chẳng hạn:

Mã:
[COLOR=#0000cd]?ucase(1)[/COLOR]
[COLOR=#0000cd]1[/COLOR]
[COLOR=#ff0000]?ucase("1")[/COLOR]
[COLOR=#ff0000]1[/COLOR]

Trường hợp xanh là dạng số cũng trả kết quả là 1 và trường hợp đỏ là dạng số trong chuỗi, cũng trả kết quả là 1

Tôi không dám nói là tôi đã ăn hết trí khôn trong thiên hạ. Nhưng tôi sẽ nói tôi đã hiểu thế nào.

Thứ nhất: substrings contained in an array
Theo tôi help nói rõ ràng là array chứa các chuỗi. Help không nói là: Array chứa các giá trị CÓ THỂ CONVERT thành chuỗi.

Thứ hai: hoặc số trong dạng chuỗi là thế nào?
Nếu giá trị trả về là "12" thì bạn còn có thể cố cãi là: đó là "số trong dạng chuỗi" vì 12 là số. Nhưng nếu trả về "12, 34, 56, 78" thì làm sao cãi được là đó là "số trong dạng chuỗi"? Vì 12, 34, 56, 78 là SỐ gì vậy?

Nếu bạn muốn tranh luận với tôi thì nên dùng từ chính xác.

Thêm nữa, 2 trường hợp mảng này, một dạng là số và một dạng số trong dạng chuỗi thì hàm Join vẫn cho ra kết quả:

Mã:
Sub Macro1()
    Dim Arr()
    Arr = Array(1, 2, 3, 4, 5)
    MsgBox Join(Arr, ", ")
End Sub

Sub Macro2()
    Dim Arr()
    Arr = Array("1", "2", "3", "4", "5")
    MsgBox Join(Arr, ", ")
End Sub

vậy cái Substring (chuỗi con) đâu nhất thiết phải là một chuỗi hay một số?
Cái SubStrings nói trong Join chắc chắn là chuỗi chứ không phải như bạn nói nó có thể là số.
Theo tôi bạn đưa vd. nhưng bạn không hiểu bản chất của vấn đề.

Trong vd. bạn đưa ra nếu bạn dùng TypeName thì bạn có thể đọc "dạng" của giá trị hiện hành. Đó có thể là "Integer" hoặc "String". Nhưng về bản chất thì mỗi phần tử của Arr là VARIANT

Bạn chạy

Mã:
Sub Macro1()
    Dim Arr()
    Arr = Array(1, 2, 3, 4, 5)
    MsgBox Arr(0)
    MsgBox TypeName(Arr(0))
    Arr(0) = "hic hic"
    MsgBox Arr(0)
    MsgBox TypeName(Arr(0))
End Sub

thì không có lỗi nào. Đơn giản vì mỗi phần tử của Arr là VARIANT

Nhưng chạy

Mã:
Sub Macro2()
    Dim Arr(0 To 4) As Long, index As Long
    For index = 0 To 4
        Arr(index) = index + 1
    Next
    MsgBox Arr(0)
    MsgBox TypeName(Arr(0))
    Arr(0) = "hic hic"      '  <-- lỗi
    MsgBox Arr(0)
    MsgBox TypeName(Arr(0))
End Sub

thì có lỗi vì mỗi phần tử của Arr là LONG. Vậy không thể viết: Arr(0) = "hic hic" được.

Nhưng code sau lại không có lỗi

Sub Macro2()
Dim Arr(0 To 4) As Long, index As Long
For index = 0 To 4
Arr(index) = index + 1
Next
MsgBox Arr(0)
MsgBox TypeName(Arr(0))
Arr(0) = "7689"
MsgBox Arr(0)
MsgBox TypeName(Arr(0))
MsgBox TypeName(Arr(1))
End Sub

Đơn giản vì VBA theo tôi quá thân thiện. Bạn có thể nhập STRING nhưng phải ở dạng có thể convert được sang LONG. Lúc đó cái bạn nhập vào sẽ được convert sang LONG nếu cần thiết (nhập Long thì không cần thiết convert, nhập string thì cần) và kiểu của nó là LONG dù bạn đã nhập vào chuỗi.

Khi phần tử là VARIANT thì nếu bạn nhập numeric hay string có thể convert sang numeric thì giá trị của phần tử đó có thể coi là numeric hay là string đều được. Tùy vào tình huống cụ thể mà nó sẽ được dùng với "tư cách" là số hay chuỗi. Tất nhiên "hic hic", "he he" thì chỉ có thể "lên sân khấu" với tư cách là string mà thôi. Nhưng 1 (hoặc "1") thì luôn có thể "lên sân khấu" với tư cách là chuỗi hoặc số.

Bạn đừng so sánh 2 trường hợp - 1 ở bài #931 và 1 ở bài này - nhé. Vì ở bài kia mỗi phần tử của mảng là LONG còn ở bài này mỗi phần tử của mảng là VARIANT. Mà đã là VARIANT thì dù nhập vào SỐ thì nó luôn được "nhìn" là SỐ hoặc CHUỖI tùy theo "nhu cầu" hiện hành.

Và thủ tục này, i là biến kiểu Byte, nếu một biến X nào đó (không để kiểu) mà bằng i (X = i) thì X chính là dạng Byte, điều này ai cũng biết. Thế thì:

Mã:
Sub Test()
    Dim i As Byte
    Dim Arr(0 To 9)
    For i = 0 To 9
        Arr(i) = i
    Next
[B][COLOR=#0000ff]    MsgBox TypeName(Arr(1))[/COLOR][/B]
[COLOR=#ff0000][B]    MsgBox Join(Arr, ",")[/B][/COLOR]
End Sub

Nhưng Byte thì Byte hàm JOIN vẫn "xơi" tuốt luốt, không bị "mắc xương"!
Chơi tuốt thì dĩ nhiên rồi. Ở code trên thì mỗi phần tử của Arr là VARIANT. Bạn có thể nhập SỐ nhưng mỗi phần tử lúc đó có thể xuất hiện với tư cách là SỐ hoặc CHUỖI tùy vào nhu cầu.
Ở bài #931 thì mỗi phần tử của mảng là LONG. Bạn không thấy sự khác biệt giữa 2 trường hợp à?

Thêm nữa, trong HELP không nói rằng "không được dùng mảng một chiều có dạng Numeric Data Type". Chính vì điều này mới đố chứ (he he) và đương nhiên nếu nó đưa câu đó ra thì ai đố làm gì vì ai cũng có thể xem Help!

Help đã nói rất rõ rồi. Sao help lại phhải liệt kê các th cấm? Vd. Hiến Pháp nói: "Ứng viên tham gia bầu cử tổng thống VN phải có quốc tịch Việt Nam, sinh ra trên lãnh thổ VN và có ít nhất 35 tuổi". Thế chưa đủ sao? Hay phải nói thêm: "Cấm những người chưa đủ 35 tuổi, không có quốc tịch VN hoặc không sinh ra trên lãnh thổ VN ...?"

Help nói rõ rồi. Còn chuyện bạn muốn truyền mảng thế nào là quyền của bạn. VBA không cấm. Chỉ có điều nếu bạn truyền mảng "không đúng" thì VBA "phạt". Đó cũng là quyền của VBA. Thế thôi.
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi không dám nói là tôi đã ăn hết trí khôn trong thiên hạ. Nhưng tôi sẽ nói tôi đã hiểu thế nào.

Thứ nhất: substrings contained in an array
Theo tôi help nói rõ ràng là array chứa các chuỗi. Help không nói là: Array chứa các giá trị CÓ THỂ CONVERT thành chuỗi.

Em vẫn chưa tâm phục vì sự trả lời này, bởi vì:

Câu màu đỏ, được hiểu rằng:

1) Các chuổi (con) được chứa trong một mảng

hoặc:

2) Một mảng chứa các chuỗi (con)

Chứ không nói KIỂU DỮ LIỆU CỦA MỘT MẢNG!

Thứ hai: hoặc số trong dạng chuỗi là thế nào?

Ô A1 có giá trị là Nghia_1

Công thức: =RIGHT(A1,1)

Kết quả = 1

Nhưng thực chất đây là một số trong dạng chuỗi (Number stored as text) >> không tính toán được với số này! Thế thôi!

Mã:
Sub Macro2()
    Dim Arr(0 To 4) As Long, index As Long
    For index = 0 To 4
        Arr(index) = index + 1
    Next
    MsgBox Arr(0)
    MsgBox TypeName(Arr(0))
    Arr(0) = "hic hic"      '  <-- lô~i
    MsgBox Arr(0)
    MsgBox TypeName(Arr(0))
End Sub

Vì dạng Long không chấp nhận chuỗi nên phát sinh ra lỗi. OK

Nhưng với VD dưới đây, kiểu số nó ngán kiểu chuỗi chứ thằng kiểu chuỗi nó đâu có ngán kiểu số:

Mã:
Sub test3()

    Dim Arr(0 To 3) [COLOR=#ff0000][B]As String[/B][/COLOR]
    
    Arr(0) = "Hoang"
    Arr(1) = "Trong"
    Arr(2) = "Nghia"
[COLOR=#ff0000][B]    Arr(3) = 2151[/B][/COLOR]
    
    MsgBox Arr(3)
End Sub

Vì thế, JOIN là hàm xử lý ghép các phần tử trong mảng ra chuỗi (số cũng sẽ cho ra chuỗi, mà chuỗi đương nhiên là chuỗi), thì tại sao phải vấp lỗi khi gặp mảng dữ liệu kiểu số?
 
Lần chỉnh sửa cuối:
Upvote 0
VNI thì khỏi nói chắc lúc xưa Microsoft hỗ trợ bây giờ chưa có người VN làm trong đội ngũ của Office nên chưa hỗ trợ Unicode quá !!!!. Sao trên máy e thi ko có hiện tượng như anh nói khi chỉnh sang Script Vietnamese thì dữ liệu đầu vào phải là Unicode tổ hợp mới chấp còn unicode dựng sẵn là bị lỗi như hình anh Ndu đưa, cách Ndu thì mọi trường hợp điều không bị lỗi mà thấy hơi bất tiện sao sao đó vì khi viết code cũng khó khăn vì dân không chuyên mà. File này em test trên máy Win 8, office 2013 với kiểu gõ unicode tổ hợp thì không bị lỗi các Bạn, Anh ,Chị xem có bị lỗi không. Cảm ơn
À, mình làm kiểu "lụi" đó mà, sau khi lấy nguồn từ Unicode cho ComboBox, CBB này đã được cài sẳn Script Vietnamese, sau đó chọn một mục trong list, rồi click vào một cell nào đó. Trong quá trình này mình chạy sự kiện LostFocus để chuyển chuỗi của CBB từ chuỗi Uni sang chuỗi CP1258. Kiểu "lụi" này không thành công.

Còn file của nmhung49 là đã tạo cái source ngay từ đầu rồi.
 
Upvote 0
Em vẫn chưa tâm phục vì sự trả lời này, bởi vì:

Câu màu đỏ, được hiểu rằng:

1) Các chuổi (con) được chứa trong một mảng

hoặc:

2) Một mảng chứa các chuỗi (con)

Chứ không nói KIỂU DỮ LIỆU CỦA MỘT MẢNG!



Ô A1 có giá trị là Nghia_1

Công thức: =RIGHT(A1,1)

Kết quả = 1

Nhưng thực chất đây là một số trong dạng chuỗi (Number stored as text) >> không tính toán được với số này! Thế thôi!



Vì dạng Long không chấp nhận chuỗi nên phát sinh ra lỗi. OK

Nhưng với VD dưới đây, kiểu số nó ngán kiểu chuỗi chứ thằng kiểu chuỗi nó đâu có ngán kiểu số:

Mã:
Sub test3()

    Dim Arr(0 To 3) [COLOR=#ff0000][B]As String[/B][/COLOR]
    
    Arr(0) = "Hoang"
    Arr(1) = "Trong"
    Arr(2) = "Nghia"
[COLOR=#ff0000][B]    Arr(3) = 2151[/B][/COLOR]
    
    MsgBox Arr(3)
End Sub

Vì thế, JOIN là hàm xử lý ghép các phần tử trong mảng ra chuỗi (số cũng sẽ cho ra chuỗi, mà chuỗi đương nhiên là chuỗi), thì tại sao phải vấp lỗi khi gặp mảng dữ liệu kiểu số?

Tất cả những gì tôi định viết thì thì đã viết rồi. Tôi không có gì muốn thêm
 
Upvote 0
Hùa thêm với bác Siwtom một chút nữa, theo phần tài liệu hoá của Microsoft về hàm Join tại trang dưới đây, họ viết khá rõ về tham số đầu vào cho hàm Join.
[GPECODE=csharp]Function Join(
ByVal SourceArray() As { Object | String },
Optional ByVal Delimiter As String = " "
) As String[/GPECODE]
http://msdn.microsoft.com/en-us/library/b65z3h4h(v=vs.90).aspx

Ngoài ra, còn một điểm khác, khi không đặc tả kiểu số liệu của tham số thì hàm Join sẽ sử dụng tính năng chuyển đổi kiểu dữ liệu thụ động (implicit conversion) đưa số liệu về kiểu ký tự. Xem liên kết.
[http://msdn.microsoft.com/en-us/library/kca3w8x6.aspx]
Nếu đặc tả kiểu dữ liệu đầu vào thì nó sẽ sử dụng kiểu dữ liệu đó, không chuyển đổi kiểu số liệu nữa và xử lý, nếu xử lý không được thì nó sẽ báo lỗi về sai cấu trúc dữ liệu. Tất nhiên nếu khai báo kiểu số liệu là Variant thì implicit conversion sẽ được kích hoạt để đưa tham số đầu vào về khuôn khổ.

Xin được võ vẽ thêm đôi câu cùng Nghĩa!

Ví dụ mình sửa lại một tí đoạn test của Nghĩa để thí nghiệm vụ Implicit và Explicit...
[GPECODE=vb]Sub testJoin() 'Tat ca bien kieu Numeric deu bi loi:
Dim i As Long
Dim Arr1() As Date ' Integer, Byte, Double, Currency, Date v.v...
Dim Arr() As Variant
ReDim Arr1(9)
ReDim Arr(9)
For i = 0 To 9
Arr1(i) = i
Arr(i) = Arr1(i)
Next
Debug.Print Join(Arr, ",")
End Sub[/GPECODE]
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT

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

Back
Top Bottom