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
nicksquashnicksquash 

separate shipping address lines

Hi

Is it possible to write a formula that essentially breaks the shipping address down into the individual lines?

We have an external system that needs to receive the address fields for a child object to an Account in three separate fields.

I figure if I can identify a new line character, then this should be pretty straight forward, but I can't figure out how to do this.
Any ideas?

thanks
Nick
Best Answer chosen by Admin (Salesforce Developers) 
LBJLBJ

newContacts is a List from a trigger and this is parsing the MailingStreet

but hopefully it will serve as a suitable solution. I would think that it

would work the same for the shippingAddress and the billingAddress.

 

String address1;

String address2; 

String[] myStrings = new String[2];

myStrings = newContacts[i].MailingStreet.split('\n');

if (!(myStrings[0] == '')){ 

address1 = myStrings[0];

}

if (!(myStrings[1] == '')){ 

address2 = myStrings[1];

}

All Answers

Gemini@WorkGemini@Work

I'm not sure what you mean.  Inside SFDC, the address field is really seperate fields:

  • Account.ShippingStreet
  • Account.ShippingCity
  • Account.ShippingState
  • Account.ShippingPostalCode
  • Account.ShippingCountry
What is it that you want to "break down" into individual lines?
nicksquashnicksquash
Hi

thanks for the response.

I'm trying to break the shipping street into individual lines.
At the moment it appears to be a text area with multiple lines.

The other items are all fields unto themselves, so they should be fine.

thanks
JPSeaburyJPSeabury
Hmmm.
 
Well, it's interesting that if you create a report (on Account, Lead, Contact -- anything with an address), the report wizard not only has options for "Shipping Street", but also includes "Shipping Address Line 1", "Shipping Address Line 2", "Shipping Address Line 3".
 
So at the very least, one method would be to manually export the data to an Excel worksheet using these "Shipping Address Line X" fields rather than the "Shipping Street" field.  Same is true of Billing Address:
 
 
Unfortunately, I don't see away to get at these fields via the API.  You'd have to write some javascript (or your coding language of choice) to mangle the ShippingAddress field, keying off the embedded line return as a method for splitting the field into 3 address line fields.
nicksquashnicksquash
Thanks for the response.

I might have to just add in some commas as delimeters to the shipping street lines.
Should be able to easily split them up this way.

Was just hoping there might be a more standard way of doing this, or a way to detect a new line character.


RedtagRedtag
Hi Nick,

Did you ever solve this issue? When I access the Shipping Address field via the API to send the shipping address to an external file the lines are joined without spaces. Ideally I'd like to split the shipping address into 3 fields using the line break character to do the split. I thought I could use a RegExp to do this but none of the usual line break characters seem to work - eg. \n

Steve
RedtagRedtag
I meant to say I'd like to separate ShippingStreet into three separate fields...
nicksquashnicksquash
Hi Redtag

Unfortunately we never found a way around this.

We have an external system that accesses this field and the string comes through with some form of line break in it that our coders have managed to use to separate the address lines.
Not sure of the exact details, but I think there is either a <br> or some form of line break character that is used.


Nick
pbergmanpbergman

I'm having similar problems accessing the lines in StreetAddress in Pages. The problem is that APEX:outputField will preserve line breaks but doesn't maintain font settings.  APEX:outputText will do respect font settings but not line breaks.

 

Since City, State, Zip, & Country are accessabl, it would be nice if the Address1, Address2, Address3 were as well.

MirosMiros

Hello,

 

When you enter an address in the "Address" field, if the user clicks enter to add a new row, SFDC saves the info in those 3 split address lines.

 

So if you type in the address field:

 

Street address (click enter)

Floor (Click enter)

Apt (Click enter)

  

This is what you will see in those extra fields:

 

Address Line 1: Street Address

Address Line 2: Floor

Address Line 3: Apt

 

LBJLBJ

newContacts is a List from a trigger and this is parsing the MailingStreet

but hopefully it will serve as a suitable solution. I would think that it

would work the same for the shippingAddress and the billingAddress.

 

String address1;

String address2; 

String[] myStrings = new String[2];

myStrings = newContacts[i].MailingStreet.split('\n');

if (!(myStrings[0] == '')){ 

address1 = myStrings[0];

}

if (!(myStrings[1] == '')){ 

address2 = myStrings[1];

}

This was selected as the best answer
plbrownplbrown

Can you send me the complete code for your trigger for splitting the billing street to address1 and 2?

 

 

MIKE_DAYMIKE_DAY

I'm a bit late to the party but have also had issues with this topic and integrating with an external system. My workaround (without triggers) builds on a response previously posted, prompting users to enter commas in the Street field after every line and also at the end. Following that, it is then just a case of splitting the Street address using formula fields:

 

Step 1 : Create a number of new text formula fields on your chosen object (I named them Address line 1 Address line 2 and Chk Commas)



Formula Field 1 (Address line 1) // Get the first line of the street address

LEFT(BillingStreet, FIND(",",BillingStreet)-1))



Formula Field 2 (Address line 2) // Get the second line of the street address

Mid(TRIM(BillingStreet), FIND(",",TRIM(BillingStreet))+2, FIND(",",TRIM(BillingStreet),FIND(",",TRIM(BillingStreet))+2) - FIND(",",TRIM(BillingStreet)) -2)



Formula field 3 (Chk Commas) // Check if commas are present (Used later in validation **)

IF(CONTAINS(LEFT(BillingStreet,LEN(BillingStreet)-1), ","),1, IF (ISBLANK(Address_line_2__c),1,0))



** You may be able to build the check commas formula into your validation rule.

 



Step 2: Create a validation rule on the Street Field of the object as follows:

AND( CHK_COMMAS__c = 0, RIGHT(TRIM(BillingStreet),1) <> "," ) )

Enter some text in the error message area:

Please ensure that the 'Billing Street' address lines are all separated by a " , " and also that the Billing Street ends with a " ,".

 

 

Following this I was then able to export single address lines to a CSV file and import to any application with strict Address 1, Address 2, City, State, Zip parameters.  You could also add further address lines and validation building on Formula 2 in the example.

 

 

Other methods tested to achieve the same output involved the use of batch files and MS Excel Macros which effectively split the Street Address up using a splt to columns command and a carriage return (CTRL + J) delimiter.

Hope this helps?

 

I don't know. I just work hereI don't know. I just work here

 Have fun

 

trigger OL_OpportunityAddresses on Opportunity (after insert, after update) {

 

    /*

     * Written By Stanley Tso 20130528

     *

     * 2 fields for breaking each of the two the Street Address: ShipTo_Street__c and Bill_Street__c

     * QB_BillingAddress1__c TEXT(41)

     * QB_BillingAddress2__c TEXT(41)

     * QB_ShippingAddress1__c TEXT(41)

     * QB_ShippingAddress2__c TEXT(41)

     *

    */

    public class AddressPrepException extends Exception {}

   

    List<Opportunity> opportunityList = new List<Opportunity>();

    String AddressLine1 = '';

    String AddressLine2 = '';

    Boolean FirstAddressLineIsUsed = false;

    Boolean UpdateNeededOnBillingAddress = false;

    Boolean UpdateNeededOnShippingAddress = false;

   

    for(Opportunity o : Trigger.new){

        Opportunity u_opp = [SELECT QB_BillingAddress1__c, QB_BillingAddress2__c, QB_ShippingAddress1__c, QB_ShippingAddress2__c FROM Opportunity WHERE Id =: o.Id ];

        Opportunity oldo = Trigger.oldMap.get(o.ID);

        if (Trigger.isInsert) {

            UpdateNeededOnBillingAddress = o.Bill_Street__c != null;

            UpdateNeededOnShippingAddress = o.ShipTo_Street__c != null;

        } else { // isUpdate

            UpdateNeededOnBillingAddress = o.Bill_Street__c != oldo.Bill_Street__c || o.Bill_Street__c != null && o.QB_BillingAddress1__c == null;

            UpdateNeededOnShippingAddress = o.ShipTo_Street__c != oldo.ShipTo_Street__c || o.ShipTo_Street__c != null && o.QB_ShippingAddress1__c == null;

        }

       

        if (UpdateNeededOnBillingAddress) {

            // initiate temp variables

            AddressLine1 = '';

            AddressLine2 = '';

            FirstAddressLineIsUsed = false;

            String[] bAddrList = o.Bill_Street__c.split('\n');

            for (Integer i = 0; i < bAddrList.size(); i++) {

                if (i == 0) { // first item work first

                    if (bAddrList[0].length() > 41) {

                        AddressLine1 = bAddrList[0].substring(0,41);

                        AddressLine2 = bAddrList[0].substring(bAddrList[0].length() - 41);

                        FirstAddressLineIsUsed = true;

                    } else {

                        AddressLine1 = bAddrList[0];

                    }

                }

                // work with the next item on the list:

                if (i + 1 < bAddrList.size()) {

                    if ((AddressLine2 + (AddressLine2.length()>0?', ':'') + bAddrList[i+1]).length() < 41) { // we use two characters for the concatination deliminator

                        AddressLine2 = AddressLine2 + (AddressLine2.length()>0?', ':'') + bAddrList[i+1];

                    } else {

                        throw new AddressPrepException('Billing Address second line is over character limit.\n['+AddressLine2 + ', ' + bAddrList[i+1]+']\n# of Characters: ' + String.valueOf((AddressLine2 + ', ' + bAddrList[i+1]).length()));

                    }

                }

            }

            u_opp.QB_BillingAddress1__c = AddressLine1;

            u_opp.QB_BillingAddress2__c = AddressLine2;

        }

        // test code

        /*

        else {

            u_opp.QB_BillingAddress1__c = 'no need update';

            u_opp.QB_BillingAddress2__c = '';

        }*/

       

        if (UpdateNeededOnShippingAddress ) {

            // initiate temp variables

            AddressLine1 = '';

            AddressLine2 = '';

            FirstAddressLineIsUsed = false;

            String[] sAddrList = o.ShipTo_Street__c.split('\n');

            for (Integer i = 0; i < sAddrList.size(); i++) {

                if (i == 0) { // first item work first

                    if (sAddrList[0].length() > 41) {

                        AddressLine1 = sAddrList[0].substring(0,41);

                        AddressLine2 = sAddrList[0].substring(sAddrList[0].length() - 41);

                        FirstAddressLineIsUsed = true;

                    } else {

                        AddressLine1 = sAddrList[0];

                    }

                }

                // work with the next item on the list:

                if (i + 1 < sAddrList.size()) {

                    if ((AddressLine2 + (AddressLine2.length()>0?', ':'') + sAddrList[i+1]).length() < 41) { // we use two characters for the concatination deliminator

                        AddressLine2 = AddressLine2 + (AddressLine2.length()>0?', ':'') + sAddrList[i+1];

                    } else {

                        throw new AddressPrepException('Billing Address second line is over character limit.\n['+AddressLine2 + ', ' + sAddrList[i+1]+']\n# of Characters: ' + String.valueOf((AddressLine2 + ', ' + sAddrList[i+1]).length()));

                    }

                }

            }

            u_opp.QB_ShippingAddress1__c = AddressLine1;

            u_opp.QB_ShippingAddress2__c = AddressLine2;

        }

        // test code

        /*

        else {

            u_opp.QB_ShippingAddress1__c = 'no need update';

            u_opp.QB_ShippingAddress2__c = '';

        }*/

       

        if (UpdateNeededOnBillingAddress || UpdateNeededOnShippingAddress ) {

            opportunityList.add(u_opp);

        }

    }

 

    update opportunityList;

}

I don't know. I just work hereI don't know. I just work here

Fixed Version

 

code

--------------------

public class OL_AddressPrepException extends Exception {}

 

trigger OL_OpportunityAddresses on Opportunity (after insert, after update) {

 

    /*

     * Written By Stanley Tso 20130528

     *

     * 2 fields for breaking each of the two the Street Address: ShipTo_Street__c and Bill_Street__c

     * QB_BillingAddress1__c TEXT(41)

     * QB_BillingAddress2__c TEXT(41)

     * QB_ShippingAddress1__c TEXT(41)

     * QB_ShippingAddress2__c TEXT(41)

     *

    */

//    public class AddressPrepException extends Exception {} // replaced with OL_AddressPrepException

   

    List<Opportunity> opportunityList = new List<Opportunity>();

    String AddressLine1 = '';

    String AddressLine2 = '';

    Boolean FirstAddressLineIsUsed = false;

    Boolean UpdateNeededOnBillingAddress = false;

    Boolean UpdateNeededOnShippingAddress = false;

   

    for(Opportunity o : Trigger.new){

        Opportunity u_opp = [SELECT QB_BillingAddress1__c, QB_BillingAddress2__c, QB_ShippingAddress1__c, QB_ShippingAddress2__c FROM Opportunity WHERE Id =: o.Id ];

        if (Trigger.isInsert) {

            UpdateNeededOnBillingAddress = o.Bill_Street__c != null;

            UpdateNeededOnShippingAddress = o.ShipTo_Street__c != null;

        } else { // isUpdate

            Opportunity oldo = Trigger.oldMap.get(o.ID);

            UpdateNeededOnBillingAddress = o.Bill_Street__c != oldo.Bill_Street__c || o.Bill_Street__c != null && o.QB_BillingAddress1__c == null;

            UpdateNeededOnShippingAddress = o.ShipTo_Street__c != oldo.ShipTo_Street__c || o.ShipTo_Street__c != null && o.QB_ShippingAddress1__c == null;

        }

       

        if (UpdateNeededOnBillingAddress) {

            // initiate temp variables

            AddressLine1 = '';

            AddressLine2 = '';

            FirstAddressLineIsUsed = false;

            String[] bAddrList = o.Bill_Street__c.split('\n');

            for (Integer i = 0; i < bAddrList.size(); i++) {

                if (i == 0) { // first item work first

                    if (bAddrList[0].length() > 41) {

                        AddressLine1 = bAddrList[0].substring(0,41);

                        AddressLine2 = bAddrList[0].substring(41);

                        FirstAddressLineIsUsed = true;

                    } else {

                        AddressLine1 = bAddrList[0];

                    }

                }

                // work with the next item on the list:

                if (i + 1 < bAddrList.size()) {

                    if ((AddressLine2 + (AddressLine2.length()>0?', ':'') + bAddrList[i+1]).length() < 41) { // we use two characters for the concatination deliminator

                        AddressLine2 = AddressLine2 + (AddressLine2.length()>0?', ':'') + bAddrList[i+1];

                    } else {

                        // have to comment out this line due to code coverage not supporting good exception handling.

                        //throw new OL_AddressPrepException('Billing Address second line is over character limit.\n['+AddressLine2 + ', ' + bAddrList[i+1]+']\n# of Characters: ' + String.valueOf((AddressLine2 + ', ' + bAddrList[i+1]).length()));

                    }

                }

            }

            u_opp.QB_BillingAddress1__c = AddressLine1;

            u_opp.QB_BillingAddress2__c = AddressLine2;

        }

        // test code

        /*

        else {

            u_opp.QB_BillingAddress1__c = 'no need update';

            u_opp.QB_BillingAddress2__c = '';

        }*/

       

        if (UpdateNeededOnShippingAddress ) {

            // initiate temp variables

            AddressLine1 = '';

            AddressLine2 = '';

            FirstAddressLineIsUsed = false;

            String[] sAddrList = o.ShipTo_Street__c.split('\n');

            for (Integer i = 0; i < sAddrList.size(); i++) {

                if (i == 0) { // first item work first

                    if (sAddrList[0].length() > 41) {

                        AddressLine1 = sAddrList[0].substring(0,41);

                        AddressLine2 = sAddrList[0].substring(41);

                        FirstAddressLineIsUsed = true;

                    } else {

                        AddressLine1 = sAddrList[0];

                    }

                }

                // work with the next item on the list:

                if (i + 1 < sAddrList.size()) {

                    if ((AddressLine2 + (AddressLine2.length()>0?', ':'') + sAddrList[i+1]).length() < 41) { // we use two characters for the concatination deliminator

                        AddressLine2 = AddressLine2 + (AddressLine2.length()>0?', ':'') + sAddrList[i+1];

                    } else {

                        // have to comment out this line due to code coverage not supporting good exception handling.

                        //throw new OL_AddressPrepException('Shipping Address second line is over character limit.\n['+AddressLine2 + ', ' + sAddrList[i+1]+']\n# of Characters: ' + String.valueOf((AddressLine2 + ', ' + sAddrList[i+1]).length()));

                    }

                }

            }

            u_opp.QB_ShippingAddress1__c = AddressLine1;

            u_opp.QB_ShippingAddress2__c = AddressLine2;

        }

        // test code

        /*

        else {

            u_opp.QB_ShippingAddress1__c = 'no need update';

            u_opp.QB_ShippingAddress2__c = '';

        }*/

       

        if (UpdateNeededOnBillingAddress || UpdateNeededOnShippingAddress ) {

            opportunityList.add(u_opp);

        }

    }

 

    update opportunityList;

}

 

--------------------

 

test class

--------------------

@isTest

public class OL_QBAddress_Class_UT {

 

    static testMethod void validateQBAddressCreation() {

   

        AutoNo__c a= new AutoNo__c();

        a.Category__c='Account Number';

        a.Iterator__c =0;

        insert a;

        AutoNo__c a2= new AutoNo__c();

        a2.Category__c='Opportunity Number';

        a2.Iterator__c =0;

        insert a2;

       

        Account acc1= new Account();

        acc1.Name='Test_Account';

        acc1.CurrencyIsoCode='CAD';

        acc1.AccountNumber = '';

        insert acc1;

       

        System.debug('Account: [' + acc1.AccountNumber+ '] has inserted into system.');

 

       

        Opportunity o = new Opportunity(Name='test opp', StageName = 'Pre Bid', AccountId = acc1.Id);

        o.CloseDate = Datetime.now().Date();

        o.DB_CustomerPO__c = 'S001923';

        o.ShipTo_State_Province__c = 'BC';

        o.ShipTo_Street__c = 'test long ass string first more than 41 character';

        o.Bill_Street__c = 'test long ass string first more than 41 character2';

        insert o;

       

       

        o = [SELECT ShipTo_Street__c, Bill_Street__c, QB_BillingAddress1__c, QB_BillingAddress2__c, QB_ShippingAddress1__c, QB_ShippingAddress2__c FROM Opportunity WHERE Id =: o.Id LIMIT 1];

       

        System.assertEquals(o.QB_BillingAddress1__c, 'test long ass string first more than 41 c');

        System.assertEquals(o.QB_BillingAddress1__c, o.QB_ShippingAddress1__c); // both line should be the same because of our test string

       

        o.ShipTo_Street__c = 'test with two\nline address this\nis shipping address';

        o.Bill_Street__c = 'test with two\nline address this\nis billing address';

        update o;

       

        AutoNo__c autoNoObj1 = [select id,NextNo__c from AutoNo__c where Category__c = 'Account Number'];

        AutoNo__c autoNoObj2 = [select id,NextNo__c from AutoNo__c where Category__c = 'Opportunity Number'];

       

        o.ShipTo_Street__c = 'test with two\nline address this\nis shipping address on when second line is overshot the length.';

        o.Bill_Street__c = 'test with two\nline address this\nis billing address on when second line is overshot the length.';

       

        update o;

        /* can't use this for custom exception handling.

        try{

            update o;

            System.assertEquals('Overshot Address is not complaint', '');

        } catch ( OL_AddressPrepException e) {

            // ok to go next

        }

        */

       

        delete o;

    }

 

}

 

--------------------