Как я могу создать / скопировать рабочий лист, присвоив ему имя на основе значения ячейки в определенном столбце, но переменной строки?

#vba #excel

#vba #excel

Вопрос:

По сути, я создаю лист отслеживания, в котором будет ячейка, при нажатии на которую будет создан новый лист Excel в той же книге. В целях тестирования я в настоящее время просто создаю новый лист, но в конечном итоге у меня будет лист, который он скопирует. В чем мне нужна помощь, так это в том, как мне заставить VB извлекать значение ячейки для использования в качестве имени нового / скопированного листа? Вот сценарий:

В каждой строке будет столбец Client (который является столбцом C), который я хочу использовать для имен книг, которые будут созданы. Я пытаюсь создать ячейку (скажем, столбец R в этой строке), которая при нажатии создает новый рабочий лист и вводит значение столбца C в этой строке в качестве имени рабочего листа.

Итак, скажем, в строке 5 есть «Тестовый клиент» в C5. При нажатии на R5 я хочу, чтобы он создал лист с именем «Тестовый клиент». Я видел решения, которые используют циклы для перехода по столбцу и создания листа для каждого, но это не сработало бы для моего сценария, поскольку мне нужно, чтобы они создавались «на лету», а не всегда для каждой строки.

Я знаю, как создавать листы в vb, но моя проблема заключается в получении имени. Есть ли способ заставить vba извлекать имя из столбца C для строки, в которой оно было активировано? Итак, если он был активирован для строки 5, он извлекает C5, если это была строка 10, он извлекает C10 и т.д.

Любые предложения будут с благодарностью приняты, в настоящее время я использую это для создания листов:

 Sub CreateSheet()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add(After:= _
         ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
End Sub
  

и это для вызова:

 Private Sub Worksheet_SelectionChange(ByVal Target As Range) 

If Target.Row > 5 And Target.Column = 18 And Target.Count = 1 Then Call CreateSheet

End Sub
  

Ответ №1:

Приведенный ниже код считывает значение в столбце C для соответствующей строки, а затем передает его как a String вашей функции:

 Private Sub Worksheet_Change(ByVal Target As Range)

If Target.Row > 5 And Target.Column = 18 And Target.Count = 1 Then
    Dim ShtName         As String

    ShtName = Cells(Target.Row, "C").Value
    Call CreateSheet(ShtName)
End If

End Sub
  

Это ваша функция, я добавил String , который передается, представляя имя рабочего листа:

 Public Sub CreateSheet(ws_Name As String)

Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add(After:= _
         ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))

ws.Name = ws_Name

End Sub
  

Комментарии:

1. Хороший ответ, но в случае, если OP захочет скопировать его в другую книгу ThisWorkbook , его, однако, можно заменить любой рабочей книгой, переданной функциональному вызову CreateSheet()

2. Я знаю, но операция, запрошенная для той же книги, поэтому я пытаюсь сделать ее максимально простой

3. Точка зрения принята. Пожалуйста, измените свою первую строку (читается Sting вместо String )

Ответ №2:

Обновление: как указал Шай Радо, мне не хватало обработчика ошибок.

Сначала вы должны проверить, существует ли рабочий лист. Этот шаблон упростит отладку и добавит функциональность в ваш код.

Модуль рабочего листа

 Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim ws As Worksheet
    Dim WorksheetName As String

    If Target.Row > 5 And Target.Column = 18 And Target.Count = 1 Then

        WorksheetName = Cells(Target.Row, "C").Value

        Set ws = getWorkSheet(WorksheetName)

        If Not ws Is Nothing Then Set ws = getNewWorkSheet(WorksheetName)           

    End If

End Sub
  

Стандартный модуль

 Function getWorkSheet(WorksheetName As String, Optional WorkbookName As String) As Worksheet
    If Len(WorkbookName) = 0 Then WorkbookName = ThisWorkbook.Name

    With Workbooks(WorkbookName)
        On Error Resume Next
        Set getWorkSheet = .Worksheets(WorksheetName)
        On Error GoTo 0
    End With

End Function

Function getNewWorkSheet(WorksheetName As String, Optional WorkbookName As String) As Worksheet
    Dim ws As Worksheet

    If Len(WorkbookName) = 0 Then WorkbookName = ThisWorkbook.Name

    With Workbooks(WorkbookName)
        Set ws = .Worksheets.Add(After:=.Worksheets(.Worksheets.Count))
        On Error Resume Next
        ws.Name = WorksheetName

        If Err.Number = 0 Then
            Set getNewWorkSheet = ws
        Else
            ws.Delete
        End If
        On Error GoTo 0

    End With
End Function
  

Комментарии:

1. вы понимаете, что вы можете добавить бесконечную обработку ошибок? что делать, если ячейка содержит ? символ или другой, например: # , % , и т.д.)

2. @ShaiRado Lol .. Я был бы польщен :-). Я понимаю, что иногда немного переусердствую со своими ответами. Больше всего я использую Stack для улучшения своей собственной методологии. Я многому научился за свои 126 дней здесь.