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
SlanganSlangan 

Automated email with PDF attachment & attachment on opportunity

Hello -

 

I have developed a vf page for our sales team that shows a formatted Forecast for the opportunity. This page is embedded directly on the opportunity object in a colapsable page section called 'Forecast'. There are two buttons on the Forecast page (at the top)- one to preview the forecast in PDF form (a second vf page) and another to "Generate Forecast". This second button takes the user to a screen with a list of potential people to whom they can send the forecast (listed as checkboxes). Once the user selects the people to whom they want to send the Forecast and hit the send button, the Forecast is sent as a PDF attachment on an email to whomever they have selected. As well, the PDF is saved as an attachment on the opportunity.

 

 My issue is that while my initial tests allowed me to open and view the attachment, I now get an error when I try to open either attachment (from the email, or from the Notes & Attachments area on the opportunity). I know I must have tweaked something that is causing this error but I do not know what? The error is "File does not begin with '%PDF-'"

 

Any help would be appreciated - this is my first time working with controllers, so it might be something obvious that I am missing. I have attached the code for the page that triggers the creation of the PDF's & email, and the controller associated with it.

 

Page Code:

 

<apex:page standardController="Opportunity" Extensions="emailForecast" showHeader="false" sideBar="false">
<apex:form >
<apex:pageBlock >
<apex:pageblockSection >
<apex:outputText value="Please select the people to whom you would like to email your forecast:"/><br/><br/>
<apex:pageblockSectionItem >
<apex:selectCheckboxes value="{!Addresses}" layout="pageDirection" style="text-align:left;">
<apex:selectOptions value="{!items}"/>
</apex:selectCheckboxes>
</apex:pageblockSectionItem><br/>
<apex:commandButton value="Send" action="{!emailPeople}" status="status" />
</apex:pageblockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

 

 Controller:

 

public class emailForecast {
ApexPages.StandardController controller;
public Opportunity q {get;set;}
public Opportunity opportunityNo {get;set;}
String op = ApexPages.currentPage().getParameters().get('id');

public emailForecast(ApexPages.StandardController c) {
controller = c;
q = (Opportunity) c.getRecord();}

public PageReference emailPeople() {
String thisOpp = ApexPages.currentPage().getParameters().get('Id');
opportunityNo = [select Opportunity_No__c, NAME,Id,OwnerId,Account.Id from Opportunity where Id = :thisOpp];

//Attach the Forecast to the Notes & Attachments Area
/* Get the page definition */
PageReference ForecastPdfPage = Page.forecast;
/* set the id on the page definition */
ForecastPdfPage.getParameters().put('Id',q.Id);
/* generate the pdf blob */
Blob ForecastPdfBlob = ForecastPdfPage.getContent();
/* create the attachment against the Opportunity */
Attachment a = new Attachment(parentId = q.id, name=opportunityNo.NAME + '-'+ opportunityNo.Opportunity_No__c+'-'+'Forecast.pdf', body = ForecastPdfBlob);
/* insert the attachment */
insert a;

// Create an email
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage ();
email.setSaveAsActivity(true);
// NEED TO FIGURE OUT HOW TO ADD TARGET ID SO WE CAN SAVE TO HISTORY - email.setTargetObjectId(opportunityNo.OwnerId);
email.setToAddresses(addresses);
email.setSenderDisplayName('New Order');
email.setSubject('New Order Created for Opportunity # ' + opportunityNo.Opportunity_No__c);
email.setPlainTextBody('A new order has been created for ' + opportunityNo.Name +' , '+ opportunityNo.Opportunity_No__c+'. The ERF and SO Approval are attached.');
email.setHtmlBody('A new order has been created for' + '&nbsp;'+'<b>'+ opportunityNo.Name +'&nbsp;'+'</b>'+ opportunityNo.Opportunity_No__c+'. The ERF and SO Approval are attached.'+
' To view this Opportunity <a href=https://na1.salesforce.com/'+ q.Id +'><b>click here</b></a>');

// Create an email attachment
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
// Set name of PDF
efa.setFileName(opportunityNo.Opportunity_No__c+'forecast.pdf');
// Set body of PDF
efa.setBody(ForecastPdfBlob);
// Attach the PDF to your email
email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

// Send email & return to Opportunity
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});


