Liệt kê hoán vị chập 2 VBA

Liên hệ QC

QuáchThiênLong

Thành viên mới
Tham gia
31/10/18
Bài viết
8
Được thích
0
Em có 4 chữ cái: A, B, C, D (Bảng 1). Em muốn excel hiện bảng liệt kê kết hợp lần lượt 2 chữ cái và không trùng nhau (Bảng 2). Cao nhân giúp em với1.PNG
Bài đã được tự động gộp:

Tác giả Nguyễn Ngọc Thu Hiền có đoạn mã sau rất hay nhưng cái này là tổ hợp, em không biết chỉnh thế nào. Các bạn giúp em với

Option Explicit

'****************************************
'Tac gia: Nguyen Ngoc Thu Hien
'Fb: https://www.facebook.com/profile.php?id=100011406609466
'YouTube: https://www.youtube.com/channel/UC-k00RkGYpeHnFRcafeD2YQ
'Chuc nang: Liet ke to hop chap k cua n phan tu
'Ngay Tao: 30/11/2017
'Version:1.1
'Thanh phan di kem:
'+
'+
'+
'****************************************





Sub ToHop(k As Long, sArr As Variant, ByVal rDes As Range)
'sArr: mang hai chieu chua cac phan tu can to hop
'rDes: vi tri cua o bat dau chua ket qua

Dim vaData, vaDataCurrentRow
Dim lIndex As Long, vTemp As Variant
Dim lNumItem As Long, lNumRe As Long, lNumCol As Long, lRowStartSheet As Long, lrowMaxSheet As Long

Dim lngaMin() As Long, lngaMax() As Long, lngaCurrent() As Long, vaKQ() As Variant


Dim lngRowInPage As Long
Dim lngRowPageCurrent As Long
Dim lngRowMinPage As Long
Dim lngRowMaxPage As Long

Dim lngComVisitMax As Long

ReDim vaData(1 To (UBound(sArr) - LBound(sArr) + 1) * (UBound(sArr, 2) + 1 - LBound(sArr)))

lngRowInPage = 60000
lIndex = 1
For Each vTemp In sArr
vaData(lIndex) = vTemp
lIndex = lIndex + 1
Next

lNumItem = UBound(vaData)
lNumCol = k
lNumRe = Application.WorksheetFunction.Combin(lNumItem, lNumCol)
ReDim lngaMin(1 To lNumCol) As Long
ReDim lngaMax(1 To lNumCol) As Long
ReDim lngaCurrent(1 To lNumCol) As Long
ReDim vaKQ(1 To lngRowInPage, 1 To lNumCol)
ReDim vaDataCurrentRow(1 To lNumCol) As Variant

For lIndex = 1 To lNumCol
lngaMin(lIndex) = lIndex
lngaCurrent(lIndex) = lIndex
lngaMax(lIndex) = (lNumItem - lNumCol) + lIndex ' + 1
vaDataCurrentRow(lIndex) = vaData(lIndex)
Next

rDes = rDes.Cells(1, 1)
lRowStartSheet = rDes.Row
lrowMaxSheet = rDes.Worksheet.Rows.Count
lngaCurrent(lNumCol) = lngaCurrent(lNumCol) - 1 'dich xuong mot phan tu


Do While (1)
lngRowMinPage = lngRowMaxPage + 1
lngRowMaxPage = lngRowMinPage + lngRowInPage - 1
If lngRowMaxPage > lNumRe Then
lngRowMaxPage = lNumRe
End If

