+ Start a Discussion
Sammy7Sammy7 
Hi, 
 Im getting the following error and cannot figure out why: 

System.EmailException: SendEmail failed. First exception on row 0; first error: INVALID_EMAIL_ADDRESS, Email address is invalid: null: [toAddresses, null]

Class.email_class.send: line 48, column 1
Class.TestquoteEmailclass.sendEmailTestMethod: line 47, column 1

Below is my test class: 
@isTest
public class TestquoteEmailclass {
    @isTest static void sendEmailTestMethod(){
    
        Product2 prod = new Product2(Name = 'SLA: Bronze', IsActive = true);
        insert prod;
        PricebookEntry pbe=new PricebookEntry(unitprice=0.01,Product2Id=prod.Id, Pricebook2Id=Test.getStandardPricebookId(), IsActive= true); 
        insert pbe; 
        Account acc = new Account (name='Acme');
        insert acc;
        Opportunity opp= new Opportunity (name='Testopp', Accountid=acc.id, CloseDate= date.today(), StageName='Closed Won', Pricebook2id=Test.getStandardPricebookId());
        insert opp; 
        OpportunityLineItem oppLine = new OpportunityLineItem( pricebookentryid=pbe.Id,TotalPrice=2000, Quantity = 2,Opportunityid = opp.Id);
        insert oppLine;       
        Quote q= new Quote (Name='Testq', Opportunityid=opp.id, QuotetoInvoice__c= True,  Pricebook2id=Test.getStandardPricebookId());
        insert q;
    
     System.currentPagereference().getParameters().put('id',q.id);
     Attachment objAtt = new Attachment();
     objAtt.Name = 'Test';
     objAtt.body = Blob.valueof('string');
     objAtt.ParentId = q.Id;
     insert objAtt;

         ApexPages.StandardController sc =new ApexPages.StandardController(q); 
        email_class ec=new email_class (sc);
        ec.ToAddresses='test@gmail.com';
         ec.CCAddresses='test2@gmail.com';
        ec.emailCC= 'test3@gmail.com';
        ec.email_body='test1111111';
        ec.subject='test22222';
        
         Messaging.InboundEmail email = new Messaging.InboundEmail();  
         Messaging.InboundEnvelope env = new Messaging.InboundEnvelope();
        email.plainTextBody = 'This should become a note';
        email.fromAddress ='test@test.com';
        String contactEmail = 'jsmith@salesforce.com';
        email.ccAddresses = new String[] {'Jon Smith <' + contactEmail + '>'};
        email.subject = 'Dummy Account Name 123';

        ec.send();

}
}

And my controller:
public class email_class{
        
    Public string ToAddresses {get;set;}
    Public string CCAddresses {get;set;}
    Public string quoteId {get;set;}
    Public string subject {get;set;}
    public string email_body {get;set;}
    public string emailTo {get;set;}
    public string emailCC {get;set;}
     public  string [] ccaddress;   
              
        
        
        public email_class(ApexPages.StandardController controller) {
                quoteId = ApexPages.currentPage().getParameters().get('id');
    }
        
    Public PageReference send(){

                Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); // set the to address
                mail.setToAddresses(new String[] {emailTo}); 
               // mail.setCCAddresses(new String[] {emailCC});   //set the cc address
                   
        if(emailCC != null && emailCC.trim() != '')
        {
        ccaddress = emailCC.split(',',0);
        mail.setCCAddresses(ccaddress);}
                                                              
   
                mail.setSubject(subject);
                mail.setBccSender(false);
                mail.setUseSignature(false);
                mail.setPlainTextBody(email_body);
               

                List<Messaging.Emailfileattachment> fileAttachments = new List<Messaging.Emailfileattachment>();

                for (Attachment a : [select Name, Body, BodyLength from Attachment where ParentId = :quoteId]){  // Add to attachment file list  
                        Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();  
                        efa.setFileName(a.Name); 
                        efa.setBody(a.Body); 
                        fileAttachments.add(efa);
                }
                mail.setFileAttachments(fileAttachments);// Send email
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
                return null;
        }
}

