Форум программистов, компьютерный форум, киберфорум
Наши страницы
VBA
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
Але-Дашкова
381 / 4 / 3
Регистрация: 20.03.2013
Сообщений: 43
1

Анализ строк в VBA

11.06.2013, 22:51. Просмотров 1722. Ответов 20
Метки нет (Все метки)

Привет, ребята! Пожалуйста, помогите мне разобраться с анализом строк! Нужно написать программу для поиска чисел 72 и 42 в строке, и что-то у меня не получается... Всю голову сломала и решила обратиться к вам за помощью.
Вот программа, которую я написала:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Sub Поиск_чисел72и42в_строке()
    Dim КоличествоЧисел72и42 As Integer
    Dim Строка As String
    Dim I As Integer, J As Integer
    Dim Символ As String
    Dim ДругойСимвол As String
    Строка = InputBox("Пожалуйста, введите строку, в которой будут искаться числа 72 и 42")
    КоличествоЧисел72и42 = 0
    For I = 1 To Len(Строка)
        Символ = Mid(Строка, I, 1)
        If Символ = 7 Then
            For J = 1 To Len(Строка)
                ДругойСимвол = Mid(Строка, J, 1)
                If ДругойСимвол = 2 Then
                    КоличествоЧисел72и42 = КоличествоЧисел72и42 + 1
                End If
            Next J
        End If
        If Символ = 4 Then
            For J = 1 To Len(Строка)
                ДругойСимвол = Mid(Строка, J, 1)
                If ДругойСимвол = 2 Then
                    КоличествоЧисел72и42 = КоличествоЧисел72и42 + 1
                End If
            Next J
        End If
    Next I
    MsgBox "Количество чисел 72 и 42 в строке равно " & КоличествоЧисел72и42
End Sub
Когда я ввожу строку, не содержащую чисел 72 и 42, например "5555", то программа правдиво отвечает, что количество чисел 72 и 42 в строке равно нулю, однако, когда я ввожу строку "7242", то программа находит четыре числа, хотя на самом деле их только два.
Буду благодарна, если поможете разобраться.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.06.2013, 22:51
Ответы с готовыми решениями:

Вывод строк в VBA
Есть на Лист1 колонки "A" и "B" с наименованием. Есть на Лист2 колонки "A" и...

Вывод строк в VBA
Есть код макроса который позволяет ввести в окошко часть слова, и далее если в...

Перенос найденных строк в VBA
Подскажите как перенести строчку с одного листа на другой, которую я нахожу...

Удаление строк в Excel на VBA.
Прошу помощи у специалистов. Есть массив (2 столбца) на одном листе. Со...

Заполение строк числами vba
Помогите пожалуйста написать задачу в Vba, буду очень благодарен. 1)Начиная с...

20
Igor_Tr
4369 / 653 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
11.06.2013, 23:57 2
А почему не через inStr? Мне кажется, что такой вариант и тот был бы легче и проще.

Добавлено через 44 минуты
Попробуйте:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Sub myFS()
    Dim mstr$, mARR(), i&, j&, n&, counter&, str2$
    mARR = Array(72, 42)
    mstr = " 2343 as7242q42aa 42 lls d 7272sdf 72"
    For i = LBound(mARR) To UBound(mARR)
        counter = 0
            If InStr(1, mstr, mARR(i), vbTextCompare) <> 0 Then
                For j = 1 To Len(mstr)
                    n = InStr(j, mstr, mARR(i), vbTextCompare)
                        If Mid(mstr, n + 1, 1) = 2 Then counter = counter + 1: j = n + 1
                Next j
                str2 = Application.Trim(str2 & Space(1) & mARR(i) & ";;" & counter)
                    Else: str2 = str2 & Space(1) & mARR(i) & ";;" & "NoMATCH."
            End If
    Next 'i
    MsgBox "RESULTS: " & Chr(13) & Chr(13) & _
                "VALUE" & Space(3) & Split(Split(str2, Space(1))(0), ";;")(0) & _
                Space(3) & "FOUND" & Space(3) & Split(Split(str2, Space(1))(0), ";;")(1) & _
                Chr(13) & String(20, "-") & Chr(13) & _
                "VALUE" & Space(3) & Split(Split(str2, Space(1))(1), ";;")(0) & _
                Space(3) & "FOUND" & Space(3) & Split(Split(str2, Space(1))(1), ";;")(1)
End Sub
Можно mARR и циклы заменить фукцией. Но оно надо?

Добавлено через 15 минут
Хоть и работает, но здесь не совсем корректно. Нужно заменить выражение:
If Mid(mstr, n + 1, 1) = 2 Then counter = counter + 1: j = n + 1
выражением:
If n > 0 Then counter = counter + 1: j = n + 1 Else Exit For
Наверное, уже мозги дымят от своего...
1
Аксима
5843 / 1264 / 188
Регистрация: 12.12.2012
Сообщений: 988
12.06.2013, 00:04 3
Але-Дашкова, внутренние циклы в вашей программе не нужны, вместо этого вам нужно просто посмотреть символ, следующий за 7 или 4 (этот символ будет иметь индекс I+1).
Или, как заметил Igor_Tr, использовать функцию InStr.

А если вам нужно общее количество чисел 72 и 42 без классификации, то можно поступить совсем просто:
Visual Basic
1
2
3
Sub Search_72_and_42()
    MsgBox "Êîëè÷åñòâî Г·ГЁГ±ГҐГ« 72 ГЁ 42 Гў ñòðîêå: " & UBound(Split(Replace(InputBox("Ââåäèòå ñòðîêó"), "7", "4"), "42"))
End Sub
С уважением,
Aksima
2
ikki
призрак
2823 / 879 / 118
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
12.06.2013, 06:12 4
Лучший ответ Сообщение было отмечено как решение

Решение

вариант
Visual Basic
1
2
3
4
5
6
Sub r_7242()
  s = "642572334242"
  s72 = Replace(s, "72", ""):   n72 = (Len(s) - Len(s72)) / 2
  s42 = Replace(s72, "42", ""): n42 = (Len(s72) - Len(s42)) / 2
  MsgBox "чисел 72 в строке: " & n72 & vbCr & "чисел 42 в строке: " & n42
End Sub
3
Igor_Tr
4369 / 653 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
12.06.2013, 11:22 5
Сказка! Очень мне нравятся такие решения
0
ArtemoBis
10 / 5 / 0
Регистрация: 09.03.2013
Сообщений: 29
12.06.2013, 12:15 6
и мне
0
Але-Дашкова
381 / 4 / 3
Регистрация: 20.03.2013
Сообщений: 43
12.06.2013, 12:45  [ТС] 7
Спасибо большое!
Воспользуюсь решением Igor_Tr - это больше похоже на то, что я бы сама написала. Но и другие решения возьму на заметку .
Кстати, простите меня за наглость, не поможете еще с одной задачей анализа строк? Нужна написать функцию, которая проверяет, удовлетворяет ли строка следующим условиям:
1) В строке содержится слово "бак"
2) Строка не содержит "ка"
Эти условия должны выполняться одновременно, например, слово "табак" подходит обоим условиям, а слово "кабак" уже не подходит, так как содержит строку "ка".
Заранее спасибо!
0
Hugo121
6294 / 2393 / 406
Регистрация: 19.10.2012
Сообщений: 7,086
12.06.2013, 12:59 8
Лучший ответ Сообщение было отмечено как решение

Решение

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Sub t()
    Dim s$
    s = "табак"
    MsgBox delotabak(s)
    s = "кабак"
    MsgBox delotabak(s)
End Sub
 
Function delotabak(s As String) As Boolean
    If InStr(s, "бак") Then
        If InStr(s, "ка") = 0 Then
            delotabak = True
        End If
    End If
End Function
3
Igor_Tr
4369 / 653 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
12.06.2013, 13:55 9
To_Hugo. Тоже красиво! И остроумно с табаком!!!
To_Але-Дашкова. А еще можно опять через InStr. Но уже сами, все также, и ничего сложного (если 0 - нет!, если <> 0 - есть! И все!) А еще - как у Ikki. А еще...
0
Аксима
5843 / 1264 / 188
Регистрация: 12.12.2012
Сообщений: 988
12.06.2013, 14:30 10
Здравствуйте,
Для полноты предложу еще вариант решения через регулярные выражения:

Visual Basic
1
2
3
4
5
6
Function DeloTabak(s As String) As Boolean
    With CreateObject("VBScript.Regexp")
        .Pattern = "^(?:[^ГЎГЄ]|ГЄ+[^Г*ГЄ]|ГЎ[^Г*ГЎ]|ГЎ(?:ГЎ|Г*ГЎ)*[^ГЎГЄ])*(?:ГЎ(?:ГЎ|Г*ГЎ)*)Г*ГЄ(ГЄ|[^Г*ГЄ][^ГЄ]*)*$"
        DeloTabak = .Test(s)
    End With
End Function
Теперь у Але-Дашковой будет весь джентльменский набор методов анализа строк .

С уважением,
Aksima
2
Igor_Tr
4369 / 653 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
12.06.2013, 15:10 11
Если честно - я думал, что сейчас Ikki разбушуется и бабахнет Regular. Железные нервы у человека!!!
0
Але-Дашкова
381 / 4 / 3
Регистрация: 20.03.2013
Сообщений: 43
12.06.2013, 21:19  [ТС] 12
Hugo121, спасибо большое!


