I got a custom sharepoint list, with a title column which contains Servernames and i got alot of .csv files that has the same name as the title
Is it somehow possible to upload em to the list item as an attachment with a script? Maybe Powershell?
I got over 100 files so it would be a pain if i had to do it all manually.
The File and Title column looks like this:
Title
Server1.domain.com
.csv
Server1.domain.com.csv
Have been looking around for quite a while but havent been able to find anything i could use
Approach:
Iterate over the SharePoint list items.
Load the corresponding CSV file by the SPListItem.Title
Add the file as attachment to the SPListItem.
Script:
$w = Get-SPWeb http://List/Location/Url
$l = $w.Lists["TheList"]
foreach ($item in $l.Items)
{
$file = Get-Item "$($item.Title).csv"
$stream = $file.OpenRead()
$buffer = New-Object byte[] $stream.length
[void]$stream.Read($buffer, 0, $stream.Length)
$item.Attachments.AddNow($file.Name, $buffer)
}
Considerations:
Disposing of the file stream
Disposing of the SPWeb object
Handle missing files
Edit
Two mistakes in first attempt:
SPAttachmentCollection.Add expects a byte array.
SPAttachmentCollection.AddNow should be used to add the attachment directly (without update of the SPListItem)
Updated the code...
Related
When I upload a file in to a subfolder the subfolder modified date is not updated where as the document library last modified date is updated
Now I want to find which file is last updated inside a subfolder using csom
You could use caml query to get the lasted modified item in a library like this:
$list = $Web.Lists.GetByTitle($ListTitle)
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = '<View><Query><OrderBy><FieldRef Name="Modified" Ascending="FALSE"/></OrderBy></Query><RowLimit>1</RowLimit></View>'
$items = $list.GetItems($query)
$Context.load(items)
$context.ExecuteQuery()
I have a TV multi select list type that is evaluating a snippet:
#EVAL return $modx->runSnippet('getFeaturedResourceTree');
Evaluating this snippett:
<?php
$output = array();
$context = $modx->resource->get('context_key');
$sql = "select * from modx_site_content where context_key = '$context' order by `pagetitle`;";
$results = $modx->query($sql);
foreach($results as $result){
$output[] = $result['pagetitle'].'=='.$result['id'];
}
$output = implode('||', $output);
echo $output;
return;
This does work in the manager, I can select and pick multiple resources in the list. However, when I save the TV, nothing is actuially saved. the TV values are not present in the database and when I reload the resource, the TV field is blank.
what could the problem be here?
I'm fairly certain you can accomplish what you're trying to do with an #SELECT binding rather than #EVAL. This has 2 potential benefits:
#EVAL is Evil, LOL. Not all the time, mind you—there are certainly legitimate uses of #EVAL but I've personally always tried very hard to find an alternative, whenever I've considered using #EVAL.
The method I'm about to show you has worked for me in the past, so I'm speculating it will work for you.
#SELECT pagetitle, id FROM modx_site_content WHERE context_key = 'web' ORDER BY `pagetitle`
If you're using #EVAL because you have multiple contexts and you want the context of the Resource currently being edited, then you could use your Snippet, but I would try:
Rather than echo-ing your output, return it.
Call the snippet in a Chunk, and render the Chunk on a test page to ensure it has the output you want, formatted for the TV Input Options exactly the way it should be.
If the Chunk output passes the test, call it into the TV Input Options field with the #CHUNK binding.
One more note: I can't remember if the current Resource is available in the TV as $modx->resource or $resource, but that might be something you want to double check.
i'am stuck coding with below requirement.
I have two excel(xls) files(old and new users list). In each file there are 4 fields "Userid", "UserName", "Costcenter", Approving Manager" . Now, i need to check whether each Userid from New user list exists in Old user list. If so, i have to copy/replace the values of "Costcenter" and Approving Manager" in the New User list with the values from the same columns from Old user list. If this condition fails then hightlight the entire row for the "userid" in the New User List for which there is no corresponding matching record in the Old User list and finally not last but least we have to save the New user list. There are about 2000+ userid's
below, i started of coding to get the Userid list from the New user list into an Array. will be doing the same for Old user list. From there on how do i go by modifying the new user list like i explained above?
$objExcel = new-object -comobject excel.application
$UserWorkBook = $objExcel.Workbooks.Open("O:\UserCert\New_Users.xls")
$UserWorksheet = $UserWorkBook.Worksheets.Item(1)
$OldUsers = #()
$intRow = 2 #starting from 2 since i have to exclude the header
do {
$OldUsers = $UserWorksheet.Cells.Item($intRow, 1).Value()
$intRow++
} while ($UserWorksheet.Cells.Item($intRow,1).Value() -ne $null)
Any help Greatly appreciated...
If the userIDs in each list in some type of regular order, then it should be easy to open both workbooks up at the same time, maintain 2 pointers (Row_for_old_userlist and Row_for_new_userlist) and compare the contents of the New User ID with the old one.
If they aren't in some semblance of order, then for each item in the new userlist, you'll have to scan the entire old userlist to find them and then take your action.
I'm not sure that saving in CSV is a valid approach from your requirements - you may not be able to get the data that way.
However - I think you're really asking how to set the value of an Excel spreadsheet cell.
If so, here's some code I use to insert a list of defects into a spreadsheet...and then set the last cell's column A to a different color. Strangely enough, that "value2" part...it's non-negotiable. Don't ask me why it's "value2", but it is.
for ($x=0; $x -lt $defects.count; $x++)
{
$row++
[string] $ENGIssue = $defects[$x]
$sheet.Cells.Item($row,1).value2 = $ENGIssue
}
$range = $sheet.range(("A{0}" -f $row), ("B{0}" -f $row))
$range.select() | Out-Null
$range.Interior.ColorIndex=6
I wanted to delete all the Items from SharePoint List using Lists webservice,
i know we can do it by iterating all the items, my problem is that the, i have 25000 items in my list and wanted to delete it in one go, Is there any way to do this?
or is there a way to get all the attributes of List then delte the list and re-create the list with the previously saved attributes.
Thanks in Advance.
You could save the list as a template (List Settings -> Save list as template), then delete the list, then create a new list based on the template that you saved.
You could use the UpdateListItems method of the Lists web service, however it is still going to take a long time to delete all items at once.
Try the following snippet -
var batch = new StringBuilder();
batch.Append("<Batch OnError='Continue' ListVersion='1' ListName='{GUID}'>");
string itemTemplate = "<Method ID='1' Cmd='Delete'><Field Name='ID'>{0}</Field></Method>";
for (int i = 0; i < 300000; i++)
batch.Append(string.Format(itemTemplate, i));
batch.Append("</Batch>");
//query Lists service
This code assumes that your item's ID range is from 0 to 300000 - this will be your only option without iterating
all items (and getting their ID). However, with this much items even the StringBuilder will run into performance
problems, not to mention SharePoint.
Your best bet is to delete the site and re-create it like pmartin suggested it.
Here is the way we can do it simply:
XmlNode listItems = SharepointUtilities.GetListItems(sharePointCredentials, sharePointCredentials.SharePointListName);
var nodes = (from nd in listItems.ChildNodes.OfType<XmlNode>() where nd.NodeType.Equals(System.Xml.XmlNodeType.Element) select nd);
var itemIDs = from nd in nodes.FirstOrDefault().ChildNodes.OfType<XmlNode>() where nd.NodeType.Equals(System.Xml.XmlNodeType.Element) select nd.Attributes["ows_ID"].Value;
if (itemIDs.Count() > 0)
{
Lists spSrv = GetSharepointListsService(sharePointCredentials);
XmlDocument doc = new XmlDocument();
XmlElement batchElement = doc.CreateElement("Batch");
batchElement.SetAttribute("OnError", "Continue");
string batchCommand = "<Method ID='1' Cmd='Delete'><Field Name='ID'>";
batchCommand += string.Join("</Field></Method><Method ID='1' Cmd='Delete'><Field Name='ID'>", itemIDs.ToArray());
batchCommand += "</Field></Method>";
batchElement.InnerXml = batchCommand;
spSrv.UpdateListItems(sharePointCredentials.SharePointListName, batchElement);
}
Open the list in DataSheetView, select all records (ctrl+A) and Delete all records.
This is the shortest solution.
I have some code that inserts a list item into a list...
I then have this code
SPFolder folder = web.Folders["Lists"].SubFolders[list.RootFolder.Name].SubFolders["Attachments"].SubFolders[item.ID.ToString()];
foreach (SPFile file in folder.Files)
{
string attachmentName = this.downloadedMessageID + ".xml";
if (file.Name == attachmentName)
{
SPFieldUrlValue value = new SPFieldUrlValue();
value.Description = this.downloadedMessageID + ".xml";
value.Url = this.SiteAddress + file.Url;
item["ZFO"] = value;
}
}
this is fine except for one problem... before this code actually works... I need to call the item.update() method to save the item to SharePoint...
But as you can see there is more work to do ... after item.update is called...
So this means... I have
work
item.update();
more work
item.update();
The problem I am having is I really want just
work
item.update();
So that in any event of failure the whole thing will fail at once or pass at once.... (almost like a SQL transaction).
So whats preventing me from doing this is - I need to set a hyperlink to one of the fields in the list item, this will be to an attachment in the list attachments collection.
Is there any way I can predict this address without having saved the list item to MOSS?
An attachment path depends on the item ID, and I don't believe your item will have an ID until you save it. Have you considered storing the attachments in a document library instead, linked by the field you're trying to set?
Transactional operation isn't exactly SharePoint's strong suit.