Category Archives: SharePoint 2007

Translate choice column values in NewForm, DispForm and EditForm

Change log

25.02.2013 Updated the code and changed the variable “fields” to “localizeFields” to avoid interference with other scripts.


I got a request for a solution for translating choice column values in a form.

This solution changes the text in the drop-down list, radio button or checkbox in NewForm or EditForm, leaving the “value” untouched. In DispForm the field value is “localized” directly.

This means that the text the user sees is changed, but the value that SharePoint sees is the original. This means that the value shown in the form is localized, but the value stored in the SharePoint list when saving the form is not.

Add this code to a CEWP or HTML Form web part BELOW the list form web part in NewForm, DispForm and EditForm of your list.

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
var translationSettings = {
					"MyDropDownMenu":
						{
							"Yes":{"1044":"Ja","default":"Yes"},
							"No":{"1044":"Nei","default":"No"}
						},
					"MyMultiChoice":
						{
							"Choice 1":{"1044":"Valg 1","default":"Choice 1"},
							"Choice 2":{"1044":"Valg 2","default":"Choice 2"},
							"Choice 3":{"1044":"Valg 3","default":"Choice 3"}
						}
					};

var localizeFields = init_fields_v2();
var isDispForm = $("input:button[id$='SaveItem']").length===0;

$.each(translationSettings,function(fin,t){
	if(localizeFields[fin] !== undefined){
		var fType, arr, txt, tTxt;
		fType = "";
		txt = "";
		tTxt = "";
		if($(localizeFields[fin]).attr("fieldtype") === "SPFieldChoice"){
			if(!isDispForm){
				if($(localizeFields[fin]).find("select").length > 0){
					fType = "select";
				}else if($(localizeFields[fin]).find("select").length === 0 && $(localizeFields[fin]).find("input:radio").length > 0){
					fType = "radio";
				}
			}else{
				fType = "dispform";
			}
		}else if($(localizeFields[fin]).attr("fieldtype") === "SPFieldMultiChoice"){
			if(!isDispForm){
				fType = "multichoice";
			}else{
				fType = "dispform";
			}
		}else{
			return;
		}
		switch(fType){
			case "dispform":
				arr = $(localizeFields[fin]).find('.ms-formbody').text().replace(/[ xA0]+$/,'').split("; ");
				tTxt = [];
				$.each(arr,function(i,txt){	
					if(t[txt] !== undefined){
						tTxt.push(t[txt][L_Menu_LCID] !== undefined ? t[txt][L_Menu_LCID] : t[txt]["default"]);
					}
				});
				$(localizeFields[fin]).find('.ms-formbody').text(tTxt.join("; "));
			break;
			case "select":				
				$(localizeFields[fin]).find("select option").each(function(i,opt){
					txt = $(this).text();
					if(t[txt] !== undefined){
						tTxt = t[txt][L_Menu_LCID] !== undefined ? t[txt][L_Menu_LCID] : t[txt]["default"];
						$(this).text(tTxt);
					}
				});
			break;
			case "radio":
			case "multichoice":
				$(localizeFields[fin]).find("input").each(function(i,opt){
					txt = $(this).next().text();
					if(t[txt] !== undefined){
						tTxt = t[txt][L_Menu_LCID] !== undefined ? t[txt][L_Menu_LCID] : t[txt]["default"];
						$(this).next().text(tTxt);
					}
				});
			break;
		}
	}
});

// This function is found in spjs-utility.js and can be removed from here if you already have referred this library.
function init_fields_v2(){
	var res = {};
	$("td.ms-formbody").each(function(){
	var myMatch = $(this).html().match(/FieldName="(.+)"s+FieldInternalName="(.+)"s+FieldType="(.+)"s+/);	
		if(myMatch!=null){
			// Display name
			var disp = myMatch[1];
			// FieldInternalName
			var fin = myMatch[2];
			// FieldType
			var type = myMatch[3];
			if(type=='SPFieldNote'){
				if($(this).find('script').length>0){
					type=type+"_HTML";
				}else if($(this).find("div[id$='_TextField_inplacerte']").length>0){
					type=type+"_EHTML";
				}				
			}
			if(type=='SPFieldLookup'){
				if($(this).find('input').length>0){
					type=type+"_Input";
				}
			}
			// Build object
			res[fin] = this.parentNode;
			$(res[fin]).attr('FieldDispName',disp);
			$(res[fin]).attr('FieldType',type);
		}		
	});
	return res;
}
</script>

The translation is set up in the variable “translationSettings” like this:
var translationSettings = {
“FieldInternalName”:
{
“Actual value 1”:{“1044″:”Norwegian value 1″,”default”:”Default value 1″},
“Actual value 1”:{“1044″:”Norwegian value 1″,”default”:”Default value 2″}
}
};

You can add alternate languages by using the LCID. The selected LCID must be among the installed language packs on your SharePoint server.

Ask if something is unclear.

Alexander

Lookup column relinker – cross site – for SharePoint 2007 and SharePoint 2010 – using JavaScript

Change log
May 28, 2014
Changes in v1.1 for SP 2010 / 13 and v1.2 for SP 2007:
Fixed a bug where the list guid was not wrapped using curly braces. This made Microsoft Word fail to load the document information panel when you had a cross site lookup column in that library. To fix this, relink the lookup column again using the updated version.

I have previously posted a solution that, among other features, lets you relink a lookup column. This article introduces a new tool that does lookup column relinking only.

SharePoint 2007
IMG

SharePoint 2010
IMG

Get the code here, and ensure you use the correct version.

The difference between the 2007 and the 2010 version is that in 2007, you must place the code in a web part in the site where the lookup column resides.

You can target another site, but must run the code in the site where the column you want to alter is located.

In the 2010 version, you can change the source web as long as you target a web within the site collection.

If you like the solution, buy me a beer using the Beer button on the top right of this page.

Alexander

SPJS Charts for SharePoint update 20.09.2012

27.09.2012 v3.3.6 includes these changes:

  • Changed the method for caching the filter values when loading the charts and changing the filter dropdowns. This should fix any errors when you have multiple filtered charts in one page.
  • Added option to override “chart options” set in the GUI by adding an object to the CEWP like this:
    var chartOptionOverride = {&quot;MyChart1&quot;:{&quot;title&quot;:&quot;This is the chart title!&quot;}};
    

See the CEWP code example for v3.3.6 in the download section


In v3.3.5 I have added these features:

  1. Changed the way the chart and the accessories are rendered to keep all items within the “chart container”. This helps in positioning the charts in the page.
  2. Added option to load the chart manually.
  3. Added option to display a placeholder / overlay when the chart is loading. This will prevent the page from looking like it has frozen while loading a heavy chart. The page is still unresponsive – but at least it looks better.
1.

What happens under the hood is that the chart is created in a separate container – dynamically created within the container defined in the CEWP. For those interested, this container is named containerId_chart. Where “containerId” is the id defined in the array “arrOfChartContainers” in the CEWP.

2.

You can delay the loading of the chart by 4000ms (4 seconds) like this:

&lt;div id=&quot;MyChart1&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
/*****************************************************
		Address all containers
*****************************************************/
// All charts must be represented by a container with a unique id. 
// This container  must be present in the page
var arrOfChartContainers = [&quot;MyChart1&quot;];
var loadRC = false;
var allowEval = false;

var loadManually = true;
function manualLoad(){
	loadManually = false;
	spjs_GenerateChart();
}

setTimeout(function(){
	manualLoad();
},4000);

&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Charts/Javascript/3.3/SPJS_ChartsForSharePoint_v3.3.5.js&quot;&gt;&lt;/script&gt;

Or you can make a button and call the chart manually like this:

&lt;input type=&quot;button&quot; onclick=&quot;manualLoad()&quot; value=&quot;Load chart&quot;&gt;
&lt;div id=&quot;MyChart1&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
/*****************************************************
		Address all containers
*****************************************************/
// All charts must be represented by a container with a unique id. 
// This container  must be present in the page
var arrOfChartContainers = [&quot;MyChart1&quot;];
var loadRC = false;
var allowEval = false;

var loadManually = true;
function manualLoad(){
	loadManually = false;
	spjs_GenerateChart();
}
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Charts/Javascript/3.3/SPJS_ChartsForSharePoint_v3.3.5.js&quot;&gt;&lt;/script&gt;
3.

To have a placeholder like this while the chart loads:
IMG

You must add this code to your CEWP:

&lt;style type=&quot;text/css&quot;&gt;
.chartLoadingOverlay{
	font-style:italic;
	color:gray;
	border:1px silver solid;
	background-color:#F5F5F5;
	line-height:250px;
	height:250px;
	width:500px;	
	text-align:center;	
	margin:2px;
}
&lt;/style&gt;

&lt;div id=&quot;MyChart1&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
/*****************************************************
		Address all containers
*****************************************************/
// All charts must be represented by a container with a unique id. 
// This container  must be present in the page
var arrOfChartContainers = [&quot;MyChart1&quot;];
var loadRC = false;
var allowEval = false;

var loadManually = true;
function manualLoad(){
	loadManually = false;
	spjs_GenerateChart();
}
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/test/English/Charts/Javascript/3.3/SPJS_ChartsForSharePoint_v3.3.5.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;

$.each(arrOfChartContainers,function(i,id){
	$(&quot;#&quot;+id).html(&quot;&lt;div class='chartLoadingOverlay'&gt;Loading chart please be patient...&lt;/div&gt;&quot;);
});
setTimeout(function(){
	manualLoad();
},100);
&lt;/script&gt;

The setTimeout is necessary to let the browser render the overlay before it freezes while retrieving the data for the chart.

Please note the these features require v3.3.5 of SPJS Charts for SharePoint.

You find the files, and additional information in this article

Alexander

Wrap choice-field in multiple columns: Updated version

I have preciously posted a solution for wrapping checkboxes or radio buttons in multiple rows. This one is a bit sleeker and easier to implement.

IMG

I have added a slightly modified version of “init_fields” to accommodate for lists and surveys.

Add this code to a CEWP below the form:

<style type="text/css">
.ms-RadioText label{
	white-space:nowrap;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script type="text/javascript">

var fields = init_fields_v3();

multichoiceVertical(['Checkboxes'],4);

function multichoiceVertical(arr,breakAfter){
	var toFind, index, counter, table;
	toFind = "td.ms-formbody";
	if($("td.ms-formbodysurvey").length>0){
		toFind = "td.ms-formbodysurvey";
	}
	$.each(arr,function(i,fin){
		if(fields[fin]!==undefined){
			index = 0;
			counter = 0;
			table = $(fields[fin]).find(toFind+' table:first');
			$(table).prepend("<tr id='vertical_"+fin+"_"+index+"'></tr>");
			$(table).find('tr:first').nextAll().each(function(){
				if(counter%breakAfter===0){
					$("#vertical_"+fin+"_"+index).after("<tr id='vertical_"+fin+"_"+(index+1)+"'></tr>");					
					index += 1;
				}				
				$(this).find('td:first').appendTo($("#vertical_"+fin+"_"+index));
				$(this).remove();
				counter += 1;
			});			
		}
	});
}

function init_fields_v3(){
	var toFind, res, myMatch, disp, fin, type
	res = {};
	toFind = "td.ms-formbody";
	if($("td.ms-formbodysurvey").length>0){
		toFind = "td.ms-formbodysurvey";
	}
	$(toFind).each(function(){
		myMatch = $(this).html().match(/FieldName="(.+)"\s+FieldInternalName="(.+)"\s+FieldType="(.+)"\s+/);	
		if(myMatch!=null){
			disp = myMatch[1];
			fin = myMatch[2];
			type = myMatch[3];
			if(type=='SPFieldNote'){
				if($(this).find('script').length>0){
					type=type+"_HTML";
				}else if($(this).find("div[id$='_TextField_inplacerte']").length>0){
					type=type+"_EHTML";
				}				
			}
			if(type=='SPFieldLookup'){
				if($(this).find('input').length>0){
					type=type+"_Input";
				}
			}
			res[fin] = this.parentNode;
			$(res[fin]).attr('FieldDispName',disp);
			$(res[fin]).attr('FieldType',type);
		}		
	});
	return res;
}

</script>

Change the script src to use a local copy of jQuery if you prefer that.

You call the function with an array of the FieldInternalNames you want top apply this solution to, and the number of columns to distribute the choices over like this:

multichoiceVertical(['Checkboxes'],4);

Alexander

Dynamic Forms for SharePoint – Now with Tabs

Change log
May 06. 2013
I have released v2.95 – you find it here
February 20, 2013 Updated to v2.70 with these changes:

  • Fixed bug where the tab setup link is missing in initial setup.
  • Added “show field description when readonly” switch under “Misc” section.
  • Added support for SP 2013.
  • Small change to the file default.css to remove form background color in SP 2013 (goes better with the SP 2013 look).
  • Added error handling when using invalid characters in the custom css setup in the heading configuration and including.
  • Added support for rules comparing date columns against other date columns in the form, or validation of empty / not empty date columns.

Read more here


January 13, 2013 Updated to v2.65 with these changes:

Fixes:

  • Validation text was shown multiple times if the rule was triggered repeatedly.
  • When saving the GUI the input values for visible or hidden tabs / headings got the previous rule value if the fields were left blank.
  • Error message in DispForm due to “customValidationMsg” being triggered.
  • Update the css file (note the text “Dynamic Forms for SharePoint v2.65” in the top) to help wrap the tabs better when not using the “Break tabs at index” option.

New features

  • It’s now possible to have a rule check other rules before triggering.

January 4, 2013 Updated to v2.61 BETA with these changes:

  • Set field value had a bug preventing choice fields from being set correctly.
  • Added MUI support for the validation message / alert.

January 1, 2013 Updated to v2.6 BETA with these new features:

  • Option to bypass all rules for selected users or groups (Misc tab).
  • Set date column value like [today], [today]-14 or [today]+14.
  • Tabs now support MUI.
  • Added support for headings (MUI).
  • Changed boolean column behavior to fix issue with hiding tabs.

You must update these files: “DynamicFormsForSharePoint.js” and “default.css”.

Regarding setting a date column to [today]
Not all reginal settings are supported. You will get an alert with instructions if your LCID is not supported.

Headings
You find the headings in the tabs section, and you add them as you do with the fields. Hover over the help icon in the GUI to learn how to set up MUI

Please note that you must update spjs-utility.js to v1.13.


04.11.2012 Updated to v2.51 with these changes:

  1. The form was hidden when no settings were found (first setup) – thus hiding the link to initiate the setup. It was still possible to use ?dfsetup=1 to initialte the setup.
  2. Whan not using TABS in SP2007, you go a javascript error:
    “The value of the property ‘ExecuteOrDelayUntilScriptLoaded’ is null or undefined, not a Function object”

01.11.2012 Updated to v2.5 with these changes:

  • Finally, you can rearrange the order of RTE fields in the tabs.
  • Initial form visibility set to hidden to prevent flashing all fields before applying rules / tabs (display:none is not used because the dialog size would be distorted).

NOTE: You must update both “DynamicFormsForSharePoint_v2.js” and “default.css”.

19.10.2012 Updated to v2.41 with these changes:

  • The action “Set field value” can now pull values from other columns in the current form (in addition to item ID) – as requested by Morten. To include a value from another field, enter the FieldInternalName like this: {Title}.
  • Added trigger “The form is saved”. This trigger will affect the action “Set field value” only.
  • Added password obfuscation as requested by Matthias.

15.10.2012 Updated to v2.4 with these changes:

  • Minimum dialog width (SP2010) set to 700px in default.css.
  • The variable “_spUserId” is changed to “_spPageContextInfo.userId” in SP2010 as some users are missing the “_spUserId” variable in their master page.
  • The edit link was previously only visible for the person who first set up the solution. It is now visible for all users. Protect the settings with the built in password functionality.
  • Added a fix to handle multiple single item lookup columns with more than 20 items in different tabs (in IE). The problem was that the options “dropdown” sometimes did not render.
  • To fix the problem when adding more than 2 rich text or enhanced rich text columns (in SP2007 only) broke the script, I have disabled the ordering of those field types completely. Put them in the top or bottom of the form (using list settings).
  • Added “Is in group trigger”.
  • Added single choice lookup columns as trigger.
  • Added show or hide tabs by rule option.

The changes are in the files “DynamicFormsForSharePoint_v2.js” and “default.css”.


18.08.2012 in v2.3:

  • Added option to show a tab only for members in selected SharePoint groups.
  • Fixed a bug in date columns when you type in the value, in combination with the “alert validation message option”.

15.08.2012 in v2.2:

  • Added option to alert the validation message.
  • Added support for “All fields tab” – to enable, add a tab with no fields.
  • Enabled solid color table background – same color as the selected tab. To disable, remove line 51-63 in the default.css file.

14.08.2012 In v2.1: Changed the “Orphan fields” handling by adding a checkbox “Show orphan fields in a separate tab” in the tabs configuration, ensured compatibility with Christophe’s Easy Tabs and changed the tab position in non-dialog forms in SP2010.


This is a follow up on Dynamic Forms for SharePoint: Production, and describes the new features – including the integration with Tabs for SharePoint forms. Please refer the previous article for an introduction to the solution.

IMG

Some of the changes:

  • Integrated with the Tabs for SharePoint forms solution. You can now rearrange the order of the fields in the tabs (not true for rich text fields).
  • Added option to hide save item button based on a rule.
  • Added option to apply a rule if the current user is not the author of the item.
  • Added option to set a field value based on a rule.
  • Added support for handling the content type selector (hide, read only, set value).
  • Added option to hide the attachments, or set them as read only (hide the “delete link”).
  • Added option to show a validation message when applying a rule.
  • Setting a field as read only now shows the field description as well.
  • Some bugfixes

The solution is still compatible with both SharePoint 2007 and 2010.

Some screenshots

Rule configuration
IMG

Tab configuration
IMG
IMG

DueDate rule
IMG
I have entered a date in the past to demonstrate the validation. Note that the save item button has disappeared.

Complete task rule
IMG
When clicking the “Completed” checkbox, the “FinalNotes” field is set as required, and the label “You must enter a brief statement in the field below.” is shown.

Tabs or Rules – or both

You can decide whether you want to use both features, or just one of them. Simply delete the last rule or tab configuration to disable that module.

Setup

Please refer this article for setup details.

There are one change to the CEWP code as you now have to refer a css-file. You also have to add an image to the same folder as the css file. This is used to add a gradient color to the tabs.

Download the files
Get jQuery here.
Get the Dynamic Forms For SharePoint files here.

Ensure you pick v2.0 or above. The image “gradient.png” must be placed in the same location as the file “default.css”.

You must also upgrade spjs-utility.js. Get spjs-utility.js v1.11 or above here.

The CEWP code:
You must change the “script src” and the “css href” to reflect your locale files.

<link type="text/css" href="https://files.spjsworks.com/files/DynamicFormsForSharePoint/v2.1/default.css" rel="stylesheet" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://files.spjsworks.com/files/spjs-utility/v1.11/spjs-utility.js"></script>
<script type="text/javascript" src="https://files.spjsworks.com/files/DynamicFormsForSharePoint/v2.1/DynamicFormsForSharePoint_v2.js"></script>
Do you use this solution?

I spend a lot of time developing these solutions. Hit the PayPal button to keep me motivated!

PayPal

Post any bugs or comments below.

Alexander

SPJS Charts for SharePoint update 18.07.2012

I have updated SPJS Charts for SharePoint to v3.3 and added a few new features.

You find the code in the original article

1. Option to have multi select in filter select

IMG
When setting up a chart filter, you now have an option “multiselect” which you can set to true to have multiple selection in the filter select. You can also specify the size of the select. See the “Instructions” link above the filter setup textarea.

2. Added formatter: ColorFormat

Description pulled from here
Assigns colors to the foreground or background of a numeric cell, depending on the cell value. This formatter is an unusual, in that it doesn’t take its options in the constructor. Instead, you should call addRange() or addGradientRange() as many times as you want, to add color ranges, before calling format(). Colors can be specified in any acceptable HTML format, for example “black”, “#000000”, or “#000”.

3. Added DataTable Roles (Experimental)

IMG
Dotted line represents uncertain numbers.

Description pulled from here
Google DataTable and DataView objects now support explicitly assigned column roles. A column role describes the purpose of the data in that column: for example, a column might hold data describing tooltip text, data point annotations, or uncertainty indicators.

Previously, there were only two roles available to a column: ‘domain’ which specifies major axis labels; and ‘data’ which specifies bar heights, pie slice widths, and so on. These roles were assigned implicitly, based on the order and type of the columns in the table. However, with the ability to explicitly assign column roles, you can now add optional columns that provide new, interesting features to a chart such as arbitrary annotation labels, hovertext, and uncertainty bars.

4. Filter multiple charts with the same filter controls

You can apply the same filter on multiple charts in a page. To do this, add the parameter “filterAdditionalCharts” to the filter setup textarea like this:

[{&quot;label&quot;:&quot;Year&quot;,&quot;urlKey&quot;:&quot;year&quot;,&quot;filterAdditionalCharts&quot;:[&quot;MyChart2&quot;],&quot;options&quot;:[{&quot;f&quot;:&quot;All&quot;,&quot;v&quot;:&quot;*&quot;},{&quot;f&quot;:&quot;2010&quot;,&quot;v&quot;:&quot;2010&quot;},{&quot;f&quot;:&quot;2011&quot;,&quot;v&quot;:&quot;2011&quot;},{&quot;f&quot;:&quot;2012&quot;,&quot;v&quot;:&quot;2012&quot;}]}]

You supply an array of additional chart container IDs to apply this filter to. If you set up multiple filters, you only have to set this parameter for the first filter select. In the additional charts, you must set up the Custom CAML to consume the filter values.

5. boolean configuration options will now be handled properly

Previously there were a problem using boolean options like “sortAscending”. This has now been fixed.

6. Alphabetically sorted field names in field select – now with FieldInternalName in parentheses

In the “Edit Chart GUI” the field names are now Alphabetically sorted. You also have the FieldInternalName in parentheses behind the display name. This might come in handy when setting up custom CAML.

7. Load the Google Visualization API release candidate

Google periodically releases a new version of the Google Visualization API. As the API does not have support for versioning, the new version is forced on everyone using this tool. To stay one step ahead, you might want to check out the release candidate before it goes live. To do this, you can set the variable “loadRC” to true in the CEWP code (as before), or you can now use a query string parameter in the URL like this:

../MyPage.aspx?loadRC=1

Alexander

Send email to distribution group stored in a SharePoint list using local email client

Change log
16.07.2014 Added support for selecting multiple groups. Please note that there may be limitations in the browser restricting the length of the mailto link.

12.11.2013 Fixed a typo in OrderBy part of the CAML.
29.06.2012 Fixed a missing “&” in line 48 – thanks to Jim.

I got a request some time ago from Brett Anderson, asking for a solution for sending a group email to users stored in a SharePoint list.

This solution can be used to harvest email addresses from a SharePoint list, and sending an email using the users local email client. It requires the email addresses to be stored in plain text.

When setup it will look like this:
IMG

Step 1

Create a list (or reuse an existing) with two fields: One for storing the email (in this example the Title field), and one for storing the distribution group name:
IMG

Add this code to a CEWP using the content link option linking to a file containing the code, or in a HTML Form web part in the sourcecode editor, somewhere in your portal:

<table cellpadding="2">
	<tr>
		<td valign="top" title="Ctrl + click to select multiple groups" style="cursor:help;">Select groups</td>
		<td valign="top" title="Use BCC to hide the addresses from the receiver" style="cursor:help;">Address option</td>
		<td valign="top"></td>
	</tr>	
	<tr>
		<td valign="top" id="groupSelectTd">
			<select id="distributionGroupSelector" multiple="multiple" size="3"></select>
		</td>
		<td valign="top">
			<input type="radio" name="cc_bcc" id="radio_to" value="to"><label for="radio_to">To</label><br>
			<input type="radio" name="cc_bcc" id="radio_cc" value="cc"><label for="radio_cc">CC</label><br>
			<input type="radio" name="cc_bcc" id="radio_bcc" value="Bcc" checked="checked"><label for="radio_bcc">BCC</label>
		</td>
		<td valign="top">
			<input type="button" onclick="doSendGroupEmail()" value="Open email client">
		</td>
	</tr>
</table>
	

<script type="text/javascript" src="/Scripts/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/Scripts/spjs-utility/spjs-utility.js"></script>
<script type="text/javascript">

var emailgroupArgObj = {"listGuid":"SendMail",
						"listBaseUrl":L_Menu_BaseUrl,
						"groupNameField":"GroupName",
						"emailField":'Title',
						"subject":"My email subject",
						"body":"My email body"};
						
/*************************************************/						
/*********** No changes below this line **********/
/*************************************************/	
var emailObj = {};

function getEmailGroups(argObj){
	var res, qb, hb;
	qb = [];
	qb.push("<Where>");
	qb.push("<IsNotNull>");
	qb.push("<FieldRef Name='"+argObj.emailField+"' />");
	qb.push("</IsNotNull>");
	qb.push("</Where>");
	qb.push("<OrderBy><FieldRef Name='"+argObj.groupNameField+"' /></OrderBy>");
	res = spjs_QueryItems({listName:argObj.listGuid,listBaseUrl:argObj.listBaseUrl,query:qb.join(''),viewFields:['ID',argObj.emailField,argObj.groupNameField]});
	hb = [];
	$.each(res.items,function(i,item){
		if(emailObj[item[argObj.groupNameField]]===undefined){
			emailObj[item[argObj.groupNameField]] = [];
			hb.push("<option value='"+item[argObj.groupNameField]+"'>"+item[argObj.groupNameField]+"</option>");
		}
		emailObj[item[argObj.groupNameField]].push(item[argObj.emailField]);
	});
	$("#distributionGroupSelector").html(hb.join(''));
}

function doSendGroupEmail(){
	var groupIdArr = $("#distributionGroupSelector").val(), emailArr = [], link = "";
	if(groupIdArr === null){
		$("#groupSelectTd").css("background-color","#ffcccc");
		return;
	}else{
		$("#groupSelectTd").css("background-color","#ffffff");
	}
	$.each(groupIdArr,function(i,groupId){
		emailArr = $.merge(emailArr,emailObj[groupId]);
	});
	if($("#radio_to").prop('checked')){
		link += "mailto:"+emailArr.join('; ')+"&";
	}else if($("#radio_cc").prop('checked')){
		link += "mailto:?cc="+emailArr.join('; ')+"&";
	}else{
		link += "mailto:?bcc="+emailArr.join('; ')+"&";
	}
	location.href = link+"subject="+emailgroupArgObj.subject+"&body="+emailgroupArgObj.body;
}

getEmailGroups(emailgroupArgObj);
</script>
Step 2

Change the properties in the variable “emailgroupArgObj” to match your setup

  • listGuid: The list GUID or the display name of the list containing the email addresses.
  • listBaseUrl: The base url of the list containing the email addresses. If the code is in the same site, no need to change the variable L_Menu_BaseUrl.
  • groupNameField: The FieldInternalName of the field containing the group name.
  • emailField: The FieldInternalName of the field containing the email address.
  • subject: Enter a value here to have the subject field prefilled in the email client.
  • body: Enter a value here to have the body field prefilled in the email client.

Read here on how to find the list GUID and the FieldInternalNames

The script src in the code above should be changed to point to local copies of both jQuery and spjs-utility.js.
You find jQuery here, and spjs-utility.js here – ensure you use the latest version.

Ask if anything is unclear.

Alexander