Aksima, не могли бы вы объяснить мне ваше регулярное выражение? А то я ничего в нем не понимаю .
0
ikki
призрак
2823 / 879 / 118
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
12.06.2013, 22:38 13
я бы предложил такой вариант с regexp:
Visual Basic
1
2
3
4
5
6
Function DeloTabak(s As String) As Boolean
    With CreateObject("VBScript.Regexp")
        .Pattern = "^(?!ка).*бак(?!ка).*$"
        DeloTabak = .Test(s)
    End With
End Function
но у меня есть сомнения:
строка "бака" удовлетворяет условию или нет?

пс. практической пользы от регулярок в данной задаче нет никакой - чисто спортивный интерес

Добавлено через 7 минут
ппс. ну или слово "бакалавр", если кого-то смущает "бака"
1
Аксима
5843 / 1264 / 188
Регистрация: 12.12.2012
Сообщений: 988
12.06.2013, 22:47 14
Цитата Сообщение от Але-Дашкова Посмотреть сообщение
не могли бы вы объяснить мне ваше регулярное выражение?
С удовольствием.

Итак, имеем регулярное выражение:
Код
"^(?:[^бк]|к+[^ак]|б[^аб]|б(?:б|аб)*[^бк])*(?:б(?:б|аб)*)ак(к|[^ак][^к]*)*$"
В начале регулярного выражения находится знак "^". Если этот знак находится вне квадратных скобок, то он означает начало строки.

В конце выражения находится знак "$". Он означает конец строки. Вместе эти два знака заставляют выражение анализировать всю строку целиком.

Круглые скобки "(" и ")" используются для группировки, причем результаты группировки сохраняются в специальном буфере. Если нам не нужно сохранять результаты в буфере, то мы вставляем после открывающей скобки последовательность "?:" и ускоряем таким образом работу интерпретатора регулярных выражений.

Вертикальная черта "|" выполняет роль связки "или", а звездочка "*" означает, что данный символ или группа повторяются в выражении любое количество раз.

Таким образом, часть "(?:[^бк]|к+[^ак]|б[^аб]|б(?:б|аб)*[^бк])*" выражения означает, что после начала строки могут следовать в любом порядке и количестве следующие символы или группы символов:
Код
"[^бк]"
"к+[^ак]"
"б[^аб]"
"б(?:б|аб)*[^бк]"
Рассмотрим их подробнее:
  1. "[^бк]"
    Внутри квадратных скобок символ "^" означает отрицание. Таким образом, "[^бк]" означает: любой символ, кроме "б" и "к". Очевидно, что если символ не является ни символом "б", ни символом "к", то он не может быть началом буквосочетаний "бак" или "ка".
  2. "к+[^ак]"
    Символ "+" означает "одно или более". Таким образом, в выражении нам может встретиться один или более символов "к" подряд - это нормально, главное, чтобы после символа "к" не было символа "а" (иначе образуется подстрока "ка", что противоречит условиям задачи), и чтобы в конце последовательности стоял символ более продуктивный, чем "к", например, символ "б".
  3. "б[^аб]"
    Данное выражение определяет символ "б", который не приносит результата, так как после него не стоит продолжающий фразу "бак" символ "а", и даже буквы "б" после него не следует.
  4. "б(?:б|аб)*[^бк]"
    Данное выражение определяет второй вариант символа "б", который не приносит результата. Хотя после него стоят символы "а" или "б", в конце видно, что эта ветка также обрывается.
Таким образом, все рассмотренные выше выражения определяют нулевые ветки - ветки, которые могут входить в выражение, не противоречащее условиям задачи, но при этом не приносят результата.
Следующая часть выражения "(?:б(?:б|аб)*)ак" определяет искомую подстроку "бак".
  1. "б" - буква "б";
  2. "ак" может следовать не сразу за первой буквой "б": после первой буквы "б" могут стоять и другие буквы "б" и даже подстроки вида "аб", но, как бы то ни было, перед "ак" будет все-таки стоять буква "б".
Наконец, после искомой подстроки "бак" может стоять любая последовательность символов, не образующая подстроку "ка", в том числе в сочетании с буквой "к" подстроки "бак". Эта последовательность определяется выражением (к|[^ак][^к]*)*, которое означает следующее:
  1. после символа "к" подстроки "бак" может стоять любое количество символов "к";
  2. после символа "к" может стоять символ, прерывающий последовательность символов "к", т.е. не символ "к", но также и не символ "а", так как он образует вместе с символом "к" подстроку "ка", которая противоречит условиям задачи;
  3. второй вариант может продолжаться любыми символами, кроме "к", если же встретился символ "к", то оба варианта (1-ый и 2-ой) рассматриваются с самого начала.

С уважением,
Aksima
Добавлено через 4 минуты
Цитата Сообщение от ikki Посмотреть сообщение
строка "бака" удовлетворяет условию или нет?
Кстати, такой вариант, как следует из изложенного мной выше, тоже учитывается (и бракуется).
За исключением этого варианта, регулярное выражение, предложенное ikki - просто супер!
2
ikki
призрак
2823 / 879 / 118
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
12.06.2013, 22:52 15
Цитата Сообщение от Aksima Посмотреть сообщение
За исключением этого, вариант ikki
вариант "без исключений":
Visual Basic
1
.Pattern = "^(?!ка).*бак([^а]|$)(?!ка).*$"
1
Але-Дашкова
381 / 4 / 3
Регистрация: 20.03.2013
Сообщений: 43
12.06.2013, 23:32  [ТС] 16
Aksima, огромное спасибо за столь подробное объяснение!
И всем, кто помогал мне сегодня, тоже очень признательна!
0
Igor_Tr
4369 / 653 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
12.06.2013, 23:56 17
Нет!!! Ну не могу... Обидели.... В смысле - словари обошли незаслуженно!!!
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sub withD()
   Dim dict As Object, s$, i&, mKey
      Set dict = CreateObject("scripting.dictionary")
      dict.comparemode = 1
      dict.Add Key:="к", Item:=0&: dict.Add Key:="б", Item:=0&
      s = "Табак"
         For i = 1 To Len(s)
            If dict.exists(Mid(s, i, 1)) Then
               If Mid(s, i + 1, 1) = "а" Then
                  dict.Item(Mid(s, i, 1)) = CLng(dict.Item(Mid(s, i, 1))) + 1
               End If
            End If
         Next 'i
      For Each mKey In dict.Keys
         MsgBox mKey & "а" & " - " & dict.Item(mKey)
      Next
End Sub
А вот теперь я наверное получу... И от Ikki, и от Aksima, и от Hugo...
0
Аксима
5843 / 1264 / 188
Регистрация: 12.12.2012
Сообщений: 988
13.06.2013, 10:03 18
Igor_Tr, это уж чересчур, в самом деле .

Цитата Сообщение от ikki Посмотреть сообщение
вариант "без исключений":
Visual Basic
1
.Pattern = "^(?!ка).*бак([^а]|$)(?!ка).*$
Работает, но все-таки не до конца:
Visual Basic
1
2
3
4
5
6
7
8
9
10
Function DeloTabak(s As String) As Boolean
    With CreateObject("VBScript.Regexp")
        .Pattern = "^(?!ГЄГ*).*ГЎГ*ГЄ([^Г*]|$)(?!ГЄГ*).*$"
        DeloTabak = .Test(s)
    End With
End Function
 
Sub ProverkaRegularki()
   Debug.Print DeloTabak("акабакокка") 'True, а должно быть False.
End Sub
Тем не менее, ikki молодец - указал на подход, который после определнной доработки может оказаться очень эффективным при решении подобных задач.
2
Igor_Tr
4369 / 653 / 36
Регистрация: 17.01.2010
Сообщений: 2,134
13.06.2013, 10:56 19
To_Aksima. Ну да... Вот смотрю квадратными глазами, и ничего не понимаю.... Очень нравятся Reg, но зачем??? они??? здесь??? Кто бы мне, глупому, обяснил... Чуть подправить корректный и простенький код Ikki - и абсолютно хватит (если нет прямого указания для Reg).
0
ikki
призрак
2823 / 879 / 118
Регистрация: 11.05.2012
Сообщений: 1,702
Записей в блоге: 2
13.06.2013, 11:33 20
Цитата Сообщение от Aksima Посмотреть сообщение
Работает, но все-таки не до конца
это значит "нифига не работает"
"чуть-чуть беременной" быть нельзя.

отмазки "ночью соображалось плохо" не принимаются - очевидно, что так регулярки не работают.
кончно, самый правильный, понятный и быстрый вариант (если уж использовать regexp) - такой:
Visual Basic
1
2
3
4
5
6
7
8
Function DeloTabak(s As String) As Boolean
    With CreateObject("VBScript.Regexp")
        .Pattern = "бак"
        t = .Test(s)
        .Pattern = "ка"
        t = t And Not .Test(s)
    End With
End Function
но он подозрительно похож на вариант с InStr

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

пс. надеюсь, Але-Дашкова, с моим "решением" ещё не добралась до препода

ппс. Aksima, спасибо за тщательное тестирование.
0
13.06.2013, 11:33
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.06.2013, 11:33

VBA excel перебор строк
Добрый день! Имеется список из 3х столбцов в excel: Иванов 16 ...

Vba нумерация строк по условию
Здравствуйте всем. Ни как не могу найти должный пример к своей проблеме, что бы...

Группирование строк в EXCEL (макрос) / VBA
Ребят, добрый день!! Помогите, пожалуйста,написать макрос, чтобы в таблице...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru