Xin phép được nhắc đến bài "Tắt các chế độ cập nhật màn hình và các chế độ khác để tăng tốc thực hiện code" của levanduyet ở đây:
Diễn đàn > Lập trình với Excel > Excel và các ngôn ngữ lập trình khác > Thư viện mã lập trình
Trong bài này có nói đến hai hàm SpeedOn(...) và SpeedOff(). Mục đích của hàm thứ nhất là tắt một số chế độ trong lúc chạy đoạn code và sau khi chạy xong thì dùng hàm thứ hai mở ra trở lại.
Tôi không muốn bàn về code trong hàm. Tuy nhiên, người viết code không nói rõ về cách thức và trường hợp sử dụng cho nên tôi chú thêm để góp ý.
Theo nguyên tắc lập trình, khi phải dùng đến công cụ ảnh hưởng đến chế độ của ứng dụng (application, ở đây là Excel) người lập trình phải cẩn trọng bằng cách trả nó về tình trạng ban đầu sau khi đoạn code làm việc xong. Ở đây, đôi hàm này cũng làm theo nguyên tắc đó: hàm thứ nhất thay đổi chế độ và hàm thứ hai trả về chế độ ban đầu.
Điểm chủ quan của đôi hàm này là ở cụm từ "trạng thái/chế độ ban đầu". Làm sao biết thế nào là trạng thái ban đầu? Hàm thứ hai làm như vậy có bảo đảm là đúng không?
Xin trả lời: đối với project nhỏ thì được, nhưng gặp project lớn thỉ sẽ có vấn đề (project ở đây là VBAProject của Excel)
Ví dụ cụ thể: trong một module nào đó, ta có hàm A, bên trong hàm A, ta gọi hàm B. Để tăng tốc một đoạn code nào đó trong hàm A, ta gọi SpeedOn(), sau đó gọi SpeedOff(). Rất tiếc là nếu B cũng có gọi SpeedOn() và SpeedOff() thì SpeedOff() của B sẽ vô hiệu hóa SpeedOn() của A.
Trên thực tế, khi lập trình một project lớn, người ta không gọi hàm khơi khơi như vậy. Trước khi thay đổi trạng thái ứng dụng, người ta trữ lại trạng thái hiện hành và khi cần trả về thì trả về trạng thái này chứ không phải trạng thái mặc định như code trong hàm SpeedOff()
Làm thế nào để trữ lại trạng thái ban đầu? Dùng biến toàn cục? Xin thưa là không bởi vì chỉ cần một vài lần trữ không có ngăn xếp (stack) là sai bấy hết. Dùng biến cục bộ của hàm và truyền cho SpeedOn(), SpeedOff() qua tham số? Xin thưa là có tất cả 8 biến, nếu phải bảo trì thêm 8 biến này thì cũng hơi cực. Có thể giảm thiểu bằng cách dùng cấu trúc (type, tương tự như struct trong C)? Được nhưng vẫn còn hơi phiền phức và dễ bị lỗi (error prone).
Giải pháp người ta thường dùng là áp dụng đối tượng. Theo giải pháp này, người ta đặt ra một lớp (class module) – ví dụ SpeedOnOff. Trong lớp này, ta đặt 8 thuộc tính private để chứa tình trạng hiện hành (private vì bên ngoài không cần biết đến chúng). Lớp chứa hai hàm public SpeedOn() và SpeedOff(). Trước khi tắt chế độ màn hình, SpeedOn() ghi lại 8 thuộc tính hiện hành. SpeedOff() chỉ việc dùng các thuộc tính này để khôi phục lại chế độ ban đầu.
Cách dùng:
[code bình thường…]
Dim mySpeed As SpeedOnOff
Set mySpeed = New SpeedOnOff
mySpeed.SpeedOn ‘ tắt chế độ hiển thị màn hình
[code cần chạy nhanh]
mySpeed.SpeedOff ‘ trả về chế độ ban đầu
[code bình thường…]
Tương đối giản dị và an toàn.
Đối tượng gói kín thuộc tính (dữ liệu) riêng của nó nên không code nào chạm đến được ngoài cách gọi hàm SpeedOn()/SpeedOff(). Mỗi hàm module cần bật tắt màn hình đều phải tạo đối tượng riêng nên dữ liệu được bảo đảm.
(*) thành thật xin lỗi mọi người, tôi không được phép làm việc trong thư mục nói trên nên bắt buộc phải mở ở đây.
Ghi chú thêm: bạn nào đọc bài về lớp/class của NguenDuyTuan mà thấy khó hiểu thì cũng có thể coi đây là một ví dụ đơn giản ứng dụng class.
Diễn đàn > Lập trình với Excel > Excel và các ngôn ngữ lập trình khác > Thư viện mã lập trình
Trong bài này có nói đến hai hàm SpeedOn(...) và SpeedOff(). Mục đích của hàm thứ nhất là tắt một số chế độ trong lúc chạy đoạn code và sau khi chạy xong thì dùng hàm thứ hai mở ra trở lại.
Tôi không muốn bàn về code trong hàm. Tuy nhiên, người viết code không nói rõ về cách thức và trường hợp sử dụng cho nên tôi chú thêm để góp ý.
Theo nguyên tắc lập trình, khi phải dùng đến công cụ ảnh hưởng đến chế độ của ứng dụng (application, ở đây là Excel) người lập trình phải cẩn trọng bằng cách trả nó về tình trạng ban đầu sau khi đoạn code làm việc xong. Ở đây, đôi hàm này cũng làm theo nguyên tắc đó: hàm thứ nhất thay đổi chế độ và hàm thứ hai trả về chế độ ban đầu.
Điểm chủ quan của đôi hàm này là ở cụm từ "trạng thái/chế độ ban đầu". Làm sao biết thế nào là trạng thái ban đầu? Hàm thứ hai làm như vậy có bảo đảm là đúng không?
Xin trả lời: đối với project nhỏ thì được, nhưng gặp project lớn thỉ sẽ có vấn đề (project ở đây là VBAProject của Excel)
Ví dụ cụ thể: trong một module nào đó, ta có hàm A, bên trong hàm A, ta gọi hàm B. Để tăng tốc một đoạn code nào đó trong hàm A, ta gọi SpeedOn(), sau đó gọi SpeedOff(). Rất tiếc là nếu B cũng có gọi SpeedOn() và SpeedOff() thì SpeedOff() của B sẽ vô hiệu hóa SpeedOn() của A.
Trên thực tế, khi lập trình một project lớn, người ta không gọi hàm khơi khơi như vậy. Trước khi thay đổi trạng thái ứng dụng, người ta trữ lại trạng thái hiện hành và khi cần trả về thì trả về trạng thái này chứ không phải trạng thái mặc định như code trong hàm SpeedOff()
Làm thế nào để trữ lại trạng thái ban đầu? Dùng biến toàn cục? Xin thưa là không bởi vì chỉ cần một vài lần trữ không có ngăn xếp (stack) là sai bấy hết. Dùng biến cục bộ của hàm và truyền cho SpeedOn(), SpeedOff() qua tham số? Xin thưa là có tất cả 8 biến, nếu phải bảo trì thêm 8 biến này thì cũng hơi cực. Có thể giảm thiểu bằng cách dùng cấu trúc (type, tương tự như struct trong C)? Được nhưng vẫn còn hơi phiền phức và dễ bị lỗi (error prone).
Giải pháp người ta thường dùng là áp dụng đối tượng. Theo giải pháp này, người ta đặt ra một lớp (class module) – ví dụ SpeedOnOff. Trong lớp này, ta đặt 8 thuộc tính private để chứa tình trạng hiện hành (private vì bên ngoài không cần biết đến chúng). Lớp chứa hai hàm public SpeedOn() và SpeedOff(). Trước khi tắt chế độ màn hình, SpeedOn() ghi lại 8 thuộc tính hiện hành. SpeedOff() chỉ việc dùng các thuộc tính này để khôi phục lại chế độ ban đầu.
Cách dùng:
[code bình thường…]
Dim mySpeed As SpeedOnOff
Set mySpeed = New SpeedOnOff
mySpeed.SpeedOn ‘ tắt chế độ hiển thị màn hình
[code cần chạy nhanh]
mySpeed.SpeedOff ‘ trả về chế độ ban đầu
[code bình thường…]
Tương đối giản dị và an toàn.
Đối tượng gói kín thuộc tính (dữ liệu) riêng của nó nên không code nào chạm đến được ngoài cách gọi hàm SpeedOn()/SpeedOff(). Mỗi hàm module cần bật tắt màn hình đều phải tạo đối tượng riêng nên dữ liệu được bảo đảm.
(*) thành thật xin lỗi mọi người, tôi không được phép làm việc trong thư mục nói trên nên bắt buộc phải mở ở đây.
Ghi chú thêm: bạn nào đọc bài về lớp/class của NguenDuyTuan mà thấy khó hiểu thì cũng có thể coi đây là một ví dụ đơn giản ứng dụng class.