Lọc báo cáo theo nhóm

Liên hệ QC

quynhnamimex

Thành viên mới
Tham gia
8/1/09
Bài viết
18
Được thích
7
Nhờ các thầy và anh chị trong group giúp dùm code chuyển từ bảng dữ liệu sang bảng kết quả

Em cám ơn các thầy và anh chị nhiều
1575859746051.png
 

File đính kèm

  • Bang bao cao.xlsx
    13.5 KB · Đọc: 10
Tiêu đề của bạn đang bị vi phạm nội quy
Untitled.png
 
Upvote 0

File đính kèm

  • Bang bao cao.xlsm
    19.8 KB · Đọc: 24
Upvote 0
Chà...! Này mà nhiều A00.... làm code lọc xỉu mệt ak ^^!
đúng rồi dữ liệu rất nhiều đây là bảng mô tả ít thôi, mình đang nghiên cứu cách mà chưa ra
Bài đã được tự động gộp:

Dữ liệu mà nhiều hơn thì nó trả kết quả đúng không anh ơi
dữ liệu rất nhiều nên không đúng, mình đang test cách mình làm nhưng chưa ra kết quả
 
Upvote 0
Dùng PivotTable, ra như thế này có đúng không, bất kể bạn bao nhiêu data sẽ xuất ra hết, nhưng sẽ hơi khác Format bạn yêu cầu một chút. còn nếu phải bắt buộc y chan format yêu cầu thì mình sẽ viết cho bạn 1 code xử lý.
 

File đính kèm

  • Copy of Bang bao cao.xlsb
    22.7 KB · Đọc: 8
Upvote 0
Dữ liệu nhiều hơn thì bạn nên tách riêng từng nhóm ra.
Bạn cũng có thể sử dụng cách này để lọc nhiều dữ liệu hơn. Bạn dùng Remove Duplicates để lọc ra 1 DS không trùng Tên nguyên liệu, xác định dòng cuối mỗi lần thêm dòng, cứ thế mà nó sẽ chèn tới dữ liệu mình setup. Từ đó sẽ giải được bài toán này. Do mình đang khá bận nên chưa làm file dc, có thời gian mình làm cho !
 
Upvote 0
Bạn cũng có thể sử dụng cách này để lọc nhiều dữ liệu hơn. Bạn dùng Remove Duplicates để lọc ra 1 DS không trùng Tên nguyên liệu, xác định dòng cuối mỗi lần thêm dòng, cứ thế mà nó sẽ chèn tới dữ liệu mình setup. Từ đó sẽ giải được bài toán này. Do mình đang khá bận nên chưa làm file dc, có thời gian mình làm cho !
Cám ơn bạn nhiều, mình đang code thử mà chưa dc tại mình cần xuất ra giống vậy
 
Upvote 0
Mình có cách này, bạn tham khảo & xài nếu thây ưng!
 

File đính kèm

  • GPE.rar
    16.6 KB · Đọc: 16
Upvote 0
đúng rồi dữ liệu rất nhiều đây là bảng mô tả ít thôi, mình đang nghiên cứu cách mà chưa ra
Bài đã được tự động gộp:


dữ liệu rất nhiều nên không đúng, mình đang test cách mình làm nhưng chưa ra kết quả
Nếu dữ liệu như đề bài chỉ cần duyệt 1 vòng lặp for next là được thôi.còn nếu dữ liệu chưa sắp xếp chắc phải dùng dictionary.
 
Upvote 0
Nhờ các thầy và anh chị trong group giúp dùm code chuyển từ bảng dữ liệu sang bảng kết quả

Đóng góp một cách khác xử lý bằng câu lênh SQL (dùng ADO kết nối dữ liệu) :)
Tôi chỉ lấy dữ liệu ra theo yêu cầu trên hình còn việc định dạng Cell thì không rành và còn một cái chưa làm được trong đây là đánh số thứ tự. Mấy bạn rành code VBA Excel thì chuyện này chắc xử lý 30 giây, nhờ các bạn hỗ trợ giùm phần này. :)

- Trong bảng dữ liệu tôi có thêm tên các cột bằng tiếng Việt (không dấu, không khoảng trắng) để tiện việc truy vấn đích danh tên cột (Field) trong vùng dữ liệu. Có thể không dùng tên cột mà thay bằng bí danh như F1, F2... nhưng sau này có thể phát sinh thay đổi vị trí cột thì phải sửa nhiều trong câu lênh SQL nên tôi không dùng cách này.
- Code cho việc truy vấn dữ liệu:

Mã:
Option Explicit

Sub QueryData()

    On Error GoTo EH

    Application.ScreenUpdating = False

    Dim oDuLieuRst As Object, oTenNLRst As Object
    Dim sDulieuNR As String
    Dim sDBFullPath As String, sTenNLSql As String, sDuLieuSql As String
    Dim lngDestRow As Long, rstTotalRow As Long, rstFR As Long, rstLR As Long

    'Ket noi toi file du lieu - là chính file Excel này
    sDBFullPath = ThisWorkbook.FullName
    ConnectDB sDBFullPath

    'Xác dinh vùng du lieu can lay - dung cho cau lenh SQL
    Dim lastRow As Long
    lastRow = Sheet1.Cells(Sheet1.Rows.Count, 6).End(xlUp).Row
    sDulieuNR = "A2:F" & lastRow

    'Loc tên mã sô duy nhat dua vao recordset rieng
    sTenNLSql = "SELECT DISTINCT MaSo, TenNL FROM " & sDulieuNR & " ORDER BY MaSo"
    Set oTenNLRst = GetADORecordset(sTenNLSql)

    Sheet1.Range("K4:O10000").ClearContents

    lngDestRow = 4
    oTenNLRst.MoveFirst
    Do Until oTenNLRst.EOF
        Sheet1.Range("K" & lngDestRow).Value = oTenNLRst!TenNL
        Sheet1.Range("L" & lngDestRow).Value = oTenNLRst!MaSo
        Sheet1.Range("K" & lngDestRow & ":L" & lngDestRow).Font.Bold = True

        'Lay du lieu có cung Mã so
        sDuLieuSql = "SELECT SoLo, NhaSX, NgayDuyet, TinhTrang FROM " & sDulieuNR & " WHERE MaSo Like '" & oTenNLRst!MaSo & "' ORDER BY SoLo"
        Set oDuLieuRst = GetADORecordset(sDuLieuSql)
        rstTotalRow = oDuLieuRst.RecordCount    'Tomg so dong cua Recordset vua filter
        rstFR = lngDestRow + 1
        rstLR = rstFR + rstTotalRow - 1
        Sheet1.Range("L" & rstFR & ":O" & rstLR).Value = WorksheetFunction.Transpose(oDuLieuRst.getrows)
        lngDestRow = lngDestRow + rstTotalRow + 1
        oTenNLRst.MoveNext
    Loop

    oTenNLRst.Close
    oDuLieuRst.Close
    Set oDuLieuRst = Nothing
    Set oTenNLRst = Nothing

    Application.ScreenUpdating = True

EH_Exit:
    Exit Sub

EH:
    MsgBox "Có loi phat sinh." & vbNewLine & vbNewLine & _
           "Ma loi: " & Err.Number & vbNewLine & _
           "Noi dung loi: " & Err.Description, vbCritical, "Query Data Error"
    Set oDuLieuRst = Nothing
    Set oTenNLRst = Nothing
    Resume EH_Exit

End Sub



- Các hàm dùng trong Sub QueryData().

Mã:
Option Explicit

Private Const adUseClient As Long = 3
Private Const adLockReadOnly As Long = 1
Private Const adStateOpen As Long = 1
Private Const adCmdStoredProc As Long = 4
Private Const adParamOutput As Long = 2
Private Const adOpenDynamic As Long = 2
Private Const adOpenStatic As Long = 3
Private Const adCmdText = &H1
Private Const adCmdTable = 2

Global oCnn As Object


Public Function ConnectDB(strWBFullName As String) As Boolean

    On Error GoTo ConnectDBError

    Dim strConn As String
    Dim blnNewConnect As Boolean
    Dim blnReturn As Boolean

    blnReturn = True
    blnNewConnect = True

    If Not oCnn Is Nothing Then   'Kiem tra xem có Connection chua, có rôi thi dung ket noi cu
        If oCnn.State And adStateOpen = adStateOpen Then  '-> Da có ket noi
            blnNewConnect = False
        End If
    End If

    If Val(Application.Version) < 12 Then
        strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                  "Data Source=" & strWBFullName & ";" & _
                  "Extended Properties=""Excel 8.0;HDR=Yes"";"    'HDR = No
    Else
        strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                  "Data Source=" & strWBFullName & ";" & _
                  "Extended Properties=""Excel 12.0 XML;HDR=Yes"";"    'HDR = No
    End If

    If blnNewConnect Then
        Set oCnn = CreateObject("ADODB.Connection")
        oCnn.ConnectionString = strConn
        oCnn.Open
    End If


ConnectDBResume:
    ConnectDB = blnReturn
    Exit Function

ConnectDBError:
    blnReturn = False
    MsgBox "Có loi phat sinh." & vbCrLf & "Ma loi: " & Err.Number _
         & "Noi dung: " & Err.Description, vbCritical, "ConnectDB"
    Resume ConnectDBResume

End Function

Sub CloseMyConnection()

    On Error GoTo HandleError

    oCnn.Close
    Set oCnn = Nothing

    Exit Sub

HandleError:
    If Err > 0 Then
        MsgBox "Có loi phat sinh." & vbCrLf & "Ma loi: " & Err.Number _
             & "Noi dung: " & Err.Description, vbCritical, "ConnectDB"
        Exit Sub
    End If
End Sub

Function GetADORecordset(strRst As String, Optional strSortFld As String) As Object    'ADODB.Recordset
    On Error GoTo EH

    Dim oRst As Object
    Set oRst = CreateObject("ADODB.Recordset")
    With oRst
        .CursorLocation = adUseClient
        .Open strRst, oCnn, adOpenDynamic, adLockReadOnly, adCmdText
        If oRst.EOF And oRst.BOF Then
            'MsgBox "Không có du lieu."
            Set GetADORecordset = Nothing
            Exit Function
        End If
        .Sort = strSortFld
        .MoveFirst
    End With

    Set GetADORecordset = oRst

    Exit Function

EH:
    MsgBox "Có loi phat sinh." & vbNewLine & vbNewLine & _
           "Ma loi: " & Err.Number & vbNewLine & _
           "Noi dung loi: " & Err.Description, vbCritical, "GetADORecordset Function Error"
    Set GetADORecordset = Nothing
    Exit Function

End Function


Screen Shot 2019-12-09 at 11.33.59 PM.png
 

File đính kèm

  • Bang bao cao(ADO).xlsm
    34.8 KB · Đọc: 19
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn bạn nhiều, mình đang code thử mà chưa dc tại mình cần xuất ra giống vậy
Bạn thukhon2014 làm thừa cột mã số đúng ra PivotTable phải làm như hình.
Tôi khuyên bạn nếu cần tổng hợp thì nên sử dụng PivotTable, nó là vô địch và có thể tùy biến theo yêu cầu báo cáo.
Đôi lúc lãnh đạo yêu cầu báo cáo kiểu này, ngày mai lại đưa ra kiểu khác. Vì vậy, bạn không nên nghĩ đến code khác, nếu có sử dụng đến code thì cũng nghĩ ngay đến code tạo PivotTable (để còn tùy biến theo yêu cầu báo cáo), còn các code khác thì tèo ngay.

A_Pivot.GIF
 
Lần chỉnh sửa cuối:
Upvote 0
Đóng góp một cách khác xử lý bằng câu lênh SQL (dùng ADO kết nối dữ liệu) :)
Tôi chỉ lấy dữ liệu ra theo yêu cầu trên hình còn việc định dạng Cell thì không rành và còn một cái chưa làm được trong đây là đánh số thứ tự. Mấy bạn rành code VBA Excel thì chuyện này chắc xử lý 30 giây, nhờ các bạn hỗ trợ giùm phần này. :)

- Trong bảng dữ liệu tôi có thêm tên các cột bằng tiếng Việt (không dấu, không khoảng trắng) để tiện việc truy vấn đích danh tên cột (Field) trong vùng dữ liệu. Có thể không dùng tên cột mà thay bằng bí danh như F1, F2... nhưng sau này có thể phát sinh thay đổi vị trí cột thì phải sửa nhiều trong câu lênh SQL nên tôi không dùng cách này.
- Code cho việc truy vấn dữ liệu:

Mã:
Option Explicit

Sub QueryData()

    On Error GoTo EH

    Application.ScreenUpdating = False

    Dim oDuLieuRst As Object, oTenNLRst As Object
    Dim sDulieuNR As String
    Dim sDBFullPath As String, sTenNLSql As String, sDuLieuSql As String
    Dim lngDestRow As Long, rstTotalRow As Long, rstFR As Long, rstLR As Long

    'Ket noi toi file du lieu - là chính file Excel này
    sDBFullPath = ThisWorkbook.FullName
    ConnectDB sDBFullPath

    'Xác dinh vùng du lieu can lay - dung cho cau lenh SQL
    Dim lastRow As Long
    lastRow = Sheet1.Cells(Sheet1.Rows.Count, 6).End(xlUp).Row
    sDulieuNR = "A2:F" & lastRow

    'Loc tên mã sô duy nhat dua vao recordset rieng
    sTenNLSql = "SELECT DISTINCT MaSo, TenNL FROM " & sDulieuNR & " ORDER BY MaSo"
    Set oTenNLRst = GetADORecordset(sTenNLSql)

    Sheet1.Range("K4:O10000").ClearContents

    lngDestRow = 4
    oTenNLRst.MoveFirst
    Do Until oTenNLRst.EOF
        Sheet1.Range("K" & lngDestRow).Value = oTenNLRst!TenNL
        Sheet1.Range("L" & lngDestRow).Value = oTenNLRst!MaSo
        Sheet1.Range("K" & lngDestRow & ":L" & lngDestRow).Font.Bold = True

        'Lay du lieu có cung Mã so
        sDuLieuSql = "SELECT SoLo, NhaSX, NgayDuyet, TinhTrang FROM " & sDulieuNR & " WHERE MaSo Like '" & oTenNLRst!MaSo & "' ORDER BY SoLo"
        Set oDuLieuRst = GetADORecordset(sDuLieuSql)
        rstTotalRow = oDuLieuRst.RecordCount    'Tomg so dong cua Recordset vua filter
        rstFR = lngDestRow + 1
        rstLR = rstFR + rstTotalRow - 1
        Sheet1.Range("L" & rstFR & ":O" & rstLR).Value = WorksheetFunction.Transpose(oDuLieuRst.getrows)
        lngDestRow = lngDestRow + rstTotalRow + 1
        oTenNLRst.MoveNext
    Loop

    oTenNLRst.Close
    oDuLieuRst.Close
    Set oDuLieuRst = Nothing
    Set oTenNLRst = Nothing

    Application.ScreenUpdating = True

EH_Exit:
    Exit Sub

EH:
    MsgBox "Có loi phat sinh." & vbNewLine & vbNewLine & _
           "Ma loi: " & Err.Number & vbNewLine & _
           "Noi dung loi: " & Err.Description, vbCritical, "Query Data Error"
    Set oDuLieuRst = Nothing
    Set oTenNLRst = Nothing
    Resume EH_Exit

End Sub



- Các hàm dùng trong Sub QueryData().

Mã:
Option Explicit

Private Const adUseClient As Long = 3
Private Const adLockReadOnly As Long = 1
Private Const adStateOpen As Long = 1
Private Const adCmdStoredProc As Long = 4
Private Const adParamOutput As Long = 2
Private Const adOpenDynamic As Long = 2
Private Const adOpenStatic As Long = 3
Private Const adCmdText = &H1
Private Const adCmdTable = 2

Global oCnn As Object


Public Function ConnectDB(strWBFullName As String) As Boolean

    On Error GoTo ConnectDBError

    Dim strConn As String
    Dim blnNewConnect As Boolean
    Dim blnReturn As Boolean

    blnReturn = True
    blnNewConnect = True

    If Not oCnn Is Nothing Then   'Kiem tra xem có Connection chua, có rôi thi dung ket noi cu
        If oCnn.State And adStateOpen = adStateOpen Then  '-> Da có ket noi
            blnNewConnect = False
        End If
    End If

    If Val(Application.Version) < 12 Then
        strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                  "Data Source=" & strWBFullName & ";" & _
                  "Extended Properties=""Excel 8.0;HDR=Yes"";"    'HDR = No
    Else
        strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                  "Data Source=" & strWBFullName & ";" & _
                  "Extended Properties=""Excel 12.0 XML;HDR=Yes"";"    'HDR = No
    End If

    If blnNewConnect Then
        Set oCnn = CreateObject("ADODB.Connection")
        oCnn.ConnectionString = strConn
        oCnn.Open
    End If


ConnectDBResume:
    ConnectDB = blnReturn
    Exit Function

ConnectDBError:
    blnReturn = False
    MsgBox "Có loi phat sinh." & vbCrLf & "Ma loi: " & Err.Number _
         & "Noi dung: " & Err.Description, vbCritical, "ConnectDB"
    Resume ConnectDBResume

End Function

Sub CloseMyConnection()

    On Error GoTo HandleError

    oCnn.Close
    Set oCnn = Nothing

    Exit Sub

HandleError:
    If Err > 0 Then
        MsgBox "Có loi phat sinh." & vbCrLf & "Ma loi: " & Err.Number _
             & "Noi dung: " & Err.Description, vbCritical, "ConnectDB"
        Exit Sub
    End If
End Sub

Function GetADORecordset(strRst As String, Optional strSortFld As String) As Object    'ADODB.Recordset
    On Error GoTo EH

    Dim oRst As Object
    Set oRst = CreateObject("ADODB.Recordset")
    With oRst
        .CursorLocation = adUseClient
        .Open strRst, oCnn, adOpenDynamic, adLockReadOnly, adCmdText
        If oRst.EOF And oRst.BOF Then
            'MsgBox "Không có du lieu."
            Set GetADORecordset = Nothing
            Exit Function
        End If
        .Sort = strSortFld
        .MoveFirst
    End With

    Set GetADORecordset = oRst

    Exit Function

EH:
    MsgBox "Có loi phat sinh." & vbNewLine & vbNewLine & _
           "Ma loi: " & Err.Number & vbNewLine & _
           "Noi dung loi: " & Err.Description, vbCritical, "GetADORecordset Function Error"
    Set GetADORecordset = Nothing
    Exit Function

End Function


View attachment 229722
xin hỏi bác
ongke0711 làm nghề gì mà học những cái cao siêu thế này; e hỏi ngu ứng dụng trong việc gì ạ ? e mới vào diễn đàn công nhận nhiều cao thủ quá !!!
 
Upvote 0
Thời buổi bi giờ, Excel đã phát triển hết giai đoạn bảng tính mở rộng và dần tiến qua truy vấn csdl rồi.

Hầu hết các điều kiện gom nhóm này nọ đều có thể thực hiện qua PowerQuery.
Dùng VBA chỉ là cái cớ để níu lại, chậm trễ việc tiến triển kỹ thuật mà thôi.
 
Upvote 0
xin hỏi bác
ongke0711 làm nghề gì mà học những cái cao siêu thế này; e hỏi ngu ứng dụng trong việc gì ạ ? e mới vào diễn đàn công nhận nhiều cao thủ quá !!!

:) Nghề tôi thì không liên quan đến lập trình rồi (chuyên về marketing) nhưng cũng có đam mê nên tự tìm tòi học hỏi thôi. Một phần cũng có liên quan là trước đây công việc cần tổng hợp, phân tích các số liệu kinh doanh để làm kế hoạch nên mới mày mò Access và xin IT cho kết nối với Server của Cty để lấy dữ liệu theo yêu cầu cho nhanh. Nói chung là có mục đích viết cái ứng dụng cụ thể để phục vụ cho công việc bản thân một cách hiệu quả hơn từ đó sẽ có động lực tìm tòi, học hỏi để hoàn thành nó. Chỉ vậy thôi.
 
Upvote 0
Web KT
Back
Top Bottom