Friday, December 27, 2019

Get attachments in list items JSlink (REST API)

In this article I’ll give an example of how to use REST API and JSlink to make a request to attachments in list items which will be useful for working with current and future development projects on the MS SharePoint server (2013, 2016, 2019, Online) platform.
function AttachmentFiledTemplate(ctx){ 
    var listItem = ctx.CurrentItem;
    var listTitle = ctx.ListTitle;
    var spHostUrl = ctx.HttpRoot;
    var itemId = listItem.ID;
    context = ctx;
    var queryUrl = spHostUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items('" + itemId + "')/AttachmentFiles";
    $.ajax({
    url: queryUrl,
        headers: { 
            "accept": "application/json; odata=verbose",
        },
        method: "GET",
         success: function(data){
            $.each(data.d.results, function(){
                //url attachments in list Items
                var attachmenturl = this.ServerRelativeUrl;
                console.log(attachmenturl);
            })
        },
        error: function ajaxError(response){
        alert(response.status + ' ' + response.statusText);
        }
    });
}

We implement using the REST API the name of the attached files in the list items (Example):
(function () {
    var linkFiledContext = {};
    linkFiledContext.Templates = {};
    linkFiledContext.Templates.Fields = {    
        "Attachments": { "View": AttachmentsFiledTemplate }
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(linkFiledContext);

})();

function AttachmentsFiledTemplate(ctx) {
    var itemId = ctx.CurrentItem.ID;
    var listName = ctx.ListTitle;       
    return getAttachments(listName, itemId);
}

function getAttachments(listName,itemId) {  
    var url = _spPageContextInfo.webAbsoluteUrl;
    var requestUri = url + "/_api/web/lists/getbytitle('" + listName + "')/items(" + itemId + ")/AttachmentFiles";
    var str = "";
    $.ajax({
        url: requestUri,
        type: "GET",
        headers: { "ACCEPT": "application/json;odata=verbose" },
        async: false,
        success: function (data) {
            for (var i = 0; i < data.d.results.length; i++) {
                str += "<a href='" + data.d.results[i].ServerRelativeUrl + "'>" + data.d.results[i].FileName + "</a>";
                if (i != data.d.results.length - 1) {
                    str += "<br/>";
                }                
            }          
        },
        error: function (err) {
        }
    });
    return str;
}

Result:
Happy Coding!

Thursday, December 12, 2019

Server Error '/' Application: Could not load file or assembly or one of its dependencies. The system cannot find the file specified.

Hello everyone, let's talk about the error that comes out after adding a new assembly to the project, for example via NuGet Package in Visual studio (Template Project: SharePoint 2016 - Visual Web Part).
Let's go step by step:
1. Open Visual studio on MS SharePoint server 2016 (On-Premises) and create new project - SharePoint 2016 - Visual Web Part,
2. Add to URL and choise "Deploy as a farm solution",
3. Add simple code (example: if (!IsPostBack) {//your simple code}) in the void Page_Load,
4. Further we need to add assembly (example: "TemplateEngine.Docx") for the project in NuGet Package -> "Tools" -> "NuGet Package manager" -> "Package manager Console", -> "Install-Package TemplateEngine.Docx -Version 1.1.4",
5. We are convinced that the assembly was added and displayed in "Reference", add simple code to example and weel see is not errors in "Error List".
6. "Build" -> "Rebuild Solution" -> "Deploy Solution".
7. Add our solution in the Page and weel see the next error:


This behavior at first glance seems strange, we added the assembly through the NuGet Package console, it would seem that when adding the assembly, it is registered in the Reference and then in all the project properties. But the error that the assembly file is missing is still there. So how to fix it quickly and most importantly correctly, again we go step by step:
1. In our project there is folder "Package" in which there is file "Package.package" a file associated with Features, where the paths for assemblies in the current project are contained, open it and immediately go to the "Advanced" tab and "Add Existing Assembly":


2. The "Add Existing Assembly" window has opened, where you can add the assembly, follow the path to our project to the \bin\Debug folder and find our assembly - "TemplateEngine.Docx.dll".
3. Choose "WebApplication" and add new item in "Safe Control": "Namespace": TemplateEngine.Docx.dll, "Assembly Name": TemplateEngine.Docx.dll.


4. We see our record and again collect our project and publish it on the server: "Build" -> "Rebuild Solution" -> "Deploy Solution".


5. Refresh Page!!!.

Happy Coding!

Friday, November 15, 2019

Checking if a User is in an SPGroup

Many know an example "How to check if user exists in a particular sharepoint group or not programatically":
using System;
using System.Linq;
using Microsoft.SharePoint;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            string userName = "DOMAIN\\user";
            string groupName = "Home Members";
            using (SPSite Site = new SPSite("http://sp"))
            {
                using (SPWeb Web = Site.OpenWeb())
                {
                    SPUser user = Web.EnsureUser(userName);
                    if (user.Groups.Cast().Any(g => g.Name.Equals(groupName)))
                    {
                        Console.WriteLine("User " + userName + " is a member of group " + groupName);
                    }
                    else
                    {
                        Console.WriteLine("User " + userName + " is NOT a member of group " + groupName);
                    }
                }
            }
        }
    }
}
The example is excellent, in the end we will write "bool" using "ToUpper()", which at the machine level works much faster, because Microsoft optimized it:
bool checkuser = user.Groups.Cast().Any(g => g.Name.ToUpper() == "Home Members".ToUpper());
//or GetCurrentUser
bool checkgcuser = SPContext.Current.Web.CurrentUser.Groups.Cast().Any(g => g.Name.ToUpper() == "Home Members".ToUpper());
Happy Coding!

