powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / VBA - кому морду бить?
22 сообщений из 22, страница 1 из 1
VBA - кому морду бить?
    #36008725
Я всего лишь хочу посимвольно анализировать текст ActiveDocument и кое-что в нём менять, не меняя даже длинны! Я не могу этого сделать нормально в VBA! Всё вылазят какие-то бяки.

Пришлось тут пописать на VBA. Некоторый анализ и коррекцию текста. Общее препакостное ощущение, что приходится все время сражаться с выдуманными Microsoft препятствиями, я не над алгоритмом размышляю, а над тем как его заставить работать в VBA и когда уже кажется, что победил, отлаживая прогу, наталкиваюсь на такое, что хочется завыть и загрызть кого-то.

Вот за это, что делать?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
  ActiveDocument.Select
  Sel$ = Selection
  len1 = Len(Sel$)
  
  len2 = ActiveDocument.Characters.Count

  If len1<>len2 Then MsgBox "I hate Microsoft!!!!"

Ладно, наплевавшись я обошелся без Select, работая только с Characters у ActiveDoument и написав пару функций на замену Mid$.

Все бы ничего, но в некоторых случаях конструкция вида:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Function GetWord(FromCharacter, WordLength As Long) As String
Dim i As Long
Dim s As String
For i = FromCharacter To FromCharacter + WordLength -  1 
  s = s + ActiveDocument.Characters(i)
Next i
GetWord = s
End Function 


сваливается с ошибкой вида Runtime Error '5941' "Запрашиваемый номер семейства не существует" хотя только недавно он существовал. То есть номер "i" вдруг перестаёт нравиться, хотя за границы не выходит, я проверял.

Обойтись одним Sel$ и Select я тоже не могу, потому что мне надо вставлять изменённый текст обратно в документ, но если в документе имеются математические формулы или рисунки, в общем, внедрённые объекты, они пропадают, если я сделаю скажем

Код: plaintext
1.
Selection.Text = Sel$

Казалось бы у Selection тоже есть свойство Characters и мог бы попробовать посимвольно что-то менять, но с непредсказуемым результатом возникает ошибка. Непредсказуемость в том, что при одном варианте макроса ошибки нет, а при другом - есть. Отчего зависит, хз, я выход за пределы диапазона проверял много раз.

Ну вот что делать? Повторю вопрос:

Я всего лишь хочу посимвольно анализировать текст ActiveDocument и кое-что в нём менять, не меняя даже длинны!
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36008769
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: СтаниславК
.....
<бред поскипан>
.....
> Ну вот что делать? Повторю вопрос:
>
> Я всего лишь хочу посимвольно анализировать текст ActiveDocument и кое-что в нём менять, не меняя даже длинны!

Это не вопрос, это восклицание желания.
А на вопрос из сабжа отвечать не буду, обидешся ;)

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


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36008802
Игорь Горбонос
Почитай справку по вба для ворда, поищи в инете и посмотри примеры как делают другие.
а ошибки у тебя могут происходить от того, что используешь ActiveDocument, если макрос работает долго и в этот момент пользователь переключился на другой файл, то он стал ActiveDocument и в нем может и не быть столько символов, и т.д. и
т.п.


Переключений не происходит, кроме того, я контролировал какие символы извлекаются, до самой ошибки извлекались те, что надо.

Ладно, попробую сформулировать вопрос точнее:

Подскажите пожалуйста какой раздел справки почитать или что я не так делаю, чтобы:

1) Как правильно получить в ActiveDocument произвольный символ в тексте?
2) Как правильно его записать обратно?

С учётом того, что ActiveDocument.Characters(i) - даже справа может свалиться с ошибкой.
Что у ActiveDocument (и Documents) отсутствует свойство Text.
Что текст получаемый через Selection в каких-то спецсимволах не совпадает с тем, что получается через свойство Characters.

Если бы у меня вообще не получалось читать и править текст, это одно. Но у меня получается, но один вариант программы на некоторых файлах иногда (Selection не всегда не совпадает с Characters на отладочном примере он совпал!) пишет обратно текст не в своё место. А другой вариант текст пишет правильно, но часто сваливается с ошибкой.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36008869
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1) В ворде нужно работать с сущностями по мере их мельчания: Document — Paragraphs.Range — Sentences.Range — Words.Range — Characters.Range
2) Править текст нужно С КОНЦА.

