Powershell - concatenating an array reference with another variable - powershell

I'm trying to concatenate a variable with a value from an array, and having problems.
The output I get is the variable value, plus the ENTIRE array, not just the desired value (index of $i).
$Database = "Checklist.dbo."
$ExtractTables = #("Page"
, "HotelOwner"
, "Hotel"
)
for ($i=0; $i -le $ExtractTables.Length – 1; $i++) {
write-host $Database$ExtractTables[$i] # <<<<<<< takes ENTIRE array
}
My ultimate goal is to call an executable (bcp) something like this:
# & bcp $Database$ExtractTables[$i] out $OutputDirectory$ExtractTables[$i].txt -c -T -SCHELDEV02
Any pointers for a newbie?
Thanks!

$Database = "Checklist.dbo."
$ExtractTables = #("Page"
, "HotelOwner"
, "Hotel"
)
for ($i=0; $i -le $ExtractTables.Length – 1; $i++) {
write-host "$Database$($ExtractTables[$i])"
}
To evaluate a sub-expression before the rest of the expression put it inside $()

$Database = "Checklist.dbo."
$ExtractTables = #("Page"
, "HotelOwner"
, "Hotel"
)
$ExtractTables | ForEach {
write-host "$Database$_"
}

Related

Displaying user inputs with powershell

say I have an array
$something = #(
"first",
"second"
)
how can I display this to the user as
1. first
2. second
Selection :
I am able to do this by hash table and manually mapping
#{
1="first"
2="second"
};
and doing the following
$something.Keys | sort |% { Write-Host $_ ")" $something.Item($_) }
[int32]$constuctPayload.Action = Read-Host
but if need to perform this using an array how can I do this. I.e looping over the item and displaying with index for user selection. ?
You could use the IndexOf() method, to find the index in the array.
$something | ForEach-Object {Write-Host "$([Array]::IndexOf($something, $_)). $_ "}
Standard warning about being careful with Write-Host. Also you might want to look into Out-GridView.
Use a for loop to iterate over the elements of the array and prepend each value with the index + 1.
$something = 'first', 'second'
for ($i = 0; $i -lt $something.Count; $i++) {
Write-Host ('{0}. {1}' -f ($i+1), $something[$i])
}
[int32]$constuctPayload.Action = Read-Host -Prompt 'Selection'
I would recommend using the PromptForChoice() method over Read-Host, though:
$something = '&first', '&second'
$title = 'The title.'
$msg = 'Selection?'
$choices = $something | ForEach-Object {
New-Object Management.Automation.Host.ChoiceDescription $_
}
$options = [Management.Automation.Host.ChoiceDescription[]] $choices
$default = 0
$constuctPayload.Action = $Host.UI.PromptForChoice($title, $msg, $options, $default)

Powershell Word Table single row error

I have the following function that I provide 3 arrays as variables
$columnHeaders = #('Ticket ID', 'Date Raised', 'Title', 'Status' )
$columnproperties = #('number', 'opened_at', 'short_description', 'state')
$contents
$contents has multiple rows of data matching the columns above, however sometimes may only have 1 row. When the $contents only has 1 row the below function errors out and doesnt print the data.
Using ISE I traced the issue to the $contents.count not showing a value, why is this? is there a way to get around it?
function TableOutput ($columnHeaders, $columnProperties, $contents){
# Number of columns
$columnCount = $columnHeaders.Count
# Create a new table
$docTable = $Word.ActiveDocument.Tables.Add($Word.Selection.Range,$contents.Count,$columnCount)
# Table style
$doctable.Style = "Adapt Table"
# Insert the column headers into the table
for ($col = 0; $col -lt $columnCount; $col++) {
$cell = $docTable.Cell(1,$col+1).Range
$cell.Font.Bold=$true
$cell.InsertAfter($columnHeaders[$col])
}
$doctable.Rows.Add() > Null
# Load the data into the table
$i = 1
$j = $contents.Count
for($row = 2; $row -lt ($contents.Count + 2); $row++){
if($row -gt 2){
}
for ($col = 1; $col -le $columnCount; $col++){
Write-Progress -Activity "Processing Table Information" -Status "Adding Row entry $i of $j" -PercentComplete (100*$i/$j)
$cell = $docTable.Cell($row,$col).Range
$cell.Font.Name="Calibri"
$cell.Font.Size="10"
$cell.Font.Bold=$FALSE
$cell.Text = $contents[$row-2].($columnProperties[$col-1])
}
$i++
}
$doctable.Columns.AutoFit()
}
any help is greatly appreciated.
Cast $content as an array of strings and see if that doesn't work better for you.
function TableOutput ($columnHeaders, $columnProperties, [string[]]$contents){
Edit: Sorry, my bad, you are passing objects with properties ad descripbed in $columnheaders, so you would need to cast it as an array of objects instead:
function TableOutput ($columnHeaders, $columnProperties, [object[]]$contents){
Tested on my end, it works fine with 1 object being passed to the function, as well as an array of two objects being passed to the function.

Method returning string but is assigned as string[]

I have this code:
[string]$emailBody = getEmailBody $firstName $emailTemplateFileContent
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i])
}
$emailTemplateText = $sb.ToString()
$emailTemplateTextCustomised = $emailTemplateText.Replace("#name", $firstName)
return $emailTemplateTextCustomised
}
When I type $emailTemplateTextCustomised.getType() I can see that it is a string.
However when I type $emailBody.getType() I can see that it is an Array.
I can also see that the array has 8 strings, each string containing the output from getEmailBody().
UPDATE:
Powershell seems really buggy, it is no longer a String[] but just a String with 8 repetitions of the output from getEmailBody().
Why is it doing this?
Thanks in advance.
PowerShell isn't buggy, well at least not in this case. :-) You have to understand that in PowerShell the "output" of a function is anything that is not captured to a variable. The line that does the StringBuilder.AppendLine() returns the StringBuilder and that is added to the output of your function. Try this:
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i]) > $null
}
$emailTemplateText = $sb.ToString()
$emailTemplateText.Replace("#name", $firstName)
}
If you are on V3 (maybe V2) you can use the -replace operator as well:
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i]) > $null
}
$emailTemplateText = $sb.ToString() -replace '#name',$firstName
$emailTemplateText
}

