Реализован сложный отчет по сотрудникам

В TradeMaster в качестве генератора отчетов используется Fast Report.

Очередной раз убеждаюсь в моей удаче и верности решения в выборе этого генератора отчетов для своей системы. Удалось реализовать сложный отчет.

Инструкция далее будет полезна программистам при формирование отчетов в FastReport, а так же разработчикам в виде дополнительной информации для оценки возможностей представленного генератора отчетов при выборе генератора для своего проекта.

Для решения задачи произошло взаимодействие со службой поддержки FastReport. Мой тикет в итоге передали Александру Циганенко основателю и техническому директору компании. Александр добавил некоторый дополнительный функционал для возможности исполнения поставленной задачи, поэтому примеры будут работать только на билде выше 2018.3.36

Необходим отчет по сотрудникам в индивидуальном формате для компании в сфере курьерских перевозок. Сотрудников много.

Впереди на базе такого подхода будет возможность формирования основных отчетов в учете это profit and loss – Доходы и расходы, cash flow – Движение денежных средств и balance Баланс.

Формат отчета предполагал
– столбцы с информацией о сотруднике (номер договора, дата найма),
– статические столбы для анализа,
– динамический набор столбцов по начисленным суммам и оплаченным. Динамический набор зависел от данных на которых строится отчет.
– строки нужно группировать по городу, проекту с итогами наверху.

 

Картинка с другого сайта.

Данные предоставляются в отчет в таком формате

id name proekt gorod dogovor DateNaima DateUvoln Komment adres exp tip analitikName summa
1998 Титов Олег Сергеевич brk МСК 554 2018.01.01 NULL NULL NULL EPR017 1 Вознаграждения 5000

Получилось сделать с помощью объекта Матрица

Как делать 

В дизайнере отрисовываем шаблон отчета на базе объекта Матрица с помощью перетаскивания мышкой полей с окна Данные. Таким образом матрица сама делает группировку строк и подсчет итогов, чтобы итоги были наверху, выставляем соответствующую галочку.

Чтобы добавить столбцы с информацией о сотруднике (номер договора договор, дата найма) добавляем обекты Текст в строку в матрице и пишем них источник из данных, например [dannieSotr.dataNaima]

Картинка с другого сайта.

Далее переходим в скрипты

событие AfterData для добавления данных

 private void Matrix1_AfterData(object sender, EventArgs e)
    {
	
	// подключаем данные 
	
	DataSourceBase rowData = Report.GetDataSource("dannieSotr");
	Matrix1.DataSource = rowData; 
	rowData.Init(); 
	
	
	// таким образом добавляем нужные нам статические столбцы в нужном нам порядке, то есть добавляем пустую строку, которую потом удалим.
	 Matrix1.AddValue(new Object[] { "Общее", "ОС" }, new Object[] { "МСК","","" }, new Object[] { 0 });
	 Matrix1.AddValue(new Object[] { "Общее", "Прибыль" }, new Object[] { "МСК","" }, new Object[] { 0 });   
         Matrix1.AddValue(new Object[] { "Общее", "Количество смен" }, new Object[] { "МСК","" }, new Object[] { 0 }); 


	// пробегаем по данным и заполняем либо статические стобцы либо динамические 
	 while (rowData.HasMoreRows)
{    
        switch ((string)Report.GetColumnValue("dannieSotr.exp"))
        {
		
			// здесь для статических стобцов. Метод   AddValue и SetValue есть в исходнике 
          case "FIN036":
            
            Matrix1.AddValue(new Object[] {"Общее", "ОС"  }, new Object[] { (string)Report.GetColumnValue("dannieSotr.gorod"), (string)Report.GetColumnValue("dannieSotr.projectName"), (string)Report.GetColumnValue("dannieSotr.name") }, new Object[] { (Decimal)Report.GetColumnValue("dannieSotr.summa") });
          break;
	 
	 	  // здесь для динамических, делая разграничение на начисления и оплату
	   default: 
            if ((int)Report.GetColumnValue("dannieSotr.tip") == 1 ){
        
		// обратите внимание передаем уже напрямую с  Report.GetDataSource("dannieSotr").CurrentRowNo , это для того чтобы столбцы с информацией о сотруднике были соответствующее строке.
              Matrix1.Data.AddValue(new Object[] { "Начисления", (string)Report.GetColumnValue("dannieSotr.analitikName") }, new Object[] { (string)Report.GetColumnValue("dannieSotr.gorod"), (string)Report.GetColumnValue("dannieSotr.projectName"),(string)Report.GetColumnValue("dannieSotr.name") }, new Object[] { (Decimal)Report.GetColumnValue("dannieSotr.summa") }, Report.GetDataSource("dannieSotr").CurrentRowNo);
             
			 }
	 
	 	  // добавляем столбцы итогов для начисления и оплат
	  Matrix1.AddValue(new Object[] { "Начисления", "Итого" }, new Object[] { "МСК","","" }, new Object[] { 0 });
      Matrix1.AddValue(new Object[] { "Оплата", "Итого" }, new Object[] { "МСК","","" }, new Object[] { 0 });
             
			 
			  //удаляем пустую строку которая нужна была для выставления порядка столбцов
      Matrix1.Data.Rows.RemoveItem(new Object[] { "МСК","","" });
      Matrix1.Data.Rows.RemoveItem(new Object[] { "МСК","" });
	
	}
 

событие AfterTotals для расчета итогов

 private void Matrix1_AfterTotals(object sender, EventArgs e)
    {
	
	// пробегаем по строкам
      int[] rowIndices = Matrix1.Data.Rows.GetTerminalIndices();
      for (int i = 0; i < rowIndices.Length; i++)
      {
        rowIndex = rowIndices[i];
		
		 // Считаем итоги по динамичсеим столбцам, например в разжеле Оплата 
		  
        int[] columnIndices = Matrix1.Data.Columns.GetTerminalIndices(new Object[] { "Оплата" });
        float oplataSum = 0;
        foreach (int columnIndex in columnIndices)
        {
          oplataSum += GetValue(columnIndex);
        } 
		//Оплата;Итого = итог по всем оплатам  
        SetValue("Оплата;Итого", oplataSum);
		
		
		//считаем аналитические столбцы
		  SetValue("Общее;Баланс", GetValue("Начисления;Итого") - GetValue("Оплата;Итого"));
		  
		 if   (GetValue("Общее;Количество смен")>0) {
          
          SetValue("Общее;Прибыль на 1 смену",  GetValue("Общее;Баланс")/ GetValue("Общее;Количество смен"));   
          
        }  	
		

В отчете условное выделение можно сделать в дизайнере. Можно менять фон, шрифт, рамку. Форма с условиями в данном случае выглядит так

Картинка с другого сайта.

 

В итоге получается такой отчет, который можно экспортировать в любой формат, а так же можно нагрузить дополнительно функционалом, например при двойном клике по сотруднику открывать его “расчетку”

 

Как видите FastReport блестяще справился с поставленной задачей. Клиент счастлив, я как разработчик доволен “как слон”. Меня радует что у меня “развязаны руки” формировать отчеты такого уровня сложности используя функционал генератора отчетов, передавая стандартный набор данных ,то есть иными словами, чтобы решать такие задачи не потребуется индивидуализировать запрос и набор предоставляемых данных к генератору отчета от моего приложения, таким образом мне легко подстраиваться под запросы пользователей, меняя только шаблон отчета и не делая изменений в ядро системы или разнообразные “костыли”.


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