Ворд капризен. Без конкретного документа невозможно дать конкретный совет.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36009776
Antonariy1) В ворде нужно работать с сущностями по мере их мельчания: Document — Paragraphs.Range — Sentences.Range — Words.Range — Characters.Range

К сожалению, совет не очень годится. До уровня параграфов ещё можно подняться, но со словами приходится самому работать. Хотя бы потому, что мнение о том, что является разделителями слов у Word не совпадает с моим. Можно конечно, все обрабатывать с учётом символов переходящих из слова в слова, но мать-перемать насколько на ровном месте усложняется программа. Причем чувствую, что без гарантии корректности работы.

2) Править текст нужно С КОНЦА.
Ворд капризен. Без конкретного документа невозможно дать конкретный совет.

Насчет с конца интересная идея, попробую. А что ворд капризен - уже заметил. Я знаю C/C++, Perl, Pascal (Delphi), имею некоторый опыт написания программ разной сложности, хотя в последнее время и подотошел от непосредственно программирования. Но вот пришлось. И скажу, VBA в Word - это что-то с чем-то, ничего похожего по своей контринтуитивности и капризности я еще не встречал.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36010181
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И скажу, VBA в Word - это что-то с чем-то, ничего похожего по своей контринтуитивности и капризности я еще не встречал.В принципе, VBA ни при чем. Это просто инструмент для работы с объектной моделью хостящего приложения. Попробуй задействовать C++ — столкнешься с теми же капризами.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36010183
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А в чем конкретно задача состоит? Мне не раз приходилось ставить ворд на колени)))
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36010309
AntonariyА в чем конкретно задача состоит? Мне не раз приходилось ставить ворд на колени)))

Задача была править характерные ошибки после FineReader-а. Любит он путать кириллицу и латиницу схожую по начертанию и еще ряд очень типичных ошибок.

Вроде пока выкрутился, зацените быдлокодерство :)

Вместо такой функции:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
Sub AssignSelectionCharacter(FromCharacter As Long, NewText As String)
'В текущем Selection присваются в Character, начиная с FromCharacter посимвольно
'слово NewText
Dim i As Long
For i =  1  To Len(NewText)
   ActiveDocument.Characters(FromCharacter + i -  1 ) = Mid$(NewText, i,  1 )
Next i
End Sub 'AssignSelectionCharacter

Пришлось наваять поиск места, где в тексте было старое слово

Выше по тексту присваивания:

ActiveDocument.Select
Sel$ = Selection

Count = ActiveDocument.Characters.Count
sellen = Len(Sel$): actlen = Count

С учётом, что они могут быть разные переписал функцию замены в тексте одного слова на другое:

Код: plaintext
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.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
Sub AssignSelectionCharacter(FromCharacter, sellen, actlen As Long, NewText, OldText As String)
'В текущем Selection присваются в Character, начиная с FromCharacter посимвольно
'слово NewText
Dim i, j, k As Long
Dim NotMatching As Boolean
Dim s1, s2, s3 As String

If sellen = actlen Then 'Не надо изощряться
  k =  0 : GoTo aa1
End If

If sellen > actlen Then 'Надо уменьшать индекс для ActiveDocument, k - отрицательное
  NotMatching = True
  s1 = Mid$(OldText,  1 ,  1 ) 'Первый символ для поиска совпадений
  k =  1  'Потом сразу уменьшим на 1.
  While NotMatching
    k = k -  1 
    If k < (actlen - sellen -  1 ) Then 'Что-то совсем неправильно
      MsgBox "Невозможно заменить слово"
      Exit Function
    End If
    If ActiveDocument.Characters(FromCharacter + k) <> s1 Then
      
    Else
      NotMatching = False
      For j =  1  To Len(OldText)
        s2 = Mid$(OldText, j,  1 )
        s3 = ActiveDocument.Characters(FromCharacter + j -  1  + k)
        If s2 <> s3 Then
          NotMatching = True
          Exit For
        End If 's2
      Next j
    End If 's1 совпал
  Wend 'NotMatching
End If 'sellen>actlen
GoTo aa1

