首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# Word文档将PlainText替换为mergefield

C# Word文档将PlainText替换为mergefield
EN

Stack Overflow用户
提问于 2018-05-11 14:49:06
回答 2查看 2.1K关注 0票数 0

我有一个word文档模板和一个CSV,我想用它进行邮件合并。

在word文档中,我的文本被<<>>包围,如果我想使用它来进行邮件合并,这与我的csv中的标头匹配。例如,我的word文档中有<<Salutation>>,csv中有字段名称谓。

是否有一种简单的方法可以将被<<>>包围的文本替换为对应于CSV中的标头的mailmerge字段?

到目前为止,我用于读取数据的代码是:

代码语言:javascript
复制
Microsoft.Office.Interop.Word.Application _wordApp = new Microsoft.Office.Interop.Word.Application();
        Microsoft.Office.Interop.Word.Document oDoc = _wordApp.Documents.Add(@"C:\Eyre\Template.docx");
        _wordApp.Visible = true;
        oDoc.MailMerge.MainDocumentType = Microsoft.Office.Interop.Word.WdMailMergeMainDocType.wdFormLetters;
        oDoc.MailMerge.OpenDataSource(@"C:\Eyre\CSV.csv", false, false, true);

        oDoc.MailMerge.Destination = Microsoft.Office.Interop.Word.WdMailMergeDestination.wdSendToNewDocument;
        oDoc.MailMerge.Execute(false);
        Microsoft.Office.Interop.Word.Document oLetters = _wordApp.ActiveDocument;
        oLetters.SaveAs2(@"C:\Eyre\letters.docx",
             Microsoft.Office.Interop.Word.WdSaveFormat.wdFormatDocumentDefault);

任何帮助都将不胜感激。

编辑

这似乎让一些人感到困惑。我有一个带有纯文本的word模板,比如问候语,我需要一个C#程序,它将用来自csv的合并字段替换这个纯文本。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-14 10:41:56

这里有一个C#版本的代码,用于将Word文档中的“占位符”替换为合并字段。(要获得VB版本的读者,请参见https://stackoverflow.com/a/50159375/3077495。)

