Họ không chịu nghe là việc của họ... cuối cùng, nếu muốn xử lý, ta tự mình chuyển sang cơ sở dữ liệu chuẩn trước vậyDạ bài dạng này của thầy em tham khảo rồi em cũng có hướng theo đó, nếu người ta chịu cách bố trí đó thì khoẻ còn không thì hơi mệt một tí thầy à
Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range)
Dim sArr1, sArr2, i As Long, j As Long, iR As Long, iC As Long
Dim Arr(1 To 60000, 1 To 200), Tmp1, Tmp2, Dic1, Dic2
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
sArr1 = sRng1: sArr2 = sRng2
For i = LBound(sArr1, 1) To UBound(sArr1, 1)
For j = LBound(sArr1, 2) To UBound(sArr1, 2)
If sArr1(i, j) <> "" Then
Tmp1 = sArr1(i, j)
Tmp2 = sArr2(i, j)
If Not Dic1.Exists(Tmp1) Then
iR = iR + 1
Dic1.Add Tmp1, iR
Dic2.Add Tmp1, 2
Arr(iR, 1) = Tmp1
Arr(iR, 2) = Tmp2
Else
Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1
Arr(Dic1.Item(Tmp1), Dic2.Item(Tmp1)) = Tmp2
End If
If iC < Dic2.Item(Tmp1) Then iC = Dic2.Item(Tmp1)
End If
Next
Next
Target.Resize(iR, iC).Value = Arr
End Sub
Sub Main()
Dim sRng1 As Range, sRng2 As Range, Target As Range
Set sRng1 = Range("A3:A100")
Set sRng2 = Range("C3:C100")
Set Target = Range("G2")
Transfer sRng1, sRng2, Target
End Sub
Transfer sRng1, sRng2, Target
Sub Transfer được viết dưới dạng tổng quát và Sub Main chính là sub chính để chạy. Khi bạn chạy sub Main, nó sẽ nạp giá trị cho sRng1, sRng2, Target rồi nó sẽ gọi sub Transfer và truyền tham số vào nó.PHP:Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range) Dim sArr1, sArr2, i As Long, j As Long, iR As Long, iC As Long Dim Arr(1 To 60000, 1 To 200), Tmp1, Tmp2, Dic1, Dic2 Set Dic1 = CreateObject("Scripting.Dictionary") Set Dic2 = CreateObject("Scripting.Dictionary") sArr1 = sRng1: sArr2 = sRng2 For i = LBound(sArr1, 1) To UBound(sArr1, 1) For j = LBound(sArr1, 2) To UBound(sArr1, 2) If sArr1(i, j) <> "" Then Tmp1 = sArr1(i, j) Tmp2 = sArr2(i, j) If Not Dic1.Exists(Tmp1) Then iR = iR + 1 Dic1.Add Tmp1, iR Dic2.Add Tmp1, 2 Arr(iR, 1) = Tmp1 Arr(iR, 2) = Tmp2 Else Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1 Arr(Dic1.Item(Tmp1), Dic2.Item(Tmp1)) = Tmp2 End If If iC < Dic2.Item(Tmp1) Then iC = Dic2.Item(Tmp1) End If Next Next Target.Resize(iR, iC).Value = Arr End Sub
PHP:Sub Main() Dim sRng1 As Range, sRng2 As Range, Target As Range Set sRng1 = Range("A3:A100") Set sRng2 = Range("C3:C100") Set Target = Range("G2") Transfer sRng1, sRng2, Target End Sub
Thưa thày sao lại cần dòng
có tác dụng gì ah, vì các dòng trên nó đã phản ánh vùng của sRng1, sRng2, Target rồi mà, hay là phải có nó thì 2 Sub mới Link với nhau (mới chịu phối hợp, làm việc cùng nhau)?PHP:Transfer sRng1, sRng2, Target
Nếu cảm thấy không cần thì bạn có thể xóa bớt rồi chạy code xem nó "ra" cái gì?Thưa thày sao lại cần dòng
có tác dụng gì ah, vì các dòng trên nó đã phản ánh vùng của sRng1, sRng2, Target rồi mà, hay là phải có nó thì 2 Sub mới Link với nhau (mới chịu phối hợp, làm việc cùng nhau)?PHP:Transfer sRng1, sRng2, Target
Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range)
Dim sArr1, sArr2, i As Long, iR As Long, iC As Long
Dim Arr(1 To 60000, 1 To 200), Tmp1, Tmp2, Dic1, Dic2
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
sArr1 = sRng1: sArr2 = sRng2
For i = LBound(sArr1, 1) To UBound(sArr1, 1)
If sArr1(i, 1) <> "" Then
Tmp1 = sArr1(i, 1)
Tmp2 = sArr2(i, 1)
If Not Dic1.Exists(Tmp1) Then
iR = iR + 1
Dic1.Add Tmp1, iR
Dic2.Add Tmp1, 2
Arr(iR, 1) = Tmp1
Arr(iR, 2) = Tmp2
Else
Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1
Arr(Dic1.Item(Tmp1), Dic2.Item(Tmp1)) = Tmp2
End If
If iC = 1 Then iC = Dic2.Item(Tmp1)
End If
Next
Target.Resize(iR, iC).Value = Arr
End Sub
Sub Main()
Dim sRng1 As Range, sRng2 As Range, Target As Range
Set sRng1 = Range("A3:A100")
Set sRng2 = Range("C3:C100")
Set Target = Range("G2")
Transfer sRng1, sRng2, Target
End Sub
Người ta xác định "độ rộng" lớn nhất của Arr bằng dòng này:Bài này hay quá, Item(Dic1) chạy đánh dấu theo chiều dọc, Item(Dic2) chạy đánh dấu theo chiều ngang
iR sẽ được xác định dựa vào điều kiện Dictionary, tuy vậy iC thì cận trên của nó xác định ở đâu nhỉ?
Em định sửa thành như thế này thì "tèo" nhưng chưa tìm ra nguyên nhân, mong các thày chỉ cho
PHP:Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range) Dim sArr1, sArr2, i As Long, iR As Long, iC As Long Dim Arr(1 To 60000, 1 To 200), Tmp1, Tmp2, Dic1, Dic2 Set Dic1 = CreateObject("Scripting.Dictionary") Set Dic2 = CreateObject("Scripting.Dictionary") sArr1 = sRng1: sArr2 = sRng2 For i = LBound(sArr1, 1) To UBound(sArr1, 1) If sArr1(i, 1) <> "" Then Tmp1 = sArr1(i, 1) Tmp2 = sArr2(i, 1) If Not Dic1.Exists(Tmp1) Then iR = iR + 1 Dic1.Add Tmp1, iR Dic2.Add Tmp1, 2 Arr(iR, 1) = Tmp1 Arr(iR, 2) = Tmp2 Else Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1 Arr(Dic1.Item(Tmp1), Dic2.Item(Tmp1)) = Tmp2 End If If iC = 1 Then iC = Dic2.Item(Tmp1) End If Next Target.Resize(iR, iC).Value = Arr End Sub
--------PHP:Sub Main() Dim sRng1 As Range, sRng2 As Range, Target As Range Set sRng1 = Range("A3:A100") Set sRng2 = Range("C3:C100") Set Target = Range("G2") Transfer sRng1, sRng2, Target End Sub
----> Nghĩa là hầu như bài nào mà đầu ra bố trí theo kiểu 2 chiều ngang, dọc của hình chữ nhật chắc là phải dùng 2 Dictionary?
Nhân đây, bạn thử nghiên cứu xem có cách nào chỉ dùng 1 biến Dic mà vẫn làm được bài này không?Em hiểu rồi ah, nhầm lẫn cơ bản quá, bởi không để ý đến dòng Arr(iR,1)=Tmp1 nên em cứ tự hỏi cột đầu tiên của Arr được xác định bởi đâu, cảm ơn thày Ndu rất nhiều.
iC nó chỉ là phần mở rộng thêm thôi chứ nó không phải là độ rộng của Arr (không bao gồm cột 1)
Vấn đề là chịu nghiên cứu, chịu "vọc". Có thầy như NDU thì không tiến bộ mới lạ.Nhân đây, bạn thử nghiên cứu xem có cách nào chỉ dùng 1 biến Dic mà vẫn làm được bài này không?
Ẹc... Ẹc...
(lại thêm 1 người nữa tiến bộ nhanh trong lĩnh vực lập trình đây... Cố lên..)
Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range)
Dim sArr1, sArr2, Arr, Dic1, Dic2, i As Long, iR As Long, iC As Long, Tmp1, Tmp2
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
sArr1 = sRng1
sArr2 = sRng2
ReDim Preserve Arr(1 To UBound(sArr1, 1), 1 To 100)
For i = 1 To UBound(sArr1, 1)
If sArr1(i, 1) <> "" And Not Dic1.Exists(sArr1(i, 1)) Then
Tmp1 = sArr1(i, 1)
Tmp2 = sArr2(i, 1)
iR = iR + 1
Dic1.Add Tmp1, iR
Dic2.Add Tmp1, 2
Arr(iR, 1) = Tmp1
Arr(iR, 2) = Tmp2
Else
Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1
Arr(iR, Dic2.Item(Tmp1)) = Tmp2
End If
If iC < Dic2.Item(Tmp1) Then iC = Dic2.Item(Tmp1)
Next
Target.Resize(iR, iC).Value = Arr
End Sub
Sub Main()
Dim sRng1 As Range, sRng2 As Range, Target As Range
Set sRng1 = Range("A3:A100")
Set sRng2 = Range("C3:C100")
Set Target = Range("G2")
Transfer sRng1, sRng2, Target
End Sub
Em chưa có kinh nghiệm lắm, đôi khi viết xong Code kiểm soát đúng sai vẫn còn hạn chế, em làm thế này cũng chạy nhưng kết quả không đúng, rất mong được thày và mọi người chỉ cho em chỗ sai
PHP:Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range) Dim sArr1, sArr2, Arr, Dic1, Dic2, i As Long, iR As Long, iC As Long, Tmp1, Tmp2 Set Dic1 = CreateObject("Scripting.Dictionary") Set Dic2 = CreateObject("Scripting.Dictionary") sArr1 = sRng1 sArr2 = sRng2 ReDim Preserve Arr(1 To UBound(sArr1, 1), 1 To 100) For i = 1 To UBound(sArr1, 1) If sArr1(i, 1) <> "" And Not Dic1.Exists(sArr1(i, 1)) Then Tmp1 = sArr1(i, 1) Tmp2 = sArr2(i, 1) iR = iR + 1 Dic1.Add Tmp1, iR Dic2.Add Tmp1, 2 Arr(iR, 1) = Tmp1 Arr(iR, 2) = Tmp2 Else Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1 Arr(iR, Dic2.Item(Tmp1)) = Tmp2 End If If iC < Dic2.Item(Tmp1) Then iC = Dic2.Item(Tmp1) Next Target.Resize(iR, iC).Value = Arr End Sub
]
Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range)
Dim sArr1, sArr2, Arr(), Dic1, Dic2, i As Long, iR As Long, iC As Long, Tmp1, Tmp2
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
sArr1 = sRng1
sArr2 = sRng2
[COLOR=#ff0000] ReDim Arr(1 To UBound(sArr1, 1), 1 To 100)[/COLOR]
For i = 1 To UBound(sArr1, 1)
[COLOR=#ff0000]If sArr1(i, 1) <> "" Then
Tmp1 = sArr1(i, 1)
Tmp2 = sArr2(i, 1)
If Not Dic1.Exists(sArr1(i, 1)) Then[/COLOR]
iR = iR + 1
Dic1.Add Tmp1, iR
Dic2.Add Tmp1, 2
Arr(iR, 1) = Tmp1
Arr(iR, 2) = Tmp2
Else
Dic2.Item(Tmp1) = Dic2.Item(Tmp1) + 1
Arr([COLOR=#ff0000]Dic1.Item(Tmp1)[/COLOR], Dic2.Item(Tmp1)) = Tmp2
End If
If iC < Dic2.Item(Tmp1) Then iC = Dic2.Item(Tmp1)
End If
Next
[COLOR=#ff0000] If iR Then [/COLOR]Target.Resize(iR, iC).Value = Arr
End Sub
If sArr1(i, 1) <> "" And Not Dic1.Exists(sArr1(i, 1)) Then
Tmp1 = sArr1(i, 1)
Tmp2 = sArr2(i, 1)
If sArr1(i, 1) <> "" Then
Tmp1 = sArr1(i, 1)
Tmp2 = sArr2(i, 1)
If Not Dic1.Exists(sArr1(i, 1)) Then
........
Phân tích được chổ sai là bạn quá giỏi rồi còn gì---> Dùng gộp nhiều lúc nguy hiểm quá ----> đa số trường hợp viết gộp là đúng, một số trường hợp cá biệt cần tách ra làm 2 câu lệnh.
2) Quan niệm nhầm iR và Dic1.Item(Tmp1) nó là 1, tưởng viết thế cho gọn; nhưng nó chỉ bằng nhau trong trường hợp Not Dic.Exists thôi, trường hợp còn lại (Else) thì nó độc lập nhau.
Từ hôm qua em học được ở thày được rất nhiều kiến thức, cảm ơn thày rất nhiều.
Sub Transfer(sRng1 As Range, sRng2 As Range, Target As Range)
Dim sArr1, sArr2, Arr(), Dic1, Dic2, i As Long, iR As Long, iC As Long, Tmp1, Tmp2, j As Long
Set Dic1 = CreateObject("Scripting.Dictionary")
Set Dic2 = CreateObject("Scripting.Dictionary")
sArr1 = sRng1
sArr2 = sRng2
ReDim Arr(1 To UBound(sArr1, 1), 1 To 100)
For i = 1 To UBound(sArr1, 1)
If sArr1(i, 1) <> "" Then
Tmp1 = sArr1(i, 1)
Tmp2 = sArr2(i, 1)
If Not Dic1.Exists(sArr1(i, 1)) Then
iR = iR + 1
Dic1.Add Tmp1, iR
j = 2
Arr(iR, 1) = Tmp1
Arr(iR, j) = Tmp2
Else
j = j + 1
Arr(Dic1.Item(Tmp1), j) = Tmp2
End If
If iC < j Then iC = j
End If
Next
If iR Then Target.Resize(iR, iC).Value = Arr
End Sub
Sub Main()
Dim sRng1 As Range, sRng2 As Range, Target As Range
Set sRng1 = Range("A3:A100")
Set sRng2 = Range("C3:C100")
Set Target = Range("G2")
Transfer sRng1, sRng2, Target
End Sub
Để ý code gốc, ta có Item của Dic1 lưu vị trí dòng và Item của Dic2 lưu vị trí cộtThưa thày Ndu, bài này có thể dùng 1 Dic làm ra được không ah, em nghĩ làm mãi chưa có kết quả , nếu sửa thành thế này thì thực ra kết quả vẫn đúng, nhưng trên cùng 1 hàng kết quả ra nó không liên tục,
---> như vậy coi như chưa đạt yêu cầu
Rất mong thày làm giúp cách chỉ có 1 Dic để em có điều kiện học hỏi