我在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#代码吗?
答案 0 :(得分:0)
用C#编码的两个函数可以完成我需要的工作。使用了几天,发现我更喜欢使用这些功能,而不是Word的默认GUI方法。 (这更像是使用LaTeX,尽管我知道这并不适合每个人。)还将我从Word的本地安装中解放出来,并允许我使用Word在线(因此可以使用Chromebook或手机)为稿件编制索引。
对于任何有兴趣的人,下面的代码。它以{{XE "foo" \r "bar"}}
{{BEGIN "bar"}}
和{{END "bar"}}
的形式识别键,其中BEGIN
和END
表示书签的开头和结尾。 (索引标记中的书签是可选的)。它执行一些简单的错误检查,并且在间隔上有点挑剔(不想在{{
和关键字之间,也不想在}}
之前
将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");
}
}
}