Invoke-sqlcmd not working when inserting csv data - powershell

Below mentioned code is generating CSV files successfully, but not inserting into database. Code was working previously, but not now:
Doesn't give error, data is not generating
$DestinationFileName = $DestinationFile
$SourceFileName = $SourceFile
$tableNum = $tableNumber
$DatabaseTable = $DatabaseTableName
$delimiter = ','
$objWord = New-Object -Com Word.Application
$objWord.Visible = $false # $false
$objDocument = $objWord.Documents.Open($SourceFileName,$false,$true)
$LETable = $objDocument.Tables.Item($tableNum)
$LETableCols = $LETable.Columns.Count
$LETableRows = $LETable.Rows.Count
$RawCSV = for($r=1; $r -le $LETableRows; $r++) {
$content= #()
for($c=1; $c -le $LETableCols; $c++) {
$content += ("`"{0}`"" -f $LETable.Cell($r,$c).Range.Text -replace "(`r|`n|`t)|$([char]7)?")
}
$Content -join $delimiter
}
$Csv = $RawCSV | ConvertFrom-Csv
$objDocument.Close()
$objWord.Quit()
# Stop Winword Process
$rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objWord)
$Csv
$Csv | Export-Csv $DestinationFileName -NoTypeInformation
$database = 'Test'
$server = '.'
$table = 'ScanDoc'
Invoke-Sqlcmd -Database $database -ServerInstance $server -Query "Trun
Import-CSV $DestinationFile -Header Col1, Col2 | Select-Object -Skip 1 | ForEach-Object { Invoke-Sqlcmd -Database $database -ServerInstance $server -Query "insert into $table VALUES ('$($SourceFileName)','$($_.Col1)','$($_.Col2)')"}

Related

Add verification data in to my powershell script

I have a PowerShell script that generates a CSV from XML files and than imports that CSV into an SQL database.
I want to add a verification cycle to check if the content that the script is adding to the CSV file already exists in it.
Here is my code:
$fi = Get-Content "dados.txt"
$nx = $fi[0] #caminho para os xmls
$lc = $fi[1] #caminho para onde vai o csv
$nc = $fi[2] #Nome do csv
$ToProcess = Get-ChildItem -Path $nx -Filter '*.xml' -Recurse #vai buscar todos os ficheiros xml dentro da diretoria com recursividade
$DataExec = Get-Date -Format "dd/MM/yyyy"
$horaExec = Get-Date -Format "HH:mm"
$CF = "$lc\" + $nc + ".csv"
$CsvFilePath = "$lc\"
$csvDelimiter = ";"
Install-Module SqlServer
$serverName = "..."
$databaseName = "FATURAS"
$tableSchema = "dbo"
$tableName = $nc
$username = "sa"
$password = "..."
$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd
$CsvFiles = $ToProcess.Name -replace('.xml','.csv') | ForEach-Object {"$CsvFilePath$_"}
ForEach ($File in $ToProcess){
[Xml]$Xml = Get-Content -Path $File.FullName
$Xml.message.invoice | Select-Object -Property #(
#{Name='File_Path';Expression={($File).DirectoryName + '\'}}
#{Name='FileName';Expression={$File.Name -split('.xml')}},
#{Name='Fornecedor'; Expression={$_.seller.id.'#text'}},
#{Name='commercialRegistrationNumber'; Expression={$Xml.message.invoice.seller.commercialRegistrationNumber}},
#{Name='documentNumber'; Expression={$Xml.message.invoice.documentNumber}},
#{Name='documentDate';Expression={$_.documentDate}},
#{Name='CreationDate';Expression={$Xml.message.creationDateTime}},
#{Name='DocType'; Expression={$Xml.message.invoice}},
#{Name='Data_Exec';Expression={$DataExec}},
#{Name='Hora_Exec';Expression={$horaExec}},
#{Name='BARCODE'; Expression={$Xml.message.invoice.reference.InnerText}},
#{Name='Description'; Expression={$Xml.message.invoice.lineItem.description}},
#{Name='Total'; Expression={$Xml.message.invoice.totalPayableAmount}}
) | Export-Csv -Path "$CsvFilePath$($File.BaseName).csv" -NoTypeInformation -Encoding Unicode
}
Import-Csv -LiteralPath $CsvFiles | Export-Csv -Path $CF -NoTypeInformation -Delimiter $csvDelimiter -Encoding UTF8
foreach($File in $CsvFiles){
Remove-Item -Path $File
}
Import-Csv -Path $CF -Delimiter $csvDelimiter | Write-SqlTableData -ServerInstance $serverName -DatabaseName $databaseName -SchemaName $tableSchema -TableName $tableName -Credential $creds -Force
Here is the file that im using to get the path's:
C:\scripts\xml para csv - sql\doc_xml\
C:\scripts\xml para csv - sql\final_teste
What i did was just download the table 1 into a csv and compare it with the one i have generate and then the different values i just insert them into the table 1
Clear-Host
Install-Module SqlServer
$fi = Get-Content "C:\scripts\xml_para_csv_sql\dados.txt"
$nx = $fi[0] #caminho para os xmls
$lc = $fi[1] #caminho para onde vai o csv
$nc = $fi[2] #Nome do csv
$sn = $fi[3] #Nome da tabela Sql
$ToProcess = Get-ChildItem -Path $nx -Filter '*.xml' -Recurse #vai buscar todos os ficheiros xml dentro da diretoria com recursividade
$DataExec = Get-Date -Format "dd/MM/yyyy"
$horaExec = Get-Date -Format "HH:mm"
$SqlFile = "$lc\$($sn)_SQL.csv"
$CF = "$lc\" + $nc + ".csv"
$CsvFilePath = "$lc\"
$csvDelimiter = ";"
if((Test-Path $CF) -eq $true){
Remove-Item $CF
}
do{
if (!(Test-Path $SqlFile)){$SqlFile = "$lc\$($sn)_SQL.csv"}
else{$SqlFile = "$lc\$($sn)_SQL" + "$($i)" + ".csv"}
$i = $i + 1
}until(!(Test-Path $SqlFile))
$serverName = "..."
$databaseName = "FATURAS"
$tableSchema = "dbo"
$tableName = $sn
$username = "sa"
$password = "..."
$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $secureStringPwd
$CsvFiles = $ToProcess.Name -replace('.xml','.csv') | ForEach-Object {"$CsvFilePath$_"}
ForEach ($File in $ToProcess){
[Xml]$Xml = Get-Content -Path $File.FullName
$Xml.message.invoice | Select-Object -Property #(
#{Name='File_Path';Expression={($File).DirectoryName + '\'}}
#{Name='FileName';Expression={$File.Name -split('.xml')}},
#{Name='Fornecedor'; Expression={$Xml.message.invoice.seller.vatNumber}},
#{Name='documentNumber'; Expression={$Xml.message.invoice.documentNumber}},
#{Name='documentDate';Expression={$_.documentDate}},
#{Name='CreationDate';Expression={$Xml.message.creationDateTime}},
#{Name='DocType'; Expression={$Xml.message.invoice}},
#{Name='Data_Exec';Expression={$DataExec}},
#{Name='Hora_Exec';Expression={$horaExec}},
#{Name='BARCODE'; Expression={$Xml.message.invoice.reference.InnerText}},
#{Name='Description'; Expression={$Xml.message.invoice.lineItem.description}},
#{Name='Total'; Expression={$Xml.message.invoice.totalPayableAmount}}
) | Export-Csv -Path "$CsvFilePath$($File.BaseName).csv" -NoTypeInformation -Encoding Unicode
}
if(!(Test-Path $CF)){
Import-Csv -LiteralPath $CsvFiles | Export-Csv -Path $CF -NoTypeInformation -Delimiter $csvDelimiter -Encoding UTF8
}else{
Write-Host "Os dados já existem!"
}
$data = Get-Content $CF -Encoding UTF8
$Return = $SQL = $dataTable = $null
$sql = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$sn'"
$dataTable = Invoke-Sqlcmd –ServerInstance $serverName -Credential $creds –Database $databaseName –Query $sql
if ($dataTable) {$return = $true}
else {$return = $false}
if($Return -eq $true){
$checksql = Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -Credential $creds -Query "Select* from $sn"
$checksql | Export-Csv $SqlFile -Delimiter ';' -Encoding UTF8 -NoTypeInformation
$compare = Compare-Object -ReferenceObject ($data | Select-Object -Skip 1 | Sort-Object ) -DifferenceObject (Get-Content $SqlFile | Select-Object -Skip 1 | Sort-Object) -IncludeEqual
$CsvLines = $compare | Where-Object {$_.SideIndicator -eq '<='}
if($CsvLines -eq $null){
Write-Warning "Não foi encontrado nenhuma linha no ficheiro $CF que a tabela $sn não tivesse"
foreach($File in $CsvFiles){
if((Test-Path $File) -eq $true){
Remove-Item -Path $File
}
}
}
$CsvLinesToSql = $CsvLines.InputObject | ForEach-Object {$_.replace('";"',"','")} | ForEach-Object{$_.replace('"','')} | ForEach-Object{("'$_'")}
foreach($line in $CsvLinesToSql){
$FileName = $line.Substring(0, $line.IndexOf(','))
$FileName = $line.Replace("$FileName,",'')
$FileName = $FileName.Substring(0, $FileName.IndexOf(','))
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -Credential $creds -Query "IF EXISTS (SELECT * FROM $sn WHERE FileName = $FileName)
delete from $sn WHERE FileName = $FileName
Insert Into dbo.$($sn) (File_Path, FileName, Fornecedor, documentNumber, documentDate, CreationDate, DocType, Data_Exec, Hora_Exec, BARCODE, Description, Total) VALUES ($line)
IF NOT EXISTS (SELECT * FROM $sn WHERE FileName = $FileName)
Insert Into dbo.$($sn) (File_Path, FileName, Fornecedor, documentNumber, documentDate, CreationDate, DocType, Data_Exec, Hora_Exec, BARCODE, Description, Total) VALUES ($line)"
}
Remove-Item $SqlFile
}
if($Return -eq $false){
Import-Csv -Path $CF -Delimiter ';' -Encoding UTF8 | Write-SqlTableData -ServerInstance $serverName -DatabaseName $databaseName -SchemaName $tableSchema -TableName $tableName -Credential $creds -Force
}
Invoke-Sqlcmd -ServerInstance $serverName -Database $databaseName -Credential $creds -Query "DELETE FROM $sn where FileName is null"
foreach($File in $CsvFiles){
if((Test-Path $File) -eq $true){
Remove-Item -Path $File
}
}```

Script PowerShell update SQL Server with csv

I am trying to make a script that allows to update my SQL Server database from several CSV files with different names, example:
LOHNSJSHM_details.csv
ZULTNQNIW_details.csv
...
Once the data is updated, the file must be deleted automatically.
Here's what I started doing:
If ((Get-PSSnapin | where {$_.Name -match "SqlServerCmdletSnapin100"}) -eq $null)
{
Add-PSSnapin SqlServerCmdletSnapin100
}
If ((Get-PSSnapin | where {$_.Name -match "SqlServerProviderSnapin100"}) -eq $null)
{
Add-PSSnapin SqlServerProviderSnapin100
}
$sql_instance_name = 'ServerSQL01\LAB'
$db_name = 'testdb'
$impcsv = ".\Example.csv"
$data = import-csv $impcsv
$count = 1
foreach($i in $data){
$reference = $i.reference
$quantity = $i.quantite
$query = "UPDATE dbo.F_ARTSTOCK (reference,quantity)
SET quantity = '$quantity'
WHERE reference = '$reference'"
$impcsv = invoke-sqlcmd -Database $db_name -Query $query -serverinstance $sql_instance_name
write-host "Processing row ..........$count" -foregroundcolor green
$count = $count + 1
}
My file has 2 columns (Reference, Quantity) and I have to update a SAGE table based on the reference withdraw quantities from each line of my CSV
Thank you for help.
If ((Get-PSSnapin | where {$_.Name -match "SqlServerCmdletSnapin100"}) -eq $null)
{
Add-PSSnapin SqlServerCmdletSnapin100
}
If ((Get-PSSnapin | where {$_.Name -match "SqlServerProviderSnapin100"}) -eq $null)
{
Add-PSSnapin SqlServerProviderSnapin100
}
$sql_instance_name = 'ServerSQL01\LAB'
$db_name = 'testdb'
$csv_folder = 'C:\temp'
$csv_completed_folder = 'C:\done'
# assuming only csv-files you want to import are located in $csv_folder
$csv_files = Get-Childitem -Path $csv_folder -Filter '*.csv'
foreach($file in $csv_files) {
$impcsv = $file.FullName
write-host "Processing file ..........$impcsv" -foregroundcolor green
$data = import-csv $impcsv
$count = 1
foreach($i in $data) {
$reference = $i.reference
$quantity = $i.quantite
$query = "UPDATE dbo.F_ARTSTOCK (reference,quantity)
SET quantity = '$quantity'
WHERE reference = '$reference'"
$impcsv = invoke-sqlcmd -Database $db_name -Query $query -serverinstance $sql_instance_name
write-host "Processing row ..........$count" -foregroundcolor green
$count = $count + 1
}
}

Export table object to CSV

We extracted the required tables from word doc, but can someone help... that how can I export this table object $LETable to CSV, or export values which we have fetched below in CSV in table format.
$objWord = New-Object -Com Word.Application
$filename = 'D:\Files\Scan1.doc'
$objDocument = $objWord.Documents.Open($filename)
$LETable = $objDocument.Tables.Item(4)
$LETableCols = $LETable.Columns.Count
$LETableRows = $LETable.Rows.Count
$obj = New-Object -TypeName PSCustomObject
Write-Output "Starting to write... "
for($r=1; $r -le $LETableRows; $r++) {
for($c=1; $c -le $LETableCols; $c++) {
#Write-Host $r "x" $c
$content = $LETable.Cell($r,$c).Range.Text
Write-Host $content
}
}
$objDocument.Close()
$objWord.Quit()
# Stop Winword Process
$rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objWord)
Not quite ready a solution but I have no more time ATM.
The script outputs all fields enclosed in double quotes and delimited with commas per row and stores in a variable $RawCSV which then is passed to ConvertFrom-Csv
I had trouble with a cr/lf and char 7 in the cell values which I replace with nothing
## Q:\Test\2018\07\17\SO_51385204.ps1
$CsvName = '.\Test.csv'
$filename = (Get-Item ".\Test-text.docx").FullName
$tableNum = 4
$delimiter = ','
$objWord = New-Object -Com Word.Application
$objWord.Visible = $true # $false
$objDocument = $objWord.Documents.Open($filename)
$LETable = $objDocument.Tables.Item($tableNum)
$LETableCols = $LETable.Columns.Count
$LETableRows = $LETable.Rows.Count
Write-Output "Starting to write... "
# "Table rows:{0} cols:{1}" -f $LETableRows,$LETableCols
$RawCSV = for($r=1; $r -le $LETableRows; $r++) {
$content= #()
for($c=1; $c -le $LETableCols; $c++) {
#Write-Host ("R:{0},C:{1}" -f $r,$c)
$content += ("`"{0}`"" -f $LETable.Cell($r,$c).Range.Text -replace "(`r|`n|`t)|$([char]7)?")
}
$Content -join $delimiter
}
$Csv = $RawCSV | ConvertFrom-Csv
$objDocument.Close()
$objWord.Quit()
# Stop Winword Process
$rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objWord)
$Csv
$Csv | Export-Csv $CsvName -NoTypeInformation

How to Export-Csv with variables?

I'm trying to write 8 variables into an CSV file with PowerShell, but it just ends up as ,,,,,,, instead of var1,var2,var3,var4,var5,var6,var7,var8
My code is as follows:
$newRow = "{0},{1},{2},{3},{4},{5},{6},{7}" -f $var1,$var2,$var3,$var4,$var5,$var6,$var7,$var8
$newRow = $newRow -Replace "`t|`n|`r",""
$newRow = $newRow -Replace " ;|; ",";"
$newRow += "`n"
$newRow | Export-Csv -Path $file -Append -noType -Force
Without -Force I get the following error message:
Export-Csv : Cannot append CSV content to the following file: C:\result.txt. The
appended object does not have a property that corresponds to the following column:
var1. To continue with mismatched properties, add the -Force parameter, and then
retry the command.
At C:\Test.ps1:72 char:12
+ $newRow | Export-Csv -Path $file -Append -noType
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (var1:String) [Export-Csv], InvalidOperationException
+ FullyQualifiedErrorId : CannotAppendCsvWithMismatchedPropertyNames,Microsoft.PowerShell.Commands.ExportCsvCommand
EDIT:
Script:
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = "powershell.exe"
$startInfo.Arguments = 'C:\zabbix\script\zabbix_vbr_job.ps1 "Discovery"'
$startInfo.RedirectStandardOutput = $true
$startInfo.UseShellExecute = $false
$startInfo.CreateNoWindow = $false
#$startInfo.Username = "DOMAIN\Username"
#$startInfo.Password = $password
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
$process.Start() | Out-Null
$discoveryJson = $process.StandardOutput.ReadToEnd()
$process.WaitForExit()
cls
$discovery = $discoveryJson | ConvertFrom-Json
$file = "C:\zabbix\script\result.txt"
function RunScript ($param, $id)
{
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = "powershell.exe"
$startInfo.Arguments = "C:\zabbix\script\zabbix_vbr_job.ps1 '$param' '$id'"
$startInfo.RedirectStandardOutput = $true
$startInfo.UseShellExecute = $false
$startInfo.CreateNoWindow = $false
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
$process.Start() | Out-Null
$output = $process.StandardOutput.ReadToEnd()
$process.WaitForExit()
return $output
}
$fileContent = Import-csv $file
$NewCSVObject = #()
foreach($obj in $discovery.data)
{
$index = [array]::indexof($discovery.data, $obj)
Write-Host $index "/" $discovery.data.count
#Write-Host (RunScript "Result" $obj.JOBID )
$Result = RunScript "Result" $obj.JOBID
#Write-Host $Result
$RunStatus = RunScript "RunStatus" $obj.JOBID
#Write-Host $RunStatus
$IncludedSize = RunScript "IncludedSize" $obj.JOBID
#Write-Host $IncludedSize
$ExcludedSize = RunScript "ExcludedSize" $obj.JOBID
#Write-Host $ExcludedSize
$VmCount = RunScript "VmCount" $obj.JOBID
#Write-Host $VmCount
$Type = RunScript "Type" $obj.JOBID
#Write-Host $Type
$RunningJob = "RunningJob"#RunScript "RunningJob" $obj.JOBID
#Write-Host $RunningJob
#$newRow = New-Object PsObject -Property #{ JobID = $obj.JOBID ; Result = $Result ; RunStatus = $RunStatus ; IncludedSize = $IncludedSize ; ExcludedSize = $ExcludedSize ; VmCount = $VmCount ; Type = $Type ; RunningJob = $RunningJob }
$newRow = "{0},{1},{2},{3},{4},{5},{6},{7}" -f $obj.JOBID,$Result,$RunStatus,$IncludedSize,$ExcludedSize,$VmCount,$Type,$RunningJob
$newRow = $newRow -Replace "`t|`n|`r",""
$newRow = $newRow -Replace " ;|; ",";"
$newRow += "`n"
#$newRow | Out-File $file
#[io.file]::WriteAllText("C:\zabbix\script\test.txt",$newRow)
Write-Host $newRow
$newRow | Export-Csv -Path $file -Append -noType
break
}
#cls
Write-Host $fileContent
CSV headers:
JobID,Result,RunStatus,IncludedSize,ExcludedSize,VmCount,Type,RunningJob
There is no point in using Export-Csv if you're building the CSV line by hand anyway.
Either change
$newRow | Export-Csv -Path $file -Append -noType -Force
into
$newRow | Add-Content $file
or build $newRow like this:
$newRow = New-Object -Type PSObject -Property #{
'JobID' = $var1
'Result' = $var2
'RunStatus' = $var3
'IncludedSize' = $var4
'ExcludedSize' = $var5
'VmCount' = $var6
'Type' = $var7
'RunningJob' = $var8
}
and the problem will disappear.
The reason for this behavior is that Export-Csv is for transforming objects into a tabular string representation of their properties. Essentially, an object
#{
propertyA: 'foo'
propertyB: 23
}
becomes
propertyA,propertyB
"foo","23"
If you're already building a string, the resulting (string) object has just a single property (Length), which doesn't match any of the properties from your existing CSV. Hence the error you're getting without -Force. Even if you use -Force, the properties written to the CSV are determined from the first item in the existing CSV. Properties that are not present in this set are omitted from the output, and properties from that set that are not present in the object are filled with null values.

