Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Word VBA Замена

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки
Страницы: 1 2

Открыть новую тему     Написать ответ в эту тему

Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Доброго времени суток!
 
Не могу пока решить такую проблемку. Нужно в тексте заменить одно на другое, и встречается такой момент:
 
 
Например, текст:
 
ааабббввв  аабб
 
Нужно заменить аабб на ввгг
 
Но заменяет как второе слово, так и первое ааабббввв  -> аввггбввв  
 
Как описать так, чтобы первое слово не трогал, учитывая то, что вместо конкретного текста у меня переменная:
 
           Selection.Find.ClearFormatting
           Selection.Find.Replacement.ClearFormatting
      With Selection.Find
          .Text = s_split(0)
          .Replacement.Text = sr
          .Forward = True
          .Wrap = wdFindContinue
          .Format = False
          .MatchCase = False
          .MatchWholeWord = True
          .MatchAllWordForms = False
          .MatchSoundsLike = False
          .MatchWildcards = False
      End With
       
           Selection.Find.Execute Replace:=wdReplaceAll
 
 
Добавлено:
Ой, конкретный пример оказался не точным.
Почему-то именно вот так оно как раз и работает.
 
Тогда вот конкретно что нужно, и что конкретно не работает:
 
-------------------------------------------
Текст:
 
БС10   БС7-6  БС5
 
-------------------------------------------
Программа:
 
s_split(0) = "БС7"
sr = "АС---10+++1"
 
           Selection.Find.ClearFormatting
           Selection.Find.Replacement.ClearFormatting
      With Selection.Find
          .Text = s_split(0)
          .Replacement.Text = sr
          .Forward = True
          .Wrap = wdFindContinue
          .Format = False
          .MatchCase = False
          .MatchWholeWord = True
          .MatchAllWordForms = False
          .MatchSoundsLike = False
          .MatchWildcards = False
      End With
       
           Selection.Find.Execute Replace:=wdReplaceAll
-------------------------------------------------------------
 
По идее вот это "БС7-6"  заменять не надо.  
Почему меняет?
Как указать, что знак "-" как бы видел, что в тексте после "БС7" есть ещё и "-6",
и игнорировал всё это "слово".
 

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 12:19 11-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну что поделать, БС7-6 - это два слова, как ни крути.
 
Может сделать финт ушами ?

Код:
 
s_split(0) = "БС7 " ' добавляем пробелы в строки поиска и замены
sr = "АС---10+++1 "  
 
           Selection.Text = Selection.Text + " " 'Чтобы БС7 на конце выделения не терялся
           Selection.Find.ClearFormatting  
           Selection.Find.Replacement.ClearFormatting  
      With Selection.Find  
          .Text = s_split(0)  
          .Replacement.Text = sr  
          .Forward = True  
          .Wrap = wdFindContinue  
          .Format = False  
          .MatchCase = False  
          .MatchWholeWord = True  
          .MatchAllWordForms = False  
          .MatchSoundsLike = False  
          .MatchWildcards = False  
      End With  
       
           Selection.Find.Execute Replace:=wdReplaceAll  
           Selection.Text = RTrim(Selection.Text) 'забрать обратно пробел  
 

 
Если есть строки вида йцу-БС7, которые не надо заменять, то финт придётся дополнить ведущим пробелом.
 

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 13:53 11-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Да, этот финт помогает. Спасибо )))
 
Только у меня в этом месте
Selection.Text = Selection.Text + " "
ставится дублирующий справа от курсора символ, где этот курсор мигает.
В принципе, благо, что в конце БС7 нет.
 
Но, тогда проявился ещё такой момент:
 
БС7 БС7
тра та та
 
Первую БС7 заменяет, а вторую нет, потому что там конец строки.
 
Также не срабатывает, если в тексте так:
 