Any help is appreciated !
Best Answer chosen by Sammy7
Sammy7Sammy7
Forgot to pass "emailTo" DOH !
Patrick BulaczPatrick Bulacz 

Hi All,

 

Just wondering if anyone has had any experience with working around the 100000 char limit on Strings in Apex.

 

Basically am producing a large text file that needs to then be attached to a record via notes and attachments.

 

I've got a few workarounds but wondering if there are any other ideas out there.

 

Ideally I'd like to check the length of the string and if it's 'nearing' the limit convert it to a blob and add it to a list of blobs and then run a loop and add all the blobs together to create 1 large file and then attach that via notes and attachments. Obviously that can't be done because you can't just simply add blobs but that's the basic dilemma so if anyone has any suggestions please let me know.

 

My other solutions are to generate the output to a visualforce page then scrape the visualforce page but I get the ugly <Html> and </Html> tags at the beginning and the formatting is a little off (would be good to just be able to 'renderAs=text' but oh well.

 

Anyway any help is much appreciated.

 

Cheers,

 

Patrick

Best Answer chosen by Admin (Salesforce Developers) 
wesnoltewesnolte

Hey

 

What about this:

 

 

Blob myBIGblob;
for(Blob thisB:myBlobs){
// unfortunately can't do the following with binary types like you can
// with strings :(
myBIGblob.valueOf(myBIGblob.toString() + thisB.toString());
}
farah sheriffarah sherif 
the trigger should be on account to check the assets and if ALL Assets where product family = "bla bla "  and their status was "Canceled" the trigger should update bla bla Account stage (API Name = Account_Status__c )  to "Cancel".
Best Answer chosen by farah sherif
Abdul KhatriAbdul Khatri
Can you try the below
 
trigger AccountUpdateFromAssetProduct on Asset (after insert, after update) {
    
    List<Asset> assetList = Trigger.new;

	List<Id> idAccountList = new List<Id>();    
    for(Asset asset : assetList) {
        
        if(Trigger.isUpdate && asset.Product2.Family == Trigger.oldMap.get(asset.Id).Product2.Family && asset.Status == Trigger.oldMap.get(asset.Id).Status) continue;
        
        if(asset.AccountId == null) continue;
        
        idAccountList.add(asset.AccountId);
    }
    
    if(idAccountList.isEmpty()) return;
    
    List<Account> acctList = [SELECT Id, (SELECT Id FROM Assets WHERE Product2.Family = 'bla bla' AND Status = 'Canceled') FROM Account LIMIT 50];
    
    for(Account acct : acctList)
    {
        if(acct.Assets.isEmpty()) continue;
        
        acct.Account_Status__c = 'Cancel';
    }

    update acctList;
}

 
Amit Singh1989Amit Singh1989 

Hi friend,

i have created an visualforce page where i have used <apex:inputFile /> to take any CSV file as input

then i am displaying that CSV file's data into the same vf page in tabular format...

 

but i want that selected CSV's data should be displayed in another vf page. (so by setting attribute renderas="pdf" i can view CSV's data in a PDF format)

 

 

how can i do this?

 

 

here is my code...

 

<apex:page controller="uploadCSVcontroller">
  <apex:form >
  <apex:pageMessages id="pm"/>
  <apex:inputFile value="{!contentFile}" filename="{!nameFile}"/>
  <apex:commandButton value="Display" id="theButton"/>  
  
  
  
  <apex:pageBlock >
  <apex:outputPanel id="results">
  <p>nameFile: {!nameFile}</p>
  <p>rowCount: {!rowCount}</p>
  <p>colCount: {!colCount}</p>
    <table title="CSV Output" border="1" width="100%">
       <apex:repeat value="{!results}" var="row">
           <tr>
               <apex:repeat value="{!row}" var="cell">
                   <td> {!cell} </td>
               </apex:repeat>
           </tr>
       </apex:repeat>
     </table>
  </apex:outputPanel>
  </apex:pageBlock>
  </apex:form>
</apex:page>







Controller


