• SFDC Hedgehog
  • NEWBIE
  • 40 Points
  • Member since 2014

  • Chatter
    Feed
  • 1
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 5
    Questions
  • 28
    Replies
Hi Everyone,

I found a great solution online which allows to email a report from SF to non-SF users - http://kevindotcar.wix.com/home/apps/blog/how-to-schedule-a-report-to-send

This worked great until the report had non-english characters which is causing an issue.

VF email template is used and when the report has non-english characters, it displays the error message of "Error occurred trying to load the template for preview: BLOB is not a valid UTF-8 string. Please try editing your markup to correct the problem." at the top of the page.

Here's the code for VF template
<messaging:emailTemplate subject="Data Export" recipientType="User" >
<messaging:plainTextEmailBody >

Hi,

please find attached the report(s) you have requested...

Kind regards,
{!$Organization.Name}
</messaging:plainTextEmailBody>
    
<messaging:attachment filename="report.csv" >
<c:ReportExportController xstrRptname="00OR0000000kUFo"/>
</messaging:attachment>
</messaging:emailTemplate>
Here's the code for ReportExportController.

<apex:component controller="CSVStream" access="global">
    <apex:attribute name="xstrRptname" description="report ID" type="String" assignTo="{!strRptname}"/>
    <apex:outputText value="{!CSVStream}" escape="false"/>
</apex:component>
Here's the code for CSVStream.
public class CSVStream {
    public static Boolean isTest;
    public static String strEmailAddr;
    public static String strOut;
    public static Boolean restRequested;
    public String strEmail{get;set;}
    public String strRptname{get;set;}
    
    void CSVStream () {
        strOut = '';        
        }

   public String getCSVStream() {
        restRequested = System.isFuture() || System.isScheduled();
        executeRpt();
        return strOut;
        }
  
    public void executeRpt() {
        String requestURL;
        requestURL = '/' + strRptname + '?csv=1&exp=1';
        strOut = new PageReference(requestURL).getContent().toString();
        System.debug('CALLING executeRpt:  output= ' + strOut );
    }

}
Does anybody have an idea how to fix this?

Appreciate your help in advance!!



  • September 19, 2014
  • Like
  • 0
Hi all,

I saw that El Capitan was not on the list of supported platforms for the Force.com IDE and before I go stomping on my brand-new Mac, I was just wondering if there was  FAQ, or if there were some things some people could share.

Thanks in advance for any advice
Hi everyone,
I need to send some reports to a user as email attachments.
Currently, I use reportResults.reportMetadata to run the report and I insert the resuls via a component that's inserted on a VF messaging template.

The template looks like this;
<messaging:emailTemplate subject="Excel Data Export of Edgecast Reports" recipientType="User" >
<messaging:plainTextEmailBody >

Hi,

please find attached the report(s) you have requested...

Kind regards,
{!$Organization.Name}
</messaging:plainTextEmailBody>

 <messaging:attachment filename="VESOpportunity.HTML">
 <c:ReportOpportunityExportController xstrRptname="00O50000004TUS9"/>
 </messaging:attachment>

</messaging:emailTemplate>
The Component looks like this;
<apex:component controller="SyncReportController" access="global">
<apex:attribute name="xstrRptname" description="report ID" type="String" assignTo="{!reportId}"/>
<!-- apex:outputText value="{!ReportResults}" escape="false"/ !-->
  <style>
      table.reportResults {
          width: 100%;
      }
  </style>
  <apex:outputPanel id="reportResults" layout="block">
      <apex:outputPanel >
         <table class="reportResults">
           <thead>
               <apex:repeat value="{!reportResults.reportMetadata.detailColumns}" var="colName">
                   <th><apex:outputText value="{!reportResults.reportExtendedMetadata.detailColumnInfo[colName].label}"/></th>
               </apex:repeat>
           </thead>

           <tbody>
               <apex:repeat value="{!reportResults.factMap['T!T'].rows}" var="row">
                   <tr>
                       <apex:repeat value="{!row.dataCells}" var="cell">
                           <td><apex:outputText value="{!cell.label}"/></td>
                       </apex:repeat>
                   </tr>
               </apex:repeat>
           </tbody>
         </table>
      </apex:outputPanel>
  </apex:outputPanel>
