2009-10-19 10 views
7

sé cómo recorrer todas las hojas de un libro, y la forma de salir una vez que llegan a un 'indicador de final de' hoja de trabajo:¿Cómo puedo recorrer un subconjunto de hojas de trabajo?

For Each ThisWorkSheet In Worksheets 
    If ThisWorkSheet.Name = "FlagEnd" Then Exit For 
    MsgBox "This worksheet name is: " & ThisWorkSheet.Name 
Next 

Sin embargo no puedo conseguir el bucle para comenzar en un 'arranque marcar la hoja de trabajo (o incluso mejor en la hoja de cálculo justo después de la hoja de trabajo de inicio de bandera. Por ejemplo, las hojas de trabajo de inicio/fin marcadas están en el medio de otras hojas de trabajo, por lo que no se puede iniciar o finalizar el recorrido.

Podría haber cientos de hojas de trabajo antes de esa hoja 'FlagStart', así que realmente necesito comenzar en la hoja correcta.

intentado:

Set ThisWorkSheet = Sheets("FlagNew") 

y

For Each Sheets("FlagNew") In Worksheets 

ideas?

Solución: Mathias estaba muy cerca, pero Dendarii que era pequeño paso más estrecha con la costumbre que termina índice. De hecho, descubrí mi solución final por mi cuenta, pero quería dar crédito. Aquí fue mi solución final:

Private Sub CommandButtonLoopThruFlaggedSheets_Click() 
    ' determine current bounds 
    Dim StartIndex, EndIndex, LoopIndex As Integer 
    StartIndex = Sheets("FlagNew").Index + 1 
    EndIndex = Sheets("FlagEnd").Index - 1 

    For LoopIndex = StartIndex To EndIndex 
     MsgBox "this worksheet is: " & Sheets(LoopIndex).Name 
     ' code here 
    Next LoopIndex 
End Sub 
+3

Kirk, que puede no ser consciente de ello, pero si se declara 3 variables en la misma línea con un tipo al final, sólo la última variable que realmente ocurre ese tipo, los demás terminan como variantes. Si va a tener todas sus declaraciones en una línea, debe especificar "Dim StartIndex como Integer, EndIndex como Integer, LoopIndex como Integer". – dendarii

+0

¡Doh, me quemé con atajos otra vez! Gracias, no estaba enterado de eso, lo cambiaré. –

Respuesta

2

Si este no es un libro de trabajo particularmente modificable (es decir, hojas de cálculo no se agregan y eliminan todo el tiempo), puede guardar los nombres de las hojas de trabajo en un rango en una hoja oculta y recorrerlos por su nombre.

Sin embargo, parece que se almacenan consecutivamente en el libro así, sobre la base de la solución de Mathias, se puede utilizar una función para devolver los índices de las hojas de trabajo de inicio y fin y a continuación, recorrer:

Public Function GetStartIndex() As Integer 
    On Error Resume Next 
    GetStartIndex = ThisWorkbook.Worksheets("MyStartingWorksheet").Index + 1 
End Function 

Public Function GetEndIndex() As Integer 
    On Error Resume Next 
    GetEndIndex = ThisWorkbook.Worksheets("MyEndingWorksheet").Index - 1 
End Function 

Sub LoopThrough() 

    Dim wks As Worksheet 
    Dim i As Integer 
    Dim iStart As Integer 
    Dim iEnd As Integer 

    iStart = GetStartIndex() 
    iEnd = GetEndIndex() 

    If iStart > 0 And iEnd > 0 And iEnd > iStart Then 
     For i = iStart To iEnd 
      Set wks = ThisWorkbook.Worksheets(i) 
      MsgBox wks.Name 
     Next i 
    End If 

End Sub 
+0

Mathias estuvo muy cerca, pero este fue ese pequeño paso más cerca con el índice final personalizado. De hecho, descubrí mi solución final por mi cuenta, pero quería dar crédito aquí. Private Sub CommandButtonLoopThruFlaggedSheets_Click() 'determinar los límites actuales Dim StartIndex, EndIndex, LoopIndex como número entero StartIndex = hojas de índice ("FlagNew") + 1 EndIndex = Sheets ("FlagEnd") Índice -.. 1 Para LoopIndex = StartIndex Para endIndex MsgBox "esta hoja de trabajo es:" & Sheets (LoopIndex) .Nombre 'código aquí Siguiente LoopIndex End Sub –

+0

(solución editado en la pregunta original anterior con el formato de código) –

+0