public class uploadCSVcontroller 
  {

    public Blob contentFile { get; set; }
    public String nameFile { get; set; }
    public Integer rowCount { get; set; }
    public Integer colCount { get; set; }
    
    public List<List<String>> getResults() 
    {
        List<List<String>> parsedCSV = new List<List<String>>();
        rowCount = 0;
        colCount = 0;
        if (contentFile != null)
        {
            String fileString = contentFile.toString();
            parsedCSV = parseCSV(fileString, False);
            rowCount = parsedCSV.size();
            for (List<String> row : parsedCSV)
            {
                if (row.size() > colCount)
                {
                    colCount = row.size();
                }
            }
        }
        return parsedCSV;
    }
    
    public Pagereference CreatePDF()
     {
      pagereference pr = new pagereference('/apex/FinalReport1');
      pr.setredirect(true);
      return pr;
     }
    
    public static List<List<String>> parseCSV(String contents,Boolean skipHeaders) 
     {
        List<List<String>> allFields = new List<List<String>>();
        contents = contents.replaceAll(',"""',',"DBLQT').replaceall('""",','DBLQT",');
        contents = contents.replaceAll('""','DBLQT');
        List<String> lines = new List<String>();
        try 
        {
          lines = contents.split('\r'); // using carriage return accomodates windows, unix, and mac files
        }
        catch (System.ListException e) 
        {
            System.debug('Limits exceeded?' + e.getMessage());
        }
        Integer num = 0;
        for(String line: lines) 
        {
           if (line.replaceAll(',','').trim().length() == 0) break;
            List<String> fields = line.split(',');  
            List<String> cleanFields = new List<String>();
            String compositeField;
            Boolean makeCompositeField = false;
            for(String field: fields) 
            {
                if (field.startsWith('"') && field.endsWith('"')) 
                {
                    cleanFields.add(field.replaceAll('DBLQT','"'));
                }
                else if (field.startsWith('"')) 
                {
                    makeCompositeField = true;
                    compositeField = field;
                }
                else if (field.endsWith('"')) 
                {
                    compositeField += ',' + field;
                    cleanFields.add(compositeField.replaceAll('DBLQT','"'));
                    makeCompositeField = false;
                }
                else if (makeCompositeField) 
                {
                    compositeField +=  ',' + field;
                }
                else
                {
                    cleanFields.add(field.replaceAll('DBLQT','"'));
                }
            }
            
            allFields.add(cleanFields);
        }
        if (skipHeaders) allFields.remove(0);
        return allFields;       
     }

}

 

 

 

Thanks,

Amit Singh

Best Answer chosen by Admin (Salesforce Developers) 
abivenkatabivenkat

 

hi amit singh1989,

 

Better read the CSV file and store in the document object in first VF page. give a button as "View and Convert to PDF" in the first VF Page. 

 

When clicking the button, just redirect them to the second VF page and just show the content of the CSV page by querying the file from the Document object and put "RenderAs" attribute in that page itself.

 

What i think is, upload the file and show the content in the first page itself and provide a button as "Convert to PDF". while clicking the button, u just redirect to the second page. in that second page controller class, retrieve the same CSV file and convert to PDF by adding the "RenderAs" attribute in the second page. 

 

Accept as solution if u find this post is useful for you..

 

Thanks,

abivenkat.

 

 

Abhilash Mishra 13Abhilash Mishra 13 
Hi, 
can i get all the values of a picklist field in a list some how?

I have picklist type custom field in the product. having some options.
In my apex class i want to use these options. can I get them some how throught code? 
Best Answer chosen by Abhilash Mishra 13
ManojjenaManojjena
Hi Abhilash,

If you want to display pick list values in your custom page through dyanamic apex .You can check below link it will help  .

https://developer.salesforce.com/blogs/developer-relations/2008/12/using-the-metadata-api-to-retrieve-picklist-values.html

If you want in a string array or list then you can use below code .
 
public List<String> getPickListValuesIntoList(){
       List<String> pickListValuesList= new List<String>();
		Schema.DescribeFieldResult fieldResult = ObjectApiName.FieldApiName.getDescribe();
		List<Schema.PicklistEntry> ple = fieldResult.getPicklistValues();
		for( Schema.PicklistEntry pickListVal : ple){
			pickListValuesList.add(pickListVal.getLabel());
		}     
		return pickListValuesList;
    }
