Связывание строки в надстройке Word VSTO Word.interop 2 - PullRequest
0 голосов
/ 10 октября 2019

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

using Word = Microsoft.Office.Interop.Word;

private Word.Range FindAndReplace(Word.Range rngToSearch, object findText, object replaceWithText)
        {
            bool found = false;
            //options
            object matchCase = false;
            object matchWholeWord = true;
            object matchWildCards = true;
            object matchSoundsLike = false;
            object matchAllWordForms = false;
            object forward = true;
            object format = false;
            object matchKashida = false;                     
            object matchDiacritics = false;
            object matchAlefHamza = false;
            object matchControl = false;
            object read_only = false;
            object visible = true;
            object replace = false;
            object wrap = 1;

            //execute find and replace
            found = rngToSearch.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
                ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
                ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl);
          if (!found)
          {
            rngToSearch = null;
          }

          return rngToSearch;
        }

        private void Button3_Click(object sender, RibbonControlEventArgs e)
        {
            Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;
            Word.Range rng = doc.Content;
            string searchTerm = @"<[0-9]-[0-9]{1;}-[0-9]{1;}/[0-9]{1;}>";
            string hyperlink = "";  //put your hyperlink stuff here

            foreach (Word.Paragraph paragraph in doc.Paragraphs)
            {
                Word.Range rngFound = FindAndReplace(rng, searchTerm, ""); //searching and wrapping.

                if (rngFound != null)
                {
                Word.Hyperlink hp = (Word.Hyperlink)
                    rngFound.Hyperlinks.Add(rngFound, hyperlink + rngFound.Text);
                }
            }
 }

1) Я устал: foreach (Word.Range docRange in doc.Words) {Word.Range rngFound = FindAndReplace(docRange, searchTerm, "") Требуются слова одно за другим. И это очень медленно. 2) Также пытался использовать выделение:

private Word.Selection FindAndReplace(Word.Selection rngToSearch, object findText, object replaceWithText)
        {
-----------------------------------------------------------------------------
foreach (Word.Paragraph paragraph in doc.Paragraphs)
            {
                Word.Selection rngFound = FindAndReplace(app.Selection, searchTerm, ""); //searching and wrapping. 

               rngFound.Range.Hyperlinks.Add(rngFound.Range, hyperlink + rngFound.Text);

Но теперь он делает одно слово одним щелчком мыши. И в конце концов я решил это с помощью этого метода. Посмотрите на мой последний комментарий.

3) Я также попробовал:

foreach (Word.Paragraph paragraph in doc.Paragraphs)
                {
                    Word.Range rngFound = FindAndReplace(paragraph.Range, searchTerm, ""); //searching and wrapping.

                    if (rngFound != null)
                    {
                    Word.Hyperlink hp = (Word.Hyperlink)
                        rngFound.Hyperlinks.Add(rngFound, hyperlink + rngFound.Text);
                    }

И он работает с первыми словами в абзацах.

Что мне нужно сделатьзапустить его во всем моем диапазоне документов.

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Причиной того, что код возвращает «нечетные» результаты, является установка свойства для параметра Find.Wrap. Это было установлено на 1, что эквивалентно перечислению wdFindcontinue. Это никогда не должно использоваться в коде для функциональности Word Find, поскольку это заставляет код продолжать цикл до тех пор, пока искомый объект не будет "найден". Если он не может быть найден, код переходит в «бесконечный цикл».

Как правило, требуется: 0, wdFindStop, что означает, что поиск начинается в начале указанного поиска Range и продолжается до конечной точки этого диапазона, затем останавливается.

Поэтому измените эту строку:

object wrap = 1;

на:

object wrap = Word.WdFindWrap.wdFindStop;  //or 0

Я настоятельно рекомендую использовать полное перечисление, а не эквивалент int, если нет явной причиныне делать этого. (Поздняя привязка / PInvoke была бы такой причиной.) Если ничего другого, это делает код намного проще для чтения и понимания, как показывает эта проблема.

С этим исправлением у меня работает следующий тестовый код,Я публикую это, чтобы показать, что устранение неполадок с помощью System.Diagnotics.Debug.Print помогло мне отследить проблему: я мог сравнить каждый paragraph в цикле с тем, что возвращал rngFound.Text.

       Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;
        Word.Range rng = doc.Content;
        string searchTerm = @"<[0-9]-[0-9]{1;}-[0-9]{1;}/[0-9]{1;}>";
        string hyperlink = "";  //put your hyperlink stuff here

        foreach (Word.Paragraph paragraph in doc.Paragraphs)
        {
            rng = paragraph.Range;
            System.Diagnostics.Debug.Print(rng.Text);  
            Word.Range rngFound = FindAndReplace(rng, searchTerm, ""); //searching and wrapping.

            if (rngFound != null)
            {
            //Word.Hyperlink hp = (Word.Hyperlink)
            System.Diagnostics.Debug.Print(rngFound.Text);
            }
        }
0 голосов
/ 11 октября 2019

Спасибо. В конце у меня есть>

Word.Selection FindAndReplace(Word.Selection rngToSearch, object findText, object replaceWithText) //funcija poiska 4erez range
        {
            bool found = false;
            //options
            object matchCase = false;
            object matchWholeWord = true;
            object matchWildCards = true;
            object matchSoundsLike = false;
            object matchAllWordForms = false;  
            object forward = true;
            object format = false;
            object matchKashida = false;
            object matchDiacritics = false;
            object matchAlefHamza = false;
            object matchControl = false;
            object read_only = false;
            object visible = true;
            object replace = false;
            object wrap = Word.WdFindWrap.wdFindStop;;

            //execute find and replace
            found = rngToSearch.Find.Execute(ref findText, ref matchCase, ref matchWholeWord,
                ref matchWildCards, ref matchSoundsLike, ref matchAllWordForms, ref forward, ref wrap, ref format, ref replaceWithText, ref replace,
                ref matchKashida, ref matchDiacritics, ref matchAlefHamza, ref matchControl);
            if (!found)
            {
                rngToSearch = null;
            }

            return rngToSearch;
        }

        private void Button3_Click(object sender, RibbonControlEventArgs e)
        {
            int WordsCount = 0;

            int counter = 0;
            Word.Application app = Globals.ThisAddIn.Application;
            Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;
            Word.Range rng = doc.Content;
            string searchTerm = @"<[0-9]-[0-9]{1;}-[0-9]{1;}/[0-9]{1;}>";
            string hyperlink = "google.com";  //
            string s = rng.Text; // Pushing doc text to the string
            Regex regex = new Regex(@"\d*-\d*-\d*/\d*"); 
            WordsCount = regex.Matches(s).Count; // Using regex getting count of searchable words 





            while (WordsCount >= counter ) // knowing count of words we know how much iterations we need to do.  
                foreach (Word.Section paragraph in doc.Sections)
            {
                    Word.Selection rngFound = FindAndReplace(app.Selection, searchTerm, ""); //searching and wrapping.

                    if (rngFound != null)
                {

                        rngFound.Range.Hyperlinks.Add(rngFound.Range, hyperlink + rngFound.Text);

                }counter++; // counting iterations


                }
        }

И это работает. Спасибо, Синди, за твой добрый совет.

...