</apex:component>
The component controller looks like this;
public with sharing class SyncReportController {

    public Id reportId { get; set; }
    public Id instanceId { get; set; }
    public Boolean reportIsRunning { get; set; }
    private transient Reports.ReportResults reportResults;

    public SyncReportController() {
        }

    public void setReportId(String theReport) {
        reportId = theReport;
        }

    public PageReference runReport() {
        reportResults = Reports.ReportManager.runReport(reportId, true);

        return null;
    }

    public Reports.ReportResults getReportResults() {
        reportResults = Reports.ReportManager.runReport(reportId, true);
        return reportResults;
    }
}

The trouble is pretty obvious;  
if the report returns more than 1000 rows the messaging will fail because of the apex:repeat call, and this report can return maybe five thousand rows.

My temporary solution is to filter the report into three different reports, based on a report-logic specific filter criteria, but that too will eventually fail.

Ideally, I would like something equivalent to "readonly=true" on the apex:component tag - It would make sense for SFDC to support this, because it is in effect a "page". but that's not going to happen.

I tried remoteObject but that is limited to 100 objects per call.
I used to be able to insert a report directly as an attachment but that has gone away since SFDC does not allow 
PageReference(requestURL).getContent()
On email services anymore...

Does anyone have any ideas? 

Many thanks,


 
Hi all,

I've scoured the net but nothing seems to work....
I have a custom object (Account_Request__c).
I have a Detail page Button.

This is the source to the button;
 
{!REQUIRESCRIPT("/soap/ajax/30.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/29.0/apex.js")}

var message = new sforce.SingleEmailMessage();
var xKey = "{!Account_Request__c.Id}";
message.replyTo = "sfdchedgehog@gmail.com";
message.toAddresses = ["toaddress@gmail.com"];
message.targetObjectId = xKey;
message.templateId = "00Xe0000000M2FH";  // valid template ID - I checked
message.saveAsActivity = false;    // eventually I want to set to "true"
var result = sforce.connection.sendEmail([message]);
if(result[0].success != 'true') {
alert(result[0].errors);
}

And I always get an error back that says
{message:'invalid cross reference id', statusCode:'INVALID_CROSS_REFERENCE_KEY', targetObjectId:null, }
I made sure the Account_Request__c object has activities enabled.  My org does NOT have cross-scripting enabled  (I'm wondering if that has something to do with this.)-  And I made sure the Account_Request__c ID is not null. 

Any ideas about what I'm doing wrong?

I can auto-populate a template with all the Account_Request__c info from the "Send an Email" button on the activities related list, but I keep getting an error on autosave, so I'm trying to find a way around that.   Any ideas are welcome.

Thanks!
 
I'm trying to get a workflow to fire an outbound message to my Salesforce instance but it always stalls in the outbound message queue with a "(404) Not Found" error.
  • I have a remote site that is active   (https://<instance>.salesforce.com)
  • The webservice is simple;
global class AccountTypeWebService { 
   webService static void AccountTypeChange(String theAccountID, String theAccountType) {
        System.debug('theAccountID: ' + theAccountID);
        System.debug('theAccountType: ' + theAccountType);
     }
}
  • The URL for the outbound message is as follows;
https://<instance>.salesforce.com/services/AccountTypeWebService/AccountTypeChange
  • I have an active workflow that has an immediate workflow action that calls the above URL and specifies that the Account ID and the custom field (AccountType) are to be passed.

Can someone tell me what I'm doing wrong?    It must be simple.

Thanks

 
I have a test class that that is inserting a product into the standard pricebook.
Relevant code:
Id pricebookId = Test.getStandardPricebookId();

Product2 prd1 = new Product2 (Name='Test Product Entry 1', Description='Test Product Entry 1',productCode = '99999', isActive = true);
insert prd1;

PricebookEntry pbe1 = new PricebookEntry (Product2ID=prd1.id, Pricebook2ID=pricebookId, UnitPrice=50, isActive=true);
insert pbe1;
Next, in the trigger, I can have the same product code in multiple pricebooks, so I have to check to see if the product
is from the standard pricebook.  Again, relevant code;
thePbe = [SELECT id, Product2Id, Pricebook2.IsStandard, Pricebook2.Id  
                   FROM PricebookEntry 
                   WHERE  IsActive = true AND Pricebook2.IsStandard=true 
                   AND Product2Id IN (SELECT Id FROM Product2 WHERE ProductCode = '99999' And isActive = True) ];
This returns zero rows - which I thought was weird.  So, in the trigger I queried the price books like this;
List<PricebookEntry> pbe =  [SELECT id, Pricebook2.IsStandard, Pricebook2.Id  from PricebookEntry WHERE  IsActive = true ];
System.debug('pbe.size(): ' + pbe.size());    // Prints "1"

if(pbe.size() > 0)
     System.debug('pbe[0].Pricebook2.IsStandard: ' + pbe[0].Pricebook2.IsStandard);
This prints "false" (!)

In other words - I don't see why SFDC would give us the ability to get and set the "StandardPricebookId" - yet when queried, it is not the standard pricebook.    Obviously, I don't want to use Seealldata=true.   

Is there a way around this?   Does anyone see anything wrong?
Thanks.








 
1) Which requirement needs to be implemented by using standard workflow instead of Process Builder?
   Choose 2 answers
A.   Create activities at multiple intervals.
B.   Send an outbound message without Apex code.
C.   Copy an account address to its contacts.
D.   Submit a contract for approval.

2)  How can a developer refer to, or instantiate, a PageReference in Apex?
      Choose 2 answers
   A. By using a PageReference with a partial or full URL.
   B. By using the Page object and a Visualforce page name.
   C. By using the ApexPages.Page() method with  a  Visualforce page  name.
   D. By using the PageReference.Page() method with  a  partial  or  full URL.


3)  A developer has a single custom controller class that works with a Visualforce Wizard to support creating and editing multiple sObjects. 
  The wizard accepts data from user inputs across multiple Visualforce pages and from a parameter on the initial URL
   Which statement is unnecessary inside the unit test for the custom controller?

A. public ExtendedController(ApexPages.StandardController cntrl) { )
B. ApexPages.currentPage().getParameters() put(input', 'TestValue).
C.  Test.setCurrentPage(pageRef),
D.  String nextPage = controller.save().getUrl();


4)  Which statement about the Lookup Relationship between a Custom Object and a Standard Object is correct?

A.  The Lookup Relationship on the Custom Object can prevent the deletion of the Standard Object.
C.   The Custom Object will be deleted when the referenced Standard Object is delete
 
Hello all!

I'm trying to create a trigger that updates a custom "IsFrozen" field when a user's record is frozen.

The User object field, IsFrozen__c is supposed to see if the UserLogin object's IsFrozen field is updated to a value of true, and if so, update the user's record to true. I think this will greatly help us with the userdeactivation process.

My code is as follows:
trigger UserIsFrozen on User (before update) {
    
    for(User U: Trigger.new) {
        User oldU = Trigger.oldMap.get(U.Id);
        
        
        if(oldU.IsActive = true) {
            List<UserLogin> ULog = [SELECT Id, IsFrozen from UserLogin where UserId = :U.Id];
            List<UserLogin> newids = new List<UserLogin>();
            
            for(Userlogin USLog : ULog) {
                if(USLog.IsFrozen = true) {
                    U.IsFrozen__c = true;
                    newids.add(USLog);
                }
            }    
            if(newids.isEmpty()== false) {
                update newids;
                update U;
            }
        }
    }
}

The trigger isn't working right now. What am I doing wrong?
Hi everyone,
I need to send some reports to a user as email attachments.
Currently, I use reportResults.reportMetadata to run the report and I insert the resuls via a component that's inserted on a VF messaging template.

The template looks like this;
<messaging:emailTemplate subject="Excel Data Export of Edgecast Reports" recipientType="User" >
<messaging:plainTextEmailBody >

