Mở 1 file exxcel bất kỳ. gõ " =C:\MYFOLDER\[filename]Sheetname'!$B$4"Chào các anh chị trên diễn đàn.
Tôi có điều cần trợ giúp: Muốn kiểm tra sheetname có tồn tại trong filename.xls ở thư mục C:\MYFOLDER mà không mở file.
Xin cảm ơn.
On Error Resume Next
str = Dir$(<tên file>)
If str = vbNullString Then
'không tồn tại
Else
'tồn tại
End If
Chào các anh chị trên diễn đàn.
Tôi có điều cần trợ giúp: Muốn kiểm tra sheetname có tồn tại trong filename.xls ở thư mục C:\MYFOLDER mà không mở file.
Xin cảm ơn.
Workbooks.Open " đường dẫn"
For ws in worksheets
If ws.name = "..." then
next
Workbooks.close(..)
Còn nếu bắt buộc không mở file theo cách bạn muốn --> vọc thêm về topic ADO trên diễn đàn
Function SheetExists(ByVal strExcelFullName As String, ByVal strSheetName As String) As Boolean
SheetExists = False
On Error GoTo ErrorHandler
Dim objExcel As Object
Set objExcel = CreateObject("ADODB.Recordset")
Dim FileExists As Boolean
FileExists = (GetAttr(strExcelFullName) And vbNormal) = vbNormal
Dim sAppEName As String
If FileExists Then
sAppEName = "DRIVER=Microsoft Excel Driver (*.xls);" & "DBQ=" & strExcelFullName
objExcel.Open "SELECT * FROM [" & strSheetName & "$]", sAppEName
SheetExists = True
End If
Exit Function
ErrorHandler:
If Not FileExists Then MsgBox "Error Description : " & Err.Description
End Function
Sub test()
MsgBox SheetExists(ThisWorkbook.Path & "\Test.xls", "Sheet2")
End Sub
Cảm ơn các bác đã quan tâm.
1. Có thể em dùng từ chưa được chính xác. Yêu cầu chính xác là "...mà không nhìn thấy mở file"
2. Mô tả công việc cụ thể thêm: Tổng hợp từ nhiều file vào 1 file
- Từ file tổng hợp chọn thư mục chứa các file.
- Dùng công thức dạng link (=thumuc\[file]sheet!range)
- Bỏ công thức (value=value)
Chú ý:Làm cho Excel2003, các bạn test thử và mở rộng thêm:
Mã:Function SheetExists(ByVal strExcelFullName As String, ByVal strSheetName As String) As Boolean SheetExists = False On Error GoTo ErrorHandler Dim objExcel As Object Set objExcel = CreateObject("ADODB.Recordset") Dim FileExists As Boolean FileExists = (GetAttr(strExcelFullName) And vbNormal) = vbNormal Dim sAppEName As String If FileExists Then sAppEName = "DRIVER=Microsoft Excel Driver (*.xls);" & "DBQ=" & strExcelFullName objExcel.Open "SELECT * FROM [" & strSheetName & "$]", sAppEName SheetExists = True End If Exit Function ErrorHandler: If Not FileExists Then MsgBox "Error Description : " & Err.Description End Function
Ví dụ:
Mã:Sub test() MsgBox SheetExists(ThisWorkbook.Path & "\Test.xls", "Sheet2") End Sub
Thì bạn làm 1 cái thử xem thế nào
(Tôi cũng đang làm 1 cái tương tự nhưng.. đang test...)
Viết code kiểu đó ai mà test được đâyEm thử viết như vầy:
Mã:Function SheetExist(SheetName As String, Optional FileName As String = "") As Boolean Dim tmp As String [COLOR=#ff0000]With New ADODB.Connection[/COLOR] .ConnectionString = "[COLOR=#0000cd]Provider=Microsoft.ACE.OLEDB.12.0[/COLOR];" & _ "Data Source=" & IIf(FileName = "", ThisWorkbook.FullName, FileName) & _ ";Extended Properties=""Excel 12.0;HDR=No;"";" .Open [COLOR=#ff0000]With .OpenSchema(adSchemaTables)[/COLOR] While Not .EOF If .Fields("TABLE_TYPE") = "TABLE" Then tmp = Replace(.Fields("TABLE_NAME"), "'", "") If UCase(tmp) Like UCase(SheetName & "$") Then SheetExist = True End If .MoveNext Wend End With End With End Function
Function SheetExists(ByVal SheetName As String, Optional ByVal FileName As String = "") As Boolean
Dim dao As Object, db As Object
Dim i As Long, lVer As Long
Dim tmp As String
On Error Resume Next
lVer = Val(Application.Version)
If Len(FileName) = 0 Then FileName = ThisWorkbook.FullName
Set dao = CreateObject("DAO.DBEngine." & IIf(lVer < 12, "36", "120"))
Set db = dao.OpenDatabase(FileName, False, False, "Excel 8.0;")
tmp = CStr(db.TableDefs(SheetName & "$").Name)
If Len(tmp) = 0 Then tmp = CStr(db.TableDefs("'" & SheetName & "$'").Name)
SheetExists = (Len(tmp) > 0)
db.Close: Set dao = Nothing: Set db = Nothing
End Function
Function SheetExists(ByVal fileName As String, ByVal sheetName As String)
Dim cn As ADODB.Connection
Dim cat As ADOX.Catalog
Dim t As ADOX.Table
SheetExists = False
Set cn = New ADODB.Connection
cn.Open "Provider=MSDASQL.1;Data Source=Excel Files;" _
& "Initial Catalog=" & fileName
Set cat = New ADOX.Catalog
Set cat.ActiveConnection = cn
For Each t In cat.Tables
If t.Name = sheetName & "$" Then
SheetExists = True
Exit For
End If
Next t
Set cat = Nothing
cn.Close
Set cn = Nothing
End Function
Có mấy vấn đề@thanhlanh:
Code của bạn không sai nhưng có hai điểm mà người lập trình nên tránh:
1. Code không huỷ object sau khi sử dụng
2. Code dùng hiện tượng bắt lỗi để làm việc chính. Đối với lập trình, hiện tượng bắt lỗi là chuyện cực chẳng đã, chỉ dùng để bắt những trường hợp không biết trước. Nếu có cách nào khác, người ta luôn luôn chọn cách khác.
Đọc Schema qua ADO hay DAO như hai bạn trên là cách đơn giản hơn.
Tôi xin hầu thêm cách đọc Catalog qua ADOX
Mã:Function SheetExists(ByVal fileName As String, ByVal sheetName As String) Dim cn As ADODB.Connection Dim cat As ADOX.Catalog Dim t As ADOX.Table SheetExists = False Set cn = New ADODB.Connection cn.Open "Provider=MSDASQL.1;Data Source=Excel Files;" _ & "Initial Catalog=" & fileName Set cat = New ADOX.Catalog Set cat.ActiveConnection = cn For Each t In cat.Tables If [COLOR=#ff0000]t.Name = sheetName & "$"[/COLOR] Then SheetExists = True Exit For End If Next t Set cat = Nothing cn.Close Set cn = Nothing End Function
Cảm ơn bạn đã dẫn. Tôi cứ ngỡ code trên dùng ODBC nên thoát khỏi cảnh phải lồng giữa 2 dấu nháy. Không chịu thử cho kỹ.
Hoá ra đọc theo tầng trên (metadata) còn tệ hơn đọc theo kiểu dữ liệu thô.
@thanhlanh:
Code của bạn không sai nhưng có hai điểm mà người lập trình nên tránh:
1. Code không huỷ object sau khi sử dụng
2. Code dùng hiện tượng bắt lỗi để làm việc chính. Đối với lập trình, hiện tượng bắt lỗi là chuyện cực chẳng đã, chỉ dùng để bắt những trường hợp không biết trước. Nếu có cách nào khác, người ta luôn luôn chọn cách khác.
Đọc Schema qua ADO hay DAO như hai bạn trên là cách đơn giản hơn.
Tôi xin hầu thêm cách đọc Catalog qua ADOX
Mã:Function SheetExists(ByVal fileName As String, ByVal sheetName As String) Dim cn As ADODB.Connection Dim cat As ADOX.Catalog Dim t As ADOX.Table SheetExists = False Set cn = New ADODB.Connection cn.Open "Provider=MSDASQL.1;Data Source=Excel Files;" _ & "Initial Catalog=" & fileName Set cat = New ADOX.Catalog Set cat.ActiveConnection = cn For Each t In cat.Tables If t.Name = sheetName & "$" Then SheetExists = True Exit For End If Next t Set cat = Nothing cn.Close Set cn = Nothing End Function
Option Explicit
Function SheetExist(ByVal mPath As String, fName As String, ShName As String) As Boolean
Dim Tm, myVar
On Error Resume Next
Tm = "'" & mPath & "[" & fName & "]" & ShName & "'!" & _
Range("A1").Address(, , xlR1C1)
myVar = ExecuteExcel4Macro(Tm)
SheetExist = Not IsEmpty(myVar)
End Function
'--------------------------------------------------------------------------------
Sub Test()
Dim myPath As String, myFile As String, mySheet As String
myPath = Thisworkbook.Path & "\"
myFile = "Mau danh cho CC BCTC48.xls"
mySheet = "B-01"
MsgBox IIf(SheetExist(myPath, myFile, mySheet), _
"Exist sheet: " & mySheet, "The sheet: " & mySheet & " not foumd")
End Sub
Mặc dù em không có vay hoặc cho vay nhưng em biết cái ODA là gì đó anhmình đâu biết gì về ADO, DAO hay ODA đâu
Code này chỉ chạy trên VBA như 1 sub thì được... Anh thử gõ trực tiếp hàm xuống sheet xem nó ra kết quả gì?Vấn đề này dùng hàm Macro4 cũng tốt mà gọn. Mình ví dụ như sau
Mã:Option Explicit Function SheetExist(ByVal mPath As String, fName As String, ShName As String) 'As Boolean Dim Tm On Error Resume Next Tm = "'" & mPath & "[" & fName & "]" & ShName & "'!" & _ Range("A1").Address(, , xlR1C1) SheetExist = ExecuteExcel4Macro(Tm) End Function '----------------------------------------------------------------------------------- Sub Test() Dim myPath As String, myFile As String, mySheet As String myPath = Thisworkbook.Path & "\" myFile = "Mau danh cho CC BCTC48.xls" mySheet = "B-01" MsgBox IIf(IsEmpty(SheetExist(myPath, myFile, mySheet)), _ "The sheet: " & mySheet & " not foumd", "Exist sheet: " & mySheet) End Sub
Mặc dù em không có vay hoặc cho vay nhưng em biết cái ODA là gì đó anh
Ẹc... Ẹc...
-------------------------
Code này chỉ chạy trên VBA như 1 sub thì được... Anh thử gõ trực tiếp hàm xuống sheet xem nó ra kết quả gì?
Test trong môi trường VBA thì được:Mình viết lại rồi, chỉ thay đổi cách gán giá trị cho Hàm thôi
Sub Test()
Dim mPath As String, fName As String, ShName As String
mPath = [A5]
fName = [A6]
ShName = [B1]
MsgBox SheetExist(mPath, fName, ShName)
End Sub
Nếu kiểm tra sự tồn tại của 1 file nào đó thì chỉ cần kiểm tra trong file đó có 1 sheet là xem như file đó đã tồn tại, cần gì phải dùng vòng lặp duyệt qua rồi tìm thấy rồi dừng vòng lặp?@thanhlanh:
Code của bạn không sai nhưng có hai điểm mà người lập trình nên tránh:
1. Code không huỷ object sau khi sử dụng
2. Code dùng hiện tượng bắt lỗi để làm việc chính. Đối với lập trình, hiện tượng bắt lỗi là chuyện cực chẳng đã, chỉ dùng để bắt những trường hợp không biết trước. Nếu có cách nào khác, người ta luôn luôn chọn cách khác.
Đọc Schema qua ADO hay DAO như hai bạn trên là cách đơn giản hơn.
Tôi xin hầu thêm cách đọc Catalog qua ADOX
Mã:Function SheetExists(ByVal fileName As String, ByVal sheetName As String) Dim cn As ADODB.Connection Dim cat As ADOX.Catalog Dim t As ADOX.Table SheetExists = False Set cn = New ADODB.Connection cn.Open "Provider=MSDASQL.1;Data Source=Excel Files;" _ & "Initial Catalog=" & fileName Set cat = New ADOX.Catalog Set cat.ActiveConnection = cn For Each t In cat.Tables If t.Name = sheetName & "$" Then SheetExists = True Exit For End If Next t Set cat = Nothing cn.Close Set cn = Nothing End Function
Dùng trong VBA được là tốt rồi, miễn sao trả về kết quả chính xác với mọi phiên bản Excel và với mọi tên Sheet, tên file.Test trong môi trường VBA thì được:
Mã:Sub Test() Dim mPath As String, fName As String, ShName As String mPath = [A5] fName = [A6] ShName = [B1] MsgBox SheetExist(mPath, fName, ShName) End Sub
Nhưng nếu anh gõ hàm trực tiếp xuống sheet, ví dụ: =SheetExist(A5, A6, B1) với A5 là thư mục, A5 là tên file và B1 là tên sheet ---> Kết quả toàn = FALSE thôi anh à
Nếu kiểm tra sự tồn tại của 1 file nào đó thì chỉ cần kiểm tra trong file đó có 1 sheet là xem như file đó đã tồn tại, cần gì phải dùng vòng lặp duyệt qua rồi tìm thấy rồi dừng vòng lặp?
Tại sao bạn ghi là đơn giản mà trong khi đó phải dùng thêm vòng lặp? Có phải bị thừa?Bạn có thấy tôi dùng từ "đơn giản" không?
Định nghĩa đơn giản là dễ hiểu dễ dùng dễ sửa. Theo quan điểm của lập trình thì quan trọng nhất là "nếu có chỗ sai thì dễ nhìn ra"
Tại sao bạn ghi là đơn giản mà trong khi đó phải dùng thêm vòng lặp? Có phải bị thừa?
Vòng lặp để làm gì khi ta xác định chỉ có 1Ah... đơn giản nó khác với code ngắn gọn nha
Lúc đầu tôi viết code kiểm tra sự tồn tại của sheet, tôi dùng DAO cũng thông quan vòng lập. Sau đó mới sửa lại thành không vòng lập và tôi nhận xét thấy:
- Có vòng lập thì dễ nhìn hơn (dễ hiểu tức là đơn giản)
- Không vòng lập: Code ngắn hơn (nhưng hơi khó hiểu hơn)
Mặc khác: Chưa chắc khi ta không dùng vòng lập thì tốc độ sẽ cao hơn đâu