В этой статье, мы рассмотрим, как создать куб в FastCube .NET с помощью кода в пользовательском приложении. Этот вопрос появится у вас сразу, когда вы начинаете работу с этой библиотекой. Ну что же, надеюсь сегодня мы проясним этот вопрос.
Файл куба может содержать как данные, так и их представление. Давайте рассмотрим на примере всю цепочку создания куба.
Создаем проект Windows Forms. В References необходимо добавить ссылки на библиотеки: FastReport, FastReport.Bars, FastReport.Olap.
Добавим на форму следующие элементы управления из toolbar:
dataSource, dtDataSet, cube, slice, sliceGrid, button.
В свойствах dataSource1 находим DataSet и выбираем доступный dtDataSet1.
В свойствах элемента управления cube1 выбираем для DataSource значение dataSource1. А для SourceType - DataSource
В свойствах slice1 выбираем Cube – cube1.
Настройте размер sliceGrid1 по форме. В его свойствах выберите Slice – slice1.
Теперь перейдем коду формы.
Прежде всего, добавим библиотеки в секцию using:
1 2 3 4 5 6 |
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Windows.Forms; using FastReport.Olap.Slice; |
Добавим следующие переменные и объекты в класс:
1 2 3 4 5 6 7 |
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; //Набор символов private Random rnd = new Random(); //объект - рандомайзер private DataTable dataTable = null; //объект - Таблица данных private int Dims = 4; //количество измерений private int Uniques = 500; //количество уникальных случайных значений private int Measures = 4; //количество показателей private int Records = 10000; //количество записей в таблице |
Здесь нужно пояснить, что мы будем заполнять таблицу фейковыми данными, просто для демонстрации возможности программной генерации данных. Кроме DataTable, мы можем использовать СУБД или stream для получения данных.
Создадим DataTable и заполним его случайными данными:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
//Метод генерации рандомной строки private string GetNewStr(int len) { len = 1 + rnd.Next(len - 1); char[] resChars = new char[len]; for (int i = 0; i < resChars.Length; i++) { resChars[i] = chars[rnd.Next(chars.Length)]; } return new string(resChars); } //Метод добавления полей в таблицу private DataTable CreateDS() { DataTable dt = new DataTable("Test"); for (int i = 0; i < Dims; i++) dt.Columns.Add("Dimension" + (i + 1), typeof(string)); for (int i = 0; i < Measures; i++) dt.Columns.Add("Measure" + (i + 1), typeof(int)); return dt; } //Метод заполнения таблицы данными private DataTable BuildDS() { DataTable dt = CreateDS(); int maxUniques = Uniques; SortedSet<string> randomStrings = new SortedSet<string>(); //Генерация уникальных значений while (randomStrings.Count < maxUniques) { randomStrings.Add(GetNewStr(10)); } int dimCount = Dims; int mesCount = Measures; object[] values = new object[dimCount + mesCount]; //Наполнение таблицы данными for (int i = 0; i < Records; i++) { for (int j = 0; j < dimCount; j++) { if (i < maxUniques) values[j] = randomStrings.ElementAt(i); else values[j] = randomStrings.ElementAt(rnd.Next(dimCount)); } for (int j = 0; j < mesCount; j++) { values[j + dimCount] = rnd.Next(255); } dt.Rows.Add(values); } return dt; } |
Итак, мы подготовили источник данных. Напомню, что вы можете использовать таблицу или представление из СУБД, либо поток данных.
Добавим в срез поля.
Теперь, для нашей единственной на форме кнопки, создадим обработчик события OnClick. И напишем следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
private void button1_Click(object sender, EventArgs e) { //Добавляем сгенерированную таблицу с данными в DataSet cube1.Close(); DataTable dt = BuildDS(); if (dataTable != null) { dataTable.Dispose(); dataTable = null; } dataTable = dt; dtDataSet1.DataTable = dataTable; dataSource1.DeleteFields(); cube1.Open(); dtDataSet1.DataTable = null; //Обновляем срез slice1.BeginUpdate(); //Добавляем поля в контейнеры for (int i = 0; i < Dims; i++) { slice1.YAxisContainer.AddSliceField(slice1.SliceFields.GetFieldByIndex(i)); } //Добавляем пустой контейнер показателей на ось X slice1.XAxisContainer.AddMeasuresField(); //Добавляем показатели в контейнер показателей for (int i = 0; i < Measures; i++) { slice1.MeasuresContainer.AddMeasure(new MeasureField( slice1, FastReport.Olap.Types.AggregateFunction.Sum, slice1.SliceFields.GetFieldByIndex(i + Dims), null, null, "Measure" + (i + 1), "Measure" + (i + 1), false )); } slice1.EndUpdate(); //Сохраняем куб в файл cube1.Save("J:/Program Files (x86)/FastReports/FastCube.Net Professional/Demos/C#/test.mdc"); } |
Вот и все. Измерения и показатели хранятся в отдельных контейнерах. Сначала мы заполнили контейнер YAxisContainer измерениями. Затем, добавили в XAxisContainer пустой список показателей. И только потом стали заполнять его показателями. Этот порядок важен для корректного отображения данных.
Чтобы было понятнее, чем мы заполняем список показателей, приведу сигнатуру конструктора класса MeasureField:
public MeasureField(Slice slice, AggregateFunction aggregateFunction, SliceField baseSliceField, SliceField distinctSliceField, SliceField extraSliceField, string name, string caption, bool distinct);
Финальной строкой нашего кода мы сохраняем куб в заданный файл.
А теперь запустим приложение и сформируем новый куб с помощью кнопки:
Как видите, создать куб в коде приложения достаточно просто. Сложнее подготовить данные для него. Но о данных для куба мы поговорим в другой статье.