Các bước trưởng thành của người code VBA

BKKBG

Yêu THVBA nhất
Không có gì, cảm ơn bạn Euler đã lập topic này.
Topic bắt đầu có giá trị thảo luận từ khi bạn tái hiện lại lỗi, từ đó mọi người có cơ sở tìm hiểu một cách đúng đắn.

Dựa vào quá trình hoạt động trên diễn đàn, một nickname sau một quá trình tham gia sẽ xây dựng nên thương hiệu, có tiếng nói. Tôi từng gặp những nick như vậy, họ thường đưa ra các kết luận không có căn cứ. Nếu người khác có đóng góp ý kiến thì họ nhảy dựng lên phản ứng.
Tôi mừng là THVBA là một diễn đàn coi chứng cứ, lý lẽ là cơ sở để thảo luận. Một nickname có nhiều đóng góp như bạn có thể dõng dạc: Tôi sai rồi-Tôi hiểu rồi. Và biết nói Cảm ơn khi được góp ý. Đó chẳng phải là cảnh giới cao nhất của một người trưởng thành khi học VBA hay sao? Làm gì có ai là biết hết, giỏi hết mà không sai.
 

Euler

Administrator
Thành viên BQT
Nguy hiểm thật. Có cách nào để kiểm soát cái này khi gõ code không nhỉ. Dù đầu nhận thức đúng, nhưng gõ code thì vẫn bị vậy.
Mã:
Sub Euler2()
    Dim rend As Long
    Dim arr
  
    Workbooks("book3").Sheets(1).Activate 'Kich hoat mot workbook khong lien quan
    With Workbooks("book1").Sheets(1)
        rend = .Cells(.Rows.Count, 1).End(xlUp).Row
        arr = .Range(.Cells(1, 1), .Cells(rend, 1)).Value
    End With
    
    With Workbooks("book2").Sheets(1)
        .Range(.Cells(1, 1), .Cells(rend, 1)).Value = arr
    End With
    
End Sub
Đã thêm .Rows
 

NhanSu

SMod
Thành viên BQT
Ngay khi mở workbook lên ta xác định dòng cuối và lấy dữ liệu luôn, lúc đó workbook mới mở là activeworkbook. Sau khi có dòng cuối rồi thì ta copy hoặc làm gì đó dựa vào with... end with hoặc activate cũng được.
 

PTHhn

Yêu THVBA như điếu đổ
Ngay khi mở workbook lên ta xác định dòng cuối và lấy dữ liệu luôn
Cách này chỉ đúng nếu workbook đó có 1 sheet dữ liệu. Nếu có 10 sheet dữ liệu thì không đúng.
Tôi nghĩ chắc ăn thì cứ làm như bạn Euler thôi:
workbooks("Name").sheets("Name").activate

Gõ code sai ý đồ nhưng không có cảnh báo lỗi nên rất nguy hiểm. Đối với code ngắn thì không sao, code dài rồi dò lỗi thì cũng mệt. Nếu nhiều người làm việc cùng nhau, chỉ một người sai sẽ ảnh hưởng tới output chung. Cách đơn giản nhất, và áp dụng cho tất cả mọi người, dù là người cẩn thận hay người không cẩn thận, người có kinh nghiệm hay ít kinh nghiệm, là bắt buộc họ thực thi activate với đối tượng muốn làm việc.

Nếu chỉ hết 0.08s như kiểm chứng, thì không là vấn đề.
 

NhanSu

SMod
Thành viên BQT
Nếu làm việc nhóm thì càng không nên activate, lý do mỗi người luôn nghĩ rằng mình activate sheet của mình rồi nên không cần kiểm tra nữa trong khi thực tế người khác đã chuyển về workbook và sheet của họ. Ví dụ anh A viết thủ tục X, anh B viết hàm Y. Hàm Y lấy dữ liệu A1:A10 book2 vào mảng. thủ tục X activate book1 rồi gọi hàm Y và copy mảng kết quả vào book1. Tuy nhiên sau khi gọi hàm Y thì book2 trở thành active nên thủ tục X chạy không đúng nữa. Vì vậy khi làm việc nhóm càng cần thiết chỉ định rõ workbook nào, sheet nào.
Mã:
Sub X()
dim arr()
Workbooks("book1").Activate
arr= Y()
range("A1:A10")=arr
End Sub
Function Y()
dim arr()
Workbooks("book2").sheets(1).Activate
arr=range("A1:A10").value
Y=arr
End Function
 
Sửa lần cuối:

tuhocvba

Administrator
Thành viên BQT
Nếu làm việc nhóm thì càng không nên activate, lý do mỗi người luôn nghĩ rằng mình activate sheet của mình rồi nên không cần kiểm tra nữa trong khi thực tế người khác đã chuyển về workbook và sheet của họ.
Không biết các bạn đang làm việc ra sao. Mình chia sẻ một chút thông tin của mình nhé.
Công việc theo nhóm sẽ có:
1 trưởng nhóm & các bạn khác.

Bước 1: Thảo luận các bước code cần thiết. Các bạn đưa ra ý kiến.
Bước 2: Thảo luận thiết kế với người yêu cầu code. Họ đồng ý thì tiến hành code.
Bước 3: Trưởng nhóm chia việc.
Ví dụ, yêu cầu code là, chúng ta có một thư mục bên trong có rất nhiều file code .c
Nhiệm vụ tổng hợp có bao nhiêu function, bao nhiêu biến số global, bao nhiêu hằng số, bao nhiêu biến static.

Người 1: Làm nhiệm vụ đọc file .c bất kỳ, tham số truyền vào là link lk của file .c, trả ra là wbname, shname.
Ngươi 2 làm nhiệm vụ đọc lấy các function.
Sub layfunction(byval wbname as string, shname as string)
Tại đây, anh ta phải kích hoạt wbname và shname.
Giá trị tìm được sẽ ghi ra mảng, cấu trúc mảng theo thỏa thuận bàn giao trước đó, mảng được khai báo public, công khai tên mảng cho cả nhóm.

Người 3 làm nhiệm vụ đọc lấy các hằng số.
...

Người n: Làm nhiệ vụ hợp code. Anh này chính là trưởng nhóm. Sẽ code giao diện và code kiểm tra input đầu vào. Và code gọi các thủ tục của những người trên.

Bước 4: Chạy thử trong nhóm theo checklist (checklist này mọi người xây dựng và thảo luận đạt được nhất trí của bên yêu cầu code).
Bước 5: review với người yêu cầu. Nếu có phản hồi thì quay lại Bước 4. Nếu không có phản hồi thì kết thúc.

Tóm lại, người trưởng nhóm biết phải chia việc ra sao, mọi người code tuân thủ theo qui định chung.
 

Euler

Administrator
Thành viên BQT
Sau khi đã trình bày các mức độ , ta đi vào từng mốc cụ thể và các kiến thức nên có ở từng giai đoạn.
1. Với một sheet dữ liệu:
Ở giai đoạn này, tôi nghĩ logic, thuật toán là quan trọng nhất. Chúng ta cần rất ít công cụ hỗ trợ, tất nhiên nếu có nhiều công cụ hỗ trợ thì càng tốt, code sẽ ngắn đi và khoa học hơn, chạy nhanh hơn.
Đối với code VBA, chúng ta quan tâm nhất là đưa ra được output chính xác. Ở trình độ này, bạn cũng chưa cần quá quan tâm tới tốc độ thực thi chương trình.
Bạn cần đăng nhập để thấy hình ảnh

Tôi đã từng học ít nhất ba ngôn ngữ lập trình ở trường đại học (không có giỏi ngôn ngữ nào cả). Nhờ vậy mà tôi tiếp cận VBA rất tự nhiên.
Đối với các bạn lần đầu tiếp xúc với lập trình, có lẽ chúng ta cần phải xây dựng hệ thống bài tập để luyện tập logic và thuật toán.
Người ta thống kê rằng, lệnh For~Next là lệnh được dùng phổ biến nhất trong VBA. Ở trình độ này, bạn nên sử dụng For~Next thành thạo, từ đó mới có thể giải quyết các bài toán logic cơ bản (sắp xếp, viết số, tô màu vào cells...).

Tùy vào tính chất công việc mà yêu cầu đòi hỏi logic-thuật toán sẽ khác nhau. Đối với người chỉ làm việc với hóa đơn chứng từ, yêu cầu logic sẽ thấp hơn.
Đối với người làm việc kỹ thuật, file excel chứa nhiều thông tin kỹ thuật phải xử lý, yêu cầu logic sẽ cao hơn.

