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
Related
I'm using FromFile to get the image out of files, and it has the following error for the png's on the FromFile line:
Exception calling "FromFile" with "1" argument(s): "The given path's
format is not supported."
So, I'm trying to convert the bmp's to jpg, (see convert line above FromFile below) but all the examples I see (that seem usable) are saving the file. I don't want to save the file in the dir. All I need is the image format, so FromFile can use it like this example. I saw ConvertTo-Jpeg, but I don't think this is a standard powershell module, or don't see how to install it.
I saw this link, but I don't think that would leave the image in the format needed by FromFile.
This is my code:
$imageFile2 = Get-ChildItem -Recurse -Path $ImageFullBasePath -Include #("*.bmp","*.jpg","*.png") | Where-Object {$_.Name -match "$($pictureName)"} #$imageFile | Select-String -Pattern '$($pictureName)' -AllMatches
Write-Host $imageFile2
if($imageFile2.Exists)
{
if($imageFile2 -Match "png")
{
$imageFile2 | .\ConvertTo-Jpeg #I don't think this will work with FromFile below
}
$image = [System.Drawing.Image]::FromFile($imageFile2) step
}
else {
Write-Host "$($imageFile2) does not exist"
}
And then I put it in excel:
$xlsx = $result | Export-Excel -Path $outFilePath -WorksheetName $errCode -Autosize -AutoFilter -FreezeTopRow -BoldTopRow -PassThru # -ClearSheet can't ClearSheet every time or it clears previous data ###left off
$ws = $xlsx.Workbook.Worksheets[$errCode]
$ws.Dimension.Columns #number of columns
$tempRowCount = $ws.Dimension.Rows #number of rows
#only change width of 3rd column
$ws.Column(3).Width
$ws.Column(3).Width = 100
#Change all row heights
for ($row = 2 ;( $row -le $tempRowCount ); $row++)
{
#Write-Host $($ws.Dimension.Rows)
#Write-Host $($row)
$ws.Row($row).Height
$ws.Row($row).Height = 150
#place the image in spreadsheet
#https://github.com/dfinke/ImportExcel/issues/1041 https://github.com/dfinke/ImportExcel/issues/993
$drawingName = "$($row.PictureID)_Col3_$($row)" #Name_ColumnIndex_RowIndex
Write-Host $image
$picture = $ws.Drawings.AddPicture("$drawingName",$image)
$picture.SetPosition($row - 1, 0, 3 - 1, 0)
if($ws.Row($row).Height -lt $image.Height * (375/500)) {
$ws.Row($row).Height = $image.Height * (375/500)
}
if($ws.Column(3).Width -lt $image.Width * (17/120)){
$ws.Column(3).Width = $image.Width * (17/120)
}
}
Update:
I just wanted to reiterate that FromFile can't be used for a png image. So where Hey Scripting Guy saves the image like this doesn't work:
$image = [drawing.image]::FromFile($imageFile2)
I figured out that the $imageFile2 path has 2 filenames in it. It must be that two met the Get-ChildItem/Where-Object/match criteria. The images look identical, but have similar names, so will be easy to process. After I split the names, it does FromFile ok.
In Powershell, I want to export the results of a query ODP.NET to a CSV file
This is my code:
$connection = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($connectionString)
$connection.open()
$cmd = New-Object Oracle.ManagedDataAccess.Client.OracleCommand -ArgumentList $query
$cmd.Connection = $connection
$reader = $cmd.ExecuteReader()
This code is working with the correct values of $connectionString and $query variables. If I add this code I can read the correct result of my query:
while ($reader.Read()) {
$col1 = $reader["Col1"]
$col2 = $reader["Col2"]
$col3 = $reader["Col3"]
#Write-Host $col1, $col2, $col3
}
Those 3 columns are an example, in my real case I have many more. Then I want to export directly to a CSV file, something like this:
XXXXXXX | export-csv -Delimiter ";" -Path "E:\export.csv"
How can I do this? The expected result is a CSV file similar than this:
"4581";"6";26867;"191057";"BH02 - 26867 - ";"30/05/2019";"";"2040";1991,04;"2040";2,4;"00";"";348;"";"1";"1";"";"";"BRL";2040;"";1
"4581";"4";28313;"747990";"BH02 - 28313 - ";"30/05/2019";"";"140";137,13;"140";2,05;"00";"";459;"";"1";"1";"";"";"BRL";140;"";1
"4581";"1";28316;"881411";"BH02 - 28316 - ";"30/05/2019";"";"140";137,13;"140";2,05;"00";"";460;"";"1";"1";"";"";"BRL";140;"";1
"4581";"1";;"878676";"BH02 - - 275650/PF19";"28/05/2019";"";"103";100,8885;"103";2,05;"00";"";305;"";"1";"1";"";"";"BRL";103;"";1
"4581";"6";28168;"006778";"BH02 - 28168 - 275714/PF19";"30/05/2019";"";"848";828,92;"848";2,25;"00";"";429;"";"1";"1";"";"";"BRL";848;"";1
"4581";"3";29080;"641559";"BH02 - 29080 - ";"30/05/2019";"";"3424,14";3338,5365;"3424,14";2,5;"00";"";488;"";"1";"1";"";"";"BRL";3424,14;"";1
"4581";"4";;"602483";"BH02 - - 23443";"28/05/2019";"";"157";153,7815;"157";2,05;"00";"";329;"";"1";"1";"";"";"BRL";157;"";1
What is the raw output of this Oracle command?
If it is a list, then use -Join and use the Csv cmdlets to export to convert to a csv file.
This also would indicate that you are new or never used PowerShell before since csv use case is a daily thing. That's OK, but jump on YouTube, MSDN Channel9 and go through the videos on PowerShell, beginning/intermediate/advanced, PowerShell and Databases, PowerShell and Csv files and get ramped up to limit/avoid, misconceptions, frustrations, bad habits, etc.
It should be straightforward as doing something like this ( of course don't put passwords in scripts)...
Add-Type -Path 'C:\oracle\instantclient_10_2\odp.net\managed\common\Oracle.ManagedDataAccess.dll'
$username = "USERID"
$password = "Password"
$datasource = "HOST:PORT/Instance"
$connectionString = "User Id = $username;Password = $password;Data Source = $datasource"
$query = "SELECT DATA1, DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, DATA8
FROM TABLE WHERE NOT REGEXP_LIKE (EMAIL_ID, '#domain.com','i') order by DATA2"
$connection = New-Object Oracle.ManagedDataAccess.Client.OracleConnection("$connectionString")
$connection.open()
$command = New-Object Oracle.ManagedDataAccess.Client.OracleCommand
$command.Connection = $connection
$command.CommandText = $query
$ds = New-Object system.Data.DataSet
$da = New-Object Oracle.ManagedDataAccess.Client.OracleDataAdapter($command)
[void]$da.fill($ds)
return $ds.Tables[0] |
SELECT DATA1, DATA2, DATA3, DATA4, DATA5, DATA6, DATA7, DATA8 |
Export-CSV "C:\test.csv" -NoTypeInformation
$connection.Close()
[void][System.Reflection.Assembly]::LoadWithPartialName("Oracle.DataAccess")
$username = "USER"
$password = "PW"
$datasource = "XXX.XXX.XXX.XXX:YYYY/NODE1"
function getConnectionString()
{
#Below is a one line code
$connectionstring = "Data Source=$datasource;User Id=$($username); Password=$($password)"
return $connectionstring
}
$query = get-content "C:\Test.sql";
$connectionstring = getConnectionString
$DataTable = New-Object System.Data.DataTable
$command = New-Object Oracle.DataAccess.Client.OracleCommand($query,$connectionstring)
$dataAdapter = New-Object Oracle.DataAccess.Client.OracleDataAdapter($command)
[void]$dataAdapter.Fill($DataTable)
#To display data on console
$DataTable | format-table -auto
#To export to csv
$DataTable | Export-Csv "C:\Test.csv" -notype
The "Test.sql contains:
SELECT ACCOUNTNUMBER, ACCOUNTID, USERID FROM account
WHERE ACCOUNTNUMBERLIKE '%0011111%'
That quesy brings back 3 rows.
Issue at hand: My powershell script only gives me the first 2 rows (1 being the headers, the other being the first data row)
Any advice?
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))
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