我的代码使用了一个已经在运行的Word实例,所以您感兴趣的部分从foreach (Word.MailMergeDataField开始.

查找/替换操作在它们自己的过程ReplaceTextWithMergeField中,数据源字段的名称(如Word所看到的那样!)和搜索的目标范围被传递给它。

请注意,在此过程中,如何将角度括号对附加到数据字段名。

查找/替换操作是标准的,重新设置继续搜索数据字段名的Range对象有点不同,因为有必要获得合并字段之外的位置--在插入字段之后,范围在字段代码中。如果这还没有完成,Find可能会在“无限”的同一字段中结束。(注:在这种情况下,不是带有双角括号的。但是,如果有人使用没有它们的代码,那么就会出现问题。)

编辑:为了在Shape对象中找到和替换这些对象,必须分别循环这些对象。任何使用文本包装进行格式化的内容都位于文档的另一层,而不是Document.Content的一部分。我在第三个过程中修改了查找过程,以便搜索文档的ShapeRange,特别是测试文本框。

代码语言:javascript
复制
    private void btnDataToMergeFields_Click(object sender, EventArgs e)
    {
        getWordInstance();
        if (wdApp != null)
        {
            if (wdApp.Documents.Count > 0)
            {
            Word.Document doc = wdApp.ActiveDocument;
            Word.Range rng = doc.Content;
            Word.ShapeRange rngShapes = rng.ShapeRange;

            if (doc.MailMerge.MainDocumentType != Word.WdMailMergeMainDocType.wdNotAMergeDocument)
                foreach (Word.MailMergeDataField mmDataField in doc.MailMerge.DataSource.DataFields)
                {
                  System.Diagnostics.Debug.Print(ReplaceTextWithMergeField(mmDataField.Name, ref rng).ToString() 
                      + " merge fields inserted for " + mmDataField.Name);
                  rng = doc.Content;
                  System.Diagnostics.Debug.Print(ReplaceTextWithMergeFieldInShapes(mmDataField.Name, ref rngShapes)
                      + " mergefields inserted for " + mmDataField.Name);

                }
            }
        }
    }

    //returns the number of times the merge field was inserted
    public int ReplaceTextWithMergeField(string sFieldName, ref Word.Range oRng)
    {
        int iFieldCounter = 0;
        Word.Field fldMerge;
        bool bFound;

        oRng.Find.ClearFormatting();
        oRng.Find.Forward = true;
        oRng.Find.Wrap = Word.WdFindWrap.wdFindStop;
        oRng.Find.Format = false;
        oRng.Find.MatchCase = false;
        oRng.Find.MatchWholeWord = false;
        oRng.Find.MatchWildcards = false;
        oRng.Find.MatchSoundsLike = false;
        oRng.Find.MatchAllWordForms = false;
        oRng.Find.Text = "<<" + sFieldName + ">>";
        bFound = oRng.Find.Execute();
        while (bFound)
        {
            iFieldCounter = iFieldCounter + 1;
            fldMerge = oRng.Fields.Add(oRng, Word.WdFieldType.wdFieldMergeField, sFieldName, false);
            oRng = fldMerge.Result;
            oRng.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
            oRng.MoveStart(Word.WdUnits.wdCharacter, 2);
            oRng.End = oRng.Document.Content.End;
            oRng.Find.Text = "<<" + sFieldName + ">>";
            bFound = oRng.Find.Execute();
        }
        return iFieldCounter;
    }

    public int ReplaceTextWithMergeFieldInShapes(string sFieldName,
                               ref Word.ShapeRange oRng)
    {
        int iFieldCounter = 0;
        Word.Field fldMerge;
        bool bFound;

        foreach (Word.Shape shp in oRng)
        {
            if (shp.Type == Office.MsoShapeType.msoTextBox)
            {
                Word.Range rngText = shp.TextFrame.TextRange;
                rngText.Find.ClearFormatting();
                rngText.Find.Forward = true;
                rngText.Find.Wrap = Word.WdFindWrap.wdFindStop;
                rngText.Find.Format = false;
                rngText.Find.MatchCase = false;
                rngText.Find.MatchWholeWord = false;
                rngText.Find.MatchWildcards = false;
                rngText.Find.MatchSoundsLike = false;
                rngText.Find.MatchAllWordForms = false;
                rngText.Find.Text = "<<" + sFieldName + ">>";
                bFound = rngText.Find.Execute();
                while (bFound)
                {
                    iFieldCounter = iFieldCounter + 1;
                    fldMerge = rngText.Fields.Add(rngText, Word.WdFieldType.wdFieldMergeField, sFieldName, false);
                    rngText = fldMerge.Result;
                    rngText.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
                    rngText.MoveStart(Word.WdUnits.wdCharacter, 2);
                    rngText.End = shp.TextFrame.TextRange.End;
                    rngText.Find.Text = sFieldName;
                    bFound = rngText.Find.Execute();
                }
            }
        }
        return iFieldCounter;
    }
票数 2
EN

Stack Overflow用户

发布于 2018-05-14 05:30:03

有许多方法取决于您更广泛的需求。如果您将根据Windows机器上简单/小任务的需要运行该工具,那么VBA/宏方法可能是最好的方法,因为您已经准备好了所需的东西。

另一种方法需要对DOCX进行更多的编码和理解,但是您可以在没有more库的机器上扩展和运行它。因为DocX是开放的和基于文本的,所以您可以解压缩它,处理XML内容并重新压缩。存在一些问题,因为XML并不简单。如果您正在这样做,使用Word合并字段比普通文本更好(对程序员来说),因为查找字段更简单。对于使用文档/模板的人来说,纯文本更好,因为他们不需要处理合并字段,但缺点是XML处理可能变得更加复杂。模板<<Salutation>>中的文本可能不容易找到XML --它可能被分割成几个部分。

另一个解决方案是使用类似Docmosis (一种商业产品-请注意我为Docmosis工作)的东西。优点是Docmosis可以完成替换和更复杂的需求(例如,条件结构和循环结构,PDF转换)。缺点是,您必须学习API并安装软件(或调用云),并将数据转换为传递给引擎的格式。

我希望这能帮上忙。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50294941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档