Tổng hợp dữ liệu từ nhiều file excel vào 1 file không cần mở file

Liên hệ QC

ffcb1900

Thành viên chính thức
Tham gia
27/7/08
Bài viết
77
Được thích
4
Mình lúc nào cũng sẽ có 5 file dữ liệu (mỗi file khoảng 2000-5000 dòng dữ liệu), download trực tiếp hàng ngày từ server với định dạng định sẵn dưới định dạng .xls (số cột và vị trí cột định sẵn theo mẫu đính kèm là các file CA1, CA2, CA3, CA4, CA5).

Mình cần tổng hợp lại 5 file vào 1 file duy nhất (như mẫu đính kèm) trong đó du liệu của các file CA1, CA2, CA3, CA4, CA5 sẽ nối tiếp nhau ghep vào 1 sheet theo đúng cột tương ứng. Để tổng hợp đc mà k cần mở cả 5 file lên là tốt nhất (như kiểu paste link và có linh external data vậy).

Mong mọi người giúp đỡ với
 

File đính kèm

  • tong hop du lieu vao 1 file.zip
    35.1 KB · Đọc: 951
Xin nhờ Diễn Đàn và các bạn hỗ trợ giúp tình huống của mình với ạ.
Chân thành cảm ơn.
 
Upvote 0
Xin chào Diễn Đàn,
Em có 2 file cần gộp, nhưng theo bản code ban đầu từ thầy NDU thì khi em lấy data lần đầu ok, nhưng nếu em lấy data lần 2 thì file tổng lại không chép đè lên mà lại chép tiếp.
Ví dụ: lần 1 em lấy CA1 có 2 dòng và CA2 có 2 dòng. Tức là file Master sẽ có 4 dòng.
Lần 2 em lấy lại CA1 và CA2 thì file Master chép lại từ đầu nhưng bắt đầu từ dòng thứ 5, như vậy là em bị trùng thông tin.
Thầy hoặc các bạn có cách nào fix giúp em với ạ.
Nhờ mọi người giúp em với ạ.
 
Upvote 0
Xin nhờ Diễn Đàn và các bạn hỗ trợ giúp tình huống của mình với ạ.
Chân thành cảm ơn.
Tôi không thử "tình huống" với các file của bạn, tôi chỉ có thể "thêm 1 chút" code có sẵn (của người khác đã viết), Bạn chay thử có thể đạt yêu cầu của bạn. Nếu không thì chờ bạn khác xem giúp.
Trong FILE TONG HOP, bạn sửa Sub Main() trong modMain như sau:
PHP:
Sub Main()
  Dim vFile, FileItem, aRes, Target As Range
  Dim FileName As String, SheetName As String, RangeAddress As String
  On Error Resume Next
  vFile = Application.GetOpenFilename("Excel File, *.xls; *.xlsx; *.xlsm", , , , True)
  If TypeName(vFile) = "Variant()" Then
    SheetName = "Sheet1": RangeAddress = "A8:V10000"
    Sheet1.Range("A8").Resize(1000, 26).ClearContents   '<============ Them dong nay'
    For Each FileItem In vFile
    aRes = Nothing
      FileName = CStr(FileItem)
      If UCase(FileName) <> UCase(ThisWorkbook.FullName) Then
        aRes = GetData(FileName, SheetName, RangeAddress, False, False)
        If IsArray(aRes) Then
          Set Target = Sheet1.Range("A60000").End(xlUp).Offset(1)
          Target.Resize(UBound(aRes, 1) + 1, UBound(aRes, 2) + 1).Value = aRes
        End If
      End If
    Next
    MsgBox "Done!"
  End If
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Mình muốn tổng hợp các sheet từ các file khác nhau vào 1 file tổng hợp, và các tên sheet import vào sẽ chính là tên file. Bạn giúp mình được không? Cảm ơn nhiều.
 
