Anhduong2015
Thành viên chính thức


- Tham gia
- 29/7/21
- Bài viết
- 53
- Được thích
- 12
File đính kèm
Lần chỉnh sửa cuối:
Không phải chỗ Cdate đó anh ạ vì chỗ đó em đã Comment Block rồi.Không liên quan gì chỗ nào khác.
Dính chưởng ở ngay đây này:
View attachment 274969
1/ Lần sau chụp hình thì chụp phun không che toàn màn hình để biết cái DateTime của máy tính là gì.
2/ Gửi file và code lên, chứ ảnh đẹp chỉ ngắm thôi.
Không phải chỗ Cdate
Không đúng nha anh. Cái này em dùng Sub trên Module s3_laytenngay không phải ghi từ Userform ạ.Đoán đúng luôn.
Dùng User form thì đừng có bao giờ dùng CDate() mà phải dùng DateSerial().
Nhiều bài nói cái này rồi.
Bằng chứng là ngày tháng ghi từ Form xuống bảng tính là ăn chuỗi chứ có phải DateTime xịn đâu. Nhìn E13 trở xuống đó.
View attachment 274988
View attachment 274987
* Thêm một cái nữa. Dữ liệu Number, DateTime đừng có canh lề, cứ để mặc định nhảy về bên phải của Cell. Để nhìn một phát là biết dữ liệu có đúng chuẩn không.
Không đúng nha anh. Cái này em dùng Sub trên Module s3_laytenngay không phải ghi từ Userform ạ.
1. Đầu tiên cám ơn anh đã góp ý giúp em. Tuy nhiên trong trường hợp này thì cái gốc rễ không phải là ở điểm gán dữ liệu ngày tháng sử dụng Cdate từ Userform xuống Sheet vì em đã xóa trắng (Clear All) dữ liệu cột ngày tháng và nhập tay lại vẫn như cũ.Tôi chỉ ra cái sai tận gốc rễ.
DateTime từ Form xuống bảng tính: Sai một phát nếu định dạng chuỗi DateTime đó khác thiết lập hệ thống.
DateTime lấy từ bảng tính lên mảng: Sai thêm một phát nữa nếu định dạng chuỗi DateTime đó khác thiết lập hệ thống.
Bạn từ từ tìm hiểu mà làm. Bí kíp, kỹ thuật tôi nêu hết rồi.
Đọc ----- thật ------ chậm ------ thôi.
Đã kiểm tra thử thì đúng là sau khi transpose dic.keys ngày tháng bị đảo ngược. Mà lạ là nếu add key thông qua một biến long gán ngày tháng thì không lỗi, mà add trực tiếp thì lỗi.1. Đầu tiên cám ơn anh đã góp ý giúp em. Tuy nhiên trong trường hợp này thì cái gốc rễ không phải là ở điểm gán dữ liệu ngày tháng sử dụng Cdate từ Userform xuống Sheet vì em đã xóa trắng (Clear All) dữ liệu cột ngày tháng và nhập tay lại vẫn như cũ.
2. Vấn đề em thấy và đã chạy thực tế là khi sử dụng Application.WorksheetFunction.Transpose nó sẽ ra ngày tháng đảo ngược, ngược lại thì đúng.
Cám ơn bạn nhiều nhé, mình đã thêm một biến long vào thì kết quả đã ra đúng. mặc dù không rõ tại sao nhưng kết quả đúng yêu cầu là tuyệt vời.Đã kiểm tra thử thì đúng là sau khi transpose dic.keys ngày tháng bị đảo ngược. Mà lạ là nếu add key thông qua một biến long gán ngày tháng thì không lỗi, mà add trực tiếp thì lỗi.
Nguyên nhân thì không rõ, còn khắc phục thì add key ngày tháng bằng hàm Dateserial cho đảm bảo
File kiểm tra lỗi:
Nguyên nhân thì không rõ, còn khắc phục thì add key ngày tháng bằng hàm Dateserial cho đảm bảo
Đúng là em cũng đọc nhiều bài và tìm hiểu thì Date Time nên dùng value2.Không hề bị làm sao.
Vụ DateTime này mình nói rồi. Bạn để ý các bài của mình đều xử lý vậy.
Cám ơn anh nhiều nhé.Không hề bị làm sao.
Vụ DateTime này mình nói rồi. Bạn để ý các bài của mình đều xử lý vậy.
Không biết ai làm thế nào chứ với tôi thì tôi sẽ dùng 1 vòng lặp duyệt qua hết keys lấy kết quả vào 1 mảng thì mới chen vị trí chứa giá trị rỗng vào được.Nhân tiện các anh/ chị cho em hỏi thêm là trong câu lệnh: .Range("F10").Resize(, c2).Value = dic2.Keys làm sao để các kết quả cách nhau xen kẽ một cột. chỗ này hơi khó diễn tả anh/chị quan tâm xin vui lòng xem hình giúp em. Do cùng bài toán em sợ mở nhiều chủ đề không hay nên có gì không đúng mong anh/chị thông cảm giúp.
Xin cám ơn rất nhiều.
View attachment 275008
View attachment 275009
Anh/chị có thể giúp em đoạn code lấy key từ dic ra được không? Em viết mà mãi không được ạ.Không biết ai làm thế nào chứ với tôi thì tôi sẽ dùng 1 vòng lặp duyệt qua hết keys lấy kết quả vào 1 mảng thì mới chen vị trí chứa giá trị rỗng vào được.
Củ chuối mà ra kết quả là tốt rồi, chứ củ sâm mà không ra kết quả thì cũng vô ích bạn ạ.Hiện tại em mới nghĩ ra được code chạy thủ công như thế này kết quả đúng nhưng nhìn hơi củ chuối xíu.
Không biết ai làm thế nào chứ với tôi thì tôi sẽ dùng 1 vòng lặp duyệt qua hết keys lấy kết quả vào 1 mảng thì mới chen vị trí chứa giá trị rỗng vào được.
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...Hiện tại em mới nghĩ ra được code chạy thủ công như thế này kết quả đúng nhưng nhìn hơi củ chuối xíu.
View attachment 275020
Đú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 ạ.Ở 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
Hihi. cao siêu quá em xin chịu ạ.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...
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
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.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 ạ.
Không phải không đúng mà có lẽ em nói từ dic đã tồn tại key chưa hợp lý lắm. Cái em nói tới là dic.count chứ không phải dic.exists. Tức là trong dic chưa có bất kỳ key nàoGiải thuật không đúng .
Đây là kỹ thuật đít sần với item gồm nhiều trường.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...
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.Đú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
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.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ú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á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.
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.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))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)
Redim mangTieuDe(1 to Ubound(arr,1))
Dạ do đầu bài em đang bỏ cách cột nên phải nhân 2.Mình vắt tay lên đầu nghĩ tại sao người ta lại có *2.
Cái gì mình tự khám phá ra sẽ nhớ dai.
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é.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