Замена Office Open XML SDK словом - PullRequest
4 голосов
/ 02 ноября 2010

Для создания текстовых документов на основе данных из базы данных SQL я использую Office Open XML SDK, чтобы избежать взаимодействия. Это ускоряет процесс и устраняет необходимость в пакете Microsoft Office, установленном в клиентской системе.

Хотя это работает очень хорошо, у меня возникает проблема при замене определенного текста в документе. Чтобы сохранить настройку окончательного документа, я создал документ с некоторыми тегами в качестве шаблона. Этот шаблон содержит теги, такие как [TagHere]. Поскольку имена тегов должны быть легко читаемыми, их можно использовать по всему документу, поэтому я заключил тег в фигурные скобки [].

Это работает довольно хорошо, но иногда возникает проблема. Когда вы печатаете в документе DOCX, текст может быть разделен на несколько тегов, даже в одном и том же слове. Тег типа [TagHere] можно разделить на

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

Когда это произойдет, замена не будет работать.

Теперь формат docx имеет несколько альтернативных опций для выполнения таких операций, таких как Content Controls, но они усложняют процесс создания шаблона. Более того, в этих документах нередко можно получить одну строку таблицы с тегами и скопировать ее несколько раз, что, вероятно, нарушит принцип тега содержимого. Поэтому я решил не использовать эту опцию.

Было бы замечательно, если бы у кого-то было решение этой проблемы.

1 Ответ

4 голосов
/ 08 августа 2011

вместо ввода обычного текста "taghere", вставьте поле слияния. (Одним словом, нажмите «Вставка»> «Быстрые детали»> «Поле». Выберите «поле слияния» и введите «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;
                }
            }
        }
    }
}
...