Upvote 0
Tôi không thử "tình huống" với các file của bạn, tôi chỉ có thể "thêm 1 chút" code có sẵn (của người khác đã viết), Bạn chay thử có thể đạt yêu cầu của bạn. Nếu không thì chờ bạn khác xem giúp.
Trong FILE TONG HOP, bạn sửa Sub Main() trong modMain như sau:
PHP:
Sub Main()
  Dim vFile, FileItem, aRes, Target As Range
  Dim FileName As String, SheetName As String, RangeAddress As String
  On Error Resume Next
  vFile = Application.GetOpenFilename("Excel File, *.xls; *.xlsx; *.xlsm", , , , True)
  If TypeName(vFile) = "Variant()" Then
    SheetName = "Sheet1": RangeAddress = "A8:V10000"
    Sheet1.Range("A8").Resize(1000, 26).ClearContents   '<============ Them dong nay'
    For Each FileItem In vFile
    aRes = Nothing
      FileName = CStr(FileItem)
      If UCase(FileName) <> UCase(ThisWorkbook.FullName) Then
        aRes = GetData(FileName, SheetName, RangeAddress, False, False)
        If IsArray(aRes) Then
          Set Target = Sheet1.Range("A60000").End(xlUp).Offset(1)
          Target.Resize(UBound(aRes, 1) + 1, UBound(aRes, 2) + 1).Value = aRes
        End If
      End If
    Next
    MsgBox "Done!"
  End If
End Sub
Whoa nó work nè, đúng là nó sẽ chép đè tiếp khi mình chạy lần 2, nhưng mà không hiểu một chút là khi thực hiện lệnh get data, nó sẽ open ra 1 file nguồn
Ví dụ: get data từ 4 file 1-2-3-4 thì nó sẽ mở file thứ 3 ra song song đó là file tổng hợp đã được tổng hợp đầy đủ
 
Upvote 0
Dùng ADO sẽ không cần mở file:
Mã:
Function GetData(ByVal FileName As String, ByVal SheetName As String, ByVal RangeAddress As String, _
            ByVal HasTitle As Boolean, ByVal UseTitle As Boolean)
           
  Dim rsCon As Object, rsData As Object, cat As Object, tbl As Object
  Dim tmpArr, Arr()
  Dim szConnect As String, szSQL As String, tmp As String
  Dim lCount As Long, lR As Long, lC As Long, lVer As Long
  lVer = Val(Application.Version)
  Set rsCon = CreateObject("ADODB.Connection")
  Set rsData = CreateObject("ADODB.Recordset")
  Set cat = CreateObject("ADOX.Catalog")
 
  If lVer < 12 Then
    szConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
                "Extended Properties=""Excel 8.0;HDR=" & IIf(HasTitle, "Yes", "No") & """;"
  Else
    szConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
                "Extended Properties=""Excel 12.0;HDR=" & IIf(HasTitle, "Yes", "No") & """;"
  End If
  If SheetName = "" Then
    Dim Dbs  As Object, db As Object
    Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVer < 12, "36", "120"))
    Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
    tmp = db.TableDefs(0).Name
    tmp = Replace(tmp, " ", "?")
    tmp = Replace(tmp, "'", " ")
    tmp = WorksheetFunction.Trim(tmp)
    tmp = Replace(tmp, " ", "'")
    tmp = Replace(tmp, "?", " ")
    SheetName = tmp
    db.Close
    Set Dbs = Nothing: Set db = Nothing
  End If
  If Right(SheetName, 1) <> "$" Then SheetName = SheetName & "$"
  rsCon.Open szConnect
  cat.ActiveConnection = rsCon
 
  szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "];"
  rsData.Open szSQL, rsCon, 0, 1, 1
  tmpArr = rsData.GetRows
  ReDim Arr(UBound(tmpArr, 2) - UseTitle, UBound(tmpArr, 1) + 1)
  If UseTitle Then
    For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
      Arr(0, lC) = rsData.Fields(lC).Name
    Next
  End If
  For lR = LBound(tmpArr, 2) To UBound(tmpArr, 2)
    For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
      Arr(lR - UseTitle, lC) = tmpArr(lC, lR)
    Next
  Next
  rsData.Close: Set rsData = Nothing
  rsCon.Close: Set rsCon = Nothing
  GetData = Arr
End Function

Sub Main()
  Dim vFile, FileItem, aRes, Target As Range
  Dim FileName As String, SheetName As String, RangeAddress As String
  On Error Resume Next
  vFile = Application.GetOpenFilename("Excel File, *.xls; *.xlsx; *.xlsm", , , , True)
  If TypeName(vFile) = "Variant()" Then
    SheetName = "Sheet1": RangeAddress = "A8:V10000"
    For Each FileItem In vFile
      FileName = CStr(FileItem)
      If UCase(FileName) <> UCase(ThisWorkbook.FullName) Then
        aRes = GetData(FileName, SheetName, RangeAddress, False, False)
        If IsArray(aRes) Then
          Set Target = Sheet1.Range("A60000").End(xlUp).Offset(1)
          Target.Resize(UBound(aRes, 1) + 1, UBound(aRes, 2) + 1).Value = aRes
        End If
      End If
    Next
    MsgBox "Done!"
  End If
End Sub
Cách dùng:
- Cho code trên vào Module
- Chạy sub Main
- Cửa sổ Open File hiện ra, dùng chuột chọn file đầu, bấm giữ phím Shift rồi còn file cuối ---> Bấm nút Open
- Chờ trong giây lát, khi MsgBox hiện ra báo hiệu hoàn tất, kiểm tra lại dữ liệu trong file hiện hành xem đã cập nhật chưa
-------------
Lưu ý: File TongHop phải được lưu theo định dạng XLSM (nếu lưu bằng XLSX sẽ mất sạch code)
Cảm ơn bác. File rất có ích ạ.
Nhưng cách này không tông hợp được hình ảnh. Cho em hỏi thêm là có cách nào tổng hợp được cả ảnh không ạ
 
Upvote 0
Cảm ơn bác. File rất có ích ạ.
Nhưng cách này không tông hợp được hình ảnh. Cho em hỏi thêm là có cách nào tổng hợp được cả ảnh không ạ
ADO chỉ lấy dữ liệu, không lấy object đâu bạn.
Cách để lấy tất cả mọi thứ là mở file nguồn lên, copy/paste sang file địch rồi đóng file nguồn lại
 
Upvote 0
Dùng ADO sẽ không cần mở file:
Mã:
Function GetData(ByVal FileName As String, ByVal SheetName As String, ByVal RangeAddress As String, _
            ByVal HasTitle As Boolean, ByVal UseTitle As Boolean)
           
  Dim rsCon As Object, rsData As Object, cat As Object, tbl As Object
  Dim tmpArr, Arr()
  Dim szConnect As String, szSQL As String, tmp As String
  Dim lCount As Long, lR As Long, lC As Long, lVer As Long
  lVer = Val(Application.Version)
  Set rsCon = CreateObject("ADODB.Connection")
  Set rsData = CreateObject("ADODB.Recordset")
  Set cat = CreateObject("ADOX.Catalog")
 
  If lVer < 12 Then
    szConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
                "Extended Properties=""Excel 8.0;HDR=" & IIf(HasTitle, "Yes", "No") & """;"
  Else
    szConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
                "Extended Properties=""Excel 12.0;HDR=" & IIf(HasTitle, "Yes", "No") & """;"
  End If
  If SheetName = "" Then
    Dim Dbs  As Object, db As Object
    Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVer < 12, "36", "120"))
    Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
    tmp = db.TableDefs(0).Name
    tmp = Replace(tmp, " ", "?")
    tmp = Replace(tmp, "'", " ")
    tmp = WorksheetFunction.Trim(tmp)
    tmp = Replace(tmp, " ", "'")
    tmp = Replace(tmp, "?", " ")
    SheetName = tmp
    db.Close
    Set Dbs = Nothing: Set db = Nothing
  End If
  If Right(SheetName, 1) <> "$" Then SheetName = SheetName & "$"
  rsCon.Open szConnect
  cat.ActiveConnection = rsCon
 
  szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "];"
  rsData.Open szSQL, rsCon, 0, 1, 1
  tmpArr = rsData.GetRows
  ReDim Arr(UBound(tmpArr, 2) - UseTitle, UBound(tmpArr, 1) + 1)
  If UseTitle Then
    For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
      Arr(0, lC) = rsData.Fields(lC).Name
    Next
  End If
  For lR = LBound(tmpArr, 2) To UBound(tmpArr, 2)
    For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
      Arr(lR - UseTitle, lC) = tmpArr(lC, lR)
    Next
  Next
  rsData.Close: Set rsData = Nothing
  rsCon.Close: Set rsCon = Nothing
  GetData = Arr
End Function

Sub Main()
  Dim vFile, FileItem, aRes, Target As Range
  Dim FileName As String, SheetName As String, RangeAddress As String
  On Error Resume Next
  vFile = Application.GetOpenFilename("Excel File, *.xls; *.xlsx; *.xlsm", , , , True)
  If TypeName(vFile) = "Variant()" Then
    SheetName = "Sheet1": RangeAddress = "A8:V10000"
    For Each FileItem In vFile
      FileName = CStr(FileItem)
      If UCase(FileName) <> UCase(ThisWorkbook.FullName) Then
        aRes = GetData(FileName, SheetName, RangeAddress, False, False)
        If IsArray(aRes) Then
          Set Target = Sheet1.Range("A60000").End(xlUp).Offset(1)
          Target.Resize(UBound(aRes, 1) + 1, UBound(aRes, 2) + 1).Value = aRes
        End If
      End If
    Next
    MsgBox "Done!"
  End If
End Sub
Cách dùng:
- Cho code trên vào Module
- Chạy sub Main
- Cửa sổ Open File hiện ra, dùng chuột chọn file đầu, bấm giữ phím Shift rồi còn file cuối ---> Bấm nút Open
- Chờ trong giây lát, khi MsgBox hiện ra báo hiệu hoàn tất, kiểm tra lại dữ liệu trong file hiện hành xem đã cập nhật chưa
-------------
Lưu ý: File TongHop phải được lưu theo định dạng XLSM (nếu lưu bằng XLSX sẽ mất sạch code)
E chào thầy. E không biết gì về VBA nhưng đọc bài viết này có ứng dụng rất tốt trong công việc của em
Nhưng ở trường hợp của em lại muốn lấy các dữ liệu ở nhiều vùng, vị trí khác nhau trong 1 bảng tính vào File tổng hợp như theo Ví Dụ kính kèm. Mong thầy và diễn đàn giúp đỡ em
Em cảm ơn
 

File đính kèm

  • Tong hop.rar
    493.2 KB · Đọc: 15
Upvote 0
Tôi không thử "tình huống" với các file của bạn, tôi chỉ có thể "thêm 1 chút" code có sẵn (của người khác đã viết), Bạn chay thử có thể đạt yêu cầu của bạn. Nếu không thì chờ bạn khác xem giúp.
Trong FILE TONG HOP, bạn sửa Sub Main() trong modMain như sau:
PHP:
Sub Main()
  Dim vFile, FileItem, aRes, Target As Range
  Dim FileName As String, SheetName As String, RangeAddress As String
  On Error Resume Next
  vFile = Application.GetOpenFilename("Excel File, *.xls; *.xlsx; *.xlsm", , , , True)
  If TypeName(vFile) = "Variant()" Then
    SheetName = "Sheet1": RangeAddress = "A8:V10000"
    Sheet1.Range("A8").Resize(1000, 26).ClearContents   '<============ Them dong nay'
    For Each FileItem In vFile
    aRes = Nothing
      FileName = CStr(FileItem)
      If UCase(FileName) <> UCase(ThisWorkbook.FullName) Then
        aRes = GetData(FileName, SheetName, RangeAddress, False, False)
        If IsArray(aRes) Then
          Set Target = Sheet1.Range("A60000").End(xlUp).Offset(1)
          Target.Resize(UBound(aRes, 1) + 1, UBound(aRes, 2) + 1).Value = aRes
        End If
      End If
    Next
    MsgBox "Done!"
  End If
End Sub
Sub Copyright_OUT()
Dim WbS As Workbook
Dim ShS1 As Worksheet
Dim ShS2 As Worksheet
Dim ShS3 As Worksheet
Dim WbD As Workbook
Dim ShD1 As Worksheet
Dim ShD2 As Worksheet
Dim Lastrow
Dim Mypath

Set WbS = ThisWorkbook
Set ShS1 = WbS.Sheets("Out")
Mypath = WbS.Path
Set WbD = Workbooks.Open(Mypath & "\Advanced_Filter.xlsb")
Set ShD = WbD.Sheets("RawData")

Application.ScreenUpdating = False
Lastrow = ShD.Range("A" & Rows.Count).End(xlUp).Row
Dim rng As Range, i As Long, k As Long, R As Long
With ShS1
Set rng = .Range("F6", .Range("F20000").End(xlUp)).Resize(, 10)
R = rng.Rows.Count
End With
ReDim arr1(1 To R, 1 To 4)
ReDim arr2(1 To R, 1 To 2)
ReDim arr3(1 To R, 1 To 2)
For i = 1 To R
If rng(i, 1).EntireRow.Hidden = False Then
k = k + 1
arr1(k, 1) = rng(i, 1)
arr1(k, 2) = rng(i, 2)
arr1(k, 3) = rng(i, 3)
arr1(k, 4) = rng(i, 4)
arr2(k, 1) = rng(i, 6)
arr2(k, 2) = rng(i, 7)
arr3(k, 1) = rng(i, 11)
arr3(k, 2) = rng(i, 12)

End If
Next i

With ShD
.Range("A" & Lastrow).Resize(R, 4) = arr1
.Range("E" & Lastrow).Resize(R, 2) = arr2
.Range("G" & Lastrow).Resize(R, 2) = arr3

End With

Set Rng1 = Nothing
Application.ScreenUpdating = True
End Sub
chỗ tô đỏ sai cho nào bác ba tê chỉnh giúp dc ko. yq mình là copy arr nối tiếp arr cũ
 
Upvote 0
Dùng ADO sẽ không cần mở file:
Mã:
Function GetData(ByVal FileName As String, ByVal SheetName As String, ByVal RangeAddress As String, _
            ByVal HasTitle As Boolean, ByVal UseTitle As Boolean)
           
  Dim rsCon As Object, rsData As Object, cat As Object, tbl As Object
  Dim tmpArr, Arr()
  Dim szConnect As String, szSQL As String, tmp As String
  Dim lCount As Long, lR As Long, lC As Long, lVer As Long
  lVer = Val(Application.Version)
  Set rsCon = CreateObject("ADODB.Connection")
  Set rsData = CreateObject("ADODB.Recordset")
  Set cat = CreateObject("ADOX.Catalog")
 
  If lVer < 12 Then
    szConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
                "Extended Properties=""Excel 8.0;HDR=" & IIf(HasTitle, "Yes", "No") & """;"
  Else
    szConnect = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
                "Extended Properties=""Excel 12.0;HDR=" & IIf(HasTitle, "Yes", "No") & """;"
  End If
  If SheetName = "" Then
    Dim Dbs  As Object, db As Object
    Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVer < 12, "36", "120"))
    Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
    tmp = db.TableDefs(0).Name
    tmp = Replace(tmp, " ", "?")
    tmp = Replace(tmp, "'", " ")
    tmp = WorksheetFunction.Trim(tmp)
    tmp = Replace(tmp, " ", "'")
    tmp = Replace(tmp, "?", " ")
    SheetName = tmp
    db.Close
    Set Dbs = Nothing: Set db = Nothing
  End If
  If Right(SheetName, 1) <> "$" Then SheetName = SheetName & "$"
  rsCon.Open szConnect
  cat.ActiveConnection = rsCon
 
  szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "];"
  rsData.Open szSQL, rsCon, 0, 1, 1
  tmpArr = rsData.GetRows
  ReDim Arr(UBound(tmpArr, 2) - UseTitle, UBound(tmpArr, 1) + 1)
  If UseTitle Then
    For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
      Arr(0, lC) = rsData.Fields(lC).Name
    Next
  End If
  For lR = LBound(tmpArr, 2) To UBound(tmpArr, 2)
    For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
      Arr(lR - UseTitle, lC) = tmpArr(lC, lR)
    Next
  Next
  rsData.Close: Set rsData = Nothing
  rsCon.Close: Set rsCon = Nothing
  GetData = Arr
