.Mình dính một đề bài xếp loại học sinh có 2 điều kiện như file ví dụ. Mong các cao thủ giúp đỡ công thức hàm excel ạ. Hoặc vba cũng được, làm sao cho đơn giản nhất ạ. Cảm ơn các bạn.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) <> "M3" Then Exit Sub
Dim lr&, i&, j&, k&, g&, rng, arr()
lr = Cells(Rows.Count, "B").End(xlUp).Row
g = WorksheetFunction.CountIf(Range("C4:G" & lr), Target)
ReDim arr(1 To g, 1 To 2)
rng = Range("B3:G" & lr).Value
For i = 2 To UBound(rng)
For j = 2 To UBound(rng, 2)
If rng(i, j) Like Target Then
k = k + 1
arr(k, 1) = rng(i, 1)
arr(k, 2) = rng(1, j)
End If
Next
Next
Range("L6:M10000").ClearContents
Range("L6").Resize(UBound(arr), 2).Value = arr
End Sub
Bạn cứ xưng hô trân phương kiểu như Anh/Chị được rồi, không cần cao nhân... gì đâu nhé!Mình dính một đề bài xếp loại học sinh có 2 điều kiện như file ví dụ. Mong các cao thủ giúp đỡ công thức hàm excel ạ. Hoặc vba cũng được, làm sao cho đơn giản nhất ạ. Cảm ơn các bạn.
Sub GPE()
Dim Arr(), Res(), i As Long, j As Long, k As Long
Dim Lr As Long
On Error Resume Next
With Sheets("Sheet1")
Lr = .Range("B" & Rows.Count).End(xlUp).Row
Arr = .Range("B3:G" & Lr).Value
ReDim Res(1 To UBound(Arr, 1) * 5, 1 To 2)
For i = 2 To UBound(Arr, 1)
For j = 2 To UBound(Arr, 2)
If UCase(Arr(i, j)) = "GI" & ChrW(7886) & "I" Then
k = k + 1
Res(k, 1) = Arr(i, 1)
Res(k, 2) = Arr(1, j)
End If
Next j
Next i
.Range("O6:P1000").ClearContents
.Range("O6").Resize(k, 2).Value = Res
End With
End Sub
Vâng ạ, rất cảm ơn anh chị đã giúp đỡ. Code chạy rất ok ạ. Mình còn 1 vấn đề nữa mong các a.c giúp luôn ạ.Bạn cứ xưng hô trân phương kiểu như Anh/Chị được rồi, không cần cao nhân... gì đâu nhé!
Tại sao lại sử dụng hàm countif tìm kiếm tuyệt đối.Rồi lấy để chọn kích thước mảng cho tìm kiếm tương đối anh.VBA nhé.
Click chuột phải vào tên sheet, View Code rồi dán code này vào.
Chọn các giá trị tại ô M3:
Mã:Option Explicit Private Sub Worksheet_Change(ByVal Target As Range) If Target.Address(0, 0) <> "M3" Then Exit Sub Dim lr&, i&, j&, k&, g&, rng, arr() lr = Cells(Rows.Count, "B").End(xlUp).Row g = WorksheetFunction.CountIf(Range("C4:G" & lr), Target) ReDim arr(1 To g, 1 To 2) rng = Range("B3:G" & lr).Value For i = 2 To UBound(rng) For j = 2 To UBound(rng, 2) If rng(i, j) Like Target Then k = k + 1 arr(k, 1) = rng(i, 1) arr(k, 2) = rng(1, j) End If Next Next Range("L6:M10000").ClearContents Range("L6").Resize(UBound(arr), 2).Value = arr End Sub
(Theo tiếp í tưởng #4) thì mỗi trang tính cần thiết danh sách 1 loại kết quả học lực nào đó của HS ta nên để macro sự kiện khi kích hoạt trang tính đó. . . . . .. Mình còn 1 vấn đề nữa mong các a.c giúp luôn ạ.
Mình muốn kết quả sẽ nằm ở 1 sheet khác, mỗi loại học sinh nằm sang 1 sheet khác nhau thì phải làm thế nào ạ.
Private Sub Worksheet_Activate()
GPE [M3].Value
End Sub
Sub GPE(HL As String)
Dim Rng As Range, sRng As Range
Dim MyAdd As String: Dim W As Integer
With Sheet1
Set Rng = .[c3].CurrentRegion
[L6].CurrentRegion.Offset(1).ClearContents
W = Rng.Cells.Count
ReDim Arr(1 To W, 1 To 2) As String: W = 0
6 Set sRng = Rng.Find(HL, , xlFormulas, xlWhole)
If Not sRng Is Nothing Then
MyAdd = sRng.Address
Do
W = W + 1
Arr(W, 1) = .Cells(sRng.Row, "B").Value
Arr(W, 2) = .Cells(3, sRng.Column).Value
Set sRng = Rng.FindNext(sRng)
Loop While Not sRng Is Nothing And sRng.Address <> MyAdd
End If
[L6].Resize(W, 2).Value = Arr(): Randomize
[L5:M5].Interior.ColorIndex = 34 + 9 * Rnd() \ 1
End With
End Sub
Thử công thức dưới:Mình dính một đề bài xếp loại học sinh có 2 điều kiện như file ví dụ. Mong các cao thủ giúp đỡ công thức hàm excel ạ. Hoặc vba cũng được, làm sao cho đơn giản nhất ạ. Cảm ơn các bạn.
L6=IFERROR(INDEX($B$4:$B$14,AGGREGATE(15,6,(ROW($B$4:$B$14)-3)/($C$4:$G$14="Giỏi"),ROW(A1))),"")
M6=IFERROR(INDEX($C$3:$G$3,AGGREGATE(15,6,(COLUMN($C$3:$G$3)-2)/(INDEX($C$4:$G$14,MATCH(L6,$B$4:$B$14,0),)="Giỏi"),COUNTIF($L$6:L6,L6))),"")
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
Unpivot1 = Table.UnpivotOtherColumns(Source, {"Tên Học Viên"}, "Năm đạt giỏi", "Value"),
SelectA = Table.SelectRows(Unpivot1, each ([Value] = "Giỏi")),
RemoveA = Table.RemoveColumns(SelectA,{"Value"})
in
RemoveA
Không biết những người hay dùng từ ngữ loại này có bao giờ nhờ các đồng nghiệp cùng phòng, hay cùng cơ quan:Cứ nghe thấy chữ cao thủ là vào chỉ dám đọc, không dám ho luôn.
Bạn có thể dùng code nàyVâng ạ, rất cảm ơn anh chị đã giúp đỡ. Code chạy rất ok ạ. Mình còn 1 vấn đề nữa mong các a.c giúp luôn ạ.
Mình muốn kết quả sẽ nằm ở 1 sheet khác, mỗi loại học sinh nằm sang 1 sheet khác nhau thì phải làm thế nào ạ.
Sub GPE()
Dim Arr(), Res(), i As Long, j As Long, k As Long, Ws As Worksheet
Dim Lr As Long, l As Long, m As Long, Res1(), Res2()
On Error Resume Next
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each Ws In Worksheets
If Ws.Name <> "Sheet1" Then
Ws.Delete
End If
Next Ws
With Sheets("Sheet1")
Lr = .Range("B" & Rows.Count).End(xlUp).Row
Arr = .Range("B3:G" & Lr).Value
ReDim Res(1 To UBound(Arr, 1) * 5, 1 To 2)
ReDim Res1(1 To UBound(Arr, 1) * 5, 1 To 2)
ReDim Res2(1 To UBound(Arr, 1) * 5, 1 To 2)
For i = 2 To UBound(Arr, 1)
For j = 2 To UBound(Arr, 2)
If UCase(Arr(i, j)) = "GI" & ChrW(7886) & "I" Then
k = k + 1
Res(k, 1) = Arr(i, 1)
Res(k, 2) = Arr(1, j)
ElseIf UCase(Arr(i, j)) = "KHチ" Then
l = l + 1
Res1(l, 1) = Arr(i, 1)
Res1(l, 2) = Arr(1, j)
ElseIf UCase(Arr(i, j)) = "TRUNG BフNH" Then
m = m + 1
Res2(m, 1) = Arr(i, 1)
Res2(m, 2) = Arr(1, j)
End If
Next j
Next i
If k Then
Worksheets.Add after:=Sheets(Sheets.Count)
ActiveSheet.Name = "GI" & ChrW(7886) & "I"
ActiveSheet.Range("B2").Resize(k, 2).Value = Res
End If
If l Then
Worksheets.Add after:=Sheets(Sheets.Count)
ActiveSheet.Name = "KHチ"
ActiveSheet.Range("B2").Resize(l, 2).Value = Res1
End If
If m Then
Worksheets.Add after:=Sheets(Sheets.Count)
ActiveSheet.Name = "TRUNG BフNH"
ActiveSheet.Range("B2").Resize(m, 2).Value = Res2
End If
End With
Application.ScreenUpdating = True
Application.DisplayAlerts = True
MsgBox "Ho瀟 th瀟h"
End Sub
Thanks bạn rất nhiều, nhưng sau 1 tuần vật vã với cái file này thì mình xin bó tayBạn có thể dùng code này
PHP:Sub GPE() Dim Arr(), Res(), i As Long, j As Long, k As Long, Ws As Worksheet Dim Lr As Long, l As Long, m As Long, Res1(), Res2() On Error Resume Next Application.ScreenUpdating = False Application.DisplayAlerts = False For Each Ws In Worksheets If Ws.Name <> "Sheet1" Then Ws.Delete End If Next Ws With Sheets("Sheet1") Lr = .Range("B" & Rows.Count).End(xlUp).Row Arr = .Range("B3:G" & Lr).Value ReDim Res(1 To UBound(Arr, 1) * 5, 1 To 2) ReDim Res1(1 To UBound(Arr, 1) * 5, 1 To 2) ReDim Res2(1 To UBound(Arr, 1) * 5, 1 To 2) For i = 2 To UBound(Arr, 1) For j = 2 To UBound(Arr, 2) If UCase(Arr(i, j)) = "GI" & ChrW(7886) & "I" Then k = k + 1 Res(k, 1) = Arr(i, 1) Res(k, 2) = Arr(1, j) ElseIf UCase(Arr(i, j)) = "KHチ" Then l = l + 1 Res1(l, 1) = Arr(i, 1) Res1(l, 2) = Arr(1, j) ElseIf UCase(Arr(i, j)) = "TRUNG BフNH" Then m = m + 1 Res2(m, 1) = Arr(i, 1) Res2(m, 2) = Arr(1, j) End If Next j Next i If k Then Worksheets.Add after:=Sheets(Sheets.Count) ActiveSheet.Name = "GI" & ChrW(7886) & "I" ActiveSheet.Range("B2").Resize(k, 2).Value = Res End If If l Then Worksheets.Add after:=Sheets(Sheets.Count) ActiveSheet.Name = "KHチ" ActiveSheet.Range("B2").Resize(l, 2).Value = Res1 End If If m Then Worksheets.Add after:=Sheets(Sheets.Count) ActiveSheet.Name = "TRUNG BフNH" ActiveSheet.Range("B2").Resize(m, 2).Value = Res2 End If End With Application.ScreenUpdating = True Application.DisplayAlerts = True MsgBox "Ho瀟 th瀟h" End Sub
Tôi nghĩ chắc bạn bị vướng hay nhầm lẫn chỗ nào đó thôi.Thanks bạn rất nhiều, nhưng sau 1 tuần vật vã với cái file này thì mình xin bó tay. Vẫn phải học hỏi... gần như lại từ đầu ạ.
Code trên chạy ổn trong file với ít biến, nhiều hơn nữa máy mình đơ luôn, với lại khai báo thêm biến rất nhiều.
Code của anh mình ưng ý nhất nhưng khi áp dụng vào file mình làm thì không thành công, cái vấn đề là mình ngu lập trình nên đọc chỉ hiểu sơ sơ, không phát triển được.
bebo021999
Mấy a chị giúp e phát nữa, chứ e cũng đã thử đủ cách vẫn không hiểu được ạ, thử đủ cách mà không bắt được activate sheet nên có khi nó đè luôn lên sheet data - out of memory luôn. Query của gg sheet thì e làm được nhưng cũng chỉ trong sheet đó thôi, nhảy qua sheet khác hoặc tạo theo kiểu nhấn từng cái trong combo box thì cũng k được.
Tôi nghĩ chắc bạn bị vướng hay nhầm lẫn chỗ nào đó thôi.
Nếu tiện bạn có thể gửi file gốc qua zalo, có thời gian tôi sẽ xem lại cho bạn!
thân!
Sub Splitdatabycol()
'updateby Extendoffice
Dim lr As Long
Dim ws As Worksheet
Dim vcol, i As Integer
Dim icol As Long
Dim myarr As Variant
Dim title As String
Dim titlerow As Integer
Dim xTRg As Range
Dim xVRg As Range
Dim xWSTRg As Worksheet
Dim xWS As Worksheet
On Error Resume Next
Set xTRg = Application.InputBox("Please select the header rows:", "Kutools for Excel", "", Type:=8)
If TypeName(xTRg) = "Nothing" Then Exit Sub
Set xVRg = Application.InputBox("Please select the column you want to split data based on:", "Kutools for Excel", "", Type:=8)
If TypeName(xVRg) = "Nothing" Then Exit Sub
vcol = xVRg.Column
Set ws = xTRg.Worksheet
lr = ws.Cells(ws.Rows.Count, vcol).End(xlUp).Row
title = xTRg.AddressLocal
titlerow = xTRg.Cells(1).Row
icol = ws.Columns.Count
ws.Cells(1, icol) = "Unique"
Application.DisplayAlerts = False
If Not Evaluate("=ISREF('xTRgWs_Sheet!A1')") Then
Sheets.Add(after:=Worksheets(Worksheets.Count)).Name = "xTRgWs_Sheet"
Else
Sheets("xTRgWs_Sheet").Delete
Sheets.Add(after:=Worksheets(Worksheets.Count)).Name = "xTRgWs_Sheet"
End If
Set xWSTRg = Sheets("xTRgWs_Sheet")
xTRg.Copy
xWSTRg.Paste Destination:=xWSTRg.Range("A1")
ws.Activate
For i = (titlerow + xTRg.Rows.Count) To lr
On Error Resume Next
If ws.Cells(i, vcol) <> "" And Application.WorksheetFunction.Match(ws.Cells(i, vcol), ws.Columns(icol), 0) = 0 Then
ws.Cells(ws.Rows.Count, icol).End(xlUp).Offset(1) = ws.Cells(i, vcol)
End If
Next
myarr = Application.WorksheetFunction.Transpose(ws.Columns(icol).SpecialCells(xlCellTypeConstants))
ws.Columns(icol).Clear
For i = 2 To UBound(myarr)
ws.Range(title).AutoFilter field:=vcol, Criteria1:=myarr(i) & ""
If Not Evaluate("=ISREF('" & myarr(i) & "'!A1)") Then
Set xWS = Sheets.Add(after:=Worksheets(Worksheets.Count))
xWS.Name = myarr(i) & ""
Else
xWS.Move after:=Worksheets(Worksheets.Count)
End If
xWSTRg.Range(title).Copy
xWS.Paste Destination:=xWS.Range("A1")
ws.Range("A" & (titlerow + xTRg.Rows.Count) & ":A" & lr).EntireRow.Copy xWS.Range("A" & (titlerow + xTRg.Rows.Count))
Sheets(myarr(i) & "").Columns.AutoFit
Next
xWSTRg.Delete
ws.AutoFilterMode = False
ws.Activate
Application.DisplayAlerts = True
End Sub
Option Explicit
Sub xeploai()
Dim lr&, i&, j&, k&, rng
Dim ip As String, xL, xL2, dk As String, arr(1 To 100000, 1 To 2)
ip = InputBox(" Chon Xep Loai: (xs: xuat sac / g:gioi / k: kha / tb: trung binh / y: yeu)")
If Len(ip) = 0 Then Exit Sub
xL = Array("xs", "g", "k", "tb", "y")
xL2 = Array("xuat sac", "gioi", "kha", "trung binh", "yeu")
For i = 0 To UBound(xL)
If ip = xL(i) Then
dk = xL2(i)
Exit For
End If
Next
If dk = "" Then Exit Sub
With Sheets("data")
lr = .Cells(Rows.Count, "B").End(xlUp).Row
rng = .Range("B4:H" & lr).Value
For i = 2 To UBound(rng)
For j = 2 To UBound(rng, 2)
If Trim(rng(i, j)) Like dk Then
k = k + 1
arr(k, 1) = rng(i, 1)
arr(k, 2) = rng(1, j)
End If
Next
Next
End With
If Not Evaluate("=ISREF('" & dk & "'!A1)") Then
Sheets.Add after:=Sheets(Sheets.Count)
With ActiveSheet
.Name = dk
.Range("A1").Value = .Name
End With
End If
Sheets(dk).Activate
Range("G8:H100000").ClearContents
Range("G8").Resize(k, 2).Value = arr
Range("G1:H1").EntireColumn.AutoFit
End Sub
E không biết nói gì hơn, cảm ơn anh rất nhiềuDùng đỡ cái này:
Mã:Option Explicit Sub xeploai() Dim lr&, i&, j&, k&, rng Dim ip As String, xL, xL2, dk As String, arr(1 To 100000, 1 To 2) ip = InputBox(" Chon Xep Loai: (xs: xuat sac / g:gioi / k: kha / tb: trung binh / y: yeu)") If Len(ip) = 0 Then Exit Sub xL = Array("xs", "g", "k", "tb", "y") xL2 = Array("xuat sac", "gioi", "kha", "trung binh", "yeu") For i = 0 To UBound(xL) If ip = xL(i) Then dk = xL2(i) Exit For End If Next If dk = "" Then Exit Sub With Sheets("data") lr = .Cells(Rows.Count, "B").End(xlUp).Row rng = .Range("B4:H" & lr).Value For i = 2 To UBound(rng) For j = 2 To UBound(rng, 2) If Trim(rng(i, j)) Like dk Then k = k + 1 arr(k, 1) = rng(i, 1) arr(k, 2) = rng(1, j) End If Next Next End With If Not Evaluate("=ISREF('" & dk & "'!A1)") Then Sheets.Add after:=Sheets(Sheets.Count) With ActiveSheet .Name = dk .Range("A1").Value = .Name End With End If Sheets(dk).Activate Range("G8:H100000").ClearContents Range("G8").Resize(k, 2).Value = arr Range("G1:H1").EntireColumn.AutoFit End Sub
Cách của bác rất hay, mình đã học được nhiều từ mấy hàm của bác.
Office 365 bạn thử công thức này xem (dán công thức vào ô trống nào đó - File bài #1):Cách của bác rất hay, mình đã học được nhiều từ mấy hàm của bác.
Chỉ góp ý nhỏ xíu, chỗ lập mảng ở "Năm đạt loại giỏi", dùng hàm MID thì khi số lượng năm lớn hơn 10, VD từ năm 99 đến 2019 chẳng hạn, số thứ tự của cột nó là 2 chữ số mà Hàm MID chỉ lấy được 1 chữ số.
Mình dùng hàm textsplit như sau =INDEX(C3:G3,TEXTSPLIT(TEXTJOIN(";",1,IF(I4=C4:G14,COLUMN(C4:G14)-2,"")),,";")) đã giải quyết đc nó.
=LET(ar,TOCOL(LET(a,B3:G14,MAP(a,LAMBDA(x,IF(x<>"Giỏi",NA(),INDEX(a,ROW(x)-2,1)&"|"&INDEX(a,1,COLUMN(x)-1))))),3),r,ROWS(ar),MAKEARRAY(r,2,LAMBDA(y,z,INDEX(TEXTSPLIT(INDEX(ar,y,1),"|"),,z))))
=TEXTSPLIT(TEXTJOIN("`",1,LET(a,B3:G14,MAP(a,LAMBDA(x,IF(x<>"Giỏi","",INDEX(a,ROW(x)-2,1)&"|"&INDEX(a,1,COLUMN(x)-1)))))),"|","`")
Anh bebo cho em hỏi với cùng 1 cách này, mình không tạo sheet mới nữa, mà tạo workbook mới (tên wb và tên sheet mới tạo ra giống nhau) được không ạ? E có khai báo thêm 2 Function và sửa code tạo sheet thành như ở dưới mà chạy toàn bị báo lỗi out of range hoặc type missmath ko à.Dùng đỡ cái này:
Mã:Option Explicit Sub xeploai() Dim lr&, i&, j&, k&, rng Dim ip As String, xL, xL2, dk As String, arr(1 To 100000, 1 To 2) ip = InputBox(" Chon Xep Loai: (xs: xuat sac / g:gioi / k: kha / tb: trung binh / y: yeu)") If Len(ip) = 0 Then Exit Sub xL = Array("xs", "g", "k", "tb", "y") xL2 = Array("xuat sac", "gioi", "kha", "trung binh", "yeu") For i = 0 To UBound(xL) If ip = xL(i) Then dk = xL2(i) Exit For End If Next If dk = "" Then Exit Sub With Sheets("data") lr = .Cells(Rows.Count, "B").End(xlUp).Row rng = .Range("B4:H" & lr).Value For i = 2 To UBound(rng) For j = 2 To UBound(rng, 2) If Trim(rng(i, j)) Like dk Then k = k + 1 arr(k, 1) = rng(i, 1) arr(k, 2) = rng(1, j) End If Next Next End With If Not Evaluate("=ISREF('" & dk & "'!A1)") Then Sheets.Add after:=Sheets(Sheets.Count) With ActiveSheet .Name = dk .Range("A1").Value = .Name End With End If Sheets(dk).Activate Range("G8:H100000").ClearContents Range("G8").Resize(k, 2).Value = arr Range("G1:H1").EntireColumn.AutoFit End Sub
Option Explicit
Sub xeploai()
Dim lr&, i&, j&, k&, rng, sFileName As String, wb As Workbook, oldWb As Workbook, sWbName As Workbook,
Dim ip As String, xL, xL2, dk As String, arr(1 To 100000, 1 To 2)
ip = InputBox(" Chon Xep Loai: (xs: xuat sac / g:gioi / k: kha / tb: trung binh / y: yeu)")
If Len(ip) = 0 Then Exit Sub
xL = Array("xs", "g", "k", "tb", "y")
xL2 = Array("xuat sac", "gioi", "kha", "trung binh", "yeu")
For i = 0 To UBound(xL)
If ip = xL(i) Then
dk = xL2(i)
Exit For
End If
Next
If dk = "" Then Exit Sub
oldWb.Activate
With Sheets("data")
sFileName = dk & ".xlsx"
If Not GetWb(sFileName, wb) & Evaluate("=ISREF('" & dk & "'!A1)") Then
Set wb = CreateNewWb(sFileName)
wb.Sheets.Add after:=Sheets(Sheets.Count)
With ActiveSheet
.Name = dk
.Range("A1").Value = .Name
End With
oldWb.Activate
End If
lr = .Cells(Rows.Count, "B").End(xlUp).Row
rng = .Range("B4:H" & lr).Value
For i = 2 To UBound(rng)
For j = 2 To UBound(rng, 2)
If Trim(rng(i, j)) Like dk Then
k = k + 1
arr(k, 1) = rng(i, 1)
arr(k, 2) = rng(1, j)
End If
Next
Next
End With
sWbName.Sheets(dk).Activate
Range("G8:H100000").ClearContents
Range("G8").Resize(k, 2).Value = arr
Range("G1:H1").EntireColumn.AutoFit
lbFinally:
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationSemiautomatic
If Err <> 0 Then
MsgBox Err.Description, vbCritical
End If
End Sub
Function GetWb(sWbName As String, wb As Workbook) As Boolean
Dim dk As Long
'sWbName = LCase(sWbName)
For G = 1 To Workbooks.Count
If Workbooks(G).Name = sWbName Then
GetWb = True
Set wb = Workbooks(G)
Exit Function
End If
Next G
End Function
Function CreateNewWb(sWbName As String) As Workbook
Dim oldWb As Workbook
Set oldWb = ActiveWorkbook
Set CreateNewWb = Workbooks.Add
CreateNewWb.SaveAs sWbName
oldWb.Activate
End Function