For lngRowPageCurrent = 1 To lngRowMaxPage - lngRowMinPage + 1
For lIndex = lNumCol To 1 Step -1
If lngaCurrent(lIndex) = lngaMax(lIndex) Then
lngComVisitMax = lIndex
Else
lngaCurrent(lIndex) = lngaCurrent(lIndex) + 1
vaDataCurrentRow(lIndex) = vaData(lngaCurrent(lIndex))
Exit For
End If
Next
If lngComVisitMax <> 0 Then
For lIndex = lngComVisitMax To lNumCol
lngaCurrent(lIndex) = lngaCurrent(lIndex - 1) + 1
vaDataCurrentRow(lIndex) = vaData(lngaCurrent(lIndex))
Next
lngComVisitMax = 0
End If
For lIndex = 1 To lNumCol
vaKQ(lngRowPageCurrent, lIndex) = vaDataCurrentRow(lIndex)
Next
Next
lIndex = lngRowMaxPage - lngRowMinPage + 1 'so du lieu ti nh duoc
If lrowMaxSheet - rDes.Row + 1 < lIndex Then
Set rDes = rDes.Worksheet.Cells(lRowStartSheet, rDes.Column + lNumCol + 2)

End If
rDes.Resize(lIndex, lNumCol).Value = vaKQ
Set rDes = rDes.Offset(lIndex)

If lngRowMaxPage >= lNumRe Then Exit Do
Loop

Erase vaData
Erase vaDataCurrentRow
Erase vaKQ
Erase lngaMax
Erase lngaMin
Erase lngaCurrent



End Sub

Sub EnumCombination()


Dim rN As Range
Dim vN As Variant
Dim lngK As Long
Dim lngNumN As Long
Dim rDes As Range
On Error Resume Next

Set rN = Application.InputBox("Chon vung chua cac phan tu:", "Select n", Type:=8)
If Err.Number <> 0 Then Exit Sub
vN = rN.Value
If IsArray(vN) = False Then
ReDim vN(1 To 1, 1 To 1) As Variant
vN(1, 1) = rN.Value
End If
lngNumN = rN.Rows.Count * rN.Columns.Count
On Error GoTo 0

lngK = Application.InputBox("Liet ke to hop chap k cua " & Str(lngNumN) & vbCrLf & "k=?", "k", lngNumN, Type:=1)
If lngK = 0 Then
Exit Sub 'nhap ko, hoac canncel
End If

On Error Resume Next
Set rDes = Application.InputBox("Chon vung chua ket qua?", "Vung chua ket qua", Type:=8)
If Err.Number <> 0 Then Exit Sub

On Error GoTo LoiThucThi
DoEvents

Application.EnableEvents = False
Application.ScreenUpdating = False
Call ToHop(lngK, vN, rDes)

Thoat:
Application.EnableEvents = True
Application.ScreenUpdating = True
Exit Sub

LoiThucThi:
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox Err.Description
Resume Thoat

End Sub
 
Lần chỉnh sửa cuối:
Em có 4 chữ cái: A, B, C, D (Bảng 1). Em muốn excel hiện bảng liệt kê kết hợp lần lượt 2 chữ cái và không trùng nhau (Bảng 2). Cao nhân giúp em vớiView attachment 206782
Bài đã được tự động gộp:

Tác giả Nguyễn Ngọc Thu Hiền có đoạn mã sau rất hay nhưng cái này là tổ hợp, em không biết chỉnh thế nào. Các bạn giúp em với

Option Explicit

'****************************************
'Tac gia: Nguyen Ngoc Thu Hien
'Fb: https://www.facebook.com/profile.php?id=100011406609466
'YouTube: https://www.youtube.com/channel/UC-k00RkGYpeHnFRcafeD2YQ
'Chuc nang: Liet ke to hop chap k cua n phan tu
'Ngay Tao: 30/11/2017
'Version:1.1
'Thanh phan di kem:
'+
'+
'+
'****************************************





Sub ToHop(k As Long, sArr As Variant, ByVal rDes As Range)
'sArr: mang hai chieu chua cac phan tu can to hop
'rDes: vi tri cua o bat dau chua ket qua

Dim vaData, vaDataCurrentRow
Dim lIndex As Long, vTemp As Variant
Dim lNumItem As Long, lNumRe As Long, lNumCol As Long, lRowStartSheet As Long, lrowMaxSheet As Long

Dim lngaMin() As Long, lngaMax() As Long, lngaCurrent() As Long, vaKQ() As Variant


