Các câu đố, bài tập nhằm ôn tập & bổ sung kiến thức căn bản VBA (1 người xem)

Liên hệ QC

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

Hoàng Trọng Nghĩa

Chuyên gia GPE
Thành viên BQT
Moderator
Tham gia
17/8/08
Bài viết
8,662
Được thích
16,725
Giới tính
Nam
Với tinh thần chơi mà học, học mà chơi, nên tôi đã mở ra topic này, hy vọng các thành viên tham gia, nhất là các thành viên mới biết về VBA.

Sau đây là câu hỏi đầu tiên:

Câu hỏi 1: Bằng phương pháp nào nhanh nhất để tìm ra ô nào trong một cột chứa một điều kiện.

Tôi có 1 file Excel 2007, với cột A, từ A1 đến A1048576 đều có giá trị.

Bằng phương pháp nào nhanh nhất (dùng mảng, dùng For Each v.v...) để tìm ra ô nào trong cột A chứa chữ "Nghia", đồng thời với ô ở cột B tương ứng nhập giá trị "OK" vào đó?

Ví dụ tìm thấy trong ô A2 có giá trị là "Nghia" thì ô B2 nhập vào "OK".

Hiện tại, đáp án nhanh nhất mà tôi có được đã gửi mail riêng (nhằm ghi lại thời gian gửi, để tránh nói ăn gian).

Để tiện việc theo dõi các câu đố, các bài tập tôi đã tạo ra topic này các bạn click vào đây:

Các link của topic "Các câu đố, bài tập nhằm ôn tập & bổ sung kiến thức căn bản VBA"
 

File đính kèm

Lần chỉnh sửa cuối:
Nhớ lại ngày xưa tôi học hơi khác: Tôi chẳng bao giờ đợi các thầy ra đề mà luôn tự mình nghĩ đề tài và tự giải
Nếu Thảo quan tâm cũng nên học theo cách này ---> Lấy công việc hằng ngày làm để tài chẳng han
Excel nó vô vàn và đề tài cũng không bao giờ thiếu
Lại nhớ những ngày chập chững bước vào "con đường đau khổ" tôi nhớ lại bài này:

http://www.giaiphapexcel.com/forum/...ức-cho-một-cột-được-không&p=101829#post101829

và được hướng dẫn bởi bài số 2 của Po_Pikachu, sau đó là bác ChanhTQ@.

Cái file mà tôi yêu cầu đó nó nằm trong bài giải của Po_Pikachu (bởi có một lúc quota gửi bài đã hết nên tôi xóa bớt những file cũ để tiếp tục có dung lượng gửi bài).

Các bạn có thấy tự học ngày đó khó khăn hơn bây giờ không? Không có sách lập trình, không được mở lớp học, không ai mở topic để hướng dẫn từ căn bản đến nâng cao như bây giờ, vướng chỗ nào thì hỏi chỗ đó (hỏi riết mà số lượng bài tăng lên đáng kể luôn, sao tăng vèo vèo luôn!).

Vậy tại sao bây giờ nhiều bạn không bắt tay ngay bây giờ để cùng "đau khổ" nhỉ!
 
Upvote 0
không dùng vòng lặp thì quang hai trả lời rồi. cách khác là dùng do loop thay vì for next vẫn được

Bạn hiền ơi, Do ... Loop và For ... Next đều là vòng lặp cả! Cho nên bạn hiền hỏi không dùng vòng lặp mà dùng Do Loop là chưa hỏi đúng đấy nhé!
 
Upvote 0
Nhân tiện đây xin đố luôn, không mới nhưng sẽ có người không biết (Chỉ dành cho người mới tập viết VBA):

Làm sao để ẩn Tên Macro ở cửa sổ Macro (Alt+F8), có bao nhiêu cách để ẩn?
Em biết thêm 1 cách nữa là để câu " Option Private Module " đầu code ( cái này e cũng mò trên GPE :) )
 
Upvote 0
Em biết thêm 1 cách nữa là để câu " Option Private Module " đầu code ( cái này e cũng mò trên GPE :) )
Đúng thế, ngày xưa cái tên Ếch Xanh hắn cũng đã từng hỏi ở topic này:

Làm sao để ẩn Macro Name?

và được một bạn trả lời như thế này:

Nếu không muốn cho người khác Run Macro nào thì Bạn thêm câu lệnh Option Private Module vào dòng đầu của Macro để ẩn nó đi (không cần phải ẩn cửa sổ Name macro).

Xin cảm ơn bạn domfootwear đã bảo cho tôi cách này !.

Đố chơi ngoài lề nha, domfootwear là ai vậy các bạn? hihihii
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
theo tôi được biết trong ngôn ngữ lập trình C++
biến là một vùng nhớtên dùng để lưu trữ các giá trị khi tính toán, các giá trị của biến có thể thay đổi trong suốt thời gian chương trình thực thi.
vùng nhớ này có độ lớn nhỏ tùy theo kiểu dữ liệu

Đối với C/C++ thì định nghĩa "biến" theo "vùng nhớ" còn hữu lý vì hai ngôn ngữ này sử dụng con trỏ để hoạt động rất hiệu quả.

Đối với các ngôn ngữ khác, khái niệm con trỏ được giấu hẳn đi. Cho nên nói chuyện "vùng nhớ" không hẳn đã thích hợp.
 
Upvote 0
Bài tập mã số D01: Hãy dịch sang ngôn ngữ tiếng Việt hàm người dùng sau:

PHP:
Option Explicit
Function KhTr(Chu As String) As Byte
 Dim Temp As String
 Temp = Replace(Trim(Chu), " ", "")
 KhTr = Len(Chu) - Len(Temp)
End Function

Theo mình, đã là ngôn ngữ, khi muốn học nó, ta fải "Đọc", "Nghe", "Nói" & có cả "Dịch"
Vậy các bạn gần xa thử xem sao!

Tất nhiên trong quá trình dịch thấy từ ngữ nào lạ thì fải tra từ điển thôi!
 
Lần chỉnh sửa cuối:
Upvote 0
Bài tập dịch D02: Các bạn dịch giúp tôi sang ngôn ngữ tiếng việt hàm người dùng sau:

PHP:
Function TachTen(HoTen As String) As String
 Dim ViTri As Long
 
