function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Manju053Manju053 

Batch apex to send email with VF template

Hello Developers

I want to design a batch apex where it should fire an email on daily basis, and i have designed a visualforce component and controller with vf email templates where it sends reports with csv attachments, How do i design a batch apex class where it can send the vf email templates on daily basis

This is my VF component
 
<apex:component controller="ReportsToEmailController" access="global">
    <apex:attribute name="ReportId" description="Report ID" type="Id" assignTo="{!rptId}"/>
    <apex:attribute name="Color" description="Background color" type="String" assignTo="{!rptId}"/>
    <apex:outputPanel >      
        
        <table style="width: 100%;">
            <thead style="background : {!Color}">                
                <apex:repeat value="{!ReportResult.reportMetadata.detailColumns}" var="colName">
                    
                    <!-- reportMetadata is a class where it contains metadata of a report.
DetailColumns is a method of ReportMetadata class, it returns the API names(Coloumns Names)
for the fields that contain detailed data-->
                    
                    <th><apex:outputText value="{!ReportResult.reportExtendedMetadata.detailColumnInfo[colName].label}"/></th>
                    
                    
                    <!-- reportExtendedMetadata is class where it contains Report extended metadata and
it provides data type and label information.
detailColumnInfo is a method of reportExtendedMetadata clas, it returns map of columns names
and its label to Display as Header -->
                    
                </apex:repeat>
                <!-- Grouped fieds in summary report to get in header -->
                <apex:repeat value="{!ReportResult.reportMetadata.groupingsDown}" var="colName">
                    <th><apex:outputText value="{!colName.name}"/></th>
                </apex:repeat>
            </thead>
            <tbody>
                
                <!-- Summary Report with 2 level of grouping -->
                <apex:repeat value="{!ReportResult.groupingsDown.groupings}" var="groupingLevel1" >
                    <apex:repeat value="{!groupingLevel1.groupings}" var="groupingLevel2" >
                        <apex:repeat value="{!ReportResult.factMap[groupingLevel2.key+'!T'].rows}" var="row" rows="999">
                            <!-- Here we will get entire data of each row and T refers to the Row -->
                            <tr> <apex:repeat value="{!row.dataCells}" var="cell">
                                <!-- Here we will get data of each cell and displayed -->
                                <td><apex:outputText value="{!cell.label}"/></td>
                                </apex:repeat><td>{!groupingLevel1.label}</td><td>{!groupingLevel2.label}</td> </tr>
                        </apex:repeat>
                    </apex:repeat>
                </apex:repeat>
                
                <!-- Summary Report with 1 level of grouping -->
                <apex:repeat value="{!ReportResult.groupingsDown.groupings}" var="grouping" >
                    <apex:repeat value="{!ReportResult.factMap[grouping.key+'!T'].rows}" var="row" rows="999">
                        <!-- Here we will get entire data of each row and T refers to the Row -->
                        <tr> <apex:repeat value="{!row.dataCells}" var="cell">
                            <!-- Here we will get data of each cell and displayed -->
                            <td><apex:outputText value="{!cell.label}"/></td>
                            </apex:repeat><td>{!grouping.label}</td> </tr>
                    </apex:repeat>
                </apex:repeat>
                
                <!-- Tabular Report -->
                <apex:repeat value="{!ReportResult.factMap['T!T'].rows}" var="row" rows="999">
                    <!-- Here we will get entire data of each row and T refers to the Row -->
                    <tr> <apex:repeat value="{!row.dataCells}" var="cell">
                        <!-- Here we will get data of each cell and displayed -->
                        <td><apex:outputText value="{!cell.label}"/></td>
                        </apex:repeat></tr>
                </apex:repeat>
                <!--</apex:repeat>-->
            </tbody>
        </table>
    </apex:outputPanel>
</apex:component>

apex controller
 
public class ReportsToEmailController {
    public Id rptId { get; set; } // Here we will get the report Id from the VF Component
    private transient Reports.ReportResults results; // It will hold the entire data of a report
 
    /*********************
     // Method Name : getReportResult
     // Description : Here we will get the data of a report and send to the VF Component
    /********************/
 
    public Reports.ReportResults getReportResult() {
        // Here it will run the report with that report ID and adding the report data into results
        results = Reports.ReportManager.runReport(rptId, true);
        return results;
    }
}

