VBA cần logic trước-rồi sau đó mới là cải thiện tốc độ

Euler

Administrator
Thành viên BQT
Ban đầu code VBA, trong đầu nghĩ như thế nào thì sẽ code như thế. Vì vậy cách tiếp cận VBA của từng người sẽ khác nhau.
Ví dụ, một người đã quen sử dụng hàm trên excel, anh ta sẽ nghĩ thay thế hàm đó trên excel bằng VBA sẽ như thế nào. Điều này không phải là không tốt. Lấy ví dụ, đảo chiều mảng, anh ta sẽ biết sử dụng Transpose, hoặc tìm kiếm, anh ta sẽ biết dùng Vlookup hoặc Find. Những lệnh này về cơ bản là nhanh, nhưng hạn chế là không giúp mọi người hiểu rõ logic.
Chẳng hạn để tìm trên cột A xem cells nào có giá trị là "tuhocvba" thì anh có thể dùng Find.
Nhưng logic toán cuả nó sẽ là:
Mã:
For i = 1 to 100 step 1
if cells(i,1).value = "tuhocvba" then
'xử lý của bạn
end if
Next i
Nhìn vào code này, không ai là không hiểu logic của nó. Tôi nghĩ, đối với người tự học, nên đi theo hướng này. Chúng ta nên tiếp cận VBA bằng logic trước.
Nếu có thêm hiểu biết về tính năng, hay hàm, tốc độ chương trình có thể được cải thiện.
Cách code như trên có thể áp dụng tổng quát cho các trường hợp khác, dò tìm từng chút một, tốc độ có thể không nhanh, nhưng luôn luôn đúng, và cũng chẳng bao giờ xảy ra lỗi ngoài ý muốn.
Trên diễn đàn của chúng ta, trong list video tự học VBA, ngay trong những video đầu tiên, chúng tôi đã phải suy nghĩ cho vấn đề nào lên trước. Nó phải là thứ logic dễ hiểu, và có thể áp dụng ở nhiều chương trình.
Sau đó mới là cải thiện tốc độ ra sao, có thể dùng những lệnh nào thay thế thì nên được trình bày sau.

Người hỗ trợ nếu phán đoán được kiến thức của người hỏi ở vị trí nào, đưa ra code support phù hợp với khả năng hiểu biết của họ, được coi là lý tưởng. Nếu một người lơ tơ mơ, nếu như sử dụng các lệnh phức tạp, họ sẽ chẳng hiểu gì, nếu code không có comment, thì họ lại càng chẳng hiểu gì. Vậy là điều chúng ta giúp đỡ sẽ giảm đi rất nhiều ý nghĩa.

Như thế nào là hỗ trợ tốt, đó là người nhận hiểu được logic, không cần biết nhanh hay chậm ra sao, sau đó họ có thể tự làm đối với những vấn đề tương tự trong tương lai.

Tôi nhớ chương trình tôi làm, chạy hết 30 phút. Chẳng sao cả, trước đó công việc của tôi có thể hết đến cả ngày.

Tôi giải hầu hết các yêu cầu bằng suy nghĩ logic, cái nào không biết thì record macro. Tôi cũng không tham gia hỗ trợ code cho ai cả, tôi đọc code và xem trong code đó họ sử dụng lệnh gì mà mình chưa biết. Đó là cách tôi học.

Khi mà có thể tự giải quyết bài toán của mình và vấn đề của người khác, lúc này sẽ diễn ra việc thảo luận trao đổi với những người khác. Nên code như thế nào cho nhanh. Hoặc là nên code như thế nào cho bớt rườm rà.
 

Euler

Administrator
Thành viên BQT
Nào thì viết tiếp.
Các bạn nên tiếp cận VBA theo list video của diễn đàn. Nó đi từ suy nghĩ rất toán. Bây giờ các bạn tiếp cận VBA nhưng trong đầu cứ nghĩ tới Vlookup, Find, như thế là bỏ quên hết logic.
Nhưng nhiều khi toán quá cũng khổ lắm đấy. Nào, ta thử bài toán sau nhé.
Bạn cần đăng nhập để thấy hình ảnh


Logic của nó rất rõ ràng. Nếu A3 = F3 và B3 = G3, C3 = H3 hoặc A3 = F3 và B3 = H3, C3 = G3 thì ta coi hai dữ liệu là giống nhau.
Nếu là toán thì nó là như này:
Mã:
if (Range("A3") = Range("F3") and ..... ) or (...) then
end if
Ôi trời ơi, lắm phép logic thế này thì gõ code chết mất thôi. Chưa nói là càng ít phép so sánh thì tốc độ càng nhanh. Ở trên tính sơ sơ có 6 cells. Một lần so sánh là 3 phép so sánh. Sau đó lại đảo lại ở phép hoặc, thêm 3 cái so sánh nữa là 6 cái. Có 12 chuỗi ký tự tham gia vào 6 phép so sánh trong code trên. Khiếp quá.
Bây giờ mình nghĩ làm sao giảm cái so sánh này xuống.
s1 = Range("A3") & Range("B3") & Range("C3")
s2 = Range("A3") & Range("C3") & Range("B3")
u1 = Range("F3") & Range("G3") & Range("H3")

