Office Open XML SDK 单词替换

发布于 2024-09-30 02:19:35 字数 603 浏览 1 评论 0原文

为了根据 SQL 数据库中的数据创建 Word 文档,我使用 Office Open XML SDK 来避免使用互操作。这加快了流程,并且无需在客户端系统上安装 Microsoft Office 套件。

虽然这工作得很好,但在替换文档中的某些文本时遇到了问题。为了保留最终文档的自定义选项,我创建了一个包含一些标签的文档作为模板。该模板包含诸如[TagHere]之类的标签。由于标签名称应该易于阅读,因此可以在整个文档中使用它们,这就是为什么我用大括号 [] 将标签括起来。

这工作得很好,但有时会出现问题。当您在 docx 文档中输入内容时,文本可以分为多个标签,甚至在同一个单词中也是如此。像 [TagHere] 这样的标签可以分为

[TagHere]

发生这种情况时,替换将不起作用。

现在 docx 格式有一些替代选项来执行此类操作,例如内容控件,但这些使得创建模板的过程更加复杂。此外,在这些文档中获取带有标签的表格的一行并复制多次的情况并不罕见,这可能会破坏内容标签原则。因此我选择不使用此选项。

如果有人能解决这个问题,那就太好了。

For creating word documents based on data from an SQL database, I'm using Office Open XML SDK to avoid using interop. This speeds up the process and it eliminates the requirement for a Microsoft office suite installed on the client system.

While this works very well, there is a problem I'm having when replacing certain text in the document. To keep customization of the final document an option, I've created a document with some tags in it as a template. This template contains tags such as [TagHere]. Since the tag names should be easy readable, they could be used throughout the document, which is why I've surrounded the tag with braces [].

This works quite well, but sometimes, an issue comes up. When you're typing in a docx document, the text can be split up into multiple tags, even in the same word. A tag like [TagHere] can be split up into

<tag>[</tag><tag>TagHere</tag><tag>]</tag>

When this happens, the replacement won't work.

Now the docx format has some alternative options to do this kind of operations, such as Content Controls, but these make the process of creating the template more complex. Furtermore, it is not uncommon in these documents to get one row of a table with tags and copy it multiple of times, which would probably break the content tag principle. Hence I've chosen to not use this option.

It would be great if someone has a solution to this problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叹梦 2024-10-07 02:19:35

不要输入纯文本“taghere”,而是插入合并字段。 (在 Word 中,单击插入 > 快速部件 > 字段。选择“合并字段”并在“字段名称”字段中输入“TagHere”。)

然后,不要执行文本查找替换,而是扫描文档中的合并字段并设置内部文本。

class Program
{
    static void Main(string[] args)
    {
        string document = args[0];
        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
        {
            Dictionary<string, string> replaceOperations = new Dictionary<string, string>();

            replaceOperations.Add("company", "alex's applications");
            replaceOperations.Add("first_name", "alexander");
            replaceOperations.Add("last_name", "taylor");
            //etc

            Replace(wordDoc, replaceOperations);
        }
    }

    public static char[] splitChar = new char[] {' '};
    public static void Replace(WordprocessingDocument document, Dictionary<string, string> replaceOperations)
    {
        //find all the fields
        foreach (var field in document.MainDocumentPart.Document.Body.Descendants<SimpleField>())
        {
            //parse the instruction
            string[] instruction = field.Instruction.Value.Split(splitChar, StringSplitOptions.RemoveEmptyEntries);

            //check if it's a merge field, and if so...
            if (instruction[0].ToLower().Equals("mergefield"))
            {
                //get the field name
                string fieldname = instruction[1];

                //find the text inside (there will only be one)
                foreach (var fieldtext in field.Descendants<Text>())
                {
                    //see if we know what to set this value to
                    string value = replaceOperations.ContainsKey(fieldname) ? replaceOperations[fieldname] : null;

                    //if we found the replace value, set the text to this value
                    if (value != null)
                        fieldtext.Text = value;

                    //should only be one text inside
                    break;
                }
            }
        }
    }
}

instead of typing plain text "taghere", insert a merge field. (in word, click insert > quick parts > field. choose "mergefield" and type "TagHere" in the "Field name" field.)

then instead of doing a text find-replace, scan the document for merge fields and set the inner texts.

class Program
{
    static void Main(string[] args)
    {
        string document = args[0];
        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
        {
            Dictionary<string, string> replaceOperations = new Dictionary<string, string>();

            replaceOperations.Add("company", "alex's applications");
            replaceOperations.Add("first_name", "alexander");
            replaceOperations.Add("last_name", "taylor");
            //etc

            Replace(wordDoc, replaceOperations);
        }
    }

    public static char[] splitChar = new char[] {' '};
    public static void Replace(WordprocessingDocument document, Dictionary<string, string> replaceOperations)
    {
        //find all the fields
        foreach (var field in document.MainDocumentPart.Document.Body.Descendants<SimpleField>())
        {
            //parse the instruction
            string[] instruction = field.Instruction.Value.Split(splitChar, StringSplitOptions.RemoveEmptyEntries);

            //check if it's a merge field, and if so...
            if (instruction[0].ToLower().Equals("mergefield"))
            {
                //get the field name
                string fieldname = instruction[1];

                //find the text inside (there will only be one)
                foreach (var fieldtext in field.Descendants<Text>())
                {
                    //see if we know what to set this value to
                    string value = replaceOperations.ContainsKey(fieldname) ? replaceOperations[fieldname] : null;

                    //if we found the replace value, set the text to this value
                    if (value != null)
                        fieldtext.Text = value;

                    //should only be one text inside
                    break;
                }
            }
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文