Dim lngRowInPage As Long
Dim lngRowPageCurrent As Long
Dim lngRowMinPage As Long
Dim lngRowMaxPage As Long

Dim lngComVisitMax As Long

ReDim vaData(1 To (UBound(sArr) - LBound(sArr) + 1) * (UBound(sArr, 2) + 1 - LBound(sArr)))

lngRowInPage = 60000
lIndex = 1
For Each vTemp In sArr
vaData(lIndex) = vTemp
lIndex = lIndex + 1
Next

lNumItem = UBound(vaData)
lNumCol = k
lNumRe = Application.WorksheetFunction.Combin(lNumItem, lNumCol)
ReDim lngaMin(1 To lNumCol) As Long
ReDim lngaMax(1 To lNumCol) As Long
ReDim lngaCurrent(1 To lNumCol) As Long
ReDim vaKQ(1 To lngRowInPage, 1 To lNumCol)
ReDim vaDataCurrentRow(1 To lNumCol) As Variant

For lIndex = 1 To lNumCol
lngaMin(lIndex) = lIndex
lngaCurrent(lIndex) = lIndex
lngaMax(lIndex) = (lNumItem - lNumCol) + lIndex ' + 1
vaDataCurrentRow(lIndex) = vaData(lIndex)
Next

rDes = rDes.Cells(1, 1)
lRowStartSheet = rDes.Row
lrowMaxSheet = rDes.Worksheet.Rows.Count
lngaCurrent(lNumCol) = lngaCurrent(lNumCol) - 1 'dich xuong mot phan tu


Do While (1)
lngRowMinPage = lngRowMaxPage + 1
lngRowMaxPage = lngRowMinPage + lngRowInPage - 1
If lngRowMaxPage > lNumRe Then
lngRowMaxPage = lNumRe
End If

For lngRowPageCurrent = 1 To lngRowMaxPage - lngRowMinPage + 1
For lIndex = lNumCol To 1 Step -1
If lngaCurrent(lIndex) = lngaMax(lIndex) Then
lngComVisitMax = lIndex
Else
lngaCurrent(lIndex) = lngaCurrent(lIndex) + 1
vaDataCurrentRow(lIndex) = vaData(lngaCurrent(lIndex))
Exit For
End If
Next
If lngComVisitMax <> 0 Then
For lIndex = lngComVisitMax To lNumCol
lngaCurrent(lIndex) = lngaCurrent(lIndex - 1) + 1
vaDataCurrentRow(lIndex) = vaData(lngaCurrent(lIndex))
Next
lngComVisitMax = 0
End If
For lIndex = 1 To lNumCol
vaKQ(lngRowPageCurrent, lIndex) = vaDataCurrentRow(lIndex)
Next
Next
lIndex = lngRowMaxPage - lngRowMinPage + 1 'so du lieu ti nh duoc
If lrowMaxSheet - rDes.Row + 1 < lIndex Then
Set rDes = rDes.Worksheet.Cells(lRowStartSheet, rDes.Column + lNumCol + 2)

End If
rDes.Resize(lIndex, lNumCol).Value = vaKQ
Set rDes = rDes.Offset(lIndex)

If lngRowMaxPage >= lNumRe Then Exit Do
Loop

Erase vaData
Erase vaDataCurrentRow
Erase vaKQ
Erase lngaMax
Erase lngaMin
Erase lngaCurrent



End Sub

Sub EnumCombination()


Dim rN As Range
Dim vN As Variant
Dim lngK As Long
Dim lngNumN As Long
Dim rDes As Range
On Error Resume Next

Set rN = Application.InputBox("Chon vung chua cac phan tu:", "Select n", Type:=8)
If Err.Number <> 0 Then Exit Sub
vN = rN.Value
If IsArray(vN) = False Then
ReDim vN(1 To 1, 1 To 1) As Variant
vN(1, 1) = rN.Value
End If
lngNumN = rN.Rows.Count * rN.Columns.Count
On Error GoTo 0

lngK = Application.InputBox("Liet ke to hop chap k cua " & Str(lngNumN) & vbCrLf & "k=?", "k", lngNumN, Type:=1)
If lngK = 0 Then
Exit Sub 'nhap ko, hoac canncel
End If

On Error Resume Next
Set rDes = Application.InputBox("Chon vung chua ket qua?", "Vung chua ket qua", Type:=8)
If Err.Number <> 0 Then Exit Sub

On Error GoTo LoiThucThi
DoEvents

Application.EnableEvents = False
Application.ScreenUpdating = False
Call ToHop(lngK, vN, rDes)

Thoat:
Application.EnableEvents = True
Application.ScreenUpdating = True
Exit Sub

LoiThucThi:
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox Err.Description
Resume Thoat

End Sub
bạn gửi file lên nhé không cần gửi code mà ko có cao nhân đâu chỉ có người biết trước và người biết sau thôi nhé.ban gửi file lên đi
 
Bài vi phạm nội quy!! Phai phiếc gì.
 
.............................................................
 
File này em tải về của tác giả Nguyễn Ngọc Thu Hiền. Trong file này cái đang có là Bảng 1, cái em muốn hiện ra là như Bảng 2. Theo đoạn mã của tác giả thì không ra được như cái em cần cho công việc. Bạn nào biết sửa giúp em với. Em mới tham gia nên có post bài nhầm chỗ mong addmin thông cảm. Em cám ơn ạ
Bài đã được tự động gộp:

bạn gửi file lên nhé không cần gửi code mà ko có cao nhân đâu chỉ có người biết trước và người biết sau thôi nhé.ban gửi file lên đi

Cái đang có là bảng 1, cái em cần hiện ra là như bảng 2 ạ. Cám ơn đã quan tâm
 

File đính kèm

  • ToHop_Video-1.xlsm
    74.5 KB · Đọc: 21
File này em tải về của tác giả Nguyễn Ngọc Thu Hiền. Trong file này cái đang có là Bảng 1, cái em muốn hiện ra là như Bảng 2. Theo đoạn mã của tác giả thì không ra được như cái em cần cho công việc. Bạn nào biết sửa giúp em với. Em mới tham gia nên có post bài nhầm chỗ mong addmin thông cảm. Em cám ơn ạ
Bài đã được tự động gộp:



Cái đang có là bảng 1, cái em cần hiện ra là như bảng 2 ạ. Cám ơn đã quan tâm
Chắc lỗi tiêu đề chung chung. Với bài 1, bạn sửa tiêu đề thành "liệt kê hoán vị chập 2 của 4" chắc là được thôi
 
File này em tải về của tác giả Nguyễn Ngọc Thu Hiền. Trong file này cái đang có là Bảng 1, cái em muốn hiện ra là như Bảng 2. Theo đoạn mã của tác giả thì không ra được như cái em cần cho công việc. Bạn nào biết sửa giúp em với. Em mới tham gia nên có post bài nhầm chỗ mong addmin thông cảm. Em cám ơn ạ
Bài đã được tự động gộp:



Cái đang có là bảng 1, cái em cần hiện ra là như bảng 2 ạ. Cám ơn đã quan tâm
bạn sửa tiêu đề bỏ chữ cao nhân đi.
 
Giả dụ tôi là "cao nhân".
Tôi thỉnh cây giáo về giúp thớt làm sào phơi quần áo à?
(chắc cây giáo này dài lắm cho nên ngừoi cao mới với tới)
 
Giả dụ tôi là "cao nhân".
Tôi thỉnh cây giáo về giúp thớt làm sào phơi quần áo à?
(chắc cây giáo này dài lắm cho nên ngừoi cao mới với tới)
Cám ơn bạn đã quan tâm và chia sẻ
Bài đã được tự động gộp:

