ทดสอบหรือตรวจสอบว่ามีแผ่นงานอยู่หรือไม่


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

โดยทั่วไปฉันวนซ้ำแผ่นงานทั้งหมดในสมุดงานต้นทางจากนั้นตั้งค่าdestsheetในสมุดงานปลายทางเป็นแผ่นงานที่มีชื่อเดียวกันกับแผ่นงานที่ทำซ้ำในปัจจุบันในสมุดงานต้นทาง

ฉันจะทดสอบได้อย่างไรว่ามีแผ่นงานนั้นอยู่ สิ่งที่ต้องการ:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 

คำตอบ:


173

ชาวบ้านบางคนไม่ชอบแนวทางนี้เนื่องจากการใช้การจัดการข้อผิดพลาดที่ "ไม่เหมาะสม" แต่ฉันคิดว่าถือว่าเป็นที่ยอมรับใน VBA ... อีกทางเลือกหนึ่งคือการวนซ้ำแผ่นงานทั้งหมดจนกว่าคุณจะพบรายการที่ตรงกัน

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
ใช้ IMO โดยสิ้นเชิง มันเป็นกับดักสำหรับสิ่งที่ถูกวางไว้ว่ามีอยู่และไม่มีและมีประวัติอันยาวนาน - cf perl เข้มงวด, STAE เป็นต้นโหวต
Wudang

13
ควรใช้ActiveWorkbookแทนThisWorkbook. ส่วนหลังหมายถึงสมุดงานที่มีรหัสแมโครซึ่งอาจแตกต่างจากสมุดงานมากกว่าที่ต้องการทดสอบ ฉันเดาว่าActiveWorkbookจะมีประโยชน์สำหรับกรณีส่วนใหญ่ (แม้ว่าสถานการณ์ที่กำหนดไว้จะพร้อมใช้งานเสมอ)
sancho.s ReinstateMonicaCellio

3
sht Is NothingจะTrueว่ามีแผ่นที่มีชื่อว่าไม่มี แต่เราต้องการที่จะกลับมาTrueถ้ามีเป็นแผ่นที่มีชื่อนั้นจึงไม่ ง่ายกว่าเล็กน้อย (แต่ไม่ถูกต้อง) หากคุณจัดเรียงอีกครั้งเป็นSheetExists = sht Is Not Nothing
Tim Williams

3
โปรดทราบว่าหากคุณเรียกใช้รหัสนี้ในสมุดงานมาโครส่วนตัวให้เปลี่ยนจากIf wb Is Nothing Then Set wb = ThisWorkbookเป็นIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K

2
นี่เป็นแนวทางที่มีประสิทธิภาพสูง (ดูความคิดเห็นของฉันเกี่ยวกับเครื่องหมายบัลลังก์ภายใต้คำตอบของ Rory ด้านล่าง) ดังนั้นใครจะสนใจว่าผู้ว่าคิดอย่างไร หมายเหตุ (ณ ตอนนี้) คุณมีคะแนนโหวตเป็นศูนย์
rory.ap

107

หากคุณสนใจเฉพาะในเวิร์กชีตเท่านั้นคุณสามารถใช้การเรียกใช้ Evaluate ง่ายๆ

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

14
@Rory ฉันทำการทดสอบเกณฑ์มาตรฐานเกี่ยวกับคำตอบนี้กับคำตอบของ Tim Williams มากกว่า 500,000 ลูปคุณใช้เวลา 22 วินาทีส่วนทิมใช้เวลา <1
rory.ap

17
@roryap - หากคุณต้องการเรียกใช้ 500,000 ครั้งนี้คุณต้องคิดทบทวนวิธีการทั้งหมดของคุณใหม่ ;)
รอรี

9
@roryap - อย่างไรก็ตามการใช้วิธีการช้าหลายวิธีจะเริ่มต้นขึ้นในไม่กี่วินาที ฉันจะบอกว่านี่เป็นข้อมูลที่มีค่าอย่างยิ่งเนื่องจาก "แอปพลิเคชัน" ของ Excel เริ่มต้นขึ้นในไม่กี่วินาทีได้อย่างง่ายดายด้วยวิธีการต่างๆเป็นต้น
tedcurrent

4
@roryap - ข้อมูลนั้นมีประโยชน์ต่อการสนทนาในทางใด? ฉันเพียงแค่ระบุว่าการกระจายวิธีการที่ไม่มีประสิทธิภาพรอบ ๆ โค้ดของคุณจะทำให้แอปพลิเคชันช้าโดยรวม คุณทดสอบ 500k ครั้งนี้ยอดเยี่ยมมากและฉันขอขอบคุณที่ทำมัน 22 วินาทีไม่ได้ยอดเยี่ยม (ฉันเห็นด้วยกับคุณ)
tedcurrent

