C#使用Word Interop按分组动态创建多个Word表格的实现问题
Word Interop 动态按分组生成多表格并追加行实现方案
前置说明:从JavaScript转做C#开发,此前从未接触过Word Interop,若存在低级错误还请谅解。
需求描述
基于单个List生成一系列Word表格:每当遍历到TableName字段的新值时就新建一个表格,后续同TableName的记录持续向当前已创建的对应表格追加行,直到遇到下一个新的TableName值为止。
初始实现代码
using Word = Microsoft.Office.Interop.Word; Word._Application oWord; Word._Document oDoc; object oMissing = System.Reflection.Missing.Value; object oTemplate = //Location of Template file in my Local drive int i = 0; for (int j = 0; j < TableList.Count; j++) { if (TableList[j].TableName != tableHolder) { i++; tableHolder = TableList[j].TableName; oDoc.Tables.Add(wrdRng, 1, 6, ref oMissing, ref oMissing); Word.Table oTable = oDoc.Tables[i]; oTable.Borders.InsideLineStyle = Word.WdLineStyle.wdLineStyleSingle; oTable.Borders.OutsideLineStyle = Word.WdLineStyle.wdLineStyleSingle; //Adding values to individual cells here wrdRng = oDoc.Tables[i].Range; wrdRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd); wrdRng.InsertParagraphAfter(); wrdRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd); } else { //add rows to Tables[i] } }
问题根因
判断方向是对的,靠自增索引i取oDoc.Tables[i]的写法非常容易出问题:
- 文档结构发生变动(插入段落、新增表格、删除内容)时,表格集合的索引会同步变化,手动计数很容易错位
- 初始代码没有持有新建表格的直接引用,每次靠索引查找性能差还不稳定
- Range定位逻辑没有和表格对象绑定,后续追加内容容易插到错误的位置
修复后可运行代码
直接用字典存储表名和对应表格对象的映射,完全抛弃手动索引计数,Tables.Add方法会直接返回新建的表格对象,直接持有引用操作即可:
using Word = Microsoft.Office.Interop.Word; Word._Application oWord = new Word.Application(); Word._Document oDoc; object oMissing = System.Reflection.Missing.Value; object oTemplate = // 本地模板文件路径 oDoc = oWord.Documents.Add(ref oTemplate, ref oMissing, ref oMissing, ref oMissing); Word.Range wrdRng = oDoc.Content; // 存储表名和表格对象的映射,不需要手动维护索引 Dictionary<string, Word.Table> tableMapping = new Dictionary<string, Word.Table>(); string currentTableKey = string.Empty; for (int j = 0; j < TableList.Count; j++) { var dataItem = TableList[j]; if (dataItem.TableName != currentTableKey) { currentTableKey = dataItem.TableName; // 光标折叠到文档末尾,避免新表格插入到旧内容中间 wrdRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd); // Add方法直接返回新创建的表格对象,直接存入字典 Word.Table newTable = oDoc.Tables.Add(wrdRng, 1, 6, ref oMissing, ref oMissing); newTable.Borders.InsideLineStyle = Word.WdLineStyle.wdLineStyleSingle; newTable.Borders.OutsideLineStyle = Word.WdLineStyle.wdLineStyleSingle; // 此处给新表格首行单元格赋值即可,示例: // newTable.Rows[1].Cells[1].Range.Text = dataItem.对应字段名; tableMapping.Add(currentTableKey, newTable); // 表格创建完成后,将光标移到表格后方,插入段落分隔,避免后续表格和当前表粘连 wrdRng = newTable.Range; wrdRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd); wrdRng.InsertParagraphAfter(); wrdRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd); } else { // 直接从字典取当前需要操作的表格,不需要通过索引查找 Word.Table targetTable = tableMapping[currentTableKey]; // 追加新行 Word.Row addRow = targetTable.Rows.Add(ref oMissing); // 给新行单元格赋值,示例: // addRow.Cells[1].Range.Text = dataItem.对应字段名; } } // 注意:使用完成后需要按创建顺序逆序释放所有COM对象,避免后台残留WINWORD进程
额外注意点
- 动态生成不确定数量的表格完全可以实现,不需要提前知道表格总数
- 不要依赖文档元素的索引做定位,新建元素时直接接住返回的对象引用操作是最稳定的写法
- 所有Range操作完成后必须折叠到对应方向的末尾,否则会覆盖原有内容
- 如果表名对比需要忽略大小写,将判断条件替换为
!string.Equals(dataItem.TableName, currentTableKey, StringComparison.OrdinalIgnoreCase)即可
内容的提问来源于stack exchange,提问作者profiter
相关产品推荐
相关产品推荐

