Powershell, Sql and export data in loop to html - html

I have table in my database with following columns :
LOGIN | AVAILABLE | MORE INFO
I want to generate html's files for every unique login. Each html file should display the rows relating to a single "login". Every "login" has a different number of rows. The name of each generated file should be such as "login"
I have only a script that writes to html the entire table.
I tried to use "loop for" to generate these files, but to no avail.
This is my code:
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "ConnectionString"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.Connection = $SqlConnection
$SqlCmd.CommandTimeout = 0
$SqlCmd.Connection.Open()
$SqlCmd.CommandText = "select login, available, more_info from [schema].[table]"
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$FilePath = "Path" + login + ".html"
$Title = " Title"
$DataSet.Tables[0] | convertto-html -property login, available, more_info -title $Title > $FilePath

Related

How do I dynamically insert a string into a text file in PowerShell?

The text is an html file. The line I am interested in looks something like:
<td>INC1234</td><td>INC1235</td><td>INC1236</td>
The INC numbers are different from file to file. I'd like to parse through the line by saying something like:
if like <td>INC, then concatenate '<td><a href="https://www.website.com/=' + INC# + '>"
To give an output like:
<td><a href="https://www.website.com/=INC1234>INC1234</a></td><td><a href="https://www.website.com/=INC1235>INC1235</a></td><td><a href="https://www.website.com/=INC1236>INC1236</a></td>"
EDIT1: Ok, if I do something like:
$parse = (-split (Get-Content -Raw C:\Temp\report.txt) -match '<td>INC')
$parse
It will find the characters, but it will return the entire line rather than looking for more that match the 'INC'. Presumably because they all reside on the same line with no spaces.
EDIT2: Maybe this will help. What I'm doing is using PowerShell to write SQL commands, send it to our SQL Server, return the data and use PSWriteHTML to build the report which works fantastic. But I am wanting the first column, which is the ticket number (eg. INC1234) to be a link to the ticket it reads.
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True)]
[string]$ReportName
)
## Build the query box
function Read-MultiLineInputBoxDialog([string]$Message, [string]$WindowTitle, [string]$DefaultText)
{
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms
## Create the Label.
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Size(10,10)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.AutoSize = $true
$label.Text = $Message
## Create the TextBox used to capture the user's text.
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Size(10,40)
$textBox.Size = New-Object System.Drawing.Size(575,200)
$textBox.AcceptsReturn = $true
$textBox.AcceptsTab = $false
$textBox.Multiline = $true
$textBox.ScrollBars = 'Both'
$textBox.Text = $DefaultText
## Create the OK button.
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Size(415,250)
$okButton.Size = New-Object System.Drawing.Size(75,25)
$okButton.Text = "OK"
$okButton.Add_Click({ $form.Tag = $textBox.Text; $form.Close() })
## Create the Cancel button.
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Size(510,250)
$cancelButton.Size = New-Object System.Drawing.Size(75,25)
$cancelButton.Text = "Cancel"
$cancelButton.Add_Click({ $form.Tag = $null; $form.Close() })
## Create the form.
$form = New-Object System.Windows.Forms.Form
$form.Text = $WindowTitle
$form.Size = New-Object System.Drawing.Size(610,320)
$form.FormBorderStyle = 'FixedSingle'
$form.StartPosition = "CenterScreen"
$form.AutoSizeMode = 'GrowAndShrink'
$form.Topmost = $True
$form.AcceptButton = $okButton
$form.CancelButton = $cancelButton
$form.ShowInTaskbar = $true
## Add all of the controls to the form.
$form.Controls.Add($label)
$form.Controls.Add($textBox)
$form.Controls.Add($okButton)
$form.Controls.Add($cancelButton)
## Initialize and show the form.
$form.Add_Shown({$form.Activate()})
$form.ShowDialog() > $null # Trash the text of the button that was clicked.
## Return the text that the user entered.
return $form.Tag
}
## Prompt the SQL Query Box
$Query = Read-MultiLineInputBoxDialog -Message "Enter SQL Query Here" -WindowTitle "SQL Query" -DefaultText "SELECT FROM"
if ($Query -eq $null) { Break }
else { Write-Host "You entered the following text: $Query" }
## Pass query to SQL Server
$Pass = Invoke-Sqlcmd -Query $Query -ServerInstance "MY-SERVER-INSTANCE" -Username "USERNAME" -Password "PASSWORD"
## Output the report and save to the network under the specified name
New-HTML {
New-HTMLTable -EnableColumnReorder -DisableInfo -DataTable $Pass -ExcludeProperty "RowError", "RowState", "Table", `
"ItemArray", "HasErrors" -HideFooter -PagingLength 25 -SearchBuilder
New-HTMLTableStyle -FontFamily Calibri -FontSize 15 -FontStyle normal -TextAlign center -TextColor "#0a0a0a"
New-HTMLTableStyle -FontFamily Calibri -BackgroundColor "#fffdb5" -FontSize 15px -TextColor "#0a0a0a" -TextAlign center -Type RowHover
} -ShowHTML -FilePath "\\Server\$ReportName.html" -Online
The report looks something like:
Ticket: Description:
----------------------------
INC1234 Broken Monitor
INC1235 No Sound
The HTML that PSWriteHTML builds throws all of the ticket numbers on one line so I would like to edit that HTML with the <a href=""> tag to dynamically create links for each ticket # mainly because I don't know how to do it in PS and can't seem to find a good answer through Google - which is why I came here.
Although not familiar with PsWriteHtml, I guess you could simply change the Ticket properties in the array you receive in $Pass:
## Pass query to SQL Server
$Pass = Invoke-Sqlcmd -Query $Query -ServerInstance "MY-SERVER-INSTANCE" -Username "USERNAME" -Password "PASSWORD"
# convert all Tickets into hyperlinks
foreach ($item in $Pass) {
$item.Ticket = '<a href="https://www.website.com/={0}>{0}</a>'-f $item.Ticket
}
Then the rest of your code
## Output the report and save to the network under the specified name
New-HTML {...}

Export all reports in RDL format from SSRS Server Automatically

SSRS gives you the ability to export a report into the original RDL format: http://sql-articles.com/articles/general/download-export-rdl-files-from-report-server/
What I am wondering is if there is a way to export all reports (via a command-line interface that I could write) or some tool into the original RDL format which can then be zipped up, etc.
Thank you for your time.
I've not tested this but it appears to do what you need.
https://gallery.technet.microsoft.com/scriptcenter/SSRS-all-RDL-files-from-00488104
I've created a powershell script to do this. You have to connect to SQL server which has the SSRS database. It is compressing all the files into a zip file.
Add-Type -AssemblyName "System.IO.Compression.Filesystem"
$dataSource = "SQLSERVER"
$user = "sa"
$pass = "sqlpassword"
$database = "ReportServer"
$connectionString = "Server=$dataSource;uid=$user; pwd=$pass;Database=$database;Integrated Security=False;"
$tempfolder = "$env:TEMP\Reports"
$zipfile = $PSScriptRoot + '\reports.zip'
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$allreports = $connection.CreateCommand()
$allreports.CommandText = "SELECT ItemID, Path, CASE WHEN Type = 2 THEN '.rdl' ELSE 'rds' END AS Ext FROM Catalog WHERE Type IN(2,5)"
$result = $allreports.ExecuteReader()
$reportable = new-object "System.Data.DataTable"
$reportable.Load($result)
[int]$objects = $reportable.Rows.Count
foreach ($report in $reportable) {
$cmd = $connection.CreateCommand()
$cmd.CommandText = "SELECT CAST(CAST(Content AS VARBINARY(MAX)) AS XML) FROM Catalog WHERE ItemID = '" + $report[0] + "'"
$xmldata = [string]$cmd.ExecuteScalar()
$filename = $tempfolder + $report["Path"].Replace('/', '\') + $report["Ext"]
New-Item $filename -Force | Out-Null
Set-Content -Path ($filename) -Value $xmldata -Force
Write-Host "$($objects.ToString()).$($report["Path"])"
$objects -= 1
}
Write-Host "Compressing to zip file..."
if (Test-Path $zipfile) {
Remove-Item $zipfile
}
[IO.Compression.Zipfile]::CreateFromDirectory($tempfolder, $zipfile)
Write-Host "Removing temporarly data"
Remove-Item -LiteralPath $tempfolder -Force -Recurse
Invoke-Item $zipfile

Powershell Storing sqlResults into an array

I have a power shell script that querys the database and returns two columns which are a key value pair. Let's call them a & b.
How do I store this in a map to be called at a later date? Below is mysql code, it runs and prints out columns out to the screen.
$Connection = New-Object MySql.Data.MySqlClient.MySqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
$Command = New-Object MySql.Data.MySqlClient.MySqlCommand($Query, $Connection)
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($Command)
$DataSet = New-Object System.Data.DataSet
$RecordCount = $dataAdapter.Fill($dataSet, "data")
$DataSet.Tables[0]
Just not sure how to store the key value pair in an mapto be used later. Both columns are numeric.
Thanks.
You want to cycle through each object in the results?
$Records = $DataSet.Tables[0]
$Records.Keys | ForEach-Object {$Record.$_}
This will allow you to iterate through the objects and run some bit of code for each of them.
For instance, I've got a hashtable like this:
$Records = [hashtable]#{'Name'='Stephen';'Hair'='Red'}
The results:
$Records.Keys | ForEach-Object {"object `$Records.$_ = $($Records.$_)"}
>object $Records.Hair = Red
>object $Records.Name = Stephen
If this isn't what you're looking for, please comment so that I can try to help you to a solution.

Getting no query results in email

This is my powershell script below. I am trying to export the query's results into email body. However, the email contains nothing except the table headers. Could anyone help out what could be wrong / incomplete?
# Create a DataTable
$table = New-Object system.Data.DataTable "bugs"
$col1 = New-Object system.Data.DataColumn bug_id,([string])
$col2 = New-Object system.Data.DataColumn bug_status,([string])
$col3 = New-Object system.Data.DataColumn resolution,([string])
$col4 = New-Object system.Data.DataColumn short_desc,([string])
$col5 = New-Object system.Data.DataColumn deadline,([string])
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
$table.columns.add($col4)
$table.columns.add($col5)
# This code defines the search string in the database table
$SQLQuery = "SELECT bug_id,
bug_status,
resolution,
short_desc,
deadline
FROM bugs
WHERE ( bug_status IN ( 'RESOLVED', 'VERIFIED', 'INTEST' )
AND deadline BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 30 DAY)
)
OR ( bug_status IN ( 'RESOLVED', 'VERIFIED', 'INTEST' )
AND deadline BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND
CURDATE() )
ORDER BY deadline ASC
"
# This code connects to the SQL server and retrieves the data
$MySQLAdminUserName = 'user_name'
$MySQLAdminPassword = 'password'
$MySQLDatabase = 'mantis'
$MySQLHost = '<HOSTNAME>'
$ConnectionString = "server=" + $MySQLHost + ";port=3306;uid=" + $MySQLAdminUserName + ";pwd=" + $MySQLAdminPassword + ";database="+$MySQLDatabase
[void][system.reflection.Assembly]::LoadFrom("C:\Program Files (x86)\Devolutions\Remote Desktop Manager Free\MySQL.Data.dll")
$Connection = New-Object MySql.Data.MySqlClient.MySqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
$Command = New-Object MySql.Data.MySqlClient.MySqlCommand($SQLQuery, $Connection)
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($Command)
$DataSet = New-Object System.Data.DataSet
$RecordCount = $dataAdapter.Fill($dataSet, "data")
$DataSet.Tables[0]
# Create an HTML version of the DataTable
$html = "<table><tr><td>bug_id</td><td>bug_status</td><td>resolution</td><td>short_desc</td><td>deadline</td></tr>"
foreach ($row in $table.Rows)
{
$html += "<tr><td>" + $row[0] + "</td><td>" + $row[1] + "</td></tr>" + "</td></tr>" + $row[2] + "</td></tr>"
}
$html += "</table>"
# Send the email
$smtpserver = "<SMTPSERVER>"
$from = "test#test.com"
$to = "test2#test.com"
$subject = "Hello"
$body = "Hi there,<br />Here is a table:<br /><br />" + $html
Send-MailMessage -smtpserver $smtpserver -from $from -to $to -subject $subject -body $body -bodyashtml
You may have other problems, but the date arithmetic is definitely one issue.
MySQL has very strange rules about date arithmetic. The value of CURDATE() is not a date. It is either a string or a number. In a numeric context (CURDATE() + 9 is a numeric context), then it returns a number.
So, the date 2015-01-25 is returned as the integer 20150125. You can see this phenomenon on SQL Fiddle here. This value plus nine is 20150134. Not a valid date and not what you expect.
The easiest fix is to use date_add():
SELECT bug_id, bug_status, resolution, short_desc, deadline
FROM bugs
WHERE bug_status IN ('RESOLVED') AND
deadline BETWEEN CURDATE() AND date_add(CURDATE(), interval 9 day)
I was able to put this together from multiple sources that seems to work with any mySQL query you plug in accordingly. I figured I'd share in case anyone else finds it helpful. Seems to be reliable from what I tested at least. You don't need to build the HTML table in with the SQL logic this way.
## -- This will download the needed PS module and load it accordingly and then prompt you to save the mySQL credential to make the connection to the data source
## -- Run PowerShell as administrator
## https://mcpmag.com/articles/2016/03/02/querying-mysql-databases.aspx
Invoke-WebRequest -Uri https://github.com/adbertram/MySQL/archive/master.zip -OutFile 'C:\Users\user\desktop\MySQL.zip'
$modulesFolder = 'C:\Program Files\WindowsPowerShell\Modules'
Expand-Archive -Path C:\Users\user\desktop\MySQL.zip -DestinationPath $modulesFolder
Rename-Item -Path "$modulesFolder\MySql-master" -NewName MySQL
$dbCred = Get-Credential
Connect-MySqlServer -Credential $dbcred -ComputerName 'localhost' -Database sakila
## Enter the mySQL username and password when prompted
Invoke-MySqlQuery -Query 'SELECT * FROM actor'
## --This will run automated after the PS module used to make the mySQL is already loaded and not prompt for credential to allow non-interactive runs
## --Embedded credential used here
$secpasswd = ConvertTo-SecureString “password” -AsPlainText -Force
$dbCred = New-Object System.Management.Automation.PSCredential (“root”, $secpasswd)
Connect-MySqlServer -Credential $dbcred -ComputerName 'localhost' -Database sakila
Invoke-MySqlQuery -Query 'SELECT * FROM actor LIMIT 5'
## This runs the Function to do the alternating row colors in the HTML table
Function Set-AlternatingRows {
[CmdletBinding()]
Param(
[Parameter(Mandatory,ValueFromPipeline)]
[string]$Line,
[Parameter(Mandatory)]
[string]$CSSEvenClass,
[Parameter(Mandatory)]
[string]$CSSOddClass
)
Begin {
$ClassName = $CSSEvenClass
}
Process {
If ($Line.Contains("<tr><td>"))
{ $Line = $Line.Replace("<tr>","<tr class=""$ClassName"">")
If ($ClassName -eq $CSSEvenClass)
{ $ClassName = $CSSOddClass
}
Else
{ $ClassName = $CSSEvenClass
}
}
Return $Line
}
}
## -- This portion builds the HTML table based on the SQL query which you can change accordingly for your needs
## https://community.spiceworks.com/scripts/show/1745-set-alternatingrows-function-modify-your-html-table-to-have-alternating-row-colors
## https://philerb.com/2011/11/sending-mail-with-powershell/
## https://thesurlyadmin.com/2013/01/21/how-to-create-html-reports/
$Title = "My Report Title"
$Header = #"
<style>
TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;}
TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
.odd { background-color:#ffffff; }
.even { background-color:#dddddd; }
</style>
<title>
$Title
</title>
"#
$Pre = "<b>Table Title"
$Post = "<b>Table Footer"
$html = Invoke-MySqlQuery -Query 'SELECT * FROM actor LIMIT 5' |
Select * -ExcludeProperty RowError, RowState, HasErrors, Name, Table, ItemArray |
ConvertTo-HTML -Head $Header -PreContent $Pre -PostContent $Post |
Set-AlternatingRows -CSSEvenClass even -CSSOddClass odd
$emailSmtpServer = "smtp.gmail.com"
$emailSmtpServerPort = "587"
$emailSmtpUser = "Username"
$emailSmtpPass = "Password"
$emailMessage = New-Object System.Net.Mail.MailMessage
$emailMessage.From = "mailbox#gmail.com"
$emailMessage.To.Add( "mailbox#gmail.com" )
$emailMessage.Subject = "Test email from PowerShell"
$emailMessage.IsBodyHtml = $true
$emailMessage.Body = #"
This is the body of the message.<br /><br /> $html
"#
$SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer , $emailSmtpServerPort )
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
$SMTPClient.Send( $emailMessage )
Sources
Modify your HTML table to have alternating row colors
Sending mail with PowerShell
How to Create HTML Reports
Querying MySQL Databases with PowerShell

Powershell SQL query result not fitting

Hi I have constructed a script that works fine except for one thing, sometimes the returned string is so long that it doesnt fit in the powershell console and when I later on send the text to a richtextbox I get all the ....... at the end and not the whole string
$username = "myaccount"
$sqlconnection = New-Object system.data.sqlclient.sqlconnection
$sqlconnection.ConnectionString ="server=myserver\sccm;database=sccm;trusted_connection=true;"
$sqlconnection.Open()
sqlcmd = New-Object system.data.sqlclient.sqlcommand
$sqlcmd = $sqlconnection.CreateCommand()
$sqlcmd.CommandText = "SELECT Info from SCCM.dbo.log WHERE Username = '$username'"
$sqlcmd.Connection = $sqlconnection
$data = New-Object system.data.sqlclient.sqldataadapter $sqlcmd
$dataset = New-Object system.data.dataset
$data.Fill($dataset)
$global:result = $dataset.Tables
I cannot specify the -Width parameter anywhere so I am lost on how to get the full length of the result?
Rather than display in powershell, you could save the dataset as a csv file:
#Fill the dataset with the SQL response. Using [void] redirects console output to null (don't display)
[void]$data.Fill($dataset)
#Pipe the contents of the dataset. Use Select to select all columns/properties excluding those that were created by the DataSet object (not actual data)
#Pipe to Export-CSV to create a CSV file, use -notypeinformation flag to skip Object type information from the file (e.g. System.String etc)
$dataset.Tables[0] | Select * -ExcludeProperty RowError, RowState, HasErrors, Table, ItemArray | Export-CSV -notypeinformation -path C:\Somedir\Somefile.csv