2012-07-06 17 views
6

Vì vậy, tôi chỉ mới bắt đầu hiểu Cụm từ thông dụng và tôi đã tìm thấy đường cong học tập khá dốc. Tuy nhiên, stackoverflow đã vô cùng hữu ích trong quá trình thử nghiệm của tôi. Có một macro từ cụ thể mà tôi muốn viết nhưng tôi đã không tìm ra cách để làm điều đó. Tôi muốn có thể tìm thấy hai từ trong vòng 10 hoặc hơn các từ của nhau trong một tài liệu và sau đó in nghiêng những từ đó, nếu các từ cách nhau hơn 10 từ hoặc theo thứ tự khác, tôi muốn macro không in nghiêng những lời đó.Macro Word Regex tìm hai từ trong phạm vi của nhau và sau đó in nghiêng những từ đó?

Tôi đã sử dụng các biểu thức chính quy sau:

\bPanama\W+(?:\w+\W+){0,10}?Canal\b 

Tuy nhiên nó chỉ cho phép tôi vận dụng toàn bộ chuỗi như một tổng thể bao gồm từ ngẫu nhiên ở giữa. Ngoài ra hàm .Replace chỉ cho phép tôi thay thế chuỗi đó bằng một chuỗi khác không thay đổi kiểu định dạng.

Có người nào có kinh nghiệm hơn có ý tưởng về cách thực hiện công việc này không? Thậm chí có thể làm được không?


EDIT: Đây là những gì tôi có cho đến nay. Có hai vấn đề tôi đang gặp phải. Đầu tiên, tôi không biết cách chỉ chọn từ "Panama" và "Kênh" từ trong Cụm từ thông dụng phù hợp và chỉ thay thế những từ đó (chứ không phải từ trung gian). Thứ hai, tôi chỉ không biết làm thế nào để thay thế một Regexp được kết hợp với một định dạng khác, chỉ một chuỗi văn bản khác - có lẽ chỉ là kết quả của việc thiếu sự quen thuộc với các macro từ.

Sub RegText() 
Dim re As regExp 
Dim para As Paragraph 
Dim rng As Range 
Set re = New regExp 
re.Pattern = "\bPanama\W+(?:\w+\W+){0,10}?Canal\b" 
re.IgnoreCase = True 
re.Global = True 
For Each para In ActiveDocument.Paragraphs 
    Set rng = para.Range 
    rng.MoveEnd unit:=wdCharacter, Count:=-1 
    Text$ = rng.Text + "Modified" 
    rng.Text = re.Replace(rng.Text, Text$) 
Next para 
End Sub 

Ok, nhờ sự giúp đỡ từ Tim Williams dưới đây tôi có những giải pháp sau cùng, nó còn hơn cả một chút vụng về trong một số khía cạnh và nó hoàn toàn không có nghĩa là regexp tinh khiết nhưng nó không nhận được công việc hoàn thành. Nếu bất cứ ai có một giải pháp tốt hơn hoặc ý tưởng về làm thế nào để đi về điều này tôi muốn được mê hoặc để nghe nó mặc dù. Một lần nữa, vũ phu của tôi buộc thay đổi với việc tìm kiếm và thay thế tính năng là một chút xấu hổ thô nhưng ít nhất nó hoạt động ...

Sub RegText() 
Dim re As regExp 
Dim para As Paragraph 
Dim rng As Range 
Dim txt As String 
Dim allmatches As MatchCollection, m As match 
Set re = New regExp 
re.pattern = "\bPanama\W+(?:\w+\W+){0,13}?Canal\b" 
re.IgnoreCase = True 
re.Global = True 
For Each para In ActiveDocument.Paragraphs 

    txt = para.Range.Text 

    'any match? 
    If re.Test(txt) Then 
    'get all matches 
    Set allmatches = re.Execute(txt) 
    'look at each match and hilight corresponding range 
    For Each m In allmatches 
     Debug.Print m.Value, m.FirstIndex, m.Length 
     Set rng = para.Range 
     rng.Collapse wdCollapseStart 
     rng.MoveStart wdCharacter, m.FirstIndex 
     rng.MoveEnd wdCharacter, m.Length 
     rng.Font.ColorIndex = wdOrange 
    Next m 
    End If 

Next para 

Selection.Find.ClearFormatting 
Selection.Find.Font.ColorIndex = wdOrange 
Selection.Find.Replacement.ClearFormatting 
Selection.Find.Replacement.Font.Italic = True 
With Selection.Find 
    .Text = "Panama" 
    .Replacement.Text = "Panama" 
    .Forward = True 
    .Wrap = wdFindContinue 
    .Format = True 
    .MatchCase = False 
    .MatchWholeWord = False 
    .MatchWildcards = False 
    .MatchSoundsLike = False 
    .MatchAllWordForms = False 
End With 
Selection.Find.Execute Replace:=wdReplaceAll 
Selection.Find.ClearFormatting 
Selection.Find.Font.ColorIndex = wdOrange 
Selection.Find.Replacement.ClearFormatting 
Selection.Find.Replacement.Font.Italic = True 
With Selection.Find 
    .Text = "Canal" 
    .Replacement.Text = "Canal" 
    .Forward = True 
    .Wrap = wdFindContinue 
    .Format = True 
    .MatchCase = False 
    .MatchWholeWord = False 
    .MatchWildcards = False 
    .MatchSoundsLike = False 
    .MatchAllWordForms = False 
End With 
Selection.Find.Execute Replace:=wdReplaceAll 

Selection.Find.ClearFormatting 
Selection.Find.Font.ColorIndex = wdOrange 
Selection.Find.Replacement.ClearFormatting 
Selection.Find.Replacement.Font.ColorIndex = wdBlack 
With Selection.Find 
    .Text = "" 
    .Replacement.Text = "" 
    .Forward = True 
    .Wrap = wdFindContinue 
    .Format = True 
    .MatchCase = False 
    .MatchWholeWord = False 
    .MatchWildcards = False 
    .MatchSoundsLike = False 
    .MatchAllWordForms = False 
End With 
Selection.Find.Execute Replace:=wdReplaceAll 
End Sub 
+0

Đối tượng đối sánh có thuộc tính Chỉ mục cho bạn biết vị trí trong văn bản khớp xảy ra. Bạn có thể sử dụng nó để xử lý các phạm vi cụ thể để thay đổi định dạng của chúng. Nếu bạn cập nhật câu hỏi của mình để hiển thị mã hiện tại của bạn, ai đó có thể kêu gọi bằng các thay đổi được đề xuất. –

+0

hiển thị cho tôi danh sách các từ bạn đang chạy regex. – jared

+1

Có phải '' từ có nhiều hơn 10 từ'' hoặc '' từ có nhiều hơn 10 chữ cái '' hoặc '' câu có hơn 10 từ'' không? – Cylian

Trả lời

6

tôi là một chặng đường dài là một lập trình viên phong nha, nhưng điều này có thể giúp bạn bắt đầu.

CHỈNH SỬA: được cập nhật để bao gồm phiên bản được tham số hóa.

Sub Tester() 

    HighlightIfClose ActiveDocument, "panama", "canal", wdBrightGreen 
    HighlightIfClose ActiveDocument, "red", "socks", wdRed 

End Sub 


Sub HighlightIfClose(doc As Document, word1 As String, _ 
        word2 As String, clrIndex As WdColorIndex) 
    Dim re As RegExp 
    Dim para As Paragraph 
    Dim rng As Range 
    Dim txt As String 
    Dim allmatches As MatchCollection, m As match 

    Set re = New RegExp 
    re.Pattern = "\b" & word1 & "\W+(?:\w+\W+){0,10}?" _ 
       & word2 & "\b" 
    re.IgnoreCase = True 
    re.Global = True 

    For Each para In ActiveDocument.Paragraphs 

     txt = para.Range.Text 

     'any match? 
     If re.Test(txt) Then 
     'get all matches 
     Set allmatches = re.Execute(txt) 
     'look at each match and hilight corresponding range 
     For Each m In allmatches 
      Debug.Print m.Value, m.FirstIndex, m.Length 
      Set rng = para.Range 
      rng.Collapse wdCollapseStart 
      rng.MoveStart wdCharacter, m.FirstIndex 
      rng.MoveEnd wdCharacter, Len(word1) 
      rng.HighlightColorIndex = clrIndex 
      Set rng = para.Range 
      rng.Collapse wdCollapseStart 
      rng.MoveStart wdCharacter, m.FirstIndex + (m.Length - Len(word2)) 
      rng.MoveEnd wdCharacter, Len(word2) 
      rng.HighlightColorIndex = clrIndex 
     Next m 
     End If 

    Next para 

End Sub 
+0

Việc tìm kiếm văn bản và thay đổi định dạng của nó thật tuyệt vời, vấn đề thực sự tôi gặp phải là tất cả các macro tôi làm chỉ có thể thay đổi toàn bộ cụm từ (thay vì chỉ là từ "panama" và "Canal"). Vì vậy, ví dụ như trên vĩ mô làm nổi bật tất cả các từ trong "Dự án Panama của một kênh" thay vì chỉ 2 và từ cuối cùng của cụm từ đó, nó có thể chỉ là những gì tôi đang cố gắng làm là không thể ... – pavja2

+0

Không không thể: Tôi chỉ không làm toàn bộ điều cho bạn :-) Bạn biết từ đầu tiên sẽ là panama, vì vậy chỉ cần chạng vạng đó (bạn biết nơi nó bắt đầu, và chiều dài của nó). Từ cuối cùng là kênh, vì vậy chỉ cần chạng vạng đó là tốt. Chỉ là toán cơ bản vào thời điểm này ... –

+0

Vâng, tôi thực sự đã tìm ra một cách xung quanh nó - nó không phải là rất duyên dáng nhưng tôi sẽ đăng nó trong câu hỏi ban đầu của tôi một trong tôi nhận được nó làm việc tất cả các cách. Cảm ơn sự giúp đỡ, điều này là khá nhiều chính xác những gì tôi đang tìm kiếm. – pavja2

0

Nếu bạn chỉ sau làm mỗi 2 từ một lần, điều này làm việc cho tôi, theo các dòng thực hành của bạn.

foo([a-zA-Z0-9]+?){0,10}bar 

Giải thích: sẽ lấy từ 1 (foo), sau đó kết hợp bất cứ điều gì đó là một lời ký tự chữ và số ([a-zA-Z0-9]+?) tiếp theo là một không gian (), 10 lần ({0,10}), sau đó từ 2 (bar).

Điều này không bao gồm các điểm dừng đầy đủ (không biết bạn có muốn) hay không, nhưng nếu bạn chỉ muốn thêm . sau 0-9 trong regex.

Vì vậy, (giả) cú pháp của bạn sẽ được tương tự tới:

$matches = preg_match_all(); // Your function to get regex matches in an array 

foreach (those matches) { 
    replace(KEY_WORD, <i>KEY_WORD</i>); 
} 

Hy vọng nó giúp. Kiểm tra dưới đây, đánh dấu những gì nó phù hợp.


Làm việc:

Các foo this that bar blah

Các foo economic order war bar

đã không làm việc

Trình tự kinh tế foo. thanh chiến tranh

Trình tự foo toàn cầu đã được khoảng vài thế kỷ, so với thời gian này mọi người đã tiến hóa các mối quan hệ thương mại khác nhau và phức tạp đối phó với những tình huống như nông nghiệp và quầy bar

+0

Có lẽ tôi chỉ thiếu một cái gì đó, vấn đề của tôi là tôi chỉ có thể thay đổi toàn bộ kết hợp regex (nghĩa là tất cả các từ giữa "foo" và "bar" cũng bị thay đổi). Tôi không biết làm thế nào để có các trận đấu và sau đó chỉ thay đổi các từ "foo" và "bar" mà không ảnh hưởng đến bất kỳ từ nào khác trong văn bản phù hợp. Vấn đề thứ hai là kết quả của việc không có google-fu hay quen thuộc với macro VBA là tôi không biết cách thay đổi định dạng Regexp phù hợp, chỉ cách thay thế nội dung. Tôi đã cập nhật câu hỏi của mình bằng macro mà tôi hiện đang làm việc. – pavja2

Các vấn đề liên quan