/* send the user back to the opportunity detail page */
return controller.view();


}

String[] addresses = new String[]{};

public List<SelectOption> getItems() {
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('email1@company.com','Person1'));
options.add(new SelectOption('email2@company.com','Person2'));
options.add(new SelectOption('email3@company.com','Person3'));
...(and so on)

return options;
}
public String[] getAddresses() {
return addresses;
}
public void setAddresses(String[] addresses) {
this.addresses = addresses;
}



}

 

 

 

Thanks

Shannon

 

 

Message Edited by Slangan on 06-10-2009 10:15 AM
Message Edited by Slangan on 06-10-2009 10:29 AM
Message Edited by Slangan on 06-10-2009 02:18 PM
Best Answer chosen by Admin (Salesforce Developers) 
SlanganSlangan

I have it working, but am not sure why my fix is helping.

 

I changed:

 

public addAttachment(ApexPages.StandardController opportunity) {}

 

 

 

To:

 

public addAttachment(ApexPages.StandardController c) { controller = c;}

 

I am a bit of a hack, so if anyone out there sees this as a terrible solution, please post so I can learn from my errors.

 

Thanks again -

 

 

Shannon

All Answers

SlanganSlangan

After some more fiddling around, I have cleaned up the code a bit and now all of the attachments save to the right places AND can be viewed properly. But now I have a new problem. If I put return controller.view(); I get a "System.NullPointerException: Attempt to de-reference a null object"  error. When I put return null; I do not get an error, but I also can't return the user to the opportunity (they get stuck on the 'select a user page'). Can someone tell me how to force the value so it doesn't return null?

 

New Code:

public class emailForecast {

ApexPages.StandardController controller;
public addAttachment(ApexPages.StandardController opportunity) {}

public PageReference emailPeople() {

//Get the opportunity Id and name
Opportunity opportunity = [SELECT id, name,Opportunity_No__c FROM opportunity WHERE Id = :System.currentPageReference().getParameters().get('id')];

//Create PDF
// Reference the page, pass in a parameter to force PDF
PageReference pdf = new PageReference('/apex/forecast' + '?id=' + opportunity.id);
pdf.getParameters().put('p','p');
pdf.setRedirect(true);
// Grab the PDF!
Blob b = pdf.getContent();
/* create the attachment against the Opportunity */
Attachment a = new Attachment(parentId = opportunity.id, name=opportunity.name + '-'+ opportunity.Opportunity_No__c+'-'+'Forecast.pdf', body = b);
/* insert the attachment */
insert a;


// Create an email
Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage ();
email.setSaveAsActivity(true);
email.setToAddresses(addresses);
email.setSenderDisplayName('New Order');
email.setSubject('New Order Created for Opportunity # ' + opportunity.Opportunity_No__c);
email.setPlainTextBody('A new order has been created for ' + opportunity.Name +' , '+ opportunity.Opportunity_No__c+'. The ERF and SO Approval are attached.');
email.setHtmlBody('A new order has been created for' + '&nbsp;'+'<b>'+ opportunity.Name +'&nbsp;'+'</b>'+ opportunity.Opportunity_No__c+'. The ERF and SO Approval are attached.'+
' To view this Opportunity <a href=https://na1.salesforce.com/'+ opportunity.Id +'><b>click here</b></a>');

// Create an email attachment
Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment();
// Set name of PDF
efa.setFileName(opportunity.Opportunity_No__c+'forecast.pdf');
// Set body of PDF
efa.setBody(b);
// Attach the PDF to your email
email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

// Send email & return to Opportunity
Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email});

/* send the user back to the opportunity detail page */
return controller.view();


}

String[] addresses = new String[]{};

public List<SelectOption> getItems() {
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('user1@email.com','Person1'));
options.add(new SelectOption('user1@email','Person2'));

return options;
}
public String[] getAddresses() {
return addresses;
}
public void setAddresses(String[] addresses) {
this.addresses = addresses;
}



}

 

