Многие слышали о FastReport, многие используют его для своих приложений. Мое первое знакомство с ним состоялось в далеком 2002 году. Delphi + FastReport, что еще нужно для создания отчетов. Скорость построения отчетов и простота проектирования. Но иногда отчет нужен не просто «выбери все из БД по определенным критериям и отобрази», а более изощренный. Например, есть несколько бендов и их нужно выводить в отчет на основании каких-то условий. В FastReport.vcl для этого была отличная возможность — OnManualBuild. Подписавшись на него в коде можно было сделать что-то типа такого:
Просто и удобно.
Но время не стоит на месте и вот я уже для разработки использую VS от мелкософта и C#.
FastReport не стоит на месте и выпускает FastReport Studio. И тут меня ждет разочарование, это ActiveX и о каком либо «ручном» управлении построения отчетов приходится забыть (вернее все же что-то можно сделать, но это скорее «танец с бубном»). Но FastReport помнит о нас :) и выпускает FastReport.NET. Я тут же «хватаюсь» за него и обнаруживаю, что про ManualBuild команда разработчиков забыла. Немного переписки с тех.поддержкой и это событие реализовано. Теперь мы можем делать все, что могли в Delphi и даже больше.
На небольшом примере я хочу показать простоту построения отчета.
Предположим у нас есть в отчете несколько пар бендов (шапка и данные), и мы хотим в каком-то произвольном порядке вывести все это в отчет.
Для начала создадим несколько вспомогательных классов.
Класс, который будет содержать имя параметра и значение (аналог FieldName и FieldValue ).
If (x = 1)
then Report.Engine.ShowBand(TfrxBand(Page.FindObject('Header1')))
else Report.Engine.ShowBand(TfrxBand(Page.FindObject('Header2')));
Просто и удобно.
Но время не стоит на месте и вот я уже для разработки использую VS от мелкософта и C#.
FastReport не стоит на месте и выпускает FastReport Studio. И тут меня ждет разочарование, это ActiveX и о каком либо «ручном» управлении построения отчетов приходится забыть (вернее все же что-то можно сделать, но это скорее «танец с бубном»). Но FastReport помнит о нас :) и выпускает FastReport.NET. Я тут же «хватаюсь» за него и обнаруживаю, что про ManualBuild команда разработчиков забыла. Немного переписки с тех.поддержкой и это событие реализовано. Теперь мы можем делать все, что могли в Delphi и даже больше.
На небольшом примере я хочу показать простоту построения отчета.
Предположим у нас есть в отчете несколько пар бендов (шапка и данные), и мы хотим в каком-то произвольном порядке вывести все это в отчет.
Для начала создадим несколько вспомогательных классов.
Класс, который будет содержать имя параметра и значение (аналог FieldName и FieldValue ).
#region PrintStruct
public class PrintStruct
{
public string NameParam
{
get;
set;
}
public string ValueParam
{
get;
set;
}
public PrintStruct()
{
}
public PrintStruct(string nameParam, string valueParam)
{
this.NameParam = nameParam;
this.ValueParam = valueParam;
}
}
#endregion
#region PrintStructList
public class PrintStructList : List {
public PrintStructList()
{
}
public PrintStructList(int capacity) : base(capacity)
{
}
public PrintStructList(IEnumerable collection) : base(collection)
{
}
}
#endregion
Класс, который будет содержать информацию о бенде (имя, тип «шапка или данные», список значений).
#region PrintBand
public class PrintBand
{
public bool IsHeader
{
get;
set;
}
public string NameBand
{
get;
set;
}
public PrintStructList Values
{
get;
set;
}
public PrintBand()
{
}
public PrintBand(bool isHeader, string nameBand, PrintStructList values)
{
this.IsHeader = isHeader;
this.NameBand = nameBand;
this.Values = values;
}
}
#endregion
#region PrintBandList
public class PrintBandList : List {
public PrintBandList()
{
}
public PrintBandList(int capacity) : base(capacity)
{
}
public PrintBandList(IEnumerable collection) : base(collection)
{
}
}
#endregion
И, наконец, основной класс, к которому и будет обращаться FastReport.
#region PrintInfo
public class PrintInfo
{
public static PrintBandList GetInfoForPrint()
{
var res = new PrintBandList();
// Добавляем Шапку
var printBand = new PrintBand
{
IsHeader = true,
NameBand = "Header1",
Values = new PrintStructList
{
new PrintStruct("Col1", "№ "),
new PrintStruct("Col2", "Знач 1"),
new PrintStruct("Col3", " Знач 2")
}
};
res.Add(printBand);
// Добавляем данные
printBand = new PrintBand
{
IsHeader = false,
NameBand = "Data1",
Values = new PrintStructList
{
new PrintStruct("Par1", "1 "),
new PrintStruct("Par2", "111"),
new PrintStruct("Par3", "111111")
}
};
res.Add(printBand);
printBand = new PrintBand
{
IsHeader = false,
NameBand = "Data1",
Values = new PrintStructList
{
new PrintStruct("Par1", "2 "),
new PrintStruct("Par2", "222"),
new PrintStruct("Par3", "222222")
}
};
res.Add(printBand);
// Добавляем Шапку
printBand = new PrintBand
{
IsHeader = true,
NameBand = "Header2",
Values = new PrintStructList
{
new PrintStruct("Col1", "№ "),
new PrintStruct("Col2", "Знач 1"),
new PrintStruct("Col3", " Знач 2"),
new PrintStruct("Col4", " Знач 3")
}
};
res.Add(printBand);
// Добавляем данные
printBand = new PrintBand
{
IsHeader = false,
NameBand = "Data2",
Values = new PrintStructList
{
new PrintStruct("Par1", "1 "),
new PrintStruct("Par2", "11"),
new PrintStruct("Par3", "111"),
new PrintStruct("Par4", "111111")
}
};
res.Add(printBand);
// повторяем сколько нам нужно :)
return res;
}
}
#endregion
Все, данные у нас есть, осталось их только вызвать в отчете и отобразить.
Для это в коде отчета пишем следующее:
private void Page1_ManualBuild(object sender, EventArgs e)
{
PrintBandList bandlist = ClassTest.PrintInfo.GetInfoForPrint();
for (int i = 0; i < bandlist.Count; i++)
{
for (int j = 0; j < bandlist[i].Values.Count; j++)
{
Report.SetParameterValue(bandlist[i].Values[j].NameParam, bandlist[i].Values[j].ValueParam);
}
if (bandlist[i].IsHeader)
{
DataHeaderBand band = Report.FindObject(bandlist[i].NameBand) as DataHeaderBand;
Engine.ShowBand(band);
}
else
{
DataBand band = Report.FindObject(bandlist[i].NameBand) as DataBand;
Engine.ShowBand(band);
}
}
}
Вот все. Только осталось запомнить несколько моментов: чтобы использовать свой класс нужно в дизайнере добавить ссылку (reference) на свою dll, управлять выводом можно только для DataHeaderBand и DataBand (шапки и подвалы отчета и страниц выводятся всегда).
Надеюсь эта небольшая статейка поможет упростить процесс создания «нелинейных» отчетов.