E có 2 file excel (A và B), giả sử 2 file này đều nằm trong một folder
Sự kiện: đang mở file A, có marco nào có thể tự động copy dữ liệu sheet1 của B sang sheet1 của A (không phải thủ công: mở file B -> bôi đen -> ctrl C -> paste sang A)
Chào Thầy ạ!
Bài này của Thầy hấp dẫn quá! hihi
Khi nào Thầy ranh rảnh vì chưa có bài viết nào thì Thầy tạo giúp con nốt cái Main_2 cho Sub GetDataFromRS Thầy nhé!
Hi, Cảm Thầy ạ!
Sub Main2()
Dim Target as Range, FileName as String, SheetName as String, RangeAddress as String
Set Target = ThisWorkbook.Sheets(1).Range("A1")
FileName = "D:\DuLieu\B.xls"
SheetName = "Sheet3"
RangeAddress = "C1:H10"
[B]GetDataFromRS[/B] Target, FileName, SheetName, RangeAddress
MsgBox "Data has been successfully imported!"
End Sub
Cái này chỉ chổ nó dữ liệu "đáp xuống" luôn (chính là biến Target)
(thử xem, tôi viết đại, chưa test)
----------------
Các bạn cần nên đặt 1 câu hỏi: Khi nào thì nên dùng hàm GetData và khi nào thì nên dùng Sub GetDataFromRS? ---> Thế mới hiểu sâu vấn đề
Sub Main2()
Dim Target as Range, FileName as String, SheetName as String, RangeAddress as String
Set Target = ThisWorkbook.Sheets(1).Range("A1")
FileName = "D:\DuLieu\B.xls"
SheetName = "Sheet3"
RangeAddress = "C1:H10"
[B]GetDataFromRS[/B] Target, FileName, SheetName, RangeAddress
MsgBox "Data has been successfully imported!"
End Sub
Cái này chỉ chổ nó dữ liệu "đáp xuống" luôn (chính là biến Target)
(thử xem, tôi viết đại, chưa test)
----------------
Các bạn cần nên đặt 1 câu hỏi: Khi nào thì nên dùng hàm GetData và khi nào thì nên dùng Sub GetDataFromRS? ---> Thế mới hiểu sâu vấn đề
Ôi, không chạy được Thầy ạ, Có lẽ con áp dụng không đúng cách.
Thầy xem lại cách 3 giúp con với ạ.
Còn câu hỏi của Thầy đặt ra đúng là rất hay. Chắc là cũng phải tùy từng trường hợp nào thì vận dụng cách này hoặc cách kia để thể hiện ưu điểm nó.
Nhưng con chỉ biết áp dụng thôi, còn đọc code con chịu thua nên không chưa thể trả lời câu hỏi trên.
Thầy chỉ giáo ạ!
Cảm ơn Thầy!
Sub GetDataFromRS(ByVal Target As Range, ByVal FileName As String, Optional ByVal SheetName As String = "", Optional ByVal RangeAddress As String = "")
Dim cnn As Object, rsData As [COLOR=#ff0000]ADODB.Recordset[/COLOR]
......
End Sub
thành vầy:
Mã:
Sub GetDataFromRS(ByVal Target As Range, ByVal FileName As String, Optional ByVal SheetName As String = "", Optional ByVal RangeAddress As String = "")
Dim cnn As Object, rsData As [COLOR=#ff0000]Object[/COLOR]
......
End Sub
Còn câu hỏi của Thầy đặt ra đúng là rất hay. Chắc là cũng phải tùy từng trường hợp nào thì vận dụng cách này hoặc cách kia để thể hiện ưu điểm nó.
Nhưng con chỉ biết áp dụng thôi, còn đọc code con chịu thua nên không chưa thể trả lời câu hỏi trên.
Thầy chỉ giáo ạ!
Cảm ơn Thầy!
Thật ra em k bít gì về VBA, nhưng e có viết công thức tính toán gồm 3 sheet: nguồn, tính toán, kết quả.
Em đã thiết kế đều chạy tốt, nhưng phải copy thủ công đưa dữ liệu vào sheet nguồn.
Có cách nào dữ liệu sheet nguồn được lấy từ 1 file khác được k ạ?
Nhấn nút COPY nó hiện hộp thoại ra cho mình chọn file để lấy dữ liệu đó ạ.
Các bác viết dùm em đoạn code cho nút COPY
Cảm ơn tất cả^^
Thật ra em k bít gì về VBA, nhưng e có viết công thức tính toán gồm 3 sheet: nguồn, tính toán, kết quả.
Em đã thiết kế đều chạy tốt, nhưng phải copy thủ công đưa dữ liệu vào sheet nguồn.
Có cách nào dữ liệu sheet nguồn được lấy từ 1 file khác được k ạ?
Nhấn nút COPY nó hiện hộp thoại ra cho mình chọn file để lấy dữ liệu đó ạ.
Các bác viết dùm em đoạn code cho nút COPY
Cảm ơn tất cả^^
Vậy thì dùng ADO mới là vô địch. Tặng bạn 2 code này:
Mã:
Function GetData(ByVal FileName As String, Optional ByVal SheetName As String = "", Optional ByVal RangeAddress As String = "")
Dim cnn As Object, rsData As Object
Dim tmpArr, arr
Dim szConn As String, szSQL As String, tmp As String
Dim lR As Long, lC As Long, lVersn As Long
On Error GoTo ErrHandler
lVersn = Val(Application.Version)
Set cnn = CreateObject("ADODB.Connection")
Set rsData = CreateObject("ADODB.Recordset")
If lVersn < 12 Then
szConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 8.0;HDR=No"";IMEX=1;"
Else
szConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 12.0;HDR=No;IMEX=1"";"
End If
If SheetName = "" Then
Dim Dbs As Object, db As Object
Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVersn < 12, "36", "120"))
Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
tmp = db.TableDefs(0).Name
tmp = Replace(tmp, "''", "'")
SheetName = tmp
db.Close
Set Dbs = Nothing: Set db = Nothing
Else
SheetName = SheetName & "$"
End If
cnn.Open szConn
szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "];"
rsData.Open szSQL, cnn, 1, 1
tmpArr = rsData.GetRows
ReDim arr(UBound(tmpArr, 2), UBound(tmpArr, 1))
rsData.Close: cnn.Close
For lR = LBound(tmpArr, 2) To UBound(tmpArr, 2)
For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
arr(lR, lC) = tmpArr(lC, lR)
Next
Next
GetData = arr
Set rsData = Nothing: Set cnn = Nothing
Exit Function
ErrHandler:
MsgBox Err.Description
Set rsData = Nothing: Set cnn = Nothing
End Function
Mã:
Sub GetDataFromRS(ByVal Target As Range, ByVal FileName As String, Optional ByVal SheetName As String = "", Optional ByVal RangeAddress As String = "")
Dim cnn As Object, rsData As Object
Dim szConn As String, szSQL As String, tmp As String
Dim lR As Long, lC As Long, lVersn As Long
On Error GoTo ErrHandler
lVersn = Val(Application.Version)
Set cnn = CreateObject("ADODB.Connection")
Set rsData = CreateObject("ADODB.Recordset")
If lVersn < 12 Then
szConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 8.0;HDR=No"";IMEX=1;"
Else
szConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 12.0;HDR=No;IMEX=1"";"
End If
If SheetName = "" Then
Dim Dbs As Object, db As Object
Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVersn < 12, "36", "120"))
Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
tmp = db.TableDefs(0).Name
tmp = Replace(tmp, "''", "'")
SheetName = tmp
db.Close
Set Dbs = Nothing: Set db = Nothing
Else
SheetName = SheetName & "$"
End If
cnn.Open szConn
szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "]"
'szSQL = "SELECT [F2],[F4] FROM [" & SheetName & RangeAddress & "] WHERE F1>5 AND F3 = 'ELECTRIC'"
rsData.Open szSQL, cnn, 1, 1
Target.CopyFromRecordset rsData
rsData.Close: cnn.Close
Set rsData = Nothing: Set cnn = Nothing
MsgBox "Data has been successfully imported!"
Exit Sub
ErrHandler:
MsgBox Err.Description
Set rsData = Nothing: Set cnn = Nothing
End Sub
Tùy chọn xài 1 trong 2 cái nha!
- Cả 2 cái đều có thể dùng trực tiếp trong VBA
- Cái thứ nhất là HÀM, vậy bạn có thể gõ trực tiếp trên bảng tính
- Cái thứ hai là SUB, vậy chỉ có thể dùng trong VBA (không gõ đươc trên bảng tính)
-------------------------------
Phần code ở trên bạn cho vào 1 Module và cũng không cần hiểu, chỉ cần biết áp dụng là đủ
Ví dụ: Bạn chọn áp dụng HÀM
- File dữ liệu đang đóng nằm ở: "D:\DuLieu\B.xls"
- Tên sheet của file dữ liệu là "Sheet3"
- Vùng dữ liệu cần lấy là "C1:H10"
- Vậy ta viết thêm code áp dụng thế này:
Mã:
Sub Main()
Dim FileName as String, SheetName as String, RangeAddress as String
Dim arr
[COLOR=#ff0000]FileName = "D:\DuLieu\B.xls"
SheetName = "Sheet3"
RangeAddress = "C1:H10"[/COLOR]
arr = GetData(FileName, SheetName, RangeAddress)
If IsArray(arr) Then
[COLOR=#0000cd]ThisWorkbook.Sheets(1).Range("A1")[/COLOR].Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr
MsgBox "Data has been successfully imported!"
End If
End Sub
Chỉ cần lưu ý 3 dòng màu đỏ, khai báo cho đúng là được
Chổ màu xanh chính là nơi bạn cần copy đến Lưu ý:
- Nếu bạn chỉ khai báo FileName, không khai báo SheetName, RangeAddress thì đồng nghĩa bạn muốn lấy toàn bộ dữ liệu của sheet đầu tiên
- Trong Sub Main (là Sub áp dụng), phần FileName bạn có thể dùng GetOpenFileName để tùy ý chọn file nguồn. Ví dụ:
Mã:
Sub Main_OpenFileName()
Dim arr, vFile
[COLOR=#ff0000]vFile = Application.GetOpenFilename("Excel Files, *.xls;*.xlsx;*.xlsm")[/COLOR]
If TypeName(vFile) = "String" Then
arr = GetData(CStr(vFile))
If IsArray(arr) Then
ThisWorkbook.Sheets(1).Range("A1").Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr
MsgBox "Data has been successfully imported!"
End If
End If
End Sub
Màu đỏ dùng để mở hộp chọn file. Đoạn code trên không khai báo SheetName và RangeAddress nên code sẽ lấy toàn bộ dữ liệu ở sheet đầu tiên
------------------
Cách dùng cho code Sub GetDataFromRS cũng gần tương tự. Bạn tự khám phá nhé
[COLOR=#000000]Sub Main_OpenFileName()[/COLOR] Dim arr, vFile
[COLOR=#ff0000]vFile = Application.GetOpenFilename("Excel Files, *.xls;*.xlsx;*.xlsm;*.xlsb")[/COLOR]
[COLOR=#ff0000][/COLOR][SIZE=2][COLOR=#ff0000][B]SheetName ="*loan"[/B][/COLOR][/SIZE]
If TypeName(vFile) = "String" Then
arr = GetData(CStr(vFile))
If IsArray(arr) Then
ThisWorkbook.Sheets(1).Range("A1").Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr
MsgBox "Data has been successfully imported!"
End If
End If [COLOR=#000000]End Sub[/COLOR]
E có sử dụng code của thầy NDU để import dữ liệu
Tại mục SheetName có khai báo *loan để lấy dữ liệu từ sheet có tên "xxx.loan.xxx" mà ko có được
Làm thế nào để lấy tên tương đối của sheet... Anh/chị giúp e với ạh
Hôm trwowsc thầy NDU có up file tổng hợp. Nhưng em muốn lấy vài dữ liệu ở sheet VD: ô A10, ô B13, ô C14 .. vào 1 dòng trong file tông hợp, thầy có thể sửa giúp em được không ah,E cảm ơn
Vậy thì dùng ADO mới là vô địch. Tặng bạn 2 code này:
Mã:
Function GetData(ByVal FileName As String, Optional ByVal SheetName As String = "", Optional ByVal RangeAddress As String = "")
Dim cnn As Object, rsData As Object
Dim tmpArr, arr
Dim szConn As String, szSQL As String, tmp As String
Dim lR As Long, lC As Long, lVersn As Long
On Error GoTo ErrHandler
lVersn = Val(Application.Version)
Set cnn = CreateObject("ADODB.Connection")
Set rsData = CreateObject("ADODB.Recordset")
If lVersn < 12 Then
szConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 8.0;HDR=No"";IMEX=1;"
Else
szConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 12.0;HDR=No;IMEX=1"";"
End If
If SheetName = "" Then
Dim Dbs As Object, db As Object
Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVersn < 12, "36", "120"))
Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
tmp = db.TableDefs(0).Name
tmp = Replace(tmp, "''", "'")
SheetName = tmp
db.Close
Set Dbs = Nothing: Set db = Nothing
Else
SheetName = SheetName & "$"
End If
cnn.Open szConn
szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "];"
rsData.Open szSQL, cnn, 1, 1
tmpArr = rsData.GetRows
ReDim arr(UBound(tmpArr, 2), UBound(tmpArr, 1))
rsData.Close: cnn.Close
For lR = LBound(tmpArr, 2) To UBound(tmpArr, 2)
For lC = LBound(tmpArr, 1) To UBound(tmpArr, 1)
arr(lR, lC) = tmpArr(lC, lR)
Next
Next
GetData = arr
Set rsData = Nothing: Set cnn = Nothing
Exit Function
ErrHandler:
MsgBox Err.Description
Set rsData = Nothing: Set cnn = Nothing
End Function
Mã:
Sub GetDataFromRS(ByVal Target As Range, ByVal FileName As String, Optional ByVal SheetName As String = "", Optional ByVal RangeAddress As String = "")
Dim cnn As Object, rsData As Object
Dim szConn As String, szSQL As String, tmp As String
Dim lR As Long, lC As Long, lVersn As Long
On Error GoTo ErrHandler
lVersn = Val(Application.Version)
Set cnn = CreateObject("ADODB.Connection")
Set rsData = CreateObject("ADODB.Recordset")
If lVersn < 12 Then
szConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 8.0;HDR=No"";IMEX=1;"
Else
szConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileName & ";" & _
"Extended Properties=""Excel 12.0;HDR=No;IMEX=1"";"
End If
If SheetName = "" Then
Dim Dbs As Object, db As Object
Set Dbs = CreateObject("DAO.DBEngine." & IIf(lVersn < 12, "36", "120"))
Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
tmp = db.TableDefs(0).Name
tmp = Replace(tmp, "''", "'")
SheetName = tmp
db.Close
Set Dbs = Nothing: Set db = Nothing
Else
SheetName = SheetName & "$"
End If
cnn.Open szConn
szSQL = "SELECT * FROM [" & SheetName & RangeAddress & "]"
'szSQL = "SELECT [F2],[F4] FROM [" & SheetName & RangeAddress & "] WHERE F1>5 AND F3 = 'ELECTRIC'"
rsData.Open szSQL, cnn, 1, 1
Target.CopyFromRecordset rsData
rsData.Close: cnn.Close
Set rsData = Nothing: Set cnn = Nothing
MsgBox "Data has been successfully imported!"
Exit Sub
ErrHandler:
MsgBox Err.Description
Set rsData = Nothing: Set cnn = Nothing
End Sub
Tùy chọn xài 1 trong 2 cái nha!
- Cả 2 cái đều có thể dùng trực tiếp trong VBA
- Cái thứ nhất là HÀM, vậy bạn có thể gõ trực tiếp trên bảng tính
- Cái thứ hai là SUB, vậy chỉ có thể dùng trong VBA (không gõ đươc trên bảng tính)
-------------------------------
Phần code ở trên bạn cho vào 1 Module và cũng không cần hiểu, chỉ cần biết áp dụng là đủ
Ví dụ: Bạn chọn áp dụng HÀM
- File dữ liệu đang đóng nằm ở: "D:\DuLieu\B.xls"
- Tên sheet của file dữ liệu là "Sheet3"
- Vùng dữ liệu cần lấy là "C1:H10"
- Vậy ta viết thêm code áp dụng thế này:
Mã:
Sub Main()
Dim FileName as String, SheetName as String, RangeAddress as String
Dim arr
[COLOR=#ff0000]FileName = "D:\DuLieu\B.xls"
SheetName = "Sheet3"
RangeAddress = "C1:H10"[/COLOR]
arr = GetData(FileName, SheetName, RangeAddress)
If IsArray(arr) Then
[COLOR=#0000cd]ThisWorkbook.Sheets(1).Range("A1")[/COLOR].Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr
MsgBox "Data has been successfully imported!"
End If
End Sub
Chỉ cần lưu ý 3 dòng màu đỏ, khai báo cho đúng là được
Chổ màu xanh chính là nơi bạn cần copy đến Lưu ý:
- Nếu bạn chỉ khai báo FileName, không khai báo SheetName, RangeAddress thì đồng nghĩa bạn muốn lấy toàn bộ dữ liệu của sheet đầu tiên
- Trong Sub Main (là Sub áp dụng), phần FileName bạn có thể dùng GetOpenFileName để tùy ý chọn file nguồn. Ví dụ:
Mã:
Sub Main_OpenFileName()
Dim arr, vFile
[COLOR=#ff0000]vFile = Application.GetOpenFilename("Excel Files, *.xls;*.xlsx;*.xlsm")[/COLOR]
If TypeName(vFile) = "String" Then
arr = GetData(CStr(vFile))
If IsArray(arr) Then
ThisWorkbook.Sheets(1).Range("A1").Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr
MsgBox "Data has been successfully imported!"
End If
End If
End Sub
Màu đỏ dùng để mở hộp chọn file. Đoạn code trên không khai báo SheetName và RangeAddress nên code sẽ lấy toàn bộ dữ liệu ở sheet đầu tiên
------------------
Cách dùng cho code Sub GetDataFromRS cũng gần tương tự. Bạn tự khám phá nhé
-- thầy có thể cải tiến hàm này thêm một bậc nữa là có 1 tùy chọn được không ạ, có thể chọn lấy dữ liệu từ file đóng vào file đang mở hoặc ghi dữ liệu từ file đang mở vào file đã đóng, cám ơn thầy
Vậy thì dùng ADO mới là vô địch. Tặng bạn 2 code này:
Mã:
Sub Main_OpenFileName()
Dim arr, vFile
[COLOR=#ff0000]vFile = Application.GetOpenFilename("Excel Files, *.xls;*.xlsx;*.xlsm")[/COLOR]
If TypeName(vFile) = "String" Then
arr = GetData(CStr(vFile))
If IsArray(arr) Then
ThisWorkbook.Sheets(1).Range("A1").Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr
MsgBox "Data has been successfully imported!"
End If
End If
End Sub
Màu đỏ dùng để mở hộp chọn file. Đoạn code trên không khai báo SheetName và RangeAddress nên code sẽ lấy toàn bộ dữ liệu ở sheet đầu tiên
------------------
Cách dùng cho code Sub GetDataFromRS cũng gần tương tự. Bạn tự khám phá nhé
Cho em hỏi phần arr = GetData(CStr(vFile)), em có viết lại là arr = GetData(CStr(vFile), SheetName) với Sheetname là tên sheets em cần lấy. Nhưng khi chạy code báo lỗi, không biết có phải ở code này thì viết thế là sai cú pháp không ạ?
Cho em hỏi phần arr = GetData(CStr(vFile)), em có viết lại là arr = GetData(CStr(vFile), SheetName) với Sheetname là tên sheets em cần lấy. Nhưng khi chạy code báo lỗi, không biết có phải ở code này thì viết thế là sai cú pháp không ạ?