Cross-tab и типизированный датасет
Добрый день,
мне нужно построить репорт типа Cross-tab, подключаемый к датасету. Проблема в том, что именно та таблица, которую нужно подключить к репорту, в ДБ не существует, а только в датасете (и заполняется соответственно кодом).
Вопрос - как объяснить это FastReport Designer'y?
DataSetDemo из примеров я смотрел, но там обычный репорт. А у меня Cross-tab выбрасывает привязку к полям, если ее сделать руками.
мне нужно построить репорт типа Cross-tab, подключаемый к датасету. Проблема в том, что именно та таблица, которую нужно подключить к репорту, в ДБ не существует, а только в датасете (и заполняется соответственно кодом).
Вопрос - как объяснить это FastReport Designer'y?
DataSetDemo из примеров я смотрел, но там обычный репорт. А у меня Cross-tab выбрасывает привязку к полям, если ее сделать руками.
Комментарии
Мы планируем ввести нативную поддержку объектов данных .NET.
Ваш пример позволил бы решить проблему на этапе проектирования.
Примерный код см. ниже
FrxDataTable m_DT = null;
................
void RunDesigner()
{
InitDataSet();
TfrxReportClass report = new TfrxReportClass();
report.DesignReport();
}
void InitDataSet()
{
DataTable dt = GetDataTable(); // тут получить таблицу
m_DT = new FrxDataTable(dt);
InitData( dt);
}
void InitData(DataTable dt)
{
InitColumns( dt ); // создаем поля таблицы
InitRows ( dt ); // заполняем данными
}
void InitColumns(DataTable dt )
{
foreach(DataColumn dc in dt.Columns)
{
DataColumn dcol = new DataColumn(dc.ColumnName,
dc.DataType,
dc.Expression,
dc.ColumnMapping);
m_DT.Columns.Add( dcol );
}
}
void InitRows(DataTable dt )
{
foreach( DataRow sourceRow in dt.Rows )
{
DataRow r = m_DT.NewRow();
foreach(DataColumn dc in dt.Columns)
{
r[dc.ColumnName] = sourceRow[dc.ColumnName];
}
m_DT.Rows.Add( r );
}
m_DT.AcceptChanges();
}
нужно создать новый конструктор для FrxDataTable
public FrxDataTable(DataTable dt)
{
m_ds = new TfrxUserDataSetClass();
if( dt == null)
throw( new Exception("Error Create FrxTable") );
m_ds.Name = dt.TableName;
this.TableName = dt.TableName;
InitEvent();
}
void InitEvent()
{
m_ds.OnCheckEOF += new IfrxUserDataSetEvents_OnCheckEOFEventHandler(OnCheckEOFEventHandler);
m_ds.OnGetValue += new IfrxUserDataSetEvents_OnGetValueEventHandler(OnGetValueHandler);
m_ds.OnFirst += new IfrxUserDataSetEvents_OnFirstEventHandler(OnFirstEventHandler);
m_ds.OnNext += new IfrxUserDataSetEvents_OnNextEventHandler(OnNextEventHandler);
m_ds.OnPrior += new IfrxUserDataSetEvents_OnPriorEventHandler(OnPriorEventHandler);
DataColumnCollection cols = Columns;
cols.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(ColumnsCollection_Changed);
}
спасибо, но я это уже понял, разбирая пример из DataSetDemo. Т.е. как из кода передать данные я вроде бы придумал - унаследую FrxDataSet от моего типизированного и сделаю конструктор с параметром моего датасета. В нем через Merge перелью данные из всех parent-таблиц, а child-таблицы буду заполнять теми же функциями, которые сейчас заполняют их в моем типизированном датасете.
Проблема только в одном - как сделать дизайн репорта? Надо бы загрузить схему датасета в FR-Designer, но такой функциональности нет.
2 alman
пример данных - запросто. :-) Прямо сюда xsd-схему запостить (она большая) или на мейл?
В общих чертах - у меня есть datatable как часть типизированного датасета. Содержит состояния банковских счетов фирм (т.е. есть н-фирм, у каждой из них м-счетов) на опр. дату.
Таким образом мне нужна кросс-таб примерно такого вида:
24.10.05 25.10.05 .... и т.д. бесконечно
фирма1 б.счет1 1200€ 1300€
б.счет2 150€ -278€
сумма-фирма1 1350€ 1022€
фирма2 б.счет1
б.счет2
сумма-фирма2
Причем на самом деле я храню естественно не состояния, а входящие\исходящие оплаты. Т.е. в идеале мне нужно было бы, чтобы кросс-таб еще и нарастающие итоги умел считать. Но поскольку мы до сих пор болели Crystal'ом, а он это не мог, то на данный момент я это обсчитываю сам. Если FR это сможет, с радостью переложу на его плечи.
На данный момент проблема, как я уже написал выше, - как мне передать схему датасета в FR-Designer? Сейчас, если я в Cross-Tab Editor вписываю Expressions руками, то они просто выбрасываются. Взять DBCrossTab-объект я не могу, потому что именно этой дататейбл в базе нет, она "вычисляемая", продукт обработки нескольких других таблиц.
А нужно только таблицы загнать в массив, например
FrxDataTable [] m_DT = null;
.......................
void InitDataSet()
{
// получить Ваш датасет
DataSet ds = GetDataSet();
m_DT = new FrxDataTable[ds.Tables.Count];
int i = 0;
foreach( DataTable dt in ds.Tables)
{
m_DT = new FrxDataTable(dt);
InitData( i, dt);
}
}
И далее в методах
InitColumns(int i, DataTable dt )
InitRows(int i, DataTable dt )
использовать i-ю таблицу массива (m_DT ), но возможны и другие варианты.
В дизайнере все таблицы видны. Что касается Relations - нужно создать самому по исходному датасету.
Менять базовые классы не советую - разработчики могут чего-то тоже изменить и тогда ничего работать не будет
все-таки мы немного о разных вещах говорим. Мне нужно передать схему в FR-Designer не в run-time, а в design-time. Я не собираюсь давать своим юзерам возможность играться с тем, как выглядит репорт (им это и не надо). Мне нужно его сдизайнить и потом просто показать во вьюере, накормив данными.
1. нарастить индекс (i++) в методе InitDataSet
2. добавить "вычисляемую" таблицу в массив m_DT, тогда можно использовать DBCrossTab.
В принципе, другие таблицы в дизайнере для указанного отчета и не нужны.
Посмотрите внимательно
В методе RunDesigner - вызывается ДИЗАЙНЕР, в котором дизайнится отчет.
А юзерам этот метод и вовсе не нужен
не обижайтесь, но мы действительно говорим о разных вещах.
Мне нужна возможность создать fr3-файл. Это я понимаю под design-time.
Чтобы было потом что лоадить. :-)
// Load demmonstration report from file
report.LoadReportFromFile("..//..//.NET Data Demo.fr3");
Или вы предлагаете мне шаблон отчета тоже из кода делать? Так именно этого я и не хочу. Мухи отдельно, котлеты отдельно. Document-View-архитектура. View в данном случае это шаблон отчета, т.е. fr3-файл. И вот чтобы его выстроить мне и нужно втащить в FR-Designer схему датасета.
В предыдущих постах описано, как создать датасет, который скормить дизайнеру FR и затем сохранить fr3-файл, т.е. именно то, чего Вам и надо было. Сожалею, что столько времени отнял у Вас на чтение.
говорю же, зря вы обижаетесь. Спасибо конечно, что вы так подробно объяснили, как создать датасет для FR, но это и так уже в общих чертах было в сэмпле DataSetDemo.
То, чего я не понимал, а сейчас разобрался - это вот этот код.
FrxDataTable fdt = new FrxDataTable(this.myDataSet.myDataTable);
TfrxReportClass report = new TfrxReportClass();
report.LoadReportFromFile("C:\\.....\\cross2.fr3");
fdt.AssignToReport(true, report);
fdt.AssignToDataBand("MasterData1", report);
report.DesignReport();
^^^^^^^^^^^^^^^^
именно вот этот момент - что нужно прямо из кода проекта сделать связку репорт-дататейбл и потом оттуда же из кода запустить дизайнер и тогда в нем будет видна искомая дататейбл. Я же вместо этого всю дорогу пытался запускать дизайнер из-под Винды.
Кстати в этой связи вопрос к разработчикам - нельзя ли всю эту кухню встроить в FR-Designer, скажем в виде ассистента? Т.е. я ему указываю, где лежит xsd-файл, а он генерирует обертку и делает AssignToReport?
Подскажите, насколько я понимаю, эта идея не получила своего развития, правильно?