- 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.
Làm sao ta có thể dùng 1 điều kiện duy nhất mà có thể lấy ra dữ liệu với họ bắt đầu lần lượt 3 ký tự (N,L,T). Kết quả như hình bên dưới.
View attachment 101583
Hix anh khen làm em thấy "xấu hổ" quá .Đúng thế bạn, bạn cũng là cao thủ rồi.
^^ câu trả lời của bạn hoàn toàn giống ý kiến của mình định đưa ra ,<------- Không biết a Hai Lúa có bổ sung góp ý gì cho bọn em không ?- Dhn46 cũng chỉ dám "ngắm" ADO chứ chưa bước chân vào, nhưng thấy ADO hay quá nên Dhn46 cũng tìm hiểu và xin trả lời câu hỏi của bạn hungpecc1 như sau:
- Với IMEX=1: ADO sẽ kiểm tra 1 số dòng dữ liệu đầu để kiểm tra Data Type cho việc chọn lựa Type để truy vấn (1 số dòng cụ thể ở đây là 8 http://support.microsoft.com/kb/194124/EN-US)
=> Với dữ liệu trong File thì 23 dòng dữ liệu đầu là dạng Date còn 6 dòng sau là dạng Text do đó ADO sẽ kiểm tra 8 dòng dữ liệu đầu cho kết quả là dạng date do đó các loại dữ liệu khác không được truy vấn, dẫn tới sai kết quá
Xin hết ạ!
Buồn đọc lại #58 xin các bạn hãy cho biết dùng cách nào ngoại trừ VBA để lấy tên sheet đầu tiên của 1 file nào đó.
Không phải là không có người hưởng ứng anh ah, hix vì câu hỏi của anh vừa khó vừa khoai!Cũng buồn vì không có người hưởng ứng.
Không phải là không có người hưởng ứng anh ah, hix vì câu hỏi của anh vừa khó vừa khoai!
--> nếu mà không dùng VBA ; (tức là không dùng Sub + End sub) thì em cũng chẳng khác gì 2 tay bị trói anh ah --> đành phải pó tay thôi
Bạn hiểu lầm câu hỏi rồi, dùng ADO hay dùng VBA... đều bắt đầu = Sub và kết thúc = End Sub, nhưng không dùng VBA để lấy thôi. Hy vọng sẽ rõ ràng cho bạn và những bạn khác.
Hihi, không biết diễn giải thế nào cho nó rõ ràng nhỉ, thôi thì dựa vào tiêu đề đề tài chắc là rõ rồi.Vậy không dùng VBA nghĩa là dùng công thức à?
Vì dù dùng ADO thì cũng được viết bằng VBA thôi (trừ phi dùng ADO nhưng được viết trên nền của VB6 hay các ngôn ngữ lập trình khác thì lại là chuyện khác)
1. Nói về bài #58 này thì em tìm hiểu thì có trang này nhưng cũng không hiểu lắm, nhưng sao thầy Tuấn đã làm rồi mà vẫn còn thắc mắc nhỉ?Buồn đọc lại #58 xin các bạn hãy cho biết dùng cách nào ngoại trừ VBA để lấy tên sheet đầu tiên của 1 file nào đó.
Theo em thì điều thầy Tuấn thắc mắc là tên sheet đầu tiên ứng với Sheet1 chứ không phải sheet hiện đầu tiên trong sheet tab như code của anh VieHoai. Cái này em tìm Google mãi chưa ra.
1. Nói về bài #58 này thì em tìm hiểu thì có trang này nhưng cũng không hiểu lắm, nhưng sao thầy Tuấn đã làm rồi mà vẫn còn thắc mắc nhỉ?
2. Em không biết và DAO nhưng tiểm hiểu trên mạng và làm được code sau không biết có chuẩn không:
[GPECODE=vb]Sub FsheetName()
Dim xlWB As DAO.Database
Dim strFirstSheetName As String
Set xlWB = OpenDatabase("E:\VBA\LuongTH.xls", False, True, "Excel 8.0;")
strFirstSheetName = xlWB.TableDefs(0).Name
MsgBox strFirstSheetName
xlWB.Close
End Sub
[/GPECODE]
Sub TestDAO()
Dim Dbs As Object, db As Object
Set Dbs = CreateObject("DAO.DBEngine.36")
Set db = Dbs.OpenDatabase("E:\VBA\LuongTH.xls", False, True, "Excel 8.0;")
MsgBox db.TableDefs(0).Name
db.Close
Set Dbs = Nothing: Set db = Nothing
End Sub
Theo em thì điều thầy Tuấn thắc mắc là tên sheet đầu tiên ứng với Sheet1 chứ không phải sheet hiện đầu tiên trong sheet tab như code của anh VieHoai. Cái này em tìm Google mãi chưa ra.
DAO sẽ lấy chính xác vì nó không tự động sắp xếp như bên ADO Thầy à.Ah, không!
Cái tôi cần là Sheet đầu tiên nhìn thấy trên sheet tab
Vấn đề là khi dùng ADO để lấy tên sheet đầu tiên mà sheet đầu có tên là "ZZZ", sheet thứ 2 có tên là "AAA" thì code sẽ xem sheet đầu tiên là sheet "AAA" (thay gì phải là "ZZZ") ---> Giống như nó đã ưu tiên sort tên sheet theo thứ tự ABC vậy
Chính xác là em muốn nói cái này, dùng DAO để lấy, vì ADO nó sẽ tự động sắp xếp theo thứ tự nên không thể lấy chính xác.
Mã:Sub TestDAO() Dim Dbs As Object, db As Object Set Dbs = CreateObject("DAO.DBEngine.36") Set db = Dbs.OpenDatabase"E:\VBA\LuongTH.xls", False, True, "Excel 8.0;") MsgBox db.TableDefs(0).Name db.Close Set Dbs = Nothing: Set db = Nothing End Sub
Nhân tiện đây xin hỏi là làm sao ta lấy được tất cà tên sheet = DAO?
Set db = Dbs.OpenDatabase(FileName, False, True, "Excel 8.0;")
Ráp vào file bị báo lỗi tại dòng
Tình nghi có liên quan đến version office (tôi dùng office 2010) nên sửa số 8.0 thành 12.0 vẫn lỗi!Mã:Set db = Dbs.OpenDatabase(FileName, False, True, "Excel 8.0;")
Em dùng Office 2013 test nó cho kết quả bình thường.
Public Sub GetSheetName()
Dim db As Database
Dim tdf As TableDef
Set db = OpenDatabase("D:\test.xls", False, False, "Excel 8.0;HDR=NO;IMEX=2;")
For Each tdf In db.TableDefs
MsgBox tdf.Name
Next
Set db = Nothing
End Sub
Sub GetSheetNames1()
Dim cn As ADODB.Connection
Dim cat As ADOX.Catalog
Dim t As ADOX.Table
Set cn = New ADODB.Connection
cn.Open "Provider=MSDASQL.1;Data Source=Excel Files;" _
& "Initial Catalog=C:\Junks\Test Book.xls"
Set cat = New ADOX.Catalog
Set cat.ActiveConnection = cn
For Each t In cat.Tables
Debug.Print t.Name
Next t
Set cat = Nothing
cn.Close
Set cn = Nothing
End Sub
Sub GetSheetNames2()
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = GetExcelConnection("C:\Junks\Test Book.xls")
Set rs = cn.OpenSchema(adSchemaTables)
Do While Not rs.EOF
strTable = rs.Fields("table_name").Value
If Right$(strTable, 1) = "$" Then ' sheet name
strWorksheetList = strWorksheetList & vbCrLf & strTable
Else ' range name
strRangeList = strRangeList & vbCrLf & strTable
End If
rs.MoveNext
Loop
Debug.Print "Worksheets:" & strWorksheetList & vbCrLf & vbCrLf & "Ranges:" & strRangeList
End Sub
Private Function GetExcelConnection(ByVal Path As String, _
Optional ByVal Headers As Boolean = True) As Connection
Dim strConn As String
Dim objConn As ADODB.Connection
Set objConn = New ADODB.Connection
strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & Path & ";" & _
"Extended Properties=""Excel 8.0;HDR=" & _
IIf(Headers, "Yes", "No") & """"
objConn.Open strConn
Set GetExcelConnection = objConn
End Function
Dựa vào trang này em đưa ra Code sau để lấy tên tất cả các sheet dựa theo DAOMã:Public Sub GetSheetName() Dim db As Database Dim tdf As TableDef Set db = OpenDatabase("D:\test.xls", False, False, "Excel 8.0;HDR=NO;IMEX=2;") For Each tdf In db.TableDefs MsgBox tdf.Name Next Set db = Nothing End Sub
2 cách dùng ADO mà tôi biết (có thể có các cách khác tôi không biết)
1. Dùng ADO Exlensions của DDLS (ADOX) để đọc Catalog
Mã:Sub GetSheetNames1() Dim cn As ADODB.Connection Dim cat As ADOX.Catalog Dim t As ADOX.Table Set cn = New ADODB.Connection cn.Open "Provider=MSDASQL.1;Data Source=Excel Files;" _ & "Initial Catalog=C:\Junks\Test Book.xls" Set cat = New ADOX.Catalog Set cat.ActiveConnection = cn For Each t In cat.Tables Debug.Print t.Name Next t Set cat = Nothing cn.Close Set cn = Nothing End Sub
2. Dùng hàm OpenSchema và tham số adSchemaTables để load schema vào một string rồi parse string đó để lấy tên sheet
Mã:Sub GetSheetNames2() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = GetExcelConnection("C:\Junks\Test Book.xls") Set rs = cn.OpenSchema(adSchemaTables) Do While Not rs.EOF strTable = rs.Fields("table_name").Value If Right$(strTable, 1) = "$" Then ' sheet name strWorksheetList = strWorksheetList & vbCrLf & strTable Else ' range name strRangeList = strRangeList & vbCrLf & strTable End If rs.MoveNext Loop Debug.Print "Worksheets:" & strWorksheetList & vbCrLf & vbCrLf & "Ranges:" & strRangeList End Sub Private Function GetExcelConnection(ByVal Path As String, _ Optional ByVal Headers As Boolean = True) As Connection Dim strConn As String Dim objConn As ADODB.Connection Set objConn = New ADODB.Connection strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & Path & ";" & _ "Extended Properties=""Excel 8.0;HDR=" & _ IIf(Headers, "Yes", "No") & """" objConn.Open strConn Set GetExcelConnection = objConn End Function
Cả 2 cách đều lấy tên sheet theo thứ tự abc. Làm thế nào để biết sheet đầu tiên thì tôi lười quá chưa nghĩ ra.
Theo tôi biết, Catalog và Schema đọc tên sheet từ ISAM table cho nên bắt buộc phải theo thứ tự index của ISAM.
ADO phức tạp thậy đấy anh Hai lúa ah, e sửa lại 1 chút anh xem như thế nào nhéCòn phải xử lý bỏ qua name, vùng lọc, vùng in, tiêu đề cần lặp lại...
Public Sub GetSheetName()
Dim db As DAO.Database
Dim tdf As TableDef
Set db = OpenDatabase("D:\test.xls", False, True, "Excel 8.0;")
For Each tdf In db.TableDefs
If Right(tdf.Name, 1) = "$" Or Right(tdf.Name, 2) = "$'" Then
MsgBox tdf.Name
End If
Next
Set db = Nothing
End Sub
Chính xác là vậy rồi, nhưng nên bỏ tham chiếu đến nó.ADO phức tạp thậy đấy anh Hai lúa ah, e sửa lại 1 chút anh xem như thế nào nhéMã:Public Sub GetSheetName() Dim db As DAO.Database Dim tdf As TableDef Set db = OpenDatabase("D:\test.xls", False, True, "Excel 8.0;") For Each tdf In db.TableDefs If Right(tdf.Name, 1) = "$" Or Right(tdf.Name, 2) = "$'" Then MsgBox tdf.Name End If Next Set db = Nothing End Sub
Sub LayTenSheet()
Dim Dbs As Object, db As Object, tbl As Object
Set Dbs = CreateObject("DAO.DBEngine.36")
Set db = Dbs.OpenDatabase("D:\test.xls", False, True, "Excel 8.0;")
For Each tbl In db.TableDefs
If Right(tbl.Name, 1) = "$" Or Right(tbl.Name, 2) = "$'" Then
MsgBox tbl.Name
End If
Next tbl
db.Close
Set Dbs = Nothing: Set db = Nothing: Set tbl = Nothing
End Sub
ADO phức tạp thậy đấy anh Hai lúa ah, e sửa lại 1 chút anh xem như thế nào nhéMã:Public Sub GetSheetName() Dim db As DAO.Database Dim tdf As TableDef Set db = OpenDatabase("D:\test.xls", False, True, "Excel 8.0;") For Each tdf In db.TableDefs If Right(tdf.Name, 1) = "$" Or Right(tdf.Name, 2) = "$'" Then MsgBox tdf.Name End If Next Set db = Nothing End Sub
If Right(SheetName, 1) = "'" Then SheetName = Mid(SheetName, 2, Len(SheetName) - 2)
If Right(SheetName, 1) <> "$" Then SheetName = SheetName & "$"
Dim Dbs As Object, db As Object
Set Dbs = [COLOR=#ff0000]CreateObject("DAO.DBEngine.36")[/COLOR]
Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;")
SheetName = db.TableDefs(0).Name
ADO sẽ không lấy tên sheet như DAO, đó là vấn đề mình muốn nói ở đây.
Bạn lưu ý đừng bao giờ khai báo biến theo kiểu db As DAO.Database, tdf As TableDef... vì chỉ máy bạn mới chạy đuọc còn máy người khác thì... thua (ai biết bạn đã check References nào chứ)
Khai báo kiểu vầy mới chắc ăn:
Code:
Bảo đảm máy nào cũng chạy đượcMã:Dim Dbs As Object, db As Object Set Dbs = [COLOR=#ff0000]CreateObject("DAO.DBEngine.36")[/COLOR] Set db = Dbs.OpenDatabase(FileName, False, False, "Excel 8.0;") SheetName = db.TableDefs(0).Name
Public Sub AutRef()
On Error Resume Next
Application.VBE.ActiveVBProject.References.AddFromFile _
"C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll"
End Sub
Mình thấy rằng việc khai báo đến thư viện của DAO là cần thiết, nhất là đối với những người đang học tập hay tìm tòi như chúng ta. Chính Topic này cũng theo mục đích đó. Như vậy, nó sẽ hỗ trợ chúng ta trong viết Code chính xác, tham vấn trực tiếp được đến các thuộc tính, phương pháp hay cú pháp chuẩn của nó.
Để khắc phục tình trạng sang máy khác không hiểu ta thêm 1 đoạn Code tự xác định tham chiếu đến thư viện nếu nhỡ trong file nào đó không tham chiếu như sau:
Mã:Public Sub AutRef() On Error Resume Next Application.VBE.ActiveVBProject.References.AddFromFile _ "C:\Program Files\Common Files\Microsoft Shared\DAO\dao360.dll" End Sub
Còn đương nhiên cách viết của Ndu là gọn nhưng nó phù hợp cho ai nắm chắc cú pháp viết Code hoặc chép Code , còn người đang học mất hẳn tính năng "nha nhá' gợi ý.
Hoặc ta cứ tham chiếu để viết Code, bao giờ xong ta chuyển sang dạng CreateObject như Ndu.
Em cũng muốn tìm hiểu ADO nên mạnh dạn đưa lời giải đầu tiên, có gì sai sót anh góp ý nhé.Ví dụ tôi có 2 file có đường dẫn là chung 1 folder, file A.xls là file chứa dữ liệu, file còn lại là B.xls.
Xin hỏi: Làm thế nào không mở file B.xls mà ta tạo ra 14 sheet và chuyển dữ liệu từ sheet Data của file A.xls với điều kiện là số liệu của sheet 1 đến 14 được lọc tương ứng ở cột STT vào file B.xls (Tức là sheet 1 thì chỉ chứa STT là 1, sheet 2 thì chỉ chứa STT là 2... sheet 14 thì chỉ chứa STT là 14)
Option Explicit
Sub CopyDL()
Dim i As Long
Dim cnn As Object, lsSQL As String, lrs As Object
Set cnn = CreateObject("ADODB.Connection")
Set lrs = CreateObject("ADODB.Recordset")
With cnn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & ThisWorkbook.Path & "\A.XLS" & _
";Extended Properties=""Excel 8.0;HDR=YES;"";"
.Open
End With
For i = 1 To 14
lsSQL = "select [Data$A1:D30].* INTO Data" & i & " IN '" & ThisWorkbook.Path & _
"\B.xls ' 'Excel 8.0;' FROM [Data$A1:D30] where Stt=" & i
lrs.Open lsSQL, cnn, 3, 1
Next
Set lrs = Nothing
cnn.Close: Set cnn = Nothing
End Sub
Em cũng muốn tìm hiểu ADO nên mạnh dạn đưa lời giải đầu tiên, có gì sai sót anh góp ý nhé.Mã:Option Explicit Sub CopyDL() Dim i As Long Dim cnn As Object, lsSQL As String, lrs As Object Set cnn = CreateObject("ADODB.Connection") Set lrs = CreateObject("ADODB.Recordset") With cnn .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & ThisWorkbook.Path & "\A.XLS" & _ ";Extended Properties=""Excel 8.0;HDR=YES;"";" .Open End With For i = 1 To 14 lsSQL = "select [Data$A1:D30].* INTO Data" & i & " IN '" & ThisWorkbook.Path & _ "\B.xls ' 'Excel 8.0;' FROM [Data$A1:D30] where Stt=" & i lrs.Open lsSQL, cnn, 3, 1 Next Set lrs = Nothing cnn.Close: Set cnn = Nothing End Sub
Đúng là như vậy, không làm khó được bạn. Thật ra nó nằm ở #9
Lrs.Open "SELECT DISTINCT STT FROM [DATA$],cnn,3,1
While i < = Lrs.RecordCount
.......................
Wend
Nếu bây giờ muốn xác định được giá trị 14 ( trong câu lệnh for next )thì phải dùng câu lệnh SQL như thế nào anh nhỉ ?
Không lẽ lại viết:
Trong SQL có hàm Count mà em không biết đưa câu lệnh : "SELECT DISTINCT COUNT(STT) FROM [DATA$] vào VBA như thế nào để lấy giá trị 14?<------------PHP:Lrs.Open "SELECT DISTINCT STT FROM [DATA$],cnn,3,1 While i < = Lrs.RecordCount ....................... Wend
![]()
"select top 1 stt From [Data$] order by stt desc"
Trong trường hợp muốn lấy giá trị cao nhất của cột STT thì bạn có thể dùng
"select top 1 stt From [Data$] order by stt desc"
"select top 1 caiGiDo From [Data$] order by stt desc"
Select MAX(stt) From [Data$]
Xin hỏi các bạn là dùng cách nào để có thể xoá toàn bộ dữ liệu của tất cả các sheet ở 1 file nào đó mà không mở file đó không?
Lại dùng chiêu "ngoại đạo", câu hỏi là xoá toàn bộ dữ liệu của tất cả các sheet ở 1 file nào đó, nếu như dữ liệu nhiều thì duyệt qua từng dòng thì sẽ rất chậm, ít ra cũng phải dùng giống như bài #118 , nhưng sẽ còn cách nữa phải không các bạn?Vọc mãi mà không hiểu sao câu lệnh .DELTE toàn bị lỗi ISAM --> nản , thôi đành dùng cách "chuối củ " này vậy,!<----
[GPECODE=vb]
Sub DELETE()
'On Error Resume Next
Dim cnn As Object, lsSQL As String, lrs As Object, Fld As Object
Dim i As Long
Set cnn = CreateObject("ADODB.Connection")
Set lrs = CreateObject("ADODB.Recordset")
With cnn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & ThisWorkbook.Path & "\B.xls" & _
";Extended Properties=Excel 8.0;"
.Open
End With
With lrs
.Open "SELECT * FROM [DATA$]", cnn, 3, 3
.MoveFirst
Do While Not .EOF
For Each Fld In .Fields
Fld.Value = Null
Next Fld
.MoveNext
Loop
End With
lrs.Close: Set lrs = Nothing
cnn.Close: Set cnn = Nothing
End Sub
[/GPECODE]
lấy luôn dữ liệu file A.xls và file B.xls của câu hỏi bài trước để test!
ặc quên chưa HDR=No,IMEX = 1 ,! <----bác nào test thì nhớ bổ sung nhé!
Để giải bài này em lại đi giải xóa toàn bộ dữ liệu của 1 Sheet nhưng vẫn chưa được. Vậy anh có thể giúp câu lệnh xóa toàn bộ dữ liệu sheet "tb1", file A.xls được không? Em đang nghỉ đến UPDATE toàn bộ thành Null nhưng vẫn chưa đượcXin hỏi các bạn là dùng cách nào để có thể xoá toàn bộ dữ liệu của tất cả các sheet ở 1 file nào đó mà không mở file đó không?
Để giải bài này em lại đi giải xóa toàn bộ dữ liệu của 1 Sheet nhưng vẫn chưa được. Vậy anh có thể giúp câu lệnh xóa toàn bộ dữ liệu sheet "tb1", file A.xls được không? Em đang nghỉ đến UPDATE toàn bộ thành Null nhưng vẫn chưa được
Xin cảm ơn anh
Nếu Update thì Anh nghiên cứu kỹ bài #118 là làm được.
Hix em cũng vọc vụ Update này từ sáng mà chưa xong:
Nếu mà 1 File không biết vùng dữ liệu ở đâu, tên tuổi như thế nào ? thì có 2 vấn đề em đang vướng như sau :
*không thể dùng HDR = Yes đươc
* Không lẽ lại liệt kê từ f1,.....fn , ( cái này cũng không đúng, nhỡ dữ liệu nó chỉ năm từ fm đến fn ) thì sao ?
-->^^ anh thử gợi ý vụ update này thêm được không ?
Nếu không biết bao nhiêu cột thì mình lấy tên cột, đưa tên cột đó vào 1 chuổi truy vấn là được. Nhưng hướng này hơi khó và mất thời gian chạy hơn. Bạn thử nhé.
Kết quả như mong đợi, còn cách không dùng update thì nếu gợi ý là ra liền, nên không thể gợi ýEm thấy vừa khó, vừa khoai, vừa khó nhai hix --> anh test thử xem cách dùng UPDATE để xoá em viết đã ok chưa ?
[GPECODE=vb]
Sub DELETE()
'On Error Resume Next
Dim cnn As ADODB.Connection, rsSchema As ADODB.Recordset, rst As ADODB.Recordset
Dim source As String, TableName As String
Dim i As Long, szFld As String
Set cnn = New ADODB.Connection
source = Application.GetOpenFilename
With cnn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & source & _
";Extended Properties=""Excel 8.0;HDR=No;"";"
.Open
End With
Set rst = New ADODB.Recordset
Set rsSchema = cnn.OpenSchema(adSchemaTables)
While Not rsSchema.EOF
TableName = rsSchema.Fields("TABLE_NAME").Value
With rst
.Open "SELECT * FROM [" & TableName & "]", cnn, 3, 3
For i = 1 To .Fields.Count
szFld = szFld & " F" & i & "= Null"
Next
.Close
End With
rst.Open "UPDATE [" & TableName & "] SET " & Replace(Trim(szFld), " ", ", "), cnn, 3, 1
rsSchema.MoveNext
szFld = vbNullString
Wend
rsSchema.Close: Set rsSchema = Nothing: Set rst = Nothing
cnn.Close: Set cnn = Nothing
End Sub
[/GPECODE]
ps: còn cách thứ 2 không dùng update , ^^ anh phải gợi ý thêm 1 ít thì em mới có hướng để đi , không thì cũng bó tay![]()
ado ko được em định dùng DAO, query delete xem có được ko? Nhưng máy em 64bits >ko hiểu sao ko chạy được DAO 3.6,nên em chưa test được? Toàn báo lỗi run time. 46,nản đi ngủ luôn!Kết quả như mong đợi, còn cách không dùng update thì nếu gợi ý là ra liền, nên không thể gợi ý, bạn chịu khó chút nữa là được.
P/s: Trình độ ADO của bạn càng lúc càng thâm hậu rồi đó.
Cái này có thấy qua lâu lắm rồi. Bây giờ lười tìm lại quá. Hình như là dùng lệnh DROP thì phải.
Nhớ mang máng có vụ cãi vả về lệnh này. Theo tiêu chuẩn thì lệnh bôi dữ liệu table của SQL là TRUNCATE, trong khi đó lệnh DROP TABLE sẽ xoá cả table luôn. Nhưng cụ Excel engine làm việc ngược ngạo, không cho dùng lệnh truncate, và lệnh drop của cụ chỉ bôi dữ liệu chứ không xoá sheet.
Chính xác là phải dùng DROP TABLE trong trường hợp này.
Nếu xác định tên Table để xóa dùng DAO thì với Excell 2003 làChính xác là phải dùng DROP TABLE trong trường hợp này.
N
Bào lỗi lại dòng Set db = OpenDatabase(FileName, False, True, "Excel 12.0;")
Vậy xin hỏi các anh chi phải sửa câu lênh trên như thế nào. Em xin cảm ơn
Nhưng với Excel 2010 là
[GPECODE=vb]Sub DELETE_DAO_2010()
Dim db As DAO.Database
Dim tdf As TableDef
Dim t As ADOX.Table
Dim FileName As String, TableName As String
FileName = Application.GetOpenFilename(",*.xlsx")
Set cnn = New ADODB.Connection
With cnn
.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & FileName & _
";Extended Properties=""Excel 12.0;HDR=No;"";"
.Open
Set db = OpenDatabase(FileName, False, True, "Excel 12.0;")
For Each tdf In db.TableDefs
.Execute " DROP TABLE [" & tdf.Name & "]"
Next
Set db = Nothing.Close
End With
End Sub[/GPECODE]
Bào lỗi lại dòng Set db = OpenDatabase(FileName, False, True, "Excel 12.0;")
View attachment 103235
Vậy xin hỏi các anh chi phải sửa câu lênh trên như thế nào. Em xin cảm ơn
Set db = OpenDatabase(FileName, False, True, "Excel 8.0;")
Anh cho em hỏi: có được phép đặt sẵn f2, f3 tại B1, D1 SheetB Workbook B không anh?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.
..............................
Xin cảm ơn.
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.
Không được phép thêm vào anh à.Anh cho em hỏi: có được phép đặt sẵn f2, f3 tại B1, D1 SheetB Workbook B không anh?
Ghi lên sheetB có sẵn trong B.xls bạn à.Anh cho em hỏi, :
*câu hỏi của anh là :ghi sheetB có sẵn trong B.xls hay là tự tạo một sheet mới rồi ghi vào !
chưa anh ah, em ngâm cứu mãi mà không ra, mấy hôm vừa rồi em thử vọc ALTER TABLE trong excel mà chẳng thấy "hiệu ứng " gì cả ! có lẽ hướng này đi vào ngõ cụt rồi !Không biết các bạn Dhn46, Hungpecc1, VieHoai ... đã tìm ra câu trả lời cho bài này chưa?
chưa anh ah, em ngâm cứu mãi mà không ra, mấy hôm vừa rồi em thử vọc ALTER TABLE trong excel mà chẳng thấy "hiệu ứng " gì cả ! có lẽ hướng này đi vào ngõ cụt rồi !
Để em ngâm cứu đi theo hướng khác![]()
Em mạnh dạn đưa ra đáp án đầu tiên, anh xem và góp ý nhé.Không biết các bạn Dhn46, Hungpecc1, VieHoai ... đã tìm ra câu trả lời cho bài này chưa?
Option Explicit
Sub CopyDL()
Dim i As Long, Target As String
Dim cnn As Object, lsSQL As String, lrs As Object
For i = 1 To 2
Set cnn = CreateObject("ADODB.Connection")
Set lrs = CreateObject("ADODB.Recordset")
If i = 1 Then
Target = ThisWorkbook.Path & "\B.XLS"
lsSQL = "CREATE TABLE [sheetB$] (f1 char(100), f2 char(100), f4 char(100), f3 float)"
Else
Target = ThisWorkbook.FullName
lsSQL = "INSERT INTO [SheetB$] IN '" & ThisWorkbook.Path & _
"\B.xls ' 'Excel 8.0;' SELECT f2, f3 FROM [DataA$A2:C16]"
End If
With cnn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source= " & Target & _
";Extended Properties=""Excel 8.0;HDR=No;"";"
.Open
End With
lrs.Open lsSQL, cnn, 3, 1
Set lrs = Nothing
Next
End Sub
Có 2 điểm cần lưu ý như sau:Em mạnh dạn đưa ra đáp án đầu tiên, anh xem và góp ý nhé.
Mã:Option Explicit Sub CopyDL() Dim i As Long, Target As String Dim cnn As Object, lsSQL As String, lrs As Object For i = 1 To 2 Set cnn = CreateObject("ADODB.Connection") Set lrs = CreateObject("ADODB.Recordset") If i = 1 Then Target = ThisWorkbook.Path & "\B.XLS" lsSQL = "CREATE TABLE [sheetB$] (f1 char(100), f2 char(100), f4 char(100), f3 float)" Else Target = ThisWorkbook.FullName lsSQL = "INSERT INTO [SheetB$] IN '" & ThisWorkbook.Path & _ "\B.xls ' 'Excel 8.0;' SELECT f2, f3 FROM [DataA$A2:C16]" End If With cnn .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source= " & Target & _ ";Extended Properties=""Excel 8.0;HDR=No;"";" .Open End With lrs.Open lsSQL, cnn, 3, 1 Set lrs = Nothing Next End Sub
Câu đố lần này khó quá ! anh phải gợi ý thêm tẹo nữa để định hướng đi vậy !![]()
Em đông ý với bạn Hungpecc1. Đề lần này khó với việc không tạo tiêu đề cột. Anh gợi ý chit chút nữa, để tụi em tìm kiếm nghiền ngẫm, suy đoán cách làm
Hiểu và ứng dụng ADO sẽ là 1 lợi thế vô cùng lớn. Cảm ơn anh Hai lúa chia sẻ và hướng dẫn. Chúc anh sứ khỏe, thánh công!
Em mạnh dạn đưa câu trả lời lần 2 dựa trên gợi ý anh HLMT. Anh xem và góp ý nhéCảm ơn các bạn đã tham gia, xin gợi ý 90% đề bài như sau:
* Mở file B.xls lên, định dạng các cột tương ứng với kiểu dữ liệu cần đưa vào rồi lưu lại là được.
Sub ChuyenDL()
On Error GoTo Handle
Dim cnn As Object, lsSQL As String, lrs As Object
Dim WbOpen As Workbook, Sh As Worksheet
Set cnn = CreateObject("ADODB.Connection")
Set lrs = CreateObject("ADODB.Recordset")
Application.ScreenUpdating = False
Set WbOpen = Application.Workbooks.Open(ThisWorkbook.Path & "\B.xls")
With WbOpen
For Each Sh In .Worksheets
If Sh.Name = "SheetB" Then
Sh.Range("A1:C1").NumberFormat = "@"
Sh.Range("A1:D1").NumberFormat = "0"
Exit For
End If
Next
.Save
.Close
End With
Application.ScreenUpdating = True
With cnn
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & ThisWorkbook.FullName & _
";Extended Properties=""Excel 8.0;HDR=No;Imex=2"";"
.Open
End With
lsSQL = "INSERT INTO [SheetB$](f2,f4) IN '" & ThisWorkbook.Path & _
"\B.xls ' 'Excel 8.0;' SELECT f2,f3 FROM [DataA$A1:D16]"
lrs.Open lsSQL, cnn, 3, 1
Set lrs = Nothing
cnn.Close: Set cnn = Nothing
Exit Sub
Handle:
MsgBox Err.Description
End Sub
Em mạnh dạn đưa câu trả lời lần 2 dựa trên gợi ý anh HLMT. Anh xem và góp ý nhé
Mình cũng đã nghĩ theo hướng này nhưng quả thực chưa tìm được cách, đành phải "liều" dùng VBA để làm. Không để topic này chìm quá lâu được.khôgn biết Có cách nào mà dùng SQL để định dạng dữ liệu ở B.xls không nhỉ ?
vì theo mình nếu mà dùng workbooks.Open thì ta copy luôn dữ liệu vào luôn, cần gì INSERT nữa nhỉ ? --> không biết ý anh HLMT thế nào ?
Vậy bạn thử viết cái Union theo hướng này thử nhé, đó là lý thuyết cái quan trọng là viết như thế nào.Theo như dữ liệu trên, có cột ID thì chỉ việc select top 10 order theo ID, union với top 10 order theo ID ngược, xong order lại cho theo ID xuôi.
Option Explicit
Sub Copy()
On Error GoTo Handle
Dim cnn As Object, lsSQL As String, lrs As Object, FileFullName As String
Set cnn = CreateObject("ADODB.Connection")
Set lrs = CreateObject("ADODB.Recordset")
FileFullName = Application.ThisWorkbook.FullName
With cnn
If Val(Application.Version) < 12 Then
.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & FileFullName & ";Extended Properties=""Excel 8.0;HDR=No"";"
Else
.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FileFullName & ";Extended Properties=""Excel 12.0;HDR=No"";"
End If
.Open
End With
lsSQL = "Select f1,f2,f3,f4,'1:10' as col from [Data$A2:D600] where f1<11 union all select f1,f2,f3,f4,'91:100' as col from [Data$A2:D600] where f1>90"
lrs.Open lsSQL, cnn, 3, 1
Sheet1.[H2:K6000].ClearContents
Sheet1.Range("H2").CopyFromRecordset lrs
Set lrs = Nothing
cnn.Close: Set cnn = Nothing
Exit Sub
Handle:
MsgBox Err.Description
End Sub
Nếu không Union thì như thế này có được không anhVậy ta không dùng union thì câu lệnh khác sẽ như thế nào?
lsSQL = "Select f1,f2,f3,f4,iif(f1<11,'1:10','91:100') as col from [Data$A2:D600] where f1<11 or f1>90"
lsSQL = "Select * From " _
& "(Select top 10 f1,f2,f3,f4,'1:10' as Col from [Data$A2:D600] Order by f1 " _
& "Union all " _
& "Select top 10 a.f1,a.f2,a.f3,a.f4,'91:10' as Col " _
& "from (Select f1,f2,f3,f4 From [Data$A2:D600] Order by f1 Desc)as a) as b " _
& "Order by b.f1"
Em đưa ra 1 phương án nữa, cái này có được không anh HLMT?
ADO ứng dụng viết Code rất hay, ngày trước khi chưa biết thì mày mò với Array, Dictionary. Giờ ứng dụng ADO thấy đơn giản hơn và cũng rất thú vị, không hiểu sao Topic này ít người tham gia thế?Mã:lsSQL = "Select * From " _ & "(Select top 10 f1,f2,f3,f4,'1:10' as Col from [Data$A2:D600] Order by f1 " _ & "Union all " _ & "Select top 10 a.f1,a.f2,a.f3,a.f4,'91:10' as Col " _ & "from (Select f1,f2,f3,f4 From [Data$A2:D600] Order by f1 Desc)as a) as b " _ & "Order by b.f1"
Cảm ơn anh HLMT nhiều!
Em đưa ra 1 phương án nữa, cái này có được không anh HLMT?
ADO ứng dụng viết Code rất hay, ngày trước khi chưa biết thì mày mò với Array, Dictionary. Giờ ứng dụng ADO thấy đơn giản hơn và cũng rất thú vị, không hiểu sao Topic này ít người tham gia thế?Mã:lsSQL = "Select * From " _ & "(Select top 10 f1,f2,f3,f4,'1:10' as Col from [Data$A2:D600] Order by f1 " _ & "Union all " _ & "Select top 10 a.f1,a.f2,a.f3,a.f4,'91:10' as Col " _ & "from (Select f1,f2,f3,f4 From [Data$A2:D600] Order by f1 Desc)as a) as b " _ & "Order by b.f1"
Cảm ơn anh HLMT nhiều!
Nếu id là số liên tục thì có thể không dùng Union. Nhưng lệnh này sẽ chạy chậm.
select * from Bảng where (id <= 10 or (select max(id) from Bang) - id <= 9)
cho Em hỏi thêm anh là: nếu trong cột ID định dạng là text --> thì các mệnh đề WHERE ID <=10 có vẻ không ổn cho lắm , lúc này ta phải giải quyết như thế nào !
Bạn có thấy chuỗi từ "Nếu id là số liên tục" không?
Nếu nó không phải là số liên tục thì phải dùng phương pháp rank. Tôi luời tra cứu cách sử dụng hàm rank trong Access quá (tôi chỉ chuyên dùng T-SQL và SQL Plus)
Ta dùng between cho nó gọn và nhẹNếu biết chắc nó là chuỗi số thì dùng hàm CInt hoặc CLng
select * from Bang where (CInt(id) <= 10 or (select CInt(max(id)) from Bang) - CInt(id) <= 9)
Đính chính: CInt là hàm của VBA, trong query dùng hàm VAL
Sau một đêm suy nghĩ, đã tìm ra cách viết không dùng UNION và cũng không phải dựa vào tính chất liên tục của ID.
Select * from Bang
Where ID IN (Select Top 10 ID From Bang Order By ID Asc)
OR ID IN (Select Top 10 ID From Bang Order By ID Desc)
Cách này chỉ là mẹo khai triển định nghĩa của UNION. Lưu ý là tính tố IN có thể chạy rất chậm đối với một số CSDL
@HLMT:
BETWEEN hàm tính tố AND. Ở đây tuy đề bài là 10 đầu vả 10 cuối nhưng nếu không dùng Union thì giải thuật là 10+10 ở đầu hoặc ở cuối
Tất cả phương án bạn đưa ra đều đúng yêu cầu. Tuy nhiên phải gõ tay cột gom nhóm. Bạn thử không gõ tay cột này xem sao nhé.
Còn cột Group thì bạn sẽ xử lý như thế nào hả bạn?
Không biết các bạn giải quyết được yêu cầu trên chưa?
lsSQL = "Select a.*,'1:10' as f5 from [Data$A2:D600] a where f1<11 union all select b.*,'91:100' as f5 from [Data$A2:D600] b where f1>90"
lsSQL = "Select a.*,iif(f1<11,'1:10','91:100') as col from [Data$A2:D600] a where f1<11 or f1>90"
Rất sáng tạo nhưng vẫn chưa theo yêu cầu. Thôi thì làm từng phần, là làm sao lấy ra kết quả cột Group (1:10,11:20,21:30...91:100), bỏ điều kiện đi nhé.Em xin đưa ra 2 câu truy vấn cho 2 phương án em giải lần trước
Gom nhóm không đánh tay các trường
1/ Dùng Union
2/ Không dùng UnionMã:lsSQL = "Select a.*,'1:10' as f5 from [Data$A2:D600] a where f1<11 union all select b.*,'91:100' as f5 from [Data$A2:D600] b where f1>90"
Mã:lsSQL = "Select a.*,iif(f1<11,'1:10','91:100') as col from [Data$A2:D600] a where f1<11 or f1>90"
Giờ em mới hiểu câu hỏi bỏ đánh trường bằng tay...hihiRất sáng tạo nhưng vẫn chưa theo yêu cầu. Thôi thì làm từng phần, là làm sao lấy ra kết quả cột Group (1:10,11:20,21:30...91:100), bỏ điều kiện đi nhé.
lsSQL = "Select a.*,int((f1-1)/10)*10+1&':'&int((f1-1)/10+1)*10 as col from [Data$A2:D600] a where f1<11 or f1>90"
Giờ em mới hiểu câu hỏi bỏ đánh trường bằng tay...hihi
Em đưa ra phương án như thế này, anh góp ý nhé
Mã:lsSQL = "Select a.*,int((f1-1)/10)*10+1&':'&int((f1-1)/10+1)*10 as col from [Data$A2:D600] a where f1<11 or f1>90"
1./ Dưới 20 dòng thì cũng chạy bình thườngCột group tôi cố tình không nói tới. Lý do là bị ngặt chỗ, 1./ nếu bảng có dưới 20 dòng thì sao? Trong câu truy vấn trước đây, tôi không có đề cập tới chuyện này, nhưng nó vẫn có thể giải quyết được dễ dàng bằng cách dùng lệnh lọc DISTINCT. Một khi phải đặt Group thì group ra sao? 2./ Những dòng trùng nhau thuộc về group nào?
Anh HLMT em kiểm tra sao không thấy mất nhỉ? Nhưng với câu trả lời này của anh thì chắc chắn còn phương án "tuyệt chiêu" nữa...Sẽ mất hết 1 dòng dữ liệu đầu tiên bạn à.
Anh HLMT em kiểm tra sao không thấy mất nhỉ? Nhưng với câu trả lời này của anh thì chắc chắn còn phương án "tuyệt chiêu" nữa...