6
แม้ว่าจะช้ากว่า แต่ก็ดูเหมือนเป็นวิธีแก้ปัญหาที่สะอาดกว่าคำตอบที่ยอมรับ +1 จากฉัน
Sascha L.

49

คุณไม่จำเป็นต้องจัดการข้อผิดพลาดเพื่อที่จะทำสิ่งนี้ให้สำเร็จ สิ่งที่คุณต้องทำคือทำซ้ำบนแผ่นงานทั้งหมดและตรวจสอบว่ามีชื่อที่ระบุอยู่หรือไม่:

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

เนื่องจากการตรวจสอบสมาชิกของคอลเล็กชันเป็นปัญหาทั่วไปนี่คือคำตอบของ Tim ที่เป็นนามธรรม:

ฟังก์ชันประกอบด้วย (objCollection As Object, strName as String) เป็น Boolean
    Dim o เป็นวัตถุ
    ใน Error Resume Next
    ตั้งค่า o = objCollection (strName)
    ประกอบด้วย = (Err.Number = 0)
    สิ้นสุด Err.Clear
 สิ้นสุดฟังก์ชัน

ฟังก์ชั่นนี้สามารถใช้กับคอลเลกชันใด ๆ เช่นวัตถุ ( Shapes, Range, Names, Workbooksฯลฯ )

ในการตรวจสอบการมีอยู่ของแผ่นงานให้ใช้ If Contains(Sheets, "SheetName") ...


5
สิ่งนี้ไม่จับประเภทดั้งเดิมในคอลเล็กชันเนื่องจากSetคำหลักจะยกข้อผิดพลาด ฉันพบว่าแทนที่จะใช้Setขอให้TypeNameสมาชิกของคอลเลกชันทำงานได้ทุกกรณีเช่นTypeName objCollection(strName)
citizenkong

2
@Peter: ควรเพิ่มบางอย่างเพื่อล้างข้อผิดพลาดที่จะเกิดขึ้นในกรณีที่ไม่มีอยู่ก่อนที่ funciton จะสิ้นสุดลงไม่ว่าจะเป็น err.clear หรือ On Error Resume Next มิฉะนั้นการจัดการข้อผิดพลาดในขั้นตอนการโทรอาจถูกกระตุ้นโดยไม่ได้ตั้งใจในกรณีดังต่อไปนี้ Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
jeffreyweir

16

แก้ไข: ไม่มีการจัดการข้อผิดพลาด:

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

ในกรณีที่ใครก็ตามต้องการหลีกเลี่ยง VBA และทดสอบว่าเวิร์กชีตมีอยู่ในสูตรของเซลล์หรือไม่สามารถทำได้โดยใช้ฟังก์ชันISREFand INDIRECT:

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

สิ่งนี้จะส่งคืนTRUEหากสมุดงานมีแผ่นงานที่เรียกSheetNameและFALSEอื่น ๆ


12

ฉันเขียนสิ่งนี้:

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

1
ฟังก์ชั่นเยี่ยม! ไม่เพียง แต่รวดเร็วเท่านั้น แต่ยังกระชับที่สุดอีกด้วย
ChrisB

ฉันเชื่อว่านี่คือคำตอบที่ตรงกับคำถามมากที่สุด
Juan Joya

ฉันชอบอันนี้ โปรดทราบว่ามันขึ้นอยู่กับข้อเท็จจริงที่ว่าค่าเริ่มต้นสำหรับ sheetExist จะเป็น False เนื่องจากเป็นฟังก์ชันบูลีน คำสั่งมอบหมายไม่ได้กำหนดค่า False ให้กับ sheetExist หากไม่มีแผ่นงาน แต่จะเกิดข้อผิดพลาดและปล่อยค่าเริ่มต้นไว้ หากคุณต้องการคุณสามารถพึ่งพาข้อเท็จจริงที่ว่าค่าใด ๆ ที่ไม่ใช่ศูนย์ที่กำหนดให้กับตัวแปรบูลีนจะให้ผลลัพธ์ที่แท้จริงและไม่ต้องใช้การเปรียบเทียบ> 0 ดังนี้ sheetExist = ActiveWorkbook.Sheets(sSheet).Index
oddacorn

5

โซลูชันของฉันดูเหมือน Tims มาก แต่ก็ใช้ได้ในกรณีที่ไม่ใช่แผ่นงาน - แผนภูมิ

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

ทดสอบในฟังก์ชันและคุณจะสามารถใช้ซ้ำได้และคุณจะอ่านโค้ดได้ดีขึ้น

อย่าใช้ "On Error Resume Next" เนื่องจากอาจขัดแย้งกับส่วนอื่น ๆ ของรหัสของคุณ

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