bạn gửi file lên nhé không cần gửi code mà ko có cao nhân đâu chỉ có người biết trước và người biết sau thôi nhé.ban gửi file lên đi
Cảm ơn bạn đã quan tâm. Mình gửi file rồi đó bạn
 
@QuáchThiênLong
Chạy thử code này xem sao
Mã:
Sub Permut_List()
Dim SArr As Variant
Dim Res As Variant
Dim i As Long, j As Long, k
SArr = Sheet1.Range("b4:b9")
i = UBound(SArr)
k = WorksheetFunction.Permut(i, 2)
ReDim Res(1 To k, 1 To 2)
k = 0
For i = 1 To UBound(SArr)
    For j = 1 To UBound(SArr)
        If j <> i Then
            k = k + 1
            Res(k, 1) = SArr(i, 1)
            Res(k, 2) = SArr(j, 1)
        End If
    Next j
Next i
Sheet1.Range("i4").Resize(UBound(Res), UBound(Res, 2)) = Res
End Sub
 
@QuáchThiênLong
Chạy thử code này xem sao
Mã:
Sub Permut_List()
Dim SArr As Variant
Dim Res As Variant
Dim i As Long, j As Long, k
SArr = Sheet1.Range("b4:b9")
i = UBound(SArr)
k = WorksheetFunction.Permut(i, 2)
ReDim Res(1 To k, 1 To 2)
k = 0
For i = 1 To UBound(SArr)
    For j = 1 To UBound(SArr)
        If j <> i Then
            k = k + 1
            Res(k, 1) = SArr(i, 1)
            Res(k, 2) = SArr(j, 1)
        End If
    Next j
Next i
Sheet1.Range("i4").Resize(UBound(Res), UBound(Res, 2)) = Res
End Sub
Cám ơn bạn đã giúp. Nhưng ý mình là muốn sử dụng code chung cho tất cả các trường hợp. Ví dụ mình quét vùng cần hiện bảng liệt kê giống như của tác giả Nguyễn Ngọc Thu Hiền. Khi click vào chữ RUN trong file sẽ hiện lên cửa sổ yêu cầu chọn vùng chứa các phần tử, khi đó mình sẽ chọn và cho ra kết quả
 
Cám ơn bạn đã giúp. Nhưng ý mình là muốn sử dụng code chung cho tất cả các trường hợp. Ví dụ mình quét vùng cần hiện bảng liệt kê giống như của tác giả Nguyễn Ngọc Thu Hiền. Khi click vào chữ RUN trong file sẽ hiện lên cửa sổ yêu cầu chọn vùng chứa các phần tử, khi đó mình sẽ chọn và cho ra kết quả
Cái này chắc bạn chờ thành viên khác hỗ trợ vậy.
Hình như tác giả này là thành viên của diễn đàn này hay sao đó, bạn kiếm thử xem
 
Cám ơn bạn đã giúp. Nhưng ý mình là muốn sử dụng code chung cho tất cả các trường hợp. Ví dụ mình quét vùng cần hiện bảng liệt kê giống như của tác giả Nguyễn Ngọc Thu Hiền. Khi click vào chữ RUN trong file sẽ hiện lên cửa sổ yêu cầu chọn vùng chứa các phần tử, khi đó mình sẽ chọn và cho ra kết quả
đây bạn xem code nay của bạn
CHAOQUAY
Mã:
Sub Permut_List()
Dim SArr As Variant
Dim Res As Variant
Dim i As Long, j As Long, k
SArr = Selection
i = UBound(SArr)
k = WorksheetFunction.Permut(i, 2)
ReDim Res(1 To k, 1 To 2)
k = 0
For i = 1 To UBound(SArr)
    For j = 1 To UBound(SArr)
        If j <> i Then
            k = k + 1
            Res(k, 1) = SArr(i, 1)
            Res(k, 2) = SArr(j, 1)
        End If
    Next j
Next i
Sheet1.Range("i4:j10000").ClearContents
Sheet1.Range("i4").Resize(UBound(Res), UBound(Res, 2)) = Res
End Sub
 
