Xml шаблон для word

Introduction

Hi, thanks for your interest in this tip. I am writing this tip because I faced a problem in achieving a simple goal.
The goal was to use a Word document as a template and create a new one, some contents from the template should get replaced by user provided values.

There are plenty of ways provided for this task but it needed more understanding of XML templates. May be some of us expect rapid task completion without spending more
time on understandings. Hence this tip is useful.

A detailed problem and its solution are provided below.

Background

OpenXML is widely used for creating/updating Office documents. It has a predefined structure of XML for document. One can refer to this
link for details.

My Task: Use Open XML and create a new Word document. Template is predefined with extension as «*.docx«.
This template contains some words which need to be replaced by user provided values.

Let’s Do It

Before you start using Visual Studio, check whether you have installed Open XML 2.0
on machine. If yes, we are good to go forward.

Follows the steps:

  1. Open Visual Studio and select the blank ASP.NET project, add references
    of two DLLs to the project: «WindowsBase» and «DocumentFormat.OpenXml«.
  2. Then create two folders «Templates» and «New Documents«.
  3. Add a Word document «mytemplate.docx» in the template
    folder to use it as template for new documents.
  4. Add your text in document. E.g., Hi folks, My name is “Replaceable Text”.
  5. Now on default.aspx, add the following code:
  6. Please enter your name <asp:TextBox ID="txtName" runat="server" />:

    <asp:Button ID="btnSubmit" runat="server" Text="Create" />
  7. Now click onto button to generate click event and add the below code in it.
  8. protected void btnSubmit_Click(object sender, EventArgs e){
        #region
        try
        {
            string sourceFile = Server.MapPath(Path.Combine("/", "Templates/mytemplate.docx"));
            string destinationFile = Server.MapPath
            (Path.Combine("/", "New Documents/FirstDocument.docx"));
    
            
            File.Copy(sourceFile, destinationFile, true);
    
           	
    		
            Dictionary<string, string> keyValues = new Dictionary<string, string>();
            keyValues.Add(""Replaceable Text"", txtName.Text);                
      		SearchAndReplace(destinationFile, keyValues);
    
            Process.Start(destinationFile);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    
    #endregion
    } 

    Note: «Replaceable Text» can be any text like ‘My text’ or ::#My Text::#

  9. Add one more function below above event.
  10. public static void SearchAndReplace(string document, Dictionary<string, string> dict)
    {
        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true))
        {
            string docText = null;
            using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
            {
                docText = sr.ReadToEnd();
            }
    
            foreach (KeyValuePair<string, string> item in dict) 
            {
                Regex regexText = new Regex(item.Key);
                docText = regexText.Replace(docText, item.Value);
            }
    
            using (StreamWriter sw = new StreamWriter(
                      wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
            {
                sw.Write(docText);
            }
    
        }
    }
  11. Compile code and execute it and we are done with code.
  12. Enter name in text box and file will open automatically.

Expected Problems and Limitations

This article has been developed by considering that the template you are using is correctly formatted.

  1. Let me explain in detail as:
  2. Consider you are trying to replace word from document is «Employee» it will not work with above code replacement.
    Because docx file is formatted in XML format internally. XML format for this word can be as follows:

    <w:r>
        <w:rPr>
          <w:b />
          <w:color w:val="333333" />
          <w:sz w:val="32" />
          <w:szCs w:val="32" />
        </w:rPr>
        <w:t>E</w:t>
    </w:r>
    <w:r w:rsidRPr="00DA41AA">
        <w:rPr>
          <w:color w:val="333333" />
          <w:sz w:val="32" />
          <w:szCs w:val="32" />
        </w:rPr>
        <w:t>mployee</w:t>
    </w:r> 

    As you can see, it has <w:t>E</w:t> formatting for E and rest of the characters are in <w:t>mployee</w:t> XML element, hence our code won’t find Employee word.
    So it cannot be replaced.

  3. We have used Regx class so take care of those charters used in regular expression formatting.

This member has not yet provided a Biography. Assume it’s interesting and varied, and probably something to do with programming.

Выяснили, как использовать элементы управления содержимым для создания документов и как вставлять данные из XML в элементы управления содержимым. Я разделил это на 2 части:

  • Часть 1. Создайте свой шаблон документа для создания документа.
  • Часть 2: Используйте код на C# для создания документов на основе шаблона

Часть 1. Создайте свой шаблон документа для создания документа.

  1. Создайте образец XML, на основе которого вы можете создать шаблон Word для создания документа. Желательно начать с менее сложной версии, чтобы понять ее.

Я использовал следующий XML для тестирования. Для тестирования у меня не было повторяющихся разделов, картинок и т. д.

<?xml version = "1.0" encoding = "utf-8"?>
<mydata xmlns = "http://CustomDemoXML.htm">
    <field1>This is the value in field1 from the XML file</field1>
    <field2>This is the value in field2 from the XML file</field2>
    <field3>This is the value in field3 from the XML file</field3>
</mydata>

Примечание 1: это будет просто образец XML для создания вашего шаблона Word. XML-файл (ы) с реальными данными в том же формате позже можно будет применить при создании документа (ов) Word из шаблона.

Заметка 2: Атрибут xmlns может содержать буквально все, что вы хотите, и это не обязательно должен быть URL, начинающийся с http.

Сохраните образец XML-файла в любом месте, чтобы его можно было импортировать в шаблон, который вы собираетесь создать.

  1. Убедитесь, что в вашей копии Word включена вкладка Developer [File -> Options -> Customize Ribbon -> В разделе Customize the Ribbon убедитесь, что выбрано Developer -> OK]. Подробности: Как: показать вкладку разработчика на ленте

  2. Создайте новый документ Word (или используйте существующий документ Word), который будет вашим шаблоном для создания документа.

  3. На вкладке Developer щелкните XML Mapping Pane. Это откроет XML Mapping Pane в правой части документа.

  4. На панели сопоставления XML выберите раскрывающийся список Custom XML Part -> Выбрать (Add new part).

  5. Выберите файл XML, который вы сохранили на шаге 1 -> Open.

  6. На панели сопоставления XML выберите раскрывающийся список Custom XML Part -> выберите элемент с текстом, который был в атрибуте xmlns настраиваемого файла XML. Если вы используете приведенный выше образец файла, это будет http://CustomDemoXML.htm.

  7. Добавьте статический текст в документ Word и добавьте рядом с ним Plain Text Content Control (на вкладке Developer -> раздел Controls. Повторите для всех полей, которые вам нужно добавить.

Для приведенного выше примера XML у меня был следующий документ Word:

  1. Щелкните первый Plain Text Content Control -> На панели сопоставления XML щелкните правой кнопкой мыши поле, которое вы хотите сопоставить с этим элементом управления содержимым -> Щелкните Map to Selected Content Control. Повторите эти действия для всех полей, которые хотите сопоставить.

Примечание: В качестве альтернативы, вместо добавления элементов Plain Text Content Control из вкладки разработчика на шаге 8, вы можете щелкнуть правой кнопкой мыши поле, которое вы хотите сопоставить, на панели сопоставления XML -> Щелкните Insert Content Control -> Щелкните Plain Text.

Точно так же вы также можете добавить другие типы элементов управления, такие как флажки, средства выбора даты и даже повторяющиеся разделы (он также поддерживает вложенные повторяющиеся разделы! — начиная с Word 2013) и сопоставить данные из XML с теми, которые используют только встроенные функции Word и без какой-либо третьей стороны. инструменты!

  1. Сохраните свой шаблон документа.

Часть 2: Используйте код на C# для создания документов на основе шаблона

При этом используется рекомендованный Microsoft OpenXML SDK для создания документов с использованием XML-файла, содержащего реальные данные.

  1. Создайте свой XML-файл / откройте существующий XML-файл, чтобы сгенерировать документ из шаблона, созданного выше. Он должен быть в том же формате, что и образец XML-файла, использованного для создания шаблона.

  2. Используйте OpenXML SDK для удаления любых элементов CustomXMLPart из документа. Это предполагает, что в документе не используются никакие другие настраиваемые части XML, как в этом примере. В сложных сценариях при необходимости можно удалить определенные части XML.

  3. Используйте OpenXML SDK, чтобы добавить новый CustomXMLPart на основе файла XML на шаге № 1 выше.

Вот пример кода, который я должен «обновить» / «перезагрузить» для образцов данных в шаблоне данными из XML-файла, содержащего реальные данные (при условии, что XML-файл, используемый для создания документа, уже создан и сохранен):

using System.IO;
using DocumentFormat.OpenXml.Packaging;

namespace SampleNamespace
{
    public static class SampleClass
    {
        public static void GenerateDocument()
        {
            string rootPath = @"C:Temp";
            string xmlDataFile = rootPath + @"MyNewData.xml";
            string templateDocument = rootPath + @"MyTemplate.docx";
            string outputDocument = rootPath + @"MyGeneratedDocument.docx";

            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(templateDocument, true))
            {
                //get the main part of the document which contains CustomXMLParts
                MainDocumentPart mainPart = wordDoc.MainDocumentPart;

                //delete all CustomXMLParts in the document. If needed only specific CustomXMLParts can be deleted using the CustomXmlParts IEnumerable
                mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts);

                //add new CustomXMLPart with data from new XML file
                CustomXmlPart myXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
                using (FileStream stream = new FileStream(xmlDataFile, FileMode.Open))
                {
                    myXmlPart.FeedData(stream);
                }
            }

        }
    }
}

Это оно!

как создать XML-файлы из слова

Формат XML предназначен для хранения данных, которые могут быть полезны в работе некоторых программ, сайтов и поддержке определенных языков разметки. Создать и открыть файл в этом формате несложно. Это можно сделать, даже если на вашем компьютере не установлено специализированное программное обеспечение.

XML сам по себе является языком разметки, чем-то похожим на HTML, который используется на веб-страницах. Но если последний используется только для отображения информации и ее правильной разметки, XML позволяет структурировать ее определенным образом, что делает этот язык похожим на аналог базы данных, не требующий СУБД.

Вы можете создавать файлы XML, используя как специализированные программы, так и встроенный текстовый редактор Windows. Удобство написания кода и уровень его функциональности зависят от типа используемого программного обеспечения.

Способ 1: Visual Studio

Вместо этого редактора кода Microsoft вы можете использовать любые его аналоги от других разработчиков. Фактически, Visual Studio — это более продвинутая версия обычного Блокнота. Код теперь имеет специальную подсветку, ошибки автоматически выделяются или исправляются, а специальные шаблоны уже загружены в программу, что упрощает создание больших файлов XML.

Для начала вам необходимо создать файл. Щелкните элемент «Файл» на верхней панели и выберите «Создать…» в раскрывающемся меню. Откроется список, в котором указана запись «Файл».

как создать XML-файлы из слова

Вам будет перенесено окно с выбором расширения файла, соответственно выберите пункт «XML файл».

как создать XML-файлы из слова

Во вновь созданном файле уже будет первая строка с кодировкой и версией. По умолчанию записывается первая версия и кодировка UTF-8, которую вы можете изменить в любой момент. Затем, чтобы создать полный XML-файл, вам нужно записать все, что было в предыдущем операторе.

По окончании работы снова выберите в верхней панели «Файл», затем из выпадающего меню пункт «Сохранить все».

Способ 2: Microsoft Excel

Вы можете создать XML-файл без написания кода, например, используя современные версии Microsoft Excel, что позволяет сохранять таблицы с этим расширением. Однако нужно понимать, что в этом случае у вас не получится создать что-то более функциональное, чем обычный стол.

Этот метод лучше всего подходит для тех, кто не хочет или не умеет работать с кодом. Однако в этом случае пользователь может столкнуться с некоторыми проблемами при перезаписи файла в формате XML. К сожалению, преобразование обычной таблицы в XML возможно только в более новых версиях MS Excel. Для этого воспользуйтесь следующими пошаговыми инструкциями:

  1. Дополните таблицу некоторым содержанием.
  2. Нажмите кнопку «Файл» в верхнем меню.
  3. Откроется специальное окно, в котором нужно нажать «Сохранить как…». Этот пункт находится в левом меню.
  4. Укажите папку, в которой вы хотите сохранить файл. Папка указана в центре экрана.
  5. Теперь вам нужно указать имя файла и в разделе «Тип файла» из выпадающего меню выбрать
    Данные XML».
  6. Нажмите кнопку «Сохранить».

Способ 3: Блокнот

Даже обычный Блокнот вполне подходит для работы с XML, но у пользователя, незнакомого с синтаксисом языка, возникнут трудности, так как в нем придется писать различные команды и теги. Несколько проще и продуктивнее процесс будет в специализированных программах для редактирования кода, например, в Microsoft Visual Studio. В них есть специальные метки и подсказки, которые значительно упрощают работу человеку, не знающему синтаксиса этого языка.

Для этого метода ничего скачивать не нужно, так как в операционной системе уже есть встроенный «Блокнот». Попробуем создать простую XML-таблицу по приведенным инструкциям:

  1. Создайте простой текстовый документ с расширением TXT. Вы можете разместить его где угодно. Открой это.
  2. Начните набирать в нем первые команды. Во-первых, вам нужно установить кодировку для всего файла и указать версию XML, это делается с помощью следующей команды:

    Первое значение — это версия, менять ее не нужно, а второе значение — это кодировка. Рекомендуется использовать кодировку UTF-8, так как с ней прекрасно работает большинство программ и обработчиков. Однако его можно изменить на любое другое, просто набрав желаемое имя.

  3. Создайте первый каталог в вашем файле, написав тег и закрыв его вот так .
  4. Теперь вы можете написать какой-то контент внутри этого тега. Создаем тег и даем ему любое имя, например «Иван Иванов». Готовая конструкция должна выглядеть так:
  5. Внутри тега теперь можно писать более подробные параметры, в данном случае это информация об определенном Иване Иванове. Мы пропишем ваш возраст и местонахождение. 
  6. Если вы следовали инструкциям, вы должны получить тот же код, что и ниже. Когда закончите, найдите «Файл» в верхнем меню и выберите «Сохранить как…» в раскрывающемся меню. При сохранении в поле «Имя файла» после точки должно стоять расширение не TXT, а XML.

как создать XML-файлы из слова

Компиляторам XML необходимо обработать этот код в виде таблицы с одним столбцом, содержащей данные о некоем Иване Иванове.

В «Блокноте» вполне можно создавать такие простые таблицы, но при создании массивов более объемных данных могут возникнуть трудности, так как в обычном «Блокноте» нет функций для исправления ошибок в коде или их выделения.

Как видите, в создании XML-файла нет ничего сложного. При желании его может создать любой пользователь, более-менее умеющий работать на компьютере. Однако для создания полного XML-файла рекомендуется изучить этот язык разметки, по крайней мере, на примитивном уровне.

8409840image001Продолжаем, начатую ранее тему работы с формами в Word. В предыдущих статьях мы смотрели на формы только с точки зрения “продвинутого пользователя”, т.е. мы создавали документы, удобные для ручного заполнения. Сегодня же я хочу предложить расширить эту задачу и попробовать использовать механизм Content controls для генерации документов.

Прежде, чем мы приступим к нашей непосредственной задаче, хочу сказать пару слов по поводу того, как хранятся в документах Word данные для сontent controls (то как они привязываются к содержимому документа я сознательно пока опущу, но надеюсь вернуться к этому как-нибудь в следующих статьях).

