All lists are iterables. Create a constructor to take the list, and change the interface of your class:
global class DF_BatchToExcessFields implements Database.Batchable<String> {...
Then return the list in the Start method. Here's a great article by AFawcett to help you get the idea:
http://andyinthecloud.com/2013/08/11/batch-worker-getting-more-done-with-less-work/
Iterable<String> i = new List<String> { 'A', 'B', 'C' };
public with sharing class SimpleBatchApex implements Database.Batchable<String> {
public Iterable<String> start(Database.BatchableContext BC) {
return new List<String> { 'Do something', 'Do something else', 'And something more' };
}
public void execute(Database.BatchableContext info, List<String> strings) {
// Do something really expensive with the string!
String myString = strings[0];
}
public void finish(Database.BatchableContext info) {}
}
then try it out in Developer Console
//Process the String's one by one each with its own governor context
Id jobId = Database.executeBatch(new SimpleBatchApex(), 1);
So I made a Map fieldTypeMap and a component to handle the date/datetime format
Here is what I did, maybe it will be usefull for someone else.
Controller
I added the map as an attribute of my inner class into the controller:
// header/type mapping
public Map<String,String> headerTypeMap {get;set;}
I initialize it at the end of the constructor, thanks to this.headers (array of string header/field name), after the queries, like this:
// calculation :
runQueries();
// mapping
this.headerTypeMap = new Map<String,String>();
for(String field : this.headers){
this.headerTypeMap.put(
field,
Schema.getGlobalDescribe().get(objType).getDescribe().fields.getMap().get(field).getDescribe().getType()+''
);
}
Visualforce component
Because I often need to format date and datetime I thought it could be a good idea to create a formating component
So I made a quick and dirty one:
<apex:component controller="FormatedValueController">
<apex:attribute name="dateValue"
type="Date"
assignTo="{!inputDateValue}"
description="input value to formatTodoBlock__c record that contains data"
/>
<apex:attribute name="datetimeValue"
type="Date"
assignTo="{!inputDateTimeValue}"
description="input value to formatTodoBlock__c record that contains data"
/>
{!formatedvalue}
Controller:
public class FormatedValueController {
public Date inputDateValue {get;set;}
public Datetime inputDateTimeValue {get;set;}
public String getFormatedValue(){
String formatedValue = '';
formatedValue += inputDateValue == null ? '' : inputDateValue.format();
formatedValue += inputDateTimeValue == null ? '' : inputDateTimeValue.format();
return formatedValue;
}
}
And a quick&dirty test class too (for code coverage only):
@isTest
global class FormatedValueController_test{
static testMethod void FormatedValueController() {
FormatedValueController c = new FormatedValueController();
Test.startTest ();
c.getFormatedValue();
Test.stopTest();
}
}
100% you-hou ;)
And finally ...
Main Component
Oddly I need to use "{!todoBlock.headerTypeMap[header]}" everywhere, where todoBlock is the instance of my innerclass and header the var of repeat on headers attribute (table with a dynamic number of columns).
I wanted to use an apex variable for each header, kind of:
<apex:variable var="type" value="{!todoBlock.headerTypeMap[header]}" />
but for an unknown reason it just display the last header value in every loop. For example if I have DATE, DATETIME, STRING, it displays STRING, STRING, STRING. Not a big deal to use the full code, it is just less readable.
So here it is :
<apex:outputLabel rendered="{!todoBlock.headerTypeMap[header]=='DATETIME'}">
<c:FormatedValue datetimeValue="{!rec[header]}"/>
</apex:outputLabel>
<apex:outputLabel rendered="{!todoBlock.headerTypeMap[header]=='DATE'}">
<c:FormatedValue dateValue="{!rec[header]}"/>
</apex:outputLabel>
<apex:outputLabel rendered="{!NOT(AND(todoBlock.headerTypeMap[header]=='DATETIME',todoBlock.headerTypeMap[header]=='DATE'))}">
{!rec[header]}
</apex:outputLabel>
Best Answer
Your strategy will work, but your constructor must contain no parameters, and the same goes for your
newInstance()
call. You pass the name of theType
you want to construct into theType.forName
method.You probably will want to implement an
interface
here as well. Something like:You would use the above as follows:
You don't even really need to cache it for simple cases: