试图弄清楚为什么 for each 语句与 if 语句一起工作,但是当我将它切换到 for 循环时抛出异常

trying to figure out why a for each statement worked with an if statement, but throws an exception when i switch it to a for loop

提前抱歉,因为我在 VB 年前才使用 C# 工作了大约一个月,历史有限。这是我试图为工作创建的一种邮件合并循环,让他们的生活更轻松。我已经弄清楚日期了。我有一个 NumUpDown 控件设置 int myInt 和一个从 0 开始的 formCount int。 当我将 if(formCount==0), 切换为

时,代码运行良好
for(formCount=0;formCount<myInt;formCount++)

它现在抛出一个

"System.NullReferenceException: 'Object reference not set to an instance of an object.'"

我知道可能还有另一种方法可以完成我正在做的事情,即一次只将连续日期添加到表格中一个月。我将日期存储在数组 myDate[31].

我正在使用 numUpDwn(min 1 max 31) 获取 myInt 这样我们就可以 select 这个月有多少天,或者如果我们需要更换页面则只打印几天,所以我们可以打印 1 到 31 页。

使用 if 语句,它将从模板创建第一个页面 (.dotx)doc(var) 将 doc 的内容复制到 doc2 并添加一个新页面以接收下一个内容粘贴。

我相信这是一个愚蠢的问题,有人也会有一个简单的答案。循环应该打开模板,添加日期,复制到 doc2。关闭原来的,然后重新启动,直到达到 pages/dates selected 的数量。感谢您的帮助,这是我需要完成的最后一部分,我很困惑。哦,我使用 != 是因为它跳过了合并字段,但只有 1 个字段不等于任何有效的字段。