Message Edited by Slangan on 06-10-2009 01:36 PM
SlanganSlangan

I have it working, but am not sure why my fix is helping.

 

I changed:

 

public addAttachment(ApexPages.StandardController opportunity) {}

 

 

 

To:

 

public addAttachment(ApexPages.StandardController c) { controller = c;}

 

I am a bit of a hack, so if anyone out there sees this as a terrible solution, please post so I can learn from my errors.

 

Thanks again -

 

 

Shannon

This was selected as the best answer
vcassvcass
Shannon, did you figure out what fixed your error ""File does not begin with '%PDF-'" ? I am having the same issue.
SlanganSlangan

The error means you didn't actually save anything (no blob). I can't remember what I changed to solve the problem, but I did update my code so it was the version that worked.

 

Did you try copying it?

vcassvcass
No not yet. I just did a visual comparison but I will do a file compare to see what is different.
MKIMKI

The solution to "File does not begin with '%PDF-'" is (in my case), adding the following attribute to the output page definition:

 

renderAs="pdf"
Message Edited by MKI on 08-31-2009 10:27 AM
PamSalesforcePamSalesforce

Hi,

 

I am trying to get the pdf attachment from an inbound mail and link it to the created Custom object so that i can see the attachment in 'Notes and Attachment' section.But my code is not working.

My code is:

 if (email.textAttachments!=null){

      for (integer i = 0 ; i < email.textAttachments.size() ; i++) {
                try {
                               if (email.textAttachments[i].filename != null) {
                             Attachment newAttachment = new Attachment(ParentId = newMileage[0].Id,Name =                email.textAttachments[i].filename,Body = Blob.valueOf(email.textAttachments[i].body) );
                    insert newAttachment;

 }
            catch (Exception e1) {
            System.debug('\n\nError:: ' + e1 + '\n\n');

            }

 

}

Please help me.

 

Thanks,

SlanganSlangan

Hey there -

 

I would love to help you, but that code is way over my head right now (I am still very much a novice at all of this). Perhaps try a new post?

 

Let us know how it works out & if you find a solution.

NaishadhNaishadh

Hi 

 

There is no hacking. The only issue is you haven't initialized your controller. So in your previous example your controller object is null. 

Iqra TechIqra Tech
trigger OpptyTest on Opportunity (before insert, before update) {

  Opportunity[] opptys = [SELECT Id, (SELECT Id, Name, ContentType FROM Attachments)  FROM Opportunity 
                          where id IN :Trigger.newMap.keySet() AND (Not Billing_Address__c  like '%United Arab Emirates%') ];
  for(Opportunity o : opptys){
            Attachment[] attc = o.Attachments;
            System.debug('attc.size() : ' + attc.size());
            if(attc.size()>0){
             System.debug('Need to set Syllabus Attached to true for Opportunity Id: ' + o.id);
             System.debug('just testing this: ' + Trigger.newMap.get(o.Id).Id);
             
                Trigger.newMap.get(o.Id).Is_declaration_attached__c = true;
                Trigger.newMap.get(o.Id).International_Clinets__c = True;
               // o.
            }
            else{
             Trigger.newMap.get(o.Id).Is_declaration_attached__c = false;
                //o.Syllabus_Attached__c = false;
                //o.addError('Please provide the Quote as an Attachment before saving this record');
            }                  
    }


i used this trigger to full fill my requir,ent but i need more thing can anyone please help me regarding to add my requir,ment in this trigger please its an urgent plzzzzzzzzzzz
Iqra TechIqra Tech

i need to achive this requiemnt in above trigger currently trigger working fine if  "International_Clinets__c = True;" and Is_declaration_attached__c = true; but not shown the error messgae when "International_Clinets__c = True;"  and Attachment are not attaached please help me to achive the follwing requirment.

!)i need to add if "International_Clinets__c = True;" then chehke attachements are atteach or not if attachment are not attached then through an error message "You are an International clinet please attach the attachement"

2) if "International_Clinets__c = True;" then chehke attachements are atteach or not if attachment are  attached then simply both chehkbox true
i.e  "International_Clinets__c = True;" and Is_declaration_attached__c = true;