Пласт БС8 такой-то, такой же пласт БС7, а вот пласт БС9 другой.
Потому что запятая.

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 15:04 11-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну, наверное, можно было бы и код какой написать похитрее, но сначала вам нужно определиться, что считать концом слова, а что нет.
ааабббввв  аабб - нормально работает, потому что ааабббввв - одно слово
А "БС7-6" с точки зрения VBA, два слова, разделённых тире.
И все ваши алгоритмы будут упираться в необходимость решить, что считается словом, а что нет.
Например, вы готовы согласиться, что слово - это "непрерывная последовательность цифр, букв и тире" ? Или могут быть ещё какие-то знаки ?

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 05:31 12-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну, в принципе, да.
В моём случае, если бейсику можно объяснить, что у меня слова - это последовательности букв, цифр и тире, то может быть и получилось бы.
А как ему это сообщить?

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 06:38 12-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну, например, написать свою функцию замены.
Что-нибудь простенькое, заменяющее только слова целиком по своему алфавиту.
Пройтись по строке посимвольно, выделенные слова проверять только на полное соответствие.

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:09 12-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Да, вот, написал свою процедурку замены. Вроде то, что нужно.
 
  For i = 1 To ActiveDocument.Sentences.Count
       yes_instr = True: l = 1
 
           Do While yes_instr
 
                j = InStr(l, ActiveDocument.Sentences(i), s_split(0))
 
                   If j <> 0 Then
                       yes_zamena = False
                          If j + Len(s_split(0)) + 1 = Len(ActiveDocument.Sentences(i)) Then
                              yes_zamena = True
                          Else
                             If (ActiveDocument.Sentences(i).Characters(j + Len(s_split(0))) = ",") Or _
                                (ActiveDocument.Sentences(i).Characters(j + Len(s_split(0))) = " ") Then
                                 yes_zamena = True
                             End If
                          End If
                   
                          If yes_zamena Then
                             ActiveDocument.Sentences(i) = Mid(ActiveDocument.Sentences(i),1,j-1)+ _
                             sr + Mid(ActiveDocument.Sentences(i), j + Len(s_split(0)))
                             l = j + Len(sr)
                          Else
                             l = j + Len(s_split(0))
                          End If
 
                          If l + 2 > Len(ActiveDocument.Sentences(i)) Then
                             yes_instr = False
                          End If
                   Else
                         yes_instr = False
                   End If
           Loop
  Next
 
Пока вопросов нет - всем спасибо!
 
Добавлено:
А, вот и вопрос назрел...
 
Если меняю строку, то сбрасывается форматирование строки. Конкретно:
 
В строке присутствуют верхние и нижние индексы (или регистры, кто они...?)
Типа H20, где 2 внизу и икс в квадрате - х2, где 2 вверху.
 
как мне сохранить это формат строки?

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 13:41 12-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Хм. А разве это не отдельные символы?  
Двойка, верхний индекс два и нижний индекс два - это три разных символа уникода.

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 20:39 13-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну, и а как их оставить, почему все в один формат перетасовываются?
Как вариант, конечно, можно ещё одну процедурку сделать, где нижние и верхние индексы заменяются на невообразимое что, а потом это невообразимое что заменить на эту двойку верхнего или нижнего индекса.
Неужели это единственный выход?

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 06:44 15-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
не видя код, сложно что-то советовать...  
Подозреваю, что когда вы меняете, вы в качестве новой строки указываете "H2O",  
а не "H" + chrW(код подстрочной двойки) + "O"

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 11:20 15-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Почему, вон код, вверху.
Ага, это мне пригодится. Но дело в том, что меняются все такие нижние и верхние индексы, которых я и не трогал.
 
вот в этом месте, когда условия совпали для замены
If yes_zamena Then  
    ActiveDocument.Sentences(i) = Mid(ActiveDocument.Sentences(i),1,j-1)+ _  
    sr + Mid(ActiveDocument.Sentences(i), j + Len(s_split(0)))  
 
 
Тут j - номер символа с которого начинается набор букв, подлежащих замене
ActiveDocument.Sentences(i) - текущая строка документа
возвращает строку до заменяемых символов
sr - новая подстрока
Len(s_split(0)) - длина новой подстроки
Ну да, ищу и заменяю без учёта chrW.
Как же это можно учесть?
 
Вот например:
 
