asperReports এর Integration Java EE এবং Spring এর সাথে

জ্যাসপার রিপোর্ট (JasperReports) - Java Technologies

300

JasperReports একটি শক্তিশালী রিপোর্টিং লাইব্রেরি যা Java EE এবং Spring প্ল্যাটফর্মের সাথে সহজে ইন্টিগ্রেট করা যায়। এর মাধ্যমে আপনি ডাইনামিক রিপোর্ট তৈরি, প্রিন্ট, এবং এক্সপোর্ট করতে পারবেন। JasperReports ইন্টিগ্রেশন Java EE এবং Spring অ্যাপ্লিকেশনে সহজে কাজ করতে পারে, কারণ এটি Java-based এবং RESTful API সাপোর্ট করে।

এখানে, Java EE এবং Spring ফ্রেমওয়ার্কে JasperReports ইন্টিগ্রেট করার পদ্ধতি এবং সুবিধাগুলি আলোচনা করা হবে।


Java EE (Jakarta EE) এর সাথে JasperReports Integration

Java EE (এখন Jakarta EE) একটি পূর্ণাঙ্গ প্ল্যাটফর্ম যা এন্টারপ্রাইজ অ্যাপ্লিকেশন ডেভেলপমেন্টের জন্য ব্যবহৃত হয়। JasperReports Java EE অ্যাপ্লিকেশনে অন্তর্ভুক্ত করা যায়, যেখানে সাধারণত EJB, JPA, JMS এবং Servlets ব্যবহার করা হয়। JasperReports সহজেই Java EE-এর Servlets বা EJB এর মধ্যে রিপোর্টের আউটপুট তৈরি করতে ব্যবহৃত হতে পারে।

Java EE - JasperReports Integration উদাহরণ

  1. Servlets ব্যবহার করে JasperReports Integration:
    • আপনি JasperReports ব্যবহার করে রিপোর্টের আউটপুট একটি Servlet-এর মাধ্যমে তৈরি করতে পারেন।
import net.sf.jasperreports.engine.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class ReportServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // Prepare data for report
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("reportTitle", "Sales Report");

            // Compile the JRXML template to JasperReport object
            JasperReport jasperReport = JasperCompileManager.compileReport(getServletContext().getRealPath("/WEB-INF/reports/sales_report.jrxml"));

            // Fill report with data
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());

            // Export to PDF
            response.setContentType("application/pdf");
            ServletOutputStream outputStream = response.getOutputStream();
            JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
        } catch (JRException e) {
            e.printStackTrace();
        }
    }
}

এখানে:

  • Servlet ব্যবহার করে JasperReports রিপোর্ট তৈরি করা হচ্ছে এবং তা PDF ফরম্যাটে ব্রাউজারে সরাসরি প্রিন্ট করা হচ্ছে।
  • JasperFillManager ব্যবহার করে রিপোর্টের প্যারামিটারগুলি ফিল করা হচ্ছে এবং তারপর JasperExportManager এর মাধ্যমে PDF আউটপুট তৈরি হচ্ছে।
  1. JPA এবং JasperReports Integration:
    • আপনি JPA ব্যবহার করে ডেটা সংগ্রহ করতে পারেন এবং সেই ডেটা JasperReports রিপোর্টে পাস করতে পারেন।
@PersistenceContext
private EntityManager entityManager;

public void generateReport() {
    List<SalesData> salesDataList = entityManager.createQuery("SELECT s FROM SalesData s", SalesData.class).getResultList();

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("salesData", salesDataList);

    // Fill report with data
    JasperPrint jasperPrint = JasperFillManager.fillReport("sales_report.jasper", parameters, new JREmptyDataSource());

    // Export the report to PDF
    JasperExportManager.exportReportToPdfFile(jasperPrint, "sales_report_output.pdf");
}

এখানে:

  • JPA এর মাধ্যমে ডেটা ফেচ করা হচ্ছে এবং তারপর সেই ডেটা JasperReports রিপোর্টে পাস করা হচ্ছে।

Spring Framework এর সাথে JasperReports Integration

Spring Framework ব্যবহার করে JasperReports ইন্টিগ্রেট করা খুবই সহজ, কারণ Spring এবং JasperReports-এর মধ্যে সরাসরি ইন্টিগ্রেশন সাপোর্ট রয়েছে। Spring Boot সহ Spring MVC, Spring Boot REST, Spring Data ইত্যাদি সিস্টেমের সঙ্গে JasperReports ব্যবহার করা যায়।

Spring Boot - JasperReports Integration

Spring Boot একটি auto-configurable প্ল্যাটফর্ম যা JasperReports ইনস্টলেশন এবং কনফিগারেশন সহজ করে তোলে। JasperReports-এর জন্য Spring Boot স্টার্টার ব্যবহার করা যেতে পারে, যা JasperReports-এর ডিপেনডেন্সি হ্যান্ডলিং সহজ করে।

  1. JasperReports এবং Spring Boot:

    প্রথমে, pom.xml-এ JasperReports ডিপেনডেন্সি যোগ করতে হবে:

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.17.0</version>
</dependency>
  1. Spring Boot Controller-এ JasperReports ব্যবহার করা:
import net.sf.jasperreports.engine.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Controller
public class ReportController {

    @GetMapping("/generateReport")
    public void generateReport(@RequestParam("reportName") String reportName, HttpServletResponse response) throws JRException {
        // Prepare parameters
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("reportName", reportName);

        // Compile the report
        JasperReport jasperReport = JasperCompileManager.compileReport("reports/sample_report.jrxml");

        // Fill the report with data
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());

