powershell export to excel and perform subtotals in workbook - excel

I am creating spreadsheet to compare the hotfixes on servers that I am also using for historical record to help diagnose issues between servers.
I have downloaded Douglas Fink's module that was featured by The Scripting Guys which will allow me to export-excel and it works very well.
I am writing the data to a csv, and then sorting it as I write it out to excel workbook. This works well, but I would like to also add a subtotal based on the count of KBxxx so that if I have the total number that matches my servers, I know that all of my servers have that KB.
I am just starting with Powershell, and have never worked with writing excel. Please help or give me some guidance.
$Date = Get-Date
$files = Get-ChildItem -path $PSScriptRoot\servers\*.*
$Filename = "-" + $Date.Year + "-" + $Date.Month + "-" + $Date.Day + "_" + $date.Hour + $date.Minute
foreach ($server in $servers){
$server
Get-hotfix -ComputerName $server |
Select CSName, Description,HotFixID,InstalledOn|
Export-Csv -Path "$PSScriptRoot\output\$($file.basename)-HotFix-list-$($Filename).csv" -Append -NoTypeInformation
}
Import-Csv -path "$PSScriptRoot\output\$($file.basename)-HotFix-list-$($Filename).csv" | Sort-Object -Property HotFixID |Export-Excel -Path "$PSScriptRoot\output\$($file.basename)-list-$($Filename).xlsx" -WorksheetName HotFixID -Append
#Remove-Item -Path "$PSScriptRoot\output\*.csv" -Force
If I use the subtotal command with the following settings, It totals the data by each hotfix.
I can easily see all servers queried have the top KB (1) When I expand the Hotfix selection (2) It shows me the remaining detail. (3)
I am learning by getting the script to run, and then adding a little more function each time.
Keith

Related

how to compare two excel sheet using powershell

I have last month excel sheet with following
Current month excel sheet with following
Now i would like find what is new server Name added in current month then list them out as shown below
So far i got following code. any idea would be appreciated ? i will be scheduling this with windows scheduler task .This should be powershell since i will be adding more code later how to pick right excel sheet from SMB share.
i am trying this
$oldbk = Import-Excel -Path '\\hcohesity05\cohesity_reports\2022\7\07-29\Cohesity_FETB_Report-2022-07-29-14-26-48.xlsx'
$newbk = Import-Excel -Path '\\hcohesity05\cohesity_reports\2022\8\08-26\Cohesity_FETB_Report-2022-08-26-14-26-48.xlsx'
$Compare = Compare-Object $oldbk $newbk -Property "Server Name" -includeDifferent -PassThru
$Compare | Export-Excel -Path '.\diff.xlsx'
but getting message
A parameter cannot be found that matches parameter name 'includeDifferent'.
By looking at your code I'm assuming you're only interested in finding the servers not present in the old Excel document, if that's the case you only need Where-Object for filtering:
$oldbk = Import-Excel -Path 'path\to\oldfile.xlsx'
Import-Excel -Path 'path\to\newfile.xlsx' | Where-Object {
$_."Server Name" -notin $oldbk."Server Name"
} | Export-Excel -Path 'path\to\diff.xlsx'
As for the error message, Compare-Object does not have a -IncludeDifferent parameter and shows differences between two objects by default.
$Compare = Compare-Object $oldbk $newbk -Property "Server Name" -PassThru

Powershell Separate csv data into separate rows

