| 
			| 
					
						| sergvg 
								Интересующийся    Offline | 
								|  | «  : 12-05-2010 10:54 »  |  | 
 
 Здравствуйте, уважаемые коллеги! Помогите, пожалуйста!  подскажите, каким образом можно найти в документе Word все слова, перед которыми стоит специальный знак (например, '*') и записать их в массив, затем все полученные слова (вместе с предшествующим знаком) заменить на другой текст? пока пришло такое решение (поиск меток):  $WordsCount = $File->Words->{Count};my $pword;
 for $i (1..$WordsCount){
 $word = $File->Words($i)->{Text};
 if ($pword eq '*' ) {
 push @$words ,$word;
 }
 $pword = $word;
 }
 
и затем произвести замену с помощью этого  my $search =  $doc-> Content->Find;my $replace = $search-> Replacement;
 
 $search-> {Text} = $oldtext;
 $replace-> {Text} = $newtext;
 $search-> Execute({Replace => wdReplaceAll});
 
Но я думаю, что есть более эффективный метод. Метод с закладками (bookmarks) мне не нравится, потому что неудобно клепать шаблоны. Намного нагляднее в тексте шаблона видеть метки, поэтому этот метод предлагать не нужно (уже есть у меня готовое решение с использованием закладок).Добавлено через 1 час, 45 минут и 39 секунд: В общем, у меня получился такой код для поиска и замены меток вида *Name my $Word = CreateObject Win32::OLE 'Word.Application' or die $!;$Word->{'Visible'} = 1;
 
 
 my $File = $Word->Documents->Open(abs_path($ARGV[0]));
 
 #$ActiveDoc = $Word->ActiveDocument;
 
 my $replaces={'PrikazNum'=>'Номер приказа 222', 'Date'=>'Дата: 2010-01-02', 'sign'=>'Подпись: 2222'};
 
 my $myRange = $File->Content;
 while ($myRange->{Find}->Execute ({FindText=>'*', Forward=>1}) ){
 $foundrange=$myRange->Next({Unit=>wdWord, Count=>1});
 $repltext = $replaces->{$foundrange->{Text}};
 $foundrange->MoveStart({Unit=>wdCharacter, Count=>-1});
 print "'$foundrange->{Text}' заменяем на '$repltext'\n";
 $foundrange->{Text} = $repltext;
 }
 
