Kiểm tra hoặc kiểm tra xem trang tính có tồn tại không


115
Dim wkbkdestination As Workbook
Dim destsheet As Worksheet

For Each ThisWorkSheet In wkbkorigin.Worksheets 
    'this throws subscript out of range if there is not a sheet in the destination 
    'workbook that has the same name as the current sheet in the origin workbook.
    Set destsheet = wkbkdestination.Worksheets(ThisWorkSheet.Name) 
Next

Về cơ bản, tôi lặp qua tất cả các trang tính trong sổ làm việc gốc, sau đó đặt destsheettrong sổ làm việc đích thành trang tính có cùng tên với trang hiện được lặp lại trong sổ làm việc gốc.

Làm cách nào để kiểm tra xem trang tính đó có tồn tại không? Cái gì đó như:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 

Câu trả lời:


173

Một số người không thích cách tiếp cận này vì sử dụng xử lý lỗi "không phù hợp", nhưng tôi nghĩ nó được coi là chấp nhận được trong VBA ... Một cách tiếp cận thay thế là lặp lại tất cả các trang tính cho đến khi bạn tìm thấy một kết quả phù hợp.

Function WorksheetExists(shtName As String, Optional wb As Workbook) As Boolean
    Dim sht As Worksheet

    If wb Is Nothing Then Set wb = ThisWorkbook
    On Error Resume Next
    Set sht = wb.Sheets(shtName)
    On Error GoTo 0
    WorksheetExists = Not sht Is Nothing
End Function

5
Hoàn toàn phê duyệt sử dụng IMO. Đó là một cái bẫy cho một thứ được cho là tồn tại và không tồn tại và có lịch sử lâu đời - cf perl nghiêm ngặt, STAE, v.v. Được ủng hộ
Wudang

13
Một có lẽ nên sử dụng ActiveWorkbookthay vì ThisWorkbook. Cái sau đề cập đến sổ làm việc có chứa mã macro, có thể khác với sổ làm việc mà người ta muốn kiểm tra. Tôi đoán ActiveWorkbooksẽ hữu ích cho hầu hết các trường hợp (mặc dù vậy, các tình huống giả định luôn có sẵn).
sancho.s ReinstateMonicaCellio

3
sht Is Nothingsẽ được Truenếu không có tấm với tên đó, nhưng chúng tôi muốn trở lại Truenếu có một tờ với tên đó, vì thế mà Không. Sẽ dễ dàng hơn một chút (nhưng không hợp lệ) nếu bạn sắp xếp lại một chút đểSheetExists = sht Is Not Nothing
Tim Williams

3
Cần lưu ý rằng nếu bạn chạy mã này trong sổ làm việc macro cá nhân của mình, hãy thay đổi từ If wb Is Nothing Then Set wb = ThisWorkbookthànhIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K

2
Đây là một cách tiếp cận hiệu quả cao (xem nhận xét của tôi về điểm chuẩn dưới câu trả lời của Rory bên dưới), vì vậy ai quan tâm những gì những người gièm pha nghĩ. Lưu ý (tính đến thời điểm hiện tại) bạn không có phiếu bầu nào.
rory.ap

107

Nếu bạn đặc biệt quan tâm đến trang tính, bạn có thể sử dụng lệnh gọi Đánh giá đơn giản:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function

14
@Rory Tôi đã chạy một số bài kiểm tra điểm chuẩn về câu trả lời này so với câu trả lời của Tim Williams. Hơn 500.000 vòng lặp, của bạn mất 22 giây và của Tim mất <1.
rory.ap

17
@roryap - nếu bạn cần chạy 500.000 lần này, bạn cần phải suy nghĩ lại toàn bộ cách tiếp cận của mình. ;)
Rory

9
@roryap - tuy nhiên, sử dụng một số phương pháp chậm sẽ bắt đầu chất đống trong giây. Tôi có thể nói đây là thông tin rất có giá trị, như Excel "ứng dụng" bắt đầu để rack lên giây khá dễ dàng với các phương pháp khác nhau Phạm vi, vv
tedcurrent

4
@roryap - thông tin đó có giá trị đối với cuộc trò chuyện theo cách nào? Tôi chỉ đơn giản nói rằng phân tán các phương pháp không hiệu quả xung quanh mã của bạn sẽ làm cho ứng dụng nói chung chậm. bạn thử nghiệm 500k lần này thật tuyệt vời và tôi cảm ơn bạn đã làm điều đó, 22 giây không phải là tuyệt vời. (Tôi đồng ý với bạn)
tedcurrent

6
Ngay cả khi nó chậm hơn, nó trông giống như một giải pháp sạch hơn nhiều so với câu trả lời được chấp nhận. +1 từ tôi.
Sascha L.

49

Bạn không cần xử lý lỗi để thực hiện điều này. Tất cả những gì bạn phải làm là lặp lại tất cả các Trang tính và kiểm tra xem tên được chỉ định có tồn tại hay không:

For i = 1 To Worksheets.Count
    If Worksheets(i).Name = "MySheet" Then
        exists = True
    End If
Next i

If Not exists Then
    Worksheets.Add.Name = "MySheet"
End If

21

Vì việc kiểm tra các thành viên của bộ sưu tập là một vấn đề chung, đây là phiên bản tóm tắt của câu trả lời của Tim:

Hàm chứa (objCollection dưới dạng đối tượng, strName dưới dạng chuỗi) dưới dạng Boolean
    Dim o as Object
    Khi có lỗi Tiếp tục tiếp theo
    đặt o = objCollection (strName)
    Chứa = (Err.Number = 0)
    Err.Clear
 Kết thúc chức năng

Chức năng này có thể được sử dụng với bất kỳ bộ sưu tập như đối tượng ( Shapes, Range, Names, Workbooks, vv).

Để kiểm tra sự tồn tại của một trang tính, hãy sử dụng If Contains(Sheets, "SheetName") ...


5
Điều này không bắt được các kiểu nguyên thủy trong Bộ sưu tập vì Settừ khóa sẽ xuất hiện lỗi . Tôi thấy rằng thay vì sử dụng Set, yêu cầu TypeNamecủa thành viên của bộ sưu tập hoạt động cho tất cả các trường hợp, tức làTypeName objCollection(strName)
citizenkong

2
@Peter: Tốt nhất là thêm một cái gì đó để xóa lỗi sẽ phát sinh trong trường hợp không tồn tại trước khi funciton kết thúc - lỗi. Xóa hoặc Khi Lỗi Tiếp tục Tiếp theo. Nếu không, việc xử lý lỗi trong quy trình gọi có thể vô tình được kích hoạt trong các trường hợp như sau. Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
jeffreyweir

16

Đã sửa: Không xử lý lỗi:

Function CheckIfSheetExists(SheetName As String) As Boolean
      CheckIfSheetExists = False
      For Each WS In Worksheets
        If SheetName = WS.name Then
          CheckIfSheetExists = True
          Exit Function
        End If
      Next WS
End Function

14

Trong trường hợp bất kỳ ai muốn tránh VBA và kiểm tra xem một trang tính có tồn tại hoàn toàn trong một công thức ô hay không, thì có thể sử dụng hàm ISREFINDIRECT:

=ISREF(INDIRECT("SheetName!A1"))

Điều này sẽ trả về TRUEnếu sổ làm việc chứa một trang tính được gọi SheetNameFALSEnếu không.


12

Tôi đã viết cái này:

Function sheetExist(sSheet As String) As Boolean
On Error Resume Next
sheetExist = (ActiveWorkbook.Sheets(sSheet).Index > 0)
End Function

1
Chức năng tuyệt vời! Không chỉ nhanh mà nó còn ngắn gọn nhất.
ChrisB

Tôi tin rằng đây là câu trả lời tương ứng với câu hỏi nhất
Juan Joya

Tôi thích cái này. Lưu ý rằng nó dựa trên thực tế là giá trị mặc định cho sheetExist sẽ là False vì nó là một hàm Boolean. Câu lệnh gán không thực sự gán giá trị False cho sheetExist nếu trang tính không tồn tại, nó chỉ xuất hiện lỗi và giữ nguyên giá trị mặc định. Nếu bạn muốn, bạn có thể dựa trên thực tế là khác không có giá trị nào được gán cho một biến Boolean sẽ cho một kết quả True và bỏ qua sự so sánh> 0, như vậy: sheetExist = ActiveWorkbook.Sheets(sSheet).Index
oddacorn

5

Giải pháp của tôi trông giống Tims nhưng cũng hoạt động trong trường hợp không phải trang tính - biểu đồ

Public Function SheetExists(strSheetName As String, Optional wbWorkbook As Workbook) As Boolean
    If wbWorkbook Is Nothing Then Set wbWorkbook = ActiveWorkbook 'or ThisWorkbook - whichever appropriate
    Dim obj As Object
    On Error GoTo HandleError
    Set obj = wbWorkbook.Sheets(strSheetName)
    SheetExists = True
    Exit Function
HandleError:
    SheetExists = False
End Function

.


3

Đặt thử nghiệm vào một chức năng và bạn sẽ có thể sử dụng lại nó và bạn có khả năng đọc mã tốt hơn.

KHÔNG sử dụng "Khi Lỗi Tiếp tục Tiếp theo" vì nó có thể xung đột với phần khác của mã của bạn.

Sub DoesTheSheetExists()
    If SheetExist("SheetName") Then
        Debug.Print "The Sheet Exists"
    Else
        Debug.Print "The Sheet Does NOT Exists"
    End If
End Sub

Function SheetExist(strSheetName As String) As Boolean
    Dim i As Integer

    For i = 1 To Worksheets.Count
        If Worksheets(i).Name = strSheetName Then
            SheetExist = True
            Exit Function
        End If
    Next i
End Function

3

Đã trễ nhiều năm, nhưng tôi chỉ cần làm điều này và không thích bất kỳ giải pháp nào được đăng ... Vì vậy, tôi đã tạo ra một giải pháp, tất cả là nhờ phép thuật của (cử chỉ tay cầu vồng SpongeBob) "Đánh giá ()"!

Evaluate("IsError(" & vSheetName & "!1:1)")

Trả về TRUE nếu Trang tính KHÔNG tồn tại; FALSE nếu trang tính KHÔNG tồn tại. Bạn có thể thay thế bất kỳ phạm vi nào bạn muốn cho "1: 1", nhưng tôi khuyên bạn không nên sử dụng một ô duy nhất, vì nếu nó chứa lỗi (ví dụ: # N / A), nó sẽ trả về True.


3

wsExistsChức năng nhỏ gọn ( không phụ thuộc vào Xử lý lỗi!)

Đây là một hàm ngắn và đơn giản không dựa vào xử lý lỗi để xác định xem trang tính có tồn tại hay không ( được khai báo đúng cách để hoạt động trong mọi tình huống!)

Function wsExists(wsName As String) As Boolean
    Dim ws: For Each ws In Sheets
    wsExists = (wsName = ws.Name): If wsExists Then Exit Function
    Next ws
End Function

Cách sử dụng ví dụ:

Ví dụ sau thêm một trang tính mới có tên myNewSheet, nếu nó chưa tồn tại:

If Not wsExists("myNewSheet") Then Sheets.Add.Name = "myNewSheet"

Thêm thông tin:


2

Tại sao không chỉ sử dụng một vòng lặp nhỏ để xác định xem trang tính được đặt tên có tồn tại hay không? Giả sử bạn đang tìm kiếm một Trang tính có tên "Sheet1" trong sổ làm việc hiện đang mở.

Dim wb as Workbook
Dim ws as Worksheet

Set wb = ActiveWorkbook

For Each ws in wb.Worksheets

    if ws.Name = "Sheet1" then
        'Do something here
    End if

Next

2

Nếu bạn là người yêu thích WorksheetFunction.hoặc bạn làm việc từ một quốc gia không sử dụng tiếng Anh với Excel không phải tiếng Anh, đây là một giải pháp tốt, hoạt động:

WorksheetFunction.IsErr(Evaluate("'" & wsName & "'!A1"))

Hoặc trong một chức năng như thế này:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Not WorksheetFunction.IsErr(Evaluate("'" & sName & "'!A1"))
End Function

1
Public Function WorkSheetExists(ByVal strName As String) As Boolean
   On Error Resume Next
   WorkSheetExists = Not Worksheets(strName) Is Nothing
End Function

sub test_sheet()

 If Not WorkSheetExists("SheetName") Then
 MsgBox "Not available"
Else MsgBox "Available"
End If

End Sub

1
    For Each Sheet In Worksheets
    If UCase(Sheet.Name) = "TEMP" Then
    'Your Code when the match is True
        Application.DisplayAlerts = False
        Sheet.Delete
        Application.DisplayAlerts = True
    '-----------------------------------
    End If
Next Sheet

1

Thay đổi "Dữ liệu" thành bất kỳ tên trang tính nào bạn đang kiểm tra ...

On Error Resume Next 

Set DataSheet = Sheets("Data")

If DataSheet Is Nothing Then

     Sheets.Add(after:=ActiveSheet).Name = "Data"
     ''or whatever alternate code you want to execute''
End If

On Error GoTo 0

1

Không nghi ngờ gì rằng chức năng trên có thể hoạt động, tôi vừa kết thúc với đoạn mã sau hoạt động khá tốt:

Sub Sheet_exist ()
On Error Resume Next
If Sheets("" & Range("Sheet_Name") & "") Is Nothing Then
    MsgBox "doesnt exist"
Else
    MsgBox "exist"
End if
End sub

Lưu ý: Sheets_Namelà nơi tôi yêu cầu người dùng nhập tên, vì vậy tên này có thể không giống với bạn.


0

Tôi đã làm một điều khác: xóa một trang tính chỉ khi nó tồn tại - không gặp lỗi nếu nó không:

Excel.DisplayAlerts = False 
Dim WS
For Each WS In Excel.Worksheets
    If WS.name = "Sheet2" Then
        Excel.sheets("Sheet2").Delete
        Exit For
    End If
Next
Excel.DisplayAlerts = True

0

Tôi đã nghĩ ra một cách dễ dàng để làm điều đó, nhưng tôi không tạo phụ đề mới cho nó. Thay vào đó, tôi chỉ "chạy kiểm tra" trong sub mà tôi đang làm việc. Giả sử tên trang tính mà chúng tôi đang tìm là "Sheet_Exist" và chúng tôi chỉ muốn kích hoạt nó nếu tìm thấy:

Dim SheetCounter As Integer

SheetCounter = 1

Do Until Sheets(SheetCounter).Name = "Sheet_Exist" Or SheetCounter = Sheets.Count + 1
 SheetCounter = SheetCounter +1
Loop
If SheetCounter < Sheets.Count + 1 Then
 Sheets("Sheet_Exist").Activate
Else
 MsgBox("Worksheet ""Sheet_Exist"" was NOT found")
End If

Tôi cũng đã thêm một cửa sổ bật lên khi trang tính không tồn tại.


0

Tôi biết đó là một bài viết cũ, nhưng đây là một giải pháp đơn giản khác nhanh chóng.

Public Function worksheetExists(ByVal wb As Workbook, ByVal sheetNameStr As String) As Boolean

On Error Resume Next
worksheetExists = (wb.Worksheets(sheetNameStr).Name <> "")
Err.Clear: On Error GoTo 0

End Function

0

Ngắn gọn và sạch sẽ:

Function IsSheet(n$) As Boolean
    IsSheet = Not IsError(Evaluate(n & "!a1"))
End Function

-4

Tôi thực sự có một cách đơn giản để kiểm tra xem trang tính có tồn tại hay không và sau đó thực hiện một số hướng dẫn:

Trong trường hợp của tôi, tôi muốn xóa trang tính và sau đó tạo lại cùng một trang tính có cùng tên nhưng mã bị gián đoạn nếu chương trình không thể xóa trang tính vì nó đã bị xóa

Sub Foo ()

    Application.DisplayAlerts = False

    On Error GoTo instructions
    Sheets("NAME OF THE SHEET").Delete

    instructions:

    Sheets.Add After:=Sheets(Sheets.Count)
    ActiveSheet.Name = "NAME OF THE SHEET"

End Sub

Vấn đề với câu trả lời này là khi xác định rằng trang tính thực sự tồn tại, nó sẽ bị xóa và do đó không còn tồn tại nữa. Nếu điều này được viết dưới dạng một hàm, nó có thể có tên như SheetExistsAfterDeletion và sẽ luôn trả về FALSE.
ChrisB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.