I recently developed a windows form which has similar Function, For this purpose, I Used C# and Developed a basic class. This class has several methods to deal with SP online list and it is written based on CSOM. You take advantage of this class and do whatever you want.
Just several points:
As I needed a fast solution It looks like spaghetti but it is a good starting point
All the methods are tested and work well but they might need some error handling.
Just use this as the starting point, it should give you a general Idea
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;
using Microsoft.SharePoint.Client;
using System.Globalization;
using System.Security;
using System.Threading;
using System.Configuration;
using System.Reflection;
using Microsoft.SharePoint;
using System.Collections.Specialized;
using System.Collections;
namespace SharepointListModify
{
internal class SharePointList
{
private LogWriter createLog = new LogWriter();
public SharePointList()
{
}
public void CreateListItem(ClientContext clientContext,
string ListTitle,
Dictionary<string, dynamic> NewItem)
{
//Create Item In List with values in Dictionary
try
{
List oList = clientContext.Web.Lists.GetByTitle(ListTitle);
ListItemCreationInformation listCreationInfromation = new ListItemCreationInformation();
ListItem oListItem = oList.AddItem(listCreationInfromation);
foreach (KeyValuePair<string, dynamic> item in NewItem)
{
string columnName = item.Key.Replace(" ", "_x0020_");
oListItem[columnName] = item.Value;//oListItem["Title"] = "TestTitle";
}
oListItem.Update();
clientContext.ExecuteQuery();
createLog.CreateMainMessage("The Item Successfully Created.");
}
catch (Exception ex)
{
createLog.CreateMainMessage(ex.Message);
}
}
public void CreateListItem( string SPUrl,
string UserName,
string Password,
string ListTitle,
Dictionary<string, dynamic> NewItem)
{
ClientContext clientContext = CreateClientContext(SPUrl, UserName, Password);
try
{
List oList = clientContext.Web.Lists.GetByTitle(ListTitle);
ListItemCreationInformation listCreationInfromation = new ListItemCreationInformation();
ListItem oListItem = oList.AddItem(listCreationInfromation);
foreach (KeyValuePair<string, dynamic> item in NewItem)
{
string columnName = item.Key.Replace(" ", "_x0020_");
oListItem[columnName] = item.Value;//oListItem["Title"] = "TestTitle";
}
oListItem.Update();
clientContext.ExecuteQuery();
createLog.CreateMainMessage("The Item Successfully Created.");
}
catch (Exception ex)
{
createLog.CreateMainMessage(ex.Message);
}
}
public void UpdateListItem( string SPUrl,
string UserName,
string Password,
string ListTitle,
string columnToFilterName,
string ValueToFilter,
Dictionary<string, dynamic> valuesToUpdate)
{
// Starting with ClientContext, the constructor requires a URL to the
//TODO to change Type to be effective For now only creates Generic List
createLog.CreateMainMessage($"updating a List item in {SPUrl} with title:{ListTitle} and item name is {ValueToFilter}");
ClientContext clientContext = CreateClientContext(SPUrl, UserName, Password);
List oList = clientContext.Web.Lists.GetByTitle(ListTitle);
CamlQuery query = new CamlQuery
{
ViewXml = string.Format("<View><Query><Where><Eq><FieldRef Name='{0}'/><Value Type='text'>{1}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>", columnToFilterName, ValueToFilter)
};
var itemsPh = oList.GetItems(query);
clientContext.Load(itemsPh);
clientContext.ExecuteQuery();
foreach (ListItem oListItem in itemsPh)
{
try
{
foreach (KeyValuePair<string, dynamic> item in valuesToUpdate)
{
string columnName = item.Key.Replace(" ", "_x0020_");
oListItem[columnName] = item.Value;//oListItem["Title"] = "TestTitle";
}
oListItem.Update();
clientContext.ExecuteQuery();
createLog.CreateSubMessage(string.Format("The Item Updated Successfully With All values."));
}
catch
{
//If we can not do it all at once Do it one cell by one
createLog.CreateSubMessage(@"Unable to Update All Cell at same time Trying to Update One by one");
foreach (KeyValuePair<string, dynamic> item in valuesToUpdate)
{
try
{
string columnName = item.Key.Replace(" ", "_x0020_");
oListItem[columnName] = item.Value;//oListItem["Title"] = "TestTitle";
oListItem.Update();
clientContext.ExecuteQuery();
createLog.CreateSubMessage(string.Format("The Item {0} with {1} as value is Updated Successfully.", item.Key, item.Value));
}
catch (Exception ex)
{
createLog.CreateSubMessage(string.Format("Unable to Update {0} with {1} as value becaues;\n\r{2}", item.Key, item.Value, ex.Message));
//MessageBox.Show(string.Format("Unable to Update {0} with {1} as value:\n\r{2}", item.Key, item.Value, ex.Message));
}
}
}
}
}
public void UpdateListItem(ClientContext clientContext,
string ListTitle,
string columnToFilterName,
string ValueToFilter,
Dictionary<string, dynamic> valuesToUpdate)
{
//makesure Column Name doesnt have space
columnToFilterName = columnToFilterName.Replace(" ", "_x0020_");
try
{
List oList = clientContext.Web.Lists.GetByTitle(ListTitle);
CamlQuery query = new CamlQuery
{
ViewXml = string.Format("<View><Query><Where><Eq><FieldRef Name='{0}'/><Value Type='text'>{1}</Value></Eq></Where></Query><RowLimit>1</RowLimit></View>", columnToFilterName, ValueToFilter)
};
var itemsPh = oList.GetItems(query);
clientContext.Load(itemsPh);
clientContext.ExecuteQuery();
createLog.CreateMainMessage("Updating SP From IAuditor.");
foreach (ListItem oListItem in itemsPh)
{
foreach (KeyValuePair<string, dynamic> item in valuesToUpdate)
{
try
{
string columnName = item.Key.Replace(" ", "_x0020_");
oListItem[columnName] = item.Value;//oListItem["Title"] = "TestTitle";
oListItem.Update();
clientContext.ExecuteQuery();
createLog.CreateSubMessage(string.Format("The Item {0} with {1} as value is Updated Successfully.", item.Key, item.Value));
}
catch (Exception ex)
{
createLog.CreateSubMessage(string.Format("Unable to Update {0} with {1} as value becaues;\n\r{2}", item.Key, item.Value, ex.Message));
MessageBox.Show(string.Format("Unable to Update {0} with {1} as value:\n\r{2}", item.Key, item.Value, ex.Message));
}
}
}
}
catch (Exception ex)
{
createLog.CreateMainMessage(ex.Message);
}
//MessageBox.Show("Updating Sharepoint From Iauditor Finished!");
}
public List<List<string>> ReadListToAray( string SPUrl,
string UserName,
string Password,
string ListTitle)
{
List<List<Dictionary < string,dynamic >>> test =new List<List<Dictionary<string, dynamic>>>();
List<List<string>> SPListAray = new List<List<string>>();
// This Method Retrives alll Sharepoint Lists in Website
///SPUrl is the website we want to Retrive Lists
createLog.CreateMainMessage($"Creating List Of All List in {SPUrl}");
List<string> SPListsFields = new List<string>();
ClientContext clientContext = CreateClientContext(SPUrl, UserName, Password);
List<string> Headings= RetriveSPListFields(SPUrl, UserName, Password, ListTitle);
SPListAray.Add(Headings);
List oList = clientContext.Web.Lists.GetByTitle(ListTitle);
CamlQuery query = new CamlQuery
{
ViewXml = string.Format("<View><Query></Query></View>")
};
ListItemCollection itemsPh = oList.GetItems(query);
clientContext.Load(itemsPh);
clientContext.ExecuteQuery();
foreach (ListItem oListItem in itemsPh)
{
List<string> ItemValues = new List<string>();
foreach(string heading in Headings)
{
try
{
ItemValues.Add(oListItem[heading].ToString());
}
catch { }
//ItemValues.Add(oListItem["Title"]);
}
SPListAray.Add(ItemValues);
ItemValues = null;
}
return SPListAray;
}
public List<string> RetriveSPLists( string SPUrl,
string UserName,
string Password)
{
// This Method Retrives alll Sharepoint Lists in Website
///SPUrl is the website we want to Retrive Lists
createLog.CreateMainMessage($"Creating List Of All List in {SPUrl}");
List<string> SPListsNameAray = new List<string>();
ClientContext context = CreateClientContext(SPUrl, UserName, Password);
// The SharePoint web at the URL.
Web web = context.Web;
// Retrieve all lists from the server.
context.Load(web.Lists,
lists => lists.Include(list => list.Title, // For each list, retrieve Title and Id.
list => list.Id));
// Execute query.
context.ExecuteQuery();
// Enumerate the web.Lists.
for(int i=0;i< web.Lists.Count; i++)
{
SPListsNameAray.Add(web.Lists[i].Title);
}
createLog.CreateSubMessage($"Creating List of Lists was successfull!");
return SPListsNameAray;
}
public void CreateSpList( string SPUrl,
string UserName,
string Password,
string ListTitle,
string Type,
string ListDescription="")
{
// Starting with ClientContext, the constructor requires a URL to the
//TODO to change Type to be effective For now only creates Generic List
createLog.CreateMainMessage($"Creating a List in {SPUrl} with title:{ListTitle}");
List<string> SPListsNameAray = new List<string>();
ClientContext context = CreateClientContext(SPUrl, UserName, Password);
// The SharePoint web at the URL.
Web web = context.Web;
ListCreationInformation creationInfo = new ListCreationInformation();
creationInfo.Title = ListTitle;
try
{
ListTemplateType choice;
if (Enum.TryParse(Type, out choice))
{
creationInfo.TemplateType = (int)choice;
}
List list = web.Lists.Add(creationInfo);
list.Description = ListDescription;
list.Update();
context.ExecuteQuery();
createLog.CreateSubMessage($"Creating a List {ListTitle} was successfull!");
}
catch(Exception ex)
{
string ValidTypes = "";
foreach (int i in Enum.GetValues(typeof(ListTemplateType)))
{
String name = Enum.GetName(typeof(ListTemplateType), i);
ValidTypes = $"{ValidTypes}\"{name}\" \n ";
}
createLog.CreateSubMessage($"Unable to create List: {ex}\n\r Only the Folowing Values are Valid for Type: {ValidTypes}");
}
}
public void DeleteSPList( string SPUrl,
string UserName,
string Password,
string ListTitle)
{
// Starting with ClientContext, the constructor requires a URL to the
// server running SharePoint.
//createLog.CreateMainMessage($"Deleting a List from {SPUrl} with title:{ListTitle}");
ClientContext context = CreateClientContext(SPUrl, UserName, Password);
try
{
// The SharePoint web at the URL.
Web web = context.Web;
List list = web.Lists.GetByTitle(ListTitle);
//list.DeleteObject();//Never Uncommrnt, This Does not Move Object To Recycle Bin It will be removed Permanently
list.Recycle();
context.ExecuteQuery();
createLog.CreateSubMessage($"List {ListTitle} was successfully Deleted!");
}
catch (Exception ex)
{
createLog.CreateSubMessage($"Unable to delete List:\n\r{ex}");
}
}
public void AddFieldSPList( ClientContext clientContext,
string ListTitle,
string FieldName,
string FieldType= "string")
{
//TODO Write this Method
}
public void DeleteSPListItem( string SPUrl,
string UserName,
string Password,
string ListTitle,
string ItemValue ,
string FieldName="Title")
{
// Starting with ClientContext, the constructor requires a URL to the
// server running SharePoint.
createLog.CreateMainMessage($"Deleting Item from List {ListTitle}");
ClientContext context = CreateClientContext(SPUrl, UserName, Password);
//TODO Write this Method
// Assume that the web has a list named "Announcements".
List announcementsList = context.Web.Lists.GetByTitle("Announcements");
// Assume that there is a list item with ID=2.
ListItem listItem = announcementsList.GetItemById(2);
listItem.DeleteObject();
context.ExecuteQuery();
}
public List<string> RetriveSPListFields( ClientContext context,
string ListTitle)
{
// This Method Retrives alll Sharepoint Lists in Website
///SPUrl is the website we want to Retrive Lists
createLog.CreateMainMessage($"Creating List Of All Fields ");
List<string> SPListsFields = new List<string>();
List list = context.Web.Lists.GetByTitle(ListTitle);
context.Load(list.Fields);
// We must call ExecuteQuery before enumerate list.Fields.
context.ExecuteQuery();
foreach (Field field in list.Fields)
{
SPListsFields.Add(field.InternalName);
}
return SPListsFields;
}
public List<string> RetriveSPListFields(string SPUrl,
string UserName,
string Password,
string ListTitle)
{
// This Method Retrives alll Sharepoint Lists in Website
///SPUrl is the website we want to Retrive Lists
createLog.CreateMainMessage($"Creating List Of All fuekds in {SPUrl}");
List<string> SPListsFields = new List<string>();
ClientContext context = CreateClientContext(SPUrl, UserName, Password);
List list = context.Web.Lists.GetByTitle(ListTitle);
context.Load(list.Fields);
// We must call ExecuteQuery before enumerate list.Fields.
context.ExecuteQuery();
foreach (Field field in list.Fields)
{
SPListsFields.Add(field.InternalName);
}
return SPListsFields;
}
private void ChangeFolderName( string SPUrl,
string UserName,
string Password,
string ListTitle)
{
ClientContext clientContext = CreateClientContext(SPUrl, UserName, Password);
List oList = clientContext.Web.Lists.GetByTitle(ListTitle);
ListItemCreationInformation listCreationInfromation = new ListItemCreationInformation();
ListItem oListItem = oList.AddItem(listCreationInfromation);
}
public void UpdateOnlieListFromOffline( string SPUrl,
string UserName,
string Password,
string ListTitle,
string CSVPathAddress,
bool UpdateEmptyValue = false)
{
//This Method Gets a CSV With Same structure as Sharepoint List and Updates all the values
ClientContext clientContext = CreateClientContext(SPUrl, UserName, Password);
LoadFile loadFile = new LoadFile();
string[,] ExistingDBData = loadFile.LoadCsv(CSVPathAddress);
List<string> ListFields = RetriveSPListFields(clientContext, ListTitle);
Dictionary<string, Dictionary<string, dynamic>> ExistingDBDataDic = new Dictionary<string, Dictionary<string, dynamic>>();
for (int Row = 1; Row < ExistingDBData.GetLength(0); Row++)//It is Assumed Row 1 is title
{
Dictionary<string, dynamic> ItemValues = new Dictionary<string, dynamic>();
for (int Col = 0; Col < ExistingDBData.GetLength(1); Col++)
{
try
{
if (ExistingDBData[0, Col] != null & ExistingDBData[0, Col] != "")//Make Sure Column name is not Emty
{
if (ListFields.Contains(ExistingDBData[0, Col]))//If Sharepoint Online List Have the title add to Dic
{
if ((ExistingDBData[Row, Col] != null & ExistingDBData[Row, Col] != "") | UpdateEmptyValue)//Only Update empty values when the setting requires
{
ItemValues.Add(ExistingDBData[0, Col], ExistingDBData[Row, Col]);//It is Assumed Row 1 is title
}
}
}
}
catch { }
}
if (ExistingDBData[Row, 0] != null & ExistingDBData[Row, 0] != "")//To Make Sure There is Title(JNumber)
{
try
{
ExistingDBDataDic.Add(ExistingDBData[Row, 0], ItemValues);
ItemValues = null;
}
catch { }
}
}
foreach (var Item in ExistingDBDataDic)
{
UpdateListItem(clientContext,ListTitle, "Title", Item.Key, Item.Value);
}
}
public void UpdateOnlieListFromOffline(ClientContext clientContext,
string ListTitle,
string CSVPathAddress,
bool UpdateEmptyValue = false)
{
//This Method Gets a CSV With Same structure as Sharepoint List and Updates all the values
LoadFile loadFile = new LoadFile();
string[,] ExistingDBData = loadFile.LoadCsv(CSVPathAddress);
List<string> ListFields = RetriveSPListFields(clientContext, ListTitle);
Dictionary<string, Dictionary<string, dynamic>> ExistingDBDataDic = new Dictionary<string, Dictionary<string, dynamic>>();
for (int Row = 1; Row < ExistingDBData.GetLength(0); Row++)//It is Assumed Row 1 is title
{
Dictionary<string, dynamic> ItemValues = new Dictionary<string, dynamic>();
for (int Col = 0; Col < ExistingDBData.GetLength(1); Col++)
{
try
{
if (ExistingDBData[0, Col] != null & ExistingDBData[0, Col] != "")//Make Sure Column name is not Emty
{
if (ListFields.Contains(ExistingDBData[0, Col]))//If Sharepoint Online List Have the title add to Dic
{
if ((ExistingDBData[Row, Col] != null & ExistingDBData[Row, Col] != "") | UpdateEmptyValue)//Only Update empty values when the setting requires
{
ItemValues.Add(ExistingDBData[0, Col], ExistingDBData[Row, Col]);//It is Assumed Row 1 is title
}
}
}
}
catch { }
}
if (ExistingDBData[Row, 0] != null & ExistingDBData[Row, 0] != "")//To Make Sure There is Title(JNumber)
{
try
{
ExistingDBDataDic.Add(ExistingDBData[Row, 0], ItemValues);
ItemValues = null;
}
catch { }
}
}
foreach (var Item in ExistingDBDataDic)
{
UpdateListItem(clientContext, ListTitle, "Title", Item.Key, Item.Value);
}
}
public ClientContext CreateClientContext( string SPUrl,
string UserName,
String Password)
{
SecureString SecurePassword = new SecureString();//to pass the password to Sharepoint
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");//this is good practice when communicating with sharepoint time and date
foreach (char c in Password)
{
SecurePassword.AppendChar(c);
}
ClientContext clientContext = new ClientContext(SPUrl);
clientContext.Credentials = new SharePointOnlineCredentials(UserName, SecurePassword);
return clientContext;
}
}
}
For more Information on How this class works, you can check microsoft website