Monday, March 4, 2019

Search text in Document (Word, Excel, Pdf, Txt)

In the previous article, I described how to create a document and attach it to a list item when creating it, this time I will focus on finding words within a document, since At the moment I am working on the implementation of my own project for searching the library of keywords within documents.
To work with documents Word and Excel I use DocumentFormat.OpenXml and to work with pdf I use TallComponents.PDFKit.

Why? Because MS SharePoint server keeps source files (documents) on the server, but in the client part we work with a copy of the document. I will give 4 code examples for MS Word (doc, docx), Excel (xls, xlsx), Pdf and Txt. I hope these examples will help you in the future in your projects.

1. Word (DocumentFormat.OpenXml):
//get file library
 SPFile file = item.File;
 string value = file.ToString();
 int index = (value.LastIndexOf('/') + 1);
 string fileName = value.Substring(index);
 string FileExtension = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower();
  //condition
   if (FileExtension == "doc" || FileExtension == "docx")
    {
     if (file.Exists)
      {
       //use file Stream
        byte[] byteArray = file.OpenBinary();
         using (MemoryStream memStr = new MemoryStream())
          {
           memStr.Write(byteArray, 0, (int)byteArray.Length);
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(memStr, false))
             {
              Document document = wordDoc.MainDocumentPart.Document;
               var body = document.MainDocumentPart.Document.Body;
                //search in body
                 foreach (var text in body.Descendants<Text>())
                  {
                   //use case sensetive
                     if (text.Text.IndexOf("test", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
                      {
                       Console.WriteLine(file.ToString());
                      }
                  }
              }
           }
        }
     }
2. Excel (DocumentFormat.OpenXml):
//condition
 if (FileExtension == "xls" || FileExtension == "xlsx")
   {
    if (file.Exists)
     {
      //use file Stream
       byte[] byteArray = file.OpenBinary();
        using (MemoryStream memStr = new MemoryStream())
         {
          memStr.Write(byteArray, 0, (int)byteArray.Length);
           using (SpreadsheetDocument document = SpreadsheetDocument.Open(memStr, false))
            {
             SharedStringTable sharedStringTable = document.WorkbookPart.SharedStringTablePart.SharedStringTable;
              string cellValue = null;
               foreach (WorksheetPart worksheetPart in document.WorkbookPart.WorksheetParts)
                {
                 //get List excel document 
                 foreach (SheetData sheetData in worksheetPart.Worksheet.Elements<SheetData>())
                  {
                   if (sheetData.HasChildren)
                    {
                     //get Row excel document
                     foreach (Row row in sheetData.Elements<Row>())
                      {
                       //get Cell excel document
                       foreach (Cell cell in row.Elements<Cell>())
                        {
                         cellValue = cell.InnerText;
                          if (cell.DataType == CellValues.SharedString)
                           {
                            cellValue = document.WorkbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault().SharedStringTable.ElementAt(int.Parse(cell.CellValue.Text)).InnerText;
                             //use case sensetive
                              if (cellValue.IndexOf("test", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
                               {
                                Console.WriteLine(file.ToString());
                               }
                            }
                         }
                       }
                    }
                 }
              }
           }
        }
    }
}
3. Pdf (TallComponents.PDFKit):
//condition
 if (FileExtension == "pdf")
   {
    if (file.Exists)
     {
      //use file Stream
      byte[] byteArray = file.OpenBinary();
       using (MemoryStream memStr = new MemoryStream())
        {
         memStr.Write(byteArray, 0, (int)byteArray.Length);
          {
           TallComponents.PDF.Document document = new TallComponents.PDF.Document(memStr);
           TextFindCriteria criteria = new TextFindCriteria("test", false, false);
           TextMatchEnumerator enumerator = document.Find(criteria);
            foreach (TextMatch match in enumerator)
             {
              Console.WriteLine(file.ToString());
             }
          }
       }
    }
 }
4. Txt (System.IO namespace):
//condition
 if (FileExtension == "txt")
   {
     if (file.Exists)
      {
        byte[] byteArray = file.OpenBinary();
         using (StreamReader reader = new StreamReader(file.OpenBinaryStream()))
           {
            string content = String.Empty;
            content = reader.ReadToEnd();
             if (content.IndexOf("test", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
               {
                 Console.WriteLine(file.ToString());
               }
           }
       }
   }
Happy Coding!

Friday, February 22, 2019

Create document and upload list item attachment (SharePoint 2010, 2013, 2016)

Hello everyone, this time I will talk about creating Event Reciever and actions that will occur with the element of the list, we are talking about reading the properties of the list item, creating the Word document, filling it with these properties of the current list element and attaching it to an attachment to this element of the list while creating. Such a task came to mind non-monotonously, it was set by user asked it on the forum, I thought that in future project it was possible, and I myself wanted to broaden my horizons in this topic.
In this project, to create a document and its content, I will use DocumentFormat.OpenXml and a description of this library I will use the blog Create a word document with OpenXml and C# (by Ludovic Perrichon).

So begin!!!

1. Create is a Custom list (name "ListProject") then modify list view and show column "Created", "Created by", "Modified", "Modified by".



2.List is ready, then open Visual studio and click "New project" choose project depending on your version SharePoint On-Premises "SharePoint -(2010, 2013, 2016) Empty Project" project name "ItemUploadAttachments".



3. Set URL and Select a Farm Solution.



4. Click right-click on the project name and click "Add" then "New item" and choose "Event Reciever" is name "UploadAttachments".



5. And will see Event Reciever Settings then choose event source "Custom List" and click handle events only "An item was added". Click Finish.



6. Open is added in project Event Reciever "UploadAttachments" and you will see "Elements.xml" open and edit file, set to comment or remove row "<Receivers ListTemplateId="101">" and add "<Receivers ListUrl="Lists/ListProject">", then save file.



7. Open DocumentFormat.OpenXml and insert last version to nuget package "Install-Package DocumentFormat.OpenXml -Version 2.9.0".







8. We continue to work with Event Reciever open file "UploadAttachments.cs" and will see code "public override void ItemAdded(SPItemEventProperties properties) {}" this will be our event, which is activated when creating a list item. Add the code of this void "ItemAdded".
using (SPWeb web = properties.OpenWeb()) {
  try {
      //GetListCurrentItem
        SPListItem currentItem = properties.ListItem;
        string Title = currentItem["Title"].ToString();
        string Author = currentItem["Author"].ToString();
        DateTime Created = DateTime.Parse(currentItem["Created"].ToString());
        string Modified = currentItem["Editor"].ToString();
        DateTime EndTime = DateTime.Parse(currentItem["Modified"].ToString());
        string filepath = @"C:\Temp\" + Title + ".docx";
        //Create file
        CreateWordprocessingDocument(filepath, Title, Author, Created, Modified, EndTime);
        //Upload file
        FileStream stream = new FileStream(filepath, FileMode.Open);
        byte[] byteArray = new byte[stream.Length];
        stream.Read(byteArray, 0, Convert.ToInt32(stream.Length));
        stream.Close();
        currentItem.Attachments.Add(Title + ".docx", byteArray);
        currentItem.Update();
      }
       catch (Exception ex)
       {
        throw ex;
       }
}
9. Further, beyond the limits of this method, we create a public static void "CreateWordprocessingDocument"
public static void CreateWordprocessingDocument(string filepath, string Title, string Author, DateTime Created, string Modified, DateTime EndTime)
        {
        using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(filepath, WordprocessingDocumentType.Document))
            {
                MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
                mainPart.Document = new Document();
                Body body = mainPart.Document.AppendChild(new Body());
                Paragraph para = body.AppendChild(new Paragraph());
                Run run = para.AppendChild(new Run());
                if (Author != "")
                    run.AppendChild(new Text("Author: " + Author));
                {
                    if (Created != null)
                    {
                        Paragraph p = new Paragraph();
                        Run r = new Run();
                        RunProperties rp2 = new RunProperties();
                        rp2.Italic = new Italic();
                        rp2.Bold = new Bold();
                        r.Append(rp2);
                        Text t = new Text("Date created: " + Created) { Space = SpaceProcessingModeValues.Preserve };
                        r.Append(t);
                        p.Append(r);
                        body.Append(p);
                    }
                    if (Modified != "")
                    {
                        Paragraph p = new Paragraph();
                        Run r = new Run();
                        Text t = new Text("Editor: " + Modified);
                        r.Append(t);
                        p.Append(r);
                        body.Append(p);
                    }
                    if (EndTime != null)
                    {
                        Paragraph p = new Paragraph();
                        Run r = new Run();
                        RunProperties rp2 = new RunProperties();
                        rp2.Bold = new Bold();
                        r.Append(rp2);
                        Text t = new Text("Date Modified: " + EndTime);
                        r.Append(t);
                        p.Append(r);
                        body.Append(p);
                    }
                }
            }
        }
10. Check our project is not error, Build solution and Deploy solution. Open our list "ListProject" then "New item" and check in attachment to this item.








Happy Coding!

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 file "Exaction.ListSearch.cab" on "Exaction.ListSearch.wsp".

9. Copy file "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 -FullTrustBinDeployment
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<Item>();
         }
            public List<Item> 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!