Как мы уже видели ранее (Open Packaging Conventions #2. Собираем MS Word документ руками) вся основная часть документа хранится в Main Document Part. Все остальные компоненты: картинки, данные данные библиографии, … и конечно же данные для content controls привязываются к нему.

Приблизительно как показано на рисунке:

image

Каждый компонент item1.xml, item2.xml и т.д. (в файлах, сформированных Word они называются так и лежат обычно в папке /customXml) хранит данные по каждому подключенному в документ источнику данных. Мы даже это наблюдали ранее, когда только осваивали создание форм в Word в статье Таблицы в формах Word 2013!

Закономерный вопрос – а что такое itemProps1.xml и аналогичные компоненты? В этих компонентах хранятся описания источников данных. Скорее всего, по задумке разработчиков помимо встроенных в документ xml-ек, предполагалось использовать и другие, но пока реализован только этот способ.

Чем полезны нам itemPropsX.xml? Тем, что в них перечислены xml-схемы (их targetNamespace), которые используются в родительском itemX.xml. Это значит, что если мы подключили в документ не одну custom xml, то чтобы найти нужную, нам нужно пробежаться по itemPropsX.xml компонентам и найти нужную схему, а значит и нужный itemX.xml.

Теперь еще один момент. Мы не будем вручную анализировать связи между компонентами и искать нужные, используя только базовый Packaging API! Вместо этого мы воспользуемся Open XML SDK (его сборки доступны через NuGet). Конечно, ранее мы не словом не говорили про этот API, но для нашей задачи от него требуется минимум и весь код будет достаточно прозрачен.

Ну что ж, основное введение сделано, можно приступать к примеру.

По сложившейся традиции возьмем все тот же “Отчет о совещании”, который мы рисовали в статье Таблицы в формах Word 2013. Напомню, что вот так выглядел шаблон документа:

image

А вот так, XML к которому привязывались поля документа

<?xml version="1.0" encoding="utf-8"?>
<meetingNotes xmlns="urn:MeetingNotes" subject="" date="" secretary="">
    <participants>
        <participant name=""/>
    </participants>
    <decisions>
        <decision problem="" solution="" responsible="" controlDate=""/>
    </decisions>
</meetingNotes>

Шаг 1. Создание модели данных

Собственно наша задача не просто сгенерировать документ, а создать (хотя бы в черновом варианте) удобный инструмент для использования как разработчиком, так и пользователем.

Поэтому модель мы объявим в виде структуры С#-классов:

[XmlRoot("meetingNotes", Namespace = "urn:MeetingNotes")]
public class MeetingNotes
{
    public MeetingNotes()
    {
        Participants = new List<Participant>();
        Decisions = new List<Decision>();
    }
 
    [XmlAttribute("subject")]
    public string Subject { get; set; }
 
    [XmlAttribute("date")]
    public DateTime Date { get; set; }
 
    [XmlAttribute("secretary")]
    public string Secretary { get; set; }
 
    [XmlArray("participants")]
    public List<Participant> Participants { get; set; }
 
    [XmlArray("decisions")]
    public List<Decision> Decisions { get; set; }
}
 
[XmlType("decision")]
public class Decision
{
    [XmlAttribute("problem")]
    public string Problem { get; set; }
 
    [XmlAttribute("solution")]
    public string Solution { get; set; }
 
    [XmlAttribute("responsible")]
    public string Responsible { get; set; }
 
    [XmlAttribute("controlDate")]
    public DateTime ControlDate { get; set; }
}
 
[XmlType("participant")]
public class Participant
{
    [XmlAttribute("name")]
     public string Name { get; set; }
}

По большому счету ничего особенного, разве что добавлены атрибуты для управления XML-сериализацией (т.к. имена в модели и требуемой XML немного различаются).

Шаг 2. Сериализация приведенной выше модели в XML

Задача, в принципе, тривиальная. Что называется “берем наш любимый XmlSerializer и вперед”, если бы не одно но

К сожалению, в текущей версии Office, по всей видимости, присутствует баг, который заключается в следующем: если в custom xml перед объявлением основного namespace (того, из которого Word должен брать элементы для отображения), объявить еще какой-нибудь, то повторяющиеся Content controls начинают отображаться не верно (показывается только столько элементов, сколько было в самом шаблоне – т.е. repeating section не работает).

Т.е. вот такой xml работает:

<?xml version="1.0" encoding="utf-8"?>
<test xmlns="urn:Test" attr1="1" attr2="2">
    <repeatedTag attr="1" />
    <repeatedTag attr="2" />
    <repeatedTag attr="3" />
</test>

и вот такой тоже:

<?xml version="1.0" encoding="utf-8"?>
<test xmlns="urn:Test" attr1="1" attr2="2" xmlns:t="urn:TTT">
    <repeatedTag attr="1" />
    <repeatedTag attr="2" />
    <repeatedTag attr="3" />
</test>

а вот такой, уже нет:

<?xml version="1.0" encoding="utf-8"?>
<test xmlns:t="urn:TTT" xmlns="urn:Test" attr1="1" attr2="2">
    <repeatedTag attr="1" />
    <repeatedTag attr="2" />
    <repeatedTag attr="3" />
</test>

я пробовал отправить баг в поддержку Microsoft на Connect, но у меня почему-то закрыт доступ для отправки багов по Office. А обсуждение на форуме MSDN тоже не помогло.

В общем, нужный обходной маневр. Если бы мы формировали XML руками, проблем бы не возникло – мы сделали бы все сами. Однако в данном случае очень хочется использовать стандартный XmlSerializer, который по-умолчанию добавляет несколько своих namespace в выходной XML, даже если эти namespace не используются.

Мы сделаем полное подавление вывода собственных namespace в XmlSerializer. Правда, этот подход сработает, только если они ему и правда будут не нужны (в противном случае они все равно будут добавлены и как раз ДО нашего Печальная рожица).

Собственно, весь код (при условии, что переменная meetingNotes содержит ранее заполненный объект типа MeetingNotes):

var serializer = new XmlSerializer(typeof(MeetingNotes));
var serializedDataStream = new MemoryStream();

var namespaces = new XmlSerializerNamespaces();
namespaces.Add(“”, “”);

serializer.Serialize(serializedDataStream, meetingNotes, namespaces);
serializedDataStream.Seek(0, SeekOrigin.Begin);


Шаг 3. Заносим полученную XML в Word-документ.

Тут мы поступаем следующим образом:

  • копируем шаблон и открываем копию
  • находим в ней нужный custom xml (ищем по namespace “urn:MeetingNotes”)
  • замещаем содержимое компонента, на нашу XML
File.Copy(templateName, resultDocumentName, true);
 
using (var document = WordprocessingDocument.Open(resultDocumentName, true))
{
    var xmlpart = document.MainDocumentPart.CustomXmlParts
        .Single(xmlPart =>
            xmlPart.CustomXmlPropertiesPart.DataStoreItem.SchemaReferences.OfType<SchemaReference>()
            .Any(sr => sr.Uri.Value == "urn:MeetingNotes"));
 
    xmlpart.FeedData(serializedDataStream);
}

Все! У нас готовый документ-отчет по совещанию. Причем, мы реализовали весьма удобный для повторного использования подход (источником данных для данного отчета может служить все, что угодно).

Как поиграться?

Пример, который приведен в статье, можно как и ранее найти на GitHub.

Если же хочется попробовать пример в деле (и не хочется разбираться в коде), можно посмотреть Web-реализацию примера генерации отчета, а исходный код этого примера найдется там же на Codeplex, но в соседней ветке.

image

Для того, чтобы создать шаблон файла, в качестве образца используйте входящий в поставку Системы файл «CustomXMLPart.xml».

Примечание: Внутри тега <Row>   </Row> используются Системные названия (internal names) реквизитов документа.

1. Сохраните файл CustomXMLPart.xml под новым именем.

2. Добавьте Системные названия (InternalName) реквизитов, нужных для автоматического заполнения в шаблоне.

<?xml version=»1.0″ encoding=»utf-8″?>
<!— Пример Custom XML Part, внедряемый в документ MS Word с помощью утилиты Word 2007 Content Control Toolkit —>
<!— Имя элемента соответствует статическому имени столбца. Для нормальной работы столбцы должны иметь статические —>
<!— имена в латинице. Не рекомендуется использовать энкодированные имена (получаемые из локализованных)  —>
<!— Поддерживаются составные имена, т.е., если столбец является подстановкой, то через точку можно указать —>
<!— имя столбца в связном списке. Поддерживаются только один уровень подстановки. —>
<Rows xmlnshttp://schemas.conteq.ru/2006/openXml/customData/«>
   <Row>
      <sdmUchastniki/>
      <sdmTransport/>
      <sdmVokzal/>
      <sdmHotel/>
      <sdmDateOt/>
      <sdmDatePo/>
      <sdmDatePriezda/>
      <sdmDataS/>
      <sdmInformNomer/>
      <sdmOrganizacia/>
      <sdmPrimechanieProg/>
      <sdmPrimechanieTransport/>
      <sdmPunktNaznachenia/>
   </Row>
</Rows>

При необходимости можно добавить составное поле (если столбец является подстановкой, то через точку можно указать имя столбца в связанном списке), например: Signer.JobTitle  — элемент будет заполнен должностью получателя. Поддерживается только 1 уровень подстановки, например:

<Rows xmlnshttp://schemas.conteq.ru/2006/openXml/customData/«>
   <Row>
      <Signer/>

      <Signer.JobTitle/>

      <RegDate/>

      <RegNumber/>
      
   </Row>
</Rows>

3. Сохраните XML-файл Шаблона.

Примечание:

Для определения Системного названия реквизита можно воспользоваться страницей настройки Типа документа в разделе Параметры DocSapce:

24

Время на прочтение
5 мин

Количество просмотров 1.4K

Привет, Хабр! Меня зовут Дарья Чувашова, я — руководитель группы отделения SAP-разработки. В процессе моей проектной деятельности мне приходилось сталкиваться с задачами выгрузки документов в .doc формат и делать это нужно было быстро. При этом эти документы могли быть с совершенно разным форматированием, кучей таблиц, реквизитов и т. д. В SAP для выгрузки в форматы pdf и excel есть удобные инструменты, возможность работать с формулярами и графическими редакторами форм. Для работы с форматом.doc инструментов меньше. В этой статье я расскажу о быстром и самом простом способе выгрузить документ любой сложности.

Почему я решила написать этот «how‑to»? Как я упомянула, задачи по выгрузке файлов в.doc мне приходилось выполнять часто. В какой‑то момент я собрала все лайфхаки и советы по ускорению работы в один материал, а сейчас хочу поделиться им с хабровской аудиторией. Надеюсь, для коллег записи будут полезными. Описанный вариант решения имеет свои особенности, поэтому я постараюсь на примерах продемонстрировать некоторые «узкие» моменты.

Пошаговая инструкция решения вопроса

Шаг 1

В первую очередь нам нужно подготовить шаблон в MS Word в нужном формате. Важно заполнить все реквизиты тестовыми данными для примера, это значительно упростит нам жизнь в последующих действиях.

В качестве примера рассмотрим вот такой документ «Счёт‑фактура» в MS Word:

Этот и другие используемые здесь примеры были взяты из открытого источника: https://glavkniga.ru/situations/k505106

Этот и другие используемые здесь примеры были взяты из открытого источника: https://glavkniga.ru/situations/k505106

Шаблон необходимо заполнить тестовыми примерами, чтобы проверить, что при заполнении ничего не съезжает, и все реквизиты остаются на месте:

Шаг 2

Сохраним наш документ в формате XML: Файл — Сохранить как. Выбираем расширение .xml

Примечание: для большинства задач вполне достаточно формата.doc, он поддерживает ограничения редактирования, элементы управления и т. п.

Для того чтобы открыть данный файл, мне удобно использовать программу Altova XML Spy. Скорее всего нам потребуется проанализировать содержимое, а в данной программе выполнять анализ файла очень удобно за счёт подсветки синтаксиса. Вы, конечно, можете использовать любой другой редактор.

Открываем свой XML, видим примерно такую картину:

После применения команды PrettyPrinter:

Шаг 3

Переходим в SAP. В своём пакете разработки создадим Преобразование:

Выберем трансформацию XSLT:

Видим следующую картину:

Для того, чтобы наша трансформация верно работала, необходимо указать следующий код между тегами <xsl:template match=»/»> </xsl:template>:

<xsl:processing-instruction name="mso-application" progid="Word.Document">
      <xsl:text progid="Word.Document"/>
  </xsl:processing-instruction>

Теперь можно смело вставить весь XML‑код ниже из нашего документа:

Визуально просматриваю данный XML‑код, обнаруживаю, что часть тегов подсвечивается, как текст:

Вижу, что это произошло из‑за кавычек в наименовании компании (Company), смело их удаляю:

Теперь пытаемся активировать трансформацию. В 90% случаях активация пройдёт успешно.

Но если у вас появятся подобные ошибки,

Предлагаю стереть данные коды, так как они не имеют никакого смысла для генерации документа из SAP.

Удаляем:

После удаления всех кодов трансформация успешно активируется.

Шаг 4

Переходим в программу. Для вызова трансформации и выгрузки файла привожу для примера такой код:

Данный код максимально облегчён для простоты восприятия и предельной наглядности.

После запуска программы в папке C:TEMP сохранится файл точно в таком же виде, как наш подготовленный шаблон:

При открытии файла может возникнуть следующая ошибка:

Для того, чтобы от неё избавиться, переходим в трансформацию и ищем /word/settings.xml

Избавиться от ошибки мне помогло удаление всего блока <pkg:part … </pkg:part>. Это не повлияло на работоспособность, и файл стал открываться нормально. Без подсветки синтаксиса тяжело искать закрывающий тег, поэтому имеет смысл снова воспользоваться программой Altova XML Spy (в данной программе вы можете удалить лишний код, а затем вставить новую версию в нашу трансформацию).

Удаляем и активируем, проверяем, что ошибка ушла и с файлом всё в порядке.

Шаг 5

Переходим к выгрузке данных из контекста. Начнём с самого простого: выгрузим данные в поле «Продавец»:

Контекст представляет собой структуру c данными, например, вот такую:

Её мы заполняем и подаём в трансформацию как контекст. Далее копируем из файла, заполненного в качестве примера, текст из реквизита «Продавец» и ищем это место в нашей XML:

Вместо данного текста вставляем:

Не забываем указать нужную структуру контекста и сделать выборку данных. Для примера прописываю хардкодом наименование продавца:

Результат трансформации:

Остальные реквизиты заполняем аналогично.

Как видим, заполненный на Шаге 1 пример нам помогает выполнять быструю навигацию по XML и искать нужные места для доработки.

Отдельную сложность может представлять собой заполнение табличных данных. В структуре контекста имеем вложенную таблицу с данными T_INVOICE. Для вывода данных используем цикл for each. Начнём с 1 строки 1 столбца. Ищем поиском пример «Яблоки» и вставляем код, приведённый чуть ниже.

Теги описания таблицы довольно понятны: <w:tc> </w:tc> — стоблец, <w:tr </w:tr> — соответственно строка, ну и сам текст <w:t> </w:t>.

Если мы хотим каждую строку таблицы из контекста выводить в новую строку таблицы, то цикл ставим перед тегом строки и закрываем после окончания описания строки:

Конец цикла будет обозначен тут:

Так как таблица большая, окончание цикла будет через 400 строк, поэтому удобно воспользоваться опять же программой с подсветкой тегов, таким образом выводим все необходимые элементы таблицы.

Результат:

Видим, что строка автоматически добавилась. Так как нам не нужны старые данные из примера, удалим эти строки из таблицы. Ищем так же по тегам.

В идеале можно было бы в самом шаблоне оставить лишь одну строку для заполнения, тогда лишних действий по удалению колонок не пришлось бы делать. Но я хочу показать неидеальный случай.

Если необходимо вывести данные из таблицы контекста не в каждой строке таблицы, а текстом с переносом, то можем воспользоваться тегом переноса строки <w:br/>, например,

Получим вот такой результат:

Ещё немного полезных рекомендаций

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

Что ещё записано в моих заметках?

Как поменять шрифт быстро, если он перестал подходить? Допустим, мы желаем заменить Arial на Calibri. Для этого в трансформации выполняем поиск Arial — «Заменить все» и вставляем название нового шрифта Calibri.

Как сделать защиту листа и позволить редактировать лишь некоторые реквизиты в выгруженном файле?

Для этого нужно в исходном файле на 1 шаге настроить защиту листа, тогда кодирующие эту операцию теги будут отражены в нашей трансформации.

Примеры исходного кода из статьи можно увидеть в репозитории github.

Данной информации должно быть достаточно, чтобы сделать выгрузку практически любого документа быстро и эффективно.

Like this post? Please share to your friends:
  • Xml map in excel
  • Xml in word 2013
  • Xml in microsoft office word 2010
  • Xml in excel cell
  • Xml from xsd excel