Перейти к содержанию

Использование расширений в карточке шаблона файла

Использование расширений в карточке шаблона файла

С помощью расширений можно воздействовать на результат, возвращаемый плейсхолдерами, а также изменить сам документ (изменить стиль, шрифт, форматирование текста документа).

В каждом сценарии расширения используется объект context, в котором, в зависимости от сценария, заполненые различные свойства (см. Расширения замены плейсхолдеров).

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

Примеры использования сценария Перед формированием документа:

  1. Инициализация параметров, которые могут быть использованы в других сценариях:

    // Запись производится в context.Info, который является общим для всех выполняемых сценариев context.Info["MagicNumber"] = 42; context.Info["MagicWord"] = "Thanks";

  2. Изменение значений всех определенных плейсхолдеров другими:

    // Берем список всех не табличных плейсхолдеров, и для определенных плейсхолдеров подмениваем их результат var replacements = context.ReplacementContext.Replacements; for (int i = 0; i < replacements.Count; i++) { var replacement = replacements[i];

    if (replacement.Placeholder.Value == "$Workplaces_User_MyTasks") { // Подмениваем старый объект IPlaceholderReplacement на новый с новым результатом replacements[i] = new PlaceholderReplacement( replacement.Placeholder, await context.GetPlaceholderValueAsync("$ApprovalHistory_ActiveTasks")); } }

Примеры использования сценария Перед формированием таблицы:

  1. Изменение значения конкретной колонки для каждой строки:

    // Для каждой строки таблицы берем ее значения по определенной колонке и дописываем к ним magicNumber var magicNumber = context.Info.TryGet<int>("MagicNumber"); foreach(var row in context.Table.Rows) { var fields = row.TryGetFields("TaskInfo");

    if (fields != null) { row["TaskInfo"] = fields .Select(x => new PlaceholderField(x.Value?.ToString() + magicNumber, x.DataType, x.Flags)) .ToList(); } }

  2. Инициализация необходимых для обработки таблицы параметров (например, инициализация кастомного нумератора строк в таблице):

    // Для таблицы записываем число строк в ней, чтобы использовать его как новый номер строки, но в обратном порядке var table = context.Table; table.Info["RowIndex"] = context.Table.Rows.Count;

Примеры использования сценария Перед формированием строки:

  1. Изменение значения конкретной колонки для текущей строки:

    // Для текущей строки таблицы берем ее значения по определенной колонке и дописываем к ним magicWord var magicWord = context.Info.TryGet<string>("MagicWord"); var fields = context.Row.TryGetFields("TaskInfo");

    if (fields != null) { context.Row["TaskInfo"] = fields .Select(x => new PlaceholderField(magicWord + x.Value?.ToString(), x.DataType, x.Flags)) .ToList(); }

  2. Реализация кастомной нумерации внутри таблицы:

    // Производим подмену значения, которое вернет плейсхолдер {n}, тем самым организовав обратную нумерацию строк в таблице // Инициализацию данного параметра следует проводить в сценарии Перед формированием таблицы var index = context.Table.Info.TryGet<int>("RowIndex"); var row = context.Row;

    row.Number = index; context.Table.Info["RowIndex"] = index - 1;

Примеры использования сценария Перед заменой плейсхолдера:

  1. Модификация результата плейсхолдера:

    // Для заданных плейсхолдеров обновляем их результат if (context.Placeholder.Text == "{*t_role}") { context.PlaceholderValue = await context.GetPlaceholderValueAsync("tv:AuthorName"); } else if (context.Placeholder.Text == "{*t_result}") { context.PlaceholderValue = new PlaceholderValue("Комментарий: " + context.PlaceholderValue.Text, context.PlaceholderValue.Fields); }

В сцеанариях После формирования документа/таблицы/строки и После замены плейсхолдера предполагается постобработка уже сформированного результата. В зависимости от типа документа это может быть изменение самого текста результата, изменение стиля (цвет фона, цвет текста, стиль и шрифт текста). В зависимости от типа документа (.docx, .xlsx, .txt, .html) воздействия на результат производятся по разному.

Документ Word

При обработке документов Word в качестве параметра context передается объект с типом WordPlaceholderReplaceExtensionContext. Со всеми свойства данного контекста можно ознакомиться в API.

Для ознакомления с внутренней структурой документа Word рекомендуется использовать утилиту “Open XML SDK 2.5 Productivity Tool”.

Примеры использования сценария После замены плейсхолдера:

  1. Изменение фона ячейки определенных плейсхолдеров:

    #using DocumentFormat.OpenXml.Wordprocessing;

    // После замены заданного плейсхолдера, производим расчет просрочки задания и добавляем подсветку ячейки, в которой находился искомый плейсхолдер. // Аналогично подсветки ячеек в представлении "Мои задания" if (context.Placeholder.Text == "{*t_completed}") { var qn = await context.GetValueFromPlaceholderAsync<long>("tv:QuantsToFinish"); if (qn < 0) { var wordContext = context.As<WordPlaceholderReplaceExtensionContext>(); qn = Math.Max(-320, qn); var color = (255 + qn * 127 / 320).ToString("X");

    var shading = new Shading() { Val = ShadingPatternValues.Clear, Color = "auto", Fill = "FF" + color + color, };

    wordContext.PlaceholderElements[0].Parent.Parent.GetFirstChild<TableCellProperties>()?.Append(shading); } }

  2. Изменение стиля текста для определенных плейсхолдеров:

    #using DocumentFormat.OpenXml.Wordprocessing;

    // Текст замененного плейсхолдера делаем жирным и подчеркнутым if (context.Placeholder.Text == "{*t_role}") { var wordContext = context.As<WordPlaceholderReplaceExtensionContext>(); Underline underline1 = new Underline(){ Val = UnderlineValues.Single }; Bold bold1 = new Bold();

    foreach(var run in wordContext.PlaceholderElements) { var runProps = run.GetFirstChild<RunProperties>(); if (runProps == null) { runProps = new RunProperties(); run.InsertAt(runProps, 0); } runProps.Append(bold1); runProps.Append(underline1); } }

Примеры использования сценария После формирования строки:

  1. Изменение фона всей строки на зеленый цвет:

    #using DocumentFormat.OpenXml.Wordprocessing;

    // Производим сменц цвета фона всех ячеек строки, если задание, по которому сформирована строка, не просрочена var qn = await context.GetValueFromPlaceholderAsync<long>("tv:QuantsToFinish"); if (qn >= 0) { var wordContext = context.As<WordPlaceholderReplaceExtensionContext>(); foreach(var cell in wordContext.CurrentRowElement.Elements<TableCell>()) { var greenShading = new Shading() { Val = ShadingPatternValues.Clear, Color = "auto", Fill = "92D050", }; cell.GetFirstChild<TableCellProperties>()?.Append(greenShading); } }

  2. Изменение высоты строки таблицы:

    #using DocumentFormat.OpenXml.Wordprocessing;

    var rowProps = wordContext.CurrentRowElement.GetFirstChild<TableRowProperties>(); // Если в элементе текущей строки нет объекта TableRowProperties, то создаем его и добавляем в строку. // Элементы вида Properties должны находиться на первом месте внутри объекта. if (rowProps == null) { rowProps = new TableRowProperties(); wordContext.CurrentRowElement.InsertAt(rowProps, 0); }

    // Высота рассчитывается в двадцатых частях от point. В свою очередь point - это 1/72 дюйма TableRowHeight tableRowHeight1 = new TableRowHeight(){ Val = (UInt32Value)20U * 40U }; // высота строки = 5/9 дюйма rowProps.Append(tableRowHeight1);

Примеры использования сценария После формирования таблицы:

  1. Изменение ширины таблиы и ее вырванивания в тексте:

    #using DocumentFormat.OpenXml.Wordprocessing;

    var wordContext = context.As<WordPlaceholderReplaceExtensionContext>();

    var tableProps = wordContext.TableElement.GetFirstChild<TableProperties>(); var tableWidth = tableProps.GetFirstChild<TableWidth>(); var tableJustification = tableProps.GetFirstChild<TableJustification>();

    if (tableJustification is null) { tableJustification = new TableJustification(); tableProps.Append(tableJustification); }

    // Определяем, в чем мы будем рассчитывать ширину tableWidth.Type = TableWidthUnitValues.Pct;

    // Задаем ширину в пятидесятых частях процента. tableWidth.Width = (50 * 80).ToString(); // 80%

    tableJustification.Val = TableRowAlignmentValues.Center;

  2. Изменение шрифта всего текста в таблице:

    #using DocumentFormat.OpenXml.Wordprocessing;

    var wordContext = context.As<WordPlaceholderReplaceExtensionContext>();

    // Находим каждый элемент RunFonts в тексте и меняем шрифт в нем на нужным нам foreach(var fonts in wordContext.TableElement.Descendants<RunFonts>()) { fonts.Ascii = "Times New Roman"; fonts.HighAnsi = "Times New Roman"; fonts.ComplexScript = "Times New Roman"; fonts.EastAsia = "Times New Roman"; }

Примеры использования сценария После формирования документа:

  1. Установка заливки фона документа:

    #using DocumentFormat.OpenXml.Wordprocessing; #using DocumentFormat.OpenXml.Vml; #using DocumentFormat.OpenXml.Vml.Office;

    var wordContext = context.As<WordPlaceholderReplaceExtensionContext>();

    // Генерация объекта фона DocumentBackground documentBackground1 = new DocumentBackground() { Color = "E2EFD9", ThemeColor = ThemeColorValues.Accent6, ThemeTint = "33" };

    Background background1 = new Background() { Id = "_x0000_s1025", Fillcolor = "#e2efd9 [665]", BlackWhiteMode = BlackAndWhiteModeValues.White, TargetScreenSize = ScreenSizeValues.Sz1024x768 };

    Fill fill1 = new Fill(){ Type = FillTypeValues.Gradient, Color2 = "fill lighten(0)", Method = FillMethodValues.Linearsigma };

    background1.Append(fill1);

    documentBackground1.Append(background1);

    wordContext.Document.MainDocumentPart.RootElement.InsertAt(documentBackground1, 0);

    // Установка информации, что используется фон wordContext.Document.MainDocumentPart.DocumentSettingsPart.Settings.DisplayBackgroundShape = new DisplayBackgroundShape();

Документ Excel

При обработке документов Excel в качестве параметра context передается объект с типом ExcelPlaceholderReplaceExtensionContext. Со всеми свойствами данного контекста можно ознакомиться в API.

Для ознакомления с внутренней структурой документа Excel рекомендуется использовать утилиту “Open XML SDK 2.5 Productivity Tool”.

Примеры использования сценария После замены плейсхолдера:

  1. Изменение фона ячейки определенных плейсхолдеров:

    #using DocumentFormat.OpenXml.Spreadsheet;

    var excelContext = context.As<ExcelPlaceholderReplaceExtensionContext>(); var stylesheet = excelContext.Document.WorkbookPart.WorkbookStylesPart.Stylesheet;

    void UpdateCellStyle(Cell cell, long qn) { // Кешируем ID стиля в контекст по цвету, чтобы не генерировать кучу одинаковых стилей qn = Math.Max(-320, qn); var color = (255 + qn * 127 / 320).ToString("X"); if (!context.Info.TryGetValue("StyleID" + color, out var styleID)) { Fill fill1 = new Fill();

    PatternFill patternFill1 = new PatternFill(){ PatternType = PatternValues.Solid }; ForegroundColor foregroundColor1 = new ForegroundColor(){ Rgb = "FF" + color + color }; BackgroundColor backgroundColor1 = new BackgroundColor(){ Indexed = (UInt32Value)64U };

    patternFill1.Append(foregroundColor1); patternFill1.Append(backgroundColor1);

    fill1.Append(patternFill1); stylesheet.Fills.Append(fill1); var fillID = stylesheet.Fills.Count() - 1;

    var oldStyleID = cell.StyleIndex.Value; var newFormat = (CellFormat)stylesheet.CellFormats.ChildElements[Convert.ToInt32(oldStyleID)].CloneNode(true); newFormat.FillId = (UInt32Value)Convert.ToUInt32(fillID); newFormat.ApplyFill = true;

    stylesheet.CellFormats.Append(newFormat); styleID = (UInt32Value)Convert.ToUInt32(stylesheet.CellFormats.Count() - 1); context.Info["StyleID" + color] = styleID; } cell.StyleIndex = (UInt32Value)styleID; }

    if (context.Placeholder.Text == "{*t_completed}") { var qn = await context.GetValueFromPlaceholderAsync<long>("tv:QuantsToFinish"); if (qn < 0) { UpdateCellStyle(excelContext.Cell, qn); } }

  2. Изменение стиля текста для определенных плейсхолдеров:

    #using DocumentFormat.OpenXml.Spreadsheet;

    // Текст замененного плейсхолдера делаем жирным и подчеркнутым if (context.Placeholder.Text == "{*t_role}") { // Т.к. у всех ячеек с данным плейсхолдером один и тот же стиль, генерируем новйы стиль один раз, а для остальных ячеек используем его if (!context.Info.TryGetValue("RoleStyleID", out var roleStyleID)) { var oldStyleID = excelContext.Cell.StyleIndex.Value; var newFormat = (CellFormat)stylesheet.CellFormats.ChildElements[Convert.ToInt32(oldStyleID)].CloneNode(true);

    var oldFontID = newFormat.FontId.Value; var newFont = (Font)stylesheet.Fonts.ChildElements[Convert.ToInt32(oldFontID)].CloneNode(true);

    newFont.Append(new Bold()); newFont.Append(new Underline());

    stylesheet.Fonts.Append(newFont); newFormat.FontId = (UInt32Value)Convert.ToUInt32(stylesheet.Fonts.Count() - 1);

    stylesheet.CellFormats.Append(newFormat); roleStyleID = (UInt32Value)Convert.ToUInt32(stylesheet.CellFormats.Count() - 1); context.Info["RoleStyleID"] = roleStyleID; }

    excelContext.Cell.StyleIndex = (UInt32Value)roleStyleID; }

