Nhờ giải thích chi tiết về biến toàn cục

Liên hệ QC
Ta có thể gộp đủ kiểu key/item vào một đít nhưng hàm truy cập hàng loạt của nó (key collection, item collection) không thể phân biệt các loại khác nhau.
Chính vì vậy mà tôi không dùng. Trên GPE tôi thấy anh Hieu_CD có dùng, sau khi tự phân tích thì tôi không học theo:
- Khi cần đếm riêng 1 loại key thì không dùng Dict.Count được
- Khi cần duyệt theo 1 loại key bằng 1 vòng lặp trên Dict thì rõ ràng là dư thừa, phải if iếc để lọc
- Giả sử trong 1 Dict có 10 cửa hàng, 30 nhân viên, 500 mặt hàng, thì khi xét 1 key "cửa hàng A" nào đó có tồn tại hay không thì VBA phải tìm trong 540 keys thay vì tìm trong 10 keys, tốn xăng
 
Chính vì vậy mà tôi không dùng. Trên GPE tôi thấy anh Hieu_CD có dùng, sau khi tự phân tích thì tôi không học theo:
- Khi cần đếm riêng 1 loại key thì không dùng Dict.Count được
- Khi cần duyệt theo 1 loại key bằng 1 vòng lặp trên Dict thì rõ ràng là dư thừa, phải if iếc để lọc
- Giả sử trong 1 Dict có 10 cửa hàng, 30 nhân viên, 500 mặt hàng, thì khi xét 1 key "cửa hàng A" nào đó có tồn tại hay không thì VBA phải tìm trong 540 keys thay vì tìm trong 10 keys, tốn xăng
Code của mình bắt chước các code trên diễn đàn và sui rủi chỉ đọc được các code dùng 1 dic, Trước đây do nhu cầu dùng 2 dic và dùng lệnh
set dic2=dic1
để tạo dic2 nhưng dic2 lại y như dic1 nên nghỉ chỉ được dùng 1 dic :cool: vậy là phải chế dạng phân biệt các loại key để nhét chung vào 1 dic, dùng nhiều thành quen và khi cần mới dùng nhiều dic
 
Cái này là vụ 'clone object'.

Ban đầu có Set object_0 = CreateObject()
* Giả sử có có nhu cầu dùng thêm object_1, object_2 mà ta dùng cách:
Set object_1 = object_0
Set object_2 = object_0

thì mọi THAY ĐỔI của object_0 tiếp sau đó cũng đều áp dụng cho cả object_1, object_2, và mọi thay đổi của object_1 và/hoặc object_2 cũng đều áp dụng cho object_0.
Tức là 3 object_0, object_1, object_2 đều trỏ tới một object như nhau, hay nôm na thực chất có 1 object mà có 3 tên khác nhau để gọi nó.

Nếu muốn 'clone' thực sự thì phải dùng phương thức clone của object đó (nếu nó có). Ví dụ Hashtable, SortedList, ArrayList

* Nếu muốn có 2 object_1, object_2 riêng biệt thì phải dùng cách CreateObject().

-----
Với array thì 'clone' sẽ dễ dàng.
Ví dụ
PHP:
Dim array_1 as Variant, array_2 as variant
Redim array_1(1 to 5)
'Thay vì dùng Redim array_2(1 to 5) thì hoàn toàn có thể dùng  '
array_2 = array_1
'là tạo được bản sao của array_1, mà array_2  ĐỘC LẬP với array_1 '
 
Code của mình bắt chước các code trên diễn đàn và sui rủi chỉ đọc được các code dùng 1 dic, Trước đây do nhu cầu dùng 2 dic và dùng lệnh
set dic2=dic1
để tạo dic2 nhưng dic2 lại y như dic1 nên nghỉ chỉ được dùng 1 dic :cool: vậy là phải chế dạng phân biệt các loại key để nhét chung vào 1 dic, dùng nhiều thành quen và khi cần mới dùng nhiều dic
Trước đây thì như thế đó.

Đến hôm nay, sao chép nhân bản dic sang dic2 Bác @HieuCD đã làm được chưa? Thấy google có đoạn api clone object cũng hay.
 
Cái này là vụ 'clone object'.

Ban đầu có Set object_0 = CreateObject()
* Giả sử có có nhu cầu dùng thêm object_1, object_2 mà ta dùng cách:
Set object_1 = object_0
Set object_2 = object_0
...
Bạn giải thích như vậy chưa rõ.