How to declare and get array value

I am new to Powershell, first time using it.
I have declared an array and use array value but using below code, I am not able to retrieve the array value...Any idea what I am missing here?
Just FYI.. I am executing script in ADOBE ILLUSTRATOR and for testing I am using 3 here in condition (for loop)... will use $array later
$array = "a.jpg","b.jpg","c.jpg";
for ($i=1; $i-le=3; $i++)
{
$.writeln("This is line number " + $array[$i]);
var targetFileName = $array[$i]+'.png';
$.writeln(targetFileName);
}
I tried $array[$i].toString() as well but still not getting values... I am getting 0
Any help is appreciated and thanks in advance to all for your help
for ($i=1; $i-le=3; $i++)
The condition in the above line doesn't have a valid comparison operator. Change that to
for ($i=1; $i -le 3; $i++)
if you want the loop to terminate after 3 cycles.
$.writeln("This is line number " + $array[$i]);
var targetFileName = $array[$i]+'.png';
$.writeln(targetFileName);
This is not valid PowerShell. Looks more like JavaScript to me. In PowerShell it should probably look like this:
Write-Output "This is line number $i"
$targetFileName = $array[$i] + '.png'
Write-Output $targetFileName
or shorter
"This is line number $i"
$array[$i] + '.png'
Note that PowerShell arrays are zero-based, so the last iteration ($array[3]) will return $null instead of an element from the array. If you want to iterate over the elements of the array you should change your loop to this:
for ($i=0; $i -lt $array.Length; $i++) {
"This is line number $($i+1)"
$array[$i] + '.png'
}
or (better) pipe your array into a foreach loop:
$i = 0
$array | % {
"This is line number " + ++$i
$_ + '.png'
}

Referencing Powershell array index produces unexpected results when referenced with string

I am trying to find out why the following occurs if you have
$arr = #("Filename1", "Filename2")
for($i =0; $i -le $arr.Length -1; $i++) {
write-host ".\"$arr[$i]
write-host ".\$arr[$i]"
write-host $arr[$i]
}
So taking just one loop through it produces:
".\ Filename1"
".\ Filename1 Filename2[0]"
"Filename1"
Just referencing the array[index] will produce the correct value, but if I concatenated with a string it places a space between the string and value. When placed within the string I assume it is dumping the entire contents because it is evaluating $array then evaluating $i ending up with
".\ filename1 filename2[index number]"
But if I assign the individual value to a separate variable and concatenate it with a string there is no space? Why is that:
Example:
$name = $arr[$i]
write-host ".\$name"
output = ".\filename1"
which is correct.
You have to do:
write-host ".\$($arr[$i])"
so that it is evaluated as array indexing.
It would be the case with something like accessing properties of an object or key of hash etc within the string:
PS > $a = #{test="A";test2="B"}
PS > write-host "$a.test"
System.Collections.Hashtable.test
PS > write-host "$($a.test)"
A
Another alternative is to use string formatting, especially useful when you have lots of variables / objects in the string:
write-host (".\{0}" -f $arr[$i])
Your code should look like this:
$arr = #("Filename1", "Filename2")
#for($i =0; $i -le $arr.Length-1; $i++) {
for($i =0; $i -le $arr.Length; $i++) {
write-host ".\"$arr[$i]
#write-host ".\$arr[$i]"
write-host ".\$($arr[$i])"
write-host $arr[$i]
}