Tag Archives | SharePoint

PowerShell script to copy a SharePoint Document Library to a Local Path

I wanted to have a PowerShell script that downloaded A Document Library’s contents to a local folder. This is what I put together.

Function JBM-SharePoint-CopyDocumentLibraryLocal {
PARAM([Parameter(Mandatory=$true)]$SiteURL,
    [Parameter(Mandatory=$true)]$DocumentLibrary,
    [Parameter(Mandatory=$true)]$Destination)
$spWeb = Get-SPWeb -Identity http://$SiteURL
$list = $spWeb.Lists[$DocumentLibrary]
foreach ($listItem in $list.Items)
{
    $DestinationPath = $listItem.Url.replace("$DocumentLibrary","$Destination").Replace("/","\")
    write-host "Downloading $($listItem.Name) -> $DestinationPath"

    if (!(Test-Path -path $(Split-Path $DestinationPath -parent)))
    {
        write-host "Createing $(Split-Path $DestinationPath -parent)"
        $dest = New-Item $(Split-Path $DestinationPath -parent) -type directory
    }
    $binary=$spWeb.GetFile($listItem.Url).OpenBinary()
    $stream = New-Object System.IO.FileStream($DestinationPath), Create
    $writer = New-Object System.IO.BinaryWriter($stream)
    $writer.write($binary)
    $writer.Close()
}
$spWeb.Dispose()

SharePoint 2010, Client OM, jQuery Autocomplete and BCS/External lists

In this previous post, I used jQuery/SOAP/SPServices to access a SharePoint BCS list (an external list). I wanted to do the same thing using the Client Object Model (Some call it Clien OM? Or maybe CSOM?). Below is the code to access contact data in a BCS connection to Microsoft CRM 2011, and use it for autocomplete values. Things to note:

  1. You need to have a method tag in your CAML statement. This tells the list which “Operation” (as it is listed in SharePoint Designer) to use
  2. You need to use the “include method” with the executeQueryAsync method
  3. You need to include the ViewFields tags in the CAML statement, and I think they should match the include statement above
$('#ContactsSearchTextbox').autocomplete({
    source: function( request, response ) {
	    var CAMLQuery= "<View><Method Name='ContactReadList' /><Query><Where><Contains><FieldRef Name='FullName' /><Value Type='Text'>"+request.term+"</Value></Contains></Where></Query><ViewFields><FieldRef Name='FullName' /><FieldRef Name='ContactId' /><FieldRef Name='ParentCustomerIdName' /></ViewFields></View>";
		var context = new SP.ClientContext.get_current();
		var web = context.get_web();
		var list = web.get_lists().getByTitle('Contacts');
		var query = new SP.CamlQuery;
		query.set_viewXml(CAMLQuery);
		allItems = list.getItems(query);
		context.load(allItems, 'Include(FullName,ContactId,ParentCustomerIdName)');
		context.executeQueryAsync(function (){
			var arrayOfResults = new Array();
			var listItemEnumerator = allItems.getEnumerator(); 
			while(listItemEnumerator.moveNext()) {
				var oListItem = listItemEnumerator.get_current();
				arrayOfResults.push(oListItem);
			}
			response($.map(arrayOfResults ,function( item ) {
				return {
				label: item.get_item('FullName') + ' (' + item.get_item('ParentCustomerIdName') + ')',
				value: item.get_item('ContactId'),
				id: item.get_item('FullName')
				}
			}));
		},function(sender, args){
		   alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
		});        
	},
	minLength: 5,
});

Accessing SharePoint 2010 BCS lists via SOAP/WebServices for use in a jQuery autocomplete

So it seems that you can’t access BCS list data via REST, according to this article. But it seems that you can access the list data through SOAP. I used the code below to query a BCS list that points to a MSCRM 2011 backend (I know I could go right to CRM via REST, but then I would have XSS issues). I then take the results and use them for a jQuery autocomplete for an input box. Obviously in the code below, Contacts is a BCS “external List”

 


$('#ContactSearchTextbox').autocomplete({
source: function( request, response ) {
	$().SPServices({
	operation: "GetListItems",
	async: false,
	listName: "Contacts",
	CAMLViewFields: "<ViewFields><FieldRef Name='FullName' /><FieldRef Name='ContactId' /><FieldRef Name='ParentCustomerIdName' /></ViewFields>",
	CAMLQuery: "<Query><Where><Contains><FieldRef Name='FullName' /><Value Type='Text'>"+request.term+"</Value></Contains></Where></Query>",
	completefunc: function (xData, Status) {
	$('#SearchResults').html(xData.responseText);
	response($.map( $(xData.responseXML).SPFilterNode("z:row"), function( item ) {
	return {
	label: $(item).attr('ows_FullName') + "(" + $(item).attr('ows_ParentCustomerIdName') +")",
	value: $(item).attr('ows_ContactId')
		}
	}));
	}
	});	    
},
minLength: 4
});

PowerShell to get all items in a SharePoint 2007 list via Web Services/SOAP

I wanted to get a list’s contents in a SharePoint 2007 site via PowerShell. I ran into only one issue – how to handle the pagination. When creating the Xml to include the next page, I was running into formatting issues because the text contained a “=”. This link suggested that I create the XML element first then add the innerText after. Worked after that!

TheBelow is my script to get the contents of a SharePoint 2007 list.

 

$listName = "List Name"
$xmlDoc = new-object System.Xml.XmlDocument
$query = $xmlDoc.CreateElement("Query")
$viewFields = $xmlDoc.CreateElement("ViewFields")
$queryOptions = $xmlDoc.CreateElement("QueryOptions")
$rowLimit = "50"
$service = New-WebServiceProxy -UseDefaultCredential -uri http://sharepoint2007.comapny.com/_vti_bin/lists.asmx?WSDL
$nextPage=$true
while($nextPage){
$list = $service.GetListItems($listName, "", $query, $viewFields, $rowLimit, $queryOptions, "")
$list.data.row | select ows_ID,ows_Created,ows_Title
if ($list.data.ListItemCollectionPositionNext){
$nextPage=@"
<Paging ListItemCollectionPositionNext="" />
"@
$queryOptions.set_InnerXml($nextPage)
$queryOptions.ChildNodes[0].Attributes["ListItemCollectionPositionNext"].InnerText = "$($list.data.ListItemCollectionPositionNext)"
}
else {
write-host "done"
$nextPage=$false
}
}

PowerShell to list SharePoint 2007 lists

I wanted to get a quick list of all the lists in our SharePoint 2007 environment. With PowerShell 2, it is easy.

$lists = New-WebServiceProxy -UseDefaultCredential -uri http://sharepoint2007.company.com/_vti_bin/lists.asmx?WSDL
$lists.GetListCollection().List | select Title, Name

Pseudo workflow approval with out SharePoint Workflows.

I wanted to have a form that a person would submit (for an example a request of some type) and then it would be approved by the appropriate people. I find the built in workflow functionality too limiting and too difficult for users, so this is what I came up with:

I would have one list that contained fields for both the user to enter data and for each approver to approve or disapprove. In addition, there would be a “Final Approval” field that cold only be set once everyone approved or disapproved and an “I agree” to terms checkbox.

First up, I hid all the fileds on the NewForm.aspx that were related to the approval process. Just the data that was to be collected was shown. I did this with jquery and a CEWP:

<script type="text/javascript">
$(document).ready(function(){
$('tr:has(select[title="User 1"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 2"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 3"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 4"])').not('tr:has(tr)').hide();
$('tr:has(select[title="User 5"])').not('tr:has(tr)').hide();
$('tr:has(select[title="Final Status"])').not('tr:has(tr)').hide();
$('nobr:contains("User 1 Comments")').closest('tr').hide();
$('nobr:contains("User 2 Comments")').closest('tr').hide();
$('nobr:contains("User 3 Comments")').closest('tr').hide();
$('nobr:contains("User 4 Comments")').closest('tr').hide();
$('nobr:contains("User 5 Comments")').closest('tr').hide();
});
</script>

Once this is submitted by the user, and email is sent by a SharePoint workflow (I still don’t like them) telling the approvers to look at the request and approve it (link to the edit page in the email)

Then on the edit page, I used the jquery below to hide the “I agree” so the user could not go back and change it. Also I hid the final approval until all drop downs (Approvals) have changed from “Pending” to Approved or Declined. Obviously there would be security issues, but this is a small use case and we weren’t worried about malicious users (famous last words) – people were on their honor.

<script type="text/javascript">
$(document).ready(function(){
$('tr:has(select[title=IAgree])').not('tr:has(tr)').hide();
$('tr:has(select[title=IAgree])').not('tr:has(tr)').append('<tr><td nowrap="true" valign="top" width="190px" class="ms-formlabel"><H3 class="ms-standardheader">I Agree</H3></TD><td valign="top" class="ms-formbody" width="400px">'+$('select[title=IAgree] :selected').text()+'</td></tr>');

$('select :selected').each(function(){
if($(this).text() == "Pending") {
$('tr:has(select[title=Final Status])').not('tr:has(tr)').hide();
}
});

});
</script

Using ajax to query XML in SharePoint Doc Lib, for use in a form’s input autocomplete

Long title, but I wanted to get across what I was trying to do. If I had and XML file in a document library (you could mail enable the doc lib, and send XML from a query in SQL server using the “FOR XML” statement!), could I use jquery to add Autocomplete values to an input field in a newform.aspx? Ended up being not that difficult.

  1. Once the ajax call sucessfully retrievs the xml file, the parseXml routine is called.
  2. Seems there is an issue that IE will not think the file is XML, but rather as txt, so there some quick code to load the file as XML
  3. Then I just look in the file and grab the values I want, and append them to an array
  4. Then just set the array to be used as the autocomplete source
<script type="text/javascript">
$(document).ready(function() {
$.ajax({ 	
	type: "GET",
	url: "http://URL/To/xmlfile.xml",
	dataType: ($.browser.msie) ? "text" : "xml",
	success: parseXml
});
});
function parseXml(data)
{
    var xml;
     if (typeof data == "string") {
       xml = new ActiveXObject("Microsoft.XMLDOM");
       xml.async = false;
       xml.loadXML(data);
     } else {
       xml = data;
     };
 	var results = []; 
	$(xml).find("ID").each(function(){  
		var ClientName = $.trim($(this).find('Name').text());
		var ClientCode = $.trim($(this).find('ZipCode').text());
		results[results.length] = ClientName + "(" + ClientCode + ")"
	});

	$('input[title=Title]').autocomplete({
	source: results,
	delay:10,
	minLength: 3
	});
};
</script>

jQuery, SharePoint Web Services and adding thumbnail to a List

We have a SharePoint list with thumbnails attached to the list items. The request was to show a thumbnail of the image that is attached. I believe this can be done via SharePoint designer, but I thought jQuery would be easier. I added a Content Editor WebPart to the top of the page. Next I inserted the jQuery code below. This code queries the SharePoint Web Services for every item (not tested on a large list), and then loops through them. If there is an attachment, jQuery takes the ID and the path to the attachment and replace the ID column (has to the first column) for the item with the tumbnail image.

The tricks were:

  1. The soapEnv has to have “<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>”
  2. Finding the right selector to get to the ID column:
$("table.ms-listviewtable tr:has(td.ms-vb2)").find("td:first").filter(function() {
			return $(this).text().toLowerCase() == ID;
			}).html("<img src='" + url[1] + "' width=150 height=100 />");

Here is the rest of the code:

$(document).ready(function() {
querySPWebServices();
});

function querySPWebServices() {
        var soapEnv = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'> \
		<soapenv:Body> \
		<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \
		<listName>Projects</listName> \
		<viewFields> \
		<ViewFields> \
		<FieldRef Name='Title' /> \
        <FieldRef Name='Body' /> \
		<FieldRef Name='ID' /> \
		<FieldRef Name='Attachments' /> \
		</ViewFields> \
		</viewFields> \
		<query> \
		<Query /> \
		</query> \
		<queryOptions> \
		<QueryOptions> \
		<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls> \
		</QueryOptions> \
		</queryOptions> \
		</GetListItems> \
		</soapenv:Body> \
        </soapenv:Envelope>";

        $.ajax({
        	async: false,
            url: "http://server.name.com/site/_vti_bin/lists.asmx",
            type: "POST",
            dataType: "xml",
            data: soapEnv,
            complete: processResult,
            contentType: "text/xml; charset=\"utf-8\""
        	});
};
function processResult(xData, status) {
	$(xData.responseXML).find("z\\:row").each(function() {
		if ($(this).attr("ows_Attachments") != 0) {
		var url = $(this).attr("ows_Attachments").replace(/#/g, "").split(';');
		var ID = $(this).attr("ows_ID");
		$("table.ms-listviewtable tr:has(td.ms-vb2)").find("td:first").filter(function() {
			return $(this).text().toLowerCase() == ID;
			}).html("<img src='" + url[1] + "' width=150 height=100 />");
		};
	});
};

My CEWP JQuery code to play flash files in a Modal

I have Flash files in a Document Library. I wanted to have users click the flash files (swf) and have them open up in a hidden div, rather than opening in a different window. I added the code below to a CEWP:

<script type="text/javascript" src="http://jquery.thewikies.com/swfobject/jquery.swfobject.1-1-1.min.js"></script>
<script>
$(document).ready(function() {
//
$("#popupclose").click(function () {
	$("#popup").Hide();
	$('.media').flash().remove();
	return false;
});
//
$("a[href*='\.swf']").each(function(){
	this.onclick = function(){
	var filetoopen = $(this).attr("href");
	$("#popup").Show;
	$('.media').flash({swf:filetoopen,height:600,width:1000});
	return false;
	};
}); 
//
});
</script>
<style type="text/css">
#popup{  
 display:none;    
 position:absolute;  
 top: 10px; 
 left: 10px;
 background:#FFFFFF;  
 border:2px solid #cecece;  
 z-index:2;  
 font-size:12px;
 }   
</style>
<div id="popup">  
  <a id="popupclose" href="javascript:void()">close</a>
<br/>
  <div class="media" style="vertical-align:top;"></div>
</div>

Hide a field in a SharePoint edit form based on other values

We have a form (list) that we want to have everyone edit and give comments. Once everyone has edited the item, we want an “overall status” field to trigger a workflow (send extended email). Be we did not want the overall status to be changed until everyone has chimed in. To achieve this, we created a list and there was a dropdown with everyone’s name to Approve the item. The default of the dropdown was “Pending”. I used the jquery below to hide the “overall status” until there were no dropdowns that said “Pending”

$('select :selected').each(function(){
if($(this).text() == "Pending") {
$('tr:has(input[title=Overall Status])').not('tr:has(tr)').hide();
};
});

The hide code is code that Paul Galvin published here.
jquery is cool.