Viết hàm như thế nào là tốt

Liên hệ QC

Pansy_flower

...nợ người, nợ đời...
Thành viên danh dự
Tham gia
3/6/06
Bài viết
1,611
Được thích
14,001
Nghề nghiệp
...thiết kế máy bay cho VOI tự lái...^.^
Chúng ta biết tại sao chỉ có mấy hàm của Excel mà chúng ta mỗi người mỗi nghề có thể dùng nó để giải quyết công việc. Các hàm được xây dựng phải giải quyết theo hướng tổng quát không nên cụ thể một chi tiết trừ khi bắt buộc. Người dùng Excel có thể vận dụng hàm để sáng tác ra các công thức khác nhau, sự thông minh (công thức ngắn gọn+tốc độ xửa lý nhanh+dễ nhớ...) của nó tùy vào sáng tạo và tư duy của mỗi người. Đây chính là điểm mạnh của Excel và làm cho chúng ta cứ như mắc nợ Excel!

Chắc hẳn chúng ta ai cũng muốn mình học VBA để biết tạo ra các hàm không những cho mình và cả những người khác sử dụng! Vậy chúng nên thiết kế hàm như thế nào là tốt nhất? Để giải quyết câu hỏi này chúng ta bắt đầu từng việc:


1-Khai báo và đặt tên Thủ tục, Hàm, Biến, Hằng (Sub, Function, Dim, Const)


Bàn vào việc đặt tên mỗi người nên chọn một kiểu gọi là "chuẩn", có thể bằng tiếng Anh hay Việt. Theo tôi các bạn nên đặt theo tiếng Anh vì ngắn gọn hơn.

Việc đặt tên thực sự rất quan trọng (chúng ta trân trọng như là đặt tên cho con mình). Các bạn hình dung thế này, nếu chúng ta có hàng trăm phương tiện, công cụ làm việc, khi cần một việc gì đó chúng ta cần gọi nó ra ngay thì liệu chúng ta có nhớ tên gọi của nó không? Phương pháp đặt tên để giúp ta dễ nhớ hơn.

+ Tên Thủ tục, Hàm:
Tên phải hàm ý về nội dung giải quyết của nó. Điều quan trọng là không được trùng với từ khóa của Excel. Ví dụ không được đặt tên là "Sub", "Do", "Loop" hay các hàm sẵn có của VBA là "Left", "Right",...

Ví dụ tôi muốn tạo một hàm để tìm chuỗi, vậy tên tôi sẽ đặt tên function là "Timchuoi", "BatdaulaChuhoa" là hàm đổi các ký tự đầu của mỗi từ thành chữ hoa (Trong Excel có hàm Proper để làm nhưng hàm này bị lỗi với font với kiểu gõ không phải Unicode và có dấu), tại sao không đặt là "Chuhoa" để ngắn hơn? Vì có thể bị nhầm sang đổi chuỗi thành chữ hoa (UPPER, VBA-Ucase).
Chúng ta đặt tên sao cho không bị nhầm chức năng.
Trong VBA khai báo như sau
PHP:
Function Timchuoi()
End Function
 
Function BatdaulaChuhoa()[HTML][/HTML]
End Function


+ Tên Dim, Const:
Cách thức cũng như phần đặ tên cho Sub/Function nhưng thêm các ký tự định nghĩa để làm sáng tỏ kiểu giá trị (Type)
Kiểu giá trị gồm: String, Byte, Integer, Long, Date, Object, Boolean....
Với tôi, tôi hay đặt tên với phần đầu là kiểu giá trị, các kiểu Byte, Integer, Long thì dùng chữ "n"-Number để đại diện vì cơ bản là giá trị số. Kiểu Boolean thì dùng chuỗi "Is".

Mã:
Dim strHoTen as String
Dim IsNam as Boolean
Dim dNgay as Date
......

Khi tôi viết hướng dẫn sử dụng hàm LEFT trên Excel tôi viết cấu trúc thế này LEFT(strChuoi, nKytu). Như vậy thì ta hiểu đối số đầu tiên là kiểu String - Chuỗi văn bản, nKytu là giá trị đưa vào kiểu số.

Có nhiều bạn khi khai báo kiểu giá trị thường hay bỏ lửng như Dim strHoTen mà không có kết thúc là "String" - Không nên chút nào! Việc xác định rõ giá trị còn là quy ước khi sử dụng chúng trong thân chương trình.