Ngay cả một người có ít kinh nghiệm VBA, chỉ với For~Next và If...then , anh ta đã có thể làm rất nhiều việc, chưa quan tâm chương trình chạy nhanh hay chậm ra sao. Vì vậy logic và thuật toán đóng vai trò quan trọng ở mọi cấp độ code. Bài toán giải được hay không sẽ phụ thuộc vào điều này.

Dictionary không phải là thuật toán hay logic, nó chỉ là phương tiện để chúng ta làm việc. Không có nó, chúng ta vẫn giải quyết được bài toán. Nhưng có nó, xử lý sẽ gọn gàng hơn, đỡ mất thời gian code, tốc độ thực thi chương trình cũng nhanh hơn. Vì vậy, ở cấp độ này, tôi khuyên mọi người nên có thêm kiến thức về Dictionary.
Tương tự như vậy, mảng (array) không phải là thuật toán hay logic, không có nó, chúng ta vẫn giải quyết được bài toán. Nhưng có nó thì sẽ giúp chúng ta code dễ dàng hơn, tốc độ thực thi chương trình nhanh hơn. Ở cấp độ này, tôi cũng khuyên mọi người có kiến thức về mảng.

Tùy vào các vấn đề mà bạn thường gặp trong công việc mà các hàm VBA được quan tâm sẽ khác nhau. Nhưng nói tới Excel thì chúng ta nói tới dữ liệu. Nói tới dữ liệu chúng ta có ký tự và số và thậm chí ngày tháng.
Trước hết nói tới ký tự, các bạn cần phải làm quen với các hàm thông dụng trong xử lý ký tự như Instr, InstrRev, Left, Right, Mid, UCase, LCase.

Ở cấp độ này, điều các bạn quan tâm là logic, là thuật toán. Thế nhưng khi thực hiện hỏi đáp trên diễn đàn, hét vào tai bạn sẽ là: hãy dùng mảng, hãy dùng dictionary,... Những điều đó không sai, nhưng đôi khi code với Range, với cells còn là để các bạn dễ hình dung, hiểu là mình đang thao tác với cái gì, logic của lời giải là trình tự thao tác như thế nào...
Đã lơ tơ mơ, còn chưa hiểu phải giải ra sao, lúc này người khác đưa cho bạn lời giải là dictionary, array... Bạn càng nhìn vào càng không hiểu gì, vậy là những hỏi đáp trên diễn đàn có chung một kết quả, bạn copy và sử dụng nhưng không hiểu gì.

Bên cạnh trau dồi khả năng tìm lời giải (thuật toán, logic), có một khía cạnh nữa của sự trưởng thành, đó là xử lý lỗi.
Bạn cần đăng nhập để thấy hình ảnh

(Khối màu xanh biểu thị tích lũy kinh nghiệm, sao màu đỏ biểu thị lỗi xảy ra)

Hiếm có ai học VBA mà lại học bài bản lỗi này là gì. Trong tình huống này có thể xảy ra lỗi nào... Thông thường đó là quá trình tích lũy của mỗi người. Khi gặp tình huống lỗi phát sinh mới đi tìm lời giải, tại sao lại bị lỗi, khắc phục như thế nào? Quá trình này cứ tích lũy dần dần, vì vậy cùng với thời gian, người có nhiều năm kinh nghiệm, người chịu khó code, sẽ là người có nhiều vốn tích lũy nhất.

Bạn nên tận dụng diễn đàn là nơi trao đổi lỗi mà bạn gặp, hỏi mọi người cách khắc phục.
Mọi người tham gia diễn đàn cũng nên chia sẻ kinh nghiệm mà mình đã gặp nhiều hơn.
 

Euler

Administrator
Thành viên BQT
2. Với nhiều sheet dữ liệu
Bạn cần đăng nhập để thấy hình ảnh