        // Export to PDF
        response.setContentType("application/pdf");
        JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
    }
}

এখানে:

  • Spring Boot Controller-এ রিপোর্ট তৈরি করা হচ্ছে। ডেটা প্যারামিটার হিসেবে পাস করা হচ্ছে এবং তারপর PDF আউটপুট তৈরি করা হচ্ছে।
  1. Spring Boot - JasperReports DataSource:
    • JasperReports সাধারণত ডেটা ফিল করার জন্য JDBC বা Spring Data JPA ব্যবহার করতে পারে। Spring Boot প্রজেক্টে সহজেই JPA বা JDBC ডেটা সোর্স ব্যবহার করা যেতে পারে।

Spring MVC - JasperReports Integration

Spring MVC ব্যবহার করে JasperReports রিপোর্ট তৈরি এবং এক্সপোর্ট করা সহজ। আপনি @RequestMapping অথবা @GetMapping অ্যানোটেশন ব্যবহার করে রিপোর্টের জন্য একটি API তৈরি করতে পারেন।

  1. Spring MVC Controller-এ JasperReports Integration:
import net.sf.jasperreports.engine.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@Controller
public class ReportController {

    @GetMapping("/generateReport")
    public void generateReport(@RequestParam("customerId") int customerId, HttpServletResponse response) throws JRException {
        // Prepare parameters for the report
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("customerId", customerId);

        // Compile the report
        JasperReport jasperReport = JasperCompileManager.compileReport("report.jrxml");

        // Fill the report with data
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());

        // Export the report to PDF
        response.setContentType("application/pdf");
        JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
    }
}

এখানে:

  • @GetMapping অ্যানোটেশন ব্যবহার করে একটি HTTP GET রিকোয়েস্ট হ্যান্ডল করা হচ্ছে, যেখানে রিপোর্ট তৈরি হবে এবং তা PDF ফরম্যাটে ব্রাউজারে সরাসরি পাঠানো হবে।

Spring Boot বা Spring MVC এ JasperReports-এর সুবিধা

  1. Auto-Configuration:
    • Spring Boot JasperReports এর জন্য অটো কনফিগারেশন সরবরাহ করে, যা ডিপেনডেন্সি ম্যানেজমেন্ট এবং কনফিগারেশনকে সহজ করে তোলে।
  2. Integration with Data Sources:
    • Spring Data JPA বা JDBC ব্যবহার করে ডেটাবেস থেকে ডেটা সংগ্রহ এবং তা JasperReports রিপোর্টে পাস করা সহজ।
  3. RESTful API Integration:
    • JasperReports-এ তৈরি রিপোর্ট সহজে RESTful API আউটপুট হিসেবে সরবরাহ করা যায়।
  4. Customizable Reports:
    • Spring Boot বা Spring MVC এর মাধ্যমে আপনি ডাইনামিক এবং কাস্টম রিপোর্ট তৈরি করতে পারবেন, যা রিপোর্টের বিভিন্ন অংশ গ্রাফিক্যালি কাস্টমাইজ করা যাবে।

JasperReports এর Java EE এবং Spring ফ্রেমওয়ার্কের সাথে ইন্টিগ্রেশন খুবই সহজ এবং কার্যকর। Spring Boot বা Spring MVC এর মাধ্যমে আপনি রিপোর্ট তৈরির জন্য ডেটাবেস থেকে ডেটা সংগ্রহ করতে পারেন এবং সহজেই পিডিএফ, এক্সেল বা অন্যান্য ফরম্যাটে রিপোর্ট এক্সপোর্ট করতে পারেন। JasperReports ব্যবহার করে আপনি কাস্টম রিপোর্ট তৈরি, এবং রিপোর্টের আউটপুট সরবরাহ করতে পারেন যা আপনার অ্যাপ্লিকেশন ও ব্যবসায়ের প্রয়োজনীয়তা অনুযায়ী ডাইনামিকভাবে কাস্টমাইজ করা যাবে।

Content added By

JasperReports হল একটি শক্তিশালী ওপেন সোর্স রিপোর্টিং টুল যা Java EE অ্যাপ্লিকেশনে একত্রিত করে ডাইনামিক রিপোর্ট তৈরি, কাস্টমাইজ এবং এক্সপোর্ট করার জন্য ব্যবহৃত হয়। JasperReports ব্যবহার করে আপনি বিভিন্ন ধরনের রিপোর্ট তৈরি করতে পারেন এবং এই রিপোর্টগুলিকে PDF, Excel, HTML, CSV ইত্যাদি ফরম্যাটে এক্সপোর্ট করতে পারবেন।

Java EE অ্যাপ্লিকেশনে JasperReports এর ইন্টিগ্রেশন অত্যন্ত সহজ, যেখানে আপনি রিপোর্ট তৈরি, রিপোর্টের ডেটা পূরণ এবং এক্সপোর্টিং সবকিছু Java EE কন্টেইনারে পরিচালনা করতে পারেন।


JasperReports এর Java EE তে Integration এর প্রক্রিয়া

১. JasperReports লাইব্রেরি প্রজেক্টে অন্তর্ভুক্ত করা

প্রথমে, আপনার Java EE অ্যাপ্লিকেশনে JasperReports লাইব্রেরি অন্তর্ভুক্ত করতে হবে। আপনি Maven বা Gradle ব্যবহার করে এই লাইব্রেরি অন্তর্ভুক্ত করতে পারেন।

Maven Dependency Example:

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.17.0</version> <!-- Use the appropriate version -->
</dependency>

Gradle Dependency Example:

dependencies {
    implementation 'net.sf.jasperreports:jasperreports:6.17.0' // Use the appropriate version
}

২. JasperReports এর JRXML ফাইল তৈরি করা

JasperReports-এর জন্য প্রথমে আপনাকে একটি JRXML ফাইল তৈরি করতে হবে, যা রিপোর্টের ডিজাইন সংরক্ষণ করবে। এই ফাইলটি Jaspersoft Studio বা iReport Designer ব্যবহার করে তৈরি করা যেতে পারে।

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
                                  http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
              name="simpleReport" language="java" pageWidth="595" pageHeight="842">
    
    <queryString>
        <![CDATA[SELECT id, name, email FROM users]]>
    </queryString>

    <field name="id" class="java.lang.Integer"/>
    <field name="name" class="java.lang.String"/>
    <field name="email" class="java.lang.String"/>
    
    <detail>
        <band height="20">
            <textField>
                <reportElement x="0" y="0" width="50" height="20"/>
                <textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="50" y="0" width="200" height="20"/>
                <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="250" y="0" width="250" height="20"/>
                <textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

৩. JasperReports এর Java EE অ্যাপ্লিকেশনে Integration

Java EE অ্যাপ্লিকেশনে JasperReports ইন্টিগ্রেট করার জন্য সাধারণত EJB (Enterprise JavaBeans), Servlets, বা JAX-RS (RESTful Services) ব্যবহার করা হয়। নিচে JSP এবং Servlet এর মাধ্যমে JasperReports-এর এক্সপোর্টিং দেখানো হয়েছে।

JSP বা Servlet মাধ্যমে JasperReports এক্সপোর্ট করা

প্রথমে, রিপোর্টটি কম্পাইল করা হবে, তারপর সেটি ফিল করা হবে এবং সঠিক আউটপুট ফরম্যাটে এক্সপোর্ট করা হবে।

Servlet Example:

import net.sf.jasperreports.engine.*;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/generateReport")
public class ReportGenerationServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // JRXML ফাইলের পথ
            String reportPath = getServletContext().getRealPath("/WEB-INF/reports/simpleReport.jrxml");

            // JRXML ফাইল কম্পাইল করা
            JasperReport jasperReport = JasperCompileManager.compileReport(reportPath);

            // ডেটা প্রক্রিয়া (এই ক্ষেত্রে, ডেটাবেস বা অন্য সোর্স থেকে)
            HashMap<String, Object> parameters = new HashMap<>();
            // যে ডেটাবেস বা ডেটা সোর্স থেকে ডেটা নিয়ে আসা হবে তার জন্য প্যারামিটার দেয়া হবে

            // রিপোর্ট পূর্ণ করা
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource());

            // PDF আউটপুট তৈরি করা
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "inline; filename=report.pdf");
            JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
        } catch (JRException e) {
            e.printStackTrace();
        }
    }
}

এই উদাহরণে:

  1. JasperCompileManager ব্যবহার করে JRXML ফাইল কম্পাইল করা হয়েছে।
  2. JasperFillManager ব্যবহার করে রিপোর্টটি পূর্ণ করা হয়েছে।
  3. JasperExportManager ব্যবহার করে রিপোর্টটি PDF আউটপুটে এক্সপোর্ট করা হয়েছে এবং সেটি HttpServletResponse এর মাধ্যমে ব্রাউজারে দেখানো হয়েছে।

৪. JasperReports-এর RESTful API (JAX-RS)

Java EE অ্যাপ্লিকেশনগুলিতে JAX-RS (Java API for RESTful Web Services) ব্যবহার করে আপনি RESTful API তৈরি করতে পারেন যেটি JasperReports এর মাধ্যমে রিপোর্ট এক্সপোর্ট করবে।

import net.sf.jasperreports.engine.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;

@Path("/report")
public class ReportResource {

    @GET
    @Path("/generate")
    @Produces("application/pdf")
    public Response generateReport() {
        try {
            String reportPath = "path/to/your/jasperreport.jasper"; // compiled jasper report file
            JasperPrint jasperPrint = JasperFillManager.fillReport(reportPath, new HashMap<>());

            // PDF রেসপন্স হিসাবে পাঠানো
            byte[] pdfData = JasperExportManager.exportReportToPdf(jasperPrint);
            return Response.ok(pdfData).build();
        } catch (JRException e) {
            e.printStackTrace();
            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
        }
    }
}

এখানে:

  1. JAX-RS-এর @Path, @GET, এবং @Produces অ্যানোটেশন ব্যবহার করে RESTful API তৈরি করা হয়েছে।
  2. JasperFillManager ব্যবহার করে রিপোর্টটি পূর্ণ করা হয়েছে এবং JasperExportManager দিয়ে PDF আউটপুট তৈরি করা হয়েছে।
  3. রিপোর্টের আউটপুট byte[] আকারে HTTP Response-এ পাঠানো হয়েছে।

Java EE তে JasperReports এর সুবিধা

  1. ডাইনামিক রিপোর্টিং:
    • JasperReports Java EE অ্যাপ্লিকেশনে ডাইনামিক রিপোর্টিং তৈরি করার জন্য সুবিধাজনক, যেখানে আপনি বিভিন্ন ডেটা সোর্স ব্যবহার করতে পারেন এবং রিপোর্টের আউটপুট কাস্টমাইজ করতে পারেন।
  2. ভিন্ন আউটপুট ফরম্যাট:
    • JasperReports একাধিক আউটপুট ফরম্যাট (যেমন, PDF, Excel, HTML, CSV) সমর্থন করে, যা রিপোর্টের উপস্থাপনা এবং এক্সপোর্টের জন্য কার্যকরী।
  3. ডেটাবেস ইন্টিগ্রেশন:
    • JasperReports সহজেই বিভিন্ন ডেটাবেসের সাথে ইন্টিগ্রেট হতে পারে এবং JPA/Hibernate বা JDBC এর মাধ্যমে ডেটা সংগ্রহ করতে সক্ষম।
  4. RESTful Integration:
    • JAX-RS ব্যবহার করে আপনি JasperReports এর রিপোর্ট তৈরির জন্য RESTful API তৈরি করতে পারেন।
  5. অতিরিক্ত কাস্টমাইজেশন:
    • JasperReports Java EE অ্যাপ্লিকেশনে আরও কাস্টমাইজেশন এবং অ্যানোটেশন সহ রিপোর্ট তৈরির জন্য সহজে ইন্টিগ্রেট করা যায়।

JasperReports এর Java EE তে ইন্টিগ্রেশন খুবই সহজ এবং প্রভাবশালী। এটি ডাইনামিকভাবে রিপোর্ট তৈরি করতে, রিপোর্টের আউটপুট কাস্টমাইজ করতে এবং একাধিক আউটপুট ফরম্যাটে এক্সপোর্ট করতে সহায়তা করে। Java EE এর EJB, Servlets, বা JAX-RS ব্যবহার করে JasperReports সহজে ইন্টিগ্রেট করা যায় এবং আপনার অ্যাপ্লিকেশনে রিপোর্টিং ফিচার যুক্ত করা সম্ভব।

Content added By

JasperReports একটি জনপ্রিয় ওপেন সোর্স রিপোর্টিং টুল যা Spring Framework এর সাথে খুব সহজে ইন্টিগ্রেট করা যায়। Spring Framework এর মধ্যে JasperReports ব্যবহার করে আপনি ডাইনামিক এবং কাস্টম রিপোর্ট তৈরি করতে পারবেন, যা বিভিন্ন ফরম্যাটে (যেমন PDF, HTML, Excel, CSV) এক্সপোর্ট করা যাবে।

Spring Boot বা Spring MVC অ্যাপ্লিকেশন ব্যবহার করে JasperReports রিপোর্ট তৈরি এবং রেন্ডার করার প্রক্রিয়া সাধারণত খুবই সোজা। এখানে Spring MVC এবং Spring Boot এ JasperReports ইন্টিগ্রেশন দেখানো হবে।


Spring Framework এর সাথে JasperReports ইন্টিগ্রেশন

ধাপ ১: Maven ডিপেনডেন্সি

প্রথমে, আপনার pom.xml ফাইলে JasperReports এর ডিপেনডেন্সি অন্তর্ভুক্ত করুন।

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.17.0</version>
</dependency>

এটি JasperReports এর লাইব্রেরি আপনার প্রজেক্টে অন্তর্ভুক্ত করবে। এছাড়াও আপনি যদি Spring Boot ব্যবহার করেন, তাহলে Spring Boot Starter Web ডিপেনডেন্সি ব্যবহার করতে হবে, যা সাধারণভাবে HTTP এন্ডপয়েন্টে রিপোর্ট জেনারেট করার জন্য দরকারি।


ধাপ ২: JasperReports Template তৈরি করা

JasperReports এর রিপোর্ট ডিজাইন সাধারণত .jrxml ফাইল আকারে থাকে, যা আপনি Jaspersoft Studio অথবা iReport Designer দিয়ে তৈরি করতে পারেন। এই ফাইলগুলি পরে .jasper ফাইলে কম্পাইল হয়, যেটি রিপোর্ট জেনারেট করতে ব্যবহৃত হয়।

ধরা যাক, আপনি একটি সাধারণ Employee রিপোর্ট তৈরি করতে চান।

EmployeeReport.jrxml:

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports 
    http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
    name="EmployeeReport" pageWidth="595" pageHeight="842" columnWidth="515" 
    leftMargin="40" rightMargin="40" topMargin="40" bottomMargin="40">

    <field name="employeeId" class="java.lang.Integer"/>
    <field name="employeeName" class="java.lang.String"/>
    <field name="department" class="java.lang.String"/>

    <detail>
        <band height="20">
            <textField>
                <reportElement x="0" y="0" width="200" height="20"/>
                <textFieldExpression><![CDATA[$F{employeeId}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="200" y="0" width="200" height="20"/>
                <textFieldExpression><![CDATA[$F{employeeName}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="400" y="0" width="200" height="20"/>
                <textFieldExpression><![CDATA[$F{department}]]></textFieldExpression>
            </textField>
        </band>
    </detail>

</jasperReport>

এখানে, employeeId, employeeName, এবং department ফিল্ডের মান টেবিল আকারে প্রদর্শিত হবে।


ধাপ ৩: Spring Boot এ JasperReports সেটআপ

Spring Boot অ্যাপ্লিকেশন সেটআপ করতে, নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করতে হবে:

  1. Spring Boot Application Class:

    একটি @SpringBootApplication ক্লাস তৈরি করুন।

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ReportApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReportApplication.class, args);
    }
}
  1. JasperReports Service ক্লাস:

    এখন একটি JasperReports Service তৈরি করুন যা রিপোর্ট ফিল এবং এক্সপোর্ট করবে।

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;

import java.util.*;

@Service
public class ReportService {

    @Value("${report.template.path}")
    private String reportTemplatePath;

    public byte[] generateReport() throws JRException {
        // Compile the .jrxml file to JasperReport object
        JasperReport jasperReport = JasperCompileManager.compileReport(reportTemplatePath);

        // Prepare data for the report (using a sample list of employees)
        List<Employee> employees = getEmployees();  // Assume getEmployees() fetches data
        JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(employees);

        // Fill the report with data
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("ReportTitle", "Employee Report");
        JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);

        // Export the report to PDF
        return JasperExportManager.exportReportToPdf(jasperPrint);
    }

    // A simple method to simulate fetching employee data
    private List<Employee> getEmployees() {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(1, "John Doe", "HR"));
        employees.add(new Employee(2, "Jane Smith", "Finance"));
        return employees;
    }
}

এখানে generateReport মেথডটি .jrxml ফাইল কম্পাইল করবে এবং তারপর JRBeanCollectionDataSource ব্যবহার করে রিপোর্টটি পূর্ণ করবে। শেষে, JasperExportManager ব্যবহার করে রিপোর্টটি পিডিএফ আকারে এক্সপোর্ট করবে।

  1. Employee ক্লাস:
public class Employee {
    private int employeeId;
    private String employeeName;
    private String department;

    public Employee(int employeeId, String employeeName, String department) {
        this.employeeId = employeeId;
        this.employeeName = employeeName;
        this.department = department;
    }

    public int getEmployeeId() {
        return employeeId;
    }

    public String getEmployeeName() {
        return employeeName;
    }

    public String getDepartment() {
        return department;
    }
}

ধাপ ৪: Report Controller

এখন, একটি Spring MVC Controller তৈরি করুন, যা রিপোর্ট জেনারেট করে এবং HTTP response এ পিডিএফ রিপোর্ট পাঠাবে।

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

@RestController
public class ReportController {

    @Autowired
    private ReportService reportService;

    @GetMapping("/report")
    public void generateReport(HttpServletResponse response) throws Exception {
        // Generate the report and get the PDF content as byte array
        byte[] reportContent = reportService.generateReport();

        // Set response type and headers for PDF
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=employee_report.pdf");

        // Write the report content to the response output stream
        response.getOutputStream().write(reportContent);
    }
}

এখানে, /report এন্ডপয়েন্টে কল করার মাধ্যমে employee_report.pdf রিপোর্ট পিডিএফ আকারে ব্রাউজারে প্রদর্শিত হবে।


ধাপ ৫: Application Properties

Spring Boot এ JasperReports ব্যবহার করার জন্য application.properties অথবা application.yml ফাইলে কনফিগারেশন নির্ধারণ করা যেতে পারে, যেমন রিপোর্ট টেমপ্লেটের পাথ।

report.template.path=classpath:reports/EmployeeReport.jrxml

  • JasperReports এবং Spring Framework এর ইন্টিগ্রেশন সহজ এবং কার্যকরী। JasperReports আপনার Spring Boot অ্যাপ্লিকেশনে কাস্টম এবং ডাইনামিক রিপোর্ট তৈরি করতে সহায়ক।
  • JasperReports Service ক্লাসের মাধ্যমে আপনি JRBeanCollectionDataSource ব্যবহার করে ডেটা পূর্ণ করে JasperExportManager এর মাধ্যমে বিভিন্ন ফরম্যাটে রিপোর্ট এক্সপোর্ট করতে পারেন।
  • Spring MVC Controller এর মাধ্যমে রিপোর্ট এক্সপোর্ট করা এবং HTTP response এ রিপোর্ট পাঠানো সম্ভব।
Content added By

JasperReports এবং RESTful Web Services এর মাধ্যমে রিপোর্ট জেনারেট করা একটি জনপ্রিয় প্র্যাকটিস যা web applications-এ রিপোর্ট ডেলিভারি এবং প্রসেসিং সহজ করে তোলে। JasperReports একটি শক্তিশালী Java ভিত্তিক রিপোর্টিং টুল এবং RESTful Web Services ব্যবহারের মাধ্যমে আপনি রিপোর্টের আউটপুট যেমন PDF, HTML, Excel ইত্যাদি JSON বা অন্য কোনো ফরম্যাটে রিটার্ন করতে পারেন।

এখানে আমরা একটি Spring Boot RESTful Web Service তৈরি করব যা JasperReports ব্যবহার করে রিপোর্ট জেনারেট করবে এবং সেই রিপোর্টটি ক্লায়েন্টে একটি REST API-র মাধ্যমে প্রদান করবে।


ধাপ ১: Spring Boot Application সেটআপ করা

প্রথমে একটি Spring Boot Application তৈরি করতে হবে এবং প্রয়োজনীয় ডিপেনডেন্সি যুক্ত করতে হবে।

pom.xml এ ডিপেনডেন্সি যুক্ত করা:

<dependencies>
    <!-- Spring Boot Starter Web (for REST API) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- JasperReports dependency -->
    <dependency>
        <groupId>net.sf.jasperreports</groupId>
        <artifactId>jasperreports</artifactId>
        <version>6.16.0</version>
    </dependency>

    <!-- Jackson for JSON (optional for REST API) -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

    <!-- Spring Boot Starter for Thymeleaf (optional if using templates) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>

