The Ultimate Visualforce Events Tab - Almost
Check old blog posts, and you’ll see that I’ve been working on custom Events and Task tabs for a while now. A Task Visualforce tab (that mimics the Task box on the Home Page) is almost ready to come out, but the Events Enhanced List tab is (pretty much) here!
This bears emphasizing: Enhanced Lists were initially not fully released for Activity/Event/Task objects, but are available now.
The code is ridiculously simple, thanks to the apex:EnhancedList Visualforce tag:
<apex:page standardController="Task" > <apex:enhancedList type="Activity" height="800" rowsPerPage="50" /> </apex:page>
See? Nothing to it! Or so we thought. There are some catches (there always are):
- The original use-case required displaying all upcoming events without the header or sidebar. We still cannot do this. Quoting from the Winter ‘09 Release Notes: The enhancedList component is not allowed on pages that have the attribute showHeader set to false.
- We’d like to create a custom tab for this page. We create a Visualforce Tab, pick a custom icon, and show the page… and when I click on the tab, the enhanced list is displayed, but the tab is not highlighted. Also, the custom icon I chose is not displayed. How do we highlight our tab?
After making the page, we make the tab as desribed above. Then we RETURN to the page and add a tabstyle modifier to the apex:page tag, like so:<apex:page standardController="Task" tabstyle="enhanced_activities__tab"> <apex:enhancedList type="Activity" height="800" rowsPerPage="50" /> </apex:page>
[Of course, change the tab name to whatever you choose.]
Success? Not quite. There’s another catch:
- The tab is highlighted (brown in our case), but the color and icon for the enhanced list are standard green/home.
Sadly, I have no workaround for this one. Sorry.
To repeat: Enhanced lists were not initially fully available for Events and Tasks, but now do support them.
Moving forward, consider if you want to create a particular enhanced list view instead of calling the standard enhanced Activity list as I have done here. If you would prefer to make a custom enhanced list view, then you will need to add more code, but that is beyond the scope of this post.
Enjoy!
Force.com Sites Guest User Profile Permissions
I’m working on an event registration application for the Sites Developer Challenge, and it involves a validation that the registrant’s email exists in a Contact record. Remembering that Steve Andersen had run into some obstacles with Contact.Email visibility, I decided to check the guest profile for Contact Field Level Security. Here’s what I found:

Guest profile Contact Field Level Security
If you squint a bit, you can see that the Opt-Out and Email fields are hidden to the guest user. I have no idea why these, in particular, are hidden. Likewise, I couldn’t find a pattern in which fields were shown on the custom objects I had created, nor which were visible on standard objects.
In any event, I don’t have any pearls of wisdom on this topic; this is more of an informative note to all that are using Sites (especially if you plan to do any communication-subscriptions) to check out the Field-Level Security.
For those wondering how to get to this Profile (since it is not visible in the usual Profile section), go to the Sites page > Site Name or URL > Public Access Settings (a button).
X-Squared Featured in ITA Newsletter
This week, X-Squared On Demand was featured in the Illinois Technology Association’s Industry Weekly newsletter ITA Member Q&A.
Thank you to the ITA for featuring us!
Inline Visualforce Page Layouts!
We’re all used to using inline S-Controls, dragging and dropping them into page layouts. And the entire Salesforce community has been spending tons of time recreating page layouts in Visualforce, just to edit one small piece of a page.
As an example, how would you implement the example at developer.force.com: Visualforce Dynamic Edit Page? You would do it the way it was explained in the blog post!
Well the rules of the game have changed.
As long as you use a Standard Controller, you can now place Visualforce pages IN regular page layouts!
Inline Visualforce Page Layout screenshot
The article was written by Sati Hillyear, who is also an expert on the License Manager Application. Check it out!
Project: Change Owner Button in Visualforce
Salesforce Labs has put out a series of Mass Action packages on the AppExchange. There is Mass Transfer Opportunity Owner (uses AJAX), Mass Update Contact Addresses (AJAX), Mass Update Opportunity Owner, Mass Update Opportunity Close Dates, etc. All of these are “thick client” tools, meaning that data must be loaded onto your computer, altered, and then uploaded back to Salesforce.
Ron Hess released a super bit of code, found in the Visualforce documentation and elsewhere, to Mass Update Opportunity Stage and Close Date. It could, theoretically, be expanded to other fields as well. This got me thinking about doing so with other objects.
A while ago, I took the code for the Mass Delete button and altered it to change the owner of the selected records to the User clicking the button. It was like an Accept button, but I could use it for any object. Actually, it wasn’t as easy as that. I had to make one button for each object, and maintenance was a pain–whenever I created a new object, I needed to clone my code.
Drawing upon some code I found in the Developers Guide, I have written a Visualforce page to mass-change the owner of all selected records to any active User in Salesforce. Yes, it only works with Contacts for now, but my next step will be to use Dynamic Apex to pass the sObject name to the page and its extension/controller, allowing me to reuse one bit of code for multiple objects. We’ll see how it goes. But in the meantime, enjoy this page that lets you perform a search, check which records you want to transfer, and then input a User. I’ve tested it with 50 records at once, so that should suffice for most uses.
VF Page:
<apex:page standardController="Contact" recordSetVar="Contacts" id="updateOwnerPage">
<apex:form>
<apex:sectionHeader title="Change Owner for Contacts"/>
<apex:pageBlock mode="edit">
<apex:pageMessages />
<apex:pageblockSection title="Change" columns="1">
<apex:pageblockSectionItem >
<apex:outputLabel for="owner">New Owner</apex:outputLabel>
<apex:inputField id="owner" value="{!Contact.OwnerId}"/>
</apex:pageblockSectionItem>
</apex:pageBlockSection>
<apex:pageBlockSection title="Selected Contacts" columns="1">
<apex:pageBlockTable value="{!selected}" var="j" bgcolor="#F3F3EC" width="100%"
styleClass="list" rowClasses="dataRow" onRowMouseOver="hiOn(this);" onRowMouseOut="hiOff(this);">
<apex:column >
<apex:facet name="header">Contact Name</apex:facet>
<apex:outputLink value="{!URLFOR($Action.Contact.View, j.id)}">
{!j.FirstName} {!j.LastName}</apex:outputLink>
</apex:column>
<apex:column >
<apex:facet name="header">Account Name</apex:facet>
<apex:outputLink value="{!URLFOR($Action.Account.View, j.Account.id)}">
{!j.Account.Name}</apex:outputLink>
</apex:column>
<apex:column>
<apex:facet name="header">Current Owner</apex:facet>
{!j.Owner.Name}
</apex:column>
</apex:pageBlockTable>
</apex:pageblockSection>
<apex:pageBlockButtons location="bottom">
<apex:commandButton value="Save" action="{!save}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>
Button:
Go to Setup -> Contact -> Buttons and Links
Create a new button, set it to execute in the current window with sidebar and header, and set it to call a Visualforce page. Select the page you just created. Then add the button to Contact Search Layout and to any Contact related lists you like.
Voila!
Project: Lookup to Picklist
In the first installment of post-Dreamforce projects, I present a mechanism to present the user with all available Lookup options in a picklist. This should simplify some Visualforce pages. (Credit to the Developers Guide from the new post-Dreamforce Library.)
The key to the code is the ability to customize the SOQL statement to focus as much, or as little, as the developer would like. Though the code I provide makes no limit on the number of records returned, I encourage developers to limit the select statement as seen fit.
VF Page:
<apex:page standardcontroller="Child__c" Extensions="ChildExtension">
<apex:messages ></apex:messages>
<apex:form >
<apex:pageBlock mode="edit" id="thePageBlock">
<apex:pageBlockButtons >
<apex:commandButton value="Save" action="{!save}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
<apex:pageblockSection id="ParentList" title="1">
<apex:pageBlockSectionItem >
<apex:outputLabel value="Parent" for="p"/>
<apex:selectList id="p" value="{!Child__c.Parent__c}" size="1" title="3">
<apex:selectOptions value="{!ParentOptions}"/>
</apex:selectList>
</apex:pageBlockSectionItem>
</apex:pageblocksection>
</apex:pageBlock>
</apex:form>
</apex:page>
Extension:
Note the SOQL query in Line 12 (below) that defines which records are included in the picklist. You can include WHERE and LIMIT statements to get the picklist down to a manageable number of items.
public class ChildExtension {
private final Child__c child;
public ChildExtension(ApexPages.StandardController controller) {
this.child = (Child__c)controller.getRecord();
}
public List<selectOption> PositionOptions {get
{
List<selectOption> parents = new List<selectOption>();
for (Parent__c prt : [select name from Parent__c pt])
parents.add(new selectOption(prt.id, prt.name));
return parents;
}
private set;
}
}
Because the parents List in the extension sends an ID to the application, it can successfully create a record with the parent Name in the picklist, but the ID in the background. You can also substitute a different field for Name: If you prefer, put a contact’s email address or anything else. Try it out!
One more thing: This is an easy segue into another project, which will be a way to use the traditional lookup interface but to pre-filter the records available in the lookup.
And because I put this in every post: There’s a catch. (There always is.) I’m sure that somewhere in there, Salesforce would prefer that we not create a picklist of a few hundred items. So please feel free to test the limits of this visualforce method, but please be prepared to filter your SOQL query.
On a separate note, I just had lunch with John Rotenstein aka The Enforcer, who already put up a photo of our time in his office. (I think the pirate logo was an accident, but it does add to my sinister persona, no?)
Salesforce Order of Execution
I came across this page in the Apex documentation and wanted to share it with everyone. So many people have asked about this in the past, so it seems a good idea to publicize it:
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_order_of_execution.htm
Triggers and Order of Execution
When a record is saved with an insert, update, or upsert statement, the following events occur in order:
1. The original record is loaded from the database (or initialized for an insert statement)
2. The new record field values are loaded from the request and overwrite the old values
3. All before triggers execute
4. System validation occurs, such as verifying that all required fields have a non-null value, and running any user-defined validation rules
5. The record is saved to the database, but not yet committed
6. All after triggers execute
7. Assignment rules execute
8. Auto-response rules execute
9. Workflow rules execute
10. If there are workflow field updates, the record is updated again
11. If the record was updated with workflow field updates, before and after triggers fire one more time (and only one more time)
12. Escalation rules execute
13. All DML operations are committed to the database
14. Post-commit logic executes, such as sending email
Additional Considerations
Please note the following when working with triggers:
* When Enable Validation and Triggers from Lead Convert is selected, if the lead conversion creates an opportunity and the opportunity has Apex before triggers associated with it, the triggers run immediately after the opportunity is created, before the opportunity contact role is created. For more information, see “Customizing Lead Settings” in the Salesforce online help.
* If you are using before triggers to set Stage and Forecast Category for an opportunity record, the behavior is as follows:
o If you set Stage and Forecast Category, the opportunity record contains those exact values.
o If you set Stage but not Forecast Category, the Forecast Category value on the opportunity record defaults to the one associated with trigger Stage.
o If you reset Stage to a value specified in an API call or incoming from the user interface, the Forecast Category value should also come from the API call or user interface. If no value for Forecast Category is specified and the incoming Stage is different than the trigger Stage, the Forecast Category defaults to the one associated with trigger Stage. If the trigger Stage and incoming Stage are the same, the Forecast Category is not defaulted.
Upcoming Plans
This is my first blog post since Dreamforce 2008, and I had an amazing time. Hello to everyone I met, and hello to all the people that I said I’d meet - but couldn’t. I left Dreamforce and came to Sydney to visit my family, and am writing this blog post sitting on a deck chair under a setting sun, listening to my niece and nephew play nicely.
This blog post is partly an announcement of X-Squared’s upcoming plans and projects, and partly a way to hold myself to my word. It is said that while managing the Yankees, Joe Torre tried to quit many times, until someone bet him $1000 that he couldn’t quit… and told everyone he knew about the bet. Clearly, $1000 is small change to Torre, but the pressure of the whole world knowing his plan to quit helped him quite a bit. So here is X-Squared On Demand’s list of projects and plans (outside of the standard billing work for our amazing clients):
Jon Mountjoy suggested that I pick one Salesforce development feature and learn it completely instead of making the mistake of trying to learn everything and doing it all poorly. I chose Visualforce. All my side projects from now on will involve Visualforce to some degree.
- Lookup to Picklist: I’ve always been interested in lookup fields and have written some interesting implementations that use error messages and custom buttons to simplify and focus allowed values for lookups. Here, I plan to present the user with a list of all the target records available and to present them in a picklist. (Of course, if there are more than 50 records, I will leave the field as a lookup.)
- Filtered Lookup: I have the code for a filtered lookup that utilizes a three-page wizard to choose the proper record for a lookup, but I want to simplify this to allow an administrator to limit a lookup to one Record Type or any other hard-coded filter. Then I’ll use a simplified wizard to enhance that feature, which would basically be like using the lookup filters in Enhanced Lookups currently available in the standard UI.
- NonProfit EventForce using Google Sites: We started this project at Dreamforce 2008, and I have a non-profit client who would like a tool to allow registration for various kinds of events. This is a super opportunity to expand upon this hackathon project. Colin Loretz has agreed to help on this, and Steve Wright of Salesforce.com Foundation has offered to provide a salesforce.com technical resource if we make the code open-source. I told Steve that in my mind I was writing the code for the Foundation, and that the Foundation could do whatever it wanted with the code. So keep an eye out for this in the next month or two.
- Airport Codes to Full Name of the airport when entered into a field, using Visualforce.
- SIC to NAICS: I have NO idea why Salesforce CRM is so attached to SIC codes–after all, the government has completed its changeover to NAICS codes. I plan to use the existing conversion charts provided by the government to allow orgs to convert their data from SIC to NAICS.
- Google Maps as a Data Enrichment Tool: Input the ZIP Code, and Google Maps will return a city/state. Or input the Street and City/State, and Google Maps will return the ZIP Code. Sorry, DemandTools and Postcode Anywhere, this might cut into your profit margin.
- Drop.io for AppExchange: I love drop.io as a file sharing and storage tool, and with the release of their API–and Ron Hess’s explanation of his XMLDom Apex Class, it may be time to create a nice app allowing 100MB of storage per record in Salesforce CRM. It might require a couple of hacks before it can be used for more than standard objects, but this will likely be my ongoing work in progress.
- Use Amazon EC2 Windows to put the Workbench in the Cloud.
- And finally, I will spend the next year making a list of everyone I want to meet at Dreamforce 2009, and will find a way to see everyone there!
There are probably many more ideas sketched on napkins and pads of paper around my office, but this is a beginning list of projects I’m most passionate about. If anyone would like to help with any, please let me know!
X-Squared at Dreamforce 2008
Please be sure to register for sessions at Dreamforce.
And DEFINITELY don’t miss my session!
Wrangle Data & Pump up the Configuration
“I’m administering Salesforce. I’ve learned the ropes. Now I want to get great!” In this session, we’ll review the latest insights and subtlties that top Salesforce consultants have learned on the front lines. We’ll focus on data and configuration to help cut the time you spend massaging data. You’ll also learn how to implement tricky config quirks you never thought possible.
Speaker: Ezra Kenigsberg, SALESFORCE.COM
Speaker: David Schach, X-Squared On Demand LLC
Date: Monday, November 3
Time: 11:45 a.m. - 12:45 p.m.
I’m on the Administrator track - we’ll be providing tips for configuring your org implementation and optimizations, and for ensuring that things remain smooth as you move forward as a Super Administrator.
Salesforce CRM “Locale” Field
Most of the people reading this are probably in the United States, so on our User record, we have Locale set to “English (US).” This has a few effects on how we see Salesforce data, including the Calendar.
I wanted to change the first day of my week to Monday, and to see my weekends on the right-side of the 7-day view. I’ve started doing this on my Google and Outlook calendars, so why not be consistent? To do this, I changed my Locale to “English (United Kingdom).”
There’s a catch (there always is!): My dates are now reversed. D’Oh!
Time will tell if I have any other major changes to the org. I don’t mind British spellings (colour vs. color) — though I’ve found the word “color” three times since I switched. The org currency will remain US Dollars, as that is set elsewhere, in the Company Profile.
So what will I do, on the whole? I need to decide if the date format is more or less important than the week format. I’ll try out this UK thing… and will decide later.




