How to Invoke VF page render as PDF from batch Apex - salesforce

I want to call the vf page controller from an Batch apex. but i am getting the following error
enter image description here
VF page controller
public with sharing class QuoteToPDFControllerdownload {
....
public QuoteToPDFControllerdownload() {
}
public QuoteToPDFControllerdownload(ApexPages.StandardController controller) {
quoteRecord = [
SELECT ID, Name, OpportunityId, Status, Subtotal, Design_Basis__c, Exclusions__c,
Special_Notes__c, Account.Company__r.Address_1__c, Account.Company__r.Address_2__c,
Account.Company__r.Address_3__c, Account.Company__r.Address_4__c,Account.CustomerCodeIFS__c , Tax, Discount,
Global_Discount__c, Absolute_Discount__c, TotalPrice, Contact_Info__c,
Opportunity.Salesman__r.Name, Opportunity.Salesman__r.MobilePhone, Opportunity.Salesman__r.Email,
Opportunity.Company__r.Address_1__c, Opportunity.Company__r.Address_2__c,
Opportunity.Company__r.Address_3__c, Opportunity.Company__r.Address_4__c,
Opportunity.Company__r.Name, Opportunity.Company__r.Company__c,
Opportunity.New_Customer_Name__c,Opportunity.New_Customer_address__c,Opportunity.New_Customer_Address_2__c,Opportunity.New_Customer_Address_3__c, Opportunity.Name, Opportunity.CreatedDate
FROM Quote
WHERE Id = :controller.getId()
];
String fileName = 'Quote_' + quoteRecord.Opportunity.Name + '.pdf';
ApexPages.currentPage().getHeaders().put('content-disposition', 'attachment; filename=' + fileName);
}
VF page
<apex:page standardController="Quote" extensions="QuoteToPDFControllerdownload" showHeader="false" standardStylesheets="false"
applyBodyTag="false" applyHtmlTag="false" docType="html-5.0"
action="{! saveToPdf }" readOnly="false" renderAs="PDF">
.....
</apex:page>
Batch Class
public class QuoteToPDFBatchDownload implements Database.Batchable, Database.Stateful {
public Integer recordsProcessed = 0;
public Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator([
SELECT ID, Opportunity_Number__c FROM Quote WHERE SentToIFS__c =TRUE
]);
}
public void execute(Database.BatchableContext bc, List scope){
for (Quote qt : scope) {
// PageReference pr = New PageReference('/apex/culliganReortDownload?id=' + qt.id );
ApexPages.StandardController sc = new ApexPages.StandardController(qt);
QuoteToPDFControllerdownload qd = new QuoteToPDFControllerdownload(sc);
recordsProcessed = recordsProcessed + 1;
}
}
public void finish(Database.BatchableContext bc){
System.debug(recordsProcessed + ' records processed. Ayesha!');
}
}

I suggest you can try using the following statement, in Apex, in a custom controller, to access the id which you are passing via Batch class:
ApexPages.currentPage().getParameters().get('id');
Please let me know if it helps you out.
Thanks.

Related

Why can't I return a List<Account> or an array of wrappers?

I would like to display a list of Accounts or Account wrappers in my VF page. I have a controller that works for a LWC and would like to add methods for a VF page, as well, that does pretty much the same thing. I have a very simple VF page that I nearly copied from the developer guide, and Salesforce wants to create a method that just returns a String, but I want to return a list of accounts. For now, I am just trying to pass in some fixed parameters. Can anyone tell me what is wrong here?
Page:
<apex:page docType="html-5.0" controller="AccountTypeAheadSearchHelper">
<h1>Account Type-Ahead Search Demo VF</h1>
<apex:outputLink value="{!URLFOR($Action.Account.View,'0018c00002N0qccAAB')}">Open this Account</apex:outputLink>
<apex:form >
<apex:actionFunction name="onKeyUpHandler" action="{!onKeyUpHandlerVF}">
<apex:param name="currentValue" assignTo="{!accountSearchVF}" value="" />
</apex:actionFunction>
<div>
<apex:inputText label="Search for account" id="theAccountName" value="{!accountSearchVF}" onkeyup="onKeyUpHandler(document.getElementById({!$Component.theAccountName}).nodeValue);" />
</div>
<apex:commandButton action="{!saveVF}" value="Save" id="theSaveButtonVF" />
</apex:form>
<apex:pageBlock title="Matching Accounts" mode="view">
<apex:dataList value="{!matchingAccountsVF}" var="matchingAccount" >
<apex:outputText value="{!matchingAccount.Name}" />
</apex:dataList>
</apex:pageBlock>
</apex:page>
Controller:
public with sharing class AccountTypeAheadSearchHelper {
private String accountSearchVFValue = 'Enter an account name';
/**
* Given a searchString, returns an array of MatchingAccountsWrappers for the LWC to consume
*
* #param searchString a part of the name of the account to search for
*
* #return an array of MatchingAccountsWrappers
*/
#AuraEnabled
public static MatchingAccountsWrapper[] getMatchingAccounts(String searchString, Boolean showContacts) {
String searchSpec = '%' + searchString + '%';
List<Account> accountsFound;
if (showContacts) {
accountsFound = [
SELECT Id, Name,
(SELECT Id, Name FROM Contacts ORDER BY Name)
FROM Account
WHERE Name LIKE :searchSpec
ORDER BY Name];
} else {
accountsFound = [
SELECT Id, Name
FROM Account
WHERE Name LIKE :searchSpec
ORDER BY Name];
}
List<MatchingAccountsWrapper> matchingAccounts = new List<MatchingAccountsWrapper>();
for (Account ma : accountsFound) {
MatchingAccountsWrapper mar = new MatchingAccountsWrapper(ma.Id, ma.Name, showContacts ? ma.Contacts: null);
matchingAccounts.add(mar);
system.debug('### matching account.name = ' + ma.Name);
}
return matchingAccounts;
}
public List<Account> getMatchingAccountsVF(String searchString, Boolean showContacts) {
String searchSpec = '%' + searchString + '%';
List<Account> accountsFound;
if (showContacts) {
accountsFound = [
SELECT Id, Name,
(SELECT Id, Name FROM Contacts ORDER BY Name)
FROM Account
WHERE Name LIKE :searchSpec
ORDER BY Name];
} else {
accountsFound = [
SELECT Id, Name
FROM Account
WHERE Name LIKE :searchSpec
ORDER BY Name];
}
return accountsFound;
}
public PageReference saveVF() {
system.debug('### AccountTypeAheadSearchHelper:saveVF() method');
return null;
}
public String accountSearchVF {
get {
system.debug('### AccountTypeAheadSearchHelper:accountSearchVF() getter: accountSearchVFValue = ' + accountSearchVFValue);
return accountSearchVFValue;
}
set {
system.debug('### AccountTypeAheadSearchHelper:accountSearchVF() setter: value = ' + value);
accountSearchVFValue = value;
}
}
public void onKeyUpHandlerVF() {
system.debug('### AccountTypeAheadSearchHelper:onKeyUpHandlerVF(): BEGIN');
system.debug('### AccountTypeAheadSearchHelper:onKeyUpHandlerVF(): accountSearchVFValue = ' + accountSearchVFValue);
MatchingAccountsWrapper[] mars = getMatchingAccounts(accountSearchVFValue, false);
system.debug('### AccountTypeAheadSearchHelper:onKeyUpHandlerVF(): END');
}
private class MatchingAccountsWrapper {
public MatchingAccountsWrapper(String k, String n) {
key = k;
name = n;
}
public MatchingAccountsWrapper(String k, String n, List<Contact> c) {
key = k;
name = n;
relatedContacts = c;
}
public MatchingAccountsWrapper(Account a) {
key = a.Id;
name = a.Name;
}
#AuraEnabled
public string key {get; set;}
#AuraEnabled
public string name {get; set;}
#AuraEnabled
public string link {get {
return URL.getSalesforceBaseUrl().toExternalForm() + '/' + this.key;
} set;}
private List<Contact> relatedContacts {get; set;}
#AuraEnabled
public List<MatchingContactsWrapper> contacts {get {
if (relatedContacts != null) {
List<MatchingContactsWrapper> matchingContacts = new List<MatchingContactsWrapper>();
for (Contact matchingContact : relatedContacts) {
MatchingContactsWrapper mac = new MatchingContactsWrapper(matchingContact);
matchingContacts.add(mac);
}
return matchingContacts;
} else {
return null;
}
} set;}
}
private class MatchingContactsWrapper {
public MatchingContactsWrapper(Contact c) {
key = c.Id;
name = c.Name;
}
#AuraEnabled
public string key {get; set;}
#AuraEnabled
public string name {get; set;}
#AuraEnabled
public string link {get {
return URL.getSalesforceBaseUrl().toExternalForm() + '/' + this.key;
} set;}
}
}
I think I really should be able to use the same getMatchingAccounts method that I use for the LWC, have also tried getMatchingAccountsVF. But it tells me that it doesn't exist in the controller. When I let Salesforce create the method, I makes a Public String method. I don't understand why it is making a String method.
The form part is not even relevant here, just the pageblock with the datalist in it. I would like to call "{!matchingAccountsVF('st', false)}" as a starting point and then pass in actual parameters from the user, but this doesn't work.
I am basing this on the very simple example I see here: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_dataList.htm
You can reuse Apex written for Aura/LWC in VF but the main difference is "state". Aura and LWC are stateless, you pass everything you need to server (or query it fresh) explicitly and the methods have to be static (btw your #AuraEnabled could really use cacheable=true). In Visualforce state is passed silently for you in a hidden encoded variable. All variables (except the ones declared transient) will be passed from the page to apex and class' internal state will be reconstructed.
You need a kind of autocomplete, right? You have few ways to do it. (Plus there are lots of examples on the net) Depends if you want it "pure Visualforce way" with that syntax or you're more comfortable with doing everything in JS.
completely reuse your component (read up about "Lightning Out")
call the javascript similar to LWC (as a static function, lightweight, mobile-friendly) with "Remoting". It's bit old and I guess you could say it's early version of Aura - JavaScript function, handle the response in JS (not VF), rebuild your list of accounts in JS.
call the server side code "old school visualforce" - with full resubmit of the form (or onKeyUp, doesn't matter). The key thing will be that parameter will be passed as part of that whole viewstate thing. And then your getMatchingAccountsVF doesn't need parameters, it becomes pure getter. It'll just rely on normal class variable with the search term.
public class Stack73082136 {
// Service part (static, useable in Aura/LWC but eventually maybe also as a REST service)
// This method would typically throw exceptions, perhaps AuraHandledException
#RemoteAction #AuraEnabled(cacheable=true)
public static MatchingAccountsWrapper[] getMatchingAccounts(String searchString, Boolean showContacts) {
String searchSpec = '%' + searchString + '%';
List<Account> accountsFound;
if (showContacts) {
accountsFound = [
SELECT Id, Name,
(SELECT Id, Name FROM Contacts ORDER BY Name)
FROM Account
WHERE Name LIKE :searchSpec
ORDER BY Name];
} else {
accountsFound = [
SELECT Id, Name
FROM Account
WHERE Name LIKE :searchSpec
ORDER BY Name];
}
List<MatchingAccountsWrapper> matchingAccounts = new List<MatchingAccountsWrapper>();
for (Account ma : accountsFound) {
MatchingAccountsWrapper mar = new MatchingAccountsWrapper(ma.Id, ma.Name, showContacts ? ma.Contacts: null);
matchingAccounts.add(mar);
system.debug('### matching account.name = ' + ma.Name);
}
return matchingAccounts;
}
// Visualforce part (old school, stateful)
// This would typically not throw exceptions but ApexPages.addMessage() etc.
// (which means that non-VF context like a trigger, inbound email handler or code called from Flow would crash and burn at runtime; in these you can only do exceptions)
public String searchValue {get;set;}
public List<MatchingAccountsWrapper> getMatchingAccountsVF() {
return getMatchingAccounts(searchValue, false);
}
public void onKeyUpHandlerVF() {
system.debug('### AccountTypeAheadSearchHelper:onKeyUpHandlerVF(): BEGIN');
system.debug('### AccountTypeAheadSearchHelper:onKeyUpHandlerVF(): accountSearchVFValue = ' + searchValue);
// do nothing. this method is "stupid", it's only job is to be called, pass the parameter and then the getMatchingAccountsVF
// will be called by VF engine when it needs to rerender {!matchingAccountsVF} expression
}
private class MatchingAccountsWrapper {
public MatchingAccountsWrapper(String k, String n) {
key = k;
name = n;
}
public MatchingAccountsWrapper(String k, String n, List<Contact> c) {
key = k;
name = n;
relatedContacts = c;
}
public MatchingAccountsWrapper(Account a) {
key = a.Id;
name = a.Name;
}
#AuraEnabled
public string key {get; set;}
#AuraEnabled
public string name {get; set;}
#AuraEnabled
public string link {get {
return URL.getSalesforceBaseUrl().toExternalForm() + '/' + this.key;
} set;}
private List<Contact> relatedContacts {get; set;}
#AuraEnabled
public List<MatchingContactsWrapper> contacts {get {
if (relatedContacts != null) {
List<MatchingContactsWrapper> matchingContacts = new List<MatchingContactsWrapper>();
for (Contact matchingContact : relatedContacts) {
MatchingContactsWrapper mac = new MatchingContactsWrapper(matchingContact);
matchingContacts.add(mac);
}
return matchingContacts;
} else {
return null;
}
} set;}
}
private class MatchingContactsWrapper {
public MatchingContactsWrapper(Contact c) {
key = c.Id;
name = c.Name;
}
#AuraEnabled
public string key {get; set;}
#AuraEnabled
public string name {get; set;}
#AuraEnabled
public string link {get {
return URL.getSalesforceBaseUrl().toExternalForm() + '/' + this.key;
} set;}
}
}
<apex:page docType="html-5.0" controller="Stack73082136">
<h1>Account Type-Ahead Search Demo VF</h1>
<apex:form >
<apex:pageBlock title="1. Total old school">
<apex:actionRegion>
<apex:inputText value="{!searchValue}" label="type and click" />
<apex:commandButton action="{!onKeyUpHandlerVF}" rerender="out1" />
<apex:outputPanel id="out1">
<apex:dataList value="{!matchingAccountsVF}" var="acc" >
<apex:outputText value="{!acc.Name}" />
</apex:dataList>
</apex:outputPanel>
</apex:actionRegion>
</apex:pageBlock>
<apex:actionFunction action="{!onKeyUpHandlerVF}" name="onKeyUpJS" rerender="out2">
<apex:param name="param1" assignTo="{!searchValue}" value="" />
</apex:actionFunction>
<apex:pageBlock title="2. Old school (viewstate, not mobile friendly) but at least onkeyup">
<!-- this is bit rubbish, fires immediately. Realistically you probably want some delay, wait till user stops typing. -->
<apex:actionRegion>
<apex:inputText value="{!searchValue}" label="type and wait" onkeyup="onKeyUpJS(this.value);"/>
<apex:outputPanel id="out2">
<apex:dataList value="{!matchingAccountsVF}" var="acc" >
<apex:outputText value="{!acc.Name}" />
</apex:dataList>
</apex:outputPanel>
</apex:actionRegion>
</apex:pageBlock>
<script>
function callRemote(term){
// call static method in ClassName.methodName format
Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.Stack73082136.getMatchingAccounts}',
term,
false, // no contacts pls
function(result, event){
if (event.status) {
//debugger;
let target = document.getElementById("out3");
while (target.firstChild) {
target.removeChild(target.firstChild);
}
result.forEach(item => target.append(item.key + ': ' + item.name + ';'));
} else if (event.type === 'exception') {
document.getElementById("responseErrors").innerHTML =
event.message + "<br/>\n<pre>" + event.where + "</pre>";
} else {
document.getElementById("responseErrors").innerHTML = event.message;
}
},
{escape: true}
);
}
</script>
<apex:pageBlock title="3. VF remoting, the grandfather of Aura. No viewstate, pure html and js">
<input type="text" id="text3" label="type and vait v2" onkeyup="callRemote(this.value)" />
<div id="out3"></div>
<div id="responseErrors"></div>
</apex:pageBlock>
</apex:form>
</apex:page>

