Add/Create new document in SharePoint document Library programmatically - sharepoint

I have created a new Document Library and set up custom content type with MS Word Document Template. When i click on Create new template it works fine. but i need to be able to add some logic on a button event where it will go into that library and create a new document, so that when i go into that library i will see a new document that has been created by that button event.
i tried doing it as i would do a regular list item, but i got the following error on item.update:
To add an item to a document library, use SPFileCollection.Add()
Now i did some research but everywhere i see the code for uploading a file to the document library but no where i can find how to add a new document using my template that is associated in that doc library.
please help and thanks.

public static void colFileMtod()
{
using (SPSite objsite = new SPSite("http://smi-dev.na.sysco.net/SyscoFinance/FSR/"))
{
using (SPWeb objWeb = objsite.OpenWeb())
{
SPFileCollection collFiles = objWeb.GetFolder("BPCPublishRecord").Files;
SPList lst = objWeb.Lists["BPCPublishRecordCopy"];
if (lst != null)
{
if (objWeb.Lists.Cast<SPList>().Any(list => list.Title.Equals("BPCPublishRecordCopy", StringComparison.OrdinalIgnoreCase)))
{
foreach (SPFile file in collFiles)
{
string strDestUrl = collFiles.Folder.Url + "/" + file.Name;
byte[] binFile = file.OpenBinary();
SPUser oUserAuthor = file.Author;
SPUser oUserModified = file.ModifiedBy;
System.DateTime dtCreated = file.TimeCreated;
System.DateTime dtModified = file.TimeLastModified;
SPFile oFileNew = collFiles.Add(strDestUrl, binFile, oUserAuthor, oUserModified, dtCreated, dtModified);
SPListItem oListItem = lst.AddItem();
oListItem = oFileNew.Item;
oListItem["Created"] = dtCreated;
oListItem["Modified"] = dtModified;
oListItem.Update();
objWeb.AllowUnsafeUpdates = true;
}
}
}
}
}
}

Related

Multi-Select fields on a Sharepoint list using OWSSVR.dll

I am in the process of creating a massive SSIS project to move the data from a series of Sharepoint Lists to a new Dynamics CRM Implementation (On-line). The SSIS package uses an OData Source to pull the data from the lists.
There are two columns on my list that do not show up on the OData call. These two columns have Multi-Select or Multi-Lookup values. REST services do not support multi-select choice fields. (Found on another thread: The methods you are attempting only work with choice columns that are NOT multi-select. Unfortunately, multi-select choice columns are not supported by the REST interface. Same holds true for SharePoint 2013 apparently.)
Therefore, I need to try to access the data in these columns on the SharePoint List using the OWSSVR.dll. The list I am having issues with gives me a "This page can’t be displayed" or a "This site can’t be reached" depending on the browser I use.
I verified the List ID by grabbing It from the list settings. Since it didn't work, I went to another SharePoint List I already migrated to verify the URL format. The other list works and brings back the data in XML format.
I am wondering if the OWSSVR.dll has the same restriction on Multi-select values. Any ideas or suggestions?
Psuedo URLS (restricted access site):
Works: http://dummy.sharepointSite.Com/cases/_vti_bin/owssvr.dll?Cmd=Display&List={b703d405-48c8-4211-9137-e1b50bdb0330}&XMLDATA=TRUE
Broken: http://dummy.sharepointSite.Com/cases/_vti_bin/owssvr.dll?Cmd=Display&List={8e148584-b5be-48f5-9343-85d23a7731cc}&XMLDATA=TRUE
I figured out a way to do this without using OWSSVR. I have to set up the User Context to the SharePoint site then retrieve the list of items.
Methods:
public static ClientContext SetupSPContext(string documentLibrarySiteURL,
string userName, string password, string domain = "")
{
ClientContext clientContext = new ClientContext(documentLibrarySiteURL);
SecureString pwString = new SecureString();
foreach (char c in password.ToCharArray()) { pwString.AppendChar(c); }
if (!String.IsNullOrWhiteSpace(domain))
clientContext.Credentials = new NetworkCredential(userName, pwString, domain);
else
clientContext.Credentials = new SharePointOnlineCredentials(userName, pwString);
Web web = clientContext.Web;
clientContext.Load(web);
clientContext.ExecuteQuery();
return clientContext;
}
public static ListItemCollection GetListItems(ClientContext context, string listName)
{
ListCollection listCollection = context.Web.Lists;
List targetList = context.Web.Lists.GetByTitle(listName);
CamlQuery query = new CamlQuery();
query.ViewXml = "<Query><OrderBy><FieldRef Name='fieldName' /></OrderBy></Query>";
ListItemCollection collListItem = targetList.GetItems(query);
context.Load(collListItem);
context.ExecuteQuery();
if (collListItem.Count == 0)
{
return null;
}
else
{
return collListItem;
}
}
Code in SSIS Script Component:
//In the PreExecute method:
// Variables were defined for the class and not in the preExecute Method
ClientContext spContext = SetupSPContext(Variables.spLocation, Variables.spUserName,
Variables.spPassword, Variables.spDomain);
ListItemCollection listItems = GetListItems(spContext, "List Name");
//Inside the Individual loop inside SSIS (Input0_ProcessInputRow):
ListItem listItem = GetListItem(listItems, fieldValue);
//Multiple Lookup Code
var values = (FieldLookupValue[])listItem["fieldName"];
var finalValue = "FieldName values: ";
if (values.Length > 0)
{
foreach (var value in values)
{
finalValue = value.LookupValue + "; ";
}
}
//Multiple Select
if (listItem["fieldName2"] != null)
{
var valuesTwo = (string[])listItem["fieldName2"];
string combinedValues = "fieldName2 Values: ";
foreach (var value in valuesTwo)
{
combinedValues += value + "; ";
}
}

Change the "Make "New Folder" command available?" option with Sharepoint Client Object Model

I got a lot of sites with document libraries where the "Make "New Folder" command available" option is set to "no".
I would like to walk through these document libraries and change this to "yes".
How can I achieve this? After doing some search, I found that a lot of things can be done with the files in a document library, but did not find any example that shows how to change settings (advanced settings) of the library itself.
Thank you,
vm
Since you are looking for solution that utilizes CSOM API, the below example demonstrates how enable folders for document libraries:
using (var ctx = new ClientContext(webUri))
{
var result = ctx.LoadQuery(ctx.Web.Lists.Where(l => l.BaseType == BaseType.DocumentLibrary && !l.Hidden));
ctx.ExecuteQuery();
foreach (var list in result)
{
list.EnableFolderCreation = true;
list.Update();
}
ctx.ExecuteQuery();
}
VB.Net version
Using context As Microsoft.SharePoint.Client.ClientContext = New Microsoft.SharePoint.Client.ClientContext(webUri)
Dim qry = From l In context.Web.Lists
Where (CInt(l.BaseType) = 1) AndAlso Not l.Hidden
Select l
Dim result As IEnumerable(Of Microsoft.SharePoint.Client.List) = context.LoadQuery(qry)
context.ExecuteQuery()
Dim list As Microsoft.SharePoint.Client.List
For Each list In result
list.EnableFolderCreation = True
list.Update()
Next
context.ExecuteQuery()
End Using
Using powershell.
$list.EnableFolderCreation = $true;
$list.update();
put this inside a for loop that iterates through the lists/sites/webs of your farm. something like:
$sc = http://myweb.com/mysitecollection
$spsite = Get-SPsite $sc
foreach ($web in $spsite.AllWebs)
{
foreach ($list in $web.Lists)
{
$list.EnableFolderCreation = $true;
$list.update();
}
}
$spsite.dispose()
if you would rather do this using the client object model, throw this into a console app. (make sure you reference Microsoft.SharePoint.dll)
using System;
using Microsoft.SharePoint;
namespace SharepointModifier
{
class FolderEnabler
{
static void Main(string[] args)
{
string sitecollectionaddress = "Http://mysitecollection.com/";
using (SPSite mysites = new SPSite(sitecollectionaddress))
{
foreach (SPWeb web in mysites.AllWebs)
{
foreach (SPList list in web.Lists)
{
list.EnableFolderCreation = true;
//Make any other changes to list properties here
list.Update();
Console.WriteLine(list.Title + " Has been updated.");
}
}
}
}
}
}

Update Modified field in Office 365

