I am working on piece of a powershell script to interact with a directory of excel documents. I have a for each loop to loop through each of the files in a directory open them to then copy and paste the DataBodyRange of listobject(1) to my main document. As stated in the title my issue is as follows: The If($shippedVal.Length -gt 0) statement will not proceed. As if the $shippedVal actually contains no value. When I try to Write-Host $shippedVal the IDE stalls.
Here is the code in question:
foreach($f in $clientPath){
$clientFile = $f.FullName
$clientWorkbook = $excel.Workbooks.open($clientFile)
$clientWorksheet = $clientWorkbook.Worksheets
Write-Host $clientFile
foreach ($ws in $clientWorksheet)
{
Write-Host $ws.Name + "Attempting List Object Count"
If($ws.ListObjects.Count -gt 0)
{
Write-Host "Made it to copy range"
$clientLR = ($ws.UsedRange.Rows.Count +1)
$shippedVal = $ws.ListObjects(1).DataBodyRange.Cells(1)
If($shippedVal.Length -gt 0)
{
Write-Host "Made it to line 41"
$shippedBreakdown = $ws.ListObjects(1).DataBodyRange
$pasteLoc = $mainWorksheet.Range("A" + "&" + $mainLR)
$shippedBreakdown.Copy() | out-null
$mainWorksheet.Paste($pasteLoc)
$mainLR = ($mainWorksheet.UsedRange.Rows.Count + 1)
Write-Host "Pasting DataBodyRange"
}
}
}
$clientWorkbook.Close
}
If you need any additional information please let me know.
Related
I'm kind of new to PowerShell and I need to fix a bank statement file. The problem is that this file has a CNAB 240 standard, however, it comes with a line break, so we have to fix it manually.
I have a script that makes this correction, however, I can't make it run alone because I need to use CMD to run PowerShell.
My idea is to use this script in the task manager to look for the .txt file and fix it, does anyone have any ideas?
Follow the script:
if ($args.count -eq 0)
{
Write-Error "Please enter a file to read"
return
}
$file = $args[0]
if(![System.IO.File]::Exists($file))
{
Write-Error "File not found: $file"
return
}
$expectedsize = 240
$lastSize = 0
foreach($line in [System.IO.File]::ReadLines($file))
{
if ($line.length -gt 0)
{
if (!($row.length -eq $expectedsize) -And (($row.length + $lastSize) -eq $expectedsize))
{
Write-Host -NoNewLine $linha
$lastSize += $line.length
}
else
{
if ($lastSize -gt 0)
{
Write-Host
}
Write-Host -NoNewLine $linha
$lastSize = $line.length
}
}
else
{
Write-Host
}
}
The script above makes the normal correction of the file, however, I am not able to make it follow the steps below:
Browse the txt file
Validate that it does not have the 240 positions in each line
And then make the correction
the below script was created by our pervious IT guy, what this script does is basically replaces the Funduc Software (RSP and RSBE) config file in the logged in user's Appdata so we can modify what the software will search over. E.g. Excel Word etc.
I need to modify this script in such a way that it when ran without any parameter provided it runs as it but if we specify a parameter it automatically runs the config we need.
Right now if we run .\RSUpdateConfigFile.ps1 it starts the script and waits for user to enter a number which corresponds to the extensions we need to search over, this works fine as is.
What we'd like it to do is if we run .\RSUpdateConfigFile.ps1 -L_V_1_String_PreSelection 10 it should execute the script and without prompting the user automatically update the config file with Word extensions.
Below is the code we are using. Any help or advice would be appreciated.
Param(
$L_V_1_String_DisplayComputerName = $env:ComputerName,
$L_V_1_String_DestinationPath = $env:APPDATA,
$L_V_Array_String_ConfigurationFilesToCopy = #(
"A:\Input\Replace Studio.cfg",
"A:\Input\Replace Studio Business Edition.cfg"
),
$L_V_HashTable_String_FileExtensions = [Ordered] #{
"All files" = "*.*";
"All Excel, PowerPoint, Visio, and Word files" = "*.xlm;*.xls;*.xlt;*.xlsm;*.xltm;*.xlsx;*.xltx;*.ppt;*.pps;*.pot;*.pptm;*.ppsm;*.potm;*.pptx;*.ppsx;*.potx;*.vsl;*.vsd;*.vsdx;*.vsdm;*.vssm;*.vstm;*.vssx;*.vstx;*.vss;*.vtt;*.vsw;*.vdx;*.vsx;*.vtx;*.doc;*.dot;*.docm;*.dotm;*.docx;*.dotx";
"All Excel, PowerPoint, Visio, and Word internal files" = "*_A_I_*.xlm;*_A_I_*.xls;*_A_I_*.xlt;*_A_I_*.xlsm;*_A_I_*.xltm;*_A_I_*.xlsx;*_A_I_*.xltx;*_A_I_*.ppt;*_A_I_*.pps;*_A_I_*.pot;*_A_I_*.pptm;*_A_I_*.ppsm;*_A_I_*.potm;*_A_I_*.pptx;*_A_I_*.ppsx;*_A_I_*.potx;*_A_I_*.vsl;*_A_I_*.vsd;*_A_I_*.vsdx;*_A_I_*.vsdm;*_A_I_*.vssm;*_A_I_*.vstm;*_A_I_*.vssx;*_A_I_*.vstx;*_A_I_*.vss;*_A_I_*.vtt;*_A_I_*.vsw;*_A_I_*.vdx;*_A_I_*.vsx;*_A_I_*.vtx;*_A_I_*.doc;*_A_I_*.dot;*_A_I_*.docm;*_A_I_*.dotm;*_A_I_*.docx;*_A_I_*.dotx";
"All Excel files" = "*.xlm;*.xls;*.xlt;*.xlsm;*.xltm;*.xlsx;*.xltx";
"All Excel internal files" = "*_A_I_*.xlm;*_A_I_*.xls;*_A_I_*.xlt;*_A_I_*.xlsm;*_A_I_*.xltm;*_A_I_*.xlsx;*_A_I_*.xltx";
"All PowerPoint files" = "*.ppt;*.pps;*.pot;*.pptm;*.ppsm;*.potm;*.pptx;*.ppsx;*.potx";
"All PowerPoint internal files" = "*_A_I_*.ppt;*_A_I_*.pps;*_A_I_*.pot;*_A_I_*.pptm;*_A_I_*.ppsm;*_A_I_*.potm;*_A_I_*.pptx;*_A_I_*.ppsx;*_A_I_*.potx";
"All Visio files" = "*.vsl;*.vsd;*.vsdx;*.vsdm;*.vssm;*.vstm;*.vssx;*.vstx;*.vss;*.vtt;*.vsw;*.vdx;*.vsx;*.vtx";
"All Visio internal files" = "*_A_I_*.vsl;*_A_I_*.vsd;*_A_I_*.vsdx;*_A_I_*.vsdm;*_A_I_*.vssm;*_A_I_*.vstm;*_A_I_*.vssx;*_A_I_*.vstx;*_A_I_*.vss;*_A_I_*.vtt;*_A_I_*.vsw;*_A_I_*.vdx;*_A_I_*.vsx;*_A_I_*.vtx";
"All Word files" = "*.doc;*.dot;*.docm;*.dotm;*.docx;*.dotx";
"All Word internal files" = "*_A_I_*.doc;*_A_I_*.dot;*_A_I_*.docm;*_A_I_*.dotm;*_A_I_*.docx;*_A_I_*.dotx";
"All Word agreement files" = "*_A_*.doc;*_A_*.dot;*_A_*.docm;*_A_*.dotm;*_A_*.docx;*_A_*.dotx"
"All Word form files" = "*_F_*.doc;*_F_*.dot;*_F_*.docm;*_F_*.dotm;*_F_*.docx;*_F_*.dotx"
"All Word letter files" = "*_L_*.doc;*_L_*.dot;*_L_*.docm;*_L_*.dotm;*_L_*.docx;*_L_*.dotx"
},
$L_V_1_String_Placeholder = "%Placeholder%"
)
Clear-Host
$L_V_1_Integer_Index = 0
$L_V_1_String_Prompt = "Enter the number representing your desired option:`n`n"
foreach ($L_V_1_String_Key in ($L_V_HashTable_String_FileExtensions.Keys))
{
$L_V_1_String_Prompt += "$L_V_1_Integer_Index) "+$L_V_1_String_Key+"`n`n"
$L_V_1_Integer_Index += 1
}
Try
{
$L_V_1_String_UserSelection = Read-Host -Prompt $L_V_1_String_Prompt
if (($L_V_1_String_UserSelection -eq $null) -or (-not($L_V_1_String_UserSelection -match "\d")))
{
Throw
}
else
{
Try
{
#Replace placeholders, and save files to destination.
foreach($L_V_1_String_ConfigurationFileToCopy in $L_V_Array_String_ConfigurationFilesToCopy)
{
$L_V_1_FileInfo_ConfigurationFileToCopy = [io.FileInfo] $L_V_1_String_ConfigurationFileToCopy
$L_V_1_DestinationFilePath = "$L_V_1_String_DestinationPath\"+$L_V_1_FileInfo_ConfigurationFileToCopy.Name
Get-Content $L_V_1_FileInfo_ConfigurationFileToCopy -ErrorAction Stop | Foreach-Object {$_.replace($L_V_1_String_Placeholder , $L_V_HashTable_String_FileExtensions[[int]$L_V_1_String_UserSelection])} | Set-Content -Path $L_V_1_DestinationFilePath -ErrorAction Stop
Write-Host "File '$L_V_1_DestinationFilePath' has been copied!"
}
}
Catch
{
Write-Host $_.Exception.Message
Exit 1
}
}
}
Catch
{
Write-Host "That is not a valid choice!"
Exit 1
}
Write-Host "ComputerName: $L_V_1_String_DisplayComputerName"
Pause
i added your parameter to the script, it should only prompt you when not provided:
Param(
$L_V_1_String_DisplayComputerName = $env:ComputerName,
$L_V_1_String_DestinationPath = $env:APPDATA,
$L_V_Array_String_ConfigurationFilesToCopy = #(
"A:\Input\Replace Studio.cfg",
"A:\Input\Replace Studio Business Edition.cfg"
),
$L_V_HashTable_String_FileExtensions = [Ordered] #{
"All files" = "*.*";
"All Excel, PowerPoint, Visio, and Word files" = "*.xlm;*.xls;*.xlt;*.xlsm;*.xltm;*.xlsx;*.xltx;*.ppt;*.pps;*.pot;*.pptm;*.ppsm;*.potm;*.pptx;*.ppsx;*.potx;*.vsl;*.vsd;*.vsdx;*.vsdm;*.vssm;*.vstm;*.vssx;*.vstx;*.vss;*.vtt;*.vsw;*.vdx;*.vsx;*.vtx;*.doc;*.dot;*.docm;*.dotm;*.docx;*.dotx";
"All Excel, PowerPoint, Visio, and Word internal files" = "*_A_I_*.xlm;*_A_I_*.xls;*_A_I_*.xlt;*_A_I_*.xlsm;*_A_I_*.xltm;*_A_I_*.xlsx;*_A_I_*.xltx;*_A_I_*.ppt;*_A_I_*.pps;*_A_I_*.pot;*_A_I_*.pptm;*_A_I_*.ppsm;*_A_I_*.potm;*_A_I_*.pptx;*_A_I_*.ppsx;*_A_I_*.potx;*_A_I_*.vsl;*_A_I_*.vsd;*_A_I_*.vsdx;*_A_I_*.vsdm;*_A_I_*.vssm;*_A_I_*.vstm;*_A_I_*.vssx;*_A_I_*.vstx;*_A_I_*.vss;*_A_I_*.vtt;*_A_I_*.vsw;*_A_I_*.vdx;*_A_I_*.vsx;*_A_I_*.vtx;*_A_I_*.doc;*_A_I_*.dot;*_A_I_*.docm;*_A_I_*.dotm;*_A_I_*.docx;*_A_I_*.dotx";
"All Excel files" = "*.xlm;*.xls;*.xlt;*.xlsm;*.xltm;*.xlsx;*.xltx";
"All Excel internal files" = "*_A_I_*.xlm;*_A_I_*.xls;*_A_I_*.xlt;*_A_I_*.xlsm;*_A_I_*.xltm;*_A_I_*.xlsx;*_A_I_*.xltx";
"All PowerPoint files" = "*.ppt;*.pps;*.pot;*.pptm;*.ppsm;*.potm;*.pptx;*.ppsx;*.potx";
"All PowerPoint internal files" = "*_A_I_*.ppt;*_A_I_*.pps;*_A_I_*.pot;*_A_I_*.pptm;*_A_I_*.ppsm;*_A_I_*.potm;*_A_I_*.pptx;*_A_I_*.ppsx;*_A_I_*.potx";
"All Visio files" = "*.vsl;*.vsd;*.vsdx;*.vsdm;*.vssm;*.vstm;*.vssx;*.vstx;*.vss;*.vtt;*.vsw;*.vdx;*.vsx;*.vtx";
"All Visio internal files" = "*_A_I_*.vsl;*_A_I_*.vsd;*_A_I_*.vsdx;*_A_I_*.vsdm;*_A_I_*.vssm;*_A_I_*.vstm;*_A_I_*.vssx;*_A_I_*.vstx;*_A_I_*.vss;*_A_I_*.vtt;*_A_I_*.vsw;*_A_I_*.vdx;*_A_I_*.vsx;*_A_I_*.vtx";
"All Word files" = "*.doc;*.dot;*.docm;*.dotm;*.docx;*.dotx";
"All Word internal files" = "*_A_I_*.doc;*_A_I_*.dot;*_A_I_*.docm;*_A_I_*.dotm;*_A_I_*.docx;*_A_I_*.dotx";
"All Word agreement files" = "*_A_*.doc;*_A_*.dot;*_A_*.docm;*_A_*.dotm;*_A_*.docx;*_A_*.dotx"
"All Word form files" = "*_F_*.doc;*_F_*.dot;*_F_*.docm;*_F_*.dotm;*_F_*.docx;*_F_*.dotx"
"All Word letter files" = "*_L_*.doc;*_L_*.dot;*_L_*.docm;*_L_*.dotm;*_L_*.docx;*_L_*.dotx"
},
$L_V_1_String_Placeholder = "%Placeholder%",
$L_V_1_String_PreSelection
)
Clear-Host
$L_V_1_Integer_Index = 0
$L_V_1_String_Prompt = "Enter the number representing your desired option:`n`n"
foreach ($L_V_1_String_Key in ($L_V_HashTable_String_FileExtensions.Keys))
{
$L_V_1_String_Prompt += "$L_V_1_Integer_Index) "+$L_V_1_String_Key+"`n`n"
$L_V_1_Integer_Index += 1
}
Try
{
if ($L_V_1_String_PreSelection){
$L_V_1_String_UserSelection = $L_V_1_String_PreSelection
} else {
$L_V_1_String_UserSelection = Read-Host -Prompt $L_V_1_String_Prompt
}
if (($L_V_1_String_UserSelection -eq $null) -or (-not($L_V_1_String_UserSelection -match "\d")))
{
Throw
}
else
{
Try
{
#Replace placeholders, and save files to destination.
foreach($L_V_1_String_ConfigurationFileToCopy in $L_V_Array_String_ConfigurationFilesToCopy)
{
$L_V_1_FileInfo_ConfigurationFileToCopy = [io.FileInfo] $L_V_1_String_ConfigurationFileToCopy
$L_V_1_DestinationFilePath = "$L_V_1_String_DestinationPath\"+$L_V_1_FileInfo_ConfigurationFileToCopy.Name
Get-Content $L_V_1_FileInfo_ConfigurationFileToCopy -ErrorAction Stop | Foreach-Object {$_.replace($L_V_1_String_Placeholder , $L_V_HashTable_String_FileExtensions[[int]$L_V_1_String_UserSelection])} | Set-Content -Path $L_V_1_DestinationFilePath -ErrorAction Stop
Write-Host "File '$L_V_1_DestinationFilePath' has been copied!"
}
}
Catch
{
Write-Host $_.Exception.Message
Exit 1
}
}
}
Catch
{
Write-Host "That is not a valid choice!"
Exit 1
}
Write-Host "ComputerName: $L_V_1_String_DisplayComputerName"
Pause
I've tried to create a visual studio solution with nested solution folders through Powershell (envdte). Everything works up to 1 level deep, but nesting a solution folder doesn't seem to work (interface is null). The issue is described in this SO question:
Creating a tree of Solution Folders using DTE and Package Manager Console
Unfortunately that question hasn't been answered yet. I've reachted out to the poster of that question but he had taken another route within his solution so the question is still open.
An excerpt of my code. The Find-Solution method finds the solutionfolder I'm looking for within the given context (= startfolder). When found, it returns this item:
function Find-SolutionFolder {
Param($SearchedFolderName, $StartFolder)
Write-Output "number " $StartFolder.ProjectItems.Count
For ($i = 1; $i -le $StartFolder.ProjectItems.Count; $i++) {
$Item = $StartFolder.ProjectItems.Item($i)
if ($Null -Eq $Item.Object) {
continue;
}
if ($Item.Object.Kind -eq [EnvDTE80.ProjectKinds]::vsProjectKindSolutionFolder) {
if ($Item.Name -Eq $SearchedFolderName) {
return $Item
}
Find-SolutionFolder $SearchedFolderName $Item
}
}
}
The Add-Projects method takes care of saving the structure to the solution. The structure is:
Solution
ModuleTypeFolder (ie. Foundation)
ModuleGroupFolder (optional)
Folder for project
projectfiles
This is a nested structure. Everything works without the ModuleGroupFolder but when the structure has the ModuleGroupFolder it causes the error due to the null result of the Get-Interface. I've confirmed that the correct solution folder is found. It's just the variable $moduleGroupNameFolderInterface is null.
The parameter modulePath is the path on disk
function Add-Projects {
Param(
[Parameter(Position = 0, Mandatory = $True)]
[string]$ModulePath
)
Write-Output "Adding project(s)..."
# For the sake of the example always use a folder named 'Foundation'
$moduleTypeFolder = Get-FoundationSolutionFolder
# When the literal 'Foundation' solution folder does not exist in the solution it will be created.
if (-Not $moduleTypeFolder) {
$dte.Solution.AddSolutionFolder($config.ModuleType)
$moduleTypeFolder = Get-ModuleTypeSolutionFolder
}
$moduleTypeFolderInterface = Get-Interface $moduleTypeFolder.Object ([EnvDTE80.SolutionFolder])
# Add ModuleGroup Folder if needed
if (-Not [string]::IsNullOrWhiteSpace($config.ModuleGroupName)) {
$moduleGroupNameFolder = Find-SolutionFolder $config.ModuleGroupName $moduleTypeFolder
if (-Not $moduleGroupNameFolder) {
$moduleTypeFolderInterface.AddSolutionFolder($config.ModuleGroupName)
$moduleGroupNameFolder = Find-SolutionFolder $config.ModuleGroupName $moduleTypeFolder
}
$moduleGroupNameFolderInterface = Get-Interface $moduleGroupNameFolder.Object ([EnvDTE80.SolutionFolder])
if ($Null -eq $moduleGroupNameFolderInterface) {
Write-Output "moduleGroupNameFolderInterface is null; this is wrong"
} else {
$moduleNameFolder = $moduleGroupNameFolderInterface.AddSolutionFolder($config.ModuleName)
$moduleNameFolderInterface = Get-Interface $moduleNameFolder.SubProject ([EnvDTE80.SolutionFolder])
# Search in the new module folder for csproj files and add those to the solution.
Get-ChildItem -File -Path $ModulePath -Filter "*$csprojExtension" -Recurse | ForEach-Object { $moduleNameFolderInterface.AddFromFile("$($_.FullName)")}
}
} else {
$moduleNameFolder = $moduleTypeFolderInterface.AddSolutionFolder($config.ModuleName)
$moduleNameFolderInterface = Get-Interface $moduleNameFolder.Object ([EnvDTE80.SolutionFolder])
# Search in the new module folder for csproj files and add those to the solution.
Get-ChildItem -File -Path $ModulePath -Filter "*$csprojExtension" -Recurse | ForEach-Object { $moduleNameFolderInterface.AddFromFile("$($_.FullName)")}
}
Write-Output "Saving solution..."
$dte.Solution.SaveAs($dte.Solution.FullName)
}
Note. the example is not optimized (ie. duplicate code)
Can anybody help me solve the issue.
Update - answer to question
I finally figured it out. Apparently when finding a nested solution folder where property Kind has guid {66A26722-8FB5-11D2-AA7E-00C04F688DDE} it's not the correct object yet. You have to use the object within the found item.
So basically you are looking for recursion. You can recurse like this.
For the solutions folder:
function RecurseSolutionFolderProjects(){
param($solutionFolder = $(throw "Please specify a solutionFolder"))
$projectList = #()
for($i = 1; $i -le $solutionFolder.ProjectItems.Count; $i++){
$subProject = $solutionFolder.ProjectItems.Item($i).subProject
if($subProject -eq $null){
continue;
}
if($subProject.Kind -eq [EnvDTE80.ProjectKinds]::vsProjectKindSolutionFolder)
{
$projectList += RecurseSolutionFolderProjects($subProject)
} else {
$projectList += $subProject
}
}
return $projectList
}
For Project Files:
function GetProjectFiles(){
param($project = $(throw "Please specify a project"))
write-debug ("getting project files for " + $project.Name + " "+ $project.ProjectName)
$projectItems = RecurseDescendants($project.ProjectItems)
return $projectItems | Where-Object {$_.Kind -ne [EnvDTE.Constants]::vsProjectItemKindPhysicalFolder}
}
For Project Items:
function GetProjectItems(){
param($project = $(throw "Please specify a project"))
if($project.ProjectItems.count -gt 0){
write-debug "getting project items for '$project.Name' '$project.ProjectName'"
}
#example: GetProjectItems((GetSolutionProjects).get_Item(1))
$result =RecurseDescendants($project.ProjectItems)
return $result
}
Refer the Solution Hierarchy answer where the above functions are neatly explained
You can get the latest version from this GitHub Link
Hope it helps.
This question already has answers here:
Why does 'continue' behave like 'break' in a Foreach-Object?
(4 answers)
Closed 5 years ago.
So I've been writing a script that will take all of the data that is stored in 238 spreadsheets and copy it into a master sheet, as well as 9 high level report sheets. I'm really not sure why, but after a specific document, the script ends prematurely without any errors being posted. It's very strange. I'll post some anonymized code below so maybe someone can help me find the error of my ways here.
As far as I can tell, the document that it exits after is fine. I don't see any data errors in it, and the info is copied successfully to the master document before powershell just calls it quits on the script completely.
I've tried changing the size of the data set by limiting only to the folder that contains the problem file. It still ends after the same file with no error output. I cannot upload the file due to company policy, but I really don't see anything different about the data on that one file when compared to any other file of the same nature.
Also, apologies in advance for the crappy code. I'm not a developer and have been relearning powershell since it's the only tool available to me right now.
$StartTime = Get-Date -Format g
Write-Host $StartTime
pushd "Z:\Shared Documents\IO"
$TrackTemplate = "C:\Users\USERNAME\Desktop\IODATA\MasterTemplate.xlsx"
# Initialize the Master Spreadsheet
$xlMaster = New-Object -ComObject Excel.Application
$xlMaster.Visible = $False
$xlMaster.DisplayAlerts = $False
$MasterFilePath = "C:\Users\USERNAME\Desktop\IODATA\Master.xlsx"
Copy-Item $TrackTemplate $MasterFilePath
$wbMaster = $xlMaster.Workbooks.Open($MasterFilePath)
$wsMaster = $wbMaster.Worksheets.Item(2)
$wsMaster.Unprotect("PASSWORD")
$wsMasterRow = 3
# Initialize L4 Document Object
$xlL4 = New-Object -ComObject Excel.Application
$xlL4.Visible = $False
$xlL4.DisplayAlerts = $False
# Initialize object for input documents
$xlInput = New-Object -ComObject Excel.Application
$xlInput.Visible = $False
$xlInput.DisplayAlerts = $False
# Arrays used to create folder path names
$ArrayRoot = #("FOLDER1","FOLDER2","FOLDER3","FOLDER4","FOLDER5","FOLDER6","FOLDER7","FOLDER8","FOLDER9")
$ArrayShort = #("SUB1","SUB2","SUB3","SUB4","SUB5","SUB6","SUB7","SUB8","SUB9")
# $counter is used to iterate inside the loop over the short name array.
$counter = 0
$FileNumber = 0
$TotalFiles = 238
$ArrayRoot | ForEach-Object {
$FilePathL4 = "C:\Users\USERNAME\Desktop\IODATA\ROLLUP\" + $ArrayShort[$counter] + "_DOC_ROLLUP.xlsx"
Copy-Item $TrackTemplate $FilePathL4
$wbL4 = $xlL4.Workbooks.Open($FilePathL4)
$wsL4 = $wbL4.Worksheets.Item(2)
$wsL4.Unprotect("PASSWORD")
$wsL4Row = 3
If ($ArrayShort[$counter] -eq "SUB7") {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\" + $ArrayShort[$counter] + " - DOC v2\"}
Else {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\!" + $ArrayShort[$counter] + " - DOC v2\"}
Get-ChildItem -Path $FilePath | ForEach-Object {
If ($_.Name -eq "SPECIFIC_DOC.xlsx") {Continue}
$FileNumber += 1
Write-Host "$FileNumber / $TotalFiles $_"
$wbInput = $xlInput.Workbooks.Open($_.FullName)
$wsInput = $wbInput.Worksheets.Item(2)
$wsInputLastRow = 0
#Find the last row in the Input document
For ($i = 3; $i -le 10000; $i++) {
If ([string]::IsNullOrEmpty($wsInput.Cells.Item($i,1).Value2)) {
$wsInputLastRow = $i - 1
Break
}
Else { Continue }
}
[void]$wsInput.Range("A3:AC$wsInputLastRow").Copy()
Start-Sleep -Seconds 1
[void]$wsMaster.Range("A$wsMasterRow").PasteSpecial(-4163)
Start-Sleep -Seconds 1
$wsMasterRow += $wsInputLastRow - 2
[void]$wsL4.Range("A$wsL4Row").PasteSpecial(-4163)
Start-Sleep -Seconds 1
$wsL4Row += $wsInputLastRow - 2
$wbInput.Close()
$wbMaster.Save()
}
$counter += 1
$wsL4.Protect("PASSWORD")
$wbL4.Save()
$wbL4.Close()
}
$wsMaster.Protect("PASSWORD")
$wbMaster.Save()
$wbMaster.Close()
$xlMaster.Quit()
$EndTime = Get-Date -Format g
$TimeTotal = New-Timespan -Start $StartTime -End $EndTime
Write-Host $TimeTotal
To continue pipeline processing with the next input object, use return - not continue - in the script block passed to the ForEach-Object cmdlet.
The following simple example skips the 1st object output by Get-ChildItem and passes the remaining ones through:
$i = 0; Get-ChildItem | ForEach-Object{ if ($i++ -eq 0) { return }; $_ }
There is currently (PSv5.1) no direct way to stop the processing of further input objects - for workarounds, see this answer of mine.
By contrast, as you've discovered, break and continue only work as expected in the script block of a for / foreach statement, not directly in the script block passed to the ForeEach-Object cmdlet:
For instance, the following produces no output (using break would have the same effect):
$i = 0; Get-ChildItem | ForEach-Object{ if ($i++ -eq 0) { continue }; $_ }
The reason is that continue and break look for an enclosing for / foreach statement to continue / break out of, and since there is none, the entire command is exited; in a script, the entire script is exited if there's no enclosing for / foreach / switch statement on the call stack.
I am trying to build a custom script for URL monitoring. I am able to run the URL's from the file and enter the same in a logfile(named with time stamp).
Till here I have completed
Issue is when I compare the values from present(present timestamp) and previous logfile(previous timestamp).
This portion is not working fine. Please help me correct it.
Here is my code trying to compare value line by line from present logfile and previous logfile and run commands to generate output:
# New log is new logfile data
$Newlog = Get-Content $URLlogfile
$old_file = Dir C:\Scripts\logs | Sort CreationTime -Descending | Select Name -last 1
# Old log is Old logfile data
$oldlog = Get-Content $old_file -ErrorAction SilentlyContinue
Foreach($logdata in $Newlog) {
$url = ($logdata.Split(" "))[0]
$nodename = ($logdata.Split(" "))[1]
$statuscheck = ($logdata.Split(" "))[2]
$description = ($logdata.Split(" "))[3]
$statuscode = ($logdata.Split(" "))[4]
Foreach($log1data in $oldlog) {
$url1 = ($log1data.Split(" "))[0]
$nodename1 = ($log1data.Split(" "))[1]
$statuscheck1 = ($log1data.Split(" "))[2]
$description1 = ($log1data.Split(" "))[3]
$statuscode1 = ($log1data.Split(" "))[4]
While ($url = $url1) {
if ($statuscheck = $statuscheck1 ) {
write-output "output is same"
} elseif ($statuscheck = Fail) {
While ($statuscheck1 = Pass) {
write-output "$url is down at $nodename1- testing event sent"
}
} elseif ($statuscheck = Pass) {
While ($statuscheck1 = Fail) {
write-output "$url is up at $nodename1- testing event sent"
}
}
}
Break
}
}
#At end am clearing the old logs except present one
dir C:\Scripts\logs -recurse | where { ((get-date)-$_.creationTime).minutes -gt 3 } | remove-item -force
Per the comment from BenH, the following part of your code needs correcting as follows:
If ($url -eq $url1) {
if ($statuscheck -eq $statuscheck1 ) {
write-output "output is same"
} elseif ($statuscheck -eq 'Fail' -and $statuscheck1 -eq 'Pass') {
write-output "$url is down at $nodename1- testing event sent"
} elseif ($statuscheck -eq 'Pass' -and $statuscheck1 -eq 'Fail') {
write-output "$url is up at $nodename1- testing event sent"
}
}
Corrections:
In your comparison statements the = needs to be -eq. In PowerShell = always assigns a value.
In your comparison statements Pass and Fail need to be surrounded by single quotes so they are treated as strings (otherwise they are treated like function statements, for functions which don't exist).
I've replaced the While statements with If statements. I'm not sure what the intent of those was but I think they'd just get stuck in an infinite loop as the variable they test is never changed from within the loop.