Hi,

please find attached the report(s) you have requested...

Kind regards,
{!$Organization.Name}
</messaging:plainTextEmailBody>

 <messaging:attachment filename="VESOpportunity.HTML">
 <c:ReportOpportunityExportController xstrRptname="00O50000004TUS9"/>
 </messaging:attachment>

</messaging:emailTemplate>
The Component looks like this;
<apex:component controller="SyncReportController" access="global">
<apex:attribute name="xstrRptname" description="report ID" type="String" assignTo="{!reportId}"/>
<!-- apex:outputText value="{!ReportResults}" escape="false"/ !-->
  <style>
      table.reportResults {
          width: 100%;
      }
  </style>
  <apex:outputPanel id="reportResults" layout="block">
      <apex:outputPanel >
         <table class="reportResults">
           <thead>
               <apex:repeat value="{!reportResults.reportMetadata.detailColumns}" var="colName">
                   <th><apex:outputText value="{!reportResults.reportExtendedMetadata.detailColumnInfo[colName].label}"/></th>
               </apex:repeat>
           </thead>

           <tbody>
               <apex:repeat value="{!reportResults.factMap['T!T'].rows}" var="row">
                   <tr>
                       <apex:repeat value="{!row.dataCells}" var="cell">
                           <td><apex:outputText value="{!cell.label}"/></td>
                       </apex:repeat>
                   </tr>
               </apex:repeat>
           </tbody>
         </table>
      </apex:outputPanel>
  </apex:outputPanel>
</apex:component>
The component controller looks like this;
public with sharing class SyncReportController {

    public Id reportId { get; set; }
    public Id instanceId { get; set; }
    public Boolean reportIsRunning { get; set; }
    private transient Reports.ReportResults reportResults;

    public SyncReportController() {
        }

    public void setReportId(String theReport) {
        reportId = theReport;
        }

    public PageReference runReport() {
        reportResults = Reports.ReportManager.runReport(reportId, true);

        return null;
    }

    public Reports.ReportResults getReportResults() {
        reportResults = Reports.ReportManager.runReport(reportId, true);
        return reportResults;
    }
}

The trouble is pretty obvious;  
if the report returns more than 1000 rows the messaging will fail because of the apex:repeat call, and this report can return maybe five thousand rows.

My temporary solution is to filter the report into three different reports, based on a report-logic specific filter criteria, but that too will eventually fail.

Ideally, I would like something equivalent to "readonly=true" on the apex:component tag - It would make sense for SFDC to support this, because it is in effect a "page". but that's not going to happen.

I tried remoteObject but that is limited to 100 objects per call.
I used to be able to insert a report directly as an attachment but that has gone away since SFDC does not allow 
PageReference(requestURL).getContent()
On email services anymore...

Does anyone have any ideas? 

Many thanks,


 
I am doing the exercise portion of the Trailhead module and I copies and pasted the first Apex code into the Developer console and saved it. When I went to to the debug Execute Anonymous Window and enter the following. I got the below error message.

EmailManager em = new EmailManager();
em.sendMail('Your email address', 'Trailhead Tutorial', '123 body');

Line: 13, Column: 1
System.EmailException: SendEmail failed. First exception on row 0; first error: INVALID_ID_FIELD, ID is invalid or you do not have access to the record.: [toAddresses, Your email address]

Here is the orginal code from the exercise that I copy and pasted into the Dev Console
public class EmailManager {
 
    // Public method
    public void sendMail(String address, String subject, String body) {
        // Create an email message object
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {address};
        mail.setToAddresses(toAddresses);
        mail.setSubject(subject);
        mail.setPlainTextBody(body);
        // Pass this email message to the built-in sendEmail method 
        // of the Messaging class
        Messaging.SendEmailResult[] results = Messaging.sendEmail(
                                 new Messaging.SingleEmailMessage[] { mail });

        // Call a helper method to inspect the returned results
        inspectResults(results);
    }
 
