您自己的 Word 书签编辑器





5.00/5 (1投票)
用于 Word 报告易于处理的 Word 书签编辑器。
引言
很多人都面临着填写各种报告、时间表和其他各类文件的必要性。这些连续的报告通常只有一些细微的变化,只要文件格式不变,就不会带来太多麻烦。但当你的领导们又一次又一次地随意更改报告格式,而文档内容几乎不变时,就会带来巨大的麻烦。在这种情况下,拥有一个带有内容样本的文档模板,并将其应用于你富有远见的领导提供的任何新格式,可能会很有用。在本文中,我们提供了一个基于Word 书签的 Word 报告便捷处理的完整应用程序。
背景
演示项目WordMark是使用标准的Visual Studio C# Appwizard创建的。它是标准C#教程示例和一些CodeProject文章的集合:《使用 C# 自动处理 Word:以编程方式创建 Word 表格》by koolprasadd,《Word 自动化》by Prathapachandran等。与上述文章的示例不同,WordMark.exe不仅仅是一个演示:它是一个完整的应用程序,任何MS Word用户都可以使用。
在开始构建提供的项目之前,强烈建议您先看一下附带的演示文稿,以便对预期的输出有所了解。
演示说明
可执行文件WordMark.exe是使用MSVS-2015 pro C#构建的。
演示的最简单操作方法如下:
- 调用菜单->文件->打开目标文件;在出现的
FileDialog
中,选择WeeklyReportBlank.doc。 - 调用菜单->文件->打开源文件;在出现的
FileDialog
中,选择WeeklyReportTable.doc。 - 调用菜单->编辑->将源文本应用于目标。
报告文本将从WeeklyReportTable.doc跳转到WeeklyReportBlank.doc中相应的书签处,您可以将结果报告以任何名称保存在任何路径下。
按下“书签组合框”旁边的“BookMarks Combo”按钮,将出现“BookMarks”组合框,您可以浏览目标文档中的书签并选择文本。
当您关闭应用程序并重新启动时,只需取消勾选“可见”复选框,调用相同的命令,然后调用菜单->文件->另存为目标文件并将结果报告保存在任何路径下,并命名为任何名称:如果源文件和目标文件已完全准备好合并,则无需打开文档可见。不用说,源和目标文档都可以通过标准的Word在没有该应用程序的情况下单独准备。
一些菜单和一些特殊的控件处理按键,用于WordMark 应用程序的正确操作
菜单->文件
- 打开目标文件:打开文档文件,用于填充书签文本(前提是文档中已准备好书签)
- 另存为目标文件:将目标文件保存在指定的路径和名称下
- 关闭目标文件:如果文件已更改,会提示保存后关闭
- 打开源文件:打开带有书签标签和文本单元格表的文档文件(前提是表格已准备好)
- 另存为源文件:将源文件保存在指定的路径和名称下
- 关闭源文件:如果文件已更改,会提示保存后关闭
- 退出:关闭应用程序,如果文件已更改,会提示保存后退出
菜单->编辑
- 新建书签:调用“书签名称”对话框,如果点击确定,则在目标文档中出现具有输入名称的新书签
- 删除书签组合框:从目标文档中删除组合框中指定的书签
- 清除书签文本:清除源文档中选定的书签在目标文档中的文本;如果没有选择,则清除所有文本
- 清除书签:从目标文档中移除源文档中选定的书签;如果没有选择,则移除所有书签
- 创建书签表:在源文档中创建带有书签和文本单元格的表格(如果尚未打开,则创建)
- 将源文本应用于目标:将源表格中的文本和字体应用到目标文档中相应的书签处
菜单->帮助
- WordMark 帮助:显示带有当前帮助文本的帮助对话框。
- 关于 WordMark:应用程序版权和许可信息
控件
- “可见”复选框:如果源和目标文件已完全准备好合并,则无需打开文档可见
- “书签组合框”按钮:使“书签”组合框可见
- “书签”组合框:浏览目标文档中的书签并选择文本
- “书签排序->按顺序”单选按钮:按目标文档中的顺序对组合框中的书签进行排序
- “书签排序->按名称”单选按钮:按字母顺序对组合框中的书签进行排序
- “表格行排序->按顺序”单选按钮:按目标文档中的顺序对源文档表格中的书签标签进行排序
- “表格行排序->按名称”单选按钮:按字母顺序对源文档表格中的书签标签进行排序
重要说明
- 一旦文档通过WordMark应用程序打开,就必须通过该应用程序关闭。否则,WordMark应用程序可能会出现问题。
- 如果您在“书签”组合框可见的情况下,使用标准的Word对目标文档中的书签进行了一些更改,只需按“书签组合框”按钮进行同步。
- 如果您在目标文档的某个表格中有选定区域,然后选择菜单->编辑->新建书签,并在“书签名称”对话框中选择确定,则为每个选定的单元格创建新的书签,该书签的名称与表格选定区域左上角的行-列索引一致,并从目标文档的表格选定区域开始。
构建说明
提供的项目是使用MSVS-2015 pro C#在Windows 10和Windows 7上开发的。
从一台计算机迁移到另一台计算机时可能遇到的唯一问题是对Microsoft.Office.Interop.Word
的引用安装。
如果在编译过程中出现Office
和Word
未访问的错误消息,只需在解决方案资源管理器->WordMark上右键单击并安装即可。
代码解释
所有以下的菜单和控件处理命令都是使用标准的MSVS C# AppWizard技术完成的。因此,我认为没有什么比标准教程解释得更清楚的了。我只想提几点我没有在教程中找到,而是通过反复试验自己发现的。
在这里,我必须承认这是我第一次接触 C#。因此,我的一些论断对于老练的人来说可能显得很奇怪。我很乐意阅读任何评论和建议。
1. 表格单元格中的文本
表格
的单元格
中的文本
以两个字节结尾:'\13' 和 '\7'。即使单元格
看起来是空的,这两个字节也存在。因此,如果从表格的单元格
借用的文本
必须在两个字节处截断
private bool ApplyTextAtBookmarkFromRow(int iRow) { Word.Table TableSrc = (Word.Table)docSrc.Tables[1]; //Select Table of Source Doc string strB = TableSrc.Cell(iRow, 1).Range.Text; //Name of the Bookmark in row specified strB = strB.Substring(0, strB.Length - 2); //Name cut with two bytes string strT = TableSrc.Cell(iRow, 2).Range.Text; //Text of the Bookmark in row specified strT = strT.Substring(0, strT.Length - 2); //Text cut with two bytes //Pick up the Font of the Cell: Microsoft.Office.Interop.Word.Font fontSrc = TableSrc.Cell(iRow, 2).Range.Font; Word.Bookmark bmk = docTgt.Bookmarks[strB]; //Select Bookmark in Target doc if( ApplyTextAtBookmark(bmk, strT, fontSrc) == false) //Replace the text in the BookMark return false; return true; }
此外,拥有一个函数来识别文本
是否属于某个表格的单元格
也很有用
private bool IsTextOfTable( string strN) { if (strN.Length < 2) //If Text in Cell at least 2 bites present return false; string strA = strN.Substring(strN.Length - 2);//2 last symbols borrowed byte[] bytes = Encoding.ASCII.GetBytes(strA); //convert to bites return bytes[0] == 13 && bytes[1] == 7; //true if bites 13 & 7 }
以及一个函数来识别 书签
是否属于某个表格的单元格
private bool IsBookMarkOfTable( Word.Bookmark bmk) { bool bTable = false; try { bTable = bmk.Range.Cells.Count > 0; } catch { bTable = false; } return bTable; }
2. 书签文本替换
在指定的书签
处进行文本
替换过程在WordMark项目中也有一些细节
private bool ApplyTextAtBookmark(Word.Bookmark bmk, string strSrc, Microsoft.Office.Interop.Word.Font fontSrc) { if (bmk == null) //if no Bookmark - nothing to do return false; bool bTable = IsBookMarkOfTable(bmk); //Flag of Bookmark in the Table's Cell int nSrc = strSrc.Length; //Length of the Source Text string strTgt = ""; //Text at the Bookmark if (bmk.Range.Text != null) strTgt = bmk.Range.Text; //Text at the Bookmark if (nSrc == 0) { strSrc = " "; //if Source Text empty assum as white space nSrc = strSrc.Length; } string strB = bmk.Name; //Remember the name of the Bookmark if (bmk.Range.Text == null) //if Bookmark Text not exist assum as white space bmk.Range.Text = " "; int nTgt = bmk.Range.Text.Length; //Length of the Bookmark Text int nDif = nSrc - nTgt; //Difference between Source and Bookmark Text length if (!bTable) //if Bookmark not in Table if (nDif < 0) //if Source Text shorter then BookMarks one for (int k = 0; k < -nDif; k++) strSrc += " "; //append white space until equal nSrc = strSrc.Length; //Length of the Source Text object bgnA = bmk.Start; //Range Start object finA = bmk.Start + nSrc; //Range End bmk.Range.Text = strSrc; //Replace the Text in BookMark Word.Range rgA = docTgt.Range(ref bgnA, ref finA);//new Range fixed rgA.Select(); //Select new Range rgA.Font = fontSrc; //Apply Font to Range object rng = appWord.Selection.Range; //Select new Range //new Bookmark with the same Name fixed: Word.Bookmark bkmr = docTgt.Bookmarks.Add(strB, ref rng); if (bTable == false) //if Bookmark not in Table if (nDif > 0) //if New Text is longer then the old one { object bgn = bkmr.Range.Start + nSrc + 1; //go to end of new Text object fin = bkmr.Range.Start + nSrc + nDif + 1;//go to end + difference Word.Range rg = docTgt.Range(ref bgn, ref fin);//fix range from end to diffence len string strf = rg.Text; //Pick up text from difference Range int nBreak = strf.IndexOf("\n"); //End of line if (nBreak > 0) { strf = strf.Substring(0, nBreak - 1); while (strf.Substring(0, 1) == " " || strf.Substring(0, 1) == "_" && strf.Length > 1) { strf = strf.Substring(1);//while first simbol is empty cut first simbol } rg.Text = strf; //apply the text cut at the end of new Text } } return true; }
请注意,所有这些关于旧文本和新文本
长度差异的调整都是为了保持文本
和环境的位置不变(你的领导认为保持他们明智的文档格式不变是绝对必要的)。
3. 表格中的多个书签初始化
作者还开发了在表格
中进行多个书签
初始化的功能,这可能对开发人员有益
private void MenuNewBookMark_Click(object sender, EventArgs e) { if (w.ShowDialog() == DialogResult.OK) //new Bookmark Name Ok { int nCel = 0; //Number of Cells selected if (appWord.Selection.Tables.Count > 0) nCel = appWord.Selection.Cells.Count; //Number of Cells selected if (nCel < 2) //if no Cells or Single Cell just append new BookMark docTgt.Bookmarks.Add(w.textBox1.Text, appWord.Selection.Range); else { Word.Table tbl = appWord.Selection.Tables[1]; //Table selected //TopLeft corner of Selection Row index: int rowStart = appWord.Selection.Cells[1].Row.Index; //TopLeft corner of Selection Column index: int colStart = appWord.Selection.Cells[1].Column.Index; //RightBottom corner of Selection Row index: int rowFin = appWord.Selection.Cells[appWord.Selection.Cells.Count].Row.Index; //RightBottom corner of Selection Column index: int colFin = appWord.Selection.Cells[appWord.Selection.Cells.Count].Column.Index; for (int i = rowStart; i <= rowFin; i++) //for each row selected for (int j = colStart; j <= colFin; j++) //for each column selected { tbl.Cell(i, j).Range.Select(); //Select Range of the cell int ri = i - rowStart + 1; //row index int ci = j - colStart + 1; //column index //Append new Bookmark indexed: docTgt.Bookmarks.Add(w.textBox1.Text + "_" + ri.ToString("00") + "_" + ci.ToString("00")); } } if (comboBox1.Visible) //if 'BookMarks' Combo Box is visible { button1_Click(sender, e); //synchronize Combo Box Content int index = comboBox1.FindString(w.textBox1.Text); //index of Name typed //in Dialog Box comboBox1.SelectedIndex = index; //select item with the Name typed //in Dialog Box } } }
应用程序处理和使用提供的项目进行您自己的应用程序开发
WordMark.exe应用程序对于任何稍微熟悉Word 书签的用户来说都易于操作。不需要任何编程技能。
您可以获取整个项目,重命名它,并随意组合和改进代码。
或者,您可以获取其中包含的任何过程文件,并通过菜单项目->现有项将其插入到任何您自己的 C# 项目中。
如果您引用了我的代码,将不胜感激。
关注点
我相信这个应用程序和代码对于处理文档的软件人员应该有所帮助。
其想法是开发一套程序,用于处理你上司提供的Word和Excel文档表格,以完成大量文书工作。
我相信,通过安排让计算机能够打出海量文件,让高层人士满意是可能的。
历史
故事才刚刚开始。