End Function

Sub Main()
  Dim vFile, FileItem, aRes, Target As Range
  Dim FileName As String, SheetName As String, RangeAddress As String
  On Error Resume Next
  vFile = Application.GetOpenFilename("Excel File, *.xls; *.xlsx; *.xlsm", , , , True)
  If TypeName(vFile) = "Variant()" Then
    SheetName = "Sheet1": RangeAddress = "A8:V10000"
    For Each FileItem In vFile
      FileName = CStr(FileItem)
      If UCase(FileName) <> UCase(ThisWorkbook.FullName) Then
        aRes = GetData(FileName, SheetName, RangeAddress, False, False)
        If IsArray(aRes) Then
          Set Target = Sheet1.Range("A60000").End(xlUp).Offset(1)
          Target.Resize(UBound(aRes, 1) + 1, UBound(aRes, 2) + 1).Value = aRes
        End If
      End If
    Next
    MsgBox "Done!"
  End If
End Sub
Cách dùng:
- Cho code trên vào Module
- Chạy sub Main
- Cửa sổ Open File hiện ra, dùng chuột chọn file đầu, bấm giữ phím Shift rồi còn file cuối ---> Bấm nút Open
- Chờ trong giây lát, khi MsgBox hiện ra báo hiệu hoàn tất, kiểm tra lại dữ liệu trong file hiện hành xem đã cập nhật chưa
-------------
Lưu ý: File TongHop phải được lưu theo định dạng XLSM (nếu lưu bằng XLSX sẽ mất sạch code)
dạ thầy cho e hỏi sao e dùng file của thầy về rồi chạy thử trên chính folder của thầy thì msbox done nhưng không ra dữ liệu. em thử test trên file của em..đã sửa tên sheet rồi nhưng chạy cũng không ra dữ liệu là sao ạ
Bài đã được tự động gộp:

dạ thầy cho e hỏi sao e dùng file của thầy về rồi chạy thử trên chính folder của thầy thì msbox done nhưng không ra dữ liệu. em thử test trên file của em..đã sửa tên sheet rồi nhưng chạy cũng không ra dữ liệu là sao ạ
Mọi ngươi em giúp em file này được không ạ, em code sửa em check đi check lại nhiều lần thấy đung rồi mà chạy ra nó báo done nhưng không ra data? Help em với ạ
Em chân thành cám ơn
 

File đính kèm

  • file danh gia.rar
    168.2 KB · Đọc: 12
Lần chỉnh sửa cuối:
Upvote 0
Cám ơn các thày, em muốn copy từ sheet đầu tiên (bất cứ tên sheet đầu là gì) của các file nguồn về 1 sheet có dc không ạ , vậy code ntn?
 
Upvote 0
Web KT

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

Back
Top Bottom