Update SharePoint list field using powershell based on Date comparison - powershell

I am currently try to update SharePoint field (Dropdown field called Overdue to Yes if the dateFormat field is equal or less than current date. At this stage, it does not change the value. Is there anything that i missed. Please refer the code i have below. Thanks
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SPWeb = Get-SPWeb "http://contoso/sites/test";
$List = $SPWeb.Lists["Catalog"];
$currentDate = Get-Date (Get-Date) -format dd/MM/yyyy;
$items = $List.Items;
foreach ($item in $items) {
$deadline = $item["TA Deadline"];
$dateFormat = Get-Date $deadline -format dd/MM/yyyy;
#if date Format is less or equal than current date then update the Overdue drop down field to yes
if($dateFormat -le $currentDate)
{
$item["Overdue"] = "YES"
$item.Update()
}
}
$SPWeb.Dispose();

I think you need to supply an index/numerical numerical value for the choice. See the blog post here.
As it mentions you could do:
$item["Overdue"] = 0; #assuming 0 == YES
Or
$item["Overdue"] = $list.Fields["Overdue"].GetFieldValue("YES");
New code for the datetime logic
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SPWeb = Get-SPWeb "http://contoso/sites/test";
$List = $SPWeb.Lists["Catalog"];
$currentDate = Get-Date;
$items = $List.Items;
foreach ($item in $items) {
$deadline = $item["TA Deadline"];
$dateFormat = [datetime]$deadline
#if date Format is less or equal than current date then update the Overdue drop down field to yes
if($dateFormat -le $currentDate)
{
$item["Overdue"] = "YES"
Write-Debug $item["Overdue"]
$item.Update()
}
}
$SPWeb.Dispose();

if the Overdue column is a yes/no field (Boolean) I guess You can either do like Dana V suggested, so:
$item["Overdue"] = 0
or
$item["Overdue"] = $true

Related

SharePoint PowerShell list filter

hoping someone can guide on the code below:
*$CreatedDate = (Get-Date $CreatedDateTime)
$AddedDateTime = (Get-Date $CreatedDate.AddMinutes(190))
Write-Host "CD:" $CreatedDate
Write-Host "AD:" $AddedDateTime
$ItemsColl = $ReviewList.Items | where {($_['Created'] -ge $CreatedDate) -and ($_['Created'] -le $AddedDateTime)}*
this is suppose to return everything within a date range, i pass on created date, add 190 minutes to that date, and the return should be everything from a workflow task list that was created as a task.
this does bring some but is missing most of the items in the list, i was hoping for an opinion to see if there is any obvious mistakes or maybe a new way of doing this.
Thanks in advance
ok so here is the scenario, when someone sends a document for approval, this creates a new version of document (uk Time), then a task is created by system account (Swiss Time +1hr from uk). I have a function that exports all the metadata for each version of the document into a csv format. where i'm struggling is filtering the reviewer list where all the tasks for each reviewer are stored.
i have two functions in my script GetMetadata and GetReviews.
Get metadata gets all metadata for each versions of the document, where a status changes to review in progress it suggests that the document has gone for a review so therefore we have to look into reviews list to find this item and see who the review was and what the outcome is, however the document could have been reviews multiple times and therefore i need to pass in document name, and datetime of created to filter the list, but date and time of created in review is 1hr and so ahead.
Script:
# ******* Variables Section ******************
#Define these variables
$WebURL="http://site"
$ModuleList = "Library With Versions"
$ReportFile = "D:\Migration\Test\CSV\ItemsForum.csv"
$ReviewList = "Review Tasks"
# *********************************************
#delete file if exists
If (Test-Path $ReportFile)
{
Remove-Item $ReportFile
}
#Get the Web and List
$Web = Get-SPWeb $WebURL
$ReviewList = $web.Lists.TryGetList($ReviewList)
#Get reviewers from review list
function GetReviews($DocumentName, $CreatedDateTime)
{
$CreatedDate = Get-Date $CreatedDateTime
#add 80 minutes, this would be plus one hr to swiss time plus account for time it takes to create item
$AddedCreatedList = Get-Date $CreatedDate.AddMinutes(80)
#filter and get items where document name matches workflow related item (this works but it's missing a lot of items as er image)
$ItemsColl = $ReviewList.Items | where {$_['WorkflowLink'] -match $DocumentName -and $_['Created'] -ge $CreatedDate -and $_['Created'] -le $AddedCreatedList}
#$ItemsColl = $ReviewList.Items
Write-Host "Item Count: " $ItemsColl.Count
$itemIds = ""
if($ItemsColl.Count -gt 0)
{
foreach ($item in $ItemsColl)
{
Write-Host $relatedItemUrl
#$relatedItem = $relatedItemUrl -split ','
#$rit = $relatedItem[1].Trim()
$itemIds += $item.id
$itemIds += ";"
}
Write-Host $itemIds
$itemIds = $itemIds.TrimEnd(";")
}
return $itemIds
}
function GetMetadata{
$List = $web.Lists.TryGetList($ModuleList)
#Check if list exists
if($List -ne $null)
{
#Get all list items
$ItemsColl = $List.Items | where {$_['Module'] -match $ModuleName}
#add headings
Add-Content -Path $ReportFile -Value "Item ID, Status, File Name + Version, Created, Review ID"
#Loop through each item
foreach ($item in $ItemsColl)
{
if ($item['Module'])
{
#Write-Host $item['Module']
ForEach($version in $item.Versions)
{
#Add version label to file in format: [Filename]_v[version#].[extension]
$filesplit = $version['Name'].split(".")
$fullname = $filesplit[0]
$fileext = $filesplit[1]
#$FullFileName = $fullname+"_v"+$version.VersionLabel+"."+$fileext
$FullFileName ="V_"+$version.VersionLabel+" " + $version['Name']
#Get Modified By
$user = $version["Editor"]
$userObj = New-Object Microsoft.SharePoint.SPFieldUserValue($web, $user)
$modifiedBy = $userObj.User.DisplayName
#get and format modified date
$ModifiedDate = ($version['Modified'] -as [datetime]).DateTime
$ModifiedDateF = Get-Date $ModifiedDate -format "yyyy-MM-ddTHH:mm:ss.fffZ"
#Write-Host $ModifiedDateF
#get and format created date
$CreatedDate = ($version.Created -as [datetime]).DateTime
$CreatedDateF = Get-Date $CreatedDate -format "yyyy-MM-ddTHH:mm:ss.fffZ"
$ReviwerID = ""
#get reviewers
#if status matches an item get review list id
if($version['WFStatus'] -eq 'Review in progress'){
#pass document name and created
$ReviwerID = GetReviews $version['Name'].TrimEnd('.docx') $version.Created
}
#add data
$VersionData = "$($item.id),$($version['WFStatus']),$($FullFileName),$($CreatedDateF),$($ReviwerID)"
#Write to report
Add-Content -Path $ReportFile -Value $VersionData
}
}
}
}
}
GetMetadata
Write-Host "Version history has been exported successfully!"
Output:
Ouput
Sample test script by SharePoint PowerShell, if your issue exists, provide more details for your script.
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$sourceWebURL = "http://sp:12001"
$sourceListName = "TestList"
$CreatedDate = Get-Date
$AddedDateTime = Get-Date $CreatedDate.AddMinutes(190)
$spSourceWeb = Get-SPWeb $sourceWebURL
$ReviewList = $spSourceWeb.Lists[$sourceListName]
$ItemsColl = $ReviewList.Items | where {($_['Created'] -ge $CreatedDate.AddMinutes(-10)) -and ($_['Created'] -le $AddedDateTime)}
Write-Host "CD:" $CreatedDate.AddMinutes(-10)
Write-Host "AD:" $AddedDateTime
$ItemsColl | ForEach-Object {
Write-Host $_['ID']
Write-Host $_['Title']
}
Update:
You could use PowerGUI editor to debug your script, the tool would help you find out most of logic issue.

Powershell ForEach-Object lines in a text file Split compare and delete

Im working on a Powershell script that can put lines from a text file into a list box, but only lines that start with a date ../../....
The add list box part is working. But id like to delete older lines from the text file first.
I tried this but it not correct. Can anyone help me code this correctly.
I will rephrase the question to hopefully make it clearer.
The text file look like this:
text.txt
//Regular Roster | Only update if making a permanent change.
!The order for the entry must be: Day time,number,name,email(optional)
!With a comma ‘,’ separating the values.
Monday 9AM-2PM,0400499449,BILL
Monday 2PM-6PM,074477464,Terry
Monday 6PM-9PM,040484747,Leanne
Tuesday 9AM-2PM,07123456,BILL
Tuesday 2PM-6PM,054647383,Barbara
Tuesday 6PM-9PM,03937464,Mandy
//Changes to Regular Roster. This section will override the above.
!The date order of the entries below is not important but each line must follow this pattern:
!date(Dayxx/Monthxx/Yearxxxx),time(9AM,2PM or 6PM),number,name,email(optional)
!Date slash must be forward facing '/'.
!The only times that can be entered are 9AM,2PM or 6PM.
!With a comma ‘,’ separating the values.
01/01/2019,6AM,0400012345,Kurt,kurt#outlook.com
02/01/2019,6AM,0412345676,Bill,bill#outlook.com
03/01/2019,6AM,0400012345,Sam,Sam#outlook.com
04/01/2019,6AM,0412345676,Barry,barry#outlook.com
05/01/2019,6AM,0400012345,Kurt,kurt#outlook.com
If I try this code in Powershell assuming the current date is 04/01/2019 (4th January 2019) it works fine
$CurrentDate = "04/01/2019"
$Text = "05/01/2019,6AM,0400012345,Kurt,kurt#outlook.com"
$Text | ForEach-Object {
$Roster1Date,$Roster2Time,$Roster3Number,$Roster4Name,$Roster5Email = $_.split(",")
$Newdate = "$Roster1Date"
$CurrentDate = [datetime]::ParseExact("$CurrentDate", 'dd/MM/yyyy', $null)
$Newdate = [datetime]::ParseExact("$Newdate", 'dd/MM/yyyy', $null)
if ($Newdate -ge $CurrentDate) {
write-output "NewDate is bigger than or equal to"
}
else {
write-output "CurrentDate is bigger"
}
};
When I try to build a Listbox with this line it works fine
#Add Listbox
$ShiftsListBox = New-Object System.Windows.Forms.ListBox
$ShiftsListBox.Location = New-Object System.Drawing.Size(400,40)
$ShiftsListBox.Size = New-Object System.Drawing.Size(360,20)
$ShiftsListBox.Height = 160
Get-Content $RosterPath | select-string -Pattern '../../...' | ForEach-Object {[void] $ShiftsListBox.Items.Add($_)};
$FormCreateNewShift.Controls.Add($ShiftsListBox)
When I tried to combine the two it just comes up blank
#Add Listbox
$TextFile = text.txt
$ShiftsListBox = New-Object System.Windows.Forms.ListBox
$ShiftsListBox.Location = New-Object System.Drawing.Size(400,40)
$ShiftsListBox.Size = New-Object System.Drawing.Size(360,20)
$ShiftsListBox.Height = 160
Get-Content $TextFile | select-string -Pattern '../../...' | ForEach-Object {
$Roster1Date,$Roster2Time,$Roster3Number,$Roster4Name,$Roster5Email = $_.split(",")
$Newdate = "$Roster1Date"
$CurrentDate = [datetime]::ParseExact("$CurrentDate", 'dd/MM/yyyy', $null)
$Newdate = [datetime]::ParseExact("$Newdate", 'dd/MM/yyyy', $null)
if ($Newdate -ge $CurrentDate) {
[void] $ShiftsListBox.Items.Add($_)
}
else {
}
};
$FormCreateNewShift.Controls.Add($ShiftsListBox)
The idea is that if the date is greater than or equal to the current date display the line in the list box, else don't. But then I will try to delete the line by adding in a replace line.
#Add Listbox
$TextFile = text.txt
$ShiftsListBox = New-Object System.Windows.Forms.ListBox
$ShiftsListBox.Location = New-Object System.Drawing.Size(400,40)
$ShiftsListBox.Size = New-Object System.Drawing.Size(360,20)
$ShiftsListBox.Height = 160
Get-Content $TextFile | select-string -Pattern '../../...' | ForEach-Object {
$Roster1Date,$Roster2Time,$Roster3Number,$Roster4Name,$Roster5Email = $_.split(",")
$Newdate = "$Roster1Date"
$CurrentDate = [datetime]::ParseExact("$CurrentDate", 'dd/MM/yyyy', $null)
$Newdate = [datetime]::ParseExact("$Newdate", 'dd/MM/yyyy', $null)
if ($Newdate -ge $CurrentDate) {
[void] $ShiftsListBox.Items.Add($_)
}
else {
((Get-Content -path $TextFile) -replace $_,"") | Set-Content -Path $TextFile;
}
};
$FormCreateNewShift.Controls.Add($ShiftsListBox)
Based on new sample file, this script distinguishes
between lines with a leading date
a date from today or later(keep)
a date before today (skip)
other lines (keep)
## Q:\Test\2019\01\01\SO_53992011.ps1
$Rosterpath = ".\rosterpath"
$CurrentDate = (Get-Date).Date # to have a datetime starting today at 00:00:00
$RegEx = [RegEx]"^(?<day>\d{2})\/(?<mon>\d{2})\/(?<year>\d{4})"
$UpdatedContent = Get-Content $RosterPath | ForEach-Object {
If ($_ -match $RegEx){
If((Get-Date -Year $Matches.year -Month $Matches.mon -Day $Matches.day) -ge $CurrentDate){
# yes keep this line
$_
} else {
#drop this line
}
} else {
# line without a date, keep
$_
}
}
$UpdatedContent | Set-Content $RosterPath

Comparing PowerShell / SharePoint list dates

I am trying to use PowerShell to get the dates from a Sharepoint list and compare today's date to see if there is a match.
I have some code so far but it doesn't seem to be working. I am guessing I have some data types wrong when I am doing a comparison or something of that nature. This is the code I have so far below:
$unusableDatesArray is set with a CAML query to a list in SharePoint
The column name of the date field in SharePoint is called 'UnusableDate' and of type date/time
$todaysDate = Get-Date
$foundUnusableDate = $false
ForEach($item in $unusableDatesArray) {
if($item['UnusableDate'] -eq $todaysDate) {
$foundUnusableDate = $true
}
}
Even though both values appear to have 8/10/2017 12:00:00 AM as the value when I find a matching date, $foundUnusableDate never ends up being true. If anyone knows what I am doing wrong please chime in.
-eq is a "hard" comparison operator to get a $true out of it, both variables would need to be at the exact same datetime. This would return $true:
$date1 = [datetime]'8/11/2017 12:00:00'
$date2 = [datetime]'8/11/2017 12:00:00'
if ($date1 -eq $date2) {$true
} else {$false}
while a simple difference of one second would cause it to return $false
$date1 = [datetime]'8/11/2017 12:00:00'
$date2 = [datetime]'8/11/2017 12:00:01'
if ($date1 -eq $date2) {$true} else {$false}
To work around that you can use different approaches
$date1 = [datetime]'8/11/2017 12:00:00'
$date2 = Get-Date
if (('{0:yyyyMMdd}' -f $date1) -eq ('{0:yyyyMMdd}' -f $date2)) {$true} else {$false}
if ($date1.Date -eq $date2.Date) {$true
} else {$false}
$date1 = ([datetime]'8/11/2017 12:00:00').Date
$date2 = (Get-Date).Date
if ($date1 -eq $date2) {$true} else {$false}
$dateToCheck = Get-Date
ForEach($item in $unusableDatesArray) {
[DateTime]$sharePointDate = $item['UnusableDate']
if(Get-Date $sharePointDate -Format 'MM/dd/yyyy') -eq (Get-Date $dateToCheck -Format 'MM/dd/yyyy')) {
$foundUnusableDate = true
}
}
The above is my final solution

Powershell compare months and exclude which are not required

I have a text file as shown below. I need to preserve the files which are within 6 months old (from the previous month) and write every other content to other file which are more than 6 months old.
What I've done so far is like:
$array3 =
do {
foreach($monthl in $monthlookup)
{
$mnthl = $monthl -split '-'
$m_day = $mnthl[1]
$m_month = $mnthl[2]
$m_year = $mnthl[3]
$m_temp = 0
$prevmonth = (Get-Date).AddMonths(-1).ToString("dd-MM-yy")
while(($m_temp -eq "0"))
{
if(($m_month -ge $startmonth) -and ($m_month -le $prevmonth))
{
$monthl | Add-Content "C:\each_month_latest.txt"
break;
}else
{
$monthl | Add-Content "C:\exclusions.txt"
}
}
}
} until ($m_month -ge $m)
What the issue I identified here is like: If the current month is 1, then it wont go back to the last 6 months and check, as I use just strings here.
Any suggestions or code improvements, anyone of you can think of..? Would be really appreciated.
Edit
monthlookup will look like:
testdatabase-30-11-14-23-00
testdatabase-31-12-14-23-00
testdatabase-30-01-15-23-00
testdatabase-31-01-15-23-00
testdatabase-27-05-15-23-00
testdatabase-28-02-15-23-00
testdatabase-31-03-15-23-00
testdatabase-30-04-15-23-00
testdatabase-31-05-15-23-00
$m is $m = Get-Date -Format "MM"
Well, I don't completly understand what you want to do but here some tipps:
$prevmonth = (Get-Date).AddMonths(-1).ToString("dd-MM-yy") shouldn't be done each time within the foreach loop
You could extract the date using a simple regex: [regex]::Match('testdatabase-30-11-14-23-00', '^.*?-(\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$)').Groups[1].Value
Parse the date using [datetime]::ParseExact and a format string
So it could look like this:
# this doesn't have to be done each time in the foreach loop
$sixMonthBefore = (Get-Date).AddMonths(-6)
foreach($monthl in $monthlookup)
{
# extract the date
$dateString = [regex]::Match($monthl, '^.*?-(\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$)').Groups[1].Value
# create a datetime using format string
$date = [datetime]::ParseExact($dateString, 'dd-MM-yy-HH-mm', $null)
if ($date.Month -eq (Get-Date).Month -and $date.Year -eq (Get-Date).Year)
{
Write-Host "$monthl is from this month"
}
elseif ($date -gt $sixMonthBefore)
{
$monthl | Add-Content "C:\each_month_latest.txt"
}
else
{
$monthl | Add-Content "C:\exclusions.txt"
}
}

