Nhờ giúp học Excel bằng bài toán lọc từng Công ty ra 1 Sheet riêng

  • Thread starter Thread starter LinDan
  • Ngày gửi Ngày gửi
Liên hệ QC

LinDan

Thành viên tiêu biểu
Tham gia
8/2/12
Bài viết
412
Được thích
111
Từ bảng theo dõi Tổng hợp, tôi muốn tách, lọc dữ liệu theo tiêu chí: Mỗi Công ty tách ra một bảng riêng, ứng với mỗi bảng nằm ở 1 Sheet mới được tạo ra (Công ty A được theo dõi ở SheetA, Công ty B sẽ được theo dõi ở SheetB)

Trong file đính kèm xin trích mẫu kết quả cho mọi người dễ hình dung

Xin trân trọng cảm ơn
-------------------
Xin làm giúp bằng VBA càng tốt (tôi đang cần học nó)
 

File đính kèm

Lần chỉnh sửa cuối:
Từ bảng theo dõi Tổng hợp, tôi muốn tách, lọc dữ liệu theo tiêu chí: Mỗi Công ty tách ra một bảng riêng, ứng với mỗi bảng nằm ở 1 Sheet mới được tạo ra (Công ty A được theo dõi ở SheetA, Công ty B sẽ được theo dõi ở SheetB)

Trong file đính kèm xin trích mẫu kết quả cho mọi người dễ hình dung

Xin trân trọng cảm ơn
-------------------
Xin làm giúp bằng VBA càng tốt (tôi đang cần học nó)
Nghiêu cứu bài 341 topic sau.
http://www.giaiphapexcel.com/forum/showthread.php?46834-Các-câu-hỏi-về-mảng-trong-VBA-(Array)/page35
 
Upvote 0
Sao tôi chạy bài http://www.giaiphapexcel.com/forum/showthread.php?46834-Các-câu-hỏi-về-mảng-trong-VBA-(Array)/page35 thì thấy báo lỗi, bôi màu vàng ở isValidWshName hả anh.

Code trong bài đó tôi lấy ở bài của anh như sau:

PHP:
Sub TonghopArr()
  Dim sArray, subArr(), Arr(), i As Long, Title, nR&, k&, n&
  Dim tmpR As Long, p As Long, lC As Long, keyArr, WshName As String
  Dim Dic As Object, Tmp As String, ArrBP()
  Dim T
  T = Timer
  Set Dic = CreateObject("Scripting.Dictionary")
  Application.ScreenUpdating = False
  With Sheets("Data")
    sArray = .Range("A5:E60000").Value
    Title = .Range("A4:E4").Value
  End With
  For i = 1 To UBound(sArray, 1)
    If Len(CStr(sArray(i, 2))) Then
      Tmp = CStr(sArray(i, 2))
      If Not Dic.Exists(Tmp) Then
        n = n + 1
        Dic.Add Tmp, n
        ReDim Preserve ArrBP(1 To n)
      End If
      nR = Dic.Item(Tmp)
      If Len(ArrBP(nR)) Then
        ArrBP(nR) = ArrBP(nR) & vbBack & i
      Else
        ArrBP(nR) = i
      End If
    End If
  Next
 For i = 1 To UBound(ArrBP)
    nR = 0
    Tmp = CStr(ArrBP(i))
    aSplit = Split(Tmp, vbBack)
    ReDim subArr(1 To UBound(aSplit) + 1, 1 To UBound(sArray, 2))
    For j = 0 To UBound(aSplit)
      nR = nR + 1
      For k = 1 To UBound(sArray, 2)
        subArr(nR, k) = sArray(aSplit(j), k)
      Next k
    Next j
    WshName = CStr(subArr(1, 2))
    If isValidWshName(WshName) Then
      If Not SheetExist(WshName) Then
        Sheets.Add(After:=Sheets(Sheets.Count)).Name = WshName
      End If
    End If
    With Sheets(WshName)
      .UsedRange.ClearContents
      .Range("A1").Resize(, UBound(sArray, 2)).Value = Title
      .Range("A2").Resize(UBound(aSplit) + 1, UBound(sArray, 2)) = subArr
    End With
  Next i
  Application.ScreenUpdating = True
MsgBox Timer - T
End Sub

Rất mong anh chỉ cho, tôi đang rất quan tâm đến loại này vì hàng tháng tôi đều phải làm.
 
Lần chỉnh sửa cuối:
Upvote 0
Chép tiếp UDF của anh NDU bài trước đó vào code. Do thiếu UDF đó nên báo lỗi.
và cũng nên học cách nhấn F8 và F9 khi chạy code từng bước. Google sẽ biết.
PHP:
Function SheetExist(ByVal WshName As String) As Boolean
  On Error Resume Next
  SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing
End Function
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
 
Upvote 0
Được rồi bác ah, nhưng sao lại phải tách ra nhiều đoạn phức tạp thế vừa Sub lại vừa Funtion (sao không gộp vào cho gọn) hả bác
 
Upvote 0
Được rồi bác ah, nhưng sao lại phải tách ra nhiều đoạn phức tạp thế vừa Sub lại vừa Funtion (sao không gộp vào cho gọn) hả bác
Đặc thù của UDF là hàm và nó lập lại nhiều lần và có thể dùng độc lập nên mới tách ra.
Thử làm 1 code về ứng dụng UDF sẽ thấy ngay.
 
Upvote 0
Xin bác Thu Nghi và mọi người giới thiệu giúp tôi vài ví dụ nhỏ về UDF để tôi tìm hiểu.

Nếu UDF là sản phẩm đã được thày Ndu96081631 dùng thì chắc chắn là rất hay, vì đọc các bài của thày trên diễn đàn, bài nào tôi cũng thấy cách xử lý của thày gần như là tối ưu nhất, rất khoa học và có rất nhiều chiêu hay.
 
Upvote 0
Như là mình thì mình chỉ để 2 trang tính mà thôi;
1 là CSDL & 2 là Report; Cần số liệu CTi nào thì réo nó ra trang Report;
 
Upvote 0
Xin bác Thu Nghi và mọi người giới thiệu giúp tôi vài ví dụ nhỏ về UDF để tôi tìm hiểu.

Nếu UDF là sản phẩm đã được thày Ndu96081631 dùng thì chắc chắn là rất hay, vì đọc các bài của thày trên diễn đàn, bài nào tôi cũng thấy cách xử lý của thày gần như là tối ưu nhất, rất khoa học và có rất nhiều chiêu hay.
PHP:
Sub TestUDF()
Dim shName$
shName = "11/"
If isValidWshName(shName) Then
  MsgBox shName & " is OK"
Else
  MsgBox shName & " is  not OK"
End If
End Sub
PHP:
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
UDF này có nhiệm vụ kiểm tra có những ký tự ":\/?*[]" trong shName (tên sh) vì nếu có là sai.
Ráng vận dụng để thay vì tạo sh mới thì tạo luôn 1 file mới, mỗi file là mỗi khách hàng, về if ngon nữa thì mỗi sh là mỗi tháng.
Đúng ra những bài toán tách sh của bạn thì mình sort data sau đó for mà tách thì nhanh hơn và chả cần Dic gì cả. Có thể copy Data sang sh Tmp, sort, xử lý, sau đó xóa sh tmp.
 
Lần chỉnh sửa cuối:
Upvote 0
Xin cho biết UDF là viết tắt của từ gì vậy, tôi hoàn toàn mù mờ về cái này, tôi thấy trên diễn đàn rất hay nói đến nó, xin hãy phân tích dùm tôi về đối tượng này.

Xin cảm ơn các bác
 
Lần chỉnh sửa cuối:
Upvote 0
Xin cho biết UDF là viết tắt của từ gì vậy, tôi hoàn toàn mù mờ về cái này, tôi thấy trên diễn đàn rất hay nói đến nó, xin hãy phân tích dùm tôi về đối tượng này.

Xin cảm ơn các bác
UDF là User Define Function, có thể hiểu là hàm tự tạo, nó chẳng qua là những Function mà chúng ta vẫn xây dựng trong chương trình đó mà.
 
Upvote 0
Xin các bác giảng giải dùm em ý nghĩa của đoạn sau với ah:

PHP:
Function SheetExist(ByVal WshName As String) As Boolean
  On Error Resume Next
  SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing
End Function
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
 
Upvote 0
Xin cho biết UDF là viết tắt của từ gì vậy, tôi hoàn toàn mù mờ về cái này, tôi thấy trên diễn đàn rất hay nói đến nó, xin hãy phân tích dùm tôi về đối tượng này.

Xin cảm ơn các bác
Là User Defined Function, nghĩa là hàm tự tạo
Đôi khi các hàm có sẵn không đáp ứng được nhu cầu (như trường hợp kiểm tra sự tồn tại và tính hợp lệ của tên sheet ở trên)... Vậy thì ta phải tự mình viết lấy hàm phục vụ cho mình thôi
Muốn dùng UDF trên bảng tính như những hàm có sẵn khác, chỉ cần bấm nút f(x), bấm mũi tên xổ xuống, chọn User Defined sẽ thấy ngay hàm của ta
Ẹc... Ẹc...
 
Upvote 0
Xin thày Ndu gợi ý cho 2 cái hàm thày viết nhằm mục đích phục vụ gì cho Sub ở trên, mục đích của tôi là muốn biết được tầm quan trọng của nó, tại sao nó không thể viết chung cùng với Sub hay bản thân nó còn phục vụ cho nhiều trường hợp khác?

PHP:
Function SheetExist(ByVal WshName As String) As Boolean
  On Error Resume Next
  SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing
End Function
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
 
Upvote 0
Xin thày Ndu gợi ý cho 2 cái hàm thày viết nhằm mục đích phục vụ gì cho Sub ở trên, mục đích của tôi là muốn biết được tầm quan trọng của nó, tại sao nó không thể viết chung cùng với Sub hay bản thân nó còn phục vụ cho nhiều trường hợp khác?

PHP:
Function SheetExist(ByVal WshName As String) As Boolean
  On Error Resume Next
  SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing
End Function
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
Hàm SheetExist dùng để kiểm tra xem tên sheet mà ta chuẩn bị đặt cho 1 sheet nào đó có tồn tại không (vì tên sheet có rồi sao đặt được)
Hàm isValidWshName dùng để kiểm tra xem tên sheet mà ta chuẩn bị đặt cho 1 sheet nào đó có hợp lệ hay không (vì tên sheet có những quy tắc riêng, không phải muốn đặt bằng ký tự gì cũng được)
 
Upvote 0
Xin cảm ơn thày Ndu, mấy bài trước đọc về Sub tính toán đơn giản, nhìn hàm của thày lạ quá nên không hiểu, xin nhờ thày giải thích giúp: số 31 nó có ý nghĩa thế nào vậy (sao không là số khác).

PHP:
Function SheetExist(ByVal WshName As String) As Boolean
  On Error Resume Next
  SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing
End Function
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
 
Upvote 0
Xin cảm ơn thày Ndu, mấy bài trước đọc về Sub tính toán đơn giản, nhìn hàm của thày lạ quá nên không hiểu, xin nhờ thày giải thích giúp: số 31 nó có ý nghĩa thế nào vậy (sao không là số khác).
Bạn cứ thử đổi tên sheet và gõ dãy ký tự hợp lệ (chữ "b" chẳng hạn) cho đến khi nào không được nữa thì dừng lại. Đếm số lượng ký tự này, bạn sẽ biết vì sao có con số 31.
 
Upvote 0
Mong bác ThuNghi và mọi người giúp tôi: ArrBP(nR) = ArrBP(nR) & vbBack & i nghĩa là gì đấy ah, trong Code sau để làm gì hả các bác

PHP:
Sub TonghopArr()
  Dim DL, KQ(), Arr(), i As Long, Title, nR&, k&, n&
  Dim tmpR As Long, p As Long, lC As Long, keyArr, WshName As String
  Dim Dic As Object, Tmp As String, ArrBP()
  Dim T
  T = Timer
  Set Dic = CreateObject("Scripting.Dictionary")
  Application.ScreenUpdating = False
  With Sheets("Data")
    DL = .Range("A5:E60000").Value
    Title = .Range("A4:E4").Value
  End With
  For i = 1 To UBound(DL, 1)
    If Len(CStr(DL(i, 2))) Then
      Tmp = CStr(DL(i, 2))
      If Not Dic.Exists(Tmp) Then
        n = n + 1
        Dic.Add Tmp, n
        ReDim Preserve ArrBP(1 To n)
      End If
      nR = Dic.Item(Tmp)
      If Len(ArrBP(nR)) Then
        ArrBP(nR) = ArrBP(nR) & vbBack & i
      Else
        ArrBP(nR) = i
      End If
    End If
  Next
 For i = 1 To UBound(ArrBP)
    nR = 0
    Tmp = CStr(ArrBP(i))
    aSplit = Split(Tmp, vbBack)
    ReDim KQ(1 To UBound(aSplit) + 1, 1 To UBound(DL, 2))
    For j = 0 To UBound(aSplit)
      nR = nR + 1
      For k = 1 To UBound(DL, 2)
        KQ(nR, k) = DL(aSplit(j), k)
      Next k
    Next j
    WshName = CStr(KQ(1, 2))
    If isValidWshName(WshName) Then
      If Not SheetExist(WshName) Then
        Sheets.Add(After:=Sheets(Sheets.Count)).Name = WshName
      End If
    End If
    With Sheets(WshName)
      .UsedRange.ClearContents
      .Range("A1").Resize(, UBound(DL, 2)).Value = Title
      .Range("A2").Resize(UBound(aSplit) + 1, UBound(DL, 2)) = KQ
    End With
  Next i
  Application.ScreenUpdating = True
MsgBox Timer - T
End Sub

Function SheetExist(ByVal WshName As String) As Boolean
  On Error Resume Next
  SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing
End Function
Function isValidWshName(ByVal WshName As String) As Boolean
  Dim i As Long, InvalidName As String
  InvalidName = ":\/?*[]"
  If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function
  For i = 1 To Len(InvalidName)
    If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function
  Next
  isValidWshName = True
End Function
 
Upvote 0
Mong bác ThuNghi và mọi người giúp tôi: ArrBP(nR) = ArrBP(nR) & vbBack & i nghĩa là gì đấy ah, trong Code sau để làm gì hả các bác
PHP:
Sub TonghopArr()   Dim DL, KQ(), Arr(), i As Long, Title, nR&, k&, n&   Dim tmpR As Long, p As Long, lC As Long, keyArr, WshName As String   Dim Dic As Object, Tmp As String, ArrBP()   Dim T   T = Timer   Set Dic = CreateObject("Scripting.Dictionary")   Application.ScreenUpdating = False   With Sheets("Data")     DL = .Range("A5:E60000").Value     Title = .Range("A4:E4").Value   End With   For i = 1 To UBound(DL, 1)     If Len(CStr(DL(i, 2))) Then       Tmp = CStr(DL(i, 2))       If Not Dic.Exists(Tmp) Then         n = n + 1         Dic.Add Tmp, n         ReDim Preserve ArrBP(1 To n)       End If       nR = Dic.Item(Tmp)       If Len(ArrBP(nR)) Then         ArrBP(nR) = ArrBP(nR) & vbBack & i       Else         ArrBP(nR) = i       End If     End If   Next  For i = 1 To UBound(ArrBP)     nR = 0     Tmp = CStr(ArrBP(i))     aSplit = Split(Tmp, vbBack)     ReDim KQ(1 To UBound(aSplit) + 1, 1 To UBound(DL, 2))     For j = 0 To UBound(aSplit)       nR = nR + 1       For k = 1 To UBound(DL, 2)         KQ(nR, k) = DL(aSplit(j), k)       Next k     Next j     WshName = CStr(KQ(1, 2))     If isValidWshName(WshName) Then       If Not SheetExist(WshName) Then         Sheets.Add(After:=Sheets(Sheets.Count)).Name = WshName       End If     End If     With Sheets(WshName)       .UsedRange.ClearContents       .Range("A1").Resize(, UBound(DL, 2)).Value = Title       .Range("A2").Resize(UBound(aSplit) + 1, UBound(DL, 2)) = KQ     End With   Next i   Application.ScreenUpdating = True MsgBox Timer - T End Sub  Function SheetExist(ByVal WshName As String) As Boolean   On Error Resume Next   SheetExist = Not ThisWorkbook.Sheets(WshName) Is Nothing End Function Function isValidWshName(ByVal WshName As String) As Boolean   Dim i As Long, InvalidName As String   InvalidName = ":\/?*[]"   If Len(WshName) > 31 Or Len(WshName) = 0 Then Exit Function   For i = 1 To Len(InvalidName)     If InStr(WshName, Mid(InvalidName, i, 1)) Then Exit Function   Next   isValidWshName = True End Function
Theo cá nhân tôi, bác LinDan có lẽ nên tập trung thời gian đầu đi nghiên cứu để nắm chắc kiến thức cơ bản đã; những khái niệm chưa vững mà nếu tập trung ngay những bài toán dạng nâng cao này để giải quyết công việc thì khả năng thành công sẽ không được cao.
 
Upvote 0
Web KT

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

Back
Top Bottom