Được thôi (chỉ sợ ít người thích nghe)
1> Thứ nhất: Ngay từ đầu đọc code là tôi đã thấy khá lằng nhằng về cách đặt tên biến khiến tôi biết đường nào mà lần
Tên biến cũng có quy định ngầm thế này: tiền tố đầu (từ 1 đến 3 ký tự) mô tả kiểu biến và luôn luôn viết thường, các ký tự sau đó mô tả công dụng của biến với ký tự đầu (hoặc vài ký tự sau đó) được viết hoa. Ví dụ:
wksMain ---> Biết ngay biến này là kiểu worksheet, có tên là Main hoặc có công dụng như một sheet chính lR hoặc lRow ---> Biến kiểu long, mô tả về chỉ số dòng aSource hoặc arrSource ---> biến Array mô tả vùng dữ liệu nguồn
vân vân....
2> Thứ hai: Nói về phép so sánh chuỗi: If NS <> TEN0 đây là phép so sánh rất chủ quan, bởi nếu đổi tên sheet thành TONGHOP thì phát biểu IF kia sẽ cho kết quả FALSE mà ta chưa chắc biết lý do tại sao. Cách an toàn là dùng UCase hoặc LCase
Mã:
Const TEN0 = "TONGHOP"
.......
If UCase(NS) <> TEN0 then
Ngoài ra, để chắc ăn cho người chạy code với bất cứ sự thay đổi tên sheet nào, ta nên vẽ 1 button lên sheet tổng hợp, chạy code thông qua button thì sẽ khỏi chạy đâu sai cả (vân vân.. và nhiều cách khác)
3> Thứ ba: kMax = UBound(tmp, 2) trong khi tmp = ws.Range("E10:AW" & z).Value2 là vùng cố định từ cột E đến AW ---> Suy ra kMax này ta luôn luôn biết trước là bao nhiêu cột rồi, vậy tại sao lại đưa vào vòng lập để tính toán?
----------------------------------
Vài góp ý nhỏ. Nhìn chung là code ổn nhưng tôi vẫn không thích tí nào về cách đặt tên biến của code này (chóng mặt, khó dò tìm...). Và cũng bởi chóng mặt, khó tìm nên nếu ai đó muốn sửa code thì chắc người ta thà viết lại từ đâu cho khỏe
Có lẽ do thói quen đặt tên biến của mỗi người, ai đặt nấy hiểu, nấy nhớ. Ví dụ biến T, biến z ...
Cũng tương tự hoạt động của code trên, nhưng nếu đặt tên biến kiểu khác có lẽ dễ "đọc" hơn một chút:
I, J, K là các biến "chạy".
Rws, hay R có thể nghĩ đến "dòng"
sArr : mảng nguồn, dArr: Mảng đích (kết quả)
FileName: Tên File......
PHP:
Public Sub GPE()Const TONGHOP As String = "Tonghop"Dim Ws As Worksheet, sArr(), dArr(1 To 50000, 1 To 50)Dim Rws As Long, I As Long, J As Long, K As Long, R As LongDim FileName As String, ShName As String, MaSheet As String, TenSheet As StringFileName = Left(ThisWorkbook.Name, InStr(ThisWorkbook.Name, ".") - 1)For Each Ws In ThisWorkbook.Worksheets If Ws.Name <> TONGHOP Then With Ws R = .Range("I1000000").End(xlUp).Row If R > 9 Then ShName = .Name: MaSheet = .Range("K6").Value: TenSheet = .Range("K7").Value sArr = .Range("E10:E" & R).Resize(, 45).Value: Rws = UBound(sArr) For I = 1 To Rws If sArr(I, 5) <> Empty Then K = K + 1 dArr(K, 1) = FileName: dArr(K, 2) = ShName dArr(K, 3) = MaSheet: dArr(K, 4) = TenSheet For J = 1 To 45 dArr(K, J + 5) = sArr(I, J) Next J End If Next I End If End With End IfNext WsWith Sheets(TONGHOP) .Range("B5").Resize(50000, 50).ClearContents .Range("B5").Resize(K, 50) = dArrEnd WithEnd Sub
Cảm ơn Ba Tê đã giúp tôi có thêm 1 sự lựa chọn và 1 cách để giúp tôi tiếp cận với code.
Tôi đã chạy thử code trên của bạn,kết quả cũng giống như code của bạn befaint (đúng với với mong muốn của tôi)
Nhìn qua code của bạn và befaint không gì khác nhau nhiều về thuật toán ?
Nhưng code của bạn tốc độ có phần nhanh hơn của bạn befaint 1 chút.
Tôi sẽ cố gắng dành thời gian tìm hiểu thêm vì sao lại như vậy.
Nếu gì vướng mắc mong lại được các bạn giúp đỡ.
Được thôi (chỉ sợ ít người thích nghe)
1> Thứ nhất: Ngay từ đầu đọc code là tôi đã thấy khá lằng nhằng về cách đặt tên biến khiến tôi biết đường nào mà lần
Tên biến cũng có quy định ngầm thế này: tiền tố đầu (từ 1 đến 3 ký tự) mô tả kiểu biến và luôn luôn viết thường, các ký tự sau đó mô tả công dụng của biến với ký tự đầu (hoặc vài ký tự sau đó) được viết hoa. Ví dụ:
wksMain ---> Biết ngay biến này là kiểu worksheet, có tên là Main hoặc có công dụng như một sheet chính
lR hoặc lRow ---> Biến kiểu long, mô tả về chỉ số dòng
aSource hoặc arrSource ---> biến Array mô tả vùng dữ liệu nguồn
vân vân....
2> Thứ hai: Nói về phép so sánh chuỗi: If NS <> TEN0 đây là phép so sánh rất chủ quan, bởi nếu đổi tên sheet thành TONGHOP thì phát biểu IF kia sẽ cho kết quả FALSE mà ta chưa chắc biết lý do tại sao. Cách an toàn là dùng UCase hoặc LCase
Mã:
Const TEN0 = "TONGHOP"
.......
If UCase(NS) <> TEN0 then
Ngoài ra, để chắc ăn cho người chạy code với bất cứ sự thay đổi tên sheet nào, ta nên vẽ 1 button lên sheet tổng hợp, chạy code thông qua button thì sẽ khỏi chạy đâu sai cả (vân vân.. và nhiều cách khác)
3> Thứ ba: kMax = UBound(tmp, 2) trong khi tmp = ws.Range("E10:AW" & z).Value2 là vùng cố định từ cột E đến AW ---> Suy ra kMax này ta luôn luôn biết trước là bao nhiêu cột rồi, vậy tại sao lại đưa vào vòng lập để tính toán?
----------------------------------
Vài góp ý nhỏ. Nhìn chung là code ổn nhưng tôi vẫn không thích tí nào về cách đặt tên biến của code này (chóng mặt, khó dò tìm...). Và cũng bởi chóng mặt, khó tìm nên nếu ai đó muốn sửa code thì chắc người ta thà viết lại từ đâu cho khỏe
Cảm ơn ndu96081631, đã chỉ dẫn.
Tôi là người hỏi nên chắc chắn sẽ tôi là người thích nghe,như vậy là đủ phải không bạn?
Nên bạn không phải lo sợ đâu ạ , tôi đang chưa có kiến thức gì về code, chưa thể nhìn nhận và tự giải quyết được các vấn đề liên quan đến code nên có có ý muốn học hỏi dần dần. Trong quá trình tiếp cận khó có thể tránh khỏi những câu hỏi ngớ ngẩn, vì thế tôi rất mong các bạn chỉ dẫn và góp ý nếu nhìn thấy vấn đề ...
2.Bạn có thể giải thích thêm dòng này được không ạ:
Ngoài ra, để chắc ăn cho người chạy code với bất cứ sự thay đổi tên sheet nào, ta nên vẽ 1 button lên sheet tổng hợp, chạy code thông qua button thì sẽ khỏi chạy đâu sai cả (vân vân.. và nhiều cách khác)
Việc chạy code thông qua button trên sheet"Tonghop" và chạy Sub trực tiếp trong cửa sổ soạn thảo code thì có gì khác nhau vậy, ý tôi muốn hỏi là chạy "code thông qua button thì sẽ khỏi chạy đâu sai cả..." là để có thể kiểm soá dễ dàng phát hiện được sự sai lệch?
Việc chạy code thông qua button trên sheet"Tonghop" và chạy Sub trực tiếp trong cửa sổ soạn thảo code thì có gì khác nhau vậy, ý tôi muốn hỏi là chạy "code thông qua button thì sẽ khỏi chạy đâu sai cả..." là để có thể kiểm soá dễ dàng phát hiện được sự sai lệch?
Trong cửa sổ vba mà chạy đoạn trên thì cứ sheet (xét cả workbook) nào được active (hiện hành) thì gán A1=1
Để chắc ăn thì gán nó vào cái nút ở sheet chỉ định cần chạy sub trên thì chỉ định gán A1=1 ở sheet có nút đó.
Hoặc viết chỉ định đích danh workbook.worksheet.range/cell
Mã:
Sub vidu()
Thisworkbook.sheets(1).range("A1")=1
End sub
thì không quan tâm sheet nào đang active, khi chạy đoạn đó trong cửa sổ vba đều chỉ gán A1=1 ở sheets(1) của workbook hiện hành.
Việc chạy code thông qua button trên sheet"Tonghop" và chạy Sub trực tiếp trong cửa sổ soạn thảo code thì có gì khác nhau vậy, ý tôi muốn hỏi là chạy "code thông qua button thì sẽ khỏi chạy đâu sai cả..." là để có thể kiểm soá dễ dàng phát hiện được sự sai lệch?
Bởi Button nằm tại sheet Tonghop nên đương nhiên bạn phải "đứng" tại sheet Tonghop mới chạy được. Và người ta sẽ có cách viết code đại khái thế này: Sheet nào có chứa cái Button thì sheet đó chính là sheet Tonghop (cho dù nó hổng phải tên Tonghop cũng không sao) và code bắt buộc phải chạy thông qua button chứ không thể chạy từ cửa sổ VBA
Như vậy sẽ rất là.. ổn
--------------------------------
Với bạn hoặc những ai mới bắt đầu với lập trình thì "nên thế nào cũng được" hoàn toàn không có vấn đề, miễn ra được kết quả là tốt rồi
Với rất nhiều thành viên am hiểu lập trình thì điều đó hoàn toàn không thể chấp nhận (trừ phi bạn đủ tài "chế" ra chuẩn mực mới khiến cả thế giới phải làm theo)
Nói nôm na như việc quản lý tại 1 cty: nếu mọi thứ đều tuân theo 1 chuẩn mực cho trước thì dễ quản lý hơn thay vì mạnh ai nấy làm theo ý mình, đúng không?
Xem chừng cũng hơi khó hiểu. Thôi thì thì làm cái thí nghiệm để minh họa nhé!
Đại khái code trong file đính kèm dưới đây sẽ lấy dữ liệu tại cell A1 của tất cả các sheet rồi đưa vào cột A của sheet hiện hành (sheet chứa button). Code chỉ chạy khi bạn nhấn vào button, ngoài ra cho dù bạn chạy code từ cửa sổ VBA hay nhấn Alt + F8 để chạy đều không được. Từ đây bất kể bạn dời sheet đi đâu hay đổi tên sheet thành thứ gì cũng được, miễn sheet đó có chứa cái Button thì code mới chạy
Mục đích của tôi là: định vị tên sheet Tonghop theo cách khác an toàn hơn
Ahihi!
Cảm ơn befaint , cảm ơn ndu96081631,
Đến giờ phút này, qua các ví dụ của 2 bạn tôi đã thấu được vấn đề:
"Việc chạy code thông qua button trên sheet"
-----------
Cứ tưởng học trên này không mất bất cứ 1 khoản phí nào.
Ai ngờ kết quả sau 1 buổi tìm hiểu về code thì đã mất 20k tiền mua "Panadol", chắc vấn đề này chưa dừng lại ở đây..
Nếu không có sự hỗ trợ chỉ dẫn tận tình của các bạn chắc tôi còn mệt dài và nặng gấp nhiều lần hơn thế.