При циклическом просмотре всех открытых рабочих книг код выходит из цикла после одной рабочей книги. - PullRequest
1 голос
/ 20 мая 2019

Я хочу просмотреть все открытые книги Excel, чтобы определить, над какими из них выполнять операции.Проблема в том, что код выходит из цикла for после активной рабочей книги и возвращает «Ничего» в результате, независимо от того, сколько рабочих книг у меня открыто.

Мне нужно запускать эту подпрограмму еженедельно, чтобы перевести рабочие часы иззагрузил книгу Excel в альтернативную книгу.Имя файла меняется каждую неделю, но всегда начинается с «Расписания»

Я использовал эту процедуру каждую неделю с января по апрель без каких-либо проблем.Я попытался использовать это сегодня, и эта проблема возникла.Я использовал эту процедуру на нескольких разных компьютерах с разными операционными системами (Windows 7, Windows 10).

Я сохранил, закрыл и снова открыл книгу, которую хочу активировать, но безрезультатно.Я не хочу менять код каждую неделю, чтобы получить доступ к определенной книге, но использую первые 4 буквы в имени файла, чтобы определить файл, над которым нужно выполнить операции.

Sub cmdImportHours_Click()

    Dim ThisWB As Workbook
    Dim ImportWB As Workbook
    Dim WB As Workbook
    Dim msg1 As String
    Dim msg As Variant

' more variables

    msg1 = "Required file not found. Open the import file and try again."

    Set ThisWB = ThisWorkbook
    ThisWB.Worksheets("Hours").Activate

'The following loop exits after one iteration (the active workbook),
'regardless of how many workbooks are open

    For Each WB In Workbooks
        If Left(WB.Name, 4) = "Time" Then
            WB.Activate
            Exit For
        End If
    Next WB

    If WB Is Nothing Then
        msg = MsgBox(msg1, vbOKOnly)
        Exit Sub
    End If

'more code

End Sub

Я ожидаю, что цикл будет просматривать имя каждой открытой книги Excel, но выходит из цикла For Loop после просмотра только активной книги.

Ответы [ 2 ]

1 голос
/ 21 мая 2019

Ваше For Each по всем рабочим книгам напрямую возвращает пригодную для использования переменную, которая ссылается на требуемую рабочую книгу, поэтому вы даже можете использовать переменную "ImportWB" здесь.Выход из цикла на Exit For, если вы нашли нужный элемент, является хорошей практикой.

Я ввел две переменные для рабочих таблиц, чтобы использовать их для операций копирования.

Sub cmdImportHours_Click()
    Dim ImportWB As Workbook
    Dim SourceSheet As Worksheet, DestSheet As Worksheet
    Dim msg1 As String
    Dim msg As Variant

    For Each ImportWB In Workbooks
        If Left(ImportWB.Name, 4) = "Time" Then Exit For
    Next ImportWB

    If ImportWB Is Nothing Then
        msg1 = "Required file not found. Open the import file and try again."
        msg = MsgBox(msg1, vbCritical + vbOKOnly, "Workbook not open")
        Exit Sub
    End If

    Set DestSheet = ThisWorkbook.Worksheets("Hours")
    'DestSheet.Activate is typically not necessary
    Set SourceSheet = ImportWB.Sheets(1)

    DestSheet.Range("A2:B10").Value = SourceSheet.Range("A2:B10").Value
    ' more code
End Sub

Поскольку ThisWorkbook всегда одно и то же (книга с вашим VBA-кодом), необязательно указывать для него дополнительную переменную, и я ее опустил.


Если вы не получили свою уже открытую книгу по указанному выше коду, то она либо открывается в защищенном представлении ...

For i = 1 To Application.ProtectedViewWindows.Count
    Debug.Print "Protected Workbook: " & _
        Application.ProtectedViewWindows(i).Workbook.Name
Next i

... или в другом экземпляре Excel.В этом случае вы можете ссылаться на него, например,

Set ImportWB = GetObject("Path\Filename.xlsx")

См. здесь , чтобы получить дополнительные примеры по этому вопросу.

1 голос
/ 20 мая 2019

Это потому, что Exit For, просто прокомментируйте эту строку. И не используйте WB за пределами for each используйте вместо этого другую переменную, в этой кодовой переменной count используется для подсчета соответствующих рабочих книг

Dim count As String
count = 0
For Each WB In Workbooks
    If Left(WB.Name, 4) = "Time" Then
        count = count + 1
        WB.Activate
        'Exit For
    End If
Next WB

If count < 1 Then
    msg = MsgBox(msg1, vbOKOnly)
    Exit Sub
End If
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...