Слово1 слово2, слово3 X2 - Y2, слово4 слово5 H2O.
Заменить нужно Y2 на A3,
где X2 - икс в квадрате, Y2 - Y в квадрате, А3 - А в кубе, H2O - соответственно АШ2О  )))
 
 
И ещё, попробовал использовать chrW (sr = string1 + chrW + string2)  - бейсик ругнулся:
Argument not optional.
 
Если для большего понимания моей проблемки нужен более полный код программки, то куда его можно поместить - сюда? Там немного, 100 строк, примерно.
 
Добавлено:
Может я вообще копаюсь не там. Вдруг всё проще, чем я намутил всё?
 
Структурная карта для отражающих горизонтов Г, М, НБС2, НАС7-8, НАС9-10, НАС11-12, НБС1, НБС7, НБС7-6, НБС4, НБС10, Б, Абалак, Т, Т1, Т2, Т3, А, рассчитанных c использованием регрессивной зависимости  
 
Здесь цифры и цифры с тирешками - все внизу
 
Заменить нужно некоторые из них
НБС1 на НАС91, где 9 внизу, а 1 вверху
НБС7 на НАС10-112, где 10-11 внизу, а 2 вверху
 
Придумал сначала заменить "БС1" на "АС---9+++1", а потом "---9" на "9" в нижнем регистре, а "+++1"  на "1" в верхнем
 
Ну и также для БС7
 
Всё заменяется, всё хорошо, но регистры в текущем предложении сбрасываются при замене "БС1" на "АС---9+++1".
 
Добавлено:
Public Sub zamena_po_predl()
 Dim s, sr As String
 Dim i, j, l, k As Integer
 Dim s_split() As String
 Dim yes_instr, yes_zamena As Boolean
 
     Open "D:\plast112test.txt" For Input As #1
     
     While Not EOF(1)
        Input #1, s
           If s <> "" Then
                  s = Trim(s):   s_split() = Split(s):   j = -1: l = UBound(s_split)
              For i = 0 To l
                If s_split(i) <> "" Then
                  j = j + 1:   s_split(j) = s_split(i)
                End If
              Next
              ReDim Preserve s_split(j)
                  l = UBound(s_split)
 
              If l < 3 Then
                sr = s_split(1) + "---" + s_split(2)
              Else
                sr = s_split(1) + "---" + s_split(2) + "+++" + s_split(3)
              End If
 
              For i = 1 To ActiveDocument.Sentences.Count
                         yes_instr = True: k = 1
                Do While yes_instr
                   
                   j = InStr(k, ActiveDocument.Sentences(i), s_split(0))
                If j <> 0 Then
                   yes_zamena = False
 
                   If j + Len(s_split(0)) + 1 = Len(ActiveDocument.Sentences(i)) Then
                      yes_zamena = True
                   Else
                     If (ActiveDocument.Sentences(i).Characters(j + Len(s_split(0))) = ",") Or (ActiveDocument.Sentences(i).Characters(j + Len(s_split(0))) = " ") Then
                        yes_zamena = True
                     End If
 
                   End If
 
                   If yes_zamena Then
                      ActiveDocument.Sentences(i) = Mid(ActiveDocument.Sentences(i), 1, j - 1) & sr & Mid(ActiveDocument.Sentences(i), j + Len(s_split(0)))
                      k = j + Len(sr)
                   Else
                      k = j + Len(s_split(0))
                   End If
 
                   If k + 2 > Len(ActiveDocument.Sentences(i)) Then
                      yes_instr = False
                   End If
               Else
                   yes_instr = False
               End If
           Loop
                 
      Next  '--------------------------
 
 
           Selection.Find.ClearFormatting
           Selection.Find.Replacement.ClearFormatting
      With Selection.Find
          .Text = "---" + s_split(2)
          .Replacement.Text = s_split(2)
          .Replacement.Font.Subscript = True
          .Replacement.Font.Superscript = False
          .Forward = True
          .Wrap = wdFindContinue
          .Format = True
          .MatchCase = False
          .MatchWholeWord = True
          .MatchWildcards = False
          .MatchSoundsLike = False
          .MatchAllWordForms = False
      End With
          Selection.Find.Execute Replace:=wdReplaceAll
 
   If l > 2 Then
 
 
           Selection.Find.ClearFormatting
           Selection.Find.Replacement.ClearFormatting
      With Selection.Find
          .Text = "+++" + s_split(3)
          .Replacement.Text = s_split(3)
          .Replacement.Font.Superscript = True
          .Replacement.Font.Subscript = False
          .Forward = True
          .Wrap = wdFindContinue
          .Format = True
          .MatchCase = False
          .MatchWholeWord = True
          .MatchWildcards = False
          .MatchSoundsLike = False
          .MatchAllWordForms = False
      End With
          Selection.Find.Execute Replace:=wdReplaceAll
 
   End If
 End If
 
  Wend
 Close #1
 
End Sub

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 12:18 15-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Когда я предлагал написать какую-нибудь свою простенькую функцию замены, я имел виду какую-нибудь действительно простенькую функцию
Например, такую:

Код:
Function MyReplace(Substr1, Substr2, Source As String) As String
  Const Alphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ1234567890-"
  Wrd = False
  Result = ""
  tmpW = ""
  For i = 1 To Len(Source)
    If InStr(Alphabet, Mid(Source, i, 1)) > 0 Then
      Wrd = True
      tmpW = tmpW + Mid(Source, i, 1)
    Else
      If Wrd Then
        If tmpW = Substr1 Then
          Result = Result + Substr2
        Else
          Result = Result + tmpW
        End If
        tmpW = ""
        Wrd = False
      End If
      Result = Result + Mid(Source, i, 1)
    End If
  Next i
  MyReplace = Result
End Function

Меняет внутри Source Substr1 на Substr2. Чувствительна к регистру и Substr1 - обязательно целое слово. Символы, которые являются частью слова перечислены в Alphabet.
Тогда, для вашей строки, чтобы заменить НБС1 на НАС91, где 9 внизу, а 1 вверху, нужно написать:

Код:
Sub qweqwe()
  For i = 1 To ActiveDocument.Sentences.Count
    ActiveDocument.Sentences(i) = MyReplace("НБС1", "НАС" + ChrW(8329) + ChrW(185), ActiveDocument.Sentences(i))
  Next i
End Sub
 
ChrW(8329) - это подстрочная 9
ChrW(185) - это надстрочная 1
 
Пробуйте.

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 20:11 15-02-2016 | Исправлено: KDPoid, 20:13 15-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Спасибо за помощь, чуть по-позже я Вашу программку поиспытаю.
 
Это хорошо, если я знаю что на что менять.
Но я беру эти данные из файла, который правят пользователи.
 
-------------------------------
БС7  АС 10-11 1
БС10 АС 11 1
БС1  АС 9 1
БС2  АС 9 1-1-1
БС3  АС 9 1-1-2
БС4  АС 9 1-1
БС5  АС 9 2
БС6  АС 10 1-1
БС8  АС 10 2
БС9  АС 11
 
формат такой: <что менять> <на что менять> <нижний индекс> <верхний индекс>
-------------------------------
 
Я не знаю заранее что на что будет меняться. Какая комбинация будет нижним регистром, а какая комбинация верхним.
А ведь комбинация может и такая быть
АС 10-11 2, где 10-11 внизу, а 2 вверху
Но эти-то замены у меня работают.
 
Эффект только один, когда произвожу замену, то во всей строке, если где-то есть (а они есть) нижние и верхние индексы - сбрасываются.
 
Если заменять стандартно Selection.Find.Execute Replace:=wdReplaceAll
то регистры не сбрасываются. Но заменяется всё, что подходит к фильтру Selection.Find.Text
а это не правильно.
 
Я думаю нужен такой цикл сделать, чтоб он посимвольно копировал из одной строки в другую, до места замены, потом копировал посимвольно новую подстроку (или просто присоединить), а потом снова копировать посимвольно до конца. И тогда сохранятся все chrW(xxxx), которые я не знаю заранее.

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 07:32 16-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А можно увидеть файл, в котором у вас "10-11" в нижнем индексе и "1-1-2" в верхнем?
Что-то мне подсказывает, что мы о разных вещах говорим...

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 08:38 16-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Простой текстовый файл, который могли бы править простые пользователи
 
-------------------------------  
БС7  АС 10-11 1  
БС10 АС 11 1  
БС1  АС 9 1  
БС2  АС 9 1-1-1  
БС3  АС 9 1-1-2  
БС4  АС 9 1-1  
БС5  АС 9 2  
БС6  АС 10 1-1  
БС8  АС 10 2  
БС9  АС 11  
 
формат такой: <что менять> <на что менять> <нижний индекс> <верхний индекс>  
-------------------------------

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 11:04 16-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Я не знаю, как вы себе представляете "1-1-2" в верхнем индексе.
Цифры в верхнем индексе - это мне понятно. А вот тире... Вы в Word-овском файле это когда-то видели? А можно мне посмотреть, как это должно выглядеть? Как реализовано тире в составе верхнего индекса у вас ?

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 13:01 16-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Ну как-то так:
 

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 06:52 17-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А ссылочку на этот файл можно ?
Минус в нижнем индексе - это какой-то уникодный символ, который я проглядел, или заданное оформление, например, отступом строки? Я бы, без лишних, слов увидел в вашем файле, что конкретно вы хотите добиться.

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 07:12 17-02-2016
Devust

Newbie
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
А что, это разве так уникально?
Я просто нажал на кнопочку.
http://imageshack.com/a/img922/2881/UUOiER.jpg
 
Рабочий файл word
https://yadi.sk/i/B7PC5nxToyEUG
 
Файл, с описанием замены
https://yadi.sk/i/8c3YEC7XoyEAQ
 
Файл с модулями на VBA
https://yadi.sk/i/wsrcoGrfoyFZE
 
последняя процедура в разработке - zamena_po_predl()

Всего записей: 18 | Зарегистр. 15-01-2013 | Отправлено: 11:48 17-02-2016
KDPoid



Full Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
"Даже если вас съели, у вас остаётся 2 выхода..."
 
Раз вы используете .subscript, а не уникодные символы цифр в нижнем индексе, то всякие ChrW(8329) вам не подходят.
 
Пишем функцию замены:

Код:
Sub MyReplace(SearchS, ReplaceS, DownS, UpS As String)
  Const Alphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ1234567890-"  
  Dim r As Range
   
  Wrd = False
  WrdB = 0
  WrdE = 0
  i = 1
   
  While i <= ActiveDocument.Characters.Count
    If InStr(Alphabet, ActiveDocument.Characters(i)) > 0 Then
      If Not Wrd Then
        Wrd = True
        WrdB = i
      End If
    Else
      If Wrd Then
        WrdE = i - 1
        Set r = ActiveDocument.Range(WrdB - 1, WrdE)
         
        If r.Text = SearchS Then
          r.Delete
          r.InsertAfter (ReplaceS)
          i = WrdB - 1 + Len(ReplaceS)
          Set r = ActiveDocument.Range(i, i)
          r.InsertAfter (DownS)
          r.Font.Subscript = True
          i = i + Len(DownS)
          If UpS <> "" Then
            Set r = ActiveDocument.Range(i, i)
            r.InsertAfter (UpS)
            r.Font.Superscript = True
            i = i + Len(UpS)
          End If
        End If
        Wrd = False
      End If
    End If
    i = i + 1
  Wend
End Sub

Тогда от всей zamena_po_predl() остаётся:

Код:
Public Sub zamena_po_predl()
Dim s As String
Dim s_split() As String
  Open "D:\plast112test.txt" For Input As #1
  While Not EOF(1)
    Input #1, s
    If s <> "" Then
      s = Trim(s):   s_split() = Split(s)
      If UBound(s_split) = 2 Then
        ReDim Preserve s_split(3)
        s_split(3) = ""
      End If
      MyReplace s_split(0), s_split(1), s_split(2), s_split(3)
    End If
  Wend
  Close #1
End Sub

Вроде как, на вашем файле работает... Только ме-е-едленно....
Теперь надо бы посмотреть, куда время уходит, и доработать напильником...

Всего записей: 404 | Зарегистр. 08-08-2006 | Отправлено: 22:48 19-02-2016
Открыть новую тему     Написать ответ в эту тему

Страницы: 1 2

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » Word VBA Замена


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru