- Tham gia
- 18/3/08
- Bài viết
- 8,311
- Được thích
- 15,874
- Giới tính
- Nam
- Nghề nghiệp
- Làm ruộng.
File đính kèm
Lần chỉnh sửa cuối:
1 tuần = 7 ngày đã trôi qua, nhưng chỉ thấy có 2 lần tải, có vẻ như mọi người không quan tâm đến đề bài này.Lâu quá không thấy ai tham dự đề tài đố vui về ADO/DAO, để khởi động lại. nay tôi xin đố các bạn là không dùng vòng lặp, clipboard mà ta có thể đổ dữ liệu thành 1 bảng ở trình soạn email outlook.
1. Bảng dữ liệu:
View attachment 189195
2. Điều kiện để đưa dữ liệu vào outlook là TP=B.
3. Kết quả như sau:
View attachment 189194
1 tuần = 7 ngày đã trôi qua, nhưng chỉ thấy có 2 lần tải, có vẻ như mọi người không quan tâm đến đề bài này.![]()
Nếu vậy em gửi đáp án luôn.Office của bà con là phiên bản lậu cho nên ngại dùng Outlook để thử.
Bạn ra luôn lời giải cho rồi. Sau khi có lời giải, bà con sẽ đố tiếp về việc dùng lời giải ấy để áp dụng vào cái khác.
Sub DoVui_ADO()
Dim objOutlook, objOutlookMsg, cn, rst As Object
Set objOutlook = CreateObject("Outlook.Application")
Set objOutlookMsg = objOutlook.CreateItem(0)
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0"
rst.Open ("select * from [Sheet1$] where TP='B'"), cn
With objOutlookMsg
.To = "hailuamientay@giaiphapexcel.com"
.Subject = Sheet2.[B1]
.HTMLBody = "<strong>Xin chào các ban ,</strong> <br><br>" & Sheet2.[B2] & "<br><table border='1'><th>No</th><th>TP</th><th>ITEM NAME</th><th>SPEC</th><th>COLOR</th><th>Q'TY</th> <tr>" & rst.GetString(, , "</td><td>", "</tr><tr>") & "</tr></table><br><a href=http://www.giaiphapexcel.com/diendan/threads/%C4%90%E1%BB%91-vui-v%E1%BB%81-ado-dao.80367/page-15#post-835345/>Xem thêm tai dây</a><br><strong>Hai Lúa Miên Tây</strong>"
.Display
End With
End Sub
Để tiếp tục, tôi xin ra tiếp câu đố là không dùng vòng lặp, làm sao ta có thể đưa kết quả vào Shape như hình bên dưới:
View attachment 190543
Miễn sao ra kết quả vậy là được.ADO có lệnh chèn dữ liệu vào 1 Shape hả anh ? Và PCS là gì vậy anh ?![]()
Cũng đã gần cuối tuần rồi, mọi người chuẩn bị đi bão nên cũng không mấy quan tâm nhỉ. Các bạn giải đáp nhanh để ta tiếp tục với câu đố tiếp theo nhé.Để tiếp tục, tôi xin ra tiếp câu đố là không dùng vòng lặp, làm sao ta có thể đưa kết quả vào Shape như hình bên dưới:
View attachment 190543
Giờ người ta không thích kiểu đố đố như thế này nữa, có thể vì:Cũng đã gần cuối tuần rồi, mọi người chuẩn bị đi bão nên cũng không mấy quan tâm nhỉ. Các bạn giải đáp nhanh để ta tiếp tục với câu đố tiếp theo nhé.
Vậy GPE mình cần thêm mục "Đố vui có thưởng" rồi.Giờ người ta không thích kiểu đố đố như thế này nữa, có thể vì:
Hoặc là giúp bài có ích - thành viên đang chờ
Hoặc là làm hoạt động gì đó ra tiền
Hoặc là bài đố phải có ứng dụng thực tiễn thật sự, thay vì chỉ vui
Ứng dụng cho bài này là có thể lấy dữ liệu đưa vào một cái nút nhấn được tạo = Shape, hoặc có thể dùng shape để trình bày dữ liệu.Giờ người ta không thích kiểu đố đố như thế này nữa, có thể vì:
Hoặc là giúp bài có ích - thành viên đang chờ
Hoặc là làm hoạt động gì đó ra tiền
Hoặc là bài đố phải có ứng dụng thực tiễn thật sự, thay vì chỉ vui
Shape là gì vậy a. 2Lúa??? ... Sử dụng như nào vậy a.Ứng dụng cho bài này là có thể lấy dữ liệu đưa vào một cái nút nhấn được tạo = Shape, hoặc có thể dùng shape để trình bày dữ liệu.
Em xin đưa phương án như sau, anh góp ý nhéĐể tiếp tục, tôi xin ra tiếp câu đố là không dùng vòng lặp, làm sao ta có thể đưa kết quả vào Shape như hình bên dưới:
View attachment 190543
Sub DoVui_ADO()
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0"
lsql = "SELECT DISTINCT [TP] & '-> ' & [GR] & '-> ' & Sum([QTY]) & 'PCS' AS [Sum Of QTY] FROM [Sheet1$] GROUP BY TP, GR"
rst.Open lsql, cn
Do While rst.EOF = False
strValue = strValue & rst.Fields("Sum Of QTY").Value & Chr(10)
rst.MoveNext
Loop
ActiveSheet.Shapes("Rec").TextFrame2.TextRange.Characters.Text = strValue
End Sub
Rất cám ơn bạn đã tham gia. Nên thử lại là ta không dùng vòng lặp nhé bạn.Em xin đưa phương án như sau, anh góp ý nhé
Mã:Sub DoVui_ADO() Set cn = CreateObject("ADODB.Connection") Set rst = CreateObject("ADODB.Recordset") cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0" lsql = "SELECT DISTINCT [TP] & '-> ' & [GR] & '-> ' & Sum([QTY]) & 'PCS' AS [Sum Of QTY] FROM [Sheet1$] GROUP BY TP, GR" rst.Open lsql, cn Do While rst.EOF = False strValue = strValue & rst.Fields("Sum Of QTY").Value & Chr(10) rst.MoveNext Loop ActiveSheet.Shapes("Rec").TextFrame2.TextRange.Characters.Text = strValue End Sub
Nếu không vòng lặp em mạnh dạn đưa đáp án như thế này, anh xem và góp ý nhé.Rất cám ơn bạn đã tham gia. Nên thử lại là ta không dùng vòng lặp nhé bạn.
Sub DoVui_ADO()
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0"
lsql = "SELECT DISTINCT [TP] & '-> ' & [GR] & '-> ' & Sum([QTY]) & 'PCS' AS [Sum Of QTY] FROM [Sheet1$] GROUP BY TP, GR"
rst.Open lsql, cn
strValue = rst.GetString(, , , Chr(10))
ActiveSheet.Shapes("Rec").TextFrame2.TextRange.Characters.Text = strValue
End Sub
Đúng là như vầy rồi. Thật ra đây là cái mà mình muốn truyền tải cho mọi người (rst.GetString), nó ứng dụng rất nhiều chứ không phải đơn thuần chỉ là đố vui như bạn @Gió Đông nói.Nếu không vòng lặp em mạnh dạn đưa đáp án như thế này, anh xem và góp ý nhé.
Mã:Sub DoVui_ADO() Set cn = CreateObject("ADODB.Connection") Set rst = CreateObject("ADODB.Recordset") cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0" lsql = "SELECT DISTINCT [TP] & '-> ' & [GR] & '-> ' & Sum([QTY]) & 'PCS' AS [Sum Of QTY] FROM [Sheet1$] GROUP BY TP, GR" rst.Open lsql, cn strValue = rst.GetString(, , , Chr(10)) ActiveSheet.Shapes("Rec").TextFrame2.TextRange.Characters.Text = strValue End Sub
Thật ra câu lệnh SQL như sau là đủ, bạn chỉnh sửa lại chút xíu nhé.Nếu không vòng lặp em mạnh dạn đưa đáp án như thế này, anh xem và góp ý nhé.
Mã:Sub DoVui_ADO() Set cn = CreateObject("ADODB.Connection") Set rst = CreateObject("ADODB.Recordset") cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0" lsql = "SELECT DISTINCT [TP] & '-> ' & [GR] & '-> ' & Sum([QTY]) & 'PCS' AS [Sum Of QTY] FROM [Sheet1$] GROUP BY TP, GR" rst.Open lsql, cn strValue = rst.GetString(, , , Chr(10)) ActiveSheet.Shapes("Rec").TextFrame2.TextRange.Characters.Text = strValue End Sub
"select TP,GR,SUM(QTY) from [Sheet1$] GROUP BY TP,GR"
Cảm ơn anh HLMT thật nhiều.Thật ra câu lệnh SQL như sau là đủ, bạn chỉnh sửa lại chút xíu nhé.
Đố vui về... a do dao?Mình có biết thớt này tên là gì không???!!
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
Set rst = CreateObject("ADODB.Recordset")
Câu trả lời của Mình là ĐƯỢC .... TA không cần sử dụng connection hay chi tiết như sau ta vẫn có thể lấy dữ liệu lên Sheet hay mảng okNhanh hay không chưa biết. Không có connection lấy gì đọc dữ liệu?
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
Ta có thể khai báo và khởi tạo Object 1 trong 2 cái trên (Hoặc cn hoặc rst) đều có thể lấy được dữ liệu. Cho dù có dùng cách không khai báo và khởi tạo Object (Conection hay Recordset) thì theo tôi đã từng sử dụng thì tốc độ cũng không có khác biệt là mấy. Bởi vì nếu như anh không khởi tạo connection thì anh cũng phải dùng chuỗi kết nối với file nguồn trong thủ tục mở recordset.Câu trả lời của Mình là ĐƯỢC .... TA không cần sử dụng connection hay chi tiết như sau ta vẫn có thể lấy dữ liệu lên Sheet hay mảng ok
Ta chỉ cần cơ bản 1 dòng sau là đủ để lấy dữ liệu lên Sheet hay lên MảngMã:Set cn = CreateObject("ADODB.Connection")
Làm phiền @Hai Lúa Miền Tây cho xin 1 ý kiến cho bài 321 & 322 và bài này ... Mạnh Cảm ƠnMã:Set rst = CreateObject("ADODB.Recordset")
Chính xác vậy và đây là code Mạnh Viết .. Nhờ HLMT coi dùmTa có thể khai báo và khởi tạo Object 1 trong 2 cái trên (Hoặc cn hoặc rst) đều có thể lấy được dữ liệu. Cho dù có dùng cách không khai báo và khởi tạo Object (Conection hay Recordset) thì theo tôi đã từng sử dụng thì tốc độ cũng không có khác biệt là mấy. Bởi vì nếu như anh không khởi tạo connection thì anh cũng phải dùng chuỗi kết nối với file nguồn trong thủ tục mở recordset.
Private Sub CopyRecordset()
Dim Rst As Object, SQL As String
Dim Strcon As String, ExcelPath As String
Dim RecCount As Long
ExcelPath = ThisWorkbook.Path & "\Data.xlsb"
Set Rst = CreateObject("ADODB.Recordset")
SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu
Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _
& ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";")
Rst.Open SQL, Strcon, 3, 1
RecCount = Rst.RecordCount
MsgBox RecCount
If Not Rst.EOF Then
Cells.ClearContents
Range("A1").CopyFromRecordset Rst
End If
End Sub
Rem ==========
Private Sub GetDataGetRows()
Dim Rst As Object, SQL As String
Dim Strcon As String, ExcelPath As String
Dim RecCount As Long
Dim dArr(), Arr(), i As Long, j As Long, k As Long
ExcelPath = ThisWorkbook.Path & "\Data.xlsb"
Set Rst = CreateObject("ADODB.Recordset")
SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu
Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _
& ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";")
Rst.Open SQL, Strcon, 3, 1
RecCount = Rst.RecordCount
MsgBox RecCount
If Not Rst.EOF Then
Arr = Rst.getrows(RecCount)
ReDim dArr(1 To UBound(Arr, 2) + 1, 1 To UBound(Arr, 1) + 1)
For i = 0 To UBound(Arr, 2)
k = k + 1
For j = 0 To UBound(Arr, 1)
dArr(k, j + 1) = Arr(j, i)
Next j
Next i
Cells.ClearContents
Range("A2").Resize(UBound(dArr, 1), UBound(dArr, 2)) = dArr
End If
End Sub
Thì như tôi đã nói ở trên thôi, thông thường thì người ta bỏ khởi tạo recordset chứ ít ai bỏ khởi tạo connection. Dùng cách nào miễn mình quen và tránh xảy ra lỗi tiềm ẩn, kết quả đúng là được.Chính xác vậy và đây là code Mạnh Viết .. Nhờ HLMT coi dùm
Mã:Private Sub CopyRecordset() Dim Rst As Object, SQL As String Dim Strcon As String, ExcelPath As String Dim RecCount As Long ExcelPath = ThisWorkbook.Path & "\Data.xlsb" Set Rst = CreateObject("ADODB.Recordset") SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _ & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";") Rst.Open SQL, Strcon, 3, 1 RecCount = Rst.RecordCount MsgBox RecCount If Not Rst.EOF Then Cells.ClearContents Range("A1").CopyFromRecordset Rst End If End Sub Rem ========== Private Sub GetDataGetRows() Dim Rst As Object, SQL As String Dim Strcon As String, ExcelPath As String Dim RecCount As Long Dim dArr(), Arr(), i As Long, j As Long, k As Long ExcelPath = ThisWorkbook.Path & "\Data.xlsb" Set Rst = CreateObject("ADODB.Recordset") SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _ & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";") Rst.Open SQL, Strcon, 3, 1 RecCount = Rst.RecordCount MsgBox RecCount If Not Rst.EOF Then Arr = Rst.getrows(RecCount) ReDim dArr(1 To UBound(Arr, 2) + 1, 1 To UBound(Arr, 1) + 1) For i = 0 To UBound(Arr, 2) k = k + 1 For j = 0 To UBound(Arr, 1) dArr(k, j + 1) = Arr(j, i) Next j Next i Cells.ClearContents Range("A2").Resize(UBound(dArr, 1), UBound(dArr, 2)) = dArr End If End Sub
Cảm ơn Bạn ... tại vì chưa hiểu sâu xa bản chất của vấn đề nên mới hỏi để học tập nghiên cứu thêm ... vậy là phần nào hiểu chút chútKhi mở một file để đọc, ADO coi như đó là một CSDL, và nó cần tạo một connection để kết nối. Cái lệnh Open mà bạn thấy nó chính thức gồm luôn Open Connection và Excute Command (lệnh SQL).
Khi chỉ cần đọc một lần, cái connection có thể được hiểu ngầm (implicit, trái với tường minh là explicit), đọc xong rồi bỏ. Kiểu giống như sử dụng các đối tượng bằng lệnh With CreateObject(...) - End With, cái Object đó được thành lập và bỏ sau lệnh End With.
Lý do tại sao phải mở connection tường minh (khai báo và set 1 cái object connection):
1. Khi cần đọc nhiều lần: một lần connect vào CSDL tốn tài nguyên, vì vậy nếu đọc nhiều lần thì nên giữ lại. Sau khi đọc xong thì đóng lại (huỷ đi). Hầu hết công việc mà các bạn làm ở đây chỉ đọc mỗi file 1 lần cho nên bạn chưa thấy nhu cầu này.
2. Khi CSDL thuộc loại có nhiều thủ tục (ví dụ SQL Server có admin của nó, chỉ cho phép 1 số tình trạng kết nối). Ngừoi dùng cần phân biệt lúc kết nối và lúc lấy dữ liệu để có thể debug hoặc bẫy lỗi.
3. Hầu hết các CSDL quan trọng không cho phép truy vấn bằng lệnh SQL suông. Gọi SQL sẽ dẫn đến việc phá hoại (SQL attack). Cách duy nhất mà admin cho phép là gọi thủ tục (stored procedure) và chi tiết thì được nạp qua tham số. Trong trường hợp này, cái object connection tường minh nó giúp bạn làm việc dễ hơn.
(*) cũng giống như biến, bạn không bắt buộc phải khai báo. Bạn hoàn toàn có thể để dùng đến đâu VBA tự lập biến đến đó.
Lý do bạn khai báo biến là vì muốn kiểm soát cho dễ. Lý do code của bạn không cần dựng connection tường minh là vì giai đoạn sử dụng rất ngắn, trung bình khoảng chục dòng code.
Nói nôm na như thế này. Khi anh cần nhập, xuất hàng thì anh phải mở của kho để nhập xuất, nếu trong phiên làm việc có nhiều lần nhập xuất và việc nhập xuất đó liên tục thì anh vẫn phải để cửa kho cho người ta nhập xuất. Khi hết phiên làm việc mới đóng cửa kho, không phải khi vừa nhập hoặc vừa xuất xong thì đóng cửa kho và mở cửa kho liên tục, làm như vậy vẫn được nhưng hãy suy nghĩ lại có ổn không. Tương tự trong ứng dụng liên quan đến CSDL người ta thường khai báo và mở kết nối 1 lần (Mở cửa kho), sau đó thực hiện thêm, xóa, lấy, chỉnh sửa... (Nhập xuất hàng). Khi kết thúc ứng dụng thì đóng kết nối (Đóng cửa kho). Dĩ nhiên phải lưu ý việc ứng dụng đã chạy nhưng không dùng thì ta phải đặt thời gian thích hợp ở Server hoăc ở ứng dụng để hủy kết nối nhằm giảm tải cho Server.Cảm ơn Bạn ... tại vì chưa hiểu sâu xa bản chất của vấn đề nên mới hỏi để học tập nghiên cứu thêm ... vậy là phần nào hiểu chút chút![]()
Mạnh hiểu rồi vậy nên nó mới đẻ ra cái dòng sau phải ko ?!Nói nôm na như thế này. Khi anh cần nhập, xuất hàng thì anh phải mở của kho để nhập xuất, nếu trong phiên làm việc có nhiều lần nhập xuất và việc nhập xuất đó liên tục thì anh vẫn phải để cửa kho cho người ta nhập xuất. Khi hết phiên làm việc mới đóng cửa kho, không phải khi vừa nhập hoặc vừa xuất xong thì đóng cửa kho và mở cửa kho liên tục, làm như vậy vẫn được nhưng hãy suy nghĩ lại có ổn không. Tương tự trong ứng dụng liên quan đến CSDL người ta thường khai báo và mở kết nối 1 lần (Mở cửa kho), sau đó thực hiện thêm, xóa, lấy, chỉnh sửa... (Nhập xuất hàng). Khi kết thúc ứng dụng thì đóng kết nối (Đóng cửa kho). Dĩ nhiên phải lưu ý việc ứng dụng đã chạy nhưng không dùng thì ta phải đặt thời gian thích hợp ở Server hoăc ở ứng dụng để hủy kết nối nhằm giảm tải cho Server.
If Cnn.State <> 1 Then
Ví dụ tôi có 2 Workbook A.xls và B.xls, làm thế nào ở WB A.xls tôi có thể ghi dữ liệu vào WB B.xls như hình bên dưới.
WB A.xls:
View attachment 104076
WB B.xls
View attachment 104077
Xin cảm ơn.
Đọc từng bài từ bài này đến bài số #74 sẽ có được câu trả lời cho bạn.Anh Hai ơi, OT chưa thấy anh chị nào trả lời bài này.
Anh cho đáp án đi ạ.
Cảm ơn anh
Đọc từng bài từ bài này đến bài số #74 sẽ có được câu trả lời cho bạn.
bạn có thể cho mình xin file đính kèm dùng code này hoạt động để học hỏi thêm được không ạ.Chính xác vậy và đây là code Mạnh Viết .. Nhờ HLMT coi dùm
Mã:Private Sub CopyRecordset() Dim Rst As Object, SQL As String Dim Strcon As String, ExcelPath As String Dim RecCount As Long ExcelPath = ThisWorkbook.Path & "\Data.xlsb" Set Rst = CreateObject("ADODB.Recordset") SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _ & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";") Rst.Open SQL, Strcon, 3, 1 RecCount = Rst.RecordCount MsgBox RecCount If Not Rst.EOF Then Cells.ClearContents Range("A1").CopyFromRecordset Rst End If End Sub Rem ========== Private Sub GetDataGetRows() Dim Rst As Object, SQL As String Dim Strcon As String, ExcelPath As String Dim RecCount As Long Dim dArr(), Arr(), i As Long, j As Long, k As Long ExcelPath = ThisWorkbook.Path & "\Data.xlsb" Set Rst = CreateObject("ADODB.Recordset") SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _ & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";") Rst.Open SQL, Strcon, 3, 1 RecCount = Rst.RecordCount MsgBox RecCount If Not Rst.EOF Then Arr = Rst.getrows(RecCount) ReDim dArr(1 To UBound(Arr, 2) + 1, 1 To UBound(Arr, 1) + 1) For i = 0 To UBound(Arr, 2) k = k + 1 For j = 0 To UBound(Arr, 1) dArr(k, j + 1) = Arr(j, i) Next j Next i Cells.ClearContents Range("A2").Resize(UBound(dArr, 1), UBound(dArr, 2)) = dArr End If End Sub
code viết đó rồi copy là xài vậybạn có thể cho mình xin file đính kèm dùng code này hoạt động để học hỏi thêm được không ạ.
Chính xác vậy và đây là code Mạnh Viết .. Nhờ HLMT coi dùm
Mã:Private Sub CopyRecordset() Dim Rst As Object, SQL As String Dim Strcon As String, ExcelPath As String Dim RecCount As Long ExcelPath = ThisWorkbook.Path & "\Data.xlsb" Set Rst = CreateObject("ADODB.Recordset") SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _ & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";") Rst.Open SQL, Strcon, 3, 1 RecCount = Rst.RecordCount MsgBox RecCount If Not Rst.EOF Then Cells.ClearContents Range("A1").CopyFromRecordset Rst End If End Sub Rem ========== Private Sub GetDataGetRows() Dim Rst As Object, SQL As String Dim Strcon As String, ExcelPath As String Dim RecCount As Long Dim dArr(), Arr(), i As Long, j As Long, k As Long ExcelPath = ThisWorkbook.Path & "\Data.xlsb" Set Rst = CreateObject("ADODB.Recordset") SQL = "select * from [Data_Nhap$]" ''Tuy chon Mo Rong de lay du lieu Strcon = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _ & ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";") Rst.Open SQL, Strcon, 3, 1 RecCount = Rst.RecordCount MsgBox RecCount If Not Rst.EOF Then Arr = Rst.getrows(RecCount) ReDim dArr(1 To UBound(Arr, 2) + 1, 1 To UBound(Arr, 1) + 1) For i = 0 To UBound(Arr, 2) k = k + 1 For j = 0 To UBound(Arr, 1) dArr(k, j + 1) = Arr(j, i) Next j Next i Cells.ClearContents Range("A2").Resize(UBound(dArr, 1), UBound(dArr, 2)) = dArr End If End Sub
Xin nói thêm là nếu như ta dùng trên cùng 1 file thì không cần phải mở kết nối hay khai báo chuỗi kết nối.Câu trả lời của Mình là ĐƯỢC .... TA không cần sử dụng connection hay chi tiết như sau ta vẫn có thể lấy dữ liệu lên Sheet hay mảng ok
Ta chỉ cần cơ bản 1 dòng sau là đủ để lấy dữ liệu lên Sheet hay lên MảngMã:Set cn = CreateObject("ADODB.Connection")
Làm phiền @Hai Lúa Miền Tây cho xin 1 ý kiến cho bài 321 & 322 và bài này ... Mạnh Cảm ƠnMã:Set rst = CreateObject("ADODB.Recordset")
Ý kiên chi?Xin nói thêm là nếu như ta dùng trên cùng 1 file thì không cần phải mở kết nối hay khai báo chuỗi kết nối.
Vậy phương pháp để lấy dữ liệu bằng cách này là như thế nào. Mời các bạn cho ý kiến nhé.
Tôn chỉ ở diễn đàn này là code ngắn và nhanh. Luật code rõ ràng, dễ kiểm soát lỗi là điều thứ yếu.Ý kiên chi?
Không dùng kết nối nhé anh, code chưa chắc là ngắn gọn. Nhưng tốc độ thì hơn hẳn so với cách thông thường. Ở máy cà tàng của em thì với dữ liệu 1.048.576 dòng thì nó cho ra kết quả trong vòng 15~20 giây. Trong khi đó với cách mở kết nối thì hơn 80 giây mới có kết quả.Tôn chỉ ở diễn đàn này là code ngắn và nhanh. Luật code rõ ràng, dễ kiểm soát lỗi là điều thứ yếu.
Với tôn chỉ ấy thì phương pháp "implicit connection" (để cho recordset nó tự kết nối lấy "đằng sau hậu trường") là phương pháp lý tưởng.
Hết.
quay lại bài này 1 chútXin nói thêm là nếu như ta dùng trên cùng 1 file thì không cần phải mở kết nối hay khai báo chuỗi kết nối.
Vậy phương pháp để lấy dữ liệu bằng cách này là như thế nào. Mời các bạn cho ý kiến nhé.
Set cn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
sConn = "Provider=Microsoft.ACE.OLEDB.12.0 + abczyx(Linh Tinh)
Anh kiem tra duong dan, cau trùc sql va file ket nói la excel hay accdb. Nó hiện len trên kiaquay lại bài này 1 chút
Trường hợp mạnh không xài 2 công cụ sau + ko xài hàm của Excel + Macro4 mà vẫn lấy được dữ liệu của File đóng thì ko biết có phải cái mà HLMT hỏi ko nhỉ ... bỏ 2 dòng sau
Bỏ hết 2 Tools trên chỉ xài sơ bộ dòng sau ...Mã:Set cn = CreateObject("ADODB.Connection") Set rst = CreateObject("ADODB.Recordset")
Trong khi vô tình quậy code tầm bạy .... Bác Bill báo theo hìnhMã:sConn = "Provider=Microsoft.ACE.OLEDB.12.0 + abczyx(Linh Tinh)
View attachment 211057
biết ròi tại làm bạy nó mới báo vậy đóAnh kiem tra duong dan,
Anh kiem tra duong dan, cau trùc sql va file ket nói la excel hay accdb. Nó hiện len trên kia
Mo riet gio em phai di benh vien kham mat day huhuhubiết ròi tại làm bạy nó mới báo vậy đó![]()
Có nghĩa là trên cùng 1 file ta không cần khởi tạo kết nốiquay lại bài này 1 chút
Trường hợp mạnh không xài 2 công cụ sau + ko xài hàm của Excel + Macro4 mà vẫn lấy được dữ liệu của File đóng thì ko biết có phải cái mà HLMT hỏi ko nhỉ ... bỏ 2 dòng sau
Bỏ hết 2 Tools trên chỉ xài sơ bộ dòng sau ...Mã:Set cn = CreateObject("ADODB.Connection") Set rst = CreateObject("ADODB.Recordset")
Trong khi vô tình quậy code tầm bạy .... Bác Bill báo theo hìnhMã:sConn = "Provider=Microsoft.ACE.OLEDB.12.0 + abczyx(Linh Tinh)
View attachment 211057
trên cùng 1 File thì Mạnh chưa có Thử .... mà khác file thấy OK đóCó nghĩa là trên cùng 1 file ta không cần khởi tạo kết nối
Cnn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ExcelPath _
& ";Extended Properties=""Excel 12.0 Xml;HDR=Yes;"";")
Cnn.Open "ODBC;DSN=Excel Files;" _
& "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" _
& "DBQ=" & ExcelPath & ";ReadOnly=0;"
1/ Mình có 4 máy điều xài Windows10_x64 + Office2016_x32 thấy chạy tốt1. thử trên 64 bit
2. thử trên 80000 dòng
So sánh kết quả
Đã từng dùng cách này, tuy nhiên anh hãy test với dữ liệu là Tiếng Việt có dấu (Unicode) nhé.2/ cách thứ 2 có chạy trên tất cả các WindowsXP To Windows10 hay không ... hay phải cài thêm cái gì nữa ???
Thử khai báo lấy nguyên Sheet thấy nó chạy cũng nhanhĐã từng dùng cách này, tuy nhiên anh hãy test với dữ liệu là Tiếng Việt có dấu (Unicode) nhé.
SQL = "SELECT * FROM [Persons$]"
Nhân đây xin đố các bạn là: Nếu lấy dữ liệu nguyên Sheet thì còn có cách nào khác ngoài cách trên không?Thử khai báo lấy nguyên Sheet thấy nó chạy cũng nhanh
Mã:SQL = "SELECT * FROM [Persons$]"
Thử lấy OpenSchema = tên Sheet của nó xong nối vào cái SQL kia ko biết có trúng ko nữaNhân đây xin đố các bạn là: Nếu lấy dữ liệu nguyên Sheet thì còn có cách nào khác ngoài cách trên không?
Set Rs = cn.OpenSchema(20)
Tiếp tục tìm thêm đáp án khác đi anh.Thử lấy OpenSchema = tên Sheet của nó xong nối vào cái SQL kia ko biết có trúng ko nữa
Mã:Set Rs = cn.OpenSchema(20)
Cảm Ơn bạn thôi chạy mất dép cái kiểu kết nối đó thôi HLMT nói đúng thử với Unicode xem saoTóc đọ là cái tôi xét đến cuói cùng. Cái này nhanh hớn cái kia 1 chút đói với tôi gần như khong quan trọng. Làm việc với CSDL thì tôi chỉ quan tâm việc truy xuất có dễ dàng và chính xác?
Bạn chưa trả lời tôi về việc giới hạn số dòng.
Cái chuỗi kết nối mà em hay dùng trên diễn đàn. Theo ý chủ quan nó là cái mà em thấy chuẩn nhất so với những cái khác mà em đã từng dùng.Cảm Ơn bạn thôi chạy mất dép cái kiểu kết nối đó thôi HLMT nói đúng thử với Unicode xem sao
Thấy nó lỗi Font
View attachment 212049
Bạn hỏi là lấy trong Access hay là SQLServer?Các anh chị cho em hỏi xíu
Trong query co cách nào mình xác dinh fiels nào là khóa chính trong câu lệnh sql không ah
nếu được thì cả 2 anh hihiBạn hỏi là lấy trong Access hay là SQLServer?
SQLServer thì bạn thử như sau:nếu được thì cả 2 anh hihi
select schema_name(tab.schema_id) as [schema_name],
pk.[name] as pk_name,
ic.index_column_id as column_id,
col.[name] as column_name,
tab.[name] as table_name
from sys.tables tab
inner join sys.indexes pk
on tab.object_id = pk.object_id
and pk.is_primary_key = 1
inner join sys.index_columns ic
on ic.object_id = pk.object_id
and ic.index_id = pk.index_id
inner join sys.columns col
on pk.object_id = col.object_id
and col.column_id = ic.column_id
order by schema_name(tab.schema_id),
pk.[name],
ic.index_column_id
Mình không biết .prt là file định dạng dữ liệu của cái nào, để dùng được ADO bạn phải biết chuỗi kết nối đến nguồn dữ liệu nên bạn check link này xem có không https://www.connectionstrings.com/Không biết là trong VBA code ADO có kết nối được file dạng này hay không?
Lâu lắm ko vào đây nay đố vui 1 tẹo
1/ File sau nếu mắt thường nhìn nó thì chỉ có 83 dòng hay chọn nguyên cột B thì Count cũng chỉ có 83 dòng ??!!
2/ trên thực tế thì nó có tới 271 RecordCount ( nếu xài ADO mà đếm)
3/ chênh lệch nhau là: 271 - 83 = 188 RecordCount
Vậy muốn đố là:
1/ sự chênh lệch nhau 188 đó ở đâu ra mà có ... tại sao ???!!!
2/ Cách xử lý nó ??? ... có mấy cách ??!!!
3/ đó là 1 trong những nguyên nhân làm File Excel phình to ra theo thời gian mặc dù dữ liệu có 1 tẹo
.....
đó cũng là 1 cái gì đó giúp ai đó đang và sẻ xài ADO hiểu thêm nó 1 chút![]()
cái ý số 3 là có đấy ( nếu nó lên 1048576 ... thì mới thấy ) ... đố chứ ko hỏi hebác đố hay là bác hỏi vậy?
- Đối với ADO và theo như file mẫu thì lỗi này do một nguyên nhân và nhớ có lần tôi đề cập rồi.
- Xử lý thì tôi cũng biết 2, 3 cách.
- Cái ý số 3 tôi không nghĩ nó làm phìn file Excel lên đâu.
Thôi đố thì từ từ giải đố vậy.![]()
cái ý số 3 là có đấy ( nếu nó lên 1048576 ... thì mới thấy ) ... đố chứ ko hỏi he
Do trong bảng tính có định dạng (Cột I) đến dòng 271. Nếu bảng dữ liệu có định dạng hoặc dòng đã được nhập dữ liệu cho dù đã xóa bằng phím Delete trên bàn phím thì nó vẫn tính là có dữ liệu.Lâu lắm ko vào đây nay đố vui 1 tẹo
1/ File sau nếu mắt thường nhìn nó thì chỉ có 83 dòng hay chọn nguyên cột B thì Count cũng chỉ có 83 dòng ??!!
2/ trên thực tế thì nó có tới 271 RecordCount ( nếu xài ADO mà đếm)
3/ chênh lệch nhau là: 271 - 83 = 188 RecordCount
Vậy muốn đố là:
1/ sự chênh lệch nhau 188 đó ở đâu ra mà có ... tại sao ???!!!
2/ Cách xử lý nó ??? ... có mấy cách ??!!!
3/ đó là 1 trong những nguyên nhân làm File Excel phình to ra theo thời gian mặc dù dữ liệu có 1 tẹo
.....
đó cũng là 1 cái gì đó giúp ai đó đang và sẻ xài ADO hiểu thêm nó 1 chút
View attachment 241246
Lâu quá không trở lại đề tài này, hôm nay mình xin đố các bạn là làm sao lấy được danh sách tên cột của một bảng cho trước mà không dùng vòng lặp?
Đúng rồi bạn.Lưu xuống Sheet cũng không cho dùng vòng lặp luôn hả bác HLMT?![]()
Lâu quá không trở lại đề tài này, hôm nay mình xin đố các bạn là làm sao lấy được danh sách tên cột của một bảng cho trước mà không dùng vòng lặp?
Trong file mẫu tôi gửi có 3 sheets (Sheet1, Sheet2, Sheet3), và 1 sheet KetQua. Khi tôi muốn lấy tên cột của sheet nào thì nó lấy kết quả tên cột của sheet ấy.
Cám ơn bạn, mời bạn cho kết quả nhé.Tôi sẽ dùng Fields Collection của ADODB recordset.
Lưu xuống Sheet thì dùng hàm Transpose().
Cám ơn bạn, mời bạn cho kết quả nhé.
Ra lẹ thế? Đang chờ bài giải của em.Rồi em mò ra được rồi
Sub GetFiled_Thuyyeu99()
Dim SheetName As String
Dim cn As Object, rs As Object, arr() As Variant
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
SheetName = InputBox(prompt:="Nhap ten Sheet", Title:="Lay Filed tren Excel", Default:="Sheet1")
If StrPtr(SheetName) = 0 Then Exit Sub
If SheetName = NullString Then Exit Sub
SheetName = SheetName & "$"
cn.Open _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"data source=" & ThisWorkbook.FullName & ";" & _
"extended properties=excel 12.0 macro;"
Set rs = cn.OpenSchema(4, Array(Empty, Empty, SheetName))
arr = rs.GetRows(, , "COLUMN_NAME")
ActiveCell.Resize(UBound(arr, 2) - LBound(arr, 2) + 1, 1).Value = Application.Transpose(arr)
rs.Close
cn.Close
End Sub
Chính xác là chỗ đó, đáp án như sau:Mã:Sub GetFiled_Thuyyeu99() Dim SheetName As String Dim cn As Object, rs As Object, arr() As Variant Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") SheetName = InputBox(prompt:="Nhap ten Sheet", Title:="Lay Filed tren Excel", Default:="Sheet1") If StrPtr(SheetName) = 0 Then Exit Sub If SheetName = NullString Then Exit Sub SheetName = SheetName & "$" cn.Open _ "Provider=Microsoft.ACE.OLEDB.12.0;" & _ "data source=" & ThisWorkbook.FullName & ";" & _ "extended properties=excel 12.0 macro;" Set rs = cn.OpenSchema(4, Array(Empty, Empty, SheetName)) arr = rs.GetRows(, , "COLUMN_NAME") ActiveCell.Resize(UBound(arr, 2) - LBound(arr, 2) + 1, 1).Value = Application.Transpose(arr) rs.Close cn.Close End Sub
Sub ColumnsName_HLMT()
Dim Arr() As Variant
With CreateObject("ADODB.Connection")
.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ThisWorkbook.FullName + ";Extended Properties=""Excel 12.0"";")
Arr = .OpenSchema(4, Array(Empty, Empty, "Sheet2$", Empty)).getrows(, , "COLUMN_NAME")
End With
ActiveCell.Resize(UBound(Arr, 2) + 1, 1).Value = Application.Transpose(Arr)
End Sub
Lâu quá không trở lại đề tài này, hôm nay mình xin đố các bạn là làm sao lấy được danh sách tên cột của một bảng cho trước mà không dùng vòng lặp?
Trong file mẫu tôi gửi có 3 sheets (Sheet1, Sheet2, Sheet3), và 1 sheet KetQua. Khi tôi muốn lấy tên cột của sheet nào thì nó lấy kết quả tên cột của sheet ấy.
View attachment 241663
Anh hơi đi xa quá rồiKhông xài chữ to mà xài Application.Transpose
Mạnh đoán là hàm đó Bill cũng chạy 2 dòng For đấy
arr = rs.GetRows(, , "COLUMN_NAME")
quậy đi là viết SQL OK đó ... lâu nay Mạnh đang xài nó ... biết vài tháng nay rồi từ trước khi Ông gì hỏi trên GPE lấy SheetName đóAnh cũng dùng ADO OpenSchema nhưng lại không biết chuyển thành array như thế nào... Ai ngờ cái getRows có các tham số như vậy, đúng là chưa khai thác hết nó... hehe.
Anh cũng dùng ADO OpenSchema nhưng lại không biết chuyển thành array như thế nào... Ai ngờ cái getRows có các tham số như vậy, đúng là chưa khai thác hết nó... hehe.
Thật ra cái vụ tên sheet và tên cột đã được HLMT đố vui hồi năm 2015, tuy nhiên nó nằm ở đề tài khác, không nằm ở đây nên muốn "đố lại" cho "đủ bộ"quậy đi là viết SQL OK đó ... lâu nay Mạnh đang xài nó ... biết vài tháng nay rồi từ trước khi Ông gì hỏi trên GPE lấy SheetName đó
bài số 4 link sau
View attachment 241689![]()
Lấy sheet của file trong folder
Nhờ anh em trên Forums xem và giúp. Hiện đang bị lỗi - Hiện tên sheets nhưng chưa lấy được nội dung - Cùng là file *.xls trong 1 folder: file thì hiện tên các sheets, file thì lại khôngwww.giaiphapexcel.com
Trên GPE này có rất nhiều code rất chi là hay ... quan trọng ai đó có biết vận dụng và kết hợp nó lại hay ko đó thôi ...!!!???Thật ra cái vụ tên sheet và tên cột đã được HLMT đố vui hồi năm 2015, tuy nhiên nó nằm ở đề tài khác, không nằm ở đây nên muốn "đố lại" cho "đủ bộ"
Tên sheet
View attachment 241716
Tên cột
View attachment 241717
![]()
Đố vui về ADO, DAO - T3/15
Lâu quá không khởi động chủ đề này, hôm nay xin đưa ra câu đố như sau: Làm thế nào ta có thể liệt kê tất cả tên sheet, name, vùng in... mà không dùng vòng lặp?www.giaiphapexcel.com
sSQL = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES " & _
"WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='" & Me.cboDatabaseName & "'"
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG
Nó nằm trong cái sys.Tables. Nếu dùng câu lệnh ngắn hơn để lấy danh sách Table thì có thể vào đây lấy.Thấy mục này đang hay ... Tiếp theo Mạnh đố chứ ko có hỏi nhe
Câu lệnh SQL sau quá dài vậy có câu nào khác thay thế nó mà mục đích y trang vậy mà ngắn nhất hay ko ???
Nếu lấy phần sau rồi đếm nó thì có 98 ký tự ( Len(SQL) )Mã:sSQL = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES " & _ "WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG='" & Me.cboDatabaseName & "'"
Với câu SQL trên Mạnh viết lại chỉ có 36 ký tựMã:SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_CATALOG
Xin mời góp vui 1 tí
Select name from sys.Tables
chính xác là nó và cái này chạy trên VBA + VB6 + Delphi Ok đóNó nằm trong cái sys.Tables. Nếu dùng câu lệnh ngắn hơn để lấy danh sách Table thì có thể vào đây lấy.
Mã:Select name from sys.Tables
Anh hơi vui tính, nó không những cho lấy được từ những cái trên mà còn hơn thế nữa. Vì sao thì ai cũng có thể hiểu.chạy trên VBA + VB6 + Delphi Ok đó
Vì ngày qua có hỏi thớt bên kia cái chuỗi đó sao trên Delphi nó Ứ có chạy ... mò diết tối qua mới biết...Anh hơi vui tính, nó không những cho lấy được từ những cái trên mà còn hơn thế nữa. Vì sao thì ai cũng có thể hiểu.
Vì ngày qua có hỏi thớt bên kia cái chuỗi đó sao trên Delphi nó Ứ có chạy ... mò diết tối qua mới biết...
vậy là cái chuỗi đó là ok nhất chạy chung cho tất cả đó
Đôi khi ngắn quá cũng không hay, ví dụ để trả về những cái Tables thì còn phải xử lý tiếp lằng nhằng sau đó. Tùy biến mà dùng, dài cũng có lợi thế của nó.Cách ngắn nữa: chạy "Exec sp_tables"![]()
cái này là do Delphi mình khai báo nó chưa có hiễu hay là xài TADOConnection.Create(nil); mà cách khai báo khác nó mới hiểuVụ này ngộ à.
Cùng là câu lệnh truy vấn Table hệ thống của SQL Server mà có Table cho lấy dữ liệu, có Table không chạy được là sao nhỉ?
Bạn dùng SQL Server phiên bản bao nhiêu?
Mỗi Table hệ thống của SQL SV đều chứa những thông tin riêng của nó, tuỳ nhu cầu, tính tiện dụng mà sử dụng thôi.
Cách ngắn nữa: chạy "Exec sp_tables"![]()