I have the following script and it gets me the info I need.
$Monitors = Get-WmiObject WmiMonitorID -Namespace root\wmi
$LogFile = "d:\monitors.csv"
"Manufacturer,Name,Serial" | Out-File $LogFile
ForEach ($Monitor in $Monitors)
{
$Manufacturer = ($Monitor.ManufacturerName|where {$_ -ne 0}|ForEach{[char]$_}) -join ""
$Name = ($Monitor.UserFriendlyName |where {$_ -ne 0}| ForEach{[char]$_}) -join ""
$Serial = ($Monitor.SerialNumberID |where {$_ -ne 0}| ForEach{[char]$_}) -join ""
"$Manufacturer,$Name,$Serial" | Out-File $LogFile -append
}
My problem is the data is exported to the excel spreadsheet like this..
Manufacturer,Name,Serial.
ACI,VE248,K8LMQS048382
HWP,HP P232,6CM8122DXL
HWP,HP P232,6CM7241DRB
I need it to be:
Manufacturer Name Serial
in the spreadsheet, and when I do the next pc, it adds to the next line and so on.
I have looked online and the examples just don't match.
Does anyone have any advice?
As others already commented, use Export-Csv to write out the wanted data in csv format, rather than constructing it manually.
That means your ForEach-Object loop should emit objects instead of lines of concatenated strings.
Also, nowadays, I would use the newer Get-CimInstance instead of Get-WmiObject (What's the difference)
Try
$LogFile = "d:\monitors.csv"
Get-CimInstance -ClassName WmiMonitorID -Namespace root\wmi | ForEach-Object {
[PsCustomObject]#{
Manufacturer = [string]::new($_.ManufacturerName, 0, $_.ManufacturerName.Length).Trim("`0")
Name = [string]::new($_.UserFriendlyName, 0, $_.UserFriendlyName.Length).Trim("`0")
Serial = [string]::new($_.SerialNumberID, 0, $_.SerialNumberID.Length).Trim("`0")
}
} | Export-Csv -Path $LogFile -NoTypeInformation -UseCulture
The -UseCulture switch makes sure the output csv file uses the same delimiter characters your locally installed Excel would expect, so you can simply double-click the file to open it in Excel

Excluding lines, which are not containing one or multiple strings from text file