এই ডিপেনডেন্সি গুলি দিয়ে আপনি Spring Boot এবং JasperReports ব্যবহার করতে পারবেন। spring-boot-starter-web REST API তৈরি করতে ব্যবহৃত হবে এবং jasperreports JasperReports লাইব্রেরি অন্তর্ভুক্ত করবে।


ধাপ ২: JasperReport তৈরি করা

এখন, একটি JasperReport তৈরি করতে হবে যা REST API এর মাধ্যমে ব্যবহারকারীকে আউটপুট প্রদান করবে। আমরা একটি সাধারণ Employee Report তৈরি করব যেখানে কর্মচারী সম্পর্কিত কিছু তথ্য থাকবে।

Employee Report (employeeReport.jrxml)

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports 
                                  http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
              name="EmployeeReport" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
              
    <field name="id" class="java.lang.Integer"/>
    <field name="name" class="java.lang.String"/>
    <field name="department" class="java.lang.String"/>

    <detail>
        <band height="20">
            <textField>
                <reportElement x="0" y="0" width="50" height="20"/>
                <textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="60" y="0" width="200" height="20"/>
                <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="270" y="0" width="150" height="20"/>
                <textFieldExpression><![CDATA[$F{department}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

এটি একটি সাধারণ Employee Report যেখানে id, name, এবং department ফিল্ড থাকবে।


ধাপ ৩: Spring Boot Controller তৈরি করা

Spring Boot এ একটি RESTful Controller তৈরি করতে হবে যা রিপোর্ট তৈরির জন্য API হ্যান্ডল করবে এবং সেই রিপোর্টটি বিভিন্ন ফরম্যাটে ক্লায়েন্টকে ফিরিয়ে দিবে।

EmployeeReportController.java

import net.sf.jasperreports.engine.*;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;

@RestController
public class EmployeeReportController {

    @GetMapping("/generateReport")
    public byte[] generateReport() {
        try {
            // JasperReports report compile and fill
            JasperReport jasperReport = JasperCompileManager.compileReport("employeeReport.jrxml");

            // Parameters (if any)
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("ReportTitle", "Employee Report");

            // Sample Data (use JRBeanCollectionDataSource or JRResultSetDataSource for actual data)
            JRDataSource dataSource = new JRBeanCollectionDataSource(getEmployeeData());

            // Fill the report
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);

            // Export the report to PDF
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);

            // Return the PDF as byte array
            return outputStream.toByteArray();

        } catch (JRException e) {
            e.printStackTrace();
            return null;
        }
    }

    // Dummy employee data
    private List<Employee> getEmployeeData() {
        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(new Employee(1, "John Doe", "HR"));
        employeeList.add(new Employee(2, "Jane Smith", "IT"));
        return employeeList;
    }
}

Explanation:

  • @RestController: এটি একটি RESTful controller যা HTTP রিকোয়েস্ট হ্যান্ডল করে।
  • @GetMapping("/generateReport"): এটি একটি GET রিকোয়েস্ট হ্যান্ডলার যা রিপোর্ট তৈরি করবে।
  • JasperCompileManager.compileReport: .jrxml ফাইলটি কম্পাইল করে।
  • JasperFillManager.fillReport: রিপোর্টে ডেটা যোগ করে।
  • JasperExportManager.exportReportToPdfStream: রিপোর্টটি PDF ফরম্যাটে এক্সপোর্ট করে।
  • রিপোর্টটি একটি byte array আকারে ক্লায়েন্টে পাঠানো হবে।

ধাপ ৪: Employee ক্লাস তৈরি করা

এখানে Employee ক্লাস যা রিপোর্টে ব্যবহৃত হবে:

public class Employee {
    private int id;
    private String name;
    private String department;

    // Constructor, Getters and Setters
    public Employee(int id, String name, String department) {
        this.id = id;
        this.name = name;
        this.department = department;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getDepartment() {
        return department;
    }
}

ধাপ ৫: Report Exporting (PDF, Excel, etc.)

রিপোর্ট এক্সপোর্ট করার জন্য আমরা এক্সপোর্ট ফরম্যাটের প্রোপার উপায় ব্যবহার করেছি:

  1. PDF Export: রিপোর্টটি PDF ফরম্যাটে রিটার্ন করা হচ্ছে।
  2. আপনি চাইলে Excel, CSV বা অন্য কোন ফরম্যাটে রিপোর্ট রিটার্ন করতে পারেন। উদাহরণস্বরূপ, Excel এক্সপোর্ট করতে JRXlsExporter ব্যবহার করা যাবে।
JRXlsExporter xlsExporter = new JRXlsExporter();
xlsExporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
xlsExporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
xlsExporter.exportReport();

ধাপ ৬: Client Request and Response

এখন আপনি GET /generateReport রিকোয়েস্ট পাঠালে PDF আউটপুটটি রিটার্ন হবে, যেটি আপনি একটি browser বা Postman-এর মাধ্যমে পরীক্ষা করতে পারবেন।

Output Response:

রিপোর্টটি PDF ফরম্যাটে ক্লায়েন্টে রিটার্ন হবে।


