Wednesday, February 13, 2019

Create folder in SharePoint list (SharePoint 2010, 2013, 2016)

So, we continue to work with basic operations, today is another piece of code in which we are using CSOM create a folder in the program list. And as usual by tradition I use Visual studio.

The main advantage of this code is the use of C#, which means such wonderful features are available as Custom Timer Job, Event Reciever and much more. In my console project I using following reference and code:

using Microsoft.SharePoint.Client;

using (var clientContext = new ClientContext("http://sp/sites/test"))
            {
                string folderName = "test";
                var list = clientContext.Web.Lists.GetByTitle("ListBase");
                list.EnableFolderCreation = true;

                clientContext.Load(list);
                clientContext.Load(list.RootFolder);
                clientContext.Load(list.RootFolder.Folders);
                clientContext.ExecuteQuery();

                var folderCollection = list.RootFolder.Folders;

                foreach (var folder in folderCollection)
                {
                    if (folder.Name == folderName)
                    {
                        clientContext.Load(folder.Files);
                        clientContext.ExecuteQuery();
                    }
                    else
                    {
                        var itemCreateInfo = new ListItemCreationInformation
                        {
                            UnderlyingObjectType = FileSystemObjectType.Folder,
                            LeafName = folderName
                        };
                        var newItem = list.AddItem(itemCreateInfo);
                        newItem["Title"] = folderName;
                        newItem.Update();
                        clientContext.ExecuteQuery();
                        break;
                    }
                }
            }
Happy Coding!

Copying folder library to another library (SharePoint 2010, 2013, 2016)

In this article, I continue to lay out the basic operations for working with .NET MS SharePoint server On-Premises one of which is copying a folder from an attachment inside from one library to another, as always I run the code from the Console application from Visual studio.

The main advantage of this code is the use of C#, which means such wonderful features are available as Custom Timer Job, Event Reciever and much more. In my console project I using following reference and code:

using Microsoft.SharePoint;

using (SPSite SPsite = new SPSite("http://sp/sites/test"))
            {
                using (SPWeb SPWeb = SPsite.OpenWeb())
                {
                    SPDocumentLibrary srcLib = (SPDocumentLibrary)SPWeb.Lists["Documents"];
                    SPDocumentLibrary destLib = (SPDocumentLibrary)SPWeb.Lists["OldDocuments"];
                    foreach (SPListItem sourceItem in srcLib.Folders)
                    {
                        SPFolder sourceFolder = sourceItem.Folder;
                        string targetPath = destLib.RootFolder.ServerRelativeUrl + "/" + sourceFolder.Name;
                        SPFolder targetFolder = SPWeb.GetFolder(targetPath);
                        SPListItem targetItem = targetFolder.Item;
                        sourceItem.Folder.CopyTo(targetPath);
                    }
               }
           }
Happy Coding!

Friday, January 25, 2019

Editing wsp-package third-party solution

In this article I will explain how to make a change to a third-party solution by changing the data in the wsp file. I have a wsp file, where the visual web part is displayed in English, since I have to work with Russian-speaking users, I need to add names in Russian and translate the web part from ANSI to UTF-8, how to do it all in order. , so, let's begin!

1. Unpacking the wsp file (.cab) It is suitable to use archivers such as 7-Zip or WinRAR. Name solution is "Exaction.ListSearch.wsp", The screenshot shows that its web part is in English.



Right-click on our wsp file and select Unpacking in "Exaction.ListSearch" open this folder and will see manifest, dll-file and another folder related to the project (Features, Layouts, CONTROLTEMPLATES).


2. To change a web part from English to Russian to open folder "CONTROLTEMPLATES" with extension ".ascx". Open this file via notepad editor and change text on "Russian names".



Save As and change Encoding on UTF-8.



3. Now is download makeddf 1.0.1 in the same folder (you can in another, but you will have to specify the full path to the file makeddf.exe).

4. Open is PowerShell ISE editor (or Command Promt) run as Administrator and insert this command:

#Get path
cd "C:\wsp\Exaction.ListSearch"
#Create ddf-file
C:\wsp\Exaction.ListSearch\makeddf.exe /p Exaction.ListSearch /d Exaction.ListSearch.ddf /c Exaction.ListSearch.cab
#Set cab-file
makecab /f Exaction.ListSearch.ddf