Let us know if it helps !!
Thanks
Manoj
 
Arundhati DebArundhati Deb 
Hi

I have a scenario where the account currency and opportunity currency can be different. The opportunity currency should be the same as opportunity owner currency. I have to write a trigger for it. Can anyone help me with it.
Highly appreciated.
Best Answer chosen by Arundhati Deb
Abdul KhatriAbdul Khatri
@Arundhati

I see some issues with your code so here is your code with some corrections.
 
public static void Opportunitycurrency (List<Opportunity> newOptyList) {
        
        List<Id> oppOwnerIds = new List<Id>();
        for(Opportunity opp: newOptyList)
        {
            if(opp.OwnerId != null)
            {  
                oppOwnerIds.add(opp.OwnerId); 
            }
        }
        
        Map<Id, User> userList = new Map<Id, User>([SELECT Id, Name, CurrencyIsoCode FROM User WHERE Id IN :oppOwnerIds]);
        
        for(Opportunity opp: newOptyList)
        {
            if(opp.type != 'Renewal')
            {
                opp.currencyisocode=userList.get(opp.OwnerId).currencyisocode;
            }
        }
    }

 
nishwalnishwal 

 If @isTest(SeeAllData=false) working for anyone?

I have annotated the class as well as the method but the testmethod can see the existing data.

Here is simple code snippet. Assertion is getting failed for me...

@isTest(SeeAllData=false)
private class testAnnotationSeeAllData {

static testmethod void myUnitTest()
{
Test.startTest();
List<User> lstUsers = [Select Id, Name From User Where IsActive= true Limit 100];
System.assert(lstUsers.size() == 0);
Test.stopTest();
}
}

tried in api version 24 and 25 both. and Developer Org and Sandbox.


is there anyone who is experiencing the same problem?

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

Users aren't considered data for this purpose.  The following doc page:

 

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_testing_data_access.htm

 

details which data will still be visible to your test - user is on that list.

Leticia Monteiro Freitas 4Leticia Monteiro Freitas 4 
Hello, I'm trying to make a Lightning component that makes a search in Account and returns results. But, I get the following error:
My variable input_text gets undefiened, even after user get.component. 
Can anyone help me?


User-added image
My code:
Class:

/*Versão 3.00 - US_179 - Leticia Freitas - 13/11 
Classe que recebe uma string, determina se é um cpf ou um cnpj e a partir dele, realiza a busca dessa conta. 
Caso exista o registro, retorna as informações: Nome, Tipo de Documento (CPF ou CNPJ), Número do documento, Número do Documento Formatado, Logradouro, CEP, Cidade e Estado.
*/

public class CEC_SearchAccount{   
     
    
    
    public static List<Account> getfoundAccount(String Key, String documentType)
    {
       List<Account> Conta  = [Select ID, Name, DocumentType__c,DocumentNumber__c,FormattedDocument__c,BillingAddress from Account 
       where DocumentNumber__c =:Key  AND DocumentType__c =:documentType];

            return Conta;
         
           
        
    }
    
    public static void getvalidCPF(String CPF)
    {
        /* Cálcula se o cpf é valido através do cálculo dos digitos validadores.*/
        integer value; 
        integer coeff = 10, sum, rest;
        String dig10,dig11;
        
        
        //Calcula o primeiro digito validador do CPF
        for(integer i=0; i<9;i++)
        {
            value = Integer.valueOf(CPF.substring(i,1))* coeff;
            coeff--;
            sum =   sum + value ;
        }
        
        rest = 11 - math.mod(sum,11);
        if((rest == 10) || (rest == 11))
        {
            dig10 = '0';
        }else{
            dig10 = String.valueOf(rest);
        }
        
        sum = 0;
        coeff = 11;
        value = 0;
        
        for(integer i=0;i<10;i++)
        {
            value = Integer.valueOf(CPF.substring(i,1))*coeff;
            coeff--;
            sum = sum + value;
            
        }   
        rest = 11 - math.mod(sum,11);
        
        if((rest == 10) || (rest==11))
        {
            dig11 = '0';
        }else{
            dig11=String.valueOf(rest);
        }
        
        // Validate if the calculus match
        if((dig11 == cpf.substring(0,11)) && (dig10 == cpf.substring(0,10)))
        {
           String documentType = 'CPF';
            getfoundAccount(CPF,documentType);
        }else{
         system.debug('CNPJ iNVÁLIDO');
        }
    }
    
    
    
    public static void getvalidCNPJ(String CNPJ)
    {
        integer value;
        integer coeff=12,sum,rest;
        String dig13,dig14;
               
        for(integer i = 0; i < 12;i++)
        {
            value = Integer.valueOf(CNPJ.substring(i,1)) * coeff;
            coeff--;
            sum = sum + value;
        }
        
        rest =Math.mod(sum,11);
        
        if((rest == 0) || (rest == 1))
        {
            dig13 = '0';
        }else{
            dig13 = String.valueOf(11 - rest);
        }
        
        // Calculando o segundo digito verificador do CNPJ
        
        rest=0;
        coeff=13;
        
        for(integer i = 0;i<13;i++)
        {
            value = Integer.valueOf(CNPJ.substring(i,1)) * coeff;
            coeff--;
            sum = sum + value;
        }
        
        rest = math.mod(sum,11);
        
        if((rest == 0) || (rest == 1))
        {
            dig14 = '0';
        }else{
            dig14 = String.valueOf(11 - rest);
        }
        
        if((CNPJ.substring(0,13) == dig13) && (CNPJ.substring(0,14)== dig14))
        {
           String documentType ='CNPJ';
            getfoundAccount(CNPJ, documentType);
        }else{
            //
        }
    }
    
    @AuraEnabled
    Public static void getvalidKey(String text)
    {
        /*Após ler a string de caracteres, o sistema chama a função de cpf ou cnpj conformo o tamanho da string */
        system.debug('Chegou na função da classe agora o/');
        //integer tamanho = text.length();
        system.debug('Tamanho:');
        system.debug('Texto:'+text);
        
        system.debug(text.length());
            
        if(text.length() == 11)
        {
            getvalidCPF(text);
        }else if(text.length() == 14)
        {
            getvalidCNPJ(text);
        }else{
            system.debug('CPF/CNPJ Inválido');
        }
    }
    
 }

Controller:
({
    /* Dentro da ação de clicar no botão, a classe controladora aponta para a função validKey*/
   
    handleClick : function(component, event, helper) {
        var action = component.get("c.getvalidKey"); 
        
        var input_text = component.get("v.searchText");
        console.log("input_text"+ input_text);
        debugger;
        action.setParams({"text":input_text});
        
        action.setCallback(this,function(response)
        {
          var state = response.getState();x
        if(component.isValid() && STATE==Sucess){
            component.set("v.acctList",response.getReturnValue());
        }
        });
        $A.enqueueAction(action);
    }
})

Cmp:
<aura:component controller="CEC_SearchAccount" implements="force:appHostable">
   
    <aura:attribute name="acctList" type="Account[]" />
    <lightning:input name="searchText" label="Insira o CPF ou CNPJ" />
    <lightning:button variant="brand" label="Buscar" onclick="{!c.handleClick}"/>
    
    
    <aura:iteration items="{!v.acctList}" var="a">
        <p>{!a.Name},{!a.Type}</p>
    </aura:iteration>
    
</aura:component>
Best Answer chosen by Leticia Monteiro Freitas 4
Raj VakatiRaj Vakati
Change your componet like below 
 
 <aura:component controller="CEC_SearchAccount" implements="force:appHostable">
   
    <aura:attribute name="acctList" type="Account[]" />
    <lightning:input aura:id="searchText" name="searchText" label="Enter some text" onblur="{! c.handleBlur }"/>
<lightning:button variant="brand" label="Buscar" onclick="{!c.handleClick}"/>
    
    
    <aura:iteration items="{!v.acctList}" var="a">
        <p>{!a.Name},{!a.Type}</p>
    </aura:iteration>
    