Như vậy thay vì so sánh 12 chuỗi ký tự với nhau ta giảm được chỉ còn hai phép so sánh sủ dụng 3 chuỗi ký tự s1,s2,u1:
Mã:
if s1 = u1 or s2 = u1 then
end if
Đấy, thấy chưa, ban đầu cứ nghĩ như thế nào code thế, nhưng cái nghĩ ấy phải là logic toán, rồi sau đó rút gọn xuống. Còn cái mà các bạn đâm ngang, vừa bắt đầu học, vì quen sử dụng hàm, nên cách nghĩ cũng là hàm, giờ muốn dùng Vlookup thì VBA như thế nào nhỉ, muốn Find thì VBA như thế nào nhỉ, cứ như thế, các bạn không có được các logic cơ bản giống như cộng trừ nhân chia là cái cơ bản khi học toán, thì code VBA nên bắt đầu từ logic trước.
Người này người kia bảo sao không dùng cái này cái kia, kệ người ta. Đó là việc mà các bạn chỉ nên quan tâm khi tự mình code tất cả mọi thứ mà mình muốn (không quan tâm nhanh chậm), rồi sau đó mới nghĩ việc cải thiện tốc độ. Mọi thứ phải từng bước từng bước chứ.
 
H

Hồng Phương

Guest
Hi hi ,,, Thế thì em viết như này có đúng không hở anh @Eluer
Dim s1= Range("A3:C3")
Dim s2= Range("A3:B3")
Dim u1= Range("F3:G3")
 

Euler

Administrator
Thành viên BQT
Hi hi ,,, Thế thì em viết như này có đúng không hở anh @Eluer
Không được. Em thử mà xem.
Bạn cần đăng nhập để thấy hình ảnh


Mấy cái s1,s2,u1 khai báo là string.
Thay vì phải so sánh nhiều chuỗi ký tự, mình ghép mấy cái vào thành một chuỗi. Rồi bê đi so sánh. Như thế thì không phải so sánh lần lượt từng cells với nhau, mệt.
 
H

Hồng Phương

Guest
Em vẫn không hiểu anh @Euler oi, anh chỉ dẫn cụ thể đi anh!
 

Euler

Administrator
Thành viên BQT
Thì viết như anh đó:
Mã:
s1 = Range("A3") & Range("B3") & Range("C3")
Đây là lệnh nối các chuỗi lại với nhau đấy. nó sẽ ra s1 = CongHoaXa
Mà hôm nay luyện công chém gió đến đây thôi. Anh đi ngủ, mai lại tán phét tiếp. :devilish:
 
H

Hồng Phương

Guest
À em tưởng anh gom tất cả các ô vào thành 1
Thế thì vẫn phải viết
s1 = Range("A3") & Range("B3") & Range("C3")
 

Euler

Administrator
Thành viên BQT
À em tưởng anh gom tất cả các ô vào thành 1
Thế thì vẫn phải viết
s1 = Range("A3") & Range("B3") & Range("C3")
Viết thế vẫn nhàn hơn and or đấy. Mà tốc độ nhanh hơn cái đống loằng ngoằng trên kia đấy. Anh chưa viết thành chuyên đề nên không cho được vào box học thuật thôi. Đừng tưởng anh viết ở trà đá vỉa hè là không có chuyên môn gì nhé. :cool:
 
H

Hồng Phương

Guest
Anh @Euler sao anh không viết là
s1 = Range("A3,B3,C3")
cho nó ngắn gọn hơn hở anh?
 
H

Hồng Phương

Guest
Anh @Euler em không cần VBA của anh làm gì cho nặng máy, em chỉ cấn 2 hàm nay thôi
ConcateNate
EXACT(Text1, Text2)
thế là xong
 
S

Snow24

Guest
@Euler Theo bạn nếu dữ liệu nó như thế này thì có đúng không.
Bạn cần đăng nhập để thấy đa phương tiện
 

Euler

Administrator
Thành viên BQT
chỉ cấn 2 hàm nay thôi
ConcateNate
EXACT(Text1, Text2)
thế là xong
Mình chẳng hiểu bạn đang nói gì, nếu bạn đang nói nối hai chuỗi thì mình cũng không hiểu.
Nếu bạn nói nó giúp so sánh hai vùng Range có logic đan chéo như mô tả ở bài viết trước, thì mình cũng không hiểu dùng như thế nào.
 

Euler