@snow25
Chắc là thớt muốn hiện mấy inputbox như trong sub EnumCombination của bài 1, bạn làm vài dòng cho kết thúc luôn đi bạn.
 
File gốc mình cần xử lý
 

File đính kèm

  • RElation.xlsx
    33.7 KB · Đọc: 23
File gốc mình cần xử lý
Mã:
Sub GPE()
  Dim sArr As Variant, tArr(), dArr(), Res()
  Dim i As Long, j As Long, sRow As Long, n As Long, k As Long
  Dim tmp, fRow As Long
  Const sCol As Byte = 2
 
  i = Range("E" & Rows.Count).End(xlUp).Row
  If i > 2 Then Range("E2:F" & i).ClearContents
  sArr = Application.InputBox("Chon vung chua ket qua?", "Vung chua ket qua", Type:=8)
  If TypeName(sArr) = "Variant()" Then
    If UBound(sArr, 2) = sCol And UBound(sArr) >= 2 Then
      sRow = UBound(sArr)
      ReDim tArr(0 To sRow + 1, 1 To 2)
      For i = 1 To sRow
        tArr(i, 1) = sArr(i, 2)
        If tArr(i, 1) <> tArr(i - 1, 1) Then
          If k > 0 Then n = n + k * (k - 1)
          tArr(q, 2) = k
          q = i:          k = 1
        Else
          k = k + 1
        End If
      Next i
      n = n + k * (k - 1)
      tArr(q, 2) = k
      If n = 0 Or n > Rows.Count - 3 Then Exit Sub
      
      ReDim Res(1 To n, 1 To 2)
      k = 0
      For i = 1 To sRow
        n = tArr(i, 2)
        If n > 0 Then
          For r = i To i + n - 1
            For j = i To i + n - 1
              If j <> r Then
                k = k + 1
                Res(k, 1) = sArr(r, 1):       Res(k, 2) = sArr(j, 1)
              End If
            Next j
          Next r
        End If
      Next i
      Range("E2").Resize(UBound(Res), UBound(Res, 2)) = Res
    End If
  End If
End Sub
 
Mã:
Sub GPE()
  Dim sArr As Variant, tArr(), dArr(), Res()
  Dim i As Long, j As Long, sRow As Long, n As Long, k As Long
  Dim tmp, fRow As Long
  Const sCol As Byte = 2

  i = Range("E" & Rows.Count).End(xlUp).Row
  If i > 2 Then Range("E2:F" & i).ClearContents
  sArr = Application.InputBox("Chon vung chua ket qua?", "Vung chua ket qua", Type:=8)
  If TypeName(sArr) = "Variant()" Then
    If UBound(sArr, 2) = sCol And UBound(sArr) >= 2 Then
      sRow = UBound(sArr)
      ReDim tArr(0 To sRow + 1, 1 To 2)
      For i = 1 To sRow
        tArr(i, 1) = sArr(i, 2)
        If tArr(i, 1) <> tArr(i - 1, 1) Then
          If k > 0 Then n = n + k * (k - 1)
          tArr(q, 2) = k
          q = i:          k = 1
        Else
          k = k + 1
        End If
      Next i
      n = n + k * (k - 1)
      tArr(q, 2) = k
      If n = 0 Or n > Rows.Count - 3 Then Exit Sub
     
      ReDim Res(1 To n, 1 To 2)
      k = 0
      For i = 1 To sRow
        n = tArr(i, 2)
        If n > 0 Then
          For r = i To i + n - 1
            For j = i To i + n - 1
              If j <> r Then
                k = k + 1
                Res(k, 1) = sArr(r, 1):       Res(k, 2) = sArr(j, 1)
              End If
            Next j
          Next r
        End If
      Next i
      Range("E2").Resize(UBound(Res), UBound(Res, 2)) = Res
    End If
  End If
End Sub
Cám ơn bạn đã quan tâm, nhưng code của bạn giúp ko chạy được
 
Web KT

Bài viết mới nhất

Back
Top Bottom