Выгрузка выбранных записей и столбцов из таблицы с помощью C#
Введение
Здесь представлен пример скрипта для скачивания выбранных столбцов и строк из таблицы в виде файла Excel.
Скрипт запускается по нажатию кнопки.
Приведённый пример скрипта поддерживает экспорт столбцов следующих типов:
- Логический
- Число
- Длительность
- Текст
- Запись
- Дата и время
- Аккаунт
Прикладная задача
Имеется шаблон «Заявки».
Требуется экспортировать из таблицы в шаблоне «Заявки» строки и столбцы, выбранные пользователем.
Данные должны выгружаться в файл формата .XLSX
по нажатию кнопки.
Пользователь выбирает столбцы и строки для экспорта следующим образом:
- устанавливает флажки выбора в требуемых строках;
- скрывает ненужные столбцы с помощью меню «Мои настройки» — «Настроить внешний вид» .
Настройка скрипта
Логика работы скрипта
Представленный здесь скрипт работает следующим образом:
- Получает список видимых и выбранных пользователем строк (записей) в таблице.
- Получает список видимых столбцов на основе настроенного пользователем представления таблицы.
- Создаёт пустой файл Excel с помощью библиотеки
Aspose.Cells
. - Заполняет файл данными из выбранных строк и столбцов.
- Форматирует ячейки в Excel в соответствии с типом экспортируемых данных (текст, числа, даты и т. д.)
- Формирует таблицу на листе для более наглядного отображения и фильтрации данных.
- Возвращает сформированный файл пользователю для скачивания.
- Обрабатывает возможные ошибки (отсутствие выбранных записей, сбои при экспорте).
-
В шаблоне «Заявки» создайте кнопку со следующими свойствами:
- Отображаемое название: Экспортировать в Excel
- Контекст операции: запись
- Операция: C#-скрипт
- Результат выполнения: скачать документ
-
Сохраните кнопку.
-
На вкладке «Скрипт» введите следующий код:
// Импорт базовых типов и функций .NET Framework для работы с основными типами данных.
using System;
// Импорт расширений LINQ для работы с коллекциями и выполнения запросов.
using System.Linq;
// Импорт классов для обработки нажатий кнопок и возврата результатов выполнения скрипта.
using Comindware.TeamNetwork.Api.Data.UserCommands;
// Импорт основных классов для работы с данными в {{ pdroductName }}.
using Comindware.TeamNetwork.Api.Data;
// Импорт классов для работы с формами.
using Comindware.TeamNetwork.Api.Data.Forms;
// Импорт классов для работы с потоками данных, файлами и операциями ввода-вывода.
using System.IO;
// Импорт библиотеки Aspose.Cells для создания и форматирования документов Excel.
using Aspose.Cells;
// Импорт дополнительных классов Aspose.Cells для работы с таблицами и их стилями в Excel.
using Aspose.Cells.Tables;
class Script
{
// userCommandContext содержит данные контекста при нажатии кнопки.
public static UserCommandResult Main(UserCommandContext userCommandContext, Comindware.Entities entities)
{
// Получаем ID выбранных записей (строк) в таблице при нажатии кнопки.
var selectedTableRows = userCommandContext.ObjectIds as string[];
if(selectedTableRows.Count() > 0)
{
try
{
// Получаем ID экспортируемой таблицы.
var tableToExportId = userCommandContext.Query.DatasetId;
// Получаем параметры разбиения таблицы на страницы.
var paging = userCommandContext.Query.Paging;
// Получаем параметры сортировки данных в таблице.
var sorting = userCommandContext.Query.Sorting;
// Получаем параметры фильтрации данных в таблице.
var filter = userCommandContext.Query.Filter;
// Получаем ID шаблона, к которому относится таблица, по ID первой из записей.
var templateId = Api.Base.OntologyService.GetAxioms(selectedTableRows.First())["cmw.container"].First().ToString();
// Получаем все таблицы шаблона для дальнейшей обработки.
var templateTables = Api.TeamNetwork.DatasetService.GetQueries(templateId);
// Создаём пустой набор экспортируемых данных.
Dataset datasetToExport;
// Создаём пустой файл Excel для экспорта данных.
Workbook excelWorkbook = new Workbook();
// Получаем первый лист книги Excel для заполнения данными.
Worksheet excelSheet = excelWorkbook.Worksheets[0];
// Создаём стили для форматирования ячеек Excel.
var style = excelWorkbook.CreateStyle();
// Разрешаем числовые типы для форматирования ячеек.
var flag = new StyleFlag();
flag.NumberFormat = true;
// Перебираем все таблицы шаблона для поиска экспортируемой таблицы по её ID.
foreach(var table in templateTables)
{
// Применяем к таблице параметры разбиения на страницы, сортировки и фильтрации.
table.Paging = paging;
table.Sorting = sorting;
table.Filter = filter;
// Проверяем, требуется ли экспортировать таблицу.
if(table.DatasetId == tableToExportId)
{
// Получаем настроенную пользователем конфигурацию таблицы.
var personalTable = Api.TeamNetwork.DatasetConfigurationService.GetPersonalDataset(table.DatasetId);
// Получаем данные строки и столбцы таблицы, без учёта выбора пользователя.
datasetToExport = Api.TeamNetwork.DatasetService.QueryData(table);
// Создаем массив контейнеров для хранения выбранных пользователем столбцов таблицы.
var selectedTableColumns = new columnContainer[personalTable.Columns.Count()];
// Инициализируем счётчик столбцов.
var i=0;
// Перебираем все столбцы настроенной пользователем таблицы.
foreach(var coll in personalTable.Columns)
{
// Проверяем, что столбец не скрыт пользователем.
if(!coll.IsHidden)
{
// Создаём контейнер с данными столбца.
selectedTableColumns[i] = new columnContainer(coll.DataSourceInfo.Id, i);
// Записываем название столбца в заголовок Excel.
excelSheet.Cells[0,i].PutValue(coll.Name);
// Получаем путь к свойству столбца для определения его типа.
var attribute = coll.DataSourceInfo.PropertyPath.Last().ToString();
// Проверяем, что атрибут в столбце не является системным.
if(attribute != "id" && attribute != "lastWriteDate" && attribute != "creationDate" && attribute != "В архиве" && attribute != "creator" && attribute != "processes" && attribute != "isDisabled")
{
// Получаем свойства атрибута для определения его типа.
var attributeProperties = Api.Base.OntologyService.GetAxioms(attribute);
// Получаем тип атрибута.
attribute = attributeProperties["cmw.propertyType"].Last().ToString();
}
// Форматируем ячейки в соответствии с типом данных.
switch(attribute)
{
case "xsd.decimal":
{
// Устанавливаем числовой формат (код 1) для десятичных чисел.
style.Number = 1;
// Применяем формат к столбцу
excelSheet.Cells.Columns[i].ApplyStyle(style, flag);
}
break;
case "lastWriteDate":
{
// Устанавливаем формат даты (код 22) для столбца даты.
style.Number = 22;
// Применяем формат к столбцу.
excelSheet.Cells.Columns[i].ApplyStyle(style, flag);
// Устанавливаем ширину столбца для отображения даты и времени.
excelSheet.Cells.Columns[i].Width = 15;
}
break;
case "creationDate":
{
// Устанавливаем формат даты (код 22) для столбца даты создания.
style.Number = 22;
// Применяем формат к столбцу.
excelSheet.Cells.Columns[i].ApplyStyle(style, flag);
// Устанавливаем ширину столбца для отображения даты и времени.
excelSheet.Cells.Columns[i].Width = 15;
}
break;
case "xsd.dateTime":
{
// Устанавливаем формат даты (код 22) для столбца даты и времени.
style.Number = 22;
// Применяем формат к столбцу.
excelSheet.Cells.Columns[i].ApplyStyle(style, flag);
// Устанавливаем ширину столбца для отображения даты и времени.
excelSheet.Cells.Columns[i].Width = 15;
}
break;
}
// Увеличиваем счётчик столбцов.
i++;
}
}
// Инициализируем счётчик строк, начиная с 1 (0 — заголовки).
var j=1;
// Инициализируем счётчик столбцов.
var y = 0;
// Перебираем все столбцы из набора данных для экспорта.
foreach(var datasetColumn in datasetToExport.Columns)
{
try
{
// Получаем идентификатор столбца в данных для экспорта.
var columnId = datasetColumn.DataSourceInfo.Id;
// Находим индекс столбца в массиве выбранных пользователем столбцов.
var selectedColumnIndex = Array.Find(selectedTableColumns, x=> x.dataSourceId == columnId).columnIndex;
// Сохраняем позицию столбца в массиве выбранных пользователем столбцов.
selectedTableColumns[selectedColumnIndex].Position = y;
}catch{}
// Увеличиваем счётчик позиции.
y++;
}
// Перебираем все строки из набора данных.
foreach(var row in datasetToExport.Rows)
{
// Проверяем, что строка выбрана пользователем для экспорта.
if(Array.Find(selectedTableRows, v => v == row.Id) != null)
{
// Получаем данные строки.
var rowData = row.Data;
// Перебираем все видимые столбцы.
for(var jj = 0; jj < i; jj++)
{
// Получаем позицию столбца в исходных данных.
var ii = selectedTableColumns[jj].Position;
// Проверяем, что данные в ячейке не пустые.
if(rowData[ii] != null)
{
// Проверяем тип данных в ячейке и обрабатываем их соответственно.
if(rowData[ii].GetType() != typeof(Comindware.TeamNetwork.Api.Data.Forms.AccountReference) && rowData[ii].GetType() != typeof(System.Boolean) && rowData[ii].GetType() != typeof(Comindware.TeamNetwork.Api.Data.Forms.InstanceReference))
{
// Для обычных типов данных просто записываем значение в ячейку.
excelSheet.Cells[j,jj].PutValue(rowData[ii]);
}
else if (rowData[ii].GetType() == typeof(Comindware.TeamNetwork.Api.Data.Forms.AccountReference))
{
// Для ссылок на аккаунты записываем имя аккаунта.
excelSheet.Cells[j,jj].PutValue(((AccountReference)rowData[ii]).Name);
}
else if(rowData[ii].GetType() == typeof(System.Boolean))
{
// Логические значения преобразуем в строку.
if((bool)rowData[ii])
{
excelSheet.Cells[j,jj].PutValue("Истина");
}
else
{
excelSheet.Cells[j,jj].PutValue("Ложь");
}
}
else if(rowData[ii].GetType() == typeof(Comindware.TeamNetwork.Api.Data.Forms.InstanceReference))
{
// Для ссылок на записи записываем имя записи.
excelSheet.Cells[j,jj].PutValue(((Comindware.TeamNetwork.Api.Data.Forms.InstanceReference)rowData[ii]).Name);
}
}
}
// Увеличиваем счётчик строк после обработки текущей строки.
j++;
}
}
// Формируем таблицу на листе Excel:
// - Применяем фильтры к заголовкам столбцов для сортировки и фильтрации данных.
// - Применяем чередующуюся заливку строк для наглядности.
// - Применяем автоматическое форматирование заголовков.
// - Параметры таблицы:
// - начальные строка и столбец (0,0)
// - конечные строка и столбец (j-1,i-1)
// - включить заголовки (true)
ListObject listObject = excelSheet.ListObjects[excelSheet.ListObjects.Add(0,0, j-1,i-1, true)];
}
}
// Создаем поток в памяти для сохранения файла Excel.
MemoryStream stream = new MemoryStream();
// Сохраняем рабочую книгу в поток в формате XLSX.
excelWorkbook.Save(stream, SaveFormat.Xlsx);
// Формируем результат нажатия кнопки с успешным статусом.
var result = new UserCommandResult
{
Success = true,
Commited = true,
File=new UserCommandFileResult(){
Content = stream.ToArray(),
// Задаём имя файла для экспорта.
Name = "ЭкспортИзТаблицы.xlsx"
},
Messages = new[]
{
new UserCommandMessage
{
Severity = SeverityLevel.Normal,
Text = "Экспорт выполнен"
}
}
};
return result;
}
catch
{
// Формируем результат нажатия кнопки с ошибкой.
var result1 = new UserCommandResult
{
Success = false,
Commited = true,
Messages = new[]
{
new UserCommandMessage
{
Severity = SeverityLevel.Normal,
Text = "Не удалось выполнить экспорт"
}
}
};
return result1;
}
}
else
{
// Формируем результат нажатия кнопки с ошибкой, если не выбрано ни одной записи.
var result1 = new UserCommandResult
{
Success = false,
Commited = true,
Messages = new[]
{
new UserCommandMessage
{
Severity = SeverityLevel.Normal,
Text = "Выберите хотя бы одну строку таблицы для экспорта"
}
}
};
return result1;
}
}
// Вспомогательный класс для хранения информации о столбцах таблицы.
public class columnContainer
{
// Индекс выбранного пользователем столбца.
public int columnIndex {get;set;}
// Позиция столбца в исходных данных.
public int Position {get;set;}
// Идентификатор источника данных столбца.
public string dataSourceId {get;set;}
// Конструктор класса.
public columnContainer(string id , int index )
{
dataSourceId = id; columnIndex = index;
}
}
}
-
Сохраните кнопку.
- Поместите кнопку «Экспортировать в Excel» на область кнопок таблицы «Все записи» шаблона «Заявки».
Тестирование скрипта
- Откройте таблицу «Все записи» шаблона «Заявки».
- Откройте меню «Мои настройки» — «Настроить внешний вид» .
- Скройте любой из столбцов таблицы и сохраните настройки внешнего вида.
- Выберите требуемые строки в таблице с помощью флажков в левом столбце.
- Нажмите кнопку «Экспортировать в Excel».
- Браузер должен скачать файл формата
.XLSX
с выбранными данными.
Эта статья была полезна 2 чел.