5. Run command to get path cd "C:\wsp\Exaction.ListSearch"

6. Run command to create ddf-file: C:\wsp\Exaction.ListSearch\makeddf.exe /p Exaction.ListSearch /d Exaction.ListSearch.ddf /c Exaction.ListSearch.cab


7. Run command to create cab-file: makecab /f Exaction.ListSearch.ddf.


8. Rename "Exaction.ListSearch.cab" to "Exaction.ListSearch.wsp".

9. Copy final "Exaction.ListSearch.wsp" into SharePoint server and Open is PowerShell ISE editor run as Administrator then add and run 2 command:

#Add PSSnapin Microsoft SharePoint
Add-pssnapin Microsoft.sharepoint.powershell
#Update Solutions
Update-SPSolution –Identity Exaction.ListSearch.wsp –LiteralPath C:\Wsp\NewListSearch\Exaction.ListSearch.wsp –GACDeployment
We are waiting for IIS to restart and open our web part, congratulations, everything works!


Happy Coding!

Thursday, January 24, 2019

Highlighting list items with .NET and CSR (Employee Vacation Project) on SharePoint server 2013, 2016

Hello everyone, in this article I will talk about the project in which I needed to highlight the elements of the list that matched by dates and categories. All of us go on vacation from time to time and someone may substitute us for the time of our absence, however, we need to see whether the period of time for vacation for employees in one category (for example, SharePoint developers) or not, for this task, I need a list of Calendar, columns Title, Category (lookup another list column), Start Time, End Time and Flag (hidden). I create several elements of the list (employees) with a start and end date, some leave vacation days.
The main advantage of this code is the use of C#, which means such features are available as Visual Web Part and JSLink (CSR).




Lets get started!

1. Open the visual studio 2012 or 2015 as run as administrator on SharePoint server (my example on SharePoint server 2013 OnPremise). 
2. Create an SharePoint server 2013 - Visual Web Part (name Project: "CalendarDatePeriods").



3. Set URL and Select a Farm Solution.



4. Add reference in the Project Microsoft.CSharp.

5. Open file "VisualWebPart1UserControl.ascx.cs".



6. Remove code "protected void Page_Load(object sender, EventArgs e){ }".

7. Add this code (Do not forget that the URL of the server and the name of the list may differ from yours!):
public class Item
 {
   public Int32 ID { get; set; }
   public string Title { get; set; }
   public string Category { get; set; }
   public DateTime StartTime { get; set; }
   public DateTime EndTime { get; set; }
 }
    //Class declaration array
    public class RootObject
    {
        public RootObject()
         {
            items = new List();
         }
            public List items { get; set; }
     }
         //Load page
         protected void Page_Load(object sender, EventArgs e)
          {
            //create int array
            List<int> ID_array = new List<int>();
            //GetListAllItems
            using (SPSite site = new SPSite("http://sp-test/sites/eng"))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    web.AllowUnsafeUpdates = true;
                    string listUrl = web.ServerRelativeUrl + "/lists/Calendar";
                    SPList list = web.GetList(listUrl);
                    SPView view = list.Views["All Events"];
                    SPListItemCollection items = list.GetItems(view);
                    //Run class RootObject
                    RootObject objs = new RootObject();
                    foreach (SPListItem item in items)
                    {
                        //Add items to array
                        objs.items.Add(new Item
                        {
                            ID = Int32.Parse(item["ID"].ToString()),
                            Title = item["Title"].ToString(),
                            Category = item["Category"].ToString(),
                            StartTime = DateTime.Parse(item["Start Time"].ToString()),
                            EndTime = DateTime.Parse(item["End Time"].ToString()),
                        });
                    }
                    //Filter array DateTime periods
                    var array = objs.items;
                    for (int i = 0; i < array.Count - 1; i++)
                    {
                        for (int j = i + 1; j < array.Count; j++)
                        {
                            var p1 = array[i];
                            var p2 = array[j];
                            if (p1.Category != "1;#-" && p2.Category != "1;#-")
                            {
                                if (p1.Category != p2.Category)
                                    continue;
                                if (!(p1.StartTime > p2.EndTime || p2.StartTime > p1.EndTime))
                                {
                                    ID_array.Add(p1.ID);
                                    ID_array.Add(p2.ID);
                                    ID_array.Distinct().ToArray();
                                }
                            }
                        }
                    }
                    //Update List Item to DateTime period
                    for (int x = 0; x < ID_array.Count; x++)
                    {
                        using (SPSite osite = new SPSite("http://sp-test/sites/eng"))
                        {
                            using (SPWeb oweb = site.OpenWeb())
                            {
                                SPList olist = oweb.Lists["Calendar"];
                                SPListItemCollection oitems = list.GetItems(new SPQuery()
                                {
                                    Query = @"<Where><Eq><FieldRef Name='ID' /><Value Type='Int'>" + ID_array[x] + "</Value></Eq></Where>"
                                });

                                foreach (SPListItem item in oitems)
                                {
                                    item["Flag"] = "Yes";
                                    item.Update();
                                }
                            }
                        }
                    }
                }
            }
        }