Is there any way to update the Modified field in Office 365? I have checked both CSOM and Batch update methods. But it's failed. Could anybody help me to update this field.
Before attempting to set Modified, Created, Editor, and Author fields for a list item you need to disable a couple of properties on the List, specifically EnableVersioning and for good measure ForceCheckout.
SharePoint Online prerequisite is the SharePointOnline CSOM:
.NET client API reference for SharePoint Online
Nuget - Microsoft.SharePointOnline.CSOM
using (var context = new ClientContext(webUrl))
{
context.Credentials = new SharePointOnlineCredentials(userName,password);
var list = context.Web.Lists.GetByTitle(listTitle);
var item = list.GetItemById(itemID);
var user = context.Web.EnsureUser(accountName);
context.Load(user);
context.Load(list);
context.Load(item);
context.ExecuteQuery();
// If the properties are enabled on the list then disable them
bool updateList = list.ForceCheckout || list.EnableVersioning;
if (list.ForceCheckout) list.ForceCheckout = false;
if (list.EnableVersioning) list.EnableVersioning = false;
if (updateList)
{
list.Update();
context.ExecuteQuery();
}
// Now set the fields that are normally locked
item["Modified"] = DateTime.Now;
item["Created"] = DateTime.Now.AddDays(-3);
item["Author"] = user.Id;
item["Editor"] = user.Id;
item.Update();
context.ExecuteQuery();
}
SharePoint CSOM API does not support system update (SystemUpdate method counterpart from SSOM API) but you could manipulate system fields like Modified By and Modified fields directly as demonstrated below.
Prerequisites: SharePoint Server 2013 Client Components SDK
using (var ctx = GetContext(webUri, userName, password))
{
//get List Item
var list = ctx.Web.Lists.GetByTitle(listTitle);
var item = list.GetItemById(itemId);
//Retrieve User
var user = ctx.Web.EnsureUser(accountName);
ctx.Load(user);
ctx.ExecuteQuery();
//Update system fields
item["Modified"] = DateTime.Now.AddMonths(-6);
item["Created"] = DateTime.Now.AddYears(-1);
item["Editor"] = user.Id;
item["Author"] = user.Id;
item.Update();
ctx.ExecuteQuery();
}
where
public static ClientContext GetContext(Uri webUri, string userName, string password)
{
var securePassword = new SecureString();
foreach (var ch in password) securePassword.AppendChar(ch);
return new ClientContext(webUri) { Credentials = new SharePointOnlineCredentials(userName, securePassword) };
}
SharePoint CSOM API now support system update using UpdateOverwriteVersion method. This way you can modify Modified, Created, Author and Editor properties without changing the item Version. For example:
$file = Get-PnPFile -Url $FileUrl -AsListItem
##update file properties
$item["Modified"] = $FileModifiedDate
$item["Created"] = $FileCreatedDate
$item["Author"] = $FileCreatedByDest.ID
$item["Editor"] = $FileModifiedByDest.ID
$fileTest2.UpdateOverwriteVersion()
Invoke-PnPQuery
That should do the trick.

How to add a Web Part into a SitePages/Home.aspx using CSOM