Administrator
Thành viên BQT
@Euler Theo bạn nếu dữ liệu nó như thế này thì có đúng không.
Bạn cần đăng nhập để thấy đa phương tiện
Đây là một phản biện tốt, trong bài toán thực tế thì nó không có dữ liệu như vậy, cho nên phản biện trên có thể bỏ qua.
Nói qua về bài toán thực tế một chút, tại sao lại có cái logic đảo chiều như trên.
Một tuyến đường (hoặc dây điện) thì có điểm đầu và điểm cuối.
Thông tin điểm đầu và điểm cuối có thể đảo vị trí.
Bằng cách nối chuỗi như đã nói ở trên thì phép so sánh sẽ được giảm đi, và việc thực thi cũng nhanh hơn.
Áp dụng suy nghĩ ấy, bạn hãy tự đánh giá dữ liệu của mình có thể làm được việc đó hay không trước khi nêu câu hỏi. Nếu dữ liệu của bạn nhất định là những chữ cái tủn mủn mà khi ghép lại có thể phát sinh trùng ý nghĩa với một trường dữ liệu riêng biệt thì bạn hãy từ bỏ phương án này.
Bổ sung:
Hoặc bạn có thể thực thi nối chuỗi đi kèm ký tự đặc biệt mà bạn chắc chắn rằng nó sẽ không xuất hiện trên dữ liệu.
Ví dụ: thay vì: abcdef thì là ab#cd#ef (nếu như # không bao giờ có trên bảng dữ liệu, cái này thì tùy mỗi người nhìn nhận dữ liệu của mình)=> dấu # hình như bạn rất hay dùng :)
 

tuhocvba

Administrator
Thành viên BQT
Tìm ra chuỗi ký tự mà không có trên bảng dữ liệu của mọi người thì đơn giản thôi. Cứ thêm "tuhocvba.net" vào:
Vậy: ab cd ef sẽ thành: abtuhocvba.netcdtuhocvba.neteftuhocvba.net
a bcd ef sẽ thành:
atuhocvba.netbcdtuhocvba.neteftuhocvba.net
Đấy, bây giờ thì mang so sánh với nhau tẹt đi.
Tôi đảm bảo không có ông nào xây dựng dữ liệu mà lại có tên domain của diễn đàn ta.
 

Euler

Administrator
Thành viên BQT
Vâng, cách nghĩ là sử dụng ký tự mà nó không có trên bảng dữ liệu khi ghép các ký tự thành một chuỗi. Nếu ký tự này có xuất hiện trên bảng dữ liệu, thì có khả năng hoạt động không đúng ý đồ người code.
Vì vậy, nếu tự ý thêm # vào, thì cách làm việc đúng là: Xác nhận với người yêu cầu, data của anh, ở vùng này có sử dụng ký tự # hay không?
Để đảm bảo không có trên vùng dữ liệu, mà lại đỡ mất công xác nhận, thì cứ dùng domain của diễn đàn khi code, đúng là đảm bảo khỏi trùng luôn.

@Hồng Phương : Cách thảo luận học thuật của em, anh có cảm giác cách nói chuyện như là muốn truyền đạt cho đối phương biết, tôi là người có kiến thức. Thật ra có kiến thức hay không, không phải là đưa ra khái niệm cao siêu dọa dẫm người khác, hay tỏ vẻ mình cũng biết nhiều, mà là nói ra mà ai cũng hiểu được mình đang nói cái gì. Có nghĩa là mình phải hiểu sâu, hiểu tường tận thì mới truyền đạt được như vậy. Cái nói ra không nhất thiết phải cao siêu hào nhoáng. Anh biết một số diễn đàn đi theo phong cách thảo luận như thế. Và mong muốn, em không vác cái cách thảo luận đó về đây. Như vậy thì anh em mình mới thảo luận vui vẻ được.
 
H

Hồng Phương

Guest
@Hồng Phương : Cách thảo luận học thuật của em, anh có cảm giác cách nói chuyện như là muốn truyền đạt cho đối phương biết, tôi là người có kiến thức. Thật ra có kiến thức hay không, không phải là đưa ra khái niệm cao siêu dọa dẫm người khác, hay tỏ vẻ mình cũng biết nhiều, mà là nói ra mà ai cũng hiểu được mình đang nói cái gì. Có nghĩa là mình phải hiểu sâu, hiểu tường tận thì mới truyền đạt được như vậy. Cái nói ra không nhất thiết phải cao siêu hào nhoáng. Anh biết một số diễn đàn đi theo phong cách thảo luận như thế. Và mong muốn, em không vác cái cách thảo luận đó về đây. Như vậy thì anh em mình mới thảo luận vui vẻ được.

Em cảm ơn các anh chị trên diễn đàn
tuy rằng diễn đàn mới hoạt động đ]ợc mấy tháng, nhưng em thấy các anh chị rất nhiệt tình PHỔ BIẾN KIẾN THỨC CHO MỌ NGƯỜI.
Bởi vì mới hoạt động thì chưa được sôi nổi
Vậy cần có những câu hỏi và......
Có những bài toán cụ thể để giải quyết
Em cảm ơn các anh chị
 
Top