    // Helper method
    private static Boolean inspectResults(Messaging.SendEmailResult[] results) {
        Boolean sendResult = true;

        // sendEmail returns an array of result objects.
        // Iterate through the list to inspect results. 
        // In this class, the methods send only one email, 
        // so we should have only one result.
        for (Messaging.SendEmailResult res : results) {
            if (res.isSuccess()) {
                System.debug('Email sent successfully');
            }
            else {
                sendResult = false;
                System.debug('The following errors occurred: ' + res.getErrors());                 
            }
        }

        return sendResult;
    }
   
}
 
Hi all,

I've scoured the net but nothing seems to work....
I have a custom object (Account_Request__c).
I have a Detail page Button.

This is the source to the button;
 
{!REQUIRESCRIPT("/soap/ajax/30.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/29.0/apex.js")}

var message = new sforce.SingleEmailMessage();
var xKey = "{!Account_Request__c.Id}";
message.replyTo = "sfdchedgehog@gmail.com";
message.toAddresses = ["toaddress@gmail.com"];
message.targetObjectId = xKey;
message.templateId = "00Xe0000000M2FH";  // valid template ID - I checked
message.saveAsActivity = false;    // eventually I want to set to "true"
var result = sforce.connection.sendEmail([message]);
if(result[0].success != 'true') {
alert(result[0].errors);
}