8. Add reference in the lines where the code is highlighted in red, he will suggest.

using System;

using Microsoft.SharePoint;

using System.Collections.Generic;

using System.Linq;

using System.Web.UI;

9. If no errors are detected in the project, then do "Deploy Solution".
10. After the project is published on the server, IIS is restarted and you need to wait a couple of minutes if you need to make sure that the project has been published successfully, follow the link: http://your_sharepoint_server:port/_admin/Solutions.aspx and see your solution "calendardateperiods.wsp" status "Deployed". Then restart our list and click to "Property" -> "Edit Page":



"Add a Web Part" -> Categories "Custom" -> Add "CalendarDatePeriods - VisualWebPart1":



We added a web part and immediately saw that in the "Flag" column, for elements that match in categories and dates, the value is "Yes". This means our code is working successfully.



To highlight the color of elements whose values match, we use CSR (JSlink) and add it via the Content Editor Web Part. We need to add item in library "Site Assets" "jquery-2.1.3.min.js", then create JavaScript-file DateCSR.js in which you need to add the code allocated by our elements and "Flag" hiding column:

<script type="text/javascript" src="/sites/eng/SiteAssets/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
(function () { 
    var priorityFiledContext = {}; 
    priorityFiledContext.Templates = {}; 
    priorityFiledContext.Templates.Fields = {  
        "EventDate": { 
            "View": EventDateFiledTemplate 
        },
        "EndDate": { 
            "View": EndDateFiledTemplate 
        }
    }; 
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(priorityFiledContext);
})();
(function () { 
    var linkFiledContext = {}; 
    linkFiledContext.Templates = {}; 
    linkFiledContext.OnPostRender = linkOnPostRender;
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(linkFiledContext);
})();
function linkOnPostRender(ctx) 
{ 
    var linkCloumnIsEmpty = 1;
    for (i = 0; i < ctx.ListData.Row.length; i++) { 
        if (ctx.ListData.Row[i]["Flag"]) 
        { 
            linkCloumnIsEmpty = 1; 
            break; 
        } 
    } 
    if (linkCloumnIsEmpty) {
        var cell = $("div [name='Flag']").closest('th'); 
        var cellIndex = cell[0].cellIndex + 1;
        $('td:nth-child(' + cellIndex + ')').hide(); 
        $('th:nth-child(' + cellIndex + ')').hide(); 
    }
}
function EventDateFiledTemplate(ctx) {
    var Flag = ctx.CurrentItem.Flag;
    var EventDate = ctx.CurrentItem.EventDate;
    if (Flag == "Yes"){
       return "<span style='color :red'>" + EventDate + "</span>";
    } else {
          return "<span style='color :green'>" + EventDate + "</span>";
    }        
}
  function EndDateFiledTemplate(ctx) {
    var Flag = ctx.CurrentItem.Flag;
    var EndDate = ctx.CurrentItem.EndDate; 
    if (Flag == "Yes"){
         return "<span style='color :red'>" + EndDate + "</span>";
    } else {
        return "<span style='color :green'>" + EndDate + "</span>";
    }
}
</script>
"Add a Web Part" -> Category "Media and content" -> Add "Content Editor":



Add script "Content link" url, your JavaScript-file('/sites/eng/SiteAssets/DateCSR.js') and "Apply"



And we see our result, the most important thing is that this solution allows you to work with a large number of list items (I used more than 1000), without delays and timeouts. Additionally, you can modify this solution to suit your requirements; you can add an Event Reciever to create, modify, or delete list items with similar logic.


Happy Coding!