I have multiple server log files. In total they contain around 500.000 lines of log text. I only want to keep the lines that contain "Downloaded" and "Log". Lines I want to exclude are focussing on error logs and basic system operations like "client startup", "client restart" and so on.
An example of the lines we are looking for is this one:
[22:29:05]: Downloaded 39 /SYSTEM/SAP logs from System-4, customer (000;838) from 21:28:51,705 to 21:29:04,671
The lines that are to be kept should be complemented by the date string, which is part of the log-file name. ($date)
Further, as the received logs are rather unstructured, the filtered files should be transformed into one csv-file (columns: timestamp, log downloads, system directory, system type, customer, start time, end time, date [to be added to every line from file name]. The replace operation of turning spaced into comma is just a first try to bring in some structure to the data. This file is supposed to be loaded into a python dashboard program.
At the moment it takes 2,5 mins to preprocess 3 Txt-Files, while the target is 5-10 seconds maximum, if even possible.
Thank you really much for your support, as I'm struggeling with this since Monday last week. Maybe powershell is not the best way to go? I'm open for any help!
At the moment I'm running this powershell script:
$files = Get-ChildItem "C:\Users\AnonUser\RestLogs\*" -Include *.log
New-Item C:\Users\AnonUser\RestLogs\CleanedLogs.txt -ItemType file
foreach ($f in $files){
$date = $f.BaseName.Substring(22,8)
(Get-Content $f) | Where-Object { ($_ -match 'Downloaded' -and $_ -match 'SAP')} | ForEach-Object {$_ -replace " ", ","}{$_+ ','+ $date} | Add-Content CleanedLogs.txt
}
This is about the fastest I could manage. I didn't test using -split vs -replace or special .NET methods:
$files = Get-ChildItem "C:\Users\AnonUser\RestLogs\*" -Include *.log
New-Item C:\Users\AnonUser\RestLogs\CleanedLogs.txt -ItemType file
foreach ($f in $files) {
$date = $f.BaseName.Substring(22,8)
(((Get-Content $f) -match "Downloaded.*?SAP") -replace " ",",") -replace "$","$date" | add-content CleanedLogs.txt
}
In general, speed is gained by removing loops and Where-Object "filtering."

Copying and renaming date in file name + 7 days. (PowerShell)

I have a folder of spreadsheets which all start with "WEEK COMM" and then the date. For example "WEEK COMM 24-12-2018". What I am looking to do is a script that finds the latest file, makes a copy of it in the SAME folder, and changes the date in the filename by adding 7 days.
So far I have got this, which successfully locates the most up to date file, and copies it as "WEEK COMM TEST", but I am unable to find anything about adding a date to the filename.
Get-ChildItem -Path "\\DESKTOP-88SIUP6\Users\User\Desktop\Shared\STOCK ORDERS\2018" |
Sort-Object -Property CreationTime -Descending |
Select-Object -First 1 |
Copy-Item -Destination "\\DESKTOP-88SIUP6\Users\User\Desktop\Shared\STOCK ORDERS\2018\WEEK COMM TEST.xlsx" -Force
Could anyone please help me?
this will capture the string date from the file .BaseName property, convert it to a [datetime] object, add 7 days, convert that to a date string in your [backwards [grin]] format, and then replace the old date string with the new date string in the .FullName of the file.
that should make the rename process pretty direct & easy. [grin]
if you can, you would likely have a rather easier time if you switched to the more logical, properly sortable yyyy-MM-dd format. you may not be able to do so, but it's worth trying ...
$FileName = [System.IO.FileInfo]'WEEK COMM 24-12-2018.xlsx'
$FN_StringDate = $FileName.BaseName.Split(' ')[2]
$FN_Date = [datetime]::ParseExact($FN_StringDate, 'dd-MM-yyyy', $Null)
$NewFN_StringDate = $FN_Date.AddDays(7).ToString('dd-MM-yyyy')
$NewFileName = $FileName.FullName -replace $FN_StringDate, $NewFN_StringDate
$FileName.FullName
$NewFileName
output [old, then new] ...
D:\Data\Scripts\WEEK COMM 24-12-2018.xlsx
D:\Data\Scripts\WEEK COMM 31-12-2018.xlsx
edit to add a very specific example. it's untested since i haven't any such location ... that is why the -WhatIf is there. [grin]
$SourceDir = '\\DESKTOP-88SIUP6\Users\User\Desktop\Shared\STOCK ORDERS\2018'
Get-ChildItem -Path $SourceDir |
Sort-Object -Property CreationTime -Descending |
Select-Object -First 1 |
ForEach-Object {
$FN_StringDate = $_.BaseName.Split(' ')[2]
$FN_Date = [datetime]::ParseExact($FN_StringDate, 'dd-MM-yyyy', $Null)
$NewFN_StringDate = $FN_Date.AddDays(7).ToString('dd-MM-yyyy')
$NewFileName = $_.FullName -replace $FN_StringDate, $NewFN_StringDate
# remove the "-WhatIf" when you are ready to do this for real
Copy-Item -LiteralPath $_.FullName -Destination $NewFileName -WhatIf
}

Powershell script to pull remote pc serial number then match against an xlsx file then match against another and output only needed info

hey im trying to build a powershell script that will pull a serial number from a remote pc and then match that against an xlsx file which would then match a column against another xlsx file i have gotten to the point where i can pull the remote sn and have everything put in to a csv output but i am having issues matching the data then filtering based on the match and then outputting only what i need im new to scripting so im pretty sure its more my lack of experiance than anything else this is my code so far
$computers = Get-Content c:\script\computerlist.txt
Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber| Format-Table |out-file C:\script\computerinfo.txt
$computerinfo = Import-Excel C:\script\compDB.xlsx
$userinfo = Import-Excel C:\script\userDB.xlsx
$Computerinfo[2].SERIAL -eq
$Computerinfo[2].DATE_ADDED
$Computerinfo[2].OS
$Computerinfo[2].MODEL
$Computerinfo[2].USER
$userinfo[2].NAME_FIRST
$userinfo[2].NAME_LAST
$userinfo[2].NT_USERID
''
'Computer Info'
'----------'
$computerinfo ,$userinfo | Format-Table - | Out-File c:\script\computerinfo.csv
First you need to save the wmi information to a variable:
$WMIinfo = Get-wmiobject Win32_Bios -ComputerName $computers | Select-Object __SERVER, SerialNumber
Then you would need to loop through the spreadsheet and compare to data in Computer spreadsheet. If it matches loop through user spreadsheet for match:
foreach ($CompEntry in $Computerinfo) {
if ($WMIinfo.serial -eq $CompEntry.serial) {
foreach ($UserEntry in $userinfo) {
if ($UserEntry.NT_USERID -eq $CompEntry.USER) {
#output information you want here
}
}
}
I'll try to help you get there.
I created an Excel file called Serial.xslx. Here's what it looks like
SerialNumber DeployedTo
212 Ham
4M24N32 Stephen
I then import this as $list.
$list = import-excel C:\temp\serial.xlsx
Next,to get the Win32_Bios info, so I can grab the SerialNumber property.
$bios = get-WmiObject Win32_Bios
Finally, I'll filter through the $list (which contains the Excel file), and find a row which has a SerialNumber that matches this computers serial number. If I find a matching one, then I grab the .DeployedTo value for that record.
$user = $list | Where SerialNumber -eq $bios.SerialNumber | Select -ExpandProperty DeployedTo
All that remains is to demonstrate that it works.
"the computer with serial $($bios.SerialNumber) is deployed to $user"
>the computer with serial 4M24N32 is deployed to Stephen
Now, you've got two separate excel files, so I would either manually join them into one, or repeat this same basic approach.

Resources