How to get specific number of rows from Excel in powershell - windows

I need to get first 35 rows (including empty rows) from column A to a variable.
I looked in the internet but I cannot find the answer anywhere. $data = $worksheet.Range("A1:A35").text returns only cell A1. I tried with Cell.item etc. but with no success. Does anyone know how to extract cell range A1:A35 from excel into variable and save it to the text file? Thanks in advance.
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.workbooks.open("*PATH_TO_THE_FILE*.xlsx")
$worksheet = $workbook.sheets.item("MatrixFill")
$data = $worksheet.Range("A1:A35").text
$excel.Quit()

the text property you are trying to access is actually an object, so you have to treat it as such. Also for ranges you will need to use a , instead of :. Below will give you what you need. It worked for me when I tested it.
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.workbooks.open("*PATH_TO_THE_FILE*.xlsx")
$worksheet = $workbook.sheets.item("MatrixFill")
$worksheet.Range("A1","A35") | select -expand text |out-file "textfilename.txt"
$excel.Quit()
or
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.workbooks.open("*PATH_TO_THE_FILE*.xlsx")
$worksheet = $workbook.sheets.item("MatrixFill")
$data = $worksheet.Range("A1","A35") | select -expand text
$data | out-file "textfilename.txt"
$excel.Quit()

Related

Is there any way linking GPO with ou using the ou canonical name?

Is there a way i can link GPO with an OU by its canonical name?
New-Gplink -gpo <gponame> -target <CANONICAL NAME>
From what I've read we can use only the distinguished name. maybe there's a way around it?
Im using this to save all of them in a variable
$test=Get-ADOrganizationalUnit -Filter * -Properties CanonicalName | Select-Object -Property CanonicalName
now using a gui i open a window for the user to select an ou from there
foreach ($item in $test){
[void]$listbox.items.add($item)}
So now i can catch the user choise by using:
$catch = $listbox.selected.item
so if i now would like to link the gpo using
new-gplink -gpo <gponame> -target $catch
I will get an error.
Any help would be much appreciated!
Try it this way:
# Get the OU objects, which include the DN, plus the CN
$test = Get-ADOrganizationalUnit -Filter * -Properties CanonicalName
# Add the values to your listbox - there's an AddRange method for arrays
[void]$listbox.Items.AddRange($test.CanonicalName)
# Find the object that matches the currently selected Canonical Name
$CatchDN = $test | Where-Object { $_.CanonicalName -eq ($listbox.SelectedItem) }
# Because $CatchDN is an object, just link the GPO using the object.
New-GpLink -Name <gponame> -Target $CatchDN
No tested the above using forms, but it should work as intended.
Ok, using your own form code:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'GPO Connector V1.0'
$form.Size = '600,200'
$form.StartPosition = 'CenterScreen'
$button1 = New-Object System.Windows.Forms.Button
$button1.Location = '10,120'
$button1.Size = '75,23'
$button1.Text = 'Link'
$button1.Anchor = 'Left,Bottom'
$button1.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $button1
$button2 = New-Object System.Windows.Forms.Button
$button2.Location = '90,120'
$button2.Size = '75,23'
$button2.Text = 'UnLink'
$button2.Anchor = 'Left,Bottom'
$Button2.Add_Click($Button2_Click)
$label = New-Object System.Windows.Forms.Label
$label.Location = '80,20'
$label.Size = '480,20'
$label.Text = 'SELECT GPO And Corresponding OU (ONLY WORKSTATION OU)'
$form.Controls.AddRange(#($label,$button1,$button2))
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = '10,40'
$listBox.Size = '260,80'
$listbox.Anchor = 'Top,Left,Bottom'
$listBox2 = New-Object System.Windows.Forms.ListBox
$listBox2.Location = '300,40'
$listBox2.Size = '260,80'
$listbox2.Anchor = 'Top,Left,Bottom,Right'
$form.Controls.AddRange(#($listBox,$listBox2))
$button1.Add_Click({
# Find the object that matches the currently selected Canonical Name
$CatchDN = $Script:OUlist | Where-Object { $_.CanonicalName -eq ($listbox2.SelectedItem) }
Write-Host "Selected CN object: $CatchDN"
# Because $CatchDN is an object, just link the GPO using the object.
$LinkedGP = $Script:GPOlist | Where-Object { $_.DisplayName -eq ($listBox.SelectedItem) }
Write-Host "Selected GPO: "$LinkedGP.DisplayName
$LinkedGP | New-GpLink -Target $CatchDN -WhatIf
})
# Show form first, then load data to lists
$form.Add_Shown({
# Retrieve GPO list
$Script:OUlist = Get-ADOrganizationalUnit -Filter * -Properties CanonicalName
# Add OU CN to listbox
$listbox2.Items.AddRange($Script:OUlist.CanonicalName)
$Script:GPOlist = Get-GPO -All # list of GPO
$listbox.Items.AddRange($Script:GPOlist.DisplayName)
})
$form.Topmost = $true
$result = $form.ShowDialog()
$form.Dispose()

Export to 2nd+ spreadsheet

I'm using Export-Csv to export [pscustomobject]s. Then I'm using a second function to convert that into a xlsx. Which works perfect. But what if I wanted to export into the second spreadsheet and rename it to something different?
I know Export-Csv doesn't support multi spread sheets.
Function SaveAsXLXS
{
#Hide Old File
(Get-Item $ResultsFilePath -Force).Attributes = "Hidden"
#Opens Old File
$Excel = New-Object -ComObject Excel.Application
$Workbook = $Excel.Workbooks.Open($ResultsFilePath)
#Formating
if ($GroupsTab.IsSelected -or $OrgBoxesTab.IsSelected)
{
$Workbook.Worksheets.Item(1).Columns.Item(1).Font.Bold = $True
$Workbook.Worksheets.Item(1).Columns.Item(1).Font.Size = 12
}
$Workbook.Worksheets.Item(1).Rows.Item(1).Font.Bold = $True
$Workbook.Worksheets.Item(1).Rows.Item(1).Font.Size = 15
$Workbook.Worksheets.Item(1).UsedRange.EntireColumn.Autofit()
#Creates Name for New File
$ExcelOut = $ResultsFilePath -replace '\.csv$', '.xlsx'
$dir = Split-Path $ExcelOut
$FilePathBase = $(Split-Path $ExcelOut -Leaf) -replace '\.xlsx$'
$FilePath = $ExcelOut
$n = 1
while (Test-Path $FilePath) {
$FilePath = Join-Path $dir $($FilePathBase + "-$n" + '.xlsx')
$n++
}
#Saves New File
$Workbook.SaveAs($FilePath, 51)
#Exits Old File
$Excel.Quit()
#Removes Old File
Remove-Item $ResultsFilePath -Force
}
You're opening the CSV as a new workbook, so you just need to open the workbook to which you want to add it as well and move/copy the sheet.
...
$Workbook = $Excel.workbooks.open($ResultsFilePath)
...
$wb2 = $Excel.Workbooks.Open('C:\path\to\other.xlsx')
$Workbook.Sheets.Item(1).Name = 'whatever' # rename sheet
$Workbook.Sheets.Item(1).Copy($wb2.Sheets.Item(1)) # copy sheet
$Workbook.Close($false) # close CSV without saving
$wb2.Save() # save & close workbook
$wb2.Close()
Of course, if you want to insert multiple CSVs into a workbook you'd open the xlsx file just once and save/close it after all sheets were inserted.
If you want to insert sheets from a CSV after a particular sheet in the destination workbook change the Copy() call to something like this:
$Workbook.Sheets.Item(1).Copy([Type]::Missing, $wb2.Sheets.Item(3))

Powershell API Post Variable to Ducksboard

Trying to use the following Powershell script which I've taken from Github to push data into a Ducksboard dashboard. The function works excellently however I need to feed in a variable as part of the data. Of the two calls to the function included below the function which pushes in the actual value 44 works fine, however if I substitute it for my variable $qtybord the function falls over. I've tried a number of options to overcome the var being within the single quotes but cannot get it to work - can anyone help me?
# Squirt data to Duscksboard
function Execute-DucksboardApi
{
param(
[string] $url = $null,
[string] $data = $null,
[string] $apikey = $null,
[string] $contentType = "application/json",
[string] $codePageName = "UTF-8",
[string] $userAgent = $null
);
if ($url -and $data -and $apikey)
{
[System.Net.WebRequest]$webRequest = [System.Net.WebRequest]::Create($url);
$webRequest.ServicePoint.Expect100Continue = $false;
[System.Net.NetworkCredential]$credentials = New-Object System.Net.NetworkCredential($apikey, 'ignored');
$webRequest.Credentials = $credentials.GetCredential($url, 'Basic');
$webRequest.PreAuthenticate = $true;
$webRequest.ContentType = $contentType;
$webRequest.Method = "POST";
if ( $userAgent )
{
$webRequest.UserAgent = $userAgent;
}
$enc = [System.Text.Encoding]::GetEncoding($codePageName);
[byte[]]$bytes = $enc.GetBytes($data);
$webRequest.ContentLength = $bytes.Length;
[System.IO.Stream]$reqStream = $webRequest.GetRequestStream();
$reqStream.Write($bytes, 0, $bytes.Length);
$reqStream.Flush();
$resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader]$sr = New-Object System.IO.StreamReader -argumentList $rs;
$sr.ReadToEnd();
}
}
$qtybord = 44
Execute-DucksboardApi -url 'https://push.ducksboard.com/v/123752/' -data '{"value": $qtybord}' -apikey 'tu2j3d3epqytWZD1haHnjJSJ1NqBrmvPe5SONc0VYge4BbIPi0'
Execute-DucksboardApi -url 'https://push.ducksboard.com/v/123752/' -data '{"value": 44}' -apikey 'tu2j3d3epqytWZD1haHnjJSJ1NqBrmvPe5SONc0VYge4BbIPi0'
*
try this:
-data "{`"value`": $qtybord}"
or
-data "{""value"": $qtybord}"
in single quote variable aren't expanded, in double quote you need to escape the double quote inside the string.
So make the -data parameter take $data instead and make $data = '{"value": ' + $qtyboard + '}' or just wrap that whole thing in parens after -data.
Also, if you're on PowerShell v3 you can play with something like this:
$data = New-Object -Type PSObject -Property #{
value = $qtyboard
} | ConvertTo-JSON

formatting csv files and powershell

Ok so we have a manual process that runs through PL/SQL Developer to run a query and then export to csv.
I am trying to automate that process using powershell since we are working in a windows environment.
I have created two files that seems to be exact duplicates from the automated and manual process but they don't work the same so I assume I am missing some hidden characters but I can't find them or figure out how to remove them.
The most obvious example of them working differently is opening them in excel. The manual file opens in excel automatically putting each column in it's own seperate column. The automated file instead puts everything into one column.
Can anybody shed some light? I am hoping that by resolving this or at least getting some info will help with the bigger problem of it not processing correctly.
Thanks.
ex one column
"rownum","year","month","batch","facility","transfer_facility","trans_dt","meter","ticket","trans_product","trans","shipper","customer","supplier","broker","origin","destination","quantity"
ex seperate column
"","ROWNUM","RPT_YR","RPT_MO","BATCH_NBR","FACILITY_CD","TRANSFER_FACILITY_CD","TRANS_DT","METER_NBR","TKT_NBR","TRANS_PRODUCT_CD","TRANS_CD","SHIPPER_CD","CUSTOMER_NBR","SUPPLIER_NBR","BROKER_CD","ORIGIN_CD","DESTINATION_CD","NET_QTY"
$connectionstring = "Data Source=database;User Id=user;Password=password"
$connection = New-Object System.Data.OracleClient.OracleConnection($connectionstring)
$command = New-Object System.Data.OracleClient.OracleCommand($query, $connection)
$connection.Open()
Write-Host -ForegroundColor Black " Opening Oracle Connection"
Start-Sleep -Seconds 2
#Getting data from oracle
Write-Host
Write-Host -ForegroundColor Black "Getting data from Oracle"
$Oracle_data=$command.ExecuteReader()
Start-Sleep -Seconds 2
if ($Oracle_data.read()){
Write-Host -ForegroundColor Green "Connection Success"
while ($Oracle_data.read()) {
#Variables for recordset
$rownum = $Oracle_data.GetDecimal(0)
$rpt_yr = $Oracle_data.GetDecimal(1)
$rpt_mo = $Oracle_data.GetDecimal(2)
$batch_nbr = $Oracle_data.GetString(3)
$facility_cd = $Oracle_data.GetString(4)
$transfer_facility_cd = $Oracle_data.GetString(5)
$trans_dt = $Oracle_data.GetDateTime(6)
$meter_nbr = $Oracle_data.GetString(7)
$tkt_nbr = $Oracle_data.GetString(8)
$trans_product_cd = $Oracle_data.GetString(9)
$trans_cd = $Oracle_data.GetString(10)
$shipper_cd = $Oracle_data.GetString(11)
$customer_nbr = $Oracle_data.GetString(12)
$supplier_nbr = $Oracle_data.GetString(13)
$broker_cd = $Oracle_data.GetString(14)
$origin_cd = $Oracle_data.GetString(15)
$destination_cd = $Oracle_data.GetString(16)
$net_qty = $Oracle_data.GetDecimal(17)
#Define new file
$filename = "Pipeline" #Get-Date -UFormat "%b%Y"
$filename = $filename + ".csv"
$fileLocation = $newdir + "\" + $filename
$fileExists = Test-Path $fileLocation
#Create object to hold record
$obj = new-object psobject -prop #{
rownum = $rownum
year = $rpt_yr
month = $rpt_mo
batch = $batch_nbr
facility = $facility_cd
transfer_facility = $transfer_facility_cd
trans_dt = $trans_dt
meter = $meter_nbr
ticket = $tkt_nbr
trans_product = $trans_product_cd
trans = $trans_cd
shipper = $shipper_cd
customer = $customer_nbr
supplier = $supplier_nbr
broker = $broker_cd
origin = $origin_cd
destination = $destination_cd
quantity = $net_qty
}
$records += $obj
}
}else {
Write-Host -ForegroundColor Red " Connection Failed"
}
#Write records to file with headers
$records | Select-Object rownum,year,month,batch,facility,transfer_facility,trans_dt,meter,ticket,trans_product,trans,shipper,customer,supplier,broker,origin,destination,quantity |
ConvertTo-Csv |
Select -Skip 1|
Out-File $fileLocation
Why are you skipping the first row(usually the headers)? Also, try using Export-CSV instead:
#Write records to file with headers
$records | Select-Object rownum, year, month, batch, facility, transfer_facility, trans_dt, meter, ticket, trans_product, trans, shipper, customer, supplier, broker, origin, destination, quantity |
Export-Csv $fileLocation -NoTypeInformation

Windows Script to consolidate files

I have to work with a huge number of text files. I am able to consolidate the files into one single file. But I also have the use of the file name in my work and I would like to have it before the text of the file itself in excel format, preferably the first column should contain the names of files and the columns afterwards can contain the data.
Any help would be appreciated. Thanks.
Here's the Powershell script. You might need to modify it a bit to look for specific file extensions as now it's only looking for PS1 files
[System.Threading.Thread]::CurrentThread.CurrentCulture = New-Object System.Globalization.CultureInfo("en-US")
$excel = new-Object -comobject Excel.Application
$excel.visible = $false
$workBook = $excel.Workbooks.Add()
$sheet = $workBook.Sheets.Item(1)
$sheet.Name = "Files"
$sheet.Range("A1", "B1").Font.Bold = $true
$sheet.Range("A1","A2").ColumnWidth = 40
$sheet.Range("B1","B2").ColumnWidth = 100
$sheet.Cells.Item(1,1) = "Filename"
$sheet.cells.Item(1,2) = "Content"
$files = get-childitem C:\PST -recurse | where {$_.extension -eq ".ps1"}
$index = 2
foreach($file in $files)
{
$sheet.Cells.Item($index,1) = $file.FullName
$sheet.Cells.Item($index,2) = [System.IO.File]::ReadAllText($file.FullName)
$index++
}
$workBook.SaveAs("C:\PST\1.xlsx")
$excel.Quit()
Note: I'm not pretending that it's perfect, you still need to polish it and refactor it, but at least it will give you direction

Resources