need help on how to achieve 100% in the test class

I have been trying to write test class for 100% coverage. I have difficulty in understanding how to call the standard controller and call the parameterised constructor also set the page to the current page as the current page.
On the account view page, I have overridden the new button on the related list of a custom object. I am able the use the same class when I edit the record. On both the edit record view page and the new record view page I am able to retrieve the account id. Currently I am able achieve 65% coverage. I am not sure what am I doing wrong. Please help if possible. I have attached the code below.
Thanks
Gayatri
//my Class
public class NewTaxExempt{
public TaxExempt__c obj {get; set;}
public String selectedIso {get;set;}
public List<selectOption> isoCodes {
get {
List<selectOption> options = new List<selectOption>();
for (State__c iso : State__c.getAll().values())
options.add(new SelectOption(iso.State_ISO__c,iso.State_Name__c+' - '+iso.State_ISO__c));
return options;
}
set;
}
// onload standard controller will be called.
public NewTaxExempt(ApexPages.StandardController controller) {
ID idte=controller.getRecord().id;
if(idte==null){
obj=(TaxExempt__c)controller.getRecord();
}
else{
obj= [Select Account__c, Certificate_ID__c, Certificate_Type__c,Description__c, Issuing_Jurisdiction__c,Status__c,Tax_Exempt_Effective_Date__c,Tax_Exempt_Expiration_Date__c from TaxExempt__c where id=:idte];
}
}
//on click on cancel button
public PageReference cancel() {
return new PageReference('/'+obj.account__c);
}
//on click on Save button
public PageReference save() {
obj.Issuing_Jurisdiction__c=selectedIso;
if(obj.id==null){
insert obj;
}
else{
update obj;
}
return new PageReference('/'+obj.account__c);
}
}
//my test class
#isTest
public class NewTaxExemptTest{
public static testMethod void whenIssueJurisdictionIsBlankDefaultValueIsSet(){
try{
BET_ObjectFactory.generateTaxExemptRequirements();
Account aobj = ( Account)TestFactory.createSObject(new Account(Name='test acc gs250144'),true);
PageReference ref = Page.NewTaxExempt;
Test.setCurrentPage(ref);
TaxExempt__c obj=new TaxExempt__c();
obj.account__c=aobj.Id;
obj.Issuing_Jurisdiction__c='RI';
ApexPages.StandardController sc = new ApexPages.StandardController(obj);
NewTaxExempt ob=new NewTaxExempt(sc);
ob.selectedIso='RI';
ob.obj=obj;
ob.save();
System.assertEquals(obj.Issuing_Jurisdiction__c,null);
List<State__c> stList=new List<State__c>();
State__c st=new State__c();
st.Name='ST_11009';
st.State_Name__c='Alabama';
st.State_ISO__c='AL';
st.State_Country_Name__c='United States';
st.State_Country_ISO__c='US';
stList.add(st);
State__c st1=new State__c();
st1.Name='ST_11008';
st1.State_Name__c='Alabama';
st1.State_ISO__c='AL';
st1.State_Country_Name__c='United States';
st1.State_Country_ISO__c='US';
stList.add(st1);
State__c st2=new State__c();
st2.Name='ST_11019';
st2.State_Name__c='Alaska';
st2.State_ISO__c='AK';
st2.State_Country_Name__c='United States';
st2.State_Country_ISO__c='US';
stList.add(st2);
State__c st3=new State__c();
st3.Name='ST_12009';
st3.State_Name__c='Arizona';
st3.State_ISO__c='AZ';
st3.State_Country_Name__c='United States';
st3.State_Country_ISO__c='US';
stList.add(st3);
State__c st4=new State__c();
st4.Name='ST_11309';
st4.State_Name__c='Arkansas';
st4.State_ISO__c='AR';
st4.State_Country_Name__c='United States';
st4.State_Country_ISO__c='US';
stList.add(st4);
State__c st5=new State__c();
st5.Name='ST_21009';
st5.State_Name__c='California';
st5.State_ISO__c='CA';
st5.State_Country_Name__c='United States';
st5.State_Country_ISO__c='US';
stList.add(st5);
State__c st6=new State__c();
st6.Name='ST_23';
st6.State_Name__c='California';
st6.State_ISO__c='';
st6.State_Country_Name__c='';
st6.State_Country_ISO__c='';
stList.add(st6);
insert stList;
List<State__c> allStates = [select State_Name__c, State_ISO__c, State_Country_Name__c, State_Country_ISO__c
from State__c
order by State_Name__c];
for(State__c stt : allStates){
if(stt.State_ISO__c == '' || stt.State_ISO__c == null){
ob.isoCodes.add(new SelectOption(stt.State_ISO__c, stt.State_Name__c));
}
else{
ob.isoCodes.add(new SelectOption(stt.State_ISO__c, stt.State_Name__c));
}
}
System.assertNotEquals(ob.isoCodes.size(),0);
}catch(Exception e){
System.debug('Gayatri exception :'+e);
}
}
public static testMethod void whenUserClicksCancel(){
BET_ObjectFactory.generateTaxExemptRequirements();
Account aobj = ( Account)TestFactory.createSObject(new Account(Name='test acc gs250144'),true);
// PageReference ref = new PageReference(pageName)
// ref.getParameters().put('TaxExempt__c',obj.Id);
// Test.setCurrentPage(ref);
PageReference ref = Page.NewTaxExempt;
Test.setCurrentPage(ref);
TaxExempt__c obj=new TaxExempt__c();
ApexPages.StandardController sc = new ApexPages.StandardController(obj);
NewTaxExempt ob=new NewTaxExempt(sc);
ob.cancel();
}
}
it's gonna be much easier if you knew what part of your code is missing in test coverage.
Go to developer console and run your test
on the bottom of the page select test tab
find your test from the right side (with title: Overall code coverage)
double click on your test
uncovered part will be in red. now try to write tests for them.
If you want to cover your class properties all you have to do is this:
#isTest static void myPropertiesTest(){
MyClass obj = new MyClass();
obj.myProperty = SomeValue;
// now assert a function in you class that uses this property.
// an easy and dumb way is to just assert the property.
System.assertEquals(SomeValue, obj.myProperty);
}

