С помощью технологии Smartcat Template Engine вы можете создать собственные шаблоны, по которым будут формироваться нужные вам документы. Например, вы можете создать индивидуальные бланки счетов и смет, которые вы выставляете клиентам.
Как это работает
Вы можете создавать шаблоны, используя специальные элементы разметки и заранее заданную в системе модель данных для соответствующего типа документов.
Модель данных — это набор полей, содержащих информацию об элементах модели. Для примера возьмём модель, с помощь которой будут генерироваться документ с информацией о выполненной работе. У модели будут такие поля:
Название поля |
Описание |
Name |
Наименование работы |
Price |
Цена с учётом налога |
Words |
Количество переведённых слов |
Date |
Дата завершения работы |
Executive.FirstName |
Имя исполнителя |
Executive.LastName |
Фамилия исполнителя |
Executive.Price |
Ставка исполнителя за слово |
Шаблон содержит текст и специальные теги, используемые для вывода или подстановки данных из модели. Для вывода нужного поля используйте конструкцию <<[Field1]>>, где Field1 — название поля.
Пример шаблона для вывода информации о выполненной работе:
Шаблон |
Результат |
Проект: <<[Name]>> Дата сдачи: <<[Date]>> Исполнитель: <<[Executive.FirstName + “ ” + Executive.LastName]>> Ставка исполнителя: <<[Executive.Price * Words]>> |
Проект: PRESS_RELEASE_APR2020 Дата сдачи: 22.04.2020 Исполнитель: Артём Филатов Ставка исполнителя: 0.44 |
В шаблоне можно использовать арифметические операции — сложение (+), вычитание (–), умножение (*) и деление (/). Их можно применять к содержимому числовых полей модели, таким как цена или количество перевёденных слов. Содержимое строковых полей, таких как имя исполнителя, можно выводить одно за другим, а также вместе с произвольными строками. В примере выше из имени и фамилии формируется полное имя исполнителя.
Продвинутые функции
Циклы
Чтобы вывести массивы данных, можно использовать циклы. Цикл выглядит так:
<<foreach [item in Items]>>
<<[item]>>
<</foreach>>
Здесь Items — массив данных, item — элемент из массива, а [item] — вывод значения элемента.
Примеры циклов
Скажем, в массиве Items лежат строковые значения item1, item2 и item3. Шаблон и результат будут такими:
Шаблон |
Результат |
<<foreach [item in items]>> <<[item]>> <</foreach>> |
item1 item2 item3 |
Выведем значения в виде нумерованного списка:
Шаблон |
Результат |
1. <<foreach [item in items]>> <<[item]>> <</foreach>> |
|
Вывод данных в таблицах с помощью циклов
Скажем, у нас есть модель данных Contracts со списком договоров. Каждый договор содержит информацию о стоимости, клиенте и менеджере. Описание полей модели Contract:
Название поля |
Описание |
Clients.Name |
Название компании клиента |
Price |
Стоимость в договоре |
Managers.Name |
Имя менеджера |
Создадим на основе этой модели шаблон:
Клиент |
Менеджер |
Стоимость в договоре |
<<foreach [ c in Contracts ]>><<[c.Clients.Name]>> |
<<[c.Managers.Name]>> |
<<[c.Price]>><</foreach>> |
Total: |
<<[Contracts.Sum(c => c.Price)]>> |
Результат:
Клиент |
Менеджер |
Стоимость в договоре |
A Company |
John Smith |
1200000 |
B Ltd. |
John Smith |
750000 |
C & D |
John Smith |
350000 |
E Corp. |
Tony Anderson |
650000 |
F & Partners |
Tony Anderson |
550000 |
G & Co. |
July James |
350000 |
H Group |
July James |
250000 |
I & Sons |
July James |
100000 |
J Ent. |
July James |
100000 |
Total: |
4300000 |
Немного изменим модель данных. Теперь у нас есть список менеджеров, у каждого менеджера — список договоров, у каждого договора — клиент.
Шаблон:
Менеджер/Клиент |
Стоимость в договоре |
<<foreach [ m in Managers ]>><<[m.Name]>> |
<<[m.Contracts.Sum(c => c.Price)]>> |
<<foreach [ c in m.Contracts ]>> <<[c.Clients.Name]>> |
<<[c.Price]>><</foreach>><</foreach>> |
Total: |
<<[Contracts.Sum(c => c.Price)]>> |
Результат:
Менеджер/Клиент |
Стоимость в договоре |
John Smith |
2300000 |
A Company |
1200000 |
B Ltd. |
750000 |
C & D |
350000 |
Tony Anderson |
1200000 |
E Corp. |
650000 |
F & Partners |
550000 |
July James |
800000 |
G & Co. |
350000 |
H Group |
250000 |
I & Sons |
100000 |
J Ent. |
100000 |
Total: |
4300000 |
Перечислим клиентов для каждого менеджера.
Шаблон:
Менеджер |
Клиенты |
<<foreach [ m in Managers ]>><<[m.Name]>> |
<<foreach [ c in m.Contracts ]>><<[c.Clients.Name]>> <</foreach>><</foreach>> |
Результат:
Менеджер |
Клиенты |
John Smith |
A Company B Ltd. C & D |
Tony Anderson |
E Corp. F & Partners |
July James |
G & Co. H Group I & Sons J Ent. |
Создадим шаблон для вывода таблицы с одной колонкой, используя опцию “-greedy”.
Шаблон:
Менеджеры |
<<foreach [m in ds.Managers]>><<[m.Name]>><</foreach -greedy>> |
Результат:
Менеджеры |
John Smith |
Tony Anderson |
July James |
Условные операторы
Чтобы вывести ту или иную информацию в зависимости от описанных условий, используйте условные операторы:
<<if [conditional_expression1]>>
template_option1
<<elseif [conditional_expression2]>>
template_option2
...
<<else>>
default_template_option
<</if>>
Здесь conditional_expression — проверка условия, возвращающее одно из двух значений: “true” («правда») или “false” («ложь»).
Скажем, у нас есть модель данных с массивом Items, в котором лежат строковые значения item1, item2 и item3, Создадим шаблон, который проверит, есть ли элементы в массиве ([!items.Any()]). Если есть, шаблон выведет количество элементов, иначе — сообщение no items.
Шаблон |
Результат |
You have chosen <<if [!items.Any()]>>no items<<else>><<[items.Count()]>> item(s)<</if>>. |
You have chosen 3 item(s). |
Используя функцию IndexOf(), выделим чётные элементы жёлтым:
Шаблон |
Результат |
<<foreach [item in items]>><<if [IndexOf() % 2 == 0]>><<[item]>> |
item1 |
Выведем все элементы массива, а если их нет — сообщение No data.
<<if [!items.Any()]>>No data.
<<else>><<foreach [item in items]>><<[item]>>
<</foreach>><</if>>
Таблицы и условные операторы
Используя условные операторы, можно выводить те или иные данные, а также в зависимости от условий применять стили к строкам таблиц. В таблице ниже, строки, относящиеся к разным опциям условного оператора, залиты соответствующими цветами.
<<if ...>> ... |
... |
... |
... |
... |
... |
<<elseif ...>> ... |
... |
... |
... |
... |
... |
<<else>> ... |
... |
... |
... |
... |
... |
... |
... |
... <</if>> |
|
|
|
Рассмотрим в качестве модели данных список клиентов. Описание полей модели Client:
Название поля |
Описание |
Name |
Наименование |
Country |
Страна |
LocalAddress |
Адрес |
Рассмотрим шаблон, который выводит данные по всем клиентам в таблицу. Клиенты из Новой Зеландии (“New Zealand”) будут выделены зёленым, относящиеся к ним столбцы будут объединены, а из полей будет выведено только поле “LocalAddress”.
... |
... |
... |
<<foreach [in clients]>><<if [Country == “New Zealand”]>><<[Name]>> |
<<[LocalAddress]>> |
|
<<else>><<[Name]>> |
<<[Country]>> |
<<[LocalAddress]>><</if>><</foreach>> |
... |
... |
... |
Результат:
A Company |
Australia |
219-241 Cleveland St STRAWBERRY HILLS NSW 1427 |
B Ltd. |
Brazil |
Avenida João Jorge, 112, ap. 31 Vila Industrial Campinas — SP 13035-680 |
C & D |
Canada |
101-3485 RUE DE LA MONTAGNE MONTRÉAL (QUÉBEC) H3G 2A6 |
E Corp. |
445 Mount Eden Road Mount Eden Auckland 1024 |
|
F & Partners |
20 Greens Road Tuahiwi Kaiapoi 7691 |
|
G & Co. |
Greece |
Karkisias 6 GR-111 42 ATHINA GRÉCE |
H Group |
Hungary |
Budapest Fiktív utca 82., IV. em./28. 2806 |
I & Sons |
43 Vogel Street Roslyn Palmerston North 4414 |
Ниже — шаблон, который выдаст соответствующее сообщение, если данных нет:
Клиент |
Страна |
Адрес |
<<if [!clients.Any()]>>No data |
||
<<else>><<foreach [in clients]>><<[Name]>> |
<<[Country]>> |
<<[LocalAddress]>><</foreach>><</if>> |
Результат:
Client |
Country |
Local Address |
No data |
Шаблон:
Шаблон |
Результат |
Header <<if [false]>>Content to remove<</if>> Footer |
Header Footer |
Применим опцию “-greedy” к шаблону выше:
Шаблон |
Результат |
Header <<if [false]>>Content to remove<</if -greedy>> Footer |
Header Footer |
Вспомогательные методы для работы с массивами
Технология Smartcat Template Engine позволяет гибко работать с массивами данных, используя вспомогательные методы (методы расширения).
Скажем, у нас есть модель данных, содержащая поле persons — список сотрудников.
Описание полей модели Person (информация о сотруднике):
Название поля |
Описание |
Name |
Имя сотрудника |
Age |
Возраст сотрудника |
Subordinates |
Список подчинённых сотрудников |
Salary |
Зарплата сотрудника |
Создадим шаблон для вывода имен сотрудников старше 50 лет:
Шаблон |
Результат |
<<foreach [person in persons.All(p => p.Age > 50)]>> <<[person.Name]>> <</foreach>> |
Иван Петров Андрей Козлов Виктор Кошкин |
А теперь выведем сумму зарплат всех сотрудников:
Шаблон |
Результат |
<<[persons.Sum( p => p.Salary)]>> |
490000 |
В таблице ниже приведено описание всех доступных методов. В качестве примера используется модель данных с двумя массивами: persons и otherPersons. Оба содержат информацию о сотрудниках.
Функция |
Пример |
All(Predicate) |
persons.All(p => p.Age < 50) |
Any() |
persons.Any() |
Average(Selector) |
persons.Average(p => p.Age) |
Concat(IEnumerable) |
persons.Concat(otherPersons) |
Contains(Object) |
persons.Contains(otherPersons.First()) |
Count() |
persons.Count() |
Count(Predicate) |
persons.Count(p => p.Age > 30) |
Distinct() |
persons.Distinct() |
First() |
persons.First() |
First(Predicate) |
persons.First(p => p.Age > 30) |
FirstOrDefault() |
persons.FirstOrDefault() |
FirstOrDefault(Predicate) |
persons.FirstOrDefault(p => p.Age > 30) |
GroupBy(Selector) |
persons.GroupBy(p => p.Age) Or persons.GroupBy( p => new { Age = p.Age, Count = p.Children.Count() }) |
Last() |
persons.Last() |
Last(Predicate) |
persons.Last(p => p.Age > 100) |
LastOrDefault() |
persons.LastOrDefault() |
LastOrDefault(Predicate) |
persons.LastOrDefault(p => p.Age > 100) |
Max(ComparableSelector) |
persons.Max(p => p.Age) |
Min(ComparableSelector) |
persons.Min(p => p.Age) |
OrderBy(ComparableSelector) |
persons.OrderBy(p => p.Age) Or persons.OrderBy(p => p.Age) .ThenByDescending(p => p.Name) Or persons.OrderBy(p => p.Age) .ThenByDescending(p => p.Name) .ThenBy(p => p.Children.Count()) |
OrderByDescending(ComparableSelector) |
persons.OrderByDescending(p => p.Age) Or persons.OrderByDescending(p => p.Age) .ThenByDescending(p => p.Name) Or persons.OrderByDescending(p => p.Age) .ThenByDescending(p => p.Name) .ThenBy(p => p.Children.Count()) |
Single() |
persons.Single() |
Single(Predicate) |
persons.Single( p => p.Name == "John Smith") |
SingleOrDefault() |
persons.SingleOrDefault() |
SingleOrDefault(Predicate) |
persons.SingleOrDefault( p => p.Name == "John Smith") |
Skip(int) |
persons.Skip(10) |
SkipWhile(Predicate) |
persons.SkipWhile(p => p.Age < 21) |
Sum(Selector) |
persons.Sum(p => p.Children.Count()) |
Take(int) |
persons.Take(5) |
TakeWhile(Predicate) |
persons.TakeWhile(p => p.Age < 50) |
Union(IEnumerable) |
persons.Union(otherPersons) |
Where(Predicate) |
persons.Where(p => p.Age > 18) |
Информация для разработчиков
Smartcat Template Engine использует подмножество языка C# (C# Language Specification 5.0) в синтаксисе шаблона. Для всех примитивных типов можно использовать методы из BCL, например для строк. Методы, описанные в параграфе «Вспомогательные методы для работы с массивами» — это методы расширения для языка запросов LINQ.
Похожие статьи:
- Нет похожих статей
Информация оказалась полезной?