Вопрос остался такой: как избежать появления пробелов в $foundrange->{Text} ? Сюда пробел попадает, другие символы нет (если в документе встречаются). |  
						| 
								|  |  
								| « Последнее редактирование: 12-05-2010 12:40 от sergvg » |  Записан | 
 |  |  | 
	| 
			| 
					
						| baldr | 
								|  | « Ответ #1 : 13-05-2010 05:52 »  |  | 
 
 sergvg, а регулярные выражения ты не пробовал? Судя по условию задачи - это самый подходящий вариант для тебя |  
						| 
								|  |  
								|  |  Записан | 
 
 Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #2 : 13-05-2010 06:10 »  |  | 
 
 Чего-то я не пойму: листинги на Perl, а раздел - VBA. Замеченные недостатки - нет проверки на наличие ключа: $repltext = $replaces->{$foundrange->{Text}};Наверно стоит так:     $foundrange->{'Text'} ~= m/^(\s*)(.*?)(\s*)$/;
 if (exists($replaces->{$2})
 {
 $foundrange->{'Text'} = $1 . $replaces->{$2} . $3;
 }
 
 |  
						| 
								|  |  
								| « Последнее редактирование: 13-05-2010 06:34 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| sergvg 
								Интересующийся    Offline | 
								|  | « Ответ #3 : 13-05-2010 07:08 »  |  | 
 
 У меня вопросы не по Perl, а по VBA (перл я знаю отлично, а вот с VBA не работал совсем)! 
 
 Какие объекты использовать, и какие методы вызывать!
 
 И в моём случае, проверку на наличие ключей хеша можно не делать, потому что документ (шаблон) сначала загружается на сервер, скриптом получается список меток. А затем, другим скриптом эти метки заполняются, где формируется хеш по списку параметров.
 
 Прошу перенести тему обратно в VBA.
 
 
 PS: о каких регулярных выражениях шла речь ?  в VBA есть регеспы ?
 
 
 со стороны Perl эти пробелы в конце, разумеется, я поубирал.
 |  
						| 
								|  |  
								| « Последнее редактирование: 13-05-2010 07:27 от RXL » |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #4 : 13-05-2010 07:34 »  |  | 
 
 Понятие "знаю отлично" у каждого свое. На мой взгляд для этого не хватает, для начала, use strict и вытекающих из этого ограничений на необъявленные переменные и голые слова, а также проверок, т.к. со strict все огрехи по вылезают как ошибки, причем, ошибка с отсутствующим ключем может вылезти уже в процессе эксплуатации. Т.ч. посторожнее с утверждениями...
 К VBA вопрос отношения не имеет. Это работа с COM-объектами. То, что в VB и VBA все объекты являются COM-объектами, еще не ставит между ними знака равенства. Точно также можно работать с Вордом на любом другом языке. Я, к примеру, использую экспорт в Excel из Borland C++ Builder. Значит темы BCB тоже в VBA переносить?
 
 Что и как у тебя формируется — мы не видим и, соответственно, знать не можем. Судим по приведенному коду и заданным вопросам.
 |  
						| 
								|  |  
								| « Последнее редактирование: 13-05-2010 07:36 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| sergvg 
								Интересующийся    Offline | 
								|  | « Ответ #5 : 13-05-2010 09:21 »  |  | 
 
 Если мне нужно уточнить, узнать какие объекты, их свойства  и методы использовать для того, чтобы поуправлять MS Word'ом, то причём тут Perl ? 
 а куски кода на Perl, потому что я пишу на Perl, и слабо знаю синтаксис VBA, чтобы привести к нему.
 
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| baldr | 
								|  | « Ответ #6 : 13-05-2010 10:58 »  |  | 
 
 sergvg, если ты спрашиваешь про объектную модель Word, то так и говори. Мы видим конкретный вопрос: Вопрос остался такой: как избежать появления пробелов в $foundrange->{Text} ? Сюда пробел попадает, другие символы нет (если в документе встречаются). И отвечаем, что лучше уж использовать регулярные выражения, и RXL  даже пример привел. Никто не говорил ни слова про VBA. Поскольку пример на Perl, то и очевидно что ожидается решение на Perl. |  
						| 
								|  |  
								|  |  Записан | 
 
 Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #7 : 13-05-2010 12:57 »  |  | 
 
 sergvg, если не знаешь, как-то делай просто: открывай документ, запускай запись макроса и выполняй действия руками (старайся делать минимум  действий - только нужные), после чего в макросе видим последовательность действий с объектами. Код там не сложный - на Perl портируется чуть ли не один в один. Собственно говоря, у тебя похоже так и сделано. У меня получилось немного иначе:     Selection.Find.ExecuteSelection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
 
Но суть та же: если после "*слово" есть пробел, то он тоже выделяется. Думаю, что не надо ничего делать - бери, что дают, реж регулярными выражениями (в Перле!) и делай с ним что надо. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Sla | 
								|  | « Ответ #8 : 13-05-2010 13:29 »  |  | 
 
 не знаю, есть ли регулярки в VBA, но в VB есть объект RegExp
 Dim myRegExp As New RegExp
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Мы все учились понемногу... Чему-нибудь и как-нибудь. |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #9 : 13-05-2010 13:43 »  |  | 
 
 Слав, VBA тут не при чем - нету его. Есть Perl и COM-объект Word.Application. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| sergvg 
								Интересующийся    Offline | 
								|  | « Ответ #10 : 13-05-2010 17:33 »  |  | 
 
 sergvg, если не знаешь, как-то делай просто: открывай документ, запускай запись макроса и выполняй действия руками (старайся делать минимум  действий - только нужные), после чего в макросе видим последовательность действий с объектами. Код там не сложный - на Perl портируется чуть ли не один в один. Собственно говоря, у тебя похоже так и сделано. У меня получилось немного иначе:     Selection.Find.ExecuteSelection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
 
Но суть та же: если после "*слово" есть пробел, то он тоже выделяется. Думаю, что не надо ничего делать - бери, что дают, реж регулярными выражениями (в Перле!) и делай с ним что надо. так-то понятно, но я долго искал в хелпе, как получить в перле уже список отмеченных слов, ещё неясно было, как продолжить поиск (после изменения Range поиск зацикливался, начинаясь наверно или сначала, или поиск производился в измененном Range) Ну а то, что пробелы перлом на раз выкусываются - это элементарно. Думал, может есть какая-то опция, чтобы эти пробелы просто не попадали в результат.  Было бы удобнее, если бы был поиск с регеспами, искал бы по /\*.(\w+)/. Или может есть, а я не знаю?  |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #11 : 13-05-2010 19:49 »  |  | 
 
 Полноценных регулярных выражений в Ворде нет, но можно делать примитивные шаблоны типа как в оболочке с именами файлов. Собственно, это описано в MSDN и даже в самом Ворде, когда открываешь поиск и делаешь его расширенным (и включи галку "Подстановочные знаки", а символы можно выбрать из выпадающего списка). Find object members: http://msdn.microsoft.com/en-us/library/bb257583.aspx Посмотри свойства: IgnoreSpace, MatchWildcards. Простые эксперименты руками в Ворде дали такой шаблон: \*<*> Это выбирает звездочку и слово за ним. Объекты Ворда: http://msdn.microsoft.com/en-us/library/bb225019.aspxДобавлено через 29 минут и 15 секунд: Вот макрос Ворда.     Selection.Find.ClearFormattingSelection.Find.Replacement.ClearFormatting
 With Selection.Find
 .Text = "\*<*>"
 .Forward = True
 .Wrap = wdFindContinue
 .Format = False
 .MatchCase = False
 .MatchWholeWord = False
 .MatchAllWordForms = False
 .MatchSoundsLike = False
 .MatchWildcards = True
 End With
 Selection.Find.Execute
 With Selection.Find
 .Text = "\*<*>"
 .Replacement.Text = "1111"
 .Forward = True
 .Wrap = wdFindContinue
 .Format = False
 .MatchCase = False
 .MatchWholeWord = False
 .MatchAllWordForms = False
 .MatchSoundsLike = False
 .MatchWildcards = True
 End With
 With Selection
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseStart
 Else
 .Collapse Direction:=wdCollapseEnd
 End If
 .Find.Execute Replace:=wdReplaceOne
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseEnd
 Else
 .Collapse Direction:=wdCollapseStart
 End If
 .Find.Execute
 End With
 With Selection.Find
 .Text = "\*<*>"
 .Replacement.Text = "2222"
 .Forward = True
 .Wrap = wdFindContinue
 .Format = False
 .MatchCase = False
 .MatchWholeWord = False
 .MatchAllWordForms = False
 .MatchSoundsLike = False
 .MatchWildcards = True
 End With
 With Selection
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseStart
 Else
 .Collapse Direction:=wdCollapseEnd
 End If
 .Find.Execute Replace:=wdReplaceOne
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseEnd
 Else
 .Collapse Direction:=wdCollapseStart
 End If
 .Find.Execute
 End With
 With Selection.Find
 .Text = "\*<*>"
 .Replacement.Text = "3333"
 .Forward = True
 .Wrap = wdFindContinue
 .Format = False
 .MatchCase = False
 .MatchWholeWord = False
 .MatchAllWordForms = False
 .MatchSoundsLike = False
 .MatchWildcards = True
 End With
 With Selection
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseStart
 Else
 .Collapse Direction:=wdCollapseEnd
 End If
 .Find.Execute Replace:=wdReplaceOne
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseEnd
 Else
 .Collapse Direction:=wdCollapseStart
 End If
 .Find.Execute
 End With
 
Если его подчистить, то получится примерно следующее: Инициализация     Selection.Find.ClearFormattingSelection.Find.Replacement.ClearFormatting
 
 With Selection.Find
 .Text = "\*<*>"
 .Forward = True
 .Wrap = wdFindContinue
 .Format = False
 .MatchCase = False
 .MatchWholeWord = False
 .MatchAllWordForms = False
 .MatchSoundsLike = False
 .MatchWildcards = True
 End With
 
Поиск Замена     Selection.Find.Replacement.Text = "1111"
 With Selection
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseStart
 Else
 .Collapse Direction:=wdCollapseEnd
 End If
 
 .Find.Execute Replace:=wdReplaceOne
 
 If .Find.Forward = True Then
 .Collapse Direction:=wdCollapseEnd
 Else
 .Collapse Direction:=wdCollapseStart
 End If
 End With
 
 |  
						| 
								|  |  
								| « Последнее редактирование: 13-05-2010 20:23 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| sergvg 
								Интересующийся    Offline | 
								|  | « Ответ #12 :  14-05-2010 03:17 »   |  | 
 
 спасибо, на досуге опробую.  |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |