Cross-tab и типизированный датасет

grigri
отредактировано 21:42 Раздел: FastReport Studio
Добрый день,

мне нужно построить репорт типа Cross-tab, подключаемый к датасету. Проблема в том, что именно та таблица, которую нужно подключить к репорту, в ДБ не существует, а только в датасете (и заполняется соответственно кодом).
Вопрос - как объяснить это FastReport Designer'y?
DataSetDemo из примеров я смотрел, но там обычный репорт. А у меня Cross-tab выбрасывает привязку к полям, если ее сделать руками.

Комментарии

  • almanalman космополит
    отредактировано 21:42
    Вы не могли бы предоставить пример данных?
    Мы планируем ввести нативную поддержку объектов данных .NET.
    Ваш пример позволил бы решить проблему на этапе проектирования.
  • отредактировано 21:42
    Чтобы FR узнал таблицу, ее нужно создать ( m_DT ), используя рантаймовскую, получаемую например, методом GetDataTable();
    Примерный код см. ниже


    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();
    }
  • отредактировано 21:42
    В догонку
    нужно создать новый конструктор для 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);
    }

  • grigri
    отредактировано 21:42
    2 vlad_galaxy

    спасибо, но я это уже понял, разбирая пример из 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-объект я не могу, потому что именно этой дататейбл в базе нет, она "вычисляемая", продукт обработки нескольких других таблиц.
  • отредактировано 21:42
    2 gri

    А нужно только таблицы загнать в массив, например

    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 - нужно создать самому по исходному датасету.

    Менять базовые классы не советую - разработчики могут чего-то тоже изменить и тогда ничего работать не будет

  • grigri
    отредактировано 21:42
    2 vlad_galaxy

    все-таки мы немного о разных вещах говорим. Мне нужно передать схему в FR-Designer не в run-time, а в design-time. Я не собираюсь давать своим юзерам возможность играться с тем, как выглядит репорт (им это и не надо). Мне нужно его сдизайнить и потом просто показать во вьюере, накормив данными.
  • отредактировано 21:42
    В догонку
    1. нарастить индекс (i++) в методе InitDataSet
    2. добавить "вычисляемую" таблицу в массив m_DT, тогда можно использовать DBCrossTab.

    В принципе, другие таблицы в дизайнере для указанного отчета и не нужны.
  • отредактировано 21:42
    2 gri
    Посмотрите внимательно
    В методе RunDesigner - вызывается ДИЗАЙНЕР, в котором дизайнится отчет.
    А юзерам этот метод и вовсе не нужен
  • grigri
    отредактировано 21:42
    2 vlad_galaxy

    не обижайтесь, но мы действительно говорим о разных вещах.
    Мне нужна возможность создать fr3-файл. Это я понимаю под design-time.
    Чтобы было потом что лоадить. :-)
    // Load demmonstration report from file
    report.LoadReportFromFile("..//..//.NET Data Demo.fr3");

    Или вы предлагаете мне шаблон отчета тоже из кода делать? Так именно этого я и не хочу. Мухи отдельно, котлеты отдельно. Document-View-архитектура. View в данном случае это шаблон отчета, т.е. fr3-файл. И вот чтобы его выстроить мне и нужно втащить в FR-Designer схему датасета.
  • отредактировано 21:42
    2 gri
    В предыдущих постах описано, как создать датасет, который скормить дизайнеру FR и затем сохранить fr3-файл, т.е. именно то, чего Вам и надо было. Сожалею, что столько времени отнял у Вас на чтение.
  • grigri
    отредактировано 21:42
    2 vlad_galaxy

    говорю же, зря вы обижаетесь. Спасибо конечно, что вы так подробно объяснили, как создать датасет для 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?
  • almanalman космополит
    отредактировано 21:42
    gri написал:
    Кстати в этой связи вопрос к разработчикам - нельзя ли всю эту кухню встроить в FR-Designer, скажем в виде ассистента? Т.е. я ему указываю, где лежит xsd-файл, а он генерирует обертку и делает AssignToReport?
    Интересная идея. В принципе, такое вполне возможно.
  • отредактировано 21:42
    Доброе время суток!
    alman написал: »
    Интересная идея. В принципе, такое вполне возможно.

    Подскажите, насколько я понимаю, эта идея не получила своего развития, правильно?

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.