Populating SelectList with sobject

I am trying to create a class that will populate the a multi selectlist depending on what URL parameters are passed in.
Im having trouble. The slectlist never renders, however, looking through the debugger, i can see that records are found and that it should populate.
Am I missing something stupid?
VisualForce.Page
<apex:page controller="PopUp">
<apex:form >
<apex:selectList value="{!objectType}" multiselect="true">
<apex:selectOptions value="{!SelectListOptions}"/>
</apex:selectList>
</apex:form>
Controller class:
public with sharing class PopUp {
public sObject objParameter {get;set;}
public string fldParameter {get;set;}
public string queryType {get;set;}
public static string objName{get;set;}
public list<SelectOption> selectListOptions {get;set;}
public static list<string> TEST {get;set;}
public String[] objectType= new String[]{};
public PopUp(){
objName = ApexPages.currentPage().getParameters().get('obj');
sObject dynObject = Schema.getGlobalDescribe().get(objName).newSObject() ;
objParameter = dynObject;
fldParameter = ApexPages.currentPage().getParameters().get('fld');
String queryType = ApexPages.currentPage().getParameters().get('qt');
system.debug('***objParameter: ' + objParameter);
system.debug('***fldParameter: ' + fldParameter);
//List<selectOption> L = getPicklistValues(objParameter, fldParameter, queryType);
}
public static list<SelectOption> getPicklistValues(SObject obj, String fld, String queryType)
{
list<SelectOption> options = new list<SelectOption>();
if(queryType == 'soql'){
string query = 'select ' + fld + ' from ' + objName;
system.debug('***query: ' + query);
List<sObject> dynList = Database.query(query);
system.debug('***dynList: ' + dynList);
for(integer i=0;i< dynList.size();i++){
string fldValue = string.valueof(dynList[i].get(fld));
system.debug('***fldValue: ' + fldValue);
options.add(new SelectOption(fldValue,fldValue));
TEST.add(fldValue);
}
}
system.debug('***options: ' + options);
return options;
}
public List<selectOption> getSelectListOptions() {
return getPicklistValues(objParameter, fldParameter, queryType);
}
public String[] getObjectType()
{
return objectType;
}
public void setObjectType(String[] objectType)
{
this.objectType= objectType;
}
I think you're confusing the VF page by having essentially two getter methods (the one you added, and the one you told the controller to create itself by specifying get; in the variable declaration):
public list<SelectOption> selectListOptions {get;set;}
public List<selectOption> getSelectListOptions() {
return getPicklistValues(objParameter, fldParameter, queryType);
}
It doesn't look like you're populating selectListOptions anywhere, so the VF page sees that and doesn't add any options to your picklist. The VF page will only call getSelectListOptions() if it doesn't find a getter for your variable, so modify the selectListOptions declaration like so, and you should be fine:
public List<SelectOption> selectListOptions {set;}
In fact, it doesn't look like your page should have access to set this, so you could remove the setter as well if you wanted.

How do I display the results of an aggregate SOQL query on a Visualforce page?

I'm very new to Visualforce.
I'm looking at this page here: http://force.siddheshkabe.co.in/2010/11/displaying-aggregate-result-on.html
So when I added this code onto a VisualForce page:
AggregateResult[] groupedResults = [SELECT Name, Days__c FROM Contact WHERE Days__c != ];
for (AggregateResult ar : groupedResults) {
System.debug('Name: ' + ar.get('Name') + '\nDays Taken : ' + ar.get('Days__c') + '\n');
But all it does is print the code instead of executing it. What should I be doing? Thanks for any guidance.
The Apex code goes into a custom controller or controller extension. The VisualForce page is a separate file from the controller. The page you referenced doesn't show the VF page. Also, I don't think you can bind VF components to AggregateResult, so you'll need a wrapper class.
Here's some working code.
Controller:
public with sharing class TestController {
public Summary[] Summaries { get; set; }
public TestController() {
AggregateResult[] results = [
SELECT Name, Count(Id) Quantity FROM Opportunity GROUP BY Name
];
Summaries = new List<Summary>();
for (AggregateResult ar : results) {
Summaries.add(new Summary(ar));
}
}
// wrapper class to hold aggregate data
public class Summary {
public Integer Quantity { get; private set; }
public String Name { get; private set; }
public Summary(AggregateResult ar) {
Quantity = (Integer) ar.get('Quantity');
Name = (String) ar.get('Name');
}
}
}
VF page:
<apex:page controller="TestController">
<apex:form >
<apex:repeat value="{!Summaries}" var="summary">
{!summary.Name}: {!summary.Quantity}<br/>
</apex:repeat>
</apex:form>
</apex:page>

Programatically get a list of all workspaces (shared+Personal) in VisualForce Page

I have created a custom visualforce page.
Here in the controller class i want to get a list of all workspaces in a dropdown so that user can make a choice among where to publish the data
Can somebody provide me some guidelines on how to achieve this.
Any help is appreciated.
:)
You need to query the content workspaces and then put them in select option list which can then be referenced in a visualforce page.
Apex Controller:
public Id selectedWorkspaceId { get; set; }
private List<SelectOption> workspaceOptions;
public List<SelectOption> getWorkspaceOptions() {
if(workspaceOptions == null) {
for(ContentWorkSpace workspace : [select id, name from ContentWorkspace]) {
workspaceOptions.addNewSelectOption(
new SelectOption(workspace.id, workspace.name);
}
}
}
return workspaceOptions;
}
Visualforce Page:
<apex:selectList value="{!selectedWorkspaceId}" size="1">
<apex:selectOptions value="{!workspaceOptions}"/>
</apex:selectList>
Documentation:
SelectOption Class
<apex:selectList> component
<apex:selectOptions> Component
ContentWorkSpace object
Below is Java code (from code reciepe) to Query a List of Workspaces in Salesforce CRM Content. Translate below code to apex and it should work.
package com.sforce;
import org.apache.axis.client.Stub;
import com.sforce.soap.enterprise.*;
import com.sforce.soap.enterprise.sobject.*;
public class QueryWorkspace {
/**
* #param args
*/
public static void main(String[] args) {
QueryWorkspace queryWorkspace = new QueryWorkspace();
try {
queryWorkspace.queryAvailableWorkspaces();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
private void queryAvailableWorkspaces() throws Exception {
SforceServiceLocator sforceServiceLocator
= new SforceServiceLocator();
SoapBindingStub binding
= (SoapBindingStub) sforceServiceLocator.getSoap();
// Login
LoginResult lr = binding.login("user#jstest.org",
"password");
binding._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,
lr.getServerUrl());
// Create a session header for subsequent calls
_SessionHeader sessionHeader = new _SessionHeader();
sessionHeader.setSessionId(lr.getSessionId());
binding.setHeader(sforceServiceLocator.getServiceName()
.getNamespaceURI(), "SessionHeader",
sessionHeader);
QueryResult query
= binding.query("select Id, Name from"
+ " ContentWorkspace");
SObject[] records = query.getRecords();
if (records != null) {
for (int i = 0; i < records.length; i++) {
ContentWorkspace contentWorkspace =
(ContentWorkspace)records[i];
System.out.println("Workspace Id:"
+ contentWorkspace.getId() + " Name:"
+ contentWorkspace.getName());
}
}
}
}

Resources