Tuesday, December 18, 2018

Create Custom Action "Copy URL document" to ECB menu

In this article, I created a solution for the ECB menu, where the short URL of the document is copied and inserted for example into a letter to the recipient send to email. Create JavaScript file and save in library "SiteAssets", using JQuery (version jquery-2.1.3.min.js). Add code your file:
<script type="text/javascript" src="/sites/test/SiteAssets/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
function Custom_AddDocLibMenuItems(m, ctx)
    {
	      $("#where_to_insert").hide();
	      var strDisplayText = "Copy URL document";
	      var url = '';
	      var spans = $('#where_to_insert');
		  spans.text('');
		  function getlist() {
			var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getByTitle('Documents')/items?$select=EncodedAbsUrl,FileLeafRef&$filter=Id eq " + currentItemID;
			var requestHeaders = {
			    "accept": "application/json;odata=verbose"
			}
			$.ajax({
			    url: requestUri,
			    type: 'GET',
			    dataType: 'json',
			    headers: requestHeaders,
			    success: function (data) 
			    {        
			       $.each(data.d.results, function(i,result) {
		            var EncodedAbsUrl = result.EncodedAbsUrl;
		            var link = document.createElement('a');
		            if (EncodedAbsUrl != null) {
		                link.href = EncodedAbsUrl;
		              } 
		            var FileLeafRef = result.FileLeafRef;
		            link.textContent = FileLeafRef;
		            var url = document.getElementById('where_to_insert').appendChild(link);
			    copy();
			    });
			       	function copy() {
				      var target = document.getElementById('where_to_insert');
				      var range, select;
				      if (document.createRange) {
				        range = document.createRange();
				        range.selectNode(target)
				        select = window.getSelection();
				        select.removeAllRanges();
				        select.addRange(range);
				        document.execCommand('copy');
				        select.removeAllRanges();
				      } else {
				        range = document.body.createTextRange();
				        range.moveToElementText(target);
				        range.select();
				        document.execCommand('copy');
				      }
				    }
			    },
			    error: function ajaxError(response) {
			        alert(response.status + ' ' + response.statusText);
			    }
			 });
		}
      	CAMOpt(m, strDisplayText, getlist(), strDisplayText.link);
      	CAMSep(m);
      }
</script>
<span id="where_to_insert"></span>
and save it.

"Edit Page to library -> Add a Web Part" -> Category "Media and content" -> Add "Content Editor":



Content Editor "Edit Web Part" add to your JavaScript file:



Check our solution after reloading the page, click to "Open Menu" and again "Open Menu" click item menu "Copy URL document":



Insert your copy into to Outlook messages:



If you hover the mouse over the link, it will see the URL of the document, and if you click, you will go to it by the link.
Happy Coding!

Thursday, October 11, 2018

Copying list items with metadata (history) to another list (SharePoint 2010, 2013, 2016)

In this article, I continue to sort out the tasks associated with transferring data from one source to another while preserving all the information. This time I published a sample code where I copy the list items with the whole story (metadata) into another list.

The main advantage of this code is the use of C#, which means such wonderful features are available as Custom Timer Job, Event Reciever and much more. In my console project I using following reference and code:

using System;

using Microsoft.SharePoint;

using Microsoft.SharePoint.Utilities;

using (SPSite oSPsite = new SPSite("http://sp/sites/test"))
            {
                using (SPWeb oSPWeb = oSPsite.OpenWeb())
                {
                    SPList srcList = oSPWeb.Lists["Users1"];
                    SPList destList = oSPWeb.Lists["Users2"];
                    foreach (SPListItem sourceItem in srcList.Items)
                    {
                        SPListItem targetItem = destList.AddItem();
                        for (int i = sourceItem.Versions.Count - 1; i >= 0; i--)
                        {
                            SPListItemVersion sourceField = sourceItem.Versions[i];
                            targetItem["Author"] = sourceField["Author"];
                            targetItem["Title"] = sourceField["Title"];
                            targetItem["Modified By"] = sourceField["Modified By"];
                            targetItem[SPBuiltInFieldId.Modified] = GetFieldValueAsDate(sourceField["Modified"]);
                            targetItem[SPBuiltInFieldId.Created] = GetFieldValueAsDate(sourceField["Created"]);
                            targetItem.Update();
                        }
                    }
                }
  private static String GetFieldValueAsDate(object sourceField)
        {
            string result = string.Empty;
            if (sourceField != null)
            {
                DateTime date = Convert.ToDateTime(sourceField);
                if (date.Year > 1900)
                    result = SPUtility.CreateISO8601DateTimeFromSystemDateTime(date);
            }
            return result;
        }
    }
}
Happy Coding!

