• Xuất dữ liệu từ report ra Excel theo mẫu
  • Xuất dữ liệu từ report ra Excel theo mẫu

    xiketuan > 19-07-20, 10:07 PM

    Xin chào các bạn,
    mình cập nhật dữ liệu từ form và muốn xuất ra Excel theo mẫu Report. Các bạn có code demo xuất dữ liệu ra file Excel giống như report đã tạo, các cột trong report đã có công thức tính toán từ form (các công thức ở code vba). Nếu mình xuất ra được excel theo mẫu, thì có thể dùng file excel khi có kết quả import lại vào data theo mẫu đã xuất ra. Nếu được thì sẽ giảm tải rất nhiều công việc ạ.

    Cảm ơn rất nhiều.
    Mình gửi hình demo

    [Hình: MuQqn]
    [Hình: Mu4dH]
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    ongke0711 > 19-07-20, 11:28 PM

    Access chỉ xuất dữ liệu ra Excel từ nguồn là Table hoặc Query. Do đó các tính toán gì đó trên Form hay Report nên lưu thành table tạm hoặc query rồi xuất. Xuất theo kiểu mặc định này sẽ không theo mẫu thiết kế sẳn của Excel, chỉ có định dạng như Table thôi và xuất kiểu này mới có bộ code xuất dùng chung. Muốn xuất theo một mẫu thiết kế nào đó phải viết code riêng cho từng mẫu biểu của Excel.

    Mã PHP:
    Function DataToExcel(strSourceName As StringOptional strWorkbookPath As StringOptional strTargetSheetName As String)

        Dim rst As DAO.Recordset
        Dim excelApp 
    As Object
        Dim Wbk 
    As Object
        Dim Sht 
    As Object
        Dim xlRng 
    As Object
        Dim fldHeadings 
    As DAO.Field

        
    'Lay du lieu cho recordset (table hoac query).
        Set rst = CurrentDb.OpenRecordset(strSourceName)

        '
    Tao phiên làm viec Excel moi.
        Set excelApp CreateObject("Excel.Application")

        On Error Resume Next

        
    'Try to open the specified workbook. If there is no workbook specified
        '
    (or if it cannot be openedcreate a new one and rename the target sheet.
        Set Wbk excelApp.Workbooks.Open(strWorkbookPath)
        If Err.Number <> Or Len(strWorkbookPath) = 0 Then
            Set Wbk 
    excelApp.Workbooks.Add
            Set Sht 
    Wbk.Worksheets("Sheet1")
            If Len(strTargetSheetName) > 0 Then
                Sht
    .Name Left(strTargetSheetName34)
            End If
        End If

        'If the specified workbook has been opened correctly, then in order to avoid
        '
    problems with other sheets that might containnew sheet is added and is
        
    'being renamed according to the strTargetSheetName.
        Set Sht = Wbk.Worksheets.Add
        If Len(strTargetSheetName) > 0 Then
            Sht.Name = Left(strTargetSheetName, 34)
        End If

        On Error GoTo 0

        excelApp.Visible = True

        On Error GoTo ErrorHandler

        '
    Copy dòng tiêu de.
        For Each fldHeadings In rst.Fields
            excelApp
    .ActiveCell fldHeadings.Name
            excelApp
    .ActiveCell.Offset(01).Select
        Next

        
    'Copy du lieu xuong sheet.
        rst.MoveFirst
        Sht.range("A2").Select
        Sht.range("A2").CopyFromRecordset rst
        Sht.range("1:1").Select

        '
    Dinh dang dòng tiêu de.
        excelApp.Selection.Font.Bold True
        With excelApp
    .Selection
            
    .HorizontalAlignment = -4108    '= xlCenter in Excel.
            .VerticalAlignment = -4108  '
    xlCenter in Excel.
            .WrapText False
        End With

        Set xlRng 
    Sht.UsedRange
        With xlRng
            
    .Font.Name "Verdana"
            .Font.Size 8
            With 
    .Borders
                
    .ColorIndex = -4105    'xlAutomatic
                .LineStyle = 1    '
    xlContinuous
                
    .Weight 2  'xlThin
            End With
            With .Rows(1)
                .Font.Bold = True
                .Interior.ColorIndex = 15
            End With
            .WrapText = False
            .EntireColumn.AutoFit
        End With

        excelApp.ActiveSheet.Cells.EntireColumn.AutoFit

        With excelApp.ActiveWindow
            .FreezePanes = False
            .ScrollRow = 1
            .ScrollColumn = 1
        End With
        Sht.Rows("2:2").Select
        excelApp.ActiveWindow.FreezePanes = True

        With Sht
            .Tab.Color = RGB(255, 0, 0)
            .range("A1").Select
        End With

        rst.Close
        Set rst = Nothing

        Exit Function

    ErrorHandler:
        Msgbox "Ma loi: " & Err.Number & vbNewLine & "Noi dung loi: " & Err.Description, vbExclamation, "Thong bao"
        Exit Function

    End Function 
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    xiketuan > 19-07-20, 11:37 PM

    (19-07-20, 11:28 PM)ongke0711 Đã viết: Access chỉ xuất dữ liệu ra Excel từ nguồn là Table hoặc Query. Do đó các tính toán gì đó trên Form hay Report nên lưu thành table tạm hoặc query rồi xuất. Xuất theo kiểu mặc định này sẽ không theo mẫu thiết kế sẳn của Excel, chỉ có định dạng như Table thôi và xuất kiểu này mới có bộ code xuất dùng chung. Muốn xuất theo một mẫu thiết kế nào đó phải viết code riêng cho từng mẫu biểu của Excel.
    Đúng rồi bạn, mình thiết kế command button xuất file sang excel từ dữ liệu query. Ví dụ chỉ một mẫu biểu excel như bảng điểm, như vậy mỗi lần xuất file thì lưu 1 tên riêng theo mẫu mà mình code đúng không bạn? Có thể giúp cho mình code demo với ạ.
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    ongke0711 > 19-07-20, 11:42 PM

    (19-07-20, 11:37 PM)xiketuan Đã viết: Đúng rồi bạn, mình thiết kế command button xuất file sang excel từ dữ liệu query. Ví dụ chỉ một mẫu biểu excel như bảng điểm, như vậy mỗi lần xuất file thì lưu 1 tên riêng theo mẫu mà mình code đúng không bạn? Có thể giúp cho mình code demo với ạ.

    Cái hàm xuất ở trên rồi đó, bạn chỉ cần cung cấp các tham số cho hàm rồi chạy thôi.
    Bạn test với CSDL của bạn đi. Nếu không áp dụng được bạn đưa dữ liệu mẫu của bạn lên đây, tôi xem bạn áp dụng sai ở đoạn nào rồi sửa.
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    hmhieu > 01-05-21, 03:49 PM

    (19-07-20, 11:28 PM)ongke0711 Đã viết: Access chỉ xuất dữ liệu ra Excel từ nguồn là Table hoặc Query. Do đó các tính toán gì đó trên Form hay Report nên lưu thành table tạm hoặc query rồi xuất. Xuất theo kiểu mặc định này sẽ không theo mẫu thiết kế sẳn của Excel, chỉ có định dạng như Table thôi và xuất kiểu này mới có bộ code xuất dùng chung. Muốn xuất theo một mẫu thiết kế nào đó phải viết code riêng cho từng mẫu biểu của Excel.

    Mã PHP:
    Function DataToExcel(strSourceName As StringOptional strWorkbookPath As StringOptional strTargetSheetName As String)

        Dim rst As DAO.Recordset
        Dim excelApp 
    As Object
        Dim Wbk 
    As Object
        Dim Sht 
    As Object
        Dim xlRng 
    As Object
        Dim fldHeadings 
    As DAO.Field

        
    'Lay du lieu cho recordset (table hoac query).
        Set rst = CurrentDb.OpenRecordset(strSourceName)

        '
    Tao phiên làm viec Excel moi.
        Set excelApp CreateObject("Excel.Application")

        On Error Resume Next

        
    'Try to open the specified workbook. If there is no workbook specified
        '
    (or if it cannot be openedcreate a new one and rename the target sheet.
        Set Wbk excelApp.Workbooks.Open(strWorkbookPath)
        If Err.Number <> Or Len(strWorkbookPath) = 0 Then
            Set Wbk 
    excelApp.Workbooks.Add
            Set Sht 
    Wbk.Worksheets("Sheet1")
            If Len(strTargetSheetName) > 0 Then
                Sht
    .Name Left(strTargetSheetName34)
            End If
        End If

        'If the specified workbook has been opened correctly, then in order to avoid
        '
    problems with other sheets that might containnew sheet is added and is
        
    'being renamed according to the strTargetSheetName.
        Set Sht = Wbk.Worksheets.Add
        If Len(strTargetSheetName) > 0 Then
            Sht.Name = Left(strTargetSheetName, 34)
        End If

        On Error GoTo 0

        excelApp.Visible = True

        On Error GoTo ErrorHandler

        '
    Copy dòng tiêu de.
        For Each fldHeadings In rst.Fields
            excelApp
    .ActiveCell fldHeadings.Name
            excelApp
    .ActiveCell.Offset(01).Select
        Next

        
    'Copy du lieu xuong sheet.
        rst.MoveFirst
        Sht.range("A2").Select
        Sht.range("A2").CopyFromRecordset rst
        Sht.range("1:1").Select

        '
    Dinh dang dòng tiêu de.
        excelApp.Selection.Font.Bold True
        With excelApp
    .Selection
            
    .HorizontalAlignment = -4108    '= xlCenter in Excel.
            .VerticalAlignment = -4108  '
    xlCenter in Excel.
            .WrapText False
        End With

        Set xlRng 
    Sht.UsedRange
        With xlRng
            
    .Font.Name "Verdana"
            .Font.Size 8
            With 
    .Borders
                
    .ColorIndex = -4105    'xlAutomatic
                .LineStyle = 1    '
    xlContinuous
                
    .Weight 2  'xlThin
            End With
            With .Rows(1)
                .Font.Bold = True
                .Interior.ColorIndex = 15
            End With
            .WrapText = False
            .EntireColumn.AutoFit
        End With

        excelApp.ActiveSheet.Cells.EntireColumn.AutoFit

        With excelApp.ActiveWindow
            .FreezePanes = False
            .ScrollRow = 1
            .ScrollColumn = 1
        End With
        Sht.Rows("2:2").Select
        excelApp.ActiveWindow.FreezePanes = True

        With Sht
            .Tab.Color = RGB(255, 0, 0)
            .range("A1").Select
        End With

        rst.Close
        Set rst = Nothing

        Exit Function

    ErrorHandler:
        Msgbox "Ma loi: " & Err.Number & vbNewLine & "Noi dung loi: " & Err.Description, vbExclamation, "Thong bao"
        Exit Function

    End Function 

    Đã test, OK!
    Có 2 vấn đề mình cần trợ giúp:

    1) Bây giờ mình muốn thêm 1 cột STT (cột đầu tiên của bảng) và tự động đánh số thứ tự từ 1 đến hết dữ liệu xuất ra thì phải làm sao?
    2) Hàm trên chỉ chạy trên Table hoặc Query không có điều kiện, Khi mình cho chạy query có điều kiện truyền vào thì nó báo lỗi tại dòng Set rst = CurrentDb.OpenRecordset(strSourceName)

    Lỗi Run-time (3061): Too few parameters. Expected 2.

    Vậy để gọi được Query có điều kiện truyền vào từ ngoài thì sửa như thế nào? 

    Mong được giúp!
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    ongke0711 > 01-05-21, 11:29 PM

    (01-05-21, 03:49 PM)hmhieu Đã viết: 1) Bây giờ mình muốn thêm 1 cột STT (cột đầu tiên của bảng) và tự động đánh số thứ tự từ 1 đến hết dữ liệu xuất ra thì phải làm sao?


    Về đánh số thứ tự có thể đánh số thứ tự trong query trước khi xuất Excel. Tham khảo nhiều cách đánh Stt trong link này: https://thuthuataccess.com/forum/post-27113.html#pid27113


    (01-05-21, 03:49 PM)hmhieu Đã viết:
    2) Hàm trên chỉ chạy trên Table hoặc Query không có điều kiện, Khi mình cho chạy query có điều kiện truyền vào thì nó báo lỗi tại dòng Set rst = CurrentDb.OpenRecordset(strSourceName)

    Lỗi Run-time (3061): Too few parameters. Expected 2.

    Vậy để gọi được Query có điều kiện truyền vào từ ngoài thì sửa như thế nào? 

    Đúng là nếu là Query có tham số (parameters) thì nó báo lỗi nếu chỉ khai báo tên Query. Có 2 cách đối với Query có tham số:

    1. Dùng luôn câu lệnh SQL của Query đó. Trong hàm trên tham số strSourceName là dạng chuỗi (String), bạn chỉ cần copy câu lệnh SQL của query đó đưa vào biến chuỗi, sau đó chỉnh sửa đoạn nào có tham số lấy từ form cho phù hợp là xong.
    Vd: 
    Mã PHP:
    strSourceName " SELECT * FROM Table1 WHERE ID =" Me.txtID
    Set rst 
    CurrentDb.OpenRecordset (strSourceName

    2. Nếu muốn dùng luôn tên Query mà không dùng câu lệnh SQL thì bạn phải khai báo lại tham số parameters trong code VBA nó mới hiểu.
    Vd: 

    Mã PHP:
    Dim qdf As DAO.QueryDefs
    Set qdf 
    CurrentDb.QueryDefs("qryCongNo")
        qdf("[Forms]![frmBaoCaoTongHop]![txtTuNgay]") = [Forms]![frmBaoCaoTongHop]![txtTuNgay]
        qdf("[Forms]![frmBaoCaoTongHop]![txtDenNgay]") = [Forms]![frmBaoCaoTongHop]![txtDenNgay]
        qdf("[Forms]![frmBaoCaoTongHop]![cboKhachHang") = [Forms]![frmBaoCaoTongHop]![cboKhachHang]
        Set rst qdf.OpenRecordset() 
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    hmhieu > 02-05-21, 03:53 PM

    (01-05-21, 11:29 PM)ongke0711 Đã viết:
    (01-05-21, 03:49 PM)hmhieu Đã viết: 1) Bây giờ mình muốn thêm 1 cột STT (cột đầu tiên của bảng) và tự động đánh số thứ tự từ 1 đến hết dữ liệu xuất ra thì phải làm sao?


    Về đánh số thứ tự có thể đánh số thứ tự trong query trước khi xuất Excel. Tham khảo nhiều cách đánh Stt trong link này: https://thuthuataccess.com/forum/post-27113.html#pid27113


    (01-05-21, 03:49 PM)hmhieu Đã viết:
    2) Hàm trên chỉ chạy trên Table hoặc Query không có điều kiện, Khi mình cho chạy query có điều kiện truyền vào thì nó báo lỗi tại dòng Set rst = CurrentDb.OpenRecordset(strSourceName)

    Lỗi Run-time (3061): Too few parameters. Expected 2.

    Vậy để gọi được Query có điều kiện truyền vào từ ngoài thì sửa như thế nào? 

    Đúng là nếu là Query có tham số (parameters) thì nó báo lỗi nếu chỉ khai báo tên Query. Có 2 cách đối với Query có tham số:

    1. Dùng luôn câu lệnh SQL của Query đó. Trong hàm trên tham số strSourceName là dạng chuỗi (String), bạn chỉ cần copy câu lệnh SQL của query đó đưa vào biến chuỗi, sau đó chỉnh sửa đoạn nào có tham số lấy từ form cho phù hợp là xong.
    Vd: 
    Mã PHP:
    strSourceName " SELECT * FROM Table1 WHERE ID =" Me.txtID
    Set rst 
    CurrentDb.OpenRecordset (strSourceName

    2. Nếu muốn dùng luôn tên Query mà không dùng câu lệnh SQL thì bạn phải khai báo lại tham số parameters trong code VBA nó mới hiểu.
    Vd: 

    Mã PHP:
    Dim qdf As DAO.QueryDefs
    Set qdf 
    CurrentDb.QueryDefs("qryCongNo")
        qdf("[Forms]![frmBaoCaoTongHop]![txtTuNgay]") = [Forms]![frmBaoCaoTongHop]![txtTuNgay]
        qdf("[Forms]![frmBaoCaoTongHop]![txtDenNgay]") = [Forms]![frmBaoCaoTongHop]![txtDenNgay]
        qdf("[Forms]![frmBaoCaoTongHop]![cboKhachHang") = [Forms]![frmBaoCaoTongHop]![cboKhachHang]
        Set rst qdf.OpenRecordset() 

    Vấn đề 2, mình đã giải quyết được.
    Vấn đề 1, mình đã tham khảo link bạn cho và nhiều cách khác. Tuy nhiên, link trên thì chủ yếu là đánh STT trên Form, các tham khảo khác để đánh STT trên Query thì khi truy vấn liệu từ Table của Access nó đánh thứ tự đúng, nhưng truy vấn dữ liệu ở Table được link từ SQL Sever (qua công cụ ODBC Database) thì nó đánh số thứ tự không đúng (thử nhiều lần nhưng vẫn sai).

    Vì vậy, mình muốn chèn thêm Cột STT (cột A ) và đánh số thứ tự trên Bảng tính Excel khi đã xuất dữ liệu ra (chứ k phải chèn cột STT trên Query) thì bổ sung code như thế nào trong hàm DataToExcel ấy?

    Thank!
  • RE: Xuất dữ liệu từ report ra Excel theo mẫu

    ongke0711 > 02-05-21, 06:54 PM

    (02-05-21, 03:53 PM)hmhieu Đã viết: Vấn đề 1, mình đã tham khảo link bạn cho và nhiều cách khác. Tuy nhiên, link trên thì chủ yếu là đánh STT trên Form, các tham khảo khác để đánh STT trên Query thì khi truy vấn liệu từ Table của Access nó đánh thứ tự đúng, nhưng truy vấn dữ liệu ở Table được link từ SQL Sever (qua công cụ ODBC Database) thì nó đánh số thứ tự không đúng (thử nhiều lần nhưng vẫn sai).

    Vì vậy, mình muốn chèn thêm Cột STT (cột A ) và đánh số thứ tự trên Bảng tính Excel khi đã xuất dữ liệu ra (chứ k phải chèn cột STT trên Query) thì bổ sung code như thế nào trong hàm DataToExcel ấy?

    Tôi không biết bạn thiết kế query như thế nào, đúng hay không nên không ra kết quả, chứ Linkked Table từ SQL SV thì cũng là Table nên việc xử lý nó như nhau thôi. Nó có khác biệt rõ là khi truy vấn liên quan đến font chữ Unicode tiếng Việt thì Query Access không làm được mà phải thông qua Pass Through query.

    Nếu bạn muốn xử lý trong bảng tính Excel thì dùng VBA cho Excel mà xử lý, nó cũng đơn giản như bạn gõ Cell bên dưới = Cell bên trên + 1 thôi.
    Giải thuật là gì:
    - Xác định Cell bắt đầu đổ dữ liệu từ Access xuống. Ví dụ: Sheet1.Range("A2")  --> "A1" là dòng tiêu đề
    - Xác định tổng số dòng của dữ liệu ghi xuống. Dùng rst.RecordCount.
    - Dùng vòng lập duyệt từng Cell + 1 cho đến dòng cuối cùng.

    Vd:

    Mã PHP:
    Dim i As Integer
        
    For 2 To rst.RecordCount 1
            sht
    .Range("A" i).Value 1
        Next