Для реализации отчётов в системе Directum RX в основном используется инструмент FastReport, но бывают случаи, когда невозможно использовать его из-за некоторых ограничений.
Одним из таких ограничений является генерация диаграмм только в виде изображений, которые не поддаются ручному редактированию, а также не подхватывают изменения в данных, на основании которых построены.
У заказчика была необходимость реализовать отчёт в формате Excel, при изменении данных диаграммы должны подхватывать данные и перестраиваться после генерации отчёта.
В связи с этим, появилась необходимость реализации отчёта другими средствами. В нашем случае для реализации была выбрана библиотека Aspose.Cells.
Получить библиотеку можно на официальном сайте Aspose. Но для самостоятельной разработки новой функциональности потребуется купить лицензию на Aspose.
Для работы с xls-документом из кода, потребуется добавить библиотеку Aspose.Cells. Добавляем библиотеку в модуль через вкладку «Сторонние библиотеки»
Для демонстрации работы с документом через Aspose.Cells рассмотрим следующий упрощённый пример задания: реализовать отчёт состоящий из 2-х страниц данных в формате Excel.
Также в случае необходимости изменить визуальную составляющую диаграмм, статических ячеек или стилей (которые берутся из шаблона) не нужно будет подключать разработчиков, для этого достаточно изменить шаблон документа.
В данной статье описан подход полной реализации отчёта через код.
Первым делом нам нужно создать документ и определить листы данных с которыми будем в дальнейшем взаимодействовать.
// Название страниц
var sheetNameData = "Виды документов";
var sheetNameDiagram = "Диаграмма";
// Создаём документ
var excelDocument = new Aspose.Cells.Workbook();
// Создаём листы Excel
var sheetData = excelDocument.Worksheets.Add(sheetNameData);
var sheetDiagram = excelDocument.Worksheets.Add(sheetNameDiagram);
// Получение ячеек страницы
var cell = sheetData.Cells[0, 0]; // Ячейка А1
// Или
var cell = sheetData.Cells[“A1”];
Для ячеек мы можем устанавливать стили двумя способами.
// Копирование стиля из другой ячейки
var cellStyle = sheet.Cells["А99"].GetStyle();
sheet.Cells["A3"].SetStyle(cellStyle);
Данный способ будет полезен если у вас есть откуда брать готовые стили. К примеру, настроить стили в шаблоне и подгружать его во время генерации отчёта.
// Определение стиля из кода
var cellFactory = new Aspose.Cells.CellsFactory();
var style = cellFactory.CreateStyle();
// Жирный шрифт
style.Font.IsBold = true;
// Тип рамки: Dotted - линия рамки представлена точками.
style.Borders.DiagonalStyle = Aspose.Cells.CellBorderType.Dotted;
// Установка стиля
sheet.Cells["A3"].SetStyle(style);
Для заполнения данных на листы определим функцию.
/// <summary>
/// Добавляет строки на лист.
/// </summary>
/// <param name="document">Aspose.Cells.Workbook документ.</param>
/// <param name="sheetName">Название вкладки.</param>
/// <param name="rows">Данные для заполнения.</param>
/// <param name="startCellAddress">Адрес левой верхней ячейки.</param>
public virtual void AddRowsFromList (Aspose.Cells.Workbook document, string sheetName, List<List<object>> rows,
string startCellAddress)
{
if (!rows.Any())
return;
//Получаем лист Excel, который будем заполнять данными
var sheet = document.Worksheets.FirstOrDefault(x => x.Name == sheetName);
if (sheet == null)
return;
//Для удобства перебора преобразуем адрес в номер строки и колонки
var startCell = sheet.Cells[startCellAddress];
int rowStart = startCell.Row;
int colStart = startCell.Column;
for (var rowNum = 0; rowNum < rows.Count; rowNum++)
{
var currentRow = rowNum + rowStart;
var row = rows[rowNum];
for (var colNum = 0; colNum < row.Count; colNum++)
{
var currentCol = colNum + colStart;
var cell = sheet.Cells[currentRow, currentCol];
// Устанавливаем значения в ячейке
cell.PutValue(row[colNum]);
}
}
}
Первым делом необходимо определить sql запрос в системе.
Дублирую запрос для удобности копирования:
SELECT kind."name" , COUNT(*)
FROM sungero_content_edoc doc
JOIN sungero_docflow_documentkind kind ON kind.id = doc.documentkind_docflow_sungero
WHERE doc.created between @DateFrom AND @DateTo
GROUP BY kind."name"
Далее создаём запрос в базу данных
/// <summary>
/// Получение количества документов в разрезе документопотока.
/// </summary>
/// <param name="dateFrom">Дата начала периода.</param>
/// <param name="dateTo">Дата конца периода.</param>
/// <returns>Список с результатами запроса.</returns>
/// <description>С списком объектов будет удобнее работать при вставке данных на страницу дкоумента.</description>
public List<List<object>> GetDocumentFlow(DateTime dateFrom, DateTime dateTo)
{
// полученные данные
List<List<object>> sheet = new List<List<object>>();
// создаём подключение
using (var cmd = SQL.GetCurrentConnection().CreateCommand())
{
// выбираем созданный ранее sql запрос
cmd.CommandText = Queries.Module.DocumentFlow;
// заполняем параметры
Sungero.Docflow.PublicFunctions.Module.AddDateTimeParameterToCommand(cmd, "@DateFrom", dateFrom);
Sungero.Docflow.PublicFunctions.Module.AddDateTimeParameterToCommand(cmd, "@DateTo", dateTo);
// Выполняем и считываем данные
var reader = cmd.ExecuteReader();
while (reader.Read())
{
List<object> row = new List<object>();
var kindName = reader.GetString(0); //Название вида документа
var count = reader.GetInt32(1); //Количество документов
// Записываем в строку
row.Add(kindName);
row.Add(count);
// Добавляем строку с данными
sheet.Add(row);
}
reader.Close();
}
return sheet;
}
Имея данные и функцию занесения этих данных в отчёт можем приступить к его генерации.
В данной главе продемонстрирована лишь малая часть возможностей работы с диаграммами. Чтобы узнать все возможности работы с диаграммами обратитесь к официальной документации.
//Получаем лист Excel, в который собираемся вставить диаграмму
var worksheet = excelDocument.Worksheets.FirstOrDefault(x => x.Name == "Диаграмма");
// Добавляем диаграмму, и получаем индекс диаграммы
// Вначале указывается тип, далее размер диаграммы, первые два числа – координаты начальной ячейки (левый верхний угол) последние два-координаты конечной ячейки (правый нижний угол)
int chartIndex = worksheet.Charts.Add(Aspose.Cells.Charts.ChartType.Column, 0, 0, 18, 6);
// Получаем доступ к экземпляру недавно добавленной диаграммы
var chart = worksheet.Charts[chartIndex];
// Устанавливаем диапазон значений – Значения используемые на странице с видами документов.
chart.SetChartDataRange(string.Format("'Количество документов'!$B$3:$C${0}", 3 + countRows), true);
После выполнения данных действий получим следующую диаграмму
В данном случае заголовок соответствует легенде и будет излишним, поэтому можем от него избавиться, так же немного изменим внешний вид диаграммы.
//Жирный стиль текста
chart.ChartArea.Font.IsBold = true;
// Убираем отображение заголовка
chart.Title.IsVisible = false;
// Размещаем легенду сверху
chart.Legend.Position = Aspose.Cells.Charts.LegendPositionType.Top;
// Убираем заливку области построения
chart.PlotArea.Area.FillFormat.FillType = Aspose.Cells.Drawing.FillType.None;
//Устанавливаем тени
chart.ChartArea.ShapeProperties.ShadowEffect.PresetType = PresetShadowType.InsideCenter;
В итоге получим следующий вид у диаграммы
Так как страниц в отчёте может быть много, лучше будет разнести генерацию каждой из них в отдельную функцию.
/// <summary>
/// Заполнение документа.
/// </summary>
/// <param name="dateFrom">Дата начала периода.</param>
/// <param name="dateTo">Дата конца периода.</param>
/// <returns>Сформированный отчёт.</returns>
public virtual Aspose.Cells.Workbook DocumentFill(DateTime dateFrom, DateTime dateTo)
{
var excelDocument = new Aspose.Cells.Workbook();
IncomingDocumentsFill(excelDocument, dateFrom, dateTo);
DocumentFlowFill(excelDocument, dateFrom, dateTo);
DocumentFlowDiagram (excelDocument, dateFrom, dateTo);
return excelDocument;
}
По итогу мы имеем отчёт с следующими страницами данных.
Страница «Виды документов»
Страница «Диаграмма»
Авторизуйтесь, чтобы написать комментарий