  • JasperReports এবং Spring Boot RESTful Web Services এর মাধ্যমে আপনি রিপোর্ট তৈরি করতে পারেন এবং সেই রিপোর্টটি বিভিন্ন ফরম্যাটে ক্লায়েন্টকে সরবরাহ করতে পারেন।
  • রিপোর্ট জেনারেট করার জন্য আপনি JasperReports API ব্যবহার করতে পারেন এবং ডেটা সোর্স হিসেবে JRBeanCollectionDataSource বা অন্য যে কোনো ডেটা সোর্স ব্যবহার করতে পারেন।
  • REST API এ রিপোর্ট রিটার্ন করার জন্য আপনি byte arrays ব্যবহার করতে পারেন, যা ক্লায়েন্টে ডাউনলোড হিসেবে পাঠানো হবে।
  • JasperReports দিয়ে PDF, Excel, HTML, CSV ইত্যাদি ফরম্যাটে রিপোর্ট তৈরি এবং এক্সপোর্ট করা সম্ভব।

এটি একটি পূর্ণাঙ্গ উদাহরণ যেখানে JasperReports এবং RESTful Web Services এর মাধ্যমে রিপোর্ট জেনারেট করার পদ্ধতি দেখানো হয়েছে।

Content added By

Dynamic Report Generation হল এমন একটি প্রক্রিয়া যার মাধ্যমে রিপোর্টগুলো রানটাইমে তৈরি করা হয়, অর্থাৎ রিপোর্টের কাঠামো এবং ডেটা নির্ভর করে ব্যবহারকারীর ইনপুট বা ডেটা সোর্সের ওপর। এটি স্ট্যাটিক রিপোর্টের থেকে আলাদা, যেখানে রিপোর্ট আগে থেকেই প্রস্তুত থাকে। JasperReports-এ Dynamic Report Generation-এ ডেটা এবং রিপোর্টের কাঠামো সময় অনুযায়ী পরিবর্তিত হতে পারে।

JasperReports-এর মাধ্যমে Dynamic Report Generation-এর জন্য JRXML ফাইলটি পরিবর্তন বা তৈরি করা যায়, এবং রিপোর্টটি কাস্টম ডেটা সোর্স থেকে তৈরি করা যায়। ডাইনামিক রিপোর্ট তৈরির জন্য সাধারণত Java code, JasperReports API, এবং XML templates ব্যবহার করা হয়।

Dynamic Report Generation-এর ধাপ

1. Data Source:

  • Dynamic রিপোর্ট তৈরি করার জন্য প্রথমে ডেটা সোর্স তৈরি করতে হবে। এটি হতে পারে JDBC, JavaBeans, CSV, বা XML ফাইল।

2. Dynamic JRXML Creation:

  • JRXML ফাইল (JasperReports Markup Language) একটি XML ফাইল যেখানে রিপোর্টের লেআউট, স্টাইল, এবং কনটেন্ট ডিফাইন করা থাকে।
  • Dynamic রিপোর্টের ক্ষেত্রে, JRXML তৈরি বা কাস্টমাইজ করার জন্য Java code ব্যবহার করা যেতে পারে।

3. Compiling JRXML:

  • JasperCompileManager.compileReportToFile() এর মাধ্যমে JRXML ফাইলটি .jasper ফরম্যাটে কম্পাইল করা হয়।

4. Filling the Report:

  • JasperFillManager.fillReport() ব্যবহার করে রিপোর্টে ডেটা ফিল করা হয়। রিপোর্টটি ফিল করার সময় parameters এবং data source ব্যবহার করা হয়।

5. Exporting the Report:

  • রিপোর্টটি রেন্ডার করার জন্য বিভিন্ন ফরম্যাটে JasperExportManager ব্যবহার করা হয় (যেমন PDF, HTML, Excel, CSV)।

Dynamic Report Generation Example in JasperReports

ধরা যাক, আপনি একটি Sales Report তৈরি করতে চান, যেখানে রিপোর্টের ডেটা এবং কাঠামো কাস্টম ইনপুট বা রানটাইম ডেটা সোর্সের উপর নির্ভরশীল।

Step 1: Create Dynamic JRXML with Java Code

Dynamic JRXML Creation Using Java Code:
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import java.util.*;

public class DynamicReportGeneration {