private void BtnPrint_Click(object sender, EventArgs e)
       {
           var app = new Microsoft.Office.Interop.Word.Application();
           var doc = new Microsoft.Office.Interop.Word.Document();
           var doc2 = new Microsoft.Office.Interop.Word.Document();
           //app.Visible = true;
           doc = null;
           doc2.PageSetup.Orientation = WdOrientation.wdOrientLandscape;
           doc2.PageSetup.TopMargin = app.InchesToPoints(0.6f);
           doc2.PageSetup.BottomMargin = app.InchesToPoints(0.17f);
           doc2.PageSetup.LeftMargin = app.InchesToPoints(0.5f);
           doc2.PageSetup.RightMargin = app.InchesToPoints(0.5f);
           String fileSave;
           fileSave = ("OTSU" + "_" + myDate[0].Month + "_" + myDate[0].Year + ".docx");
           
           
           int formCount;
           //formCount = 0;
           var filepath = System.Windows.Forms.Application.StartupPath + outfile;
           doc = app.Documents.Add(filepath);
           
           doc2.Activate();
           //OBJECT OF MISSING "NULL VALUE"
           Object oMissing = System.Reflection.Missing.Value;
           for (formCount = 0; formCount<myInt;formCount++)
           {
               doc.Activate();

               foreach (Microsoft.Office.Interop.Word.Field field in doc.Fields)
               {

                   Range rngFieldCode = field.Code;
                   String fieldText = rngFieldCode.Text;
                   // ONLY GETTING THE MAILMERGE FIELDS
                   if (fieldText.StartsWith(" MERGEFIELD"))
                   {
                       Int32 endMerge = fieldText.IndexOf("\");
                       Int32 fieldNameLength = fieldText.Length - endMerge;
                       String fieldName = fieldText.Substring(11);
                       // GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dotx FILE
                       fieldName = fieldName.Trim();
                       if (fieldName != "M_2nd__3rd")
                       {
                           field.Select();
                           app.Selection.TypeText(myDate[formCount].ToShortDateString());
                       }
                       formCount++;
                       Microsoft.Office.Interop.Word.Range dRange = doc.Content;
                       dRange.Copy();
                       
                       doc2.Range(doc2.Content.End - 1, doc2.Content.End - 1).PasteSpecial(DataType: Microsoft.Office.Interop.Word.WdPasteOptions.wdKeepSourceFormatting);
                       doc2.Range(doc2.Content.End - 1, doc2.Content.End - 1).InsertBreak(Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak);
                       Clipboard.Clear();
                       doc.Close(WdSaveOptions.wdDoNotSaveChanges);
                   }

               }
           }
           doc2.SaveAs2("OTSU" + myDate[0].Month + "_" + myDate[0].Year + ".docx");
           app.Documents.Open("OTSU" + myDate[0].Month + "_" + myDate[0].Year + ".docx");
           doc.Close(WdSaveOptions.wdDoNotSaveChanges);
           doc2.Close(WdSaveOptions.wdDoNotSaveChanges);


我没有 运行 你的代码,但据我所知,在你有多个 MERGEFIELD 字段的情况下,即使没有 formcount 循环,这段代码也可能会失败,因为你关闭了 doc 一旦您处理了这样一个字段,而 foreach 循环正在处理 doc.Fields 中的每个字段。

即使该 foreach 循环正常终止,在您使用 doc.Activate() 的 formCount 循环的下一次迭代中,但 doc 已关闭,因此将失败。

所以我建议主要做的事情是考虑需要在什么时候打开哪些文档才能使流程正常工作。

一些观察(不一定与您的主要问题有关)

  • myInt 设置在哪里?
  • 有一个 formCount++ 循环 在循环中为 doc 中的每个 MERGEFIELD 使用 formCount++ 真的是你的意图吗?
  • 在过滤 MAILMERGE 字段而不是匹配文本时测试 field.Type() 可能会更好,至少如果这些字段可以由最终用户设置的话
  • 当您在 Word 中处理集合并添加或删除集合成员时,有时您必须考虑使用从集合的最后一个成员开始并返回到开头的循环。不确定在这种情况下是否需要这样做,但由于在执行 field.Select 然后 Typetext 时可能会“删除”,请牢记这一点
  • 当你主要试图勾勒出你的循环逻辑时,这似乎是一个复杂的问题,但我通常发现开始使用 try...catch...finally 在发展。

我暂时找到了解决办法。因为只有一个 MERGFIELD,而不是尝试打开文档、插入日期、复制到新的 doc2、关闭文档、重复我发现我可以打开、插入日期、复制到新的 doc2、撤消对文档的编辑并重复。至少它现在有效,我可以在规划我计划的大项目时回到书本上学习更多东西。我相信我会在这里问更多问题。如果没有 @slightly-snarky 问他所做的问题,我就不会想到这一点,所以我必须感谢他们的回答。我确实必须把 doc.Undo();在循环的顶部,它只适用于一个字段。但这是一个开始。

     private void BtnPrint_Click(object sender, EventArgs e)
    {
        var app = new Microsoft.Office.Interop.Word.Application();
        String fileSave;
        fileSave = ("OTSU" + "_" + myDate[0].Month + "_" + myDate[0].Year + ".docx");
        int formCount;
        formCount = 0;
        var filepath = System.Windows.Forms.Application.StartupPath + outfile;
        var doc = new Microsoft.Office.Interop.Word.Document();
        doc = app.Documents.Add(filepath);
        app.Visible = true;
        doc.Activate();
        var doc2 = new Microsoft.Office.Interop.Word.Document();
        doc2.PageSetup.Orientation = WdOrientation.wdOrientLandscape;
        doc2.PageSetup.TopMargin = app.InchesToPoints(0.6f);
        doc2.PageSetup.BottomMargin = app.InchesToPoints(0.17f);
        doc2.PageSetup.LeftMargin = app.InchesToPoints(0.5f);
        doc2.PageSetup.RightMargin = app.InchesToPoints(0.5f);

        doc2.Activate();
        //OBJECT OF MISSING "NULL VALUE"
        Object oMissing = System.Reflection.Missing.Value;
        for (formCount = 0; formCount < myInt; formCount++)
        {
            doc.Undo();
            foreach (Microsoft.Office.Interop.Word.Field field in doc.Fields)
            {
                Range rngFieldCode = field.Code;
                String fieldText = rngFieldCode.Text;
                // ONLY GETTING THE MAILMERGE FIELDS
                if (fieldText.StartsWith(" MERGEFIELD"))
                {
                    Int32 endMerge = fieldText.IndexOf("\");
                    Int32 fieldNameLength = fieldText.Length - endMerge;
                    String fieldName = fieldText.Substring(11);
                    // GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dotx FILE
                    fieldName = fieldName.Trim();
                    if (fieldName != "M_2nd__3rd")
                    {
                        field.Select();
                        app.Selection.TypeText(myDate[formCount].ToShortDateString());
                    }
                    Microsoft.Office.Interop.Word.Range dRange = doc.Content;
                    dRange.Copy();
                    doc2.Range(doc2.Content.End - 1, doc2.Content.End - 1).PasteSpecial(DataType: Microsoft.Office.Interop.Word.WdPasteOptions.wdKeepSourceFormatting);
                    doc2.Range(doc2.Content.End - 1, doc2.Content.End - 1).InsertBreak(Microsoft.Office.Interop.Word.WdBreakType.wdPageBreak);
                    Clipboard.Clear();
                }
            }
        }
        doc2.SaveAs2("OTSU" + myDate[0].Month + "_" + myDate[0].Year + ".docx");
        doc.Close(WdSaveOptions.wdDoNotSaveChanges);
        doc2.Close(WdSaveOptions.wdDoNotSaveChanges);
        app.Documents.Open("OTSU" + myDate[0].Month + "_" + myDate[0].Year + ".docx");
    }
}

}