So với input là một sheet dữ liệu thì bài toán nhiều sheet dữ liệu sẽ có một chút rắc rối sau.
Dữ liệu kiểu này không phải là file do máy xuất ra. Một số phần mềm chuyên dụng tạo ra file csv hay Excel thì chúng đều chỉ có một sheet dữ liệu. Dữ liệu như vậy đều có định dạng (format, cấu trúc dữ liệu) rất chuẩn. Người code hầu như không phải tốn công tốn sức kiểm tra input đầu vào.
Tuy nhiên với dữ liêu kiểu nhiều sheet, chúng phần lớn là các file do ai đó tạo ra và nhập dữ liệu bằng tay. Có nghĩa là dữ liệu không chuẩn. Người code rất tốn công sức kiểm tra input đầu vào.

-Vị trí dòng hay cột đã chuẩn chưa. Để kiểm tra điều này, cần phải định nghĩa được từ khóa cần kiểm tra. Nếu không phát hiện thấy từ khóa thì đưa ra cảnh báo định dạng dữ liệu không tốt, người dùng cần kiểm tra lại.
Ở đây có hai cách nghĩ, ngay khi tìm thấy điểm mâu thuẫn phải đưa ra cảnh báo và dừng chương trình và đưa ra cảnh báo.
Hoặc là cứ kiểm tra hết đi rồi sau đó ra thông báo bằng một danh sách các lỗi.

Tất nhiên thoạt nghe, chúng ta sẽ thấy, nếu đưa ra thông báo băgf một danh sách các lỗi thì thích biết bao. Nhưng việc này không phải lúc nào cũng thực hiện được.
Bạn cần đăng nhập để thấy đính kèm

Nếu các keyword là ngang hàng nhau thì ta sẽ tiến hành làm theo cách này. Kiểm tra tất cả các Keyword rồi ra thông báo bằng danh sách lỗi. Tất nhiên, nếu yêu cầu không cao, cứ thấy lỗi ở đâu thì ra cảnh báo ở đó và dừng hẳn-điều đó rất thuận lợi cho người code. Các hỏi đáp trên các diễn đàn nếu hỗ trợ code cũng sẽ đi theo hướng này, giảm thiểu thời gian code. Thậm chí người code còn chẳng kiểm tra điều kiện đầu vào, mặc định input đúng, đi vào logic chính.

Sự việc sẽ phức tạp hơn nếu các Keyword liên quan tới nhau.
Bạn cần đăng nhập để thấy đính kèm

Lúc này, thiết kế phổ biến là chỉ cần phát hiện ra lỗi là lập tức ra cảnh báo rồi dừng luôn. Các Keyword phía sau không cần kiểm tra nữa, chương trình dừng ngay lập tức để đưa ra cảnh báo và dừng hẳn sau đó.

Sự việc sẽ còn phức tạp nếu các sheet có cấu trúc không giống nhau. Đối với cấu trúc các sheet giống nhau thì thật thuận tiện. Ví dụ sheet1 là dữ liệu của tháng 1, sheet 2 là dữ liệu của tháng 2,.. Như thế thì việc code không có gì phức tạp lắm.

Các kiến thức bạn cần có là: Dictionary, mảng, phương thức Find.
Tôi phải đặc biệt lưu ý, khi làm việc với nhiều sheet dữ liệu, lúc này mảng không còn là kiến thức khuyến khích nữa mà là bắt buộc. Nếu không xử lý bằng mảng, chương trình của bạn có thể chạy rất chậm.
Ngoài ra còn phải kể tới một công cụ đắc lực là Dictionary.
Tôi nghĩ Dictionary, mảng là hai công cụ chính khi làm việc với nhiều sheet dữ liệu, hay thậm chí nhiều file dữ liệu.
Với nhiều người còn quen thao tác bằng tay với Excel, khi viết code, họ đơn thuần là chuyển hóa cách nghĩ từ làm bằng tay sang làm bằng macro, vì vậy phương thức Find là cần thiết. Nhưng với những người code có kinh nghiệm, sử dụng Find có lẽ là không cần thiết, trừ trường hợp bạn không biết chính xác từ khóa cần tìm kiếm nằm ở nơi nào trên sheet. Find là công cụ đắc lực tìm vị trí từ khóa nằm ở dòng nào, cột nào...

Sự việc sẽ phức tạp hơn nếu mỗi sheet là một kiểu dữ liệu có cấu trúc khác nhau.
Bạn cần đăng nhập để thấy đính kèm

Keyword trên mỗi sheet cũng khác nhau. Việc kiểm tra input đầu vào sẽ phức tạp hơn.

Tóm lại ở cấp độ này đòi hỏi người code cần có tối thiểu các kiến thức về:
-Mảng
-Dictionary
-Phương thức Find
-Thiết kế chương trình, kiểm tra input đầu vào
-Biết tạo ra workbook mới (hoặc file txt) lưu thông tin danh sách lỗi
-Biết tạo manual cho chương trình và checklist cho input đầu vào.

Việc kiểm tra input đầu vào và đưa ra cảnh báo cho người dùng là việc rất quan trọng. Chương trình có thân thiện hay không chính là ở điểm này.
Nếu mới code, phần lớn mọi người đều nhanh nhanh chóng chóng ra một thông báo là:
Mã:
Msgbox "Khong tim thay du lieu"
Nếu cẩn thận hơn, lý do không tìm thấy dữ liệu là gì:
Mã:
Msgbox "Khong tim thay du lieu vi khong tim thay " & keyword
Trong trường hợp đưa ra danh sách lỗi, bạn lại cần biết tạo ra file txt như thế nào và ghi thông tin lên đó ra sao. Với những người chưa quen thì nhanh nhất là cứ sử dụng môi trường Excel, tôi sẽ tạo ra một workbook mới và ghi danh sách lỗi vào đó.
Dự án hỗ trợ số 01 phải tạo ra rất nhiều file log (file ghi danh sách lỗi), mất rất nhiều thời gian. Dù đây không phải là yêu cầu của người cần hỗ trợ code, nhưng trong khi thảo luận thiết kế, admin tuhocvba đã tư vấn và đạt được nhất trí, sau đó code đi theo hướng này.

Một điểm nữa, vì dữ liệu input được nhập bằng tay. Nếu không có hướng dẫn sử dụng, đôi khi nhận được thông báo lỗi mà người dùng vẫn chẳng hiểu tại sao sai, tại sao chương trình không chạy được. Lý do này nghĩa là gì ấy nhỉ? Vì vậy, tạo ra manual hướng dẫn sử dụng là cần thiết. Thậm chí là bản checlist để người dùng sử dụng và tự check dữ liệu bằng tay trước khi chạy chương trình macro. Nghe qua thì thấy ôi sao tốn công tốn sức thế, nhưng nếu cần thiết thì cũng phải làm, nó đảm bảo macro đưa ra output chính xác 100%. Nếu sai hay không chạy thì ít nhất người dùng phải lý giải được lý do mà macro đưa ra và biết khắc phục.
Đây là giai đoạn bạn bắt đầu làm quen với thiết kế, trong đó trọng tâm là kiểm tra input đầu vào.
 

Euler

Administrator
Thành viên BQT
3. Với nhiều file dữ liệu
Vì phải làm việc với nhiều file cho nên công cụ không thể thiếu là FSO.
Phải làm việc với file .txt, file .c, .csv,... hay đơn thuần là file Excel? Mỗi trường hợp lại có cách xử lý khác nhau.
Việc tạo ra file output, nếu đơn thuần là Output Excel thì ở trình độ này cũng tương đương với trình độ trước. Kiến thức tập trung vào mảng, Dictionary, Find.
Việc tạo ra file output là các file có định dạng đặc biệt, chẳng hạn .txt, .dbc, .c thì có một chú ý khi sử dụng FSO đó là đừng cố gắng lưu file dưới dạng Unicode.
Không có cuốn sách nào dạy chúng ta nên làm như thế nào, nên xử lý ra sao, tôi chỉ có thể nói rằng, bạn càng va chạm nhiều, gặp nhiều vấn đề phải giải quyết thì kinh nghiệm cũng nhiều hơn.
Về mặt lý thuyết, nếu bạn hỏi, cần phải có kiến thức nào, câu trả lời là FSO.

Như vậy, tôi đã dựa vào kinh nghiệm bản thân, để chỉ ra các kiến thức cần có đối với từng cấp độ. Tất nhiên chúng ta còn nhiều thứ khác cần biết, nhưng những thứ tôi đã nói nó là xương sống. Nếu trình bày quá chi tiết e rằng sẽ rất dài, mà tôi cũng không đủ sức để làm tới mức như thế.

Tôi hi vọng các bạn đã hình dung ra con đường mình sẽ đi, hi vọng những chia sẻ trong topic này có ích cho các bạn.
 
Top