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):

  1. 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.
  2. 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:

  3. 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!

Technorati Tags: , , , ,

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!

Technorati Tags:

Inline Visualforce Page Layouts!

This is huge news!

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

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!

Technorati Tags: , , ,

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!

Technorati Tags: ,

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?)

Technorati Tags: , , , ,

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!

Technorati Tags: , , ,

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.

Technorati Tags: ,

A Super Apex/Visualforce Blog

I recently discovered a blog so chock-full of Apex and Visualforce goodies that I had to mention it.

Sam Arjmandi is a CRM System Analyst/Designer at Open Text in Toronto, and he writes incredible posts sharing some innovative Apex, Visualforce, and AJAX code ideas. He has posts on proper test coverage for Apex (always a difficult topic, and one that salesforce.com has not addressed adequately in its documentation–hint, hint), on actionStatus tags, extensions, controllers, and more.

Check out this blog and subscribe to its feed; anyone even remotely interested in developing on the Force.com platform will find it a huge resource.

Thanks, Sam!

Technorati Tags: , , ,

Winter 09 Full Training Orgs

Sure, prerelease orgs are nice, but something’s always lacking. We have to go in and enable all the cool features, which is nice in that we learn them better, but it’s also nice to get to play in a full-featured org. Salesforce CRM (the new name) has had Exercises to teach us what to do, and I’m sure they will again this time…

Meanwhile, I stumbled upon an even better treat: Winter 09 TRAINING orgs. Yes, orgs with tons of data and all the add-ons you could ever want:
Salesforce Content
Customer Portal
Partner Portal
Advanced Currency Management
Custom Fiscal Year
Translation Workbench (and international Apex features)
Outlook Connect 3.2.501 (new version)
Cool orange highlighting of fields I’m editing in the setup area
Recruiting App
QuotePDF App
Bug Tracking
Time Card (??)
A/R Invoice
…AND all the new stuff from Winter09

Where is this? I’ll tell you:
Standard Prerelease org: https://prerelwww.pre.salesforce.com/form/trial/prerelease_winter09.jsp
Premium Training org: https://prerelwww.pre.salesforce.com/form/trial/training_winter09.jsp

Technorati Tags:

Absentee Voting Forms (Necessary for Dreamforce Attendees)

I realized a while ago that Dreamforce would be on Election Day. Somehow it took a while to register (no pun intended) that I needed to fill in an absentee ballot. But where to get one?

Thankfully, there is a website devoted to absentee ballots, http://www.longdistancevoter.org/. Please go to this site and do what is necessary to fulfill your civic duty.

If you want to vote early, which is slightly different, Reed College has a super website on early voting (updated regularly) with information on each state’s policies.

And if I may, I’ll get on my soapbox now: I was born in South Africa, a country where specific groups of people were not only denied the right to vote, but were denied the right to live in certain areas and pretty much every other right that we have in this country. I became a citizen at age 12 and promised my family that I would always do whatever it took to cast a vote in every election I could. Sadly, I broke my promise when I didn’t vote in the 2004 Presidential election. Yes, Kerry carried Illinois, so in retrospect my vote didn’t “matter,” but I still feel bad about it.

Of note, in Australia, not only is it one’s civic duty to vote, but all citizens are REQUIRED to vote. Yes, that’s right. If they don’t vote, they have penalties!

And this year, absentee ballots are predicted by some to be more important than ever.

So please do two things:

  1. Vote. If you’ll be at Dreamforce, vote absentee. Even if you live in San Francisco, if you don’t want to miss a minute of Dreamforce, you can still vote absentee. You can send in your application pretty much anytime in the month of October, and ballots are due, in general, on Election Day.
  2. Join me at one of the Ballots and Beer (my label, not theirs) parties Tuesday night in San Francisco. I’m planning to find the one with the most non-profit customers and consultants, as I bet we’ll all be cheering for the same candidate.

See you at Dreamforce, as none of us will see each other at the polls.

Technorati Tags:

Next Page →