Word自动化循环操作报错:多数据行导出问题咨询
问题分析与解决方法
你的代码核心问题是逻辑顺序完全颠倒:你在遍历每个Word合并字段时,反复查询数据库并循环所有数据行,这会导致第一个字段写完所有行数据后,后续字段再读取数据时reader已经处于末尾,触发读取错误。正确的逻辑应该是先读取所有数据库数据,再针对每一行数据,基于模板生成对应的Word内容并填充字段。
修正后的代码
using System; using System.Data.OleDb; using System.Windows.Forms; using Word = Microsoft.Office.Interop.Word; public void ExportToWord() { Object oMissing = System.Reflection.Missing.Value; Word.Application oWord = new Word.Application(); oWord.Visible = true; string templatePath = Application.StartupPath + "\\GeziListesi.docx"; // 一次性读取所有数据库数据 using (OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=gezievrak2541.mdb; Mode = ReadWrite")) { conn.Open(); using (OleDbCommand cmd = new OleDbCommand("Select * from gezibilgileri25", conn)) { using (OleDbDataReader dr = cmd.ExecuteReader()) { // 遍历每一行数据 while (dr.Read()) { // 基于模板新建文档副本 Word.Document oWordDoc = oWord.Documents.Add(ref templatePath, ref oMissing, ref oMissing, ref oMissing); // 遍历文档合并字段,填充当前行数据 foreach (Word.Field myMergeField in oWordDoc.Fields) { Word.Range rngFieldCode = myMergeField.Code; string fieldText = rngFieldCode.Text; if (fieldText.StartsWith(" MERGEFIELD")) { int endMerge = fieldText.IndexOf("\\"); string fieldName = fieldText.Substring(11, endMerge - 11).Trim(); switch (fieldName) { case "tcno": myMergeField.Select(); oWord.Selection.TypeText(dr["tcno"].ToString()); break; case "adsoyad": myMergeField.Select(); oWord.Selection.TypeText($"{dr["adi"]} {dr["soyadi"]}"); break; case "sinifi": myMergeField.Select(); oWord.Selection.TypeText(dr["sinifi"].ToString()); break; case "unvan": myMergeField.Select(); oWord.Selection.TypeText(dr["unvani"].ToString()); break; } } } } } } } // 清理COM对象,避免内存泄漏 GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); }
关键改动说明
- 逻辑顺序调整:先读取全量数据库数据,再逐行处理,每行对应一份模板文档,彻底避免reader越界问题。
- 资源优化:数据库连接、命令仅初始化一次,减少重复连接的开销和资源浪费。
- 代码简化:用
switch替代多分支if,字段匹配逻辑更清晰易维护。 - 避免重复写入:每个合并字段仅填充当前行的对应数据,不会出现同一字段重复写入所有行内容的错误。
额外优化建议
如果需要将所有数据导出到同一个Word文档,可以修改逻辑:打开一份模板文档后,每处理完一行数据就插入分页,复制模板内容到新页面,再填充下一行数据。
内容的提问来源于stack exchange,提问作者user17750070
相关产品推荐
相关产品推荐