has anyone managed to add a Web Part into a Wiki page using CSOM?
Background: Home.aspx is a Wiki page and all its WPs are located in the rich text zone (in fact a "WikiField" column). Technically they are located in a hidden "wpz" web part zone and in addition to this there is always a placeholder with WP's ID in the WikiField column.
I've modified the existing server-side code seen on http://blog.mastykarz.nl/programmatically-adding-web-parts-rich-content-sharepoint-2010/ and http://640kbisenough.com/2014/06/26/sharepoint-2013-moving-webparts-programmatically-to-rich-content-zone/ into this:
using System;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;
public class Class1
{
void DeployWebPart(ClientContext clientContext, string zone, string pattern, string position)
{
List library = clientContext.Web.GetList("/sites/site/SitePages/");
clientContext.Load(library);
clientContext.ExecuteQuery();
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
ListItemCollection itemColl = library.GetItems(query);
clientContext.Load(itemColl, items => items.Include(i => i.Id, i => i.DisplayName, i => i["WikiField"]));
clientContext.ExecuteQuery();
ListItem item = itemColl.Where(i => i.DisplayName == "Home").First();
clientContext.ExecuteQuery();
File page = item.File;
LimitedWebPartManager lwm = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
string xmlWebPart = #"<webParts>...</webParts>";
WebPartDefinition wpd = lwm.ImportWebPart(xmlWebPart);
WebPartDefinition realWpd = lwm.AddWebPart(wpd.WebPart, "wpz", 0);
List targetList = clientContext.Web.GetList("/sites/site/Announcements/");
clientContext.Load(targetList, l => l.Views);
clientContext.Load(realWpd);
clientContext.ExecuteQuery();
string wpId = String.Format("g_{0}", realWpd.Id.ToString().Replace('-', '_'));
if (zone == "wpz")
{
string htmlcontent = String.Format(CultureInfo.InvariantCulture, "<div class=\"ms-rtestate-read ms-rte-wpbox\" contenteditable=\"false\"><div class=\"ms-rtestate-notify ms-rtestate-read {0}\" id=\"div_{0}\"></div><div id=\"vid_{0}\" style=\"display:none;\"></div></div>", new object[] { realWpd.Id.ToString("D") });
string content = item["WikiField"] as string;
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(System.Text.RegularExpressions.Regex.Escape(pattern));
if (position == "before")
{
content = regex.Replace(content, (htmlcontent + pattern), 1);
}
else
{
content = regex.Replace(content, (pattern + htmlcontent), 1);
}
item.Update();
clientContext.ExecuteQuery();
}
}
}
Everything works fine until the last item.Update() and clientContext.ExecuteQuery() are being invoked. Before the Update() the new placeholder gets properly inserted into the WikiField contents. But after the Update() the WikiField contents reverts back to its original state (!)
Note: As an alternative it is possible to add the WP into another zone (eg. "Bottom"). In this case the WP gets displayed on the page. But it has two major drawbacks: The newly created zone is not well formatted and the WP cannot be moved or even deleted.
Thanks for any input on this.
The following example demonstrates how to add web part into Enterprise Wiki page:
public static void AddWebPartIntoWikiPage(ClientContext context, string pageUrl, string webPartXml)
{
var page = context.Web.GetFileByServerRelativeUrl(pageUrl);
var webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
var importedWebPart = webPartManager.ImportWebPart(webPartXml);
var webPart = webPartManager.AddWebPart(importedWebPart.WebPart, "wpz", 0);
context.Load(webPart);
context.ExecuteQuery();
string marker = String.Format(CultureInfo.InvariantCulture, "<div class=\"ms-rtestate-read ms-rte-wpbox\" contentEditable=\"false\"><div class=\"ms-rtestate-read {0}\" id=\"div_{0}\"></div><div style='display:none' id=\"vid_{0}\"></div></div>", webPart.Id);
ListItem item = page.ListItemAllFields;
context.Load(item);
context.ExecuteQuery();
item["PublishingPageContent"] = marker;
item.Update();
context.ExecuteQuery();
}
Usage
var webPartXml = System.IO.File.ReadAllText(filePath);
using (var ctx = new ClientContext(webUri))
{
AddWebPartIntoWikiPage(ctx, wikiPageUrl,webPartXml);
}
Result

SharePoint copying images from document library of a Web site to a document library in another Web site

I am moving image files from document library of a Web site to a document library in another Web site. I get the following error # line SPListItem oListItemDest = oFileDest.Item;
error:
[Microsoft.SharePoint.SPException] = {"The object specified does not belong to a list."}
Code:
try
{
using (SPSite oSiteCollectionSrc = new SPSite("http://dev:32223/"))
{
SPWeb oWebsiteSrc = oSiteCollectionSrc.AllWebs["en/people"];
SPList oListSrc = oWebsiteSrc.Lists["Images"];
SPListItemCollection collListItemsSrc = oListSrc.Items;
foreach (SPListItem oListItemSrc in collListItemsSrc)
{
SPFile oFileSrc = oListItemSrc.File;
Stream srcStream = oFileSrc.OpenBinaryStream();
using (SPSite oSiteCollectionDest = new SPSite("http://www.devmysites.com/"))
{
SPWeb oWebsiteDest = oSiteCollectionDest.OpenWeb("en/people");
SPList oListDest = oWebsiteDest.Lists["Images"];
SPFileCollection collFilesDest = oListDest.RootFolder.Files;
try
{
SPFile oFileDest = collFilesDest.Add(oListDest + #"/" + oFileSrc.Name, srcStream, true);
SPListItem oListItemDest = oFileDest.Item;
oListItemDest["Created"] = oFileDest.TimeCreated;
oListItemDest["Modified"] = oFileDest.TimeLastModified;
oListItemDest.Update();
}
catch(Exception es1)
{
Console.WriteLine("# Exception:#");
Console.WriteLine(es1.Message);
}
oWebsiteDest.Dispose();
}
}
oWebsiteSrc.Dispose();
}
}
catch (Exception es)
{
Console.WriteLine("# Exception:#");
Console.WriteLine(es.Message);
}
I have also had to copy documents between sharepoint lists, the code that I used to do it is in the answer to this question: SharePoint 2010: Copy documents between lists

Resources