Vf template
 
<messaging:emailTemplate subject="Report" recipientType="User" >
    <messaging:plainTextEmailBody >
        Hi {!recipient.FirstName}
        Please find the below attachments. 
 
    </messaging:plainTextEmailBody>
    <messaging:attachment filename="Account Report.xls">
        <!-- Here we can add multiple Reports -->
        <c:ReportsToEmail ReportId="00O2w000002RDbUEAW"/>
        <c:ReportsToEmail ReportId="00O2w000002Rp56EAC"/>
    </messaging:attachment>
</messaging:emailTemplate>

Can someone help me with the batch apex
Best Answer chosen by Manju053
Sachin HoodaSachin Hooda
You would need a scheduler in order to schedule the batch class on a daily basis.
So the whole idea would be,
1. Create another class that implements the schedulable interface & creates an object of the batch class. [Scheduler class]
2. Create a cron that will execute the class daily. (use cronmaker.com to make one)
3. And the final one is to create an object of the Scheduler class.

Here's the Scheduler class:
global with sharing class Schedule_BatchapextosendEmail implements Schedulable {
    global Schedule_BatchapextosendEmail () {
//constructor
    }
    global void execute(SchedulableContext sc){
        batchapextosendemail batchObj= new batchapextosendemail (); //creates an object of the Batch class
        Database.executeBatch(batchObj); //executes the bacth class
    }
}
Use CronMaker to create a cron,
0 0 12 1/1 * ? *

Now, all you need is to Schedule the Batch class using the cron that runs on a daily basis.
Now on the Anonymous window, create an object of the scheduler class & schedule it.
Schedule_BatchapextosendEmail obj = new Schedule_BatchapextosendEmail();
String cron = '0 0 12 1/1 * ? *';
System.Schedule('ScheduleMailEveryday', cron, obj);
Execute the script from the Anonymous window.
I think this should be it.
Make sure whether a job is scheduled or not.
Go to setup, Search Scheduled Jobs in the Quick Find.
And look for ScheduleMailEveryday. If it exists you're done.

I hope it worked. (:

All Answers

Manju053Manju053
FYI
below is my Batch apex code

How do i check if the batch class is working or not

what should i give in the anonomous window
 
global class batchapextosendemail implements Database.Batchable<sObject>
{
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query = 'select id,name from lead where Email_Fire__c =true';
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<Lead> scope)
    {       
        EmailTemplate emailTemplate = [select Id, Body from EmailTemplate where DeveloperName = 'Send Email'];
        
        
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setToAddresses(new String[] {'grimlock053@gmail.com'});
        email.setSaveAsActivity(false);
        email.setTemplateId(emailTemplate.Id);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});
        
    }  
    global void finish(Database.BatchableContext BC)
    {
    }
}

 
Sachin HoodaSachin Hooda
You would need a scheduler in order to schedule the batch class on a daily basis.
So the whole idea would be,
1. Create another class that implements the schedulable interface & creates an object of the batch class. [Scheduler class]
2. Create a cron that will execute the class daily. (use cronmaker.com to make one)
3. And the final one is to create an object of the Scheduler class.

Here's the Scheduler class:
global with sharing class Schedule_BatchapextosendEmail implements Schedulable {
    global Schedule_BatchapextosendEmail () {
//constructor
    }
    global void execute(SchedulableContext sc){
        batchapextosendemail batchObj= new batchapextosendemail (); //creates an object of the Batch class
        Database.executeBatch(batchObj); //executes the bacth class
    }
}
Use CronMaker to create a cron,
0 0 12 1/1 * ? *

Now, all you need is to Schedule the Batch class using the cron that runs on a daily basis.
Now on the Anonymous window, create an object of the scheduler class & schedule it.
Schedule_BatchapextosendEmail obj = new Schedule_BatchapextosendEmail();
String cron = '0 0 12 1/1 * ? *';
System.Schedule('ScheduleMailEveryday', cron, obj);
Execute the script from the Anonymous window.
I think this should be it.
Make sure whether a job is scheduled or not.
Go to setup, Search Scheduled Jobs in the Quick Find.
And look for ScheduleMailEveryday. If it exists you're done.

I hope it worked. (:
This was selected as the best answer
Manju053Manju053
@sachin
i t worked, thank you so much