#vba #excel
#vba #excel
Вопрос:
Я хочу просмотреть свои рабочие листы Excel и найти лист с определенным именем и удалить этот лист, если он найден. После этого я хочу создать лист после всех существующих листов с таким именем. Мой код выглядит следующим образом:
For Each ws In Worksheets
If ws.Name = "asdf" Then
Application.DisplayAlerts = False
Sheets("asdf").Delete
Application.DisplayAlerts = True
End
End If
Next
Sheets.Add(After:=Sheets(Sheets.count)).Name = "asdf"
Однако это не выполняет оба этих действия за один запуск кода. Если лист уже существует, он просто удалит лист, а не создаст новый, как я хочу. Мне нужно запустить его снова, чтобы создать новый.
Как мне исправить мой код, чтобы удалить старый лист, если он существует, и создать новый?
Ответ №1:
Удалите End
инструкцию, ваш код завершается после нахождения и удаления рабочего листа asdf
.
For Each ws In Worksheets
If ws.Name = "asdf" Then
Application.DisplayAlerts = False
Sheets("asdf").Delete
Application.DisplayAlerts = True
End If
Next
Sheets.Add(After:=Sheets(Sheets.count)).Name = "asdf"
Ответ №2:
Вместо перебора Worksheets
вы можете проверить существование элемента в коллекции, попытавшись получить его:
Function GetWorksheet(shtName As String) As Worksheet
On Error Resume Next
Set GetWorksheet = Worksheets(shtName)
End Function
If Not GetWorksheet("asdf") Is Nothing Then
Application.DisplayAlerts = False
Worksheets("asdf").Delete
Application.DisplayAlerts = True
End If
Worksheets.Add(After:=sheets(sheets.Count)).name = "asdf"
Однако самым простым методом было бы попытаться удалить лист, заключенный в On Error Resume Next
— On Error GoTo 0
«блок»:
Application.DisplayAlerts = False
On Error Resume Next
Worksheets("asdf").Delete
On Error GoTo 0
Application.DisplayAlerts = True
Worksheets.Add(After:=sheets(sheets.Count)).name = "asdf"
Ответ №3:
Я не согласен с тем, что «самый простой» подход заключается в преднамеренном создании (и подавлении) ошибки. Лично я бы выбрал метод loop-to-locate, пытаясь удалить только в том случае, если объект существует.
Если вы все равно собираетесь заново создавать рабочий лист, это выполнит свою работу почти в каждом случае:
Sheets("asdf").Cells.Delete 'deletes all cells in the specified worksheet
Безопасное удаление рабочего листа
Если однострочный вариант (выше) у вас не работает (возможно, из-за некоторых стойких фоновых цветов / изображений), то вот вспомогательный модуль, который вы можете вызвать для удаления любого указанного рабочего листа:
Sub deleteSheet(wsName As String)
Dim ws As Worksheet
For Each ws In ThisWorkbook.Sheets 'loop to find sheet (if it exists)
Application.DisplayAlerts = False 'hide confirmation from user
If ws.Name = wsName Then ws.Delete 'found it! - delete it
Application.DisplayAlerts = True 'show future confirmations
Next ws
End Sub
Назовите его просто как:
deleteSheet "asdf"
…где asdf
— название рабочего листа (вкладки), который нужно удалить.
Удалить и заменить рабочий лист
В качестве альтернативы, вызов подраздела ниже удалит и заменит рабочий лист, присвоив ему то же имя и поместив его в ту же позицию табуляции, что и исходный:
Sub resetSheet(wsName As String)
Dim ws As Worksheet, ws2 As Worksheet
For Each ws In ThisWorkbook.Sheets 'loop to find sheet (if it exists)
If ws.Name = wsName Then 'found it!
Set ws2 = ThisWorkbook.Sheets.Add(ws) 'add new sheet located before old one
Application.DisplayAlerts = False 'hide confirmation from user
ws.Delete 'delete sheet (new one takes its place)
Application.DisplayAlerts = True 'show future confirmations
ws2.Name = wsName 'rename new sheet to old name
Exit Sub 'finished! (no need to continue looping)
End If
Next ws
End Sub
О ThisWorkbook
:
Я использовал ThisWorkbook
в обоих подразделах, что важно при запуске VBA, который изменяет другие книги, или при одновременном открытии нескольких книг.
Использование ThisWorkbook
гарантирует, что ваш код всегда ссылается на рабочую книгу, где находится код, который его вызвал.
Без этого, например, если у вас открыты два похожих файла, и вы просматриваете один, ожидая запуска VBA в другой книге, если в книге, которая находится «сверху», есть рабочий лист с именем того, который VBA пытается удалить, он удалит рабочий лист в текущей (активной) книге вместо предполагаемого.
(… и вы не можете Ctrl Z отменить VBA!)