HoTen = Trim(HoTen)
 If HoTen = "" Then
     TachTen = ""
 Else
     ViTri = InStrRev(HoTen, " ", Len(HoTen))
     If ViTri = 0 Then
          TachTen = HoTen
     Else
          TachTen = Mid(HoTen, ViTri + 1)
     End If
 End If
End Function

Tác giả hàm này là Thầy Phạm Duy Long (ĐT) quá cố! Xin kính cẩn tri ân thầy!

 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Em xin giơ tay lên bảng ạ.
Em hiểu và dịch tạm như vầy không biết có chính xác không mong các Thầy các anh chị lược bớt hoặc bổ xung thêm:

Mã:
Option Explicit
[COLOR=#ff0000]' Yeu cau khai bao day du cac bien su dung[/COLOR]
Function KhTr(Chu As String) As Byte
[COLOR=#ff0000]'Ham KhTr - tham so dau vao la chuoi va dau ra la so nguyen duong nho hon 256[/COLOR]
 Dim Temp As String
[COLOR=#ff0000] ' Khai bao bien Temp dung kieu chuoi[/COLOR]
 Temp = Replace(Trim(Chu), " ", "")
 [COLOR=#ff0000]' Bo het khoang trang trong chuoi Chu va thay the dau cach Chw(32) = "" ky tu rong[/COLOR]
 KhTr = Len(Chu) - Len(Temp)
[COLOR=#ff0000] ' KhTr = So ky tu trong Chu - so ky tu trong Temp[/COLOR]
End Function 
[COLOR=#ff0000]' Ket thuc[/COLOR]

Mã:
Function TachTen(HoTen As String) As String
[COLOR=#ff0000]'Ham TachTen bien dau vao kieu chuoi va ra kieu chuoi[/COLOR]
 Dim ViTri As Long
 [COLOR=#ff0000]'Khai bao bien ViTri dung kieu so nguyen[/COLOR]
HoTen = Trim(HoTen)
[COLOR=#ff0000]'Cat bo ky tu trang trong bien dau vao HoTen[/COLOR]
 If HoTen = "" Then
     TachTen = ""
[COLOR=#ff0000] 'Neu bien ho ten = "" thi ham TachTen = ""[/COLOR]
 Else [COLOR=#ff0000]'nguoc lai[/COLOR]
     ViTri = InStrRev(HoTen, " ", Len(HoTen))
     [COLOR=#ff0000]'Tim vi tri khoang trang trong chuoi HoTen theo chieu tu phai sang trai[/COLOR]
     If ViTri = 0 Then
          TachTen = HoTen
     [COLOR=#ff0000]'Neu Vitri = 0 thi Ham TachTen = HoTen[/COLOR]
     Else [COLOR=#ff0000]' nguoc lai[/COLOR]
          TachTen = Mid(HoTen, ViTri + 1)
          [COLOR=#ff0000]'Ham TachTen = Lay ky tu trong HoTen bat dau tu ViTri + 1 den het chuoi HoTen[/COLOR]
     End If [COLOR=#ff0000]' Ket thuc dieu kien = o va nguoc lai[/COLOR]
 End If [COLOR=#ff0000]' Ket thuc dieu kien HoTen = "" va nguoc lai[/COLOR]
End Function 
[COLOR=#ff0000]' Ket thuc[/COLOR]

Em cũng có 1 thắc mắc nhỏ mong mọi người chỉ giúp: Dòng này:
Mã:
TachTen = Mid(HoTen, ViTri + 1)

Hàm Mid được viết kiểu này mà VBA cũng hiểu và lấy đúng đối số thứ 3 (den het chuoi HoTen). Theo em thì đầy đủ ra thì phải viết như này chứ:
Mã:
TachTen = Mid(HoTen, ViTri + 1, Len(HoTen) - ViTri + 1)

Thế mà VBA vẫn hiểu._)()(-
 
Upvote 0
PHP:
Option Explicit
Function KhTr(Chu As String) As Byte
 Dim Temp As String
 Temp = Replace(Trim(Chu), " ", "")
 KhTr = Len(Chu) - Len(Temp)
End Function

e xin thử :
Function KhTr(Chu As String) As Byte ' khai báo hàm KhTr có biến là chu ( dạng chuỗi ), hàm này trả về kết quả là byte

Dim Temp As String ' khai báo biến Temp là dạng chuỗi

Temp = Replace(Trim(Chu), " ", "") ' biến temp = thay thế biến "chu" những khoãng trắng bên trong thành không có ( với điều kiện là đã bỏ những khoảng trắng thừa ở 2 đầu chuỗi - hàm trim )

KhTr = Len(Chu) - Len(Temp) ' trả về số khoảng trắng bên trong biến "chu" ( lấy chiều dài ban đầu của biến "chu" trừ cho chiều dài lúc sau của nó sau khi bỏ hết các khoảng trắng )

End Function ' kết thúc hàm
 
Upvote 0
PHP:
Option Explicit
Function KhTr(Chu As String) As Byte
 Dim Temp As String
 Temp = Replace(Trim(Chu), " ", "")
 KhTr = Len(Chu) - Len(Temp)
End Function

Theo mình, đã là ngôn ngữ, khi muốn học nó, ta fải "Đọc", "Nghe", "Nói" & có cả "Dịch"
Vậy các bạn gần xa thử xem sao!

Tất nhiên trong quá trình dịch thấy từ ngữ nào lạ thì fải tra từ điển thôi!
Hổng hiểu hàm này dùng để làm gì nhỉ?
Đếm số từ cũng không đúng! chẳng lẽ để đếm... khoảng trắng
??!!??
Mà đếm khoảng trắng để làm cái gì?
 
Upvote 0
Hổng hiểu hàm này dùng để làm gì nhỉ?
Đếm số từ cũng không đúng! chẳng lẽ để đếm... khoảng trắng
??!!??
Mà đếm khoảng trắng để làm cái gì?
- Em thấy bác Sa đã nói từ đầu là rèn luyện cách đọc Code, hiểu Code, diễn giải Code nên cái này cũng rất cần thiết cho thành viên mới.

- Qua bài trên thành viên mới sẽ hiểu được một số vấn đề sau:

+/ Cách khai báo biến (String, Byte)
+/ Cách sử dụng hàm: Len, Trim, Replace
+/ Cách xây dựng một Function đơn giản

=> Em đã theo dõi nhiều bài hướng dẫn của bác Sa và học được rất nhiều điều vì nó rất cơ bản và nếu theo dõi dài liên kết lại thì đó tươn đương với cuốn giáo trình rất hay.
 
Upvote 0
- Em thấy bác Sa đã nói từ đầu là rèn luyện cách đọc Code, hiểu Code, diễn giải Code nên cái này cũng rất cần thiết cho thành viên mới.

.

Mình thì không đồng ý! Dù là ví dụ thì cũng phải có ý nghĩa ứng dụng thực tế
(và thực tế chẳng khi nào mình viết 1 code chỉ để nhìn chơi mà không ứng dụng gì)
Nên nhớ rằng: Người ta muốn học VBA nhanh là phải thông qua ứng dụng. Càng thấy hiệu quả do VBA mang lại thì người ta mới càng hứng thú
 
Upvote 0
Upvote 0
Dù sao nó cũng là 1 học liệu đó chứ, chú mầy!

[thongbao]Mình thì không đồng ý! Dù là ví dụ thì cũng phải có ý nghĩa ứng dụng thực tế
(và thực tế chẳng khi nào mình viết 1 code chỉ để nhìn chơi mà không ứng dụng gì)
[/thongbao]

Có thể nó là 1 học liệu tồi nhất & đán thương tệ trong topic này!
 
Upvote 0
Đếm khoảng trắng suy ra được số từ, ẹc ẹc

Cái đó chưa chắc đâu sư phụ à! Số lượng khoảng trắng không bao giờ tương quan với số từ, nhất là khi trong chuổi có khoảng trắng thừa
Ấy là em đang phân tích theo giải thuật trong code của sư phụ ChanhTQ. Đương nhiên, nếu em muốn đếm số từ thì cũng dựa vào khoảng trắng để đếm nhưng phải thêm công đoạn TRIM nữa thì mới chắc ăn
Em không hề phê phán code mà chỉ mới nêu bật tính ứng dụng, nhất là khi ta đang truyền đạt cho người chưa biết...
Em nói theo quan điểm của em: Nếu em không cảm thấy code ấy dùng để làm gì thì làm sao em có hứng để học?
 
Upvote 0
Cái đó chưa chắc đâu sư phụ à! Số lượng khoảng trắng không bao giờ tương quan với số từ, nhất là khi trong chuổi có khoảng trắng thừa
Ấy là em đang phân tích theo giải thuật trong code của sư phụ ChanhTQ. Đương nhiên, nếu em muốn đếm số từ thì cũng dựa vào khoảng trắng để đếm nhưng phải thêm công đoạn TRIM nữa thì mới chắc ăn
Em không hề phê phán code mà chỉ mới nêu bật tính ứng dụng, nhất là khi ta đang truyền đạt cho người chưa biết...
Em nói theo quan điểm của em: Nếu em không cảm thấy code ấy dùng để làm gì thì làm sao em có hứng để học?

Chỉ cần thay trim của VBA bằng trim của excel là được rồi mà. Vả lại ndu nhớ lại câu đầu tiên trong For Next là tính giai thừa không? Và tiếp theo là 3, 4 bài tập "vớ vẩn"?

Bài tập của Bác ChanhTQ cũng là 1 cách để giới thiệu việc xử lý chuỗi vậy? Có điều, tiếp theo bài này, nên có 1 bài gợi ý ứng dụng InStr, Mid, StrRev, ... vào 1 bài toán thường gặp nào đó.

Chẳng hạn như bài tập gán bảng màu chẵn xuống sheet, tiếp theo là 1 bài tập ứng dụng ghi dữ liệu, phát triển từ "kinh nghiệm" gán màu.
 
Upvote 0
Chỉ cần thay trim của VBA bằng trim của excel là được rồi mà. Vả lại ndu nhớ lại câu đầu tiên trong For Next là tính giai thừa không? Và tiếp theo là 3, 4 bài tập "vớ vẩn"?

.

Mấy cái đó em thấy chẳng vớ vẫn tí nào cả sư phụ à. Ít nhất nó ứng dụng được trên VB6 hoặc Word chẳng hạn (vì ứng dụng khác không có hàm hổ trợ sẵn)
-------------
Bài của sư phụ ChanhTQ theo em nên có những câu hỏi mở, chẳng hạn:
- Code này dùng để làm gì?
- Code này cần cải tiến những gì?
- Ứng dụng mở rộng của code?
vân vân.. và.. vân vân... nó mới hứng
Làm được sẽ nói lên tất cả mà không cần phải giải thích code (nói thật, có nhiều khi em còn chưa biết giải thích code của chính em, dù em hiểu rõ nó)
Là 1 lập trình viên, người ta cũng chẳng cần phải giải thích toàn bộ code, chỉ cần xem qua 1 đoạn code và biết đâu mới là trọng tâm (mấu chốt vấn đề có khi chỉ nằm đúng 1 dòng code trong cả "đám rừng")
 
Lần chỉnh sửa cuối:
Upvote 0
[thongbao]Nhân tiện đây xin đố luôn, không mới nhưng sẽ có người không biết (Chỉ dành cho người mới tập viết VBA):

Làm sao để ẩn Tên Macro ở cửa sổ Macro (Alt+F8), có bao nhiêu cách để ẩn?
[/thongbao]

Cách 1 của leonguyenz: OK
Thay Sub thành Private Sub.
Còn cách khác thì em chưa biết, chờ các bạn khác giải đáp.
Cách 2 của quocphuoc88: OK
Em biết thêm 1 cách nữa là để câu " Option Private Module " đầu code ( cái này e cũng mò trên GPE :) )
Còn ít nhất 1 cách nữa, mong các bạn tiếp tục.
 
Lần chỉnh sửa cuối:
Upvote 0
[thongbao]Nhân tiện đây xin đố luôn, không mới nhưng sẽ có người không biết (Chỉ dành cho người mới tập viết VBA):

Làm sao để ẩn Tên Macro ở cửa sổ Macro (Alt+F8), có bao nhiêu cách để ẩn?
[/thongbao]

Cách 1 của leonguyenz: OK

Cách 2 của quocphuoc88: OK

Còn ít nhất 1 cách nữa, mong các bạn tiếp tục.

Đối với những người mới học, chỉ có cách thứ nhất là nên dùng.

Cách thứ 2 tương đối hơi khó hiểu. Đòi hỏi kiến thức về phạm vi code. Chỉ những người làm việc với nhiều projects (trong một lúc) mới nên dùng tới.

Cách thứ 3 (không biết có phải là cách người ra bài muốn nói?) tương đối lại càng cao cấp hơn. Người dùng phải hiểu cách hoạt động của hàm.
 
Upvote 0
Đúng là cách 3 là như bạn nói.

Tóm lại cách thứ 3 là gán cho thủ tục 1 tham số bất kỳ nhưng không dùng tới. Optional cũng được, nhưng cũng có thể không cần.

Lý do là tất cả thủ tục có tham số truyền không thể chạy bằng F5 hoặc chạy trực tiếp, và cũng không thể thấy bằng Alt - F8
 
Upvote 0
Muốn chạy được bằng F5 thì hàm không được có tham số. Ta có thể thay tên sub thành function vì function không được coi như macro cho nên nó sẽ không có mặt trong list của macro.

Lưu ý là function thì phải trả về một trị. Cho nên cuối function phải có dòng = 0 (hay cái gì cũng được). Và nếu module dùng "Option Explicit" thì phải định dạng trả về của function.

-- Đương nhiên function cũng có cái bất lợi khác của nó. Bởi vậy tôi mới nói cách này hơi cao cấp.
 
Upvote 0
Muốn chạy được bằng F5 thì hàm không được có tham số. Ta có thể thay tên sub thành function vì function không được coi như macro cho nên nó sẽ không có mặt trong list của macro.

Lưu ý là function thì phải trả về một trị. Cho nên cuối function phải có dòng = 0 (hay cái gì cũng được). Và nếu module dùng "Option Explicit" thì phải định dạng trả về của function.

-- Đương nhiên function cũng có cái bất lợi khác của nó. Bởi vậy tôi mới nói cách này hơi cao cấp.
Tất nhiên là funtion thì OK rồi nhưng mọi người đang bám sát câu hỏi của Hai Lúa Miền Tây mà bạn VetMini

[thongbao]Làm sao để ẩn Tên Macro ở cửa sổ Macro (Alt+F8), có bao nhiêu cách để ẩn?
[/thongbao]
 
Lần chỉnh sửa cuối:
Upvote 0
Cho em hỏi, học VBA và macro ở trung tâm nào tại TP.HCM vậy?
Có ai biết, thông tin giúp em với
 
Upvote 0
Upvote 0
Cách "củ chuối" này có được tính không nhỉ? Hic, hic, hic (gọi là để trả lời chứ ai lại áp dụng thế này :))

Code trong UserForm1:
[GPECODE=vb]Sub MyMacro() 'Macro trong Userform thì ẩn quá rùi nhỉ?
MsgBox "MyMacro is running !"
End Sub[/GPECODE]
Code trong Module: (Để kiểm chứng Sub trong UserForm1 vẫn chạy được)
[GPECODE=vb]Sub Test()
Call UserForm1.MyMacro
End Sub[/GPECODE]
 
Lần chỉnh sửa cuối:
Upvote 0
Cách "củ chuối" này có được tính không nhỉ? Hic, hic, hic (gọi là để trả lời chứ ai lại áp dụng thế này :))

Code trong UserForm1:
[GPECODE=vb]Sub MyMacro() 'Macro trong Userform thì ẩn quá rùi nhỉ?
MsgBox "MyMacro is running !"
End Sub[/GPECODE]
Code trong Module:
[GPECODE=vb]Sub Test()
Call UserForm1.MyMacro
End Sub[/GPECODE]
Nếu thế này thì cái thằng Test trong module vẫn thấy được !
 
Upvote 0
Nếu thế này thì cái thằng Test trong module vẫn thấy được !
Ui trời, "hắn" này máy móc quá. Đã nói là VD "củ chuối" cho cái MyMacro. Sub Test (lẽ ra tui ko cho vào) là để kiểm chứng sub trong UserForm vẫn chạy được thui chứ tui cho vào Private Sub Button1_Click() thì mò ở đâu? Nói chung là ko nên đưa ra những ý kiến để ý tí một như vậy. (đã sửa thêm chú thích bài #331)

Tks/Brgds
 
Lần chỉnh sửa cuối:
Upvote 0
Ui trời, "hắn" này máy móc quá. Đã nói là VD "củ chuối" cho cái MyMacro. Sub Test (lẽ ra tui ko cho vào) là để kiểm chứng sub trong UserForm vẫn chạy được thui chứ tui cho vào Private Sub Button1_Click() thì mò ở đâu? Nói chung là ko nên đưa ra những ý kiến để ý tí một như vậy.

Tks/Brgds
Dạ, e xin lỗi không đọc kỹ. Tại e nhìn vào code thì thấy vẫn còn thấy nó nên nói vậy !
 
Upvote 0
Đề tài này bị chìm lâu quá, mình xin đẩy nó lên:

Excel sheet có:

1./ Hàm đổi CHỮ HOA thành chữ thường (LOWER) --> VBA có hàm Lcase.
2./ Hàm đổi chữ thường thành CHỮ HOA (UPPER) --> VBA có hàm UCase.

Vậy xin hỏi các bạn là làm thế nào không dùng những hàm trên để đổi CHỮ HOA thành chữ thường và ngược lại?
 
Upvote 0
Đề tài này bị chìm lâu quá, mình xin đẩy nó lên:

Excel sheet có:

1./ Hàm đổi CHỮ HOA thành chữ thường (LOWER) --> VBA có hàm Lcase.
2./ Hàm đổi chữ thường thành CHỮ HOA (UPPER) --> VBA có hàm UCase.

Vậy xin hỏi các bạn là làm thế nào không dùng những hàm trên để đổi CHỮ HOA thành chữ thường và ngược lại?
Có thể sử dụng hàm StrConv (em hiểu là String convert) :
Mã:
StrConv(string, conversion, LCID)
Với conversion:
- 1: Upper
- 2: Lower
- 3: Proper
...
Còn LCID thì em chưa biết, nhờ các Thầy diễn giải dùm!
 
Upvote 0
Có thể sử dụng hàm StrConv (em hiểu là String convert) :
Mã:
StrConv(string, conversion, LCID)
Với conversion:
- 1: Upper
- 2: Lower
- 3: Proper
...
Còn LCID thì em chưa biết, nhờ các Thầy diễn giải dùm!

LCID là Locale ID tức Locale identifier. Tôi không thạo tiếng Anh nên cứ hiểu nôm na là Mã Vùng, Số nhận dạng của vùng.

Có nhiều lúc cần phải nhập LCID. Vd. như hàm API GetLocaleInfo dùng để đọc ra những thông tin như: dạng ngày tháng dài/ngắn, ký tự thập phân, ký tự tiền tệ, ...
Nhưng đọc các thông tin cho quốc gia nào??? vd. đọc cho Việt Nam thì ký tự tiền tệ là ₫. Nhưng đọc cho Nga thì lại là ký tự khác. Vậy thì phải truyền vào GetLocaleInfo cái gọi là LCID. Việt Nam thì là &H042A

Có 2 loại LCID: user default locale identifier - có thể đọc ra bằng hàm API GetUserDefaultLCID, và system default locale identifier - có thể đọc ra bằng hàm API GetSystemDefaultLCID

Nếu tôi không lầm thì thế này:
1. Khi ta cài Windows thì có bước ta phải chọn vùng. Chọn gì thì có nghĩa là ta đã xác định system default locale identifier, và đồng thời user default locale identifier
2. Trong quá trình dùng Windows ta có thể nhiều lần đổi vùng trong Control Panel. Mỗi lần đổi như thế là ta đã đổi user default locale identifier

Ví dụ tôi cài Windows và chọn vùng là Ba Lan. Sau khi cài xong tôi có system default locale identifier = user default locale identifier = 1045 = &H415. Sau đó tôi chon trong CP vùng là Việt Nam. Lúc này
system default locale identifier = 1045, user default locale identifier = 1066 = &H42A

Đấy là LCID trong Windows. Cái LCID trong StrConv tôi nghĩ nó cũng chính là cái này. Thiết nghĩ nó chẳng qua là để convert cho chuẩn mà thôi. Nếu không nhập thì nó là system default locale identifier
 
Upvote 0
Cũng câu hỏi:

Excel sheet có:

1./ Hàm đổi CHỮ HOA thành chữ thường (LOWER) --> VBA có hàm Lcase.
2./ Hàm đổi chữ thường thành CHỮ HOA (UPPER) --> VBA có hàm UCase.

Vậy xin hỏi các bạn là làm thế nào không dùng những hàm trên để đổi CHỮ HOA thành chữ thường và ngược lại?

Ngoài cách dùng cách ở bài #336 thì còn cách nào khác không.
 
Upvote 0
Upvote 0
Rỗi không các bạn, ngày nghỉ mà:

TÌM CÁCH VIẾT HOA DÒNG TIÊU ĐỀ BÁO CÁO.

Chúng ta có 1 cơ sở dữ liệu (CSDL) cấp fát bảo hộ lao động (BHLĐ) của 1 tỉnh như lượt trích dưới đây:

B | C | D | E | F | G | | L | M | N | O | P | Q Ngày | MaBH | Ten BH | MaNV | TenNV | MaDVi |…| Ma | Ten BHLĐ | ĐVT | Niên hạn ||
1/18/09|wLF|Áo quần lễ fục|NTK00|Ng. T.T. Kha|AL|…|GDa|Giầy |đôi|2||
2/2/09|zLF|Mũ lễ fục|NTK00|Ng. T.T. Kha|AL|…|MuK|Mũ kê pi |cái|2||
2/23/09|wLF|Áo quần lễ fục|NKT00|Ng. K.Tuyến|PC|…|BTD|QA thu đông |bộ|2||
3/3/09|zLF|Mũ lễ fục|NKT00|Ng. K.Tuyến|PC|…|MuM|Mũ mềm |cái|2||
.|.|.|.|.|.|…|.|.|.|.|.|.
5/10/12|BTD|QA thu đông|NKD00|Ng. K.Diễm|TS|…| MaNV | HoTen | MĐV || MaH | Huyện
6/14/12|TLD|Thắc lưng|NKD00|Ng. K. Diễm|TS|…|NKT01|Ng. K Tuyến |PC||PC|Phù Cát
.|.|.|.|.|.|…|.|.|.|.|.|.

CSDL này liệt kê ngày cấp gần chục loại trang bị BHLĐ hàng năm cho 200 nhân viên kiểm lâm.
Để theo dõi việc cấp fát BHLĐ đến từng cá nhân, ta cần lập “SỔ CẤP PHÁT BHLĐ” cho từng cá nhân trong tỉnh.
Sổ đó có dạng trình bày như sau:

3. . . . . . . . SỔ LĨNH BHLĐ CỦA Trần Bảo Trân.
4. . . . . . . . Đơn vị: Hoài An.

6 |TT|Ngày|MaBH|Tên BHLĐ|Ghi chú
7 |1|4/8/09|wLF|Áo quần lễ f ục|
8 |2|4/9/09|zLF|Mũ Kê pi lễ fục|
9 |3|3/4/13|MuK|Mũ Kê pi|
10 |4|3/4/13|Gda|Giầy da|
..|…|….|….|
15 |9|3/21/13|ADM|Áo mưa|

Để trích lọc & tạo sổ theo dõi thực lãnh BHLĐ từ trang “DuLieu” sang trang “SoBHLD” cho từng cán bộ nhân viên coi như đã làm xong;


Đề bài tập sẽ là:

Tại dòng 3 ta thấy chưa thỏa đán cho lắm;
Các bạn làm sao để dòng này có dạng:

3. . . . . . . . SỔ LĨNH BHLĐ CỦA TRẦN BẢO TRÂN.
(Xin các bạn xem thêm trong file)
 

File đính kèm

Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Đố các bạn kết quả MsgBox sẽ trả về là bao nhiêu?

Các bạn tự đoán trước kết quả và chạy code sau nhé!

Mã:
Sub Test()
    Dim a As Long, b As Long
    a = 1.5
    b = 1.5
[COLOR=#ff0000][B]    MsgBox a + b[/B][/COLOR]
End Sub

Các bạn rút ra điều gì khi sử dụng biến Long?
 
Upvote 0
Đố các bạn kết quả MsgBox sẽ trả về là bao nhiêu?

Các bạn tự đoán trước kết quả và chạy code sau nhé!

Mã:
Sub Test()
    Dim a As Long, b As Long
    a = 1.5
    b = 1.5
[COLOR=#ff0000][B]    MsgBox a + b[/B][/COLOR]
End Sub

Các bạn rút ra điều gì khi sử dụng biến Long?
Khi anh làm quen với việc tạo CSDL thì anh sẽ biết cái này, kiểu biến cũng gần giống như kiểu dữ liệu ở các trường trong CSDL. Tùy vào ý đồ cũng như việc tính toán, lưu trữ mà ta chọn kiểu dữ liệu khác nhau.

VD: Theo bài của anh ở trên là số thập phân thì phải chọn kiểu dữ liệu dạng double hoặc single. Nếu như chọn kiểu Long nó sẽ mặc định làm tròn số nếu số thập phân >=5 thì sẽ làm tròn lên, ngược lại sẽ làm tròn xuống (Giống như hàm Round(So,0) ở Excel). Áp dụng vào bài anh thì a=1.5=>2, b=1.5=>2 Như vậy a+b sẽ cho ra là 4 là điều dể hiểu.
 
Upvote 0
Khi anh làm quen với việc tạo CSDL thì anh sẽ biết cái này, kiểu biến cũng gần giống như kiểu dữ liệu ở các trường trong CSDL. Tùy vào ý đồ cũng như việc tính toán, lưu trữ mà ta chọn kiểu dữ liệu khác nhau.

VD: Theo bài của anh ở trên là số thập phân thì phải chọn kiểu dữ liệu dạng double hoặc single. Nếu như chọn kiểu Long nó sẽ mặc định làm tròn số nếu số thập phân >=5 thì sẽ làm tròn lên, ngược lại sẽ làm tròn xuống (Giống như hàm Round(So,0) ở Excel). Áp dụng vào bài anh thì a=1.5=>2, b=1.5=>2 Như vậy a+b sẽ cho ra là 4 là điều dể hiểu.

Bài học rút ra ở đây:

1) Đừng nghĩ biến Long là một số nguyên mà đánh đồng nó với giá trị có hàm INT. Vì thế nếu muốn nó là số nguyên không làm tròn thì thêm hàm INT vào giá trị trước khi biến đó được định giá trị.

2) Khi tính toán, nếu giá trị có số thập phân thì nên chọn biến có kiểu dữ liệu là Double hoặc Single, hoặc Currency

Và nếu lựa chọn giữa 3 biến Double/ Single/ Currency, ta lại làm tiếp bài test sau:

Mã:
Sub Test()
    Dim c As Currency
    Dim d As Double
    Dim s As Single
    
    c = 1 / 3
    d = 1 / 3
    s = 1 / 3
    
    MsgBox "d = c: " & (d = c) & _
    vbLf & vbLf & "d: " & d & _
    vbLf & vbLf & "c: " & c
    
    MsgBox "c = s: " & (c = s) & _
    vbLf & vbLf & "c: " & c & _
    vbLf & vbLf & "s: " & s


    MsgBox "d = s: " & (d = s) & _
    vbLf & vbLf & "d: " & d & _
    vbLf & vbLf & "s: " & s
End Sub

Kết quả d = c = s, nhưng hiển thị lại khác nhau. Các bạn rút ra được điều gì?
 
Lần chỉnh sửa cuối:
Upvote 0
Trong hầu hết các ngôn ngữ lập trình đều có một luật gọi là luật ép kiểu. Luật này được trình dịch (compiler) áp dụng triệt để khi có sự không thống nhất giũa các dữ liệu.

a là kiểu dữ liệu được khai báo là Long. Compiler luôn luôn biết nó là Long
1.5 là kiểu dữ liệu được mặc định là Float hoặc Double, tuỳ theo mặc định môi trường.

Vì đây là hai kiểu khác nhau nên khi sử dụng toán tử gán (=), compiler bắt buộc phải lôi luật ép kiểu ra.
Theo quy định của VBA, lúc ép kiểu sang Integer hay Long, Float và Double sẽ bị làm tròn.

(*) Ghi chú: mỗi ngôn ngữ có một cách ép kiểu khác nhau, lúc ép kiểu cần phải cẩn thận. Tuy VBA làm tròn, nhưng ngôn ngữ khác (T-SQL chẳng hạn) có thể sẽ chặt bỏ phần thập phân (.9999999 cũng bị chặt bỏ như thường)

(**) Ghi chú 2: có ngôn ngữ không ép kiểu của biểu thức mà ngược lại, tự động đổi kiểu dữ liệu của biến.
 
Upvote 0
Luật sử dụng biến Float/Double:

Người lập trình chân chính không bao giờ so sánh trực tiếp 2 biến float với nhau qua toán tử "=".

Để so sánh, người ta xét xem chúng có gần bằng nhau hay không. Theo luật lập trình, nếu 2 số cách nhau ít hơn một khoảng ép si lon rất nhỏ nào đó thì coi như bằng nhau.

if (abs(float1 - float2) < 1E-10) then { 2 số coi như bằng nhau }
 
Upvote 0
Trong hầu hết các ngôn ngữ lập trình đều có một luật gọi là luật ép kiểu. Luật này được trình dịch (compiler) áp dụng triệt để khi có sự không thống nhất giũa các dữ liệu.

a là kiểu dữ liệu được khai báo là Long. Compiler luôn luôn biết nó là Long
1.5 là kiểu dữ liệu được mặc định là Float hoặc Double, tuỳ theo mặc định môi trường.

Vì đây là hai kiểu khác nhau nên khi sử dụng toán tử gán (=), compiler bắt buộc phải lôi luật ép kiểu ra.
Theo quy định của VBA, lúc ép kiểu sang Integer hay Long, Float và Double sẽ bị làm tròn.

(*) Ghi chú: mỗi ngôn ngữ có một cách ép kiểu khác nhau, lúc ép kiểu cần phải cẩn thận. Tuy VBA làm tròn, nhưng ngôn ngữ khác (T-SQL chẳng hạn) có thể sẽ chặt bỏ phần thập phân (.9999999 cũng bị chặt bỏ như thường)

(**) Ghi chú 2: có ngôn ngữ không ép kiểu của biểu thức mà ngược lại, tự động đổi kiểu dữ liệu của biến.

Cám ơn bạn đã bổ sung kiến thức từ VBA sang các ngôn ngữ khác. Tuy nhiên chúng ta đang bàn về VBA và bài tôi gửi lên không phải đánh đố, mà nhằm cho các bạn mới học hoặc đã biết VBA từ lâu nhưng chưa chú ý đến vấn đề này.
 
Upvote 0
Cám ơn bạn đã bổ sung kiến thức từ VBA sang các ngôn ngữ khác. Tuy nhiên chúng ta đang bàn về VBA và bài tôi gửi lên không phải đánh đố, mà nhằm cho các bạn mới học hoặc đã biết VBA từ lâu nhưng chưa chú ý đến vấn đề này.

Tôi không có ý lôi kéo đề tài sang chỗ khác. Vì có bạn nói tới CSDL cho nên tôi nhắc nhở rằng không phải ở đâu cũng có phép ép kiểu giống nhau.

Riêng trong VBA thì ví dụ của bạn chưa hoàn hảo. Bạn cần đưa thêm ra chi tiết để thấy VBA dùng phép Round của nó khi ép kiểu. Nói cách khác, nếu bạn gán
a = 1.5 hay a = 2.5 thì dều thấy cuối cùng a = 2.
 
Upvote 0
Tôi không có ý lôi kéo đề tài sang chỗ khác. Vì có bạn nói tới CSDL cho nên tôi nhắc nhở rằng không phải ở đâu cũng có phép ép kiểu giống nhau.

Riêng trong VBA thì ví dụ của bạn chưa hoàn hảo. Bạn cần đưa thêm ra chi tiết để thấy VBA dùng phép Round của nó khi ép kiểu. Nói cách khác, nếu bạn gán
a = 1.5 hay a = 2.5 thì dều thấy cuối cùng a = 2.
Như vậy vẫn chưa hoàn hảo hihihihi, thử test thủ tục dưới đây:

Mã:
Sub Test()
    Dim a As Long, b As Byte
    For b = 1 To 10
        a = b + 0.5
        MsgBox "b" & b & ": " & a
    Next
End Sub

Ta lại thấy điều gì nhỉ? Với biến b, Số lẻ thì sao và số chẳn thì sao?
 
Lần chỉnh sửa cuối:
Upvote 0
Trong hầu hết các ngôn ngữ lập trình đều có một luật gọi là luật ép kiểu. Luật này được trình dịch (compiler) áp dụng triệt để khi có sự không thống nhất giũa các dữ liệu.

a là kiểu dữ liệu được khai báo là Long. Compiler luôn luôn biết nó là Long
1.5 là kiểu dữ liệu được mặc định là Float hoặc Double, tuỳ theo mặc định môi trường.

Vì đây là hai kiểu khác nhau nên khi sử dụng toán tử gán (=), compiler bắt buộc phải lôi luật ép kiểu ra.
Theo quy định của VBA, lúc ép kiểu sang Integer hay Long, Float và Double sẽ bị làm tròn.

(*) Ghi chú: mỗi ngôn ngữ có một cách ép kiểu khác nhau, lúc ép kiểu cần phải cẩn thận. Tuy VBA làm tròn, nhưng ngôn ngữ khác (T-SQL chẳng hạn) có thể sẽ chặt bỏ phần thập phân (.9999999 cũng bị chặt bỏ như thường)

(**) Ghi chú 2: có ngôn ngữ không ép kiểu của biểu thức mà ngược lại, tự động đổi kiểu dữ liệu của biến.

Thông tin đỏ đỏ theo tôi không có giá trị. Không phải là sai. Vì trong mỗi ngôn ngữ có thể sẽ khác nên luôn luôn phải kiểm tra xem trong ngôn ngữ mà mình đang dùng nó thế nào.
Delphi rất khắc nghiệt trong chuyện dùng kiểu. Nếu a được khai báo là BYTE, Integer, hay DWORD thì không thể viết:
Mã:
a := 4 / 2
được vì compiler sẽ thông báo lỗi. Vì đối với Delphi thì 4 / 2 không là 2 mà là 2.0, tức giá trị Extended. Chỉ viết được như trên khi a được khai báo là Single, Double hoặc Extended.
Phép gán là được phép khi 2 kiểu dữ liệu là "phù hợp". Ví dụ Integer, Byte, Dword là phù hợp với nhau (cùng là những giá trị "nguyên") hoặc Single, Double, Extended.
Hoặc chẳng hạn PBYTE, PInteger, PDWORD là những pointer, tức giá trị "nguyên", nên nếu a là giá trị Byte, Integer, Dword còn b được khai báo là PDWORD (kiểu pointer) thì có thể viết

Mã:
b := [COLOR=#ff0000]PDWORD[/COLOR](a); (type casting)


Nhưng không thể viết
Mã:
b := a;

Mà người lập trình phải "ép" (PDWORD(...)), Delphi không "ép" gì cả

Tất nhiên nếu a là Integer và b là Double thì không được phép a := b; nhưng lại được phép b := a; Cái này nó cũng kiểu như: "Số tự nhiên luôn là số thực, nhưng số thực chưa chắc là số tự nhiên".

Trong Delphi nếu 2 kiểu dữ liệu không "phù hợp" với nhau thì compiler "không cho qua", compiler không lôi "luật ép kiểu" ra, cũng không "tự động đổi kiểu dữ liệu của biến"

Vậy thì đã chuyển sang ngôn ngữ khác thì phải tìm hiểu.
 
Lần chỉnh sửa cuối:
Upvote 0
Trong hầu hết các ngôn ngữ lập trình đều có một luật gọi là luật ép kiểu. Luật này được trình dịch (compiler) áp dụng triệt để khi có sự không thống nhất giũa các dữ liệu.

...

Tôi đã cẩn thận dùng từ "hầu hết" để phân biệt với "tất cả". FORTRAN cũng đâu có ép kiểu.

Trình dịch không tự động ép kiểu thì nó từ chối ngay từ đầu, không phải quan tâm lắm.
Gặp những lúc trình dịch ép kiểu mới quan trọng. Nếu không quen cách thức ép kiểu thì có thể nhận kết quả sai mà không biết.
 
Upvote 0
Với tinh thần chơi mà học, học mà chơi, nên tôi đã mở ra topic này, hy vọng các thành viên tham gia, nhất là các thành viên mới biết về VBA.

Sau đây là câu hỏi đầu tiên:

Câu hỏi 1: Bằng phương pháp nào nhanh nhất để tìm ra ô nào trong một cột chứa một điều kiện.

Tôi có 1 file Excel 2007, với cột A, từ A1 đến A1048576 đều có giá trị.

Bằng phương pháp nào nhanh nhất (dùng mảng, dùng For Each v.v...) để tìm ra ô nào trong cột A chứa chữ "Nghia", đồng thời với ô ở cột B tương ứng nhập giá trị "OK" vào đó?

Ví dụ tìm thấy trong ô A2 có giá trị là "Nghia" thì ô B2 nhập vào "OK".

Hiện tại, đáp án nhanh nhất mà tôi có được đã gửi mail riêng (nhằm ghi lại thời gian gửi, để tránh nói ăn gian).

Để tiện việc theo dõi các câu đố, các bài tập tôi đã tạo ra topic này các bạn click vào đây:

Các link của topic "Các câu đố, bài tập nhằm ôn tập & bổ sung kiến thức căn bản VBA"
Em mới mua cuốn sách lập trình VBA của thầy Hướng và em đang tập tành viết code, em có thầy chủ đề này của anh Nghĩa và em giải câu đố thứ nhất của anh. Em không xem cách giải của bạn nào cả. Mục đích chính là để tự mình suy nghĩ tìm tỏi. Em có viết 2 đoạn code như sau:
Đoạn 1:
Public Sub tim_tu()
Dim i As Long, rng As Range, cll As Range
Set rng = Sheet1.Range("A1:B65536")
For Each cll In rng
If cll.Value = "Nghia" Then cll.Offset(0, 1) = "Ok"
Next cll
End Sub
Đoạn 2:
Public Sub timtu()
Dim arr(), i As Long
arr = Worksheets("sheet1").Range("A1:B65536").Value
For i = 1 To UBound(arr, 1)
If arr(i, 1) = "Nghia" Then
arr(i, 2) = "Ok"
End If
Next i
End Sub
Ở code 1 em chạy kết quả chính xác, còn ở code 2 em không hiểu sao code chạy không báo lỗi gì nhưng nó không ra kết quả là "Ok" bên cạnh chữ "Nghia" ạ?
Mong anh chị giải thích giúp ạ!
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Code thứ nhất bạn đọc và ghi trực tiếp trên range/cells của bảng tính cho nên bạn thấy kết quả.
Code thứ hai bạn trich xuất dữ liệu vào một mảng. Sau đó bạn ghi trên mảng mảng này. Mảng triong bài này là một vùng trên bộ nhớ. Bạn đâu có chi nó lại trên range thì làm sao mà thấy được.

Khuyến khích:
Bạn tự học mày mò là đáng khích lệ. Nhưng sau mỗi lần tự giải một cái gì đó thì cũng nên tìm hiểu thêm xem người khác giải ra sao để học thêm giải thuật (lưu ý tôi dùng "sau")
 
Upvote 0
Code thứ nhất bạn đọc và ghi trực tiếp trên range/cells của bảng tính cho nên bạn thấy kết quả.
Code thứ hai bạn trich xuất dữ liệu vào một mảng. Sau đó bạn ghi trên mảng mảng này. Mảng triong bài này là một vùng trên bộ nhớ. Bạn đâu có chi nó lại trên range thì làm sao mà thấy được.

Khuyến khích:
Bạn tự học mày mò là đáng khích lệ. Nhưng sau mỗi lần tự giải một cái gì đó thì cũng nên tìm hiểu thêm xem người khác giải ra sao để học thêm giải thuật (lưu ý tôi dùng "sau")
Em rất cảm ơn anh đã giải thích. Tại em cũng chưa hiểu rõ cách sử dụng biến mảng nên mới vậy ạ.
Anh (chị) có thể chỉ giúp em cách ghi lại giá trị của biến mảng vào Range để em hiểu rõ được không ạ?
 
Lần chỉnh sửa cuối:
Upvote 0
Ồ có người bới lên mình mới biết chị Điều hành viên còn có cả tài viết code nữa cơ đấy . hâm mộ chị Điều hành viên quá đi . --=0--=0--=0
 
Upvote 0
vâng, mặc dù là những câu đố "căn bản", nhưng tôi tin là các thành viên đã, đang, sẽ học vba trong đó có tôi, sẽ chờ một đáp án bằng dao hoặc ado để giải quyết vấn đề ở câu đố 1 nhằm mục đích để học hỏi, để mở rộng thêm tầm mắt của mình.

Dù là tốc độ đã xét rồi, nhưng sáng nay tôi cũng ngẫm nghĩ và có một giải pháp cho bài đó cũng khá nhanh (có lẽ không bằng kiểu xử lý mảng rồi gán trực tiếp xuống chuỗi dùng cho trường hợp dữ liệu như trong file đính kèm), nhưng đây cũng là một phương pháp hữu hiệu nhưng ít thành viên nhắc đến, đó là dùng find method.

Dùng find method tôi đã thấy người ta dùng rất nhiều, nhưng tôi chưa đọc được bài nào viết trên diễn đàn nói về dùng find next. Vậy nhân đây tôi xin giới thiệu cách viết này cho các bạn cùng tham khảo, góp ý.

Mã:
private sub findnext()
    dim c as long, i as long, j as long, r as long, _
        frng as range, lrng as range
    with sheet1.range("a1:a1048576")
        set lrng = .cells(1, 1)
        for i = 1 to .rows.count
            set frng = .find(what:="nghia", after:=lrng, lookin:=xlformulas, lookat:=xlwhole)
            if frng is nothing then exit for
            if frng.row = 1 then exit for
            .findnext(after:=lrng).offset(, 1) = "ok"
            set lrng = frng
        next
    end with
end sub

các bạn lưu ý: Với cách tìm kiếm giá trị thì lookin:=xlformulas luôn luôn nhanh hơn lookin:=xlvalues.

--------------------------------------------

do code trên tôi làm một cách vội vã, chưa kiểm tra kỹ nên sẽ phát sinh vòng lặp chạy liên tục nếu ô đầu tiên không thỏa điều kiện, cho nên tôi đã sửa lại ở bài này:

http://www.giaiphapexcel.com/forum/showthread.php?86400-Đố-vui-căn-bản-về-vba&p=538878#post538878

chân thành xin lỗi các bạn!
Lâu lắm hôm nay rãnh mới đọc được bài này
hình như code của bạn hiền dùng find +for next vẫn còn chậm 1 nửa so với find + do loop
--=0
 
Upvote 0

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

Back
Top Bottom