+ Xác định tham số cho Sub, Function

Nhắc lại về hàm LEFT(strChuoi, nKytu). Chúng ta cứ tự hỏi tại sao phải có 2 đối số? Tại sao? Muốn lấy bên trái với n ký tự thì buộc người dùng phải đưa vào strChuoi - chuối để lấy, nKytu là số ký tự cần lấy.

Như vậy tham số cho Sub, Function là những tham số mà người dùng phải buộc đưa vào thì Sub, Function mới xử lý được. Tên các tham số này người dùng (bất kỳ ai sử dụng) phải gần như tự đọc hiểu được).

Có một ví dụ về kiểu khai báo thế này:

Function Tachten(St as String,Bt as Integer)
St, Bt là cái gì? Viết thế này thì chỉ có tác giả mới hiểu và đến lúc nào đó chính họ sẽ không biết nó là cái gì nữa!

Khi đưa biến vào làm tham số chúng ta cũng cần chú ý một cách để Optional - Tùy ý và gán giá trị ngầm định.

Ví dụ:
PHP:
Function Timchuoi(Byval strChuoi as String,Byval strChuoiTim as String, _
      Optional Byval TuBenTrai as Boolean = True) as Long
End Function

Hàm "Timchuoi" để tìm strChuoiTim trong strChuoi, ngầm định (Optional) tìm từ trái sang phải.
A1="090 4210337"
=Timchuoi(A1," ")

Hàm sẽ tìm ký tự " " trong ô A1 và trả về vị trí tìm được, chúng ta nếu tìm từ trái thì không cần phải vào tham số thứ 3 vì ngầm định TuBenTrai=True rồi
Nếu tìm từ bên phải thì =Timchuoi(A1," ", False)

Chúng ta gán Optional đầu tiên trước khai báo Byval hay Byref khi biết chắc đa số mọi người sẽ quy ước biến này về một giá trị nào đó, sử dụng Optional để người dùng sử dụng ngắn gọn hơn (Bản chất là ta khai báo giá trị tham số giúp cho người dùng).

2- Tạo ra Sub, Function để giải quyết mấu chốt công việc, khai thác triệt để các hàm sãn có

Chúng viết các Sub, Function là để giải quyết mấu chốt công việc, không nên quá cụ thể nếu điều đó không phải là bắt buộc.

Tôi sẽ viết hàm "Timchuoi". Hàm này sẽ tìm chuỗi từ trái sang phải hoặc ngược lại, kết quả tìm được sẽ cho ra một số >0 là vị trí tìm được, =0 nếu không tìm được.

Cách 1

PHP:
Function Timchuoi(Byval strChuoi as String, Byval strChuoiTim as String, _
      Optional Byval TuBenTrai as Boolean = True) as Long
Dim I as Long
Dim nKytuChuoitim as Long
Dim nKytuChuoi as Long
nKytuChuoi=Len(strChuoi)
nKytuChuoitim =Len(strChuoiTim)
 
If nKytuChuoi<nKytuChuoitim then Exit Function
 
    If TuBenTrai Then
        For I=1 To nKytuChuoi
            If Mid(strChuoi,I,nKytuChuoitim)=strChuoiTim Then
                Timchuoi=I
                Goto Done:
            End if
        Next I
     Else
         For I=nKytuChuoi To 1 Step -1
             If Not (nKytuChuoi-I< nKytuChuoitim) Then
                 If Mid(strChuoi,I,nKytuChuoitim)=strChuoiTim Then
                    Timchuoi=I
                     Goto Done:
                  End if
             End if
        Next I
    End If 
  Done:
End Function
Mặc dù Cách 1 Khá chặt chẽ nhưng không hay chút nào vì vừa dài lại vừa không khai thác các hàm mà VBA đã cung cấp->Tốc độ xử lý rất có thể bị chậm hơn nhiều với việc áp dụng hàm đã có

Cách 2: 'Khai thác hàm đã có Instr và InstrRev

PHP:
Function Timchuoi(Byval strChuoi as String, Byval strChuoiTim as String, _
           Optional Byval TuBenTrai as Boolean = True) as Long
Dim I as Long
Dim nKytuChuoitim as Long
Dim nKytuChuoi as Long
nKytuChuoi=Len(strChuoi)
nKytuChuoitim =Len(strChuoiTim)
 
