在MS Word Online中添加书签和索引标记的VBA / C#解决方法?

时间:2018-07-26 15:40:58

标签: vba ms-word

我在Windows 10中安装了MS Word,但通常在Chrome中使用Word Online编辑稿件。效果很好,但是现在我需要创建一个索引,因此需要添加索引标记和书签(我正在使用后者是为索引标记指定范围)。

除非我丢失了某些内容,否则Word Online不支持创建这些标记,因此,我认为我可以在Chrome中进行编辑时插入特殊的文本来标识标记,而下次我在Windows 10上时,请使用VBA宏以搜索此特殊文本并将其替换为标记。

我想这两个标记都将使用大括号来标识要转换的文本。以下是示例文本,显示了将触发单个标记,带有范围的标记和书签的插入:

Lorem ipsum ultricies sodales magna{{XE magna}} class sit aliquam nisl, 
aptent curabitur{{XE curabitur /r end_xe1}} urna mollis aliquam urna 
aenean sollicitudin, donec elementum class porta tortor ultricies nullam 
aliquet donec tincidunt pretium ipsum magna blandit quam.{{BM end_xe1}}

因此,宏将搜索文本以定义{{XE "foo" \r "bar"}}{{BEGIN "bar"}}{{END "bar"}}形式的书签,并用索引标记(有些带有范围)和书签替换关联的文本。

在我深入研究之前,我的问题是(1)这是在使用Chrome编辑时将索引标记和书签插入Word文档的最佳方法,还是更好的设计或现有的解决方案? (2)如果不是,那么有人可以指向一些完成上述部分或全部操作的VBA / C#代码吗?

1 个答案:

答案 0 :(得分:0)

用C#编码的两个函数可以完成我需要的工作。使用了几天,发现我更喜欢使用这些功能,而不是Word的默认GUI方法。 (这更像是使用LaTeX,尽管我知道这并不适合每个人。)还将我从Word的本地安装中解放出来,并允许我使用Word在线(因此可以使用Chromebook或手机)为稿件编制索引。

对于任何有兴趣的人,下面的代码。它以{{XE "foo" \r "bar"}} {{BEGIN "bar"}}{{END "bar"}}的形式识别键,其中BEGINEND表示书签的开头和结尾。 (索引标记中的书签是可选的)。它执行一些简单的错误检查,并且在间隔上有点挑剔(不想在{{和关键字之间,也不想在}}之前

将Word书签和索引标记转换为文本键的功能:

private void MarksToText(object sender, RoutedEventArgs e)
{
    bool isWordRunning = true;
    try
    {
        object o = System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
    }
    catch (Exception)
    {
        MessageBox.Show("Word is not running");
        isWordRunning = false;
    }

    if (isWordRunning)
    {
        Microsoft.Office.Interop.Word.Application application =
            (Microsoft.Office.Interop.Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");

        if (application == null || application.Documents.Count == 0)
        {
            MessageBox.Show("Word is running but no open document found");
        }
        else
        {
            Document document = application.ActiveDocument;
            MessageBox.Show("Converting " + document.Name);

            // convert bookmarks
            int bmCount = 0;
            int xeCount = 0;
            foreach (Bookmark bm in document.Bookmarks)
            {
                bm.Range.InsertBefore("{{BEGIN \"" + bm.Name + "\"}}");
                bm.Range.InsertAfter("{{END \"" + bm.Name + "\"}}");
                bm.Delete();
                bmCount++;
            }

            // convert index marks
            foreach (Field f in document.Fields)
            {
                if (f.Type == WdFieldType.wdFieldIndexEntry)
                {
                    Microsoft.Office.Interop.Word.Range rngField = f.Code;
                    rngField.Collapse(WdCollapseDirection.wdCollapseEnd);
                    rngField.MoveStart(WdUnits.wdCharacter, 1);
                    string s = @"{{";
                    s += f.Code.Text.ToString().Trim();
                    s += @"}}";
                    rngField.InsertAfter(s);
                    f.Delete();
                    xeCount++;
                }
            }
            MessageBox.Show(@"Converted (" + bmCount + ") bookmarks, (" + xeCount + ") index marks");
        }
    }
}

将文本键转换为Word书签和索引标记的功能:

private void TextToMarks(object sender, RoutedEventArgs e)
{
    bool isWordRunning = true;
    try
    {
        object o = System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
    }
    catch (Exception)
    {
        MessageBox.Show("Word is not running");
        isWordRunning = false;
    }

    if (isWordRunning)
    {
        Microsoft.Office.Interop.Word.Application application =
            (Microsoft.Office.Interop.Word.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");

        if (application == null || application.Documents.Count == 0)
        {
            MessageBox.Show("Word is running but no open document found");
        }
        else
        {
            Document document = application.ActiveDocument;
            MessageBox.Show("Converting " + document.Name);

            Selection sel = application.Selection;
            sel.Find.ClearFormatting();
            sel.Find.MatchWildcards = true;
            // sel.Find.Wrap = wdFindContinue; // VBA
            sel.Find.Forward = true;

            // convert two text blocks {{BEGIN "foo"}} and {{END "foo"}} into Word bookmarks
            int bmCount = 0;
            int xeCount = 0;
            List<string> bookmarks = new List<string>();
            List<string> bookmarksReferenced = new List<string>();
            bool isOK;  // while-loop flag
            do
            {
                isOK = false;

                sel.SetRange(document.Content.Start, document.Content.End);
                sel.Find.Text = @"\{\{?@\}\}";
                sel.Find.Execute();

                if (sel.Find.Found)
                {
                    //delete the brackets and trim leading and trailing whitespace
                    string cmd = sel.Text.Replace(@"{{", string.Empty);
                    cmd = cmd.Replace(@"}}", string.Empty);
                    cmd.Trim();

                    string[] tokens = cmd.Split(' ');

                    if (tokens[0] == "BEGIN")
                    {

                        string bmName = Regex.Replace(tokens[1], "[\u0022\u0027\u2018\u2019\u201C\u201D\u201E]", string.Empty);
                        bookmarks.Add(bmName);

                        sel.SetRange(document.Content.Start, document.Content.End);
                        // using '?' instead of '"' b/c of the different types of quotes
                        sel.Find.Text = @"\{\{BEGIN ?" + bmName + @"?\}\}?@\{\{END ?" + bmName + @"?\}\}";
                        sel.Find.Execute();
                        if (sel.Find.Found)
                        {
                            sel.Bookmarks.Add(bmName);

                            sel.SetRange(document.Content.Start, document.Content.End);

                            // remove tag text
                            sel.Find.Text = @"\{\{BEGIN ?" + bmName + @"?\}\}";
                            sel.Find.Execute();
                            if (sel.Find.Found)
                                sel.Range.Text = "";
                            sel.Find.Text = @"\{\{END ?" + bmName + @"?\}\}";
                            sel.Find.Execute();
                            if (sel.Find.Found)
                                sel.Range.Text = "";
                            bmCount++;
                            isOK = true;
                        }
                        if (!isOK)
                            MessageBox.Show(@"Error processing {{" + cmd + @"}}. Maybe no matching {{END?");
                    }
                    else if (tokens[0] == "XE")
                    {
                        cmd = cmd.Substring(cmd.IndexOf(" ") + 1);
                        cmd.Trim();

                        // remove quotes
                        cmd = Regex.Replace(cmd, "[\u0022\u0027\u2018\u2019\u201C\u201D\u201E]", "");

                        // if refs a bookmark
                        string bookmarkParam = @" \r ";
                        if (cmd.Contains(bookmarkParam))
                        {
                            string[] entryAndBookmark = cmd.Split(new[] { bookmarkParam }, StringSplitOptions.None);
                            entryAndBookmark[0].Trim();
                            entryAndBookmark[1].Trim();
                            document.Indexes.MarkEntry(sel.Range, Entry: entryAndBookmark[0], BookmarkName: entryAndBookmark[1]);
                            bookmarksReferenced.Add(entryAndBookmark[1]);
                        }
                        else // does not ref a bookmark
                        {
                            document.Indexes.MarkEntry(sel.Range, Entry: cmd);
                        }
                        sel.Range.Text = "";
                        xeCount++;
                        isOK = true;
                    }
                }
            } while (isOK);

            // see if any double curly braces were not processed
            sel.SetRange(document.Content.Start, document.Content.End);
            sel.Find.Text = @"\{\{";
            sel.Find.Execute();
            if (sel.Find.Found)
                MessageBox.Show(@"Error: double braces '{{' skipped. Maybe followed by space? Spaces are not allowed " +
                    @"between braces and commend (E.g., must be '{{BEGIN ""blah""}}'. Or maybe missing closing double braces?");

            // check for missing bookmarks
            foreach (var bm in bookmarksReferenced)
                if (bookmarks.Contains(bm) == false)
                    MessageBox.Show(@"Mark missing bookmark """ + bm + @"""");

            // check for missing marks
            foreach (var bm in bookmarks)
                if (bookmarksReferenced.Contains(bm) == false)
                    MessageBox.Show(@"Bookmark missing index mark""" + bm + @"""");

            // give totals
            MessageBox.Show(@"Converted (" + bmCount + ") bookmarks, (" + xeCount + ") index marks");
        }
    }
}