If sellen < actlen Then 'Надо увеличивать индекс для ActiveDocument, k - положительное
  NotMatching = True
  s1 = Mid$(OldText,  1 ,  1 ) 'Первый символ для поиска совпадений
  k = - 1  'Потом сразу увеличим на 1.
  While NotMatching
    k = k +  1 
    If k > (actlen - sellen +  1 ) Then 'Что-то совсем не так.
      MsgBox "Невозможно заменить слово"
      Exit Function
    End If
    If ActiveDocument.Characters(FromCharacter + k) <> s1 Then
      
    Else
      NotMatching = False
      For j =  1  To Len(OldText)
        s2 = Mid$(OldText, j,  1 )
        s3 = ActiveDocument.Characters(FromCharacter + j -  1  + k)
        If s2 <> s3 Then
          NotMatching = True
          Exit For
        End If 's2
      Next j
    End If 's1 совпал
  Wend 'NotMatching
End If 'sellen>actlen
GoTo aa1


aa1: For i =  1  To Len(NewText)
   s3 = ActiveDocument.Characters(FromCharacter + i -  1  + k)
   ActiveDocument.Characters(FromCharacter + i -  1  + k) = Mid$(NewText, i,  1 )
Next i

End Sub 'AssignSelectionCharacter

На goto и фактически лишние s1,s2,s3 и лишний круг цикла не обращайте внимание, сам знаю, просто от процесса отладки осталось.

Вроде бы теперь программа заработала правильно. Хотя подобные извращения чем-то напоминают анекдот.

Между прочим, как узнать какой номер у ActiveDocument, чтобы потом обращаться к нему через Documents(Index) ?
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36010336
Exit Sub в предыдущем тексте, прошу прощения, каким-то образом скопипастил черновой вариант, который я отдельно сохранил.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36010546
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нужен документ целиком с примером вызова, в отрыве эту функцию никак не пощупать.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011002
Фотография VladConn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
СтаниславК,
Там Вы неявно декларируете i, j, s1 и s2 как Variant.
И сходу вопрос, Вы не пробовали регулярные выражения для поиска и замены текста? Тогда может и от циклов получится избавиться?
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011119
AntonariyНужен документ целиком с примером вызова, в отрыве эту функцию никак не пощупать.

К сожалению, документы конфиденциальные, поэтому не могу показать. Вообще документ представляет собой текст объёмом иногда более 100 Мб, но обычно менее 1 Мб. Является результатом распознавания в FineReader 9-ой версии и дальнейшей обработки. Может содержать математические и химические формулы, а также рисунки.

VladConnСтаниславК,
Там Вы неявно декларируете i, j, s1 и s2 как Variant.
И сходу вопрос, Вы не пробовали регулярные выражения для поиска и замены текста? Тогда может и от циклов получится избавиться?

Отчего Variant?

Регулярные выражения вообще неплохая мысль, но опять же теряется гибкость, да и слишком много крутить придется.

Я как-то с трудом представляю как средствами Word составить такое выражение, чтобы найти слово (причем не всегда пробел или запятая разделитель - зависит от слова) одновремённо и символы латинского и символы русского алфавита в одном слове. Хотя допустимо только русские или только латинские. Но может и можно, просто сходу ничего не придумывается.

Еще ведь надо показать человеку (оператору) найденный текст, что вокруг его тоже подцепить и показать. А в диалоговом окне уже надо выбрать, что делать с текстом. Желательно курсор передвинуть туда же.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011175
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну дайте любой не конфиденциальный документ, главное чтобы в нем были характерные ошибки.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011212
Фотография VladConn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Первый раз слышу, что от регулярных выражений теряется гибкость.... ОК. Если Вы предпочитаете "извращения, напоминающие анекдот"....

:0)

Отчего Variant? От правил синтаксиса.... Вы этим переменным не присвоили тип. По умолчанию они приняли религию Variant.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011217
Фотография VladConn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, еще, выражение (Вы имеете ввиду pattern?) составляется не средствами Word, а средствами RegExp.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011257
Фотография VladConn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Там если пользоваться RegExp, то надо будет, видимо, динамически строить pattern, что может быть интересно. Циклы, с глобальной заменой, скорее всего уйдут.

RegExp
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011431
AntonariyНу дайте любой не конфиденциальный документ, главное чтобы в нем были характерные ошибки.

Это надо специально поискать. Найду дам, просто как-то даже нет под рукой сейчас.