If nKytuChuoi<nKytuChuoitim then Exit Function
 
If TuBenTrai Then
    Timchuoi=Instr(strChuoi,strChuoiTim)
Else
    Timchuoi=InstrRev(strChuoi,strChuoiTim)
End If
 
End Function

Ứng dụng hàm "Timchuoi"

Trích nguyên văn:
+ Hàm tách tên
Mã:
Function TachTen(Byval strHoTen as String) as String
 TachTen=Mid(strHoTen,Timchuoi(strHoTen," ",False)+1)
End Function
+ Tách tên
Giả sử cột A là Họ và tên. Cần tách tên
Cách 1
=MID(A1,Timchuoi(A1," ",False)+1)
Cách 2
=TachTen(A1)

+ Tách dịch vụ điện thoại di động theo mã số
Giả sử cột A là các số điện thoại 090 4210337; 091 3255126; 098 555444; 0916 066512...
Cần lấy mã dịch vụ
=LEFT(A1,Timchuoi(A1," ")-1)
+ Từ số điện thoại cố định, tách mã vùng
Giả sử cột A là các số điện thoại 04 7544525 08 899655; 051 545222; 020 123456;...

=LEFT(A1,Timchuoi(A1," ")-1)

+ Tách tên tệp ra khỏi đường dẫn
'Sử dụng trong môi trương VBE
Sub VD()
Dim strFullPath as String
Dim strFileName as String

strFullPath = ActiveWorkbook.FullPath
strFileName=Mid(strFullPath,Timchuoi(strFullPath," \",False)+1)
'Thông báo
Msgbox strFileName,,strFullPath
End Sub


Như vậy chỉ có một hàm "Timchuoi" mà giải quyết được những vấn đề về cắt chuỗi theo các mục đích khác nhau.

Vấn đề tôi muốn nhấn mạnh là chúng ta viết hàm không phải để nó chỉ giải quyết một việc cụ thể mà nó phải giải quyết những bào toán tổng quát. Hàm như một linh kiện máy tính PC có thể lắp vào máy này hay máy khác.

Việc viết hàm và thủ tục còn có rất nhiều các thuật toán hay giúp cho bài toán của bạn được đánh giá ử mức tối ưu. Việc đặt tên cũng vậy còn nhiều trường hợp để đặt khác. Trong phạm vi một bài viết ngắn tôi chỉ có thể đưa ra những lý giải cơ bản và ví dụ nhỏ, các bạn xem và tự tích tũy dần những kiến thức cũng như kinh nghiệm về việc coding.

(Trích bài của anh Tuanktcdcn)​
 
Lần chỉnh sửa cuối:
Xin chào các Bác,
Xin bàn thêm 1 ý:
Hàm InstrRev trong đoạn "Timchuoi=InstrRev(strChuoi,strChuoiTim)" không thể sử dụng được trong Excel 97, bởi: với phiên bản VBA tương ứng không tích hợp hàm này, InstrRev chỉ có trong Excel 2000 trở về sau.

(Trích bài anh Lehongduc)

lehongduc đã viết:
Xin chào các Bác,
Xin bàn thêm 1 ý:
Hàm InstrRev trong đoạn "Timchuoi=InstrRev(strChuoi,strChuoiTim)" không thể sử dụng được trong Excel 97, bởi: với phiên bản VBA tương ứng không tích hợp hàm này, InstrRev chỉ có trong Excel 2000 trở về sau.


Đúng vậy! Chính xác là InstrRev không có trong Office 97 (VBA6.DLL). Các bạn nên loại bỏ Office97 đi vì các lý do cơ bản:
Sản phẩm mới:
- Sản phẩm mới bao giờ cũng sửa lỗi mà các version cũ có
- Tăng nhiều tiện ích người dùng
- Tốc độ truy xuất file nhanh hơn
- Trong VBA-Cung cấp các hàm tiện dụng hơn
- Trong VBA cho phép khai báo Enum
......
Với bộ Office các bạn nên sử dụng tối thiểu từ Office2000 trở lên.
Office2000 không yêu cấu máy cấu hình cao lắm, kể cả khi bạn vẫn dùng Pentium(R) 133 MHZ RAM32

To SA_DQ: nKytuChuoi=Len(strChuoi)
nKytuChuoitim =Len(strChuoiTim)

Trong Hàm Timchuoi() đúng là có thể không cần khai báo trên. Với các thủ tục khác nếu trong thân chương trình còn dùng tới độ rộng của chuỗi (LEN) nó thì nên có để kế thừa phép tính trước mà không phải tính lại.

Tiết kiệm là điều chúng ta phải tính chứ, nhưng vấn đề tiết kiệm ở đây phải hiểu đúng.
Trong một thủ tục:
1-> Khai báo tài nguyên
2-> Sử dụng tài nguyên
3-> Giải phóng tài nguyên

Nếu thiếu bước 3 thì ứng dụng của bàn sẽ dần tới chỗ cạn kiệt và break.

Trong một thủ tục, nếu không phải là biến đối tượng (Dim obj As Object; Set obj=...) thì khi kết thúc thủ tục thì chúng tự được giải phóng (Free/Dispose). Nếu chúng ta không khai báo mà vẫn dùng biến đây không phải là cách tốt - Không chặt chẽ và một nơi nào đó của hệ thống vẫn còn nhớ biến đó.

Mong các bác tiếp tục viết ra những gì mình biết và đang quan tâm, chúng ta tiếp tục thảo luận.

(Trích bài anh Tuanktcdcn)
 
Upvote 0
Ông thầy dạy cách lãng fí đây?!

Tuanktcdcn đã viết:
Cách 1. . .Cách 2Khai thác hàm đã có Instr và InstrRev

Function Timchuoi(Byval strChuoi as String, Byval strChuoiTim as String, Optional Byval TuBenTrai as Boolean = True) as Long
1Dim I as Long
2Dim nKytuChuoitim as Long
3Dim nKytuChuoi as Long
4nKytuChuoi=Len(strChuoi)
5nKytuChuoitim =Len(strChuoiTim)
6If nKytuChuoi<nKytuChuoitim then Exit Function

If TuBenTrai Then
Timchuoi=Instr(strChuoi,strChuoiTim)
Else
Timchuoi=InstrRev(strChuoi,strChuoiTim)
End If

End Function
.

dance2.gif

/(/hững lãng fí theo thiển í, được liệt kê như sau:
a/. Câu lệnh 1 không dùng (thông cảm do lịch sử để lại)!
b/. Câu lệnh 2 & 3 khai As Long là lãng fí không cần thiết; Nếu ai đó cố tình tạo ra chuỗi kí tự hay kí số dài hơn 2 triệu thì chuyển đến "Biên hoà" cho rồi!
c/. Các câu lệnh từ 2 - 6 có thể thay = câu:
26 If Len(nKiTuChuoi) < Len( nKiTuChuoiTim) Then Exit Function
Lời nhắn CC: Cần tiêt kiệm tài nguyên; Vì nước ta còn nghèo lắm!
angel.gif
drummer.gif

(Trích bài của anh SA_DQ)
 
Lần chỉnh sửa cuối:
Upvote 0
SA_DQ đã viết:
/(/hững lãng fí theo thiển í, được liệt kê như sau:
b/. Câu lệnh 2 & 3 khai As Long là lãng fí không cần thiết; Nếu ai đó cố tình tạo ra chuỗi kí tự hay kí số dài hơn 2 triệu thì chuyển đến "Biên hoà" cho rồi!

Nếu ai hiểu chương trình dịch nó hoạt động như thế nào thì khai báo Long tuy tốn chút mem nhưng lại chạy nhanh hơn và dân lập trình chuyên nghiệp (bọn M$ ấy) nó toàn dùng kiểu Long thôi chứ ít dùng Interger lắm. Giải thích: Kiểu gì khi sang mã máy, compiler nó đều thêm 1 lệnh chuyển kiểu Interger sang kiểu Long. Vì vậy tôi hay khai báo As Long cho chương trình chạy nhanh (mem thì bây giờ thiếu gì).

SA_DQ đã viết:
c/. Các câu lệnh từ 2 - 6 có thể thay = câu:
26 If Len(nKiTuChuoi) < Len( nKiTuChuoiTim) Then Exit Function

Mọi người thử phân biệt 2 cách viết xem cách viết nào nhanh hơn nhé:

For i% = 1 to Len(nKiTuChuoi)
....
Next



lngStringLen% = Len(nKiTuChuoi)
For i% = 1 to lngStringLen%
....
Next

Nếu mọi người tìm ra được chân lý thì tự khắc mọi người hiểu tại sao phải dùng thêm 2 biến. Vì đây là hàm quá đơn giản (chỉ là 1 ví dụ thôi nên có thể mọi người chưa thấy được chân lý đó). Lập trình ko chỉ là làm cho code chạy. Lập trình là cả 1 bề dày kinh nghiệm học hỏi liên tục kèm theo những kỹ năng, những nguyên tắc cần tuân thủ, những bản chất gốc gác của nền tảng (ví dụ phải hiểu windows programming,...) thì tự nhiên thấy trở nên professional.

À, té ra Tuân đã nói vần đề này rồi
smile.gif
-->


To SA_DQ: nKytuChuoi=Len(strChuoi)
nKytuChuoitim =Len(strChuoiTim)

Trong Hàm Timchuoi() đúng là có thể không cần khai báo trên. Với các thủ tục khác nếu trong thân chương trình còn dùng tới độ rộng của chuỗi (LEN) nó thì nên có để kế thừa phép tính trước mà không phải tính lại.

Tiết kiệm là điều chúng ta phải tính chứ, nhưng vấn đề tiết kiệm ở đây phải hiểu đúng.
Trong một thủ tục:
1-> Khai báo tài nguyên
2-> Sử dụng tài nguyên
3-> Giải phóng tài nguyên
(Trích bài của anh hai2hai)
 
Upvote 0
hai2hai đã viết:
Nếu hiểu chương trình nó hoạt động như thế nào thì khai báo Long tuy tốn chút mem nhưng lại chạy nhanh hơn và dân lập trình chuyên nghiệp (. . .) nó toàn dùng kiểu Long thôi. Giải thích: Kiểu gì khi sang mã máy, compiler nó đều thêm 1 lệnh chuyển kiểu sang kiểu Long. Vì vậy khai báo As Long cho chương trình chạy nhanh ().

Quả là hay và quá hay! Đáng đồng tiền bát gạo!


hai2hai đã viết:
Mọi người thử phân biệt 2 cách viết xem cách viết nào nhanh hơn nhé:
For i% = 1 to Len(nKiTuChuoi)
....
Next

lngStringLen% = Len(nKiTuChuoi)
For i% = 1 to lngStringLen%
....
Next
Nếu mọi người tìm ra được chân lý thì tự khắc mọi người hiểu tại sao phải dùng thêm 2 biến.

Phải vầy không, Bác 2Hai2: Nếu Len(nKiTuChuoi) = 8 thì vòng lập đầu phải thực hiện 16 lệnh! Chính xác chưa vậy B.?!
Quả là 1 ngày đường một sàng khôn!
 
Upvote 0
Dear all,
--------
Em thì chưa biết nhiều về chân lý mấy! Nhưng em cảm nhận thế này:
- Nếu Len(nKiTuChuoi) = 8 thì cả hai vòng đều lặp 8 lần, còn thực hiện bao nhiêu lệnh thì còn phụ thuộc vào số lượng các câu lệnh bên trong nó.
- Khi khai gán lngStringLen = Len(nKiTuChuoi) thì khi lặp, nó không phải tính lại Len(nKiTuChuoi) nữa.
Em mạo muội anh 2 kết luận: Chính xác!

(Trích bài anh Đào Việt Cường)
 
Upvote 0
Xin được diễn đạt nông dân hơn như thế này

Xin chào các Bác,
Để cho các bạn mới vọc VBA (và cũng là mới bắt đầu thảo chương) đỡ mất thời gian, tôi xin góp thêm ý diễn đạt nôm na là vầy:
+ Nếu cứ để For i%=1 to Len(nKytuChuoi) ... thì cái ứng dụng nó buộc phải xử lý 1 vòng bằng hàm Len với cái chuỗi nKytuChuoi. Cứ đụng tới cái đọan bạn ghi là Len(nKytuChuoi) nó lại mần tiếp cái chuyện ấy.
+ Thế là rất mất thời gian, chi bằng ta tính 1 lần ngay từ đầu Len(nKytuChuoi) bằng bao nhiêu rồi gán quách nó cho 1 biến gọi là lngStringLen. Sau đó cái ứng dụng chỉ cần lấy giá trị của biến này để xơi mà khỏi phải bận tâm mần răng để có nó nữa.
Kính các Bác nhé.

(Trích bài anh lehongduc)
 
Upvote 0
Thực ra sau khi đưa ví dụ đó thì nhìn là hiểu đoạn code nào chạy nhanh hơn rồi
smile.gif


Cũng tương tự như vậy, mỗi khi thực hiện oRS_Customer.EOF thì ADO Engine nó phải làm những thao tác gì (Cái này làm DB phải tìm hiểu rõ từng lệnh 1). Và như vậy, 1 triệu bản ghi - 1tr vòng lặp --> thì nó lại thực hiện 1tr lần cái công việc đó (Ít bản ghi thì mọi người ko nhận thấy sự khác biệt đâu).

Hãy tìm cách lấy được tổng số bản ghi trước và sau đó dùng vòng For thì khi có nhiều đến vài triệu bản ghi, mọi người sẽ thấy cải thiện đáng kể.

'// Đây là đoạn code khá ... ko tốt
smile.gif
(và sure luôn là rất nhiều người viết kiểu này)
Do While Not oRS_Customer.EOF '// Khi kiểm tra EOF cũng phải thực hiện khá nhiều thao tác mà ta có thể không biết (để biết thì phải đọc khá kỹ).
...
oRS_Customer.MoveNext '// Mỗi lần Move Next lại phải làm khá nhiều thao tác mà bình thường ta ko hề biết.

End Do

Tóm lại, trong bất kỳ vòng lặp nào cần chú ý hạn chế tối đa những tiến trình consume long time. v.v....

Và còn nhiều điều trong lập trình nói chung, lập trình CSDL nói riêng cần phải optimize lắm.

Hy vọng mọi người ngày càng có nhiều chia sẻ cho nhau. Và hãy bắt đầu ngay bằng việc .... CODING CONVENTION (Điều mà mình thấy rất thiếu khi mọi người bàn đến chuyện lập trình ở đây).


(Trích bài anh hai2hai)
 
Upvote 0
Thêm 1 hàm nữa, mời các Bạn thảo luận.

Xin mời các Bạn thảo luận hàm do tôi tự biên tự diễn sau nhé:
+ Để cho việc thảo luận có hiệu quả, sau khi các thành viên thảo luận xong rất mong Bác Mod cho 1 cái tổng kết với hàm đã được hiệu chỉnh lại tối ưu nhất.
+ Cái hàm này có tác dụng cắt lấy chuỗi con từ bên trái hoặc bên phải 1 chuỗi mẹ đến 1 ký tự xác định. Chúng ta có thể dùng các hàm có sẵn của Excel như Left, Right và Instr để đáp ứng nhu cầu này, song theo tôi trong một số trường hợp ta buộc phải viết 1 hàm bằng VBA mới xử lý được, đó là lý do của việc tôi thấy cần viết cái hàm này. Ý các Bạn ra sao?

Mã:
[B]Function CutLoR(St As String, Char As String, N As Boolean)[/B]
'
'Cat lay chuoi con tu ben trai hay ben phai chuoi me den ky tu xac dinh
'Char: ky tu xac dinh
'n=true => cat ben trai, n=false => cat ben phai
'
Dim Sb As String, stChk As String
Dim i As Integer, LngSt As Integer
St = Trim(St)
LngSt = Len(St)
If LngSt = 0 Then Exit Function
    For i = 0 To LngSt
        If N = True Then 'Cat trai
              stChk = Mid(St, i + 1, 1)
        Else
              stChk = Mid(St, Len(St) - i, 1)
        End If
        If stChk <> Char Then
             If N = True Then
                    Sb = Sb & stChk
             Else
                    Sb = stChk & Sb
             End If
        Else
             Exit For
         End If
    Next i

    CutLoR = Sb

[B]End Function[/B][/COLOR]
(Trích bài anh lehongduc)
 
Upvote 0
Mọi người nên chú ý về coding convention & optimize code 1 chút.

Ví dụ: CutLoR(St As String, Char As String, N As Boolean) đọc sẽ rất khó hiểu (mọi người thử xem cách mà M$ nó declare API xem có dễ hiểu ko?

Char là 1 ký tự: Ví dụ A, B, C. Hiện nếu mình viết tên hàm, tên biến đều tiếng Việt và tự nhiên có 1 biến lại dùng từ tiếng anh là rất khó đọc (nếu ko muốn nói là đọc ko hiểu gì cả).

Đặc biệt là những từ viết tắt như: Dim Sb As String '// --> Hầu như ko hiểu biến này có mục tiêu là gì.

Về chuyện optimize code. Ở đây chúng ta dùng khá nhiều hàm xử lý String mà mọi người có thể chưa biết là chỉ cần thêm $ sau tên hàm là tốc độ cũng tăng lên so với khi mình ko viết (dĩ nhiên điều này chỉ thấy hiệu quả khi phải sử lý với khối lượng công việc lớn). Ví dụ: Thay vì Mid() thì ta viết Mid$(), Trim() thì viết Trim$(), v.v...

Cao cấp hơn, để sử lý string thì có thể dùng CopyMem nhưng có lẽ lựa chọn này khá cao cấp và ko cần thiết với mọi người.


Hàm này là 1 hàm khá đơn giản, có mục đích rõ ràng. (Bấm vào nút Trích dẫn để xem). Mọi người có thể tự viết phần thân cho hàm này. Tuy nhiên code được đánh giá cao nhất là code viết theo coding conventions (hungarian naming conventions).

Function SMid(orig_string As String, start As Long, str_start As String, str_end As String)
'************************************************* *************************************************
' Name: SMid - "Smart" Mid
' Description: This function is similar to the Mid function.
' Except, you can specify the starting, and ending strings
' (capture the data in between).
' Inputs:
' - orig_string As String : Source string
' - start As Long : Location in source to start from
' - str_start As String : beginning string (capture from)
' - str_end As String : ending string (capture to)
' o_string = Origional String
' s_start = Start From string
' s_end = Ending string
' Returns:This code will return the data
' that is found between the "str_start" and "str_end" strings.
' Example:
' newStr = SMid("Hello 1Between2 world!", 1, "1", "2")
' will return: "Between"
' By: hai2hai - VNUNI
'************************************************* *******************************

'// Please, your code should be here....

(Trích bài của anh hai2hai)
 
Upvote 0
Theo tôi, những người có khả năng lập trình hạn chế hoặc không chuyên thì hàm càng đơn giản càng tốt.
Khi đó người sử dụng càng hiểu hơn. Tất nhiên luôn cập nhật những cái tối ưu để hoàn thiện và rút ngắn code.
*****


-----------------
Khỏe .... để xây dựng Tổ Quốc!
 
Upvote 0
Định lượng 1 lần để biết

Sub KiemTocDo()
Dim FAn As String, Xh As String
Dim iZ As Long, iDem As Integer, bDem As Byte
Dim iSoNgau As Integer

Xh = Chr(10) & Chr(13)
FAn = "A. Not" & Xh & "B. 1/0"
FAn = InputBox(FAn, "HAY CHON FUONG AN:", "A")
FAn = UCase$(FAn)

Time0 = Time
For iZ = 1 To 10 ^ 8
‘Khối lệnh A(i)
Next iZ
Time9 = Time - Time0
For iZ = 1 To 10 ^ 4
‘ Khối lệnh B(i)
Next iZ
Time7 = Time - Time9

MsgBox Str(Time9) & Xh & Str(Time7), , "F.An: " & FAn

End Sub

A1 Bflag = Not Bflag: Bflag = Not Bflag
B1 If Bflag Then Bflag = False: If Not Bflag Then Bflag = True

A2 Bflag = Not Bflag: Bflag = Not Bflag
B2 If Bflag Then Bflag = 0: If Not Bflag Then Bflag = -1

A3 Randomize: iSoNgau = Int(20 * Rnd()) + 1
Bflag = (iSoNgau > 0 And iSoNgau < 10)
B3 Randomize: iSoNgau = Int(20 * Rnd()) + 1
If iSoNgau > 0 And iSoNgau < 10 Then
Bflag = False
Else
Bflag = True
End If

A4 If iZ Mod 2 = 0 Then bDem = bDem + 0
If iZ Mod 2 = 1 Then bDem = bDem - 0
B4 If iZ Mod 2 = 0 Then iDem = bDem + 0
If iZ Mod 2 = 1 Then iDem = bDem - 0
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0
Web KT
Back
Top Bottom