уникальность активного листа VBA EXCEL

#vba #excel

#vba #excel

Вопрос:

У меня есть вопрос, у меня есть на одном базовом листе строки, для каждой строки я создаю новый лист, каждый новый лист имеет в ячейке A3 значение, которое я хотел бы использовать в качестве имени для моего нового активного листа. Здесь начинается проблема, так как в Excel имя листа может содержать только 31 знак, некоторые значения в формате A3 повторяются из-за вырезания только 31 знака. Например, у меня на одном листе в формате A3 есть технологические устройства для бизнеса и банков, а на следующем — технологические устройства для бизнеса и частных лиц. Итак, если я возьму 31 знак, оба листа будут иметь одно и то же имя, и я получу сообщение об ошибке, что имя листа уже занято. В моем цикле я просматриваю 1000 строк и проверяю, что повторяющаяся проблема будет появляться 700 раз, поэтому я подумал о том, чтобы вырезать слева 28 чисел вместо 31 и добавить к номеру имени, чтобы иметь уникальное имя для каждого листа. Часть кода (только часть изменения имени):

 Dim name As String
Dim i As Integer
Dim number_repeated As Integer
Dim name_signs As Integer

name = ActiveSheet.Range("a3")
name = Left(name, 31)
For i = 1 To Worksheets.Count
If name <> Worksheets(i).Name Then
ActiveSheet.Name = name
Else
name_signs = ActiveSheet.Range("a3")
name_signs = Left(name_signs, 28)
name_signs = name_signs   CStr(number_repeated)
ActiveSheet.Name = name_signs
number_repeated = 1
number_repeated = number_repeated   1
End If
Next i
  

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

1. Почему бы не иметь скрытый лист с реальным названием страницы в столбце A, а в столбце B с кодом, скажем, инициалами каждого слова? Затем вы просто называете лист как код вместо реального имени. Например. Monthly Report Of Something Really Important как реальное имя, а затем MROSRI как код (и имя листа). Затем в вашей ячейке A3 вы можете использовать a VLOOKUP , чтобы получить правильное значение.

2. есть ли какая-либо функция для удаления первой буквы, как вы это сделали в примере? или у вас есть идея, как его написать? Я довольно новичок в VBA, но выполнение этого вручную заняло бы слишком много времени для 1000 случаев.

3. Проверьте мой ответ и скажите, поможет ли он вам 😉

4. Взять первую букву довольно просто: Left(str,1).

5. это я знаю, но это займет только первую букву первого слова.

Ответ №1:

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

 Public Function SheetIsMissing(s$, Optional WB As Workbook) As Boolean
    If WB Is Nothing Then Set WB = ActiveWorkbook
    SheetIsMissing = True
    On Error GoTo theend
    Dim x
    x = WB.Sheets(s).Cells(1, 1)
    SheetIsMissing = False
theend:
End Function
  

Ответ №2:

опубликованный вами код содержит несколько ошибок:

1) nazwa не был объявлен. рекомендуется: писать Option Explicit в начале страницы макроса (это покажет сообщение, если переменная не была объявлена).

2) код:

 For i = 1 To Worksheets.Count
If name <> Worksheets(i).Name Then
ActiveSheet.Name = name
  

попытается изменить каждый лист на одно и то же имя.

3) number_repeated никогда не будет превышать значение 2, потому что перед каждым его увеличением вы возвращаете его к 1.

может быть, это подойдет:

 Sub Macro1()
For i = 1 To Worksheets.Count
    Worksheets(i).name = Left(Worksheets(i).Range("a3").Value, 28) amp; " " amp; i
Next i
End Sub
  

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

1. 1. название, которое я отредактировал для имени, было ошибкой, 3. Я бы переместил number_repeated перед циклом. 2. Я бы поставил name = ActiveSheet. Диапазон («a3») имя = Слева (имя, 31) после for, но перед if. Что вы об этом думаете?

2. я отредактировал свое сообщение и добавил решение, которое вы можете одобрить.

Ответ №3:

(Примечание: Чтобы ответить на комментарий и избежать уродливого кода в комментариях)

Следующая функция может получить инициалы заданной строки, присутствующей в ячейке, разделенной разделителем (который является необязательным и имеет символ пробела в качестве значения по умолчанию), а затем присоединяет к нему текущую строку ячейки.

 Option Explicit

Function getInitials(sht_name As Range, Optional delimiter As String = " ")

    Dim sht_desc As String: sht_desc = sht_name.Value
    Dim str_array As Variant
    Dim split_str As Variant
    getInitials = ""

    str_array = Split(sht_desc, delimiter)
    For Each split_str In str_array
      getInitials = getInitials amp; Left(split_str, 1)
    Next

    getInitials = getInitials amp; "_" amp; sht_name.Row

End Function
  

Пример использования:

В ячейке A3 записывается Monthly Report Of Something Really Important , а в B3 записывается =getInitials(A3) , что возвращает MROSRI_3

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

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

2. @K.L — Новое решение 😉

Ответ №4:

Я бы выбрал сокращения

итак, вот функция, которая возвращает сокращение строки на основе пробелов (» «) в качестве разделителя слов:

 Function GetInitials(strng As String) As String
    Dim words As Variant, word As Variant
    words = Split(strng, " ")
    For Each word In words
        GetInitials = GetInitials amp; Left(word, 1)
    Next word
End Function
  

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

 Option Explicit

Sub main()
    Dim sht As Worksheet
    Dim shtAcronym As String

    For Each sht In Worksheets
        shtAcronym = GetInitials(sht.Range("A3")) '<- get the acronym out of the current worksheet "A3" cell

        '...
    Next sht
End Sub