filtering and though a sharepoint list items with powershell

I have tried below but not getting any result back
Not sure if i'm doing this well.
Can i filter in the foreach or in my if statement
Thanks in advance
[DateTime] $CreatedDate = $item["Created"]
$convertedCreatedDate = $CreatedDate.ToString("yyyy-MM-dd")
$today = (Get-Date).AddDays(-1).ToString("yyyy-MM-dd")
foreach ($item in $list.items | where {$convertedCreatedDate -eq $today}) {
if ($list.items | where {$convertedCreatedDate -eq $today})
{
Write-Host $item["Created"]
}
Write-Host $item["Created"]
}
You can use a complex expression in your foreach as you're doing above. I would wrap it in a #() to make the code a bit more readable and to ensure the result is an array (either length 0, 1 or n) e.g.:
foreach ($item in #($list.items | where {$convertedCreatedDate -eq $today})) {
You can also simplify you're date testing by using the Date property on a DateTime e.g.:
$convertedCreatedDate = ([DateTime]$item["Created"]).Date
$today = (Get-Date).Date
You can also put a complex expression within an if statement condition but PowerShell will only evaluate whether the statement is $true or $false. PowerShell does lots of coercion to try to take something like:
$list.items | where {$convertedCreatedDate -eq $today}
And convert that to a boolean. Essentially if the pipeline evaluates to a non-empty result, the result is $true otherwise it is $false. This is probably not what you intended.
Try this:
$today=(Get-Date).AddDays(-1).ToString("yyyy-MM-dd")
foreach ($item in $list.items) {
[DateTime]$CreatedDate=$item["Created"]
$convertedCreatedDate=$CreatedDate.ToString("yyyy-MM-dd")
if ($convertedCreatedDate -eq $today) {
Write-Host $item["Created"]
}
}