• tengel
  • NEWBIE
  • 10 Points
  • Member since 2011

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 28
    Questions
  • 29
    Replies
I have a VF email template that should get delivered with a .ical attachment. When the email gets delivered, the .ical's first line appears to be a line break. This prevents it from validating correctly at this validator (http://severinghaus.org/projects/icv/), and it also causes issues when trying to open with Outlook, for example. When I edit the attachment and remove the first line break, it validates and opens fine in Outlook.

I don't see where in the VF itself the line break is getting introduced. Can anyone offer some help? For context, when the rendered file gets delivered via email, there is a blank line right before "BEGIN:VCALENDAR" which is causing the issue.
</body>
</messaging:htmlEmailBody>
<messaging:attachment filename="{!RelatedTo.evt__Event__r.Name}.ics" renderAs="text/calendar; charset=UTF-8; method=PUBLISH">
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN
VERSION:2.0
METHOD:PUBLISH
X-WR-TIMEZONE:America/New_York
BEGIN:VEVENT
DTSTAMP:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(NOW()),':',''),'-',''),' ','T')}"/>
UID:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__Start__c),':',''),'-',''),' ','T')}"/>
ATTENDEE;CN={!RelatedTo.evt__Email__c}
STATUS:CONFIRMED
DTSTART;TZID=America/New_York:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__Start__c),':',''),'-',''),' ','T')}"/>
DTEND;TZID=America/New_York:<apex:outputText value="{!SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TEXT(RelatedTo.evt__Event__r.evt__End__c),':',''),'-',''),' ','T')}"/>
LOCATION:{!RelatedTo.evt__Event__r.evt__Venue_Name__c} - {!RelatedTo.evt__Event__r.evt__Street__c}, {!RelatedTo.evt__Event__r.evt__City__c} {!RelatedTo.evt__Event__r.evt__State__c} {!RelatedTo.evt__Event__r.evt__Postal_Code__c}
ORGANIZER;CN="Lawley Insurance":mailto:lawley@lawleyinsurance.com
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=en-us:{!RelatedTo.evt__Event__r.Name}
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
</messaging:attachment>

</messaging:emailTemplate>

 
I have a custom object that has Start and End fields as datetime. I am trying to create a Visualforce email template that will be able to send an email with a .ics attachment that will use my object's Start/End fields.

I've got everything working except that my object's field values are getting output as GMT, not UTC, and the .ics format needs UTC. Here's what I've got in the template (PS, I've tried not wrapping my fields in the outputText tags, the result is the same):
DTSTART;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__Start__c}" />
DTEND;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__End__c}" />
Here is an example of what gets output in the resulting .ics file:
DTSTART;TZID="Eastern Standard Time":Mon Jul 06 17:00:00 GMT 2015
DTEND;TZID="Eastern Standard Time":Mon Jul 06 21:00:00 GMT 2015
How do I just get VF to output my fields in UTC? Isn't this how they are actually stored in the database, anyway??

  • August 27, 2014
  • Like
  • 1
I have what appears to be a pretty simply requirement but I am really struggling with this one...

I have a custom object and am overriding the standard Edit page with a Visualforce page. This object has custom checkbox field, Finalized__c.

I'm looking to do either one of these two things, and the preferable method would be avoid an apex controller, if possible:
  • IF Finalized__c = TRUE, make the whole page readOnly;
  • IF Finalized__c = TRUE, make field A__c, B__c, and C__c read only.
Any ideas? Greatly appreciated.
  • August 09, 2014
  • Like
  • 0
Hi! I would like to present my users with a custom VF page for entering/editing records. The page will have a number of tables and the cells of these tables will have a mix of hardcoded values and input options. I thought I was on the right track, but when I try to put an apex:inputField in one of the <td> tags, the HTML breaks and my table gets all messed up.

VF code:
<table border="1" style="width:800px">
                        <tbody><tr>
                            <th>EXCLUDE DBL AND BENEFITS</th>
                            <th>SAMPLE</th>
                            <th>YOURS</th> 
                            <th>KEY</th>
                        </tr>
                        <tr>
                            <td>Gross Commission Pr1</td>
                            <td>300000</td>
                            <td></td><td class="dataCol  first " colspan="2"><input id="j_id0:j_id2:j_id3:section1:j_id13" name="j_id0:j_id2:j_id3:section1:j_id13" size="20" style="width:100px" type="text"></td></tr><tr><td class="dataCol  last " colspan="2"></td>
                            <td>Book of Business minus DBL and Benefits</td>
                        </tr>
                    </tbody></table>
Image of broken table:
User-added image
I am modifying this awesome code package from Michael Farrington (http://www.michaelforce.org/recipeView?id=a0G30000006eVxVEAU) to build a VF page that will allow a user to add multiple competitors to an Opportunity at one time. It is SO CLOSE to working, but I have this one final hurdle to cross...

I am using a junction object to attach competitors to Opportunities. My list of options is stored in the Competitor_Option__c object, and then my Competitor__c object has a master-detail to Opportunity, and a lookup to Competitor_Option__c.

The VF page has two sections: Selected Competitors and Available Competitors. Everything is working great EXCEPT that my list of Available Competitors is not returning any results when the page is first loaded. If I hit backspace while in the page's search field, my Competitor_Options__c load. If I Remove a previously added option, the options load. Can anyone help me find what in my code is preventing any options from loading when the page first loads?

User-added image

VF page:
<apex:page standardController="Opportunity" extensions="opportunityProductEntryExtension" >
    <apex:sectionHeader Title="Manage Competitors" subtitle="{!opportunity.Name}"/>
    <apex:messages style="color:red"/>
  
    <style>
        .search{
            font-size:14pt;
            margin-right: 20px;  
        }
        .fyi{
            color:red;
            font-style:italic;
        }
        .label{
            margin-right:10px;
            font-weight:bold;
        }
    </style>
  
    <script type='text/javascript'>
        // This script assists the search bar functionality
        // It will execute a search only after the user has stopped typing for more than 1 second
        // To raise the time between when the user stops typing and the search, edit the following variable:
        var waitTime = 0;
        var countDown = waitTime+1;
        var started = false;
        function resetTimer(){
            countDown=waitTime+1;
            if(started==false){
                started=true;
                runCountDown();
            }
        }
        function runCountDown(){
            countDown--;
            if(countDown<=0){
                fetchResults();
                started=false;
            }
            else{
                window.setTimeout(runCountDown,1000);
            }
        }
    </script>
  
    <apex:form id="form">
        <apex:outputPanel id="mainBody">
<!-- this is the upper table... a.k.a. the "Shopping Cart"-->
            <apex:pageBlock title="Selected Competitors" id="selected">
                <apex:pageblockTable value="{!shoppingCart}" var="s">
                    <apex:column >
                        <apex:commandLink value="Remove" action="{!removeFromShoppingCart}" reRender="selected,searchResults" immediate="true">
                            <!-- this param is how we send an argument to the controller, so it knows which row we clicked 'remove' on -->
                            <apex:param value="{!s.Competitor__c}" assignTo="{!toUnselect}" name="toUnselect"/>
                        </apex:commandLink>
                    </apex:column>
                    <apex:column headerValue="Competitor" value="{!s.Competitor__c}"/>
                    <apex:column headerValue="Incumbent">
                        <apex:inputField value="{!s.Incumbent__c}" />
                    </apex:column>
                    <apex:column headerValue="Winner">
                        <apex:inputField value="{!s.Winner__c}" />
                    </apex:column>
                    <apex:column headerValue="Strengths">
                        <apex:inputField value="{!s.Strengths__c}" style="width:200px; height:100px" required="false"/>
                    </apex:column>
                    <apex:column headerValue="Weaknesses">
                        <apex:inputField value="{!s.Weaknesses__c}" style="width:200px; height:100px" required="false"/>
                    </apex:column>
                    <apex:column headerValue="Competing Producer">
                        <apex:inputField value="{!s.Producer__c}" required="false"/>
                    </apex:column>
                </apex:pageblockTable>
                <apex:pageBlockButtons >
                    <apex:commandButton action="{!onSave}" value="Save"/>
                    <apex:commandButton action="{!onCancel}" value="Cancel" immediate="true"/>
                </apex:pageBlockButtons>
            </apex:pageBlock>
<!-- this is the lower table: search bar and search results -->
            <apex:pageBlock id="block">
                <apex:outputPanel styleClass="search">
                    Search for Competitors:
                </apex:outputPanel>
                <apex:actionRegion renderRegionOnly="false" immediate="true" id="region">
                    <apex:actionFunction name="fetchResults" action="{!updateAvailableList}" reRender="searchResults" status="searchStatus" id="function" />
                    <!-- here we invoke the scripting to get out fancy 'no button' search bar to work -->
                    <apex:inputText value="{!searchString}" onkeydown="if(event.keyCode==13){this.blur();}else{resetTimer();}" style="width:300px" id="search" />
                    &nbsp;&nbsp;
                    <i>
                        <!-- actionStatus component makes it easy to let the user know when a search is underway -->
                        <apex:actionStatus id="searchStatus" startText="searching..." stopText=" "/>
                    </i>
                </apex:actionRegion>
                <br/>
                <br/>
                <apex:outputPanel id="searchResults">
                    <apex:pageBlockTable value="{!AvailableProducts}" var="a">
                        <apex:column width="100px;">
                            <!-- command button in a column... neato -->
                            <apex:commandButton value="Select" action="{!addToShoppingCart}" reRender="selected,searchResults" immediate="true">
                                <!-- again we use apex:param to be able to tell the controller which row we are working with -->
                                <apex:param value="{!a.Id}" assignTo="{!toSelect}" name="toSelect"/>
                            </apex:commandButton>
                        </apex:column>
                        <apex:column headerValue="Competitor" value="{!a.Name}" width="300px;" />
                        <apex:column headerValue="Type" value="{!a.Competitor_Type__c}" />
                    </apex:pageBlockTable>
                    <!-- We put up a warning if results exceed 100 rows -->
                    <apex:outputPanel styleClass="fyi" rendered="{!overLimit}">
                        <br/>
                        Your search returned over 100 results, use a more specific search string if you do not see the desired Competitor.
                        <br/>
                    </apex:outputPanel>
                </apex:outputPanel>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>





Apex extension:
public with sharing class opportunityProductEntryExtension {

    public Opportunity theOpp {get;set;}
    public String searchString {get;set;}
    public Competitor__c[] shoppingCart {get;set;}
    public Competitor_Option__c[] AvailableProducts {get;set;}
  
    public String toSelect {get; set;}
    public String toUnselect {get; set;}
    public Decimal Total {get;set;}
  
    public Boolean overLimit {get;set;}
  
    private Competitor__c[] forDeletion = new Competitor__c[]{};

    public opportunityProductEntryExtension(ApexPages.StandardController controller) {

        theOpp = [select Id from Opportunity where Id = :controller.getRecord().Id limit 1];
      
        // If products were previously selected need to put them in the "selected products" section to start with
        shoppingCart = [select Id, Name, Incumbent__c, Winner__c, Strengths__c, Weaknesses__c, Producer__c, Competitor__c from Competitor__c where Opportunity__c=:theOpp.Id order by Id Asc];

    }

    public void updateAvailableList() {
  
        // We dynamically build a query string and exclude items already in the shopping cart
        String qString = 'select Id, Name, Competitor_Type__c from Competitor_Option__c where Active__c=true';
      
        // note that we are looking for the search string entered by the user in the name OR description
        // modify this to search other fields if desired
      
        if(searchString!=null){
            qString+= ' and (Name like \'%' + searchString + '%\')';
        }
      
        Set<Id> selectedEntries = new Set<Id>();
        for(Competitor__c d:shoppingCart){
            selectedEntries.add(d.Competitor__c);
        }
      
        if(selectedEntries.size()>0){
            String tempFilter = ' and Id not in (';
            for(Id i : selectedEntries){
                tempFilter+= '\'' + (String)i + '\',';
            }
            String extraFilter = tempFilter.substring(0,tempFilter.length()-1);
            extraFilter+= ')';
          
            qString+= extraFilter;
        }
      
        qString+= ' order by Name';
        qString+= ' limit 101';
      
        system.debug('qString:' +qString);      
        AvailableProducts = database.query(qString);
      
        // We only display up to 100 results... if there are more than we let the user know (see vf page)
        if(AvailableProducts.size()==101){
            AvailableProducts.remove(100);
            overLimit = true;
        }
        else{
            overLimit=false;
        }
    }
  
    public void addToShoppingCart(){
  
        // This function runs when a user hits "select" button next to a product
  
        for(Competitor_Option__c d : AvailableProducts){
            if((String)d.Id==toSelect){
                shoppingCart.add(new Competitor__c(Opportunity__c=theOpp.Id, Competitor__c=d.Id));
                break;
            }
        }
      
        updateAvailableList();
    }
  

    public PageReference removeFromShoppingCart(){
  
        // This function runs when a user hits "remove" on an item in the "Selected Products" section
  
        Integer count = 0;
  
        for(Competitor__c d : shoppingCart){
            if((String)d.Competitor__c==toUnselect){
          
                if(d.Competitor__c!=null)
                    forDeletion.add(d);
          
                shoppingCart.remove(count);
                break;
            }
            count++;
        }
      
        updateAvailableList();
      
        return null;
    }
  
    public PageReference onSave(){
  
        // If previously selected products are now removed, we need to delete them
        if(forDeletion.size()>0)
            delete(forDeletion);
  
        // Previously selected products may have new quantities and amounts, and we may have new products listed, so we use upsert here
        try{
            if(shoppingCart.size()>0)
                upsert(shoppingCart);
        }
        catch(Exception e){
            ApexPages.addMessages(e);
            return null;
        }
         
        // After save return the user to the Opportunity
        return new PageReference('/' + ApexPages.currentPage().getParameters().get('Id'));
    }
  
    public PageReference onCancel(){

        // If user hits cancel we commit no changes and return them to the Opportunity 
        return new PageReference('/' + ApexPages.currentPage().getParameters().get('Id'));
    }
 
}

Opened a case with SF support on this, but they changed their support policies for development and won't help me so I came to the next best place...the boards!

 

When using Visualforce and Apex text editors within the SF UI, the line where my cursor is placed is getting visually duplicated a few pixels down the page. It is very annoying and confusing, I've done some searching and can't determine if other users have experienced this issue. I have tried clearing my browser cache, but that doesn't appear to have any impact.

 

Image1

Image2

  • December 13, 2013
  • Like
  • 0

Loving Cloud Swarm, just customized the unmanaged package to set up auto-follow rules for a custom object. I'm not really a developer, but a curious admin who can look at some code, sort of understand what it's saying/doing, and perform slight maniuplations to customize it.

 

Before I go down this road, I'm hoping someone can tell me whether this is possible and, if so, if it's relatively simple to do using the existing code in the Cloud Swarm package. I'd like to set up auto-follow rules for Files that are uploaded to custom object records that users own.

 

EXAMPLE:

  • We have a custom object called "Producer Record."
  • I own the Producer Report record, "January 2013 Commission Report."
  • A PDF file is uploaded to the January 2013 Commission Report record.
  • I auto-follow the PDF file according to criteria established in the Cloud Swarm app.

Possible?

  • October 10, 2013
  • Like
  • 0

I have a custom object called Producer_Commission_Report__c. Each of these records will have one (1) Chatter file posted to them.

 

I would like to populate a field on this object called "Chatter File ID" with the ID of the most recently (i.e., the only) posted Chatter File on each record. Can anyone offer some help?

  • October 07, 2013
  • Like
  • 0

I desperately need to filter FeedItems where Type = 'ContentPost' and at least one of the following fields is LIKE '%Commission Report%', but they all appear to be unsupported in a query call: Body, ContentDescription, ContentFileName, Title. It looks like querying Description and Name is supported in Attachment, why can't I query anything useful related to a FeedItem?

 

Can anyone offer a suggestion on how to go about doing this? Here is my extension:

 

public with sharing class pcrControllerExtension {
private final id pdcid;
public pcrControllerExtension(ApexPages.StandardController stdController) {
pdcid = ((Producer_Document_Center__c)stdController.getRecord()).id;
}

public String getFileList() {
    String strHTMLTable = '<table>';
    Integer i = 1;
        for(FeedItem fi:[Select Id, Body, Title, RelatedRecordId FROM FeedItem
        WHERE ParentId =:pdcid AND Type = 'ContentPost' AND ContentFileName LIKE '%Commission Report%' Order By CreatedDate Desc])
        {
            strHTMLTable = strHTMLTable + '<tr><td>No.' + i + ' </td><td><a href="' + URL.getSalesforceBaseUrl().toExternalForm()+ '/' + fi.RelatedRecordId + '" target="_blank" >' + fi.Title+ '</a></td></tr><BR>';
            i++;
        }
    strHTMLTable = strHTMLTable + '</table>';
    return strHTMLTable;
    }
}

 

  • October 07, 2013
  • Like
  • 0

Hello all,

 

I've got a wonderfully complicated idea, and before I invest too much time in pursuing it, I was wondering if an expert out there could tell me whether this is possible...

 

I have a custom object in my org for Employee. We have a number of documents generated from a back-end system by our accounting department every month for some of our employees. These docs are emailed to everyone and archived somewhere, and it's a pretty time-consuming and cumbersome process.

 

I've been asked to find a way to semi-automate a process for taking those documents every month, Data Loading them into each Employee record as an attachment (I'm thinking I'd like to do it as a Chatter FeedItem), and presenting them as hyerplinked lists on a dashboard that is already configured to run as logged in user. By standardizing FeedItem Body and/or ContentFileName and/or ContentDescription, I'm thinking I'd be able to create custom related lists on the Employee object records that group documents by their types (e.g., Monthly Commission Statements, Monthly Expense Report, etc.). Using this same idea, I could create various Visualforce Components to present on a Dashboard where each component houses lists of links to files of different types (see this image for clarification: http://postimg.org/image/7b6vbztsn/).

 

I'm not terribly concerned about the Data Loading process. What I need is some clarification/direction on dynamically displaying different documents on a dashboard and/or Employee record, depending upon who is viewing the board/record at that time.

 

Is this possible?

 

Thanks.

  • October 03, 2013
  • Like
  • 0

Hello!

 

I have a pretty nice flow in place that allows a user to enter some useful competitor information when we lose an Opportunity. One of the steps in the flow allows the user to create a follow-up Opportunity for next year, which is designed to basically clone the existing Opp with all of its products.

 

To accomplish this, I created a query loop for Opportunity Product where a checkbox called "Flow Processed" is false (thanks @Rajaram! solution here: http://boards.developerforce.com/t5/Visual-Workflow/Deep-Clone-Opportunity-with-Products-via-Visual-Workflow/m-p/642189#M1419). The query retrieves each Opportunity Product one at a time, marks Flow Processed as true, clones it, and re-runs the query until there are no more Flow Processed = false products.

 

This works perfectly EXCEPT when there are a lot of products. My testing seems to suggest that 4 products is the limit. Anything over that causes this error:

 

caused by: interaction.sfdc.adapter.rules.SalesforceRuleBrokenException: UPSERT --- UPSERT FAILED ---  ERRORS :  (CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY) SL_Opportunity: System.LimitException: Too many SOQL queries: 101 ---  for SFDC record with ID : null, 

Salesforce Error ID: 497037844-218727 (-1473334608)

The SL_Opportunity referenced is a trigger developed by a third party that is essential to a system integration in place, so I can't really change that trigger. I need a different workaround.

 

I know some brilliant mind in this community can offer some suggestions for getting around this. I've been thinking about trying to count the number of Products and then separate the Product create actions into batches or something, but I keep getting confused!

 

Thanks!

  • September 25, 2013
  • Like
  • 0

Hello,

 

I have a custom text field serving as an external, non-unique ID labeled "E_Policy_ID__c." I would like to extract all records for this object where E_Policy_ID__c is NOT unique.

 

Can anyone give any tips on a SOQL query that I can use in Workbench or Data Loader? I'd like to avoid extracting ALL object records and then using Excel sleuthing to find the non-unique rows.

 

Thank you!

  • August 28, 2013
  • Like
  • 0

Hello. The trigger below updates a custom Activity field for Event called "New_Business_Opportunity__c" to true if the Related To field of the event is an Opportunity with a certain record type. My org uses LinkPoint360 to sync Outlook calendar items to Salesforce, and a number of users have been experiencing issues when LinkPoint attempts to create Salesforce events using Outlook calendar items. Salesforce items do not get created, and the following error is captured in some event logs:

 

Apex script unhandled trigger exception by user/organization: 00560000001SP8S/00D60000000JyqG

updateOppEventCheckbox: execution of BeforeInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Trigger.updateOppEventCheckbox: line 8, column 1

 Here is the trigger code:

trigger updateOppEventCheckbox on Event(before insert, before update) {
  map<id,opportunity> opportunities = new map<id,opportunity>();
  for(event record:trigger.new)
    if(record.whatid!=null&&record.whatid.getsobjecttype()==opportunity.sobjecttype)
    opportunities.put(record.whatid,null);
  opportunities.putAll([select id,recordtype.developername from opportunity where id in :opportunities.keyset()]);
  for(event record:trigger.new)
    record.New_Business_Opportunity__c = opportunities.containskey(record.whatid) && opportunities.get(record.whatid).recordtype.developername.contains('Standard');
}

 

Can anyone tell me if there is a way to optimize this code so that the error clears? Some users are losing Outlook calendar data, so this is a potentially big problem :(

 

Thank you!

  • August 06, 2013
  • Like
  • 0

Here is the use case: Sales person doesn't close the sale this year :(   They click a button on Opportunity page layout which launches a loss analysis flow where we capture useful information like who we lost it to, why we lost it, notes about how this went down, etc.

 

One screen asks the user if they want to create a follow-up Opportunity for next year. If they choose "Yes," I'd ideally clone the entire Opportunity record with all of its products and just adjust things like Stage and Close Date using the flow.

 

I know I can't achieve this without an Apex plugin, and I was wondering if anyone out there has one built that can handle this, or can assist me in getting something like it developed. I am not an Apex developer, but I can find my way around some code if I have something to start playing with.

 

Thanks for any guidance.

Hello! I am trying to give my users the ability select one or many records from a related list (using checkboxes) and then click a custom clone button that will allow them to clone and re-parent the selected record(s) to a different master record.

 

The requirement is that all selected items get re-parented to the same master record, so I'm sort of envisioning one simple intermediary screen after the custom clone button is selected where the user will use a Lookup field to select the new parent for all of the records they selected.

 

I'm not an Apex guru by any means, but I can usually get moving with a little input from the dev community and some sample code. Any ideas? Thanks!

Hello, Apex newbie here.

 

Can anyone help me along in the right direction? I would like to update a a custom Activity checkbox field to TRUE if the WhoId of an Activity equals a certain record type. In my non-Apex layman's formula terms, it's something like this:

 

IF Activity.WhoId.RecordTypeId = "01260000000LyEL", My_Checkbox__c = TRUE, FALSE

 

Any ideas?

 

Thanks!

Hello! I am overriding the standard Opportunity Product selection page. I have two custom fields, Effective Date and Expiration Date, on this page. My users would shower me with gifts and praise if I could implement functionality that would auto-populate all Product Effective and Expiration Date fields based upon the selection they make in the first Product row (see this image for clarification).

 

I know this will require Javascript, which I know next to nothing about. Hopefully, since I am already overriding the page with Visualforce, someone can provide a Javascript code snippet that I can easily paste in to at least get started? Thanks for any help!

 

 

  • April 30, 2013
  • Like
  • 0

Anyone have any tips on finishing a flow at a record edit screen that has certain fields filled out that were established in the flow?

 

If that was confusing, here is the scenario: When going to create an Opportunity, I need users to fill out some preliminary information that will effect things on the Opportunity like record type, dependent picklists, etc. I would like to set this up so that they kick off a flow when creating an Opp, fill out the preliminary information, and when they click Finish, it takes them to the edit page for that record with the information they entered in the flow already filled out BUT the record has not yet been saved/committed to the database.

 

Thanks for any info!

  • December 13, 2012
  • Like
  • 0

I am attempting to initiate a visual workflow upon the saving of an opportunity that meets certain criteria. The criteria are rather simple:

  1. The record type = "Standard New Business"
  2. The stage = "Closed Won" OR "Closed Lost"

If, upon save, the Opp is Closed Won, then I want to kick off a flow called "StandardOppWon." If Closed Lost, then kick off the flow "StandardOppLost."

 

I'm not even sure if kicking off flows via a trigger is possible, but this is the place to find out, right?! Can anyone help me get started in the right direction. I am a button-click admin who loves flows and understands them pretty well, but Apex triggers are a pretty new game for me.

 

Cheers!

  • November 27, 2012
  • Like
  • 0

I'm having difficulty setting the finishLocation of a flow. I would like users to return to the originating Account record from which they started the flow from upon clicking the Finish button.

 

I have an object with a master-detail relationship to Account. In the object's related list on the Account, I have a custom button. When clicked, the custom button loads a Visualforce page with a flow:interview embedded in it. Here is the button's URL structure:

 

https://na4.salesforce.com/apex/UWRScheduler?acct_id={!Account.Id}&acct_name={!Account.Name}

 Here is the Visualforce page without any finishLocation set:

 

<apex:page standardController="Account">
        <flow:interview name="UWScheduler" />
</apex:page>

 Here's what I have tried:

 

Attempt1: In the custom button, set the retUrl=%2F{!Account.ID}
Result1: Upon clicking Finish in the flow, I loop back to the first flow screen, and the URL = /apex/UWRScheduler?sparkID=UWScheduler

 

 

Attempt2: Set the following in the Visualforce page:

finishLocation="{!URLFOR($Action.Account.View, Account.Id, null, true)}"

Result2:

Invalid parameter for function URLFOR
Error is in expression '{!URLFOR($Action.Account.View, Account.Id, null, true)}' in component <flow:interview> in page uwrscheduler

 

Attempt3: Set the following in the Visualforce page:

finishLocation="{!URLFOR('/{!Account.Id}')}"

 Result3: Clicking Finish in the flow logs me out of Salesforce!

 

Please help! My first flow is almost complete!

  • November 08, 2012
  • Like
  • 0
I have a custom object that has Start and End fields as datetime. I am trying to create a Visualforce email template that will be able to send an email with a .ics attachment that will use my object's Start/End fields.

I've got everything working except that my object's field values are getting output as GMT, not UTC, and the .ics format needs UTC. Here's what I've got in the template (PS, I've tried not wrapping my fields in the outputText tags, the result is the same):
DTSTART;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__Start__c}" />
DTEND;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__End__c}" />
Here is an example of what gets output in the resulting .ics file:
DTSTART;TZID="Eastern Standard Time":Mon Jul 06 17:00:00 GMT 2015
DTEND;TZID="Eastern Standard Time":Mon Jul 06 21:00:00 GMT 2015
How do I just get VF to output my fields in UTC? Isn't this how they are actually stored in the database, anyway??

  • August 27, 2014
  • Like
  • 1
I have a custom object that has Start and End fields as datetime. I am trying to create a Visualforce email template that will be able to send an email with a .ics attachment that will use my object's Start/End fields.

I've got everything working except that my object's field values are getting output as GMT, not UTC, and the .ics format needs UTC. Here's what I've got in the template (PS, I've tried not wrapping my fields in the outputText tags, the result is the same):
DTSTART;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__Start__c}" />
DTEND;TZID="Eastern Standard Time":<apex:outputText value="{!RelatedTo.evt__Event__r.evt__End__c}" />
Here is an example of what gets output in the resulting .ics file:
DTSTART;TZID="Eastern Standard Time":Mon Jul 06 17:00:00 GMT 2015
DTEND;TZID="Eastern Standard Time":Mon Jul 06 21:00:00 GMT 2015
How do I just get VF to output my fields in UTC? Isn't this how they are actually stored in the database, anyway??

  • August 27, 2014
  • Like
  • 1
I have what appears to be a pretty simply requirement but I am really struggling with this one...

I have a custom object and am overriding the standard Edit page with a Visualforce page. This object has custom checkbox field, Finalized__c.

I'm looking to do either one of these two things, and the preferable method would be avoid an apex controller, if possible:
  • IF Finalized__c = TRUE, make the whole page readOnly;
  • IF Finalized__c = TRUE, make field A__c, B__c, and C__c read only.
Any ideas? Greatly appreciated.
  • August 09, 2014
  • Like
  • 0
Hi! I would like to present my users with a custom VF page for entering/editing records. The page will have a number of tables and the cells of these tables will have a mix of hardcoded values and input options. I thought I was on the right track, but when I try to put an apex:inputField in one of the <td> tags, the HTML breaks and my table gets all messed up.

VF code:
<table border="1" style="width:800px">
                        <tbody><tr>
                            <th>EXCLUDE DBL AND BENEFITS</th>
                            <th>SAMPLE</th>
                            <th>YOURS</th> 
                            <th>KEY</th>
                        </tr>
                        <tr>
                            <td>Gross Commission Pr1</td>
                            <td>300000</td>
                            <td></td><td class="dataCol  first " colspan="2"><input id="j_id0:j_id2:j_id3:section1:j_id13" name="j_id0:j_id2:j_id3:section1:j_id13" size="20" style="width:100px" type="text"></td></tr><tr><td class="dataCol  last " colspan="2"></td>
                            <td>Book of Business minus DBL and Benefits</td>
                        </tr>
                    </tbody></table>
Image of broken table:
User-added image
I am modifying this awesome code package from Michael Farrington (http://www.michaelforce.org/recipeView?id=a0G30000006eVxVEAU) to build a VF page that will allow a user to add multiple competitors to an Opportunity at one time. It is SO CLOSE to working, but I have this one final hurdle to cross...

I am using a junction object to attach competitors to Opportunities. My list of options is stored in the Competitor_Option__c object, and then my Competitor__c object has a master-detail to Opportunity, and a lookup to Competitor_Option__c.

The VF page has two sections: Selected Competitors and Available Competitors. Everything is working great EXCEPT that my list of Available Competitors is not returning any results when the page is first loaded. If I hit backspace while in the page's search field, my Competitor_Options__c load. If I Remove a previously added option, the options load. Can anyone help me find what in my code is preventing any options from loading when the page first loads?

User-added image

VF page:
<apex:page standardController="Opportunity" extensions="opportunityProductEntryExtension" >
    <apex:sectionHeader Title="Manage Competitors" subtitle="{!opportunity.Name}"/>
    <apex:messages style="color:red"/>
  
    <style>
        .search{
            font-size:14pt;
            margin-right: 20px;  
        }
        .fyi{
            color:red;
            font-style:italic;
        }
        .label{
            margin-right:10px;
            font-weight:bold;
        }
    </style>
  
    <script type='text/javascript'>
        // This script assists the search bar functionality
        // It will execute a search only after the user has stopped typing for more than 1 second
        // To raise the time between when the user stops typing and the search, edit the following variable:
        var waitTime = 0;
        var countDown = waitTime+1;
        var started = false;
        function resetTimer(){
            countDown=waitTime+1;
            if(started==false){
                started=true;
                runCountDown();
            }
        }
        function runCountDown(){
            countDown--;
            if(countDown<=0){
                fetchResults();
                started=false;
            }
            else{
                window.setTimeout(runCountDown,1000);
            }
        }
    </script>
  
    <apex:form id="form">
        <apex:outputPanel id="mainBody">
<!-- this is the upper table... a.k.a. the "Shopping Cart"-->
            <apex:pageBlock title="Selected Competitors" id="selected">
                <apex:pageblockTable value="{!shoppingCart}" var="s">
                    <apex:column >
                        <apex:commandLink value="Remove" action="{!removeFromShoppingCart}" reRender="selected,searchResults" immediate="true">
                            <!-- this param is how we send an argument to the controller, so it knows which row we clicked 'remove' on -->
                            <apex:param value="{!s.Competitor__c}" assignTo="{!toUnselect}" name="toUnselect"/>
                        </apex:commandLink>
                    </apex:column>
                    <apex:column headerValue="Competitor" value="{!s.Competitor__c}"/>
                    <apex:column headerValue="Incumbent">
                        <apex:inputField value="{!s.Incumbent__c}" />
                    </apex:column>
                    <apex:column headerValue="Winner">
                        <apex:inputField value="{!s.Winner__c}" />
                    </apex:column>
                    <apex:column headerValue="Strengths">
                        <apex:inputField value="{!s.Strengths__c}" style="width:200px; height:100px" required="false"/>
                    </apex:column>
                    <apex:column headerValue="Weaknesses">
                        <apex:inputField value="{!s.Weaknesses__c}" style="width:200px; height:100px" required="false"/>
                    </apex:column>
                    <apex:column headerValue="Competing Producer">
                        <apex:inputField value="{!s.Producer__c}" required="false"/>
                    </apex:column>
                </apex:pageblockTable>
                <apex:pageBlockButtons >
                    <apex:commandButton action="{!onSave}" value="Save"/>
                    <apex:commandButton action="{!onCancel}" value="Cancel" immediate="true"/>
                </apex:pageBlockButtons>
            </apex:pageBlock>
<!-- this is the lower table: search bar and search results -->
            <apex:pageBlock id="block">
                <apex:outputPanel styleClass="search">
                    Search for Competitors:
                </apex:outputPanel>
                <apex:actionRegion renderRegionOnly="false" immediate="true" id="region">
                    <apex:actionFunction name="fetchResults" action="{!updateAvailableList}" reRender="searchResults" status="searchStatus" id="function" />
                    <!-- here we invoke the scripting to get out fancy 'no button' search bar to work -->
                    <apex:inputText value="{!searchString}" onkeydown="if(event.keyCode==13){this.blur();}else{resetTimer();}" style="width:300px" id="search" />
                    &nbsp;&nbsp;
                    <i>
                        <!-- actionStatus component makes it easy to let the user know when a search is underway -->
                        <apex:actionStatus id="searchStatus" startText="searching..." stopText=" "/>
                    </i>
                </apex:actionRegion>
                <br/>
                <br/>
                <apex:outputPanel id="searchResults">
                    <apex:pageBlockTable value="{!AvailableProducts}" var="a">
                        <apex:column width="100px;">
                            <!-- command button in a column... neato -->
                            <apex:commandButton value="Select" action="{!addToShoppingCart}" reRender="selected,searchResults" immediate="true">
                                <!-- again we use apex:param to be able to tell the controller which row we are working with -->
                                <apex:param value="{!a.Id}" assignTo="{!toSelect}" name="toSelect"/>
                            </apex:commandButton>
                        </apex:column>
                        <apex:column headerValue="Competitor" value="{!a.Name}" width="300px;" />
                        <apex:column headerValue="Type" value="{!a.Competitor_Type__c}" />
                    </apex:pageBlockTable>
                    <!-- We put up a warning if results exceed 100 rows -->
                    <apex:outputPanel styleClass="fyi" rendered="{!overLimit}">
                        <br/>
                        Your search returned over 100 results, use a more specific search string if you do not see the desired Competitor.
                        <br/>
                    </apex:outputPanel>
                </apex:outputPanel>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>
</apex:page>





Apex extension:
public with sharing class opportunityProductEntryExtension {

    public Opportunity theOpp {get;set;}
    public String searchString {get;set;}
    public Competitor__c[] shoppingCart {get;set;}
    public Competitor_Option__c[] AvailableProducts {get;set;}
  
    public String toSelect {get; set;}
    public String toUnselect {get; set;}
    public Decimal Total {get;set;}
  
    public Boolean overLimit {get;set;}
  
    private Competitor__c[] forDeletion = new Competitor__c[]{};

    public opportunityProductEntryExtension(ApexPages.StandardController controller) {

        theOpp = [select Id from Opportunity where Id = :controller.getRecord().Id limit 1];
      
        // If products were previously selected need to put them in the "selected products" section to start with
        shoppingCart = [select Id, Name, Incumbent__c, Winner__c, Strengths__c, Weaknesses__c, Producer__c, Competitor__c from Competitor__c where Opportunity__c=:theOpp.Id order by Id Asc];

    }

    public void updateAvailableList() {
  
        // We dynamically build a query string and exclude items already in the shopping cart
        String qString = 'select Id, Name, Competitor_Type__c from Competitor_Option__c where Active__c=true';
      
        // note that we are looking for the search string entered by the user in the name OR description
        // modify this to search other fields if desired
      
        if(searchString!=null){
            qString+= ' and (Name like \'%' + searchString + '%\')';
        }
      
        Set<Id> selectedEntries = new Set<Id>();
        for(Competitor__c d:shoppingCart){
            selectedEntries.add(d.Competitor__c);
        }
      
        if(selectedEntries.size()>0){
            String tempFilter = ' and Id not in (';
            for(Id i : selectedEntries){
                tempFilter+= '\'' + (String)i + '\',';
            }
            String extraFilter = tempFilter.substring(0,tempFilter.length()-1);
            extraFilter+= ')';
          
            qString+= extraFilter;
        }
      
        qString+= ' order by Name';
        qString+= ' limit 101';
      
        system.debug('qString:' +qString);      
        AvailableProducts = database.query(qString);
      
        // We only display up to 100 results... if there are more than we let the user know (see vf page)
        if(AvailableProducts.size()==101){
            AvailableProducts.remove(100);
            overLimit = true;
        }
        else{
            overLimit=false;
        }
    }
  
    public void addToShoppingCart(){
  
        // This function runs when a user hits "select" button next to a product
  
        for(Competitor_Option__c d : AvailableProducts){
            if((String)d.Id==toSelect){
                shoppingCart.add(new Competitor__c(Opportunity__c=theOpp.Id, Competitor__c=d.Id));
                break;
            }
        }
      
        updateAvailableList();
    }
  

    public PageReference removeFromShoppingCart(){
  
        // This function runs when a user hits "remove" on an item in the "Selected Products" section
  
        Integer count = 0;
  
        for(Competitor__c d : shoppingCart){
            if((String)d.Competitor__c==toUnselect){
          
                if(d.Competitor__c!=null)
                    forDeletion.add(d);
          
                shoppingCart.remove(count);
                break;
            }
            count++;
        }
      
        updateAvailableList();
      
        return null;
    }
  
    public PageReference onSave(){
  
        // If previously selected products are now removed, we need to delete them
        if(forDeletion.size()>0)
            delete(forDeletion);
  
        // Previously selected products may have new quantities and amounts, and we may have new products listed, so we use upsert here
        try{
            if(shoppingCart.size()>0)
                upsert(shoppingCart);
        }
        catch(Exception e){
            ApexPages.addMessages(e);
            return null;
        }
         
        // After save return the user to the Opportunity
        return new PageReference('/' + ApexPages.currentPage().getParameters().get('Id'));
    }
  
    public PageReference onCancel(){

        // If user hits cancel we commit no changes and return them to the Opportunity 
        return new PageReference('/' + ApexPages.currentPage().getParameters().get('Id'));
    }
 
}

Opened a case with SF support on this, but they changed their support policies for development and won't help me so I came to the next best place...the boards!

 

When using Visualforce and Apex text editors within the SF UI, the line where my cursor is placed is getting visually duplicated a few pixels down the page. It is very annoying and confusing, I've done some searching and can't determine if other users have experienced this issue. I have tried clearing my browser cache, but that doesn't appear to have any impact.

 

Image1

Image2

  • December 13, 2013
  • Like
  • 0

Hello all,

 

I've got a wonderfully complicated idea, and before I invest too much time in pursuing it, I was wondering if an expert out there could tell me whether this is possible...

 

I have a custom object in my org for Employee. We have a number of documents generated from a back-end system by our accounting department every month for some of our employees. These docs are emailed to everyone and archived somewhere, and it's a pretty time-consuming and cumbersome process.

 

I've been asked to find a way to semi-automate a process for taking those documents every month, Data Loading them into each Employee record as an attachment (I'm thinking I'd like to do it as a Chatter FeedItem), and presenting them as hyerplinked lists on a dashboard that is already configured to run as logged in user. By standardizing FeedItem Body and/or ContentFileName and/or ContentDescription, I'm thinking I'd be able to create custom related lists on the Employee object records that group documents by their types (e.g., Monthly Commission Statements, Monthly Expense Report, etc.). Using this same idea, I could create various Visualforce Components to present on a Dashboard where each component houses lists of links to files of different types (see this image for clarification: http://postimg.org/image/7b6vbztsn/).

 

I'm not terribly concerned about the Data Loading process. What I need is some clarification/direction on dynamically displaying different documents on a dashboard and/or Employee record, depending upon who is viewing the board/record at that time.

 

Is this possible?

 

Thanks.

  • October 03, 2013
  • Like
  • 0

Hello. The trigger below updates a custom Activity field for Event called "New_Business_Opportunity__c" to true if the Related To field of the event is an Opportunity with a certain record type. My org uses LinkPoint360 to sync Outlook calendar items to Salesforce, and a number of users have been experiencing issues when LinkPoint attempts to create Salesforce events using Outlook calendar items. Salesforce items do not get created, and the following error is captured in some event logs:

 

Apex script unhandled trigger exception by user/organization: 00560000001SP8S/00D60000000JyqG

updateOppEventCheckbox: execution of BeforeInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Trigger.updateOppEventCheckbox: line 8, column 1

 Here is the trigger code:

trigger updateOppEventCheckbox on Event(before insert, before update) {
  map<id,opportunity> opportunities = new map<id,opportunity>();
  for(event record:trigger.new)
    if(record.whatid!=null&&record.whatid.getsobjecttype()==opportunity.sobjecttype)
    opportunities.put(record.whatid,null);
  opportunities.putAll([select id,recordtype.developername from opportunity where id in :opportunities.keyset()]);
  for(event record:trigger.new)
    record.New_Business_Opportunity__c = opportunities.containskey(record.whatid) && opportunities.get(record.whatid).recordtype.developername.contains('Standard');
}

 

Can anyone tell me if there is a way to optimize this code so that the error clears? Some users are losing Outlook calendar data, so this is a potentially big problem :(

 

Thank you!

  • August 06, 2013
  • Like
  • 0

Here is the use case: Sales person doesn't close the sale this year :(   They click a button on Opportunity page layout which launches a loss analysis flow where we capture useful information like who we lost it to, why we lost it, notes about how this went down, etc.

 

One screen asks the user if they want to create a follow-up Opportunity for next year. If they choose "Yes," I'd ideally clone the entire Opportunity record with all of its products and just adjust things like Stage and Close Date using the flow.

 

I know I can't achieve this without an Apex plugin, and I was wondering if anyone out there has one built that can handle this, or can assist me in getting something like it developed. I am not an Apex developer, but I can find my way around some code if I have something to start playing with.

 

Thanks for any guidance.

Hello! I am trying to give my users the ability select one or many records from a related list (using checkboxes) and then click a custom clone button that will allow them to clone and re-parent the selected record(s) to a different master record.

 

The requirement is that all selected items get re-parented to the same master record, so I'm sort of envisioning one simple intermediary screen after the custom clone button is selected where the user will use a Lookup field to select the new parent for all of the records they selected.

 

I'm not an Apex guru by any means, but I can usually get moving with a little input from the dev community and some sample code. Any ideas? Thanks!

I am attempting to initiate a visual workflow upon the saving of an opportunity that meets certain criteria. The criteria are rather simple:

  1. The record type = "Standard New Business"
  2. The stage = "Closed Won" OR "Closed Lost"

If, upon save, the Opp is Closed Won, then I want to kick off a flow called "StandardOppWon." If Closed Lost, then kick off the flow "StandardOppLost."

 

I'm not even sure if kicking off flows via a trigger is possible, but this is the place to find out, right?! Can anyone help me get started in the right direction. I am a button-click admin who loves flows and understands them pretty well, but Apex triggers are a pretty new game for me.

 

Cheers!

  • November 27, 2012
  • Like
  • 0

Hi 

In visualforce page, i am displaying the Number(16,2) fields of salary, wages etc. currently its displaying like this 10,000.00

i need it without comma for i am adding these values dynamically and save on gross pay number field. during addition it takes first two digits of before comma, it takes 10,000.00 as 10. Is there any idea to solve this issue.

 

thank you.