VladConnПервый раз слышу, что от регулярных выражений теряется гибкость.... ОК. Если Вы предпочитаете "извращения, напоминающие анекдот"....

Хорошо, как с помощью регулярных выражений найти слово, причем запятая не является разделителем, которое внутри себя содержит одновременно символы латинского и русского алфавита (любые)? Затем показать это слово в формочке, пару слов слева и справа, спросить нужно ли заменить все латинские или русские символы на русские или латинские, но похожие по начертанию. Скажем, в слове NaCl буква "C" может оказаться русской, а может ещё и "а" быть русской. Надо заменить на латинские. Или, скажем в выражении "X,Y" надо определить стоит русская или латинская Х

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

Вообще, я знаю, что любой детерминированный конечный автомат может быть заменён регулярным выражением и наоборот. Но в разных случаях удобство принципиально разное, особенно, если осуществляется не только парсинг текста.

VladConnОтчего Variant? От правил синтаксиса.... Вы этим переменным не присвоили тип. По умолчанию они приняли религию Variant.

Я чего-то не понимаю, а что тогда я сделал как не объявление типа в этих строчках вначале функции?

Код: plaintext
1.
2.
3.
Dim i, j, k As Long
Dim NotMatching As Boolean
Dim s1, s2, s3 As String

VladConn RegExp

А они к Word-у XP и 2003 (нужно к обоим) без глюков прикручиваются? И как потом с результатом дальше работать, в смысле хотя бы найти место в тексте?
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011461
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: СтаниславК
> Я чего-то не понимаю, а что тогда я сделал как не объявление типа в этих строчках вначале функции?
Код: plaintext
1.
2.
Dim i, j, k As Long
Dim NotMatching As Boolean
Dim , s3 As String

Ты объявил k как Long, NotMatching как Boolean, s3 как String, а i, j, s1, s2 как Variant


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011485
Игорь Горбонос
Ты объявил k как Long, NotMatching как Boolean, s3 как String, а i, j, s1, s2 как Variant


Спасибо, дошло. Просто на автомате привык к другому синтаксису в объявлениях типа.
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011533
Фотография Игорь Горбонос
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
> Автор: СтаниславК
> Спасибо, дошло. Просто на автомате привык к другому синтаксису в объявлениях типа.

Из-за того что VB у меня был первый, мне до сих пор не хватает On Error ... в том-же С++ :)


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
VBA - кому морду бить?
    #36011870
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
СтаниславКА они к Word-у XP и 2003 (нужно к обоим) без глюков прикручиваются? И как потом с результатом дальше работать, в смысле хотя бы найти место в тексте?В том-то и дело, что никак. Индексация символов в объектной модели ворда не буде кореллировать с индексцией символов строки, которую воспимет regexp.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
VBA - кому морду бить?
    #39334420
Fck_This
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СтаниславК
Госпаде, что за код вообще дичайший. Не знаю как вы там писали под другими языками, но тут жестя какая-то. Если вам надо организовать замену латинских-кириллических букв на аналоги по форме - для этого есть уже куча готовых макросов, которые остаётся только подстроить под свои запросы. Гугл читать надо.
Если бы я ставил перед собой такую задачу, то я шёл бы по такому пути - Поиском и заменой находил символы, которые могут иметь аналогичный вид на рус/англ раскладке. Для себя смотрел - вот они:
a 97 | а 224
A 65 | А 192
x 120 | х 245
X 88 | Х 213
B 66 | В 194
E 69 | Е 197
K 75 | К 202
M 77 | М 204
H 72 | Н 205
O 79 | О 206
P 80 | Р 208
C 67 | С 209
T 84 | Т 210
Y 89 | У 211
e 101 | е 229
k 107 | к 234
o 111 | о 238
p 112 | р 240
c 99 | с 241
y 121 | у 243
Организуем поиск и замену, потом через цикл Do while selectio.find.execute = True делаем проверку окружения символов - тут целая куча возможностей - строковые операторы, проверка следующего\ предыдущего символа. Расширяйте область до слова если надо (К слову, область - набор букв + пробел или "не буква"). Для подстрочных-надстрочных можно использовать их свойства. Для частых случаев (а ведь Адоб тоже делает по программе) можно сделать автозамену.
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / VBA - кому морду бить?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]