Pruebe o verifique si la hoja existe

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

Básicamente, recorro todas las hojas del libro de trabajo de origen y luego las coloco destsheeten el libro de trabajo de destino en la hoja con el mismo nombre que la que se está iterando actualmente en el libro de trabajo de origen.

¿Cómo puedo probar si existe esa hoja? Algo como:

If wkbkdestination.Worksheets(ThisWorkSheet.Name) Then 

fuente
2
posible duplicado de Excel VBA si existe la
hoja de trabajo

Respuestas:

173

A algunas personas no les gusta este enfoque debido a un uso "inapropiado" del manejo de errores, pero creo que se considera aceptable en VBA ... Un enfoque alternativo es recorrer todas las hojas hasta encontrar una coincidencia.

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
Tim Williams
fuente
5
Totalmente apropiado uso IMO. Es una trampa para algo que se postula como existente y que no lo tiene y que tiene una larga historia - cf perl estricto, STAE, etc. Upvoted
Wudang
13
Probablemente uno debería usar en ActiveWorkbooklugar de ThisWorkbook. Este último se refiere al libro de trabajo que contiene el código de macro, que puede ser diferente del libro de trabajo que uno desea probar. Supongo ActiveWorkbookque sería útil para la mayoría de los casos (aunque las situaciones artificiales siempre están disponibles).
sancho.s ReinstateMonicaCellio
3
sht Is Nothingserá Truesi no hay hoja con ese nombre, pero queremos volver Truesi no es una hoja con ese nombre, por lo tanto el no. Es un poco más fácil (pero no válido) si reorganiza un poco paraSheetExists = sht Is Not Nothing
Tim Williams
3
Es bueno tener en cuenta que si ejecuta este código en su libro de trabajo de macros personal, cambie de If wb Is Nothing Then Set wb = ThisWorkbookaIf wb Is Nothing Then Set wb = ActiveWorkbook
Henrik K
2
Este es un enfoque altamente eficiente (vea mis comentarios sobre los puntos de referencia en la respuesta de Rory a continuación), así que a quién le importa lo que piensen los detractores. Tenga en cuenta (a partir de ahora) que tiene cero votos negativos.
rory.ap
107

Si está específicamente interesado solo en hojas de trabajo, puede usar una simple llamada Evaluate:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Evaluate("ISREF('" & sName & "'!A1)")
End Function
Rory
fuente
14
@Rory Realicé algunas pruebas comparativas en esta respuesta frente a Tim Williams. Más de 500.000 bucles, el tuyo tomó 22 segundos y el de Tim <1.
rory.ap
17
@roryap: si necesita ejecutar esto 500.000 veces, debe repensar todo su enfoque. ;)
Rory
9
@roryap: sin embargo, el uso de varios métodos lentos comenzará a acumular segundos. Yo diría que esta es información extremadamente valiosa, ya que las "aplicaciones" de Excel comienzan a acumular segundos con bastante facilidad con varios métodos de rango, etc.
tedcurrent
4
@roryap: ¿esa información es valiosa para la conversación de qué manera? Simplemente estoy diciendo que la dispersión de métodos ineficientes alrededor de su código hará que la aplicación sea lenta en su conjunto. que pruebes esto 500k veces es increíble y te agradezco por hacerlo, 22 segundos no es genial. (Estoy de acuerdo contigo)
tedcurrent
6
Incluso si es más lento, parece una solución mucho más limpia que la respuesta aceptada. +1 de mi parte.
Sascha L.
49

No necesita el manejo de errores para lograr esto. Todo lo que tiene que hacer es iterar sobre todas las hojas de trabajo y verificar si existe el nombre especificado:

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
fbonetti
fuente
21

Como buscar miembros de una colección es un problema general, aquí hay una versión resumida de la respuesta de Tim:

La función contiene (objCollection como objeto, strName como cadena) como booleano
    Dim o como objeto
    En caso de error, reanudar siguiente
    establecer o = objCollection (strName)
    Contiene = (Err.Number = 0)
    Err.Clear
 Función final

Esta función se puede utilizar con cualquier colección como objeto ( Shapes, Range, Names, Workbooks, etc.).

Para comprobar la existencia de una hoja, utilice If Contains(Sheets, "SheetName") ...

Peter Albert
fuente
5
Esto no detecta tipos primitivos en Colecciones, ya que la Setpalabra clave generará un error . Descubrí que en lugar de usar Set, preguntar por el TypeNamemiembro de la colección funciona para todos los casos, es decirTypeName objCollection(strName)
citizenkong
2
@Peter: Lo mejor es agregar algo para borrar el error que se generará en el caso de que no exista antes de que finalice la función, ya sea un error, borrar o en caso de error, reanudar a continuación. De lo contrario, el manejo de errores en el procedimiento de llamada podría desencadenarse inadvertidamente en casos como el siguiente. Sub Test() On Error GoTo errhandler Debug.Print Contains(Workbooks, "SomeBookThatIsNotOpen") errhandler: If Err.Number <> 0 Then Stop End Sub
jeffreyweir
16

Corregido: Sin manejo de errores:

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
Shai Alon
fuente
14