หลายปีที่ผ่านมา แต่ฉันต้องทำสิ่งนี้และไม่ชอบวิธีแก้ปัญหาใด ๆ ที่โพสต์ไว้ ... ดังนั้นฉันจึงสร้างขึ้นมาทั้งหมดนี้ต้องขอบคุณความมหัศจรรย์ของ (ท่าทางมือสายรุ้ง SpongeBob) "Evaluate ()"!

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

ส่งคืนค่า TRUE หากไม่มีแผ่นงาน FALSE หากมีแผ่นงานอยู่ คุณสามารถแทนที่ช่วงใดก็ได้ที่คุณต้องการสำหรับ "1: 1" แต่ฉันไม่แนะนำให้ใช้เซลล์เดียวเพราะหากมีข้อผิดพลาด (เช่น # N / A) มันจะส่งคืน True


3

wsExistsฟังก์ชันกะทัดรัด( โดยไม่ต้องพึ่งพาการจัดการข้อผิดพลาด!)

นี่คือฟังก์ชั่นสั้น ๆ และเรียบง่ายที่ไม่ต้องพึ่งพาการจัดการข้อผิดพลาดเพื่อตรวจสอบว่ามีแผ่นงานอยู่หรือไม่ ( และได้รับการประกาศอย่างเหมาะสมว่าใช้งานได้ในทุกสถานการณ์!)

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

ตัวอย่างการใช้งาน:

ตัวอย่างต่อไปนี้จะเพิ่มเวิร์กชีตใหม่ที่ชื่อmyNewSheetหากยังไม่มี:

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

ข้อมูลมากกว่านี้:


2

ทำไมไม่ใช้ลูปเล็ก ๆ เพื่อตรวจสอบว่ามีเวิร์กชีตที่ตั้งชื่ออยู่หรือไม่ สมมติว่าคุณกำลังมองหาแผ่นงานชื่อ "Sheet1" ในสมุดงานที่เปิดอยู่

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

หากคุณเป็นแฟนตัวยงWorksheetFunction.หรือทำงานจากประเทศที่ไม่ใช่ภาษาอังกฤษโดยใช้ Excel ที่ไม่ใช่ภาษาอังกฤษนี่เป็นทางออกที่ดีซึ่งใช้ได้ผล:

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

หรือในฟังก์ชันเช่นนี้:

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

เปลี่ยน "ข้อมูล" เป็นชื่อแผ่นงานที่คุณกำลังทดสอบ ...

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

ไม่ต้องสงสัยเลยว่าฟังก์ชันข้างต้นสามารถใช้งานได้ฉันเพิ่งลงเอยด้วยรหัสต่อไปนี้ซึ่งใช้งานได้ดี:

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

หมายเหตุ: Sheets_Nameเป็นที่ที่ฉันขอให้ผู้ใช้ป้อนชื่อดังนั้นสิ่งนี้อาจไม่เหมือนกันสำหรับคุณ


0

ฉันทำอย่างอื่น: ลบแผ่นงานเฉพาะเมื่อมีอยู่ - ไม่ได้รับข้อผิดพลาดหากไม่มี:

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

ฉันคิดวิธีง่ายๆในการทำ แต่ฉันไม่ได้สร้างย่อยใหม่สำหรับมัน แต่ฉันเพียงแค่ "ดำเนินการตรวจสอบ" ในส่วนย่อยที่ฉันกำลังดำเนินการอยู่ สมมติว่าชื่อแผ่นงานที่เรากำลังมองหาคือ "Sheet_Exist" และเราต้องการเปิดใช้งานหากพบ:

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

ฉันยังเพิ่มป๊อปอัปเมื่อไม่มีแผ่นงาน


0

ฉันรู้ว่ามันเป็นโพสต์เก่า แต่นี่เป็นอีกวิธีง่ายๆที่รวดเร็ว

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


-4

ฉันมีวิธีง่ายๆในการตรวจสอบว่ามีแผ่นงานอยู่หรือไม่จากนั้นดำเนินการตามคำสั่ง:

ในกรณีของฉันฉันต้องการลบแผ่นงานและสร้างแผ่นงานเดิมขึ้นมาใหม่โดยใช้ชื่อเดียวกัน แต่รหัสถูกขัดจังหวะหากโปรแกรมไม่สามารถลบแผ่นงานได้เนื่องจากถูกลบไปแล้ว

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

ปัญหาของคำตอบนี้คือเมื่อพิจารณาแล้วว่าแผ่นงานนั้นมีอยู่จริงแผ่นนั้นจะถูกลบออกไปจึงไม่มีอยู่อีกต่อไป หากสิ่งนี้ถูกเขียนเป็นฟังก์ชันอาจมีชื่อเหมือน SheetExistsAfterDeletion และจะส่งคืน FALSE เสมอ
ChrisB
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.