Lệnh gán (dấu bằng) chỉ giành cho loại biến có thể mang giá trị. Khi ta gán a = b thì VBA sẽ lấy trị của biểu thức b gán vào biểu thức a. Sau khi gán xong, a và b chả còn gì với nhau.

Lệnh gán Set có thể dịch là "đặt". Lệnh này không copy trị mà chỉ copy địa chỉ.
Nói cách khác, trong hầu hết các trường hợp, Set tức là "đặt" tên, hay thêm tên mới cho đối tượng.
Set sh = Sheet1 ' đặt thêm cho Sheet1 tên sh
Set sh1a = sh ' sh1a là tên mới của đối tượng mà sh đang trỏ vào
Set sh1b = Sheet1
' Sheet1 hiện giờ có thêm 3 tên mới: sh, sh1a, sh1b
Set sh1a = Nothing ' bứt tên sh1a ra khỏi đối tượng mà nó đang trỏ vào
' Sheet1 hiện giờ chỉ còn 3 tên: sh, sh1b, Sheet1

Lệnh Set này chỉ giành cho các kiểu cơ cấu dữ liệu phức tạp

Chú thích 1: khi đối tượng không còn tên nào, tức là các tên của nó đều được Set Nothing hoặc Set sang đối tượng khác,, nó sẽ được coi là mồ côi và sẽ được bộ phận dọn rác của VBA hủy.
Trường hợp đối tượng tạm, không tên như
With CreateObject...
...
End With
Thì nó được coi là mồ côi sau khi VBA chạy lệnh End With.

Chú thích 2: từ "clone" trong ngữ cảnh đối tượng có nghĩa là "bản sao", tức là một đối tượng khác với phương thức và thuộc tính in hệt như đối tượng ban đầu. Sau khi "clone" xong thì hai đối tượng này hoàn toàn độc lập nhau. Khi thay đổi thằng này không ảnh hưởng thằng kia. (nói đơn giản thôi, chứ loại đối tượng chứa đối tương là chuyện khác. Lúc ấy phải phân biệt clone sâu hay cạn)
 
Lần chỉnh sửa cuối:
Với array thì 'clone' sẽ dễ dàng.
'Thay vì dùng Redim array_2(1 to 5) thì hoàn toàn có thể dùng
array_2 = array_1
là tạo được bản sao của array_1, mà array_2 ĐỘC LẬP với array_1
Cuộc đời không dễ dàng đến thế, ở đâu mà trong 1 bộ code có 2 mảng kết quả cùng số lượng cột (mảng kết quả mới cần Redim, chứ mảng đầu vào đâu cần redim) huống hồ nhiều mảng.
Còn mảng đầu vào thì số lượng cột lại càng mênh mông ...

Lại có trường hợp bảng dữ liệu có 16 cột, tôi cần cột 2, 3, 10, 14, 15,16. Tôi sẽ tạo 3 mảng đầu vào ( mảng 2 cột, mảng 1 cột và mảng thứ ba 3 cột), chứ không lấy 1 mảng 16 cột to đùng
Lại có kiểu lưu trữ dữ liệu không chuẩn vừa ngang vừa dọc, 1 bảng trên sheet phải chia làm 2 khu vực: khu vực 1 có 10 cột lấy 2, khu vực 2 có 500 cột lấy hết. Làm sao mà áp dụng Arr2 = Arr1
 
Cái này là vụ 'clone object'.

Ban đầu có Set object_0 = CreateObject()
* Giả sử có có nhu cầu dùng thêm object_1, object_2 mà ta dùng cách:
Set object_1 = object_0
Set object_2 = object_0

thì mọi THAY ĐỔI của object_0 tiếp sau đó cũng đều áp dụng cho cả object_1, object_2, và mọi thay đổi của object_1 và/hoặc object_2 cũng đều áp dụng cho object_0.
Tức là 3 object_0, object_1, object_2 đều trỏ tới một object như nhau, hay nôm na thực chất có 1 object mà có 3 tên khác nhau để gọi nó.

Nếu muốn 'clone' thực sự thì phải dùng phương thức clone của object đó (nếu nó có). Ví dụ Hashtable, SortedList, ArrayList
Đối với Dict, mỗi Dict mong muốn là 1 list các key của những đối tượng khác nhau như Dict phòng ban, Dict nhân viên, Dict chức vụ.
- Tạo bằng cách 'Set object_1 = object_0' thì cả 2 cùng chứa 1 đối tượng là phòng ban à? Dict thứ 2 nạp nhân viên thì cả 2 Dict chứa cùng lúc phòng ban và nhân viên?
- Tạo bằng cách 'clone' (giả sử tìm ra cách clone), thì Dict bản sao có còn chứa keys và items từ Dict gốc không? Nếu có thì phải clear trước rồi mới nạp key mới. Vậy khốn khổ clone làm gì.
 
Cuộc đời không dễ dàng đến thế, ở đâu mà trong 1 bộ code có 2 mảng kết quả cùng số lượng cột (mảng kết quả mới cần Redim, chứ mảng đầu vào đâu cần redim) huống hồ nhiều mảng.
Còn mảng đầu vào thì số lượng cột lại càng mênh mông ...

Lại có trường hợp bảng dữ liệu có 16 cột, tôi cần cột 2, 3, 10, 14, 15,16. Tôi sẽ tạo 3 mảng đầu vào ( mảng 2 cột, mảng 1 cột và mảng thứ ba 3 cột), chứ không lấy 1 mảng 16 cột to đùng
Lại có kiểu lưu trữ dữ liệu không chuẩn vừa ngang vừa dọc, 1 bảng trên sheet phải chia làm 2 khu vực: khu vực 1 có 10 cột lấy 2, khu vực 2 có 500 cột lấy hết. Làm sao mà áp dụng Arr2 = Arr1
Những bài toán phức tạp cần nhiều mảng trung gian giống nhau lưu tạm kết quả xử lý lúc đó không cần redim nhiều lần chỉ cần gán mảng đã khai báo. Ví dụ
redim a(1 to 3)' mảng a lưu 3 giá trị tính toán trung gian
redim arr(1 to sRow)
for i=1 to sRow
arr(i)=a
next i
 
ở đâu mà trong 1 bộ code có 2 mảng kết quả cùng số lượng cột

Có thể anh ít/ không gặp trường hợp đó thật.



Đối với Dict, mỗi Dict mong muốn là 1 list các key của những đối tượng khác nhau như Dict phòng ban, Dict nhân viên, Dict chức vụ.
- Tạo bằng cách 'Set object_1 = object_0' thì cả 2 cùng chứa 1 đối tượng là phòng ban à? Dict thứ 2 nạp nhân viên thì cả 2 Dict chứa cùng lúc phòng ban và nhân viên?
- Tạo bằng cách 'clone' (giả sử tìm ra cách clone), thì Dict bản sao có còn chứa keys và items từ Dict gốc không? Nếu có thì phải clear trước rồi mới nạp key mới. Vậy khốn khổ clone làm gì.

Anh chưa hiểu được vấn đề chỗ này rồi.
 
Cháu xin cảm ơn @VetMini , @ptm0412 ,@befaint ,@HieuCD và mọi người đã thảo luận.
Thực ra cháu cứ lấn cấn việc phải duyệt đi duyệt lại nhiều lần.
Lý do rằng cháu có sử dụng sự kiện Exit của combobox để đưa data vào listbox
Do data khoảng 10000 dòng. Thực sự chưa hiểu rằng việc duyệt qua 10000 dòng để nhặt dữ liệu không biết nó có phát sinh làm ì ạch không?
Cũng thử bằng việc duyệt qua data, hoặc autofilter rồi đưa qua sheet tạm nào đó xong gán kết quả vào listbox hoặc nạp key vào dic theo item để truy xuất (chính vì vậy nên cháu mới hỏi tới việc sử dụng biến toàn cục)
Mà không cảm nhận được sự khác biệt lắm.
Cho cháu hỏi mọi người. Với những cách làm trên. Thì cái nào tối ưu hơn và nhược điểm của nó là gì được không ạ.
 
Cháu xin cảm ơn @VetMini , @ptm0412 ,@befaint ,@HieuCD và mọi người đã thảo luận.
Thực ra cháu cứ lấn cấn việc phải duyệt đi duyệt lại nhiều lần.
Lý do rằng cháu có sử dụng sự kiện Exit của combobox để đưa data vào listbox
Do data khoảng 10000 dòng. Thực sự chưa hiểu rằng việc duyệt qua 10000 dòng để nhặt dữ liệu không biết nó có phát sinh làm ì ạch không?
Cũng thử bằng việc duyệt qua data, hoặc autofilter rồi đưa qua sheet tạm nào đó xong gán kết quả vào listbox hoặc nạp key vào dic theo item để truy xuất (chính vì vậy nên cháu mới hỏi tới việc sử dụng biến toàn cục)
Mà không cảm nhận được sự khác biệt lắm.
Cho cháu hỏi mọi người. Với những cách làm trên. Thì cái nào tối ưu hơn và nhược điểm của nó là gì được không ạ.
Theo mình thì cứ nạp lại cho khỏe. Duyệt theo kiểu nạp lấy Key để gán vào listbox thì cũng khá nhanh. Code kiểu không cần kiểm tra sự tồn tại của key thì cũng gọn

