Ngày tháng bị đảo ngược trong dictionary

Liên hệ QC
Ở bước làm việc với Dictionary object, anh ghi luôn keys cần lấy vào một mảng là được.

Dim mangTieuDe as variant, chiso as long
''
Redim mangTieuDe( 1 to so_phan_tu_xet_nghiem * 2)
chiso=1
''
'Trong vòng lặp '
objDic.add skey, item
mangTieuDe(chiso) = skey
chiso = chiso + 2

'Ghi kết quả vào bảng tính'
If chiso> 0 then Target.resize(1, chiso).value = mangTieuDe
Đúng rồi bạn. Đó là tôi quên thòng 1 câu là không can thiệp vào các dòng code đã có.
 
Ở bước làm việc với Dictionary object, anh ghi luôn keys cần lấy vào một mảng là được.

Dim mangTieuDe as variant, chiso as long
''
Redim mangTieuDe( 1 to so_phan_tu_xet_nghiem * 2)
chiso=1
''
'Trong vòng lặp '
objDic.add skey, item
mangTieuDe(chiso) = skey
chiso = chiso + 2

'Ghi kết quả vào bảng tính'
If chiso> 0 then Target.resize(1, chiso).value = mangTieuDe
Em làm như anh hướng dẫn nhưng nó chỉ ra được 1 kết quả nằm tuốt ở ngoài khơi luôn ạ, do chỗ so_phan_tu_xet_nghiem em không rõ biến nó là gì? mong anh giúp thêm ạ.
Capture.PNG
Bài đã được tự động gộp:

Tạo riêng cho nó cái mảng. Đưa nó vào mảng ngay từ lúc add key. Nếu Dic chưa có gì thì add vào cột đầu trong mảng rồi cho biến cột tăng dần, khi dic đã tồn tại key thì tăng biến cột thêm 1 nữa rồi add vào mảng... nếu khó hiểu thì bỏ qua nha...
Hihi. cao siêu quá em xin chịu ạ.
 

File đính kèm

  • Copy.xlsb
    93.8 KB · Đọc: 9
Em làm như anh hướng dẫn nhưng nó chỉ ra được 1 kết quả nằm tuốt ở ngoài khơi luôn ạ, do chỗ so_phan_tu_xet_nghiem em không rõ biến nó là gì? mong anh giúp thêm ạ.
View attachment 275021
Bài đã được tự động gộp:


Hihi. cao siêu quá em xin chịu ạ.
Bạn làm đúng hết những gì mà bài #19 đã chỉ. Cái sai của bạn là redim mangTieuDe trong vòng lặp nên qua mỗi lần lặp là kết quả trong mangTieuDe bị reset và trống rỗng, chỉ có cái chiso là vẫn cứ tăng đều. Chỉ còn mỗi cái tiêu đề cuối là chấm dứt vòng lặp kia nên không bị reset.
 
Lần chỉnh sửa cuối:
Tạo riêng cho nó cái mảng. Đưa nó vào mảng ngay từ lúc add key. Nếu Dic chưa có gì thì add vào cột đầu trong mảng rồi cho biến cột tăng dần, khi dic đã tồn tại key thì tăng biến cột thêm 1 nữa rồi add vào mảng... nếu khó hiểu thì bỏ qua nha...
Đây là kỹ thuật đít sần với item gồm nhiều trường.
Thay vì phải ghép cả đống trường vào mỗi item thì tạo một mảng 2 chiều, chứa mỗi trường vào một cột. Item trong đít sần là chỉ số dòng của mảng.
Để thực hiện, cần tạo mảng 2 chiều với số dòng lớn nhất có thể, và số cột tối thiểu là 1. Cứ mỗi lần cần thêm cột để chứa trường mới thì dùng Redim Reserved để tăng số cột.

Đúng là em cũng đọc nhiều bài và tìm hiểu thì Date Time nên dùng value2.
Nhưng vì sao thì thật tình cũng chưa tường tận lắm
Em cũng từng đọc qua bài này, có vẻ như họ khuyên nên dùng value2
View attachment 274998
Nhưng thắc mắc là tại sao trong nhiều bài code lại không dùng hẳn value2 (thấy hầu như value - trừ date time) , trong khi nó nhanh hơn và lấy giá trị chuẩn hơn???

https://stackoverflow.com/questions/17359835/what-is-the-difference-between-text-value-and-value2
Value2 lấy kết quả chứa bên trong bảng tính. Value lấy kết quả theo kiểu dữ liệu mà Excel hiểu.
Do luật trên, Value2 sẽ lấy ngày thành số (Double); Value lấy ngày thành ngày (Date). Đương nhiên là số thì dễ làm việc hơn.
Vì vậy, nếu lấy ngày để tính toán thì nên dùng Value2.
Tuy nhiên nếu chép trở lại bảng tính thì Value2 sẽ chép lại dạng Double, và người viết code phải thêm phần chỉnh format cột thành dạng Date.
Tại sao dùng Value?:
1. lười, vì nó giản dị hơn.
2. người sử dụng có 100% tự tin về mức độ hiểu biết ngày tháng cũng như cách sử lý ngày tháng của mình. Tôi là 1 trong số đó.
- tôi rất ít khi dùng Value2 vì cả hai lý do trên, cộng thêm lý do:
-- tôi quan niệm tốc độ theo độ phức tạp code chứ không theo tiết lộ bên trong các hàm thư viện. Hiện nay, Microsoft đâu có nói họ lấy Value và Value2 bằng phương pháp gì. Người ta chỉ dựa theo kinh nghiệm và test để biết. Theo tinh thần gói kín code, MS không hề cho biết họ có dự định sửa code Value và Value2. Biết đâu trong tương lai, tốc độ truy cập hai thuộc tính này in hệt nhau? hay thậm chí, ngược lại?
 
Lần chỉnh sửa cuối:
Bạn làm đúng hết những gì mà bài #19 đã chỉ. Cái sai của bạn là redim mangTieuDe trong vòng lặp nên qua mỗi lần lặp là kết quả trong mangTieuDe bị reset và trống rỗng, chỉ có cái chiso là vẫn cứ tăng đều. Chỉ còn mỗi cái tiêu đề cuối là chấm dứt vòng lặp kia nên không bị reset.
Cám ơn anh/chị em đưa cái Redim lên trước vòng lặp đã ra kết quả đúng. Nhưng chỗ khai báo Redim mangTieuDe(1 to ?x2) em chưa rõ chỗ dấu ? là mình lồng biến gì vô? hiện e đang gõ đại là 100.
Xin cám ơn
 
Cám ơn anh/chị em đưa cái Redim lên trước vòng lặp đã ra kết quả đúng. Nhưng chỗ khai báo Redim mangTieuDe(1 to ?x2) em chưa rõ chỗ dấu ? là mình lồng biến gì vô? hiện e đang gõ đại là 100.
Xin cám ơn
Lúc đầu thì đâu biết kích thước cột của tiêu đề đâu nên cách đơn giản nhất là áng chừng và khai báo đại. Ví dụ ước cỡ 100 cột như bạn rồi x 2.

Còn không thì có cách khác: Redim ở trong vòng lặp tại vị trí như lúc trước:
Redim Preserve mangTieuDe(1 to chiso * 2)
 
Lúc đầu thì đâu biết kích thước cột của tiêu đề đâu nên cách đơn giản nhất là áng chừng và khai báo đại.

Không biết chính xác nhưng chắc chắn biết số lượng tối đa = so_phan_tu_xet_nghiem * 2

Còn không thì có cách khác: Redim ở trong vòng lặp tại vị trí như lúc trước:
Redim Preserve mangTieuDe(1 to chiso * 2)
Hết cách mới dùng Redim Preserve trong vòng lặp anh nhé, vì cái đó rất nặng nhọc.
 
Lúc đầu thì đâu biết kích thước cột của tiêu đề đâu nên cách đơn giản nhất là áng chừng và khai báo đại. Ví dụ ước cỡ 100 cột như bạn rồi x 2.

Còn không thì có cách khác: Redim ở trong vòng lặp tại vị trí như lúc trước:
Redim Preserve mangTieuDe(1 to chiso * 2)
Em lấy theo kích thước của mảng luôn Redim mangTieuDe(1 to Ubound(arr,1))
 
thử cách này xem.
Mã:
                ReDim mangTieuDe(1 To 1, 1 To 2 * dic2.Count) '1 cot an 2 cot
                Dim vTemp
                chiso = 0
                For Each vTemp In dic2.Keys()
                    chiso = chiso + 1 'Nhay toi vi tri de viet
                    mangTieuDe(1, chiso) = vTemp
                    chiso = chiso + 1 ' bo qua mot cot
                Next

1650961082594.png
 
Mảng trong VBA theo chế độ cột trọng dòng khinh. Tức là xếp theo cột.
Ví dụ mảng A(1 to 3, 1 to 5) thì trong bộ nhớ các phần tử được sắp theo A(1, 1), A(2, 1), A(3, 1), (A1, 2), A(2, 2), A(3, 2),...
Vì vậy, có thể khai báo cả đống cột rồi lúc chép xuống bảng tính đã có phương thức Resize của Range bảo đảm số cột. Khai như vậy cũng ít bị bộ nhớ có khảng trống giữa.
Khai cả đống dòng thì dễ bị bộ nhớ có khoảng trống lớn ở giữa nên cần cẩn thận hơn.
Thưc ra khoảng trống giữa hoàn toàn không liên quan gì đến kết quả. Chỉ là hơi chậm 1 chút thôi. Tức là nếu hệ thống có cache lớn thì có thể nhận thấy, hệ thống cache nhỏ thì truy cập hoàn toàn qua RAM nên sẽ không thấy khác. Chỉ khi nào RAM dỏm, phần firmware dịch địa chỉ yếu (từ số địa chỉ sang vùng trên stick) thì lại thấy khác. Lưu ý là ở đây tôi nói từ "hơi chậm" theo hoàn cảnh GPE, chứ chính quan niệm của tôi thì vài phần ngàn giây không kể là có khác biệt.
 
Lần chỉnh sửa cuối:
PHP:
Option Explicit
Sub s3_lay_ten_ngay() '20/4/2022 tu viet
    Application.ScreenUpdating = False
        Dim arr, cell As Range
        Dim lr&, i&, dk$, c&, c2&
        Dim dic As Object: Set dic = CreateObject("Scripting.Dictionary")
        Dim dic2 As Object: Set dic2 = CreateObject("Scripting.Dictionary")
        dic2.CompareMode = TextCompare
        With Sheet2
            .AutoFilterMode = False
            lr = .Range("F" & Rows.Count).End(xlUp).Row
            arr = .Range("F9:M" & lr).Value2
            dk = .Range("P3").Value
        End With
        For i = 1 To UBound(arr)
            If arr(i, 6) = dk Then
                If Not dic.Exists(arr(i, 1)) Then
                    dic.Add arr(i, 1), ""
                End If
                If Not dic2.Exists(arr(i, 3)) Then
                    dic2.Add arr(i, 3), ""
                End If
            End If
        Next i
            c = dic.Count
            c2 = dic2.Count
            If c2 = 0 Then Exit Sub
            i = 0
            With Sheet3
                .Range(.Cells(10, 5), .Cells(10, 5 + c2)).EntireColumn.Hidden = False
                .Range(.Cells(10, 5), .Cells(10, 5 + c2)).ClearContents
                For Each cell In .Range("F10").Resize(, c2 * 2 - 1)
                    i = i + 1
                    If WorksheetFunction.IsOdd(i) Then cell.Value = dic2.Keys()(Int((i - 1) / 2))
                Next
                .Range(.Cells(11, 5), .Cells(11 + c, 5)).EntireRow.Hidden = False
                .Range("E11:E" & 10 + c).ClearContents
                .Range("E11").Resize(c).Value = Application.WorksheetFunction.Transpose(dic.Keys)
                .Range("E11:E" & 10 + c).Sort .Range("E10"), xlAscending
                .Range(.Cells(10, 6 + c2 * 2), .Cells(10, 52)).EntireColumn.Hidden = True
                .Range(.Cells(11 + c, 5), .Cells(400, 5)).EntireRow.Hidden = True
            End With
Application.ScreenUpdating = True
End Sub
 
PHP:
Option Explicit
Sub s3_lay_ten_ngay() '20/4/2022 tu viet
    Application.ScreenUpdating = False
        Dim arr, cell As Range
        Dim lr&, i&, dk$, c&, c2&
        Dim dic As Object: Set dic = CreateObject("Scripting.Dictionary")
        Dim dic2 As Object: Set dic2 = CreateObject("Scripting.Dictionary")
        dic2.CompareMode = TextCompare
        With Sheet2
            .AutoFilterMode = False
            lr = .Range("F" & Rows.Count).End(xlUp).Row
            arr = .Range("F9:M" & lr).Value2
            dk = .Range("P3").Value
        End With
        For i = 1 To UBound(arr)
            If arr(i, 6) = dk Then
                If Not dic.Exists(arr(i, 1)) Then
                    dic.Add arr(i, 1), ""
                End If
                If Not dic2.Exists(arr(i, 3)) Then
                    dic2.Add arr(i, 3), ""
                End If
            End If
        Next i
            c = dic.Count
            c2 = dic2.Count
            If c2 = 0 Then Exit Sub
            i = 0
            With Sheet3
                .Range(.Cells(10, 5), .Cells(10, 5 + c2)).EntireColumn.Hidden = False
                .Range(.Cells(10, 5), .Cells(10, 5 + c2)).ClearContents
                For Each cell In .Range("F10").Resize(, c2 * 2 - 1)
                    i = i + 1
                    If WorksheetFunction.IsOdd(i) Then cell.Value = dic2.Keys()(Int((i - 1) / 2))
                Next
                .Range(.Cells(11, 5), .Cells(11 + c, 5)).EntireRow.Hidden = False
                .Range("E11:E" & 10 + c).ClearContents
                .Range("E11").Resize(c).Value = Application.WorksheetFunction.Transpose(dic.Keys)
                .Range("E11:E" & 10 + c).Sort .Range("E10"), xlAscending
                .Range(.Cells(10, 6 + c2 * 2), .Cells(10, 52)).EntireColumn.Hidden = True
                .Range(.Cells(11 + c, 5), .Cells(400, 5)).EntireRow.Hidden = True
            End With
Application.ScreenUpdating = True
End Sub
Cám ơn anh nhiều nhé.
 
Web KT
Back
Top Bottom