Using powershell to modify notes.ini

I have a powershell script that parses a lotus notes INI file and replaces text inside the file. But only the replaced text is showing up in the output file.
# Example of PowerShell -replace parameter
## Get-DistinguishedName -- look up a DN from a user's (login) name
function Get-DistinguishedName {
Param($UserName)
$ads = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$ads.filter = "(&(objectClass=Person)(samAccountName=$UserName))"
$s = $ads.FindOne()
return $s.GetDirectoryEntry().DistinguishedName
}
clear-Host
set-executionpolicy remotesigned
$original_file = '.\notes.ini'
$destination_file = '.\notes2.ini'
$OS = Get-WmiObject -Class win32_OperatingSystem -namespace "root\CIMV2" -ComputerName .
$username = [Environment]::UserName
$userprofile = $env:userprofile
$fullname = Get-DistinguishedName($username) | %{$data = $_.split(","); $data[0].Substring(3)}
write-Host "Creating $userprofile"
if (($OS.Version -eq "5.1.2600") -or ($OS.Version -eq "5.2.3790")) {
$lookupTable = #{
'^SU_FILE_CLEANUP=' = 'SU_FILE_CLEANUP=' + $userprofile + '\Local Settongs\Application Data\smkits'
'%username%' = $username
'%fullname%' = $fullname
'%userprofile%' = $userprofile
'^Directory=' = 'Directory=' + $userprofile + '\Local Settongs\Application Data\Lotus\Notes\Data'}
} else {
$lookupTable = #{
'SU_FILE_CLEANUP=' = 'SU_FILE_CLEANUP=' + $userprofile + '\AppData\Roaming\smkits'
'%username%' = $username
'%fullname%' = $fullname
'%userprofile%' = $userprofile
'Directory=' = 'Directory=' + $userprofile + '\AppData\Local\Lotus\Notes\Data'}
}
Get-Content -Path $original_file | ForEach-Object {
$line = $_
$lookupTable.GetEnumerator() | ForEach-Object {
if ($line -match $_.Key)
{
$line -replace $_.Key, $_.Value
#break
}
}
write-Host $line
} | Set-Content -Path $destination_file
What am I missing
On this line, you are writing he output of the replace operator onto the pipeline, this will then get picked up by Set-Content
$line -replace $_.Key, $_.Value
whereas on this line, you are writing the output to the host (i.e. the powershell console) it will not end up on the pipeline and will not get picked up up Set-Content:
write-Host $line
To fix this, just replace write-host with write-output:
Write-Output $line