</aura:component>
 
Controller:
({
    /* Dentro da ação de clicar no botão, a classe controladora aponta para a função validKey*/
   
    handleClick : function(component, event, helper) {
        var action = component.get("c.getvalidKey"); 
        

var input_text = component.find("searchText").get("v.value"); 
       
        console.log("input_text"+ input_text);
        debugger;
        action.setParams({"text":input_text});
        
        action.setCallback(this,function(response)
        {
          var state = response.getState();x
        if(component.isValid() && STATE==Sucess){
            component.set("v.acctList",response.getReturnValue());
        }
        });
        $A.enqueueAction(action);
    }
})

 
Matthew HofmannMatthew Hofmann 
Hello,

I'm creating an Apex class that creates a Salesforce File record and associates it with a parent record. I'm having a problem creating the association (ContentDocumentLink) record.

Here is what I'm doing:
  • Create a ContentVersion record. This creates a ContentDocument record automatically if you leave the ContentVersion.ContentDocumentId field blank. (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentdocument.htm - "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record.")
  • Insert ContentVersion record
  • DEBUG: Confirm ContentVersion.ContentDocumentId is set (Here is where the problem is because it is NULL; however if I SOQL query ContentVersion after the Apex completes, ContentVersion.ContentDocumentId is set and the corresponding ContentDocument record exists)
  • Create ContentDocumentLink record (commented out because it fails because ContentDocumentLink.ContentDocumentId is a required field)
  • Insert ContentDocumentLink record (commented out because it fails because ContentDocumentLink.ContentDocumentId is a required field)
Here is the code:
public class FileController {
    
    @AuraEnabled
    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType, Id contentDocumentId) { 
        base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');
        
        ContentVersion cv = new ContentVersion();
        cv.ContentLocation = 'S';
        cv.ContentDocumentId = contentDocumentId;
        cv.VersionData = EncodingUtil.base64Decode(base64Data);
        cv.Title = fileName;
        cv.PathOnClient = filename;
        
        insert cv;
        
        //***This DEBUG statement must return an Id for the rest of the code to work***
        System.debug('contentDocumentId='+cv.ContentDocumentId);               
        
        //ContentDocumentLink cdl = new ContentDocumentLink();
        //cdl.ContentDocumentId = cv.ContentDocumentId;
        //cdl.LinkedEntityId = parentId;
        //cdl.ShareType = 'I';
        
        //insert cdl;
        
        return cv.Id;
    }

    @AuraEnabled
    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType) {         
        return saveTheFile(parentId, fileName, base64Data, contentType, NULL);
    }
}

Does anyone know what I'm doing wrong, not considering, etc?
Appreciate any thoughts and input!
Best Answer chosen by Matthew Hofmann
VineetKumarVineetKumar
Interesting..

Well the culprit in your code is the null value and way you are using it to assign the value to ContentDocumentLink.contentDocumentId.
You should query the content version object again to get the contentDocumentId (which is generated after the parent document is inserted by default because of you passing of null value).
Something like below :
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id =: cv.Id].ContentDocumentId;
cdl.LinkedEntityId = '00590000000a6dP';
cdl.ShareType = 'V';
insert cdl;

As per the salesforce documentation lines higlighted by you, "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record." it does create the parent document record as expected, but the contentDocumentId is still null in above initialised object. Id doesn't get updated automatically to the object instance. Infact you will have to pull out the corresponding Id as done in the above snippet.

Let me know if this helps.
David Roberts 4David Roberts 4 
The "Search in Files" feature is particularly irritating because it doesn't search components.
Also, the debug logs won't show the last few lines without jumping back up the list.
The "Search"  box overlays the horizontal scroll bar.
Best Answer chosen by David Roberts 4
RovRov
Either post it as an Idea on Idea Exchange 
https://success.salesforce.com/ideasearch
or
Give feedback about Salesforce.
After you login to your org, click the '?' icon. The Saleforce help menu that opens has a link at the bottom that says 'Give feedback about salesforce'