Friday, October 5, 2018

Moving/copying file with version history to another library (SharePoint 2010, 2013, 2016)

Recently, I had to copy an archive of documents from one collection of sites to another, I didn’t have any problems with PowerShell, thanks to Import\Export, but the task changed when the question arose about transferring several large documents with a long history of versioning from one library to another. I tried to find a solution without a code, but did not find anything, and suddenly in one forum I saw a small piece of code that solved my problems, in this article I will share it and tell you a little.

The main advantage of this code is the use of C#, which means such wonderful features are available as Custom Timer Job, Event Reciever and much more. In my console project I using following reference and code:

using System;

using Microsoft.SharePoint;

using System.IO;

using System.Collections;

//Get SPSite or Site Collection
using (SPSite oSPsite = new SPSite("http://sp/sites/test")){
 using (SPWeb oSPWeb = oSPsite.OpenWeb())
  {
   //Get Library source
   SPList lib_source = oSPWeb.Lists["Library1"];
   //Get Library destination
   SPList lib_destination = (SPDocumentLibrary)oSPWeb.Lists["Library2"];
   //Get item (file) using SPQuery
   SPListItemCollection items = lib_source.GetItems(new SPQuery()
    {
     Query = @"<Where><Eq><FieldRef Name='FileLeafRef'/><Value Type='Text'>Document.docx</Value></Eq></Where>"
      });
         foreach (SPListItem item in items) {
           SPFile fileSource = item.File;
           //Get the created by and created
           SPUser userCreatedBy = fileSource.Author;
           //Convert the "TimeCreated" property to local time
           DateTime dateCreatedOn = fileSource.TimeCreated.ToLocalTime();
           //Get the versions history
           int countVersions = item.File.Versions.Count;
              for (int i = 0; i <= countVersions; i++)
                {
                  Hashtable hashSourceProp;
                  Stream streamFile;
                  SPUser userModifiedBy;
                  DateTime dateModifiedOn;
                  string strVerComment = "";
                  bool bolMajorVer = false;
                    if (i < countVersions)
                     {
                      //Get all versions file, history, properties, createdBy, checkInComment
                      SPFileVersion fileSourceVer = item.File.Versions[i];
                      hashSourceProp = fileSourceVer.Properties;
                      userModifiedBy = (i == 0) ? userCreatedBy : fileSourceVer.CreatedBy;
                      dateModifiedOn = fileSourceVer.Created.ToLocalTime();
                      strVerComment = fileSourceVer.CheckInComment;
                      bolMajorVer = fileSourceVer.VersionLabel.EndsWith("0") ? true : false;
                      streamFile = fileSourceVer.OpenBinaryStream();
                     } else {
                       //Get current versions file, history, properties, createdBy, checkInComment
                       userModifiedBy = fileSource.ModifiedBy;
                       dateModifiedOn = fileSource.TimeLastModified;
                       hashSourceProp = fileSource.Properties;
                       strVerComment = fileSource.CheckInComment;
                       bolMajorVer = fileSource.MinorVersion == 0 ? true : false;
                       streamFile = fileSource.OpenBinaryStream();
                     }
                       //URL library destination
                       string urlDestFile = lib_destination.RootFolder.Url + "/Folder/" + fileSource.Name;
                       //Copy all properties
                       SPFile fileDest = lib_destination.RootFolder.Files.Add(
                         urlDestFile,
                         streamFile,
                         hashSourceProp,
                         userCreatedBy,
                         userModifiedBy,
                         dateCreatedOn,
                         dateModifiedOn,
                         strVerComment,
                         true);
                          if (bolMajorVer)
                             fileDest.Publish(strVerComment);
                          else
                            {
                             SPListItem itmNewVersion = fileDest.Item;
                             itmNewVersion["Created"] = dateCreatedOn;
                             itmNewVersion["Modified"] = dateModifiedOn;
                             itmNewVersion.UpdateOverwriteVersion();
                            }                  
                        }
                    }
                }
            }
Happy Coding!