En caso de que alguien quiera evitar VBA y probar si una hoja de trabajo existe puramente dentro de una fórmula de celda, es posible usar las funciones ISREFy INDIRECT:

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

Esto volverá TRUEsi el libro contiene una hoja llamada SheetNamey de lo FALSEcontrario.

VirtualMichael
fuente
12

Escribí este:

Function sheetExist(sSheet As String) As Boolean
On Error Resume Next
sheetExist = (ActiveWorkbook.Sheets(sSheet).Index > 0)
End Function
AOBR
fuente
1
¡Gran función! No solo es rápido, también es el más conciso.
ChrisB
Creo que esta es la respuesta que corresponde a la pregunta más
Juan Joya
Me gusta este. Tenga en cuenta que se basa en el hecho de que el valor predeterminado de sheetExist será False ya que es una función booleana. La declaración de asignación en realidad no asigna un valor Falso a sheetExist si la hoja no existe, solo genera errores y deja el valor predeterminado en su lugar. Si lo desea, puede confiar en el hecho de que cualquier valor distinto de cero asignado a una variable booleana dará un resultado Verdadero y sheetExist = ActiveWorkbook.Sheets(sSheet).Index
omitirá la
5

Mi solución se parece mucho a Tims pero también funciona en el caso de hojas que no son hojas de trabajo: gráficos

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

.

uildriks
fuente
3

Pon la prueba en una función y podrás reutilizarla y tendrás una mejor legibilidad del código.

NO utilice "En caso de error, reanudar a continuación", ya que puede entrar en conflicto con otra parte de su código.

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
Martin Carlsson
fuente
3

Muchos años tarde, pero solo necesitaba hacer esto y no me gustó ninguna de las soluciones publicadas ... ¡Así que inventé una, todo gracias a la magia de (gesto de las manos del arco iris de Bob Esponja) "Evaluar ()"!

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

Devuelve VERDADERO si la Hoja NO existe; FALSO si la hoja SÍ existe. Puede sustituir el rango que desee por "1: 1", pero desaconsejo usar una sola celda, porque si contiene un error (por ejemplo, # N / A), devolverá True.

X37V
fuente
3

wsExistsFunción compacta sin depender del manejo de errores!)

Aquí hay una función corta y simple que no se basa en el manejo de errores para determinar si existe una hoja de trabajo (¡ y si se declara correctamente que funciona en cualquier situación!)

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

Ejemplo de uso:

El siguiente ejemplo agrega una nueva hoja de trabajo denominada myNewSheet, si aún no existe:

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

Más información:

Ashleedawg
fuente
2

¿Por qué no utilizar un pequeño bucle para determinar si existe la hoja de trabajo nombrada? Diga si estaba buscando una hoja de trabajo llamada "Hoja1" en el libro de trabajo abierto actualmente.

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
ScottMcC
fuente
2

Si eres fanático WorksheetFunction.o trabajas desde un país que no es inglés con un Excel que no es inglés, esta es una buena solución, que funciona:

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

O en una función como esta:

Function WorksheetExists(sName As String) As Boolean
    WorksheetExists = Not WorksheetFunction.IsErr(Evaluate("'" & sName & "'!A1"))
End Function
Vityata
fuente
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
Philipp88
fuente
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
Shrikant
fuente
1

Cambie "Datos" a cualquier nombre de hoja que esté probando ...

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
gth826a
fuente
1

Sin ninguna duda de que la función anterior puede funcionar, acabo de terminar con el siguiente código que funciona bastante bien:

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

Nota: Sheets_Namees donde le pido al usuario que ingrese el nombre, por lo que puede que este no sea el mismo para usted.

MAx Segura
fuente
0

Hice otra cosa: eliminar una hoja solo si existe, no para obtener un error si no existe:

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
Shai Alon
fuente
0

Se me ocurrió una forma fácil de hacerlo, pero no creé un nuevo sub para ello. En su lugar, simplemente "ejecuté una verificación" dentro del submarino en el que estaba trabajando. Suponiendo que el nombre de la hoja que estamos buscando es "Sheet_Exist" y solo queremos activarlo si lo encontramos:

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

También agregué una ventana emergente para cuando la hoja no existe.

imjordy23
fuente
0

Sé que es una publicación antigua, pero aquí hay otra solución simple que es rápida.

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
Invitado
fuente
0

Corto y limpio:

Function IsSheet(n$) As Boolean
    IsSheet = Not IsError(Evaluate(n & "!a1"))
End Function
Héroe de Excel
fuente
-4

De hecho, tenía una forma sencilla de verificar si la hoja existe y luego ejecutar alguna instrucción:

En mi caso, quería eliminar la hoja y luego volver a crear la misma hoja con el mismo nombre, pero el código se interrumpió si el programa no pudo eliminar la hoja porque ya estaba eliminada.

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
chenaou
fuente
El problema con esta respuesta es que al determinar que la hoja realmente existió, se elimina y, por lo tanto, ya no existe. Si esto se escribiera como una función, podría tener un nombre como SheetExistsAfterDeletion y siempre devolvería FALSE.
ChrisB