And I always get an error back that says
{message:'invalid cross reference id', statusCode:'INVALID_CROSS_REFERENCE_KEY', targetObjectId:null, }
I made sure the Account_Request__c object has activities enabled.  My org does NOT have cross-scripting enabled  (I'm wondering if that has something to do with this.)-  And I made sure the Account_Request__c ID is not null. 

Any ideas about what I'm doing wrong?

I can auto-populate a template with all the Account_Request__c info from the "Send an Email" button on the activities related list, but I keep getting an error on autosave, so I'm trying to find a way around that.   Any ideas are welcome.

Thanks!
 
We are getting an error when we try to change a custom object field. This custom object (Projects) has Apex triggers that affect Opportunities associated with it (there are roughly 380 Opportunities associated with this object). The error is this:

There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger Publication caused an unexpected exception, contact your administrator: Publication: execution of AfterUpdate caused by: System.LimitException: Apex CPU time limit exceeded: Trigger.Publication: line 316, column 1".

On the day that we started receiving this error, we changed our calendar year to a fiscal year (7/1-6/30) and also added a rollup in the Opportunity based on this new fiscal year.

Any ideas?
I'm trying to create assignment rules, workflows, or triggers that will change the account owner to our desired user when we mass import leads into our system. 

We have created a custom field titled "Buy From", which tells us the account where the lead purchases their supplies from. I want to make the lead owner the same as the owner of the "Buy From" account when the leads are mass imported. Any idea on best practices to do this?

Hi all,

I am trying to create Permissionsets from apex.I am able to create  permission sets with object and field permissions enabled through apex. Any Idea how to create permissionsets with specific tab settings permissions enabled through apex code ?
Below is how I gave object and field permissions.

PermissionSet ps = new PermissionSet();
    ps.Name = 'Test';
    ps.Label = 'Test';
insert ps;
ObjectPermissions op = new ObjectPermissions();
op.parentId = ps.Id;
op.SobjectType = 'Account';
op.PermissionsCreate = true;
op.PermissionsRead = true;
insert op;
FieldPermissions fp = new FieldPermissions();
fp.parentId = ps.Id;
fp.SobjectType = 'Account';
fp.Field = 'Account.AccountSource';
fp.PermissionsRead = true;
fp.PermissionsEdit = true;
insert fp;


 

I'm trying to get a workflow to fire an outbound message to my Salesforce instance but it always stalls in the outbound message queue with a "(404) Not Found" error.
  • I have a remote site that is active   (https://<instance>.salesforce.com)
  • The webservice is simple;
global class AccountTypeWebService { 
   webService static void AccountTypeChange(String theAccountID, String theAccountType) {
        System.debug('theAccountID: ' + theAccountID);
        System.debug('theAccountType: ' + theAccountType);
     }
}
  • The URL for the outbound message is as follows;
https://<instance>.salesforce.com/services/AccountTypeWebService/AccountTypeChange
  • I have an active workflow that has an immediate workflow action that calls the above URL and specifies that the Account ID and the custom field (AccountType) are to be passed.

Can someone tell me what I'm doing wrong?    It must be simple.

Thanks

 
As per Summer release 15, if someone calling this method will be treated as call out, Does it means that it has timeout of 2 minutes ?
What if customer using getContentAsPDF() method to generate the PDF , Did they get any impact (If they are generating large PDF's)?
Hey everyone,

Let me briefly explain the trigger I wrote (my frist trigger actually). On the opportunity, we have a look-up field to other opportunities called 'Renewed Opportunity'. The idea is that when you create an opp that is a renewal, you use that field to reference the previous opportunity that is being renewed.

The trigger looks at the stage of the new renewal opp and updates a field on the referenced 'Renewed Opporunity' called 'Renewal Status'. The goal is to be able to see if an opp ended up renewing or not.

The issue here is that many of our older opportunities don't meet the validation rules we currently have in place. So if you populate that look-up field with an opp with missing data, you'll get an error message preventing you from updating the new, renewal opp you're creating.

Obviously, one solution would be to go back and update all our older opps, but that's practically impossible. So here is my question:

1) Is there something I can write in either the trigger or the validation rules to set up a bypass? For the validation rules, I tried writing in 'NOT(ISCHANGED(Renewal_Status__c))', but it seems that as long as a record is referenced, the validation rules will be required. The trigger doesn't even have to update the record.

2) If option 1 is not possible, is there a way to write an error message in the trigger that at least explains to the user in a clear manner that they have to update the referenced opp? I'd also like to list in the error the validation rules that must be met, but that would be a bonus.

In case you want to take a look at my trigger, here it is:


trigger RenewalProcess on Opportunity (after insert, after update) {
   
   Set<String> allOpps = new Set<String>();
    for(Opportunity renewalOpp : Trigger.new) {
        if (renewalOpp.Renewed_Opportunity__c != null) {
            allOpps.add(renewalOpp.Renewed_Opportunity__c);
         }
    }

    List<Opportunity> potentialOpps = [SELECT Id FROM Opportunity WHERE Id IN :allOpps];

    Map<String,Opportunity> opportunityMap = new Map<String,Opportunity>();
        for (Opportunity o : potentialOpps) {
            opportunityMap.put(o.id,o);
        }
     
     List<Opportunity> oppsToUpdate = new List<Opportunity>();
       
        for (Opportunity renewalOpp : Trigger.new) {
            if (renewalOpp.Renewed_Opportunity__c != null && renewalOpp.StageName.equals('Closed Won')) {
                Opportunity renewedOpp = opportunityMap.get(renewalOpp.Renewed_Opportunity__c);
                renewedOpp.Renewal_Status__c = 'Renewed';
                oppsToUpdate.add(renewedOpp);
            }
            else if(renewalOpp.Renewed_Opportunity__c != null && !renewalOpp.IsClosed) {
                Opportunity renewedOpp = opportunityMap.get(renewalOpp.Renewed_Opportunity__c);
                renewedOpp.Renewal_Status__c = 'In Negotiations';
                oppsToUpdate.add(renewedOpp);
            }
            else if(renewalOpp.Renewed_Opportunity__c != null && (renewalOpp.StageName.equals('Closed Lost') || renewalOpp.StageName.equals('Closed Stalled'))) {
                Opportunity renewedOpp = opportunityMap.get(renewalOpp.Renewed_Opportunity__c);
                renewedOpp.Renewal_Status__c = 'Did Not Renew';
                oppsToUpdate.add(renewedOpp);
            }
           
           
        }
   
    update oppsToUpdate;
   
}



Let me know if you need anymore info from me!
-Greg

Test coverage in my package is failing! It seems to be failing on blank lines, closing brackets, random lines in queries and comments. Causing my code coverage to be half (or less) than what it should be!

 

None of this should be scanned.

 

Anyone else getting this problem?