Примеры использования сценария После формирования строки:

  1. Изменение фона всей строки на зеленый цвет:

    #using DocumentFormat.OpenXml.Spreadsheet;

    var excelContext = context.As<ExcelPlaceholderReplaceExtensionContext>(); var stylesheet = excelContext.Document.WorkbookPart.WorkbookStylesPart.Stylesheet;

    void UpdateRowStyle(Row row) { // Цвет строки задается через цвета ее ячеек. // У каждой колонки может быть свой стиль, рассчитываем стили для каждой ячейки один раз и кешируем идентификатор стиля foreach(var cell in row.Elements<Cell>()) { if (!context.Info.TryGetValue("RowStyleID" + cell.CellReference.Value[0], out var styleID)) { Fill fill1 = new Fill();

    PatternFill patternFill1 = new PatternFill(){ PatternType = PatternValues.Solid }; ForegroundColor foregroundColor1 = new ForegroundColor(){ Rgb = "92D050" }; BackgroundColor backgroundColor1 = new BackgroundColor(){ Indexed = (UInt32Value)64U };

    patternFill1.Append(foregroundColor1); patternFill1.Append(backgroundColor1);

    fill1.Append(patternFill1); stylesheet.Fills.Append(fill1); var fillID = stylesheet.Fills.Count() - 1;

    var oldStyleID = cell.StyleIndex.Value; var newFormat = (CellFormat)stylesheet.CellFormats.ChildElements[Convert.ToInt32(oldStyleID)].CloneNode(true); newFormat.FillId = (UInt32Value)Convert.ToUInt32(fillID); newFormat.ApplyFill = true;

    stylesheet.CellFormats.Append(newFormat); styleID = (UInt32Value)Convert.ToUInt32(stylesheet.CellFormats.Count() - 1); context.Info["RowStyleID" + cell.CellReference.Value[0]] = styleID; } cell.StyleIndex = (UInt32Value)styleID; } }

    // Производим сменц цвета фона всех ячеек строки, если задание, по которому сформирована строка, не просрочена var qn = await context.GetValueFromPlaceholderAsync<long>("tv:QuantsToFinish"); if (qn >= 0) { UpdateRowStyle(excelContext.CurrentRowElement); }

  2. Изменение высоты строки таблицы:

    // Высота задается в point, который равен 1/72 дюйма excelContext.CurrentRowElement.Height = 40D; // 5/9 дюйма

Примеры использования сценария После формирования таблицы:

  1. Изменение ширины колонок в листе, где располагается таблица:

    #using DocumentFormat.OpenXml.Spreadsheet;

    var excelContext = context.As<ExcelPlaceholderReplaceExtensionContext>(); var columns = excelContext.Worksheet.GetFirstChild<Columns>();

    foreach(Column column in columns.ChildElements) { // Изменяем ширину для первых 5 колонок. Нумерация колонок ведется с 1 if (column.Min.Value > 0U && column.Max.Value <= 5U) { column.Width = 40D; } }

Примеры использования сценария После формирования документа:

  1. Изменение шрифта текста документа:

    #using DocumentFormat.OpenXml.Spreadsheet;

    var excelContext = context.As<ExcelPlaceholderReplaceExtensionContext>(); var stylesheet = excelContext.Document.WorkbookPart.WorkbookStylesPart.Stylesheet;

    // Задаем каждому объекту Font нужный шрифт foreach(Font font in stylesheet.Fonts.ChildElements) { font.FontName = new FontName(){ Val = "Times New Roman" }; font.FontFamilyNumbering = new FontFamilyNumbering(){ Val = 2 }; }

    // Указываем каждому стилю, что нужно применить шрифт, указанный в стиле foreach(CellFormat style in stylesheet.CellFormats.ChildElements) { style.ApplyFont = true; }

Back to top