    public static void main(String[] args) {
        try {
            // Step 1: Prepare Dynamic JRXML content as a String (or use existing JRXML file)
            String jrxmlContent = createDynamicJRXML();

            // Step 2: Compile JRXML to JasperReport
            JasperReport jasperReport = JasperCompileManager.compileReport(jrxmlContent);

            // Step 3: Prepare Data Source (For example, using a collection of JavaBeans)
            List<Product> products = getProducts(); // Assume getProducts() provides a list of product data
            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(products);

            // Step 4: Fill the report with data
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("ReportTitle", "Dynamic Sales Report");
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);

            // Step 5: Export the report to PDF
            JasperExportManager.exportReportToPdfFile(jasperPrint, "DynamicSalesReport.pdf");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String createDynamicJRXML() {
        // Dynamically creating JRXML as a String (for simplicity)
        String jrxml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
            + "<jasperReport xmlns=\"http://jasperreports.sourceforge.net/jasperreports\" "
            + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
            + "xsi:schemaLocation=\"http://jasperreports.sourceforge.net/jasperreports "
            + "http://jasperreports.sourceforge.net/xsd/jasperreports.xsd\" "
            + "name=\"DynamicSalesReport\" pageWidth=\"595\" pageHeight=\"842\" "
            + "columnWidth=\"515\" leftMargin=\"40\" rightMargin=\"40\" "
            + "topMargin=\"40\" bottomMargin=\"40\">"
            + "<title>"
            + "<band height=\"60\">"
            + "<textField>"
            + "<reportElement x=\"0\" y=\"0\" width=\"515\" height=\"50\"/>"
            + "<textFieldExpression><![CDATA[\"Dynamic Sales Report\"]]"
            + "</textFieldExpression>"
            + "</textField>"
            + "</band>"
            + "</title>"
            + "<columnHeader>"
            + "<band height=\"40\">"
            + "<textField>"
            + "<reportElement x=\"0\" y=\"0\" width=\"100\" height=\"30\"/>"
            + "<textFieldExpression><![CDATA[\"Product Name\"]]</textFieldExpression>"
            + "</textField>"
            + "<textField>"
            + "<reportElement x=\"100\" y=\"0\" width=\"100\" height=\"30\"/>"
            + "<textFieldExpression><![CDATA[\"Price\"]]</textFieldExpression>"
            + "</textField>"
            + "</band>"
            + "</columnHeader>"
            + "<detail>"
            + "<band height=\"30\">"
            + "<textField>"
            + "<reportElement x=\"0\" y=\"0\" width=\"100\" height=\"30\"/>"
            + "<textFieldExpression><![CDATA[$F{productName}]]></textFieldExpression>"
            + "</textField>"
            + "<textField>"
            + "<reportElement x=\"100\" y=\"0\" width=\"100\" height=\"30\"/>"
            + "<textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>"
            + "</textField>"
            + "</band>"
            + "</detail>"
            + "</jasperReport>";
        return jrxml;
    }

    // Example method to fetch product data
    private static List<Product> getProducts() {
        List<Product> products = new ArrayList<>();
        products.add(new Product("Product 1", 50.0));
        products.add(new Product("Product 2", 100.0));
        return products;
    }
}

class Product {
    private String productName;
    private Double price;

    public Product(String productName, Double price) {
        this.productName = productName;
        this.price = price;
    }

    public String getProductName() {
        return productName;
    }

    public Double getPrice() {
        return price;
    }
}

Explanation:

  1. Dynamic JRXML Creation: createDynamicJRXML() মেথডে একটি JRXML ফাইল কনফিগার করা হয়েছে, যা Product Name এবং Price নিয়ে একটি ডাইনামিক রিপোর্ট তৈরি করবে।
  2. Data Source: ডেটা সোর্স হিসেবে JRBeanCollectionDataSource ব্যবহার করা হয়েছে, যা Product ক্লাসের একটি List ব্যবহার করে রিপোর্টে ডেটা প্রবাহিত করবে।
  3. Filling the Report: JasperFillManager.fillReport() ব্যবহার করে রিপোর্টের মধ্যে ডেটা এবং প্যারামিটারগুলো পূর্ণ করা হয়েছে।
  4. Exporting to PDF: JasperExportManager.exportReportToPdfFile() ব্যবহার করে রিপোর্টটিকে PDF ফরম্যাটে এক্সপোর্ট করা হয়েছে।

Dynamic Reports with Conditional Logic

JasperReports-এ conditional logic ব্যবহার করে আপনি রিপোর্টের কনটেন্ট এবং ফরম্যাট কাস্টমাইজ করতে পারেন। উদাহরণস্বরূপ, আপনি Sales Amount এর উপর ভিত্তি করে কিছু নির্দিষ্ট স্টাইল বা শর্ত প্রয়োগ করতে পারেন।

Example: Conditional Formatting Based on Sales Amount

<styles>
    <style name="highSales" isDefault="false" fontSize="12" bold="true" forecolor="#FF0000"/>
    <style name="lowSales" isDefault="true" fontSize="12" bold="false" forecolor="#0000FF"/>
</styles>

<textField>
    <reportElement x="0" y="100" width="200" height="30"/>
    <textFieldExpression><![CDATA[$F{price}]]></textFieldExpression>
    <textElement>
        <conditionalStyle>
            <conditionExpression><![CDATA[$F{price} > 75]]></conditionExpression>
            <style name="highSales"/>
            <style name="lowSales"/>
        </conditionalStyle>
    </textElement>
</textField>

এখানে, Sales Amount (Price) ৭৫ এর বেশি হলে red text হবে এবং কম হলে blue text হবে।


  1. Dynamic Report Generation JasperReports-এ ডেটার উপর ভিত্তি করে রিপোর্ট তৈরি করার একটি শক্তিশালী উপায়।
  2. Java Code ব্যবহার করে JRXML ফাইল তৈরি এবং কাস্টমাইজ করা যায়।
  3. Data Source এবং Parameters এর মাধ্যমে রিপোর্টে ডেটা পাস করা যায়, যা ডাইনামিক রিপোর্ট তৈরির জন্য অত্যন্ত গুরুত্বপূর্ণ।
  4. Conditional Logic ব্যবহার করে রিপোর্টের কনটেন্ট এবং ফরম্যাট কাস্টমাইজ করা সম্ভব।

JasperReports-এ ডাইনামিক রিপোর্ট তৈরি করার মাধ্যমে আপনি আরও উন্নত এবং কাস্টমাইজড রিপোর্ট তৈরি করতে পারবেন যা পরিবর্তনশীল ডেটা এবং শর্ত অনুযায়ী সময়োপযোগী হতে পারে।

Content added By
Promotion

Are you sure to start over?

Loading...