Is it possible to update a row in MS Access from PowerShell? - powershell

I have the following PowerShell code which adds a new line of data into a MS Access database (based on user input) and works perfectly.
if ($NewAccounts ="Y") {
$cursor = 3
$lock = 3
$Ado = New-Object -ComObject ADODB.Connection
$recordset = New-Object -ComObject ADODB.Recordset
$Ado.Open("Provider = Microsoft.ACE.OLEDB.12.0;Data Source=$Source")
$query = "Select * from [Sheet1]"
$recordset.Open($query, $ado, $cursor, $lock)
$recordset.AddNew()
$recordset.Fields.Item("Account") = $AccName
$recordset.Fields.Item("Serial") = $CGBSerial
$recordset.Fields.Item("SAExpiry") = $SAEDate.ToString("dd/MM/yyyy")
$recordset.Fields.Item("SAValidatedPerson") = $SAPerson
$recordset.Fields.Item("DataCollection") = $DCRun
$recordset.Fields.Item("DataCollectionDate") = $DCRunDate
$recordset.Fields.Item("DataCollectionPerson") = $DCPerson
$recordset.Fields.Item("Version") = $Version
$recordset.Fields.Item("VersionDateValidated") = Get-Date -Format d
$recordset.Fields.Item("VersionValidatedPerson") = $logontrim
$recordset.Update()
$recordset.Close()
$ado.Close()
}
However, I cannot seem to update a row in the database that already exists. Is it possible to update a row, rather than creating an entirely new row?

$recordset.AddNew() appends a new empty record to the recordset. To update an existing record you need to navigate to the record you want to modify first, and then change the values of that record.
$recordset.Open($query, $ado, $cursor, $lock)
while ($recordset.Fields.Item('Account').Value -ne $AccName) {
$recordset.MoveNext()
}
$recordset.Fields.Item('Serial') = $CGBSerial
...
$recordset.Update()
$recordset.Close()
However, you can't use MoveNext() with a static cursor, so you need to change the cursor type to adOpenForwardOnly ($cursor = 0).
Alternatively you could use a prepared statement:
$cn = New-Object -ComObject 'ADODB.Connection'
$cn.ConnectionString = "..."
$cn.Open()
$cmd = New-Object -ComObject 'ADODB.Command'
$cmd.CommandText = 'UPDATE [Sheet1] SET Serial=?, SAExpiry=?, ... WHERE Account=?'
$cmd.Parameters.Append($cmd.CreateParameter('#p1', 200, 1, 50, $CGBSerial))
$cmd.Parameters.Append($cmd.CreateParameter('#p2', 7, 1, $null, $SAEDate))
...
$cmd.Execute()
$cn.Close()

Related

How to Clear a Chart form

i'm currently working on a project (WOL) where i have a program that launch as a window form and have few components which one of them is a chart form.
Basically, the program can re-launch multiple times as the user wants but i'm trying to clear/reset the chart form (that is in Pie style) at each launch = delete the previous datas of the chart.
My code is way too long so i will post only the concerned parts
$WOL_W = New-Object System.Windows.Forms.Form
.... (skipping useless code part)
function Chart {
param(
[Parameter(Mandatory)]
[PSCustomObject[]]
$Results
)
$G_Graphique = New-object System.Windows.Forms.DataVisualization.Charting.Chart
$G_Graphique.Location = New-Object System.Drawing.Point(300,350)
$WOL_W.Controls.Add($G_Graphique)
$Wol_W.Add_Shown({$Graphique.Activate()})
$G_Graphique.Anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right -bor [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left
# Objet Zone Graphique (ZG_)
$ZG_GraphArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$G_Graphique.ChartAreas.Add($ZG_GraphArea)
[void]$G_Graphique.Titles.Add("RĂ©ussite du WOL")
$G_Graphique.BackColor = [System.Drawing.Color]::White
$G_Graphique.BorderColor = 'Black'
$G_Graphique.BorderDashStyle = 'Solid'
[void]$G_Graphique.Series.Add("Data")
$G_Graphique.Series["Data"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Pie
$G_Graphique.Series["Data"].Points.DataBindXY($Results.Keys,$Results.Values)
}
Note : i've tried to use the followings command in another function (function of the creation for the main window) :
$G_Graphique.ChartAreas.Clear()
$Wol_W.Controls.Remove($G_Graphique)
Which failed as i want.

autocomplete in datagridviewcell

I have a datagridview control and would like in one of the cells to make use of autocomplete.
I tried using the editcontrolshowing event but cant really get it to work.
$DGVtimeAttendance_EditingControlShowing = [System.Windows.Forms.DataGridViewEditingControlShowingEventHandler]{
$queryGetaLLuSERS = "SELECT CONCAT(firstname,' ',lastname) AS Employee
FROM tbl_user"
$queryGetaLLuSERS = sql_query -Query $queryGetaLLuSERS
$getheaderText = $DGVtimeAttendance.Columns[1].HeaderText
if ($getheaderText -eq 'Employee')
{
#$getvalueChanged = $this.Rows[$_.RowIndex].Cells[$_.ColumnIndex].value
#Write-Host $getvalueChanged
$autotext = New-Object System.Windows.Forms.DataGridViewTextBoxEditingControl
$autotext.AutoCompleteMode = 'Suggest'
$autotext.AutoCompleteSource = 'CustomSource'
$autotext.AutoCompleteCustomSource.AddRange($queryGetaLLuSERS.employee)
$DGVtimeAttendance.Controls.add($autotext)
#$_.Control.autocompleteMode = 'Suggest'
Write-Host $_
}}
with the help from santiagos post
i changed the if statement to
if ($getheaderText -eq 'Employee')
{
$this.EditingControl.AutoCompleteMode = [System.Windows.Forms.AutoCompleteMode]::Suggest
$this.EditingControl.AutoCompleteSource = [System.Windows.Forms.AutoCompleteSource]::CustomSource
$this.EditingControl.AutoCompleteCustomSource.AddRange(($queryGetaLLuSERS.employee)) #= [System.Windows.Forms.AutoCompleteSource]::CustomSource
}
and worked like a charm
thx everyone and especially santiago

Tidying up a powershell script

So I need help tidying up a script that I have. The purpose of this script is to make 18 different sql files based on the data below 18 different column headers. What my script does now is make 1 sql file based on which column I choose to input via "Read-Host". This is my current script
function get-header
{Read-Host "Type the Column header betwen B-Z for which sql files needs to be created"
}
function get-column
{
Read-Host "Type the Column number"
}
do
{
$val = get-header
}
while(!($val))
do
{$col = get-column
}
while(!($col))
switch ($val)
{
"B"{$column = "1"}
"C"{$column = "2"}
"D"{$column = "3"}
"E"{$column = "4"}
"F"{$column = "5"}
"G"{$column = "6"}
"H"{$column = "7"}
"I"{$column = "8"}
"J"{$column = "9"}
"K"{$column = "10"}
"L"{$column = "11"}
"M"{$column = "12"}
"N"{$column = "13"}
"O"{$column = "14"}
"P"{$column = "15"}
"Q"{$column = "16"}
"R"{$column = "17"}
"S"{$column = "18"}
"T"{$column = "19"}
"U"{$column = "20"}
"V"{$column = "21"}
"W"{$column = "22"}
"X"{$column = "23"}
"Y"{$column = "24"}
"Z"{$column = "25"}
default { $column = 'Unknown' }
}
if ($column -eq 'Unknown')
{
Write-Warning "Not a valid input"
return
}
$csv = Import-Csv "Indices Updates - September 2018.csv" -Header 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
$date = (Get-Date -Format "MM/dd/yyyy").Replace("-","/")
$sql = #("INSERT INTO benchmark_values(created_at,benchmark_id,date,amount,created_by_username)
foreach($data in $csv)
{
$secondcolumn = [int]$column + 1
$sql += "('$date',$col,'$($data.1)',$($data.$secondcolumn),'BPylla'),"
}
$sql | Out-File "sqldata.sql"
Now I want to get rid of read-host entirely because I dont want to input any values. I also will give an example of what the csv file looks like and what the sql file should look like.
So the goal is to produce different sql files from each column of information using the the sql format posted. I already have the template for that in my script now, I just need the script to create all the sql files based on headers and still input the data below the headers in the new sql files. Any help would be greatly appreciated! Thanks!

Is it possible to pull multiple SNMP values from try..catch statements?

Is there a way to pull multiple SNMP values and update them as new values in PowerShell?
I have two different OIDs that I'm pulling from my UPS and I want those integer values saved to a database table.
This is my code
$UPS_Temp_oid = '1.3.6.1.4.1.318.1.1.10.2.3.2.1.4.1'
$Battery_Load_oid = '.1.3.6.1.4.1.318.1.1.1.4.2.3.0'
$sql = "SELECT temp, batteryload, upsid, ups_ip FROM ups WHERE ups_ip IS NOT NULL"
$cmd = New-Object System.Data.SqlClient.SqlCommand($sql, $conn)
$rows = $cmd.ExecuteReader()
while ($rows.Read()) {
$ups_id = $rows["upsid"]
$ups_ip = $rows["ups_ip"].trim()
$ups_temp = $rows["temp"]
$battery_load = $rows["batteryload"]
Write-Output $ups_id, $ups_ip, $ups_temp, $battery_load
# Ping UPS
$ping = New-Object System.Net.NetworkInformation.Ping
$ping_reply = $ping.Send($ups_mgmt_ip) | select status
# If success go call func SNMP
if ($ping_reply.status -eq "Success") {
try {
$frm_snmp = Invoke-SNMPget $ups_ip $UPS_Temp_oid "community"
} catch {
Write-Host "$ups_mgmt_ip SNMP Get error: $_"
return null
}
would I have to create another try..catch for the battery_load_oid or would I just simply do something like that?
Invoke-SNMPget ups_ip $ups_temp_oid, $nattery_load_oid "community"

How To Execute MS Access Query with OLEDB.12

I am looking for the syntax for executing MS Access named query using Microsoft.ACE.OLEDB.12.0 command object.
I see lots of examples using tables but non for queries yet. Swapping out the table name for the query name seems not to work. i.e. select * from 'myquery'
Here is my code snippet:
$OleDbConn = New-Object "System.Data.OleDb.OleDbConnection";
$OleDbCmd = New-Object "System.Data.OleDb.OleDbCommand";
$OleDbAdapter = New-Object "System.Data.OleDb.OleDbDataAdapter";
$DataTable = New-Object "System.Data.DataTable";
$OleDbConn.Open();
$OleDbCmd.Connection = $OleDbConn;
$OleDbCmd.CommandText = "'myQuery'"; # name query in MS Access db
$OleDbCmd.CommandType = [System.Data.CommandType]::StoredProcedure;
$OleDbAdapter.SelectCommand = $OleDbCmd;
$RowsReturned = $OleDbAdapter.Fill($DataTable);
Write-Host $RowsReturned;
Error: Exception calling "Fill" with "1" argument(s): "The Microsoft Access database engine cannot find the input table or query ''Lab Manual''. Make sure it exists and that its name is spelled correctly."
The trick was to append the command 'Execute' before the query name and use square brackets around the query name.
$OleDbConn = New-Object "System.Data.OleDb.OleDbConnection";
$OleDbCmd = New-Object "System.Data.OleDb.OleDbCommand";
$OleDbAdapter = New-Object "System.Data.OleDb.OleDbDataAdapter";
$DataTable = New-Object "System.Data.DataTable";
$OleDbConn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\temp\labmanual.mdb;";
$OleDbCmd.Connection = $OleDbConn;
$OleDbCmd.CommandText = "Execute [myQuery]";
$OleDbAdapter.SelectCommand = $OleDbCmd;
$OleDbConn.Open();
$RowsReturned = $OleDbAdapter.Fill($DataTable);
Write-Host $RowsReturned;
$OleDbConn.Close();