Dic(Key)=Empty
 
Theo mình thì cứ nạp lại cho khỏe. Duyệt theo kiểu nạp lấy Key để gán vào listbox thì cũng khá nhanh. Code kiểu không cần kiểm tra sự tồn tại của key thì cũng gọn

Dic(Key)=Empty
Trong bài trả lời đầu tiên, đại khái tôi có dặn "cái này phải tập làm nhiều để lấy kinh nghiệm áp dụng những giải pháp thích ứng nhất cho những trường hợp khác nhau."
 
Anh chưa hiểu được vấn đề chỗ này rồi.
Giờ bỗng nhiên lại hiểu. CreateObject 1 Dict mới toanh, nó sẽ rỗng và để dành, clone Dict rỗng này thành những Dict sau đó. May quá, DIct không clone được nên cứ thế mà CreateObject,
Cũng không mất bao nhiêu thời gian: viết 1 dòng CreateObject, copy thêm 7 lần thành 8 dòng, mỗi dòng chỉ sửa tên
 
Giờ bỗng nhiên lại hiểu. CreateObject 1 Dict mới toanh, nó sẽ rỗng và để dành, clone Dict rỗng này thành những Dict sau đó. May quá, DIct không clone được nên cứ thế mà CreateObject,
Cũng không mất bao nhiêu thời gian: viết 1 dòng CreateObject, copy thêm 7 lần thành 8 dòng, mỗi dòng chỉ sửa tên

Chỗ này đang nói Object chung, không riêng gì Dictionary đâu anh.

Có nhiều trường hợp cần clone object đó anh. Không dưng tự nhiên người ta tạo phương thức object.clone

Ở đây cần chú ý:
(1) Chỗ dùng CreateObject và dấu =, nắm chắc để vận dụng.
(2) Tại sao lại xảy ra (1). Cái mới dừng ở mức độ công nhận, còn chưa rõ tại sao.
 
...Có nhiều trường hợp cần clone object đó anh. Không dưng tự nhiên người ta tạo phương thức object.clone
...
Clone Oject luôn luôn là một vấn đề phức tạp. Phuonwg thức Clone 99% truonwgf hợp là phải tự code lấy, có khi còn phải viết vài phương thức CloneA, CloneB,... cho các cách clone khác nhau.
Như tôi đã trình bày trước đây. Clone có hai dạng, sâu (deep copy) và nông (shallow copy).
Dạng sâu là đối tượng này copy đối tượng kia hoàn toàn từng chi tiết. Nếu đối tượng bên vế phải chứa đối tượng con thì cũng clone luôn đối tượng con. Dạng này rất khó viết phương thức Clone.
Dạng nông là đối tượng này copy đối tượng kia, nhưng các thuộc tính kiểu phức tạp thì chỉ copy con trỏ (lệnh Set). Nếu đối tượng bên vế phải chứa đối tượng con thì cũng chỉ Set thuộc tính, hai đối tượng sẽ cùng dùng chung một đối tượng con. Dạng dễ viết phương thức Clone hơn.
Lưu ý là khong phải do dễ hay khó mà người ta chọn cách viết. Cách Clone được thiết kế hoàn toàn theo nhu cầu.
Đối với một số ngôn ngữ như C++, người ta dùng hàm chồng toán tử = để xác định cách clone.
Đối với VBA, không phải là loại ngôn ngữ Hướng Đối Tượng cho nên phải lập phương thức Clone (và có thể phải CloneA. CloneB,...).
Vì clone khá phức tạp nên code này rất cần chú thích (comments) đầy đủ

Chú thích:
Đối với C++ là ngôn ngữ chú trọng tốc độ, clone nông đương nhiên nhanh hơn sâu nhiều.
Đối với ngôn ngữ như VBA, clone sâu thì phải sâu đến cùng.
 
Web KT
Back
Top Bottom