Pull to refresh

FastReport.NET. Строим «хитрый» отчет.

Многие слышали о FastReport, многие используют его для своих приложений. Мое первое знакомство с ним состоялось в далеком 2002 году. Delphi + FastReport, что еще нужно для создания отчетов. Скорость построения отчетов и простота проектирования. Но иногда отчет нужен не просто «выбери все из БД по определенным критериям и отобрази», а более изощренный. Например, есть несколько бендов и их нужно выводить в отчет на основании каких-то условий. В FastReport.vcl для этого была отличная возможность — OnManualBuild. Подписавшись на него в коде можно было сделать что-то типа такого:

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 (шапки и подвалы отчета и страниц выводятся всегда).
Надеюсь эта небольшая статейка поможет упростить процесс создания «нелинейных» отчетов.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.