veo que haya configurado una buena función. Sin embargo, me gustaría sugerir algunas cosas. Le sugiero que tome el nombre de la hoja para la que desea encontrar el índice, como argumento en la función. Al no tomar argumentos, ha hecho que la función sea estática; también podría haber escrito esas dos líneas en su sub principal. Luego, use la colección de hojas para obtener el índice, ya que es posible que el código no funcione como espera, cuando el libro tiene hojas de gráficos. –

1

¿Qué tal?

For Each ThisWorkSheet In Worksheets 
    If ThisWorkSheet.Name = "FlagStart" Then output = true 
    If ThisWorkSheet.Name = "FlagEnd" Then Exit For 
    If output = true Then MsgBox "This worksheet name is: " & ThisWorkSheet.Name 
Next 

Este código puede no ser del todo correcto. Lo escribo en el editor de SO no en VBA, pero entiendes la idea.

+1

Debería haber mencionado que pensé en eso, pero no es lo suficientemente eficiente. Podría haber cientos de hojas de cálculo delante de la hoja de trabajo de FlagStart. Prefiero comenzar directamente en la hoja de trabajo correcta. ¡Gracias! –

+0

@Kirk Hings: ¡la optimización prematura te morderá! Sugeriría obtener primero una solución funcional y luego buscar la forma de optimizarla. También me preocuparía tener cientos de hojas. ¿Excel es la mejor herramienta? –

+0

buenos puntos, de hecho estoy optimizando la solución que ya están usando. actualmente copian y pegan un montón de estas cosas y estamos tratando de automatizarlo para ellos. Supongo que exageré a cientos, pero puede haber docenas de hojas, y desafortunadamente varían en número y nombres de hoja. Estoy probando estas soluciones ahora mismo. Ayer utilicé el índice después de publicar este problema. –

2

Creo que si utiliza "foreach" no tendrá ningún control sobre la hoja de partida. De hecho, ni siquiera estoy seguro de que tengas garantizado el orden en que se llevará a cabo la iteración.
Creo que lo que debe hacer es en primer lugar, obtener el índice de la hoja le interesa (obtener la hoja por su nombre, y obtener su índice), y luego iterar utilizando un bucle, a través de los índices de las hojas a partir de el índice de la hoja bandera.
[Edit: hackeado a través de un ejemplo rápido]

Sub Iterate() 

Dim book As Workbook 
Dim flagIndex As Integer 
Dim flagSheet As Worksheet 

Set book = ActiveWorkbook 
Set flagSheet = book.Worksheets("Sheet3") 
flagIndex = flagSheet.Index 

Dim sheetIndex As Integer 
Dim currentSheet As Worksheet 

For sheetIndex = flagIndex To book.Worksheets.Count 
    Set currentSheet = book.Worksheets(sheetIndex) 
Next 

End Sub 
+0

Estás en lo correcto. Las hojas de trabajo son una colección de hojas. Usted no sabe dónde está. –

0

¿Las hojas que iterar sobre tener un formato de nombre común?

Ex)

Sheets(0).name > "Reports" 
Sheets(1).name > "Start Here" 
Sheets(2).name > "emp.0001" 
Sheets(3).name > "emp.0002" 
Sheets(4).name > "emp.0003" 
Sheets(5).name > "emp.0004" 
Sheets(6).name > "End Here" 

Si es así, en su para cada bucle, acaba de hacer una Left(ThisWorkSheet.name, 4) = "emp" para verificar si se trata de una hoja que desea hacer referencia.

-1
Public Sub ITERATE_WORKSHEETS() 
    On Error Resume Next  
    Dim x As Long 
     For x = 0 To 100 
       MsgBox Worksheets(x).Name 
     Next x 
    On Error GoTo 0 
    MsgBox "all done" 
End Sub 
+1

No publique solo el código, proporcione una explicación también. – Chad

0

En Excel VBA 2013 si tiene las hojas de trabajo que desea actualizar entre las pestañas "Blankfirst" y "Blanklast" esto funciona.

Utilice el siguiente código para probar que devuelve los nombres de las pestañas y luego reemplace su código de manipulación en lugar de la parte MsgBox wks.Name.

Sub Macro2() 

    On Error Resume Next 
    GetStartIndex = ThisWorkbook.Worksheets("Blankfirst").Index + 1 

    On Error Resume Next 
    GetEndIndex = ThisWorkbook.Worksheets("Blanklast").Index - 1 

    Dim wks As Worksheet 
    Dim i As Integer 
    Dim iStart As Integer 
    Dim iEnd As Integer 

    iStart = GetStartIndex 
    iEnd = GetEndIndex 


    If iStart > 0 And iEnd > 0 And iEnd > iStart Then 
     For i = iStart To iEnd 
      Set wks = ThisWorkbook.Worksheets(i) 
      MsgBox wks.Name 
     Next i 
    End If 

End Sub 
Cuestiones relacionadas