In input :
i have an \users\myself\desktop\test\file.xslx containing multiples column like this :
ColumnA ColumnB ... ColumnQ (for a total of 17 columns)
each column have some data.
In output :
I would like to have a cmd like this :
New-ADUser -Name $(columnAdata) -GivenName "$(columnBdata)" -Surname "$(columnCdata)" -DisplayName "$(columnDdata)" -SamAccountName "$(columnEdata)" ... etc until -blabla "$(ColumnQdata)"
Is that possible to store de columndata in variables to insert them in a command ?
Thanks a lot.
I would suggest to first change the column headers to be the same as the parameters you intend to use with the New-ADUser cmdlet.
Having matching headers would help greatly in not making mistakes.
Next, save your Excel file as CSV, let's say a file called NewUsers.csv
The code then can be quite simple and easy to maintain:
# import the CSV file using the same separator character as Excel uses on your system
Import-Csv -Path 'X:\NewUsers.csv' -UseCulture | ForEach-Object {
# use Splatting: create a Hashtable with all properties needed taken from the CSV
# see: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting
$userProperties = #{
Name = $_.Name # as opposed to $_.columnAdata
GivenName = $_.GivenName # as opposed to $_.columnBdata
Surname = $_.Surname
DisplayName = $_.DisplayName
SamAccountName = $_.SamAccountName
# etcetera
}
New-ADUser #userProperties
}
Related
I'm currently stuck on a specific comparisson problem. I have two CSV files which contain application names and I need to compare both csvs for matching names. Of course that would be easy if the applications were written the same ways in both csvs, but they're not.
Each csv has two columns but only the first column contains tha application names. In csv01 an app is called "Adobe Acrobat Reader DC Continuous MUI" while the same app in csv02 is called "Adobe Acrobat Reader DC v2022.002.20191". By looking at the files, I know both contain "Adobe Reader DC". But I'd like to automate th comparisson as the csvs contains hundreds of apps.
I initially thought I'd run a nested foreach loop, taking the first product in csv01 and comparing every app in csv02 to that product to see if I have a match. I did that by splitting the application names at each space character and came up with the following code:
# Define the first string
$Products01 = Import-CSV 'C:\Temp\ProductsList01.csv' -Delimiter ";"
# Define the second string
$Products02 = Import-CSV 'C:\Temp\ProductList02.csv' -Delimiter ";"
# Flag to track if all parts of string2 are contained within string1
$allPartsMatch = $true
# Create Hashtable for results
$MatchingApps = #{}
# Loop through each part of string2
foreach ($Product in $Products01.Product) {
Write-Host "==============================="
Write-Host "Searching for product: $Product"
Write-Host "==============================="
# Split the product name into parts
$ProductSplit = $Product -split " "
Write-Host "Split $Product into $ProductSplit"
foreach ($Application in $Products02.Column1) {
Write-Host "Getting comparisson app: $Application"
# Split the product name into parts
$ApplicationSplit = $Application -split " "
Write-Host "Split comparisson App into: $ApplicationSplit"
# Check if the current part is contained within string1
if ($ProductSplit -notcontains $ApplicationSplit) {
# If the current part is not contained within string1, set the flag to false
$allPartsMatch = $false
}
}
# Display a message indicating the result of the comparison
if ($allPartsMatch) {
Write-Host "==============================="
Write-Host "$Application is contained within $Product"
Write-Host "==============================="
$MatchingApps += #{Product01 = $Product; Product02 = $Application}
} else {
#Write-Host "$Application is not contained within $Product"
}
}
However, I seem to have a logic error in my thought process as this returns 0 matches. So obviously, the script isn't properly splitting or comparing the split items.
My question is - how do compare the parts of both app names to see if I have the apps in both csvs? Can I use a specific regex for that or do I need to approach the problem differently?
Cheers,
Fred
I tried comparing both csv files for similar product names. I expected a table of similar product names. I received nothing.
The basis for "matching" one string to another is that they share a prefix - so start by writing a small function that extracts the common prefix of 2 strings, we'll need this later:
function Get-CommonPrefix {
param(
[string]$A,
[string]$B
)
# start by assuming the strings share no common prefix
$prefixLength = 0
# the maximum length of the shared prefix will at most be the length of the shortest string
$maxLength = [Math]::Min($A.Length, $B.Length)
for($i = 0; $i -lt $maxLength; $i++){
if($A[$i] -eq $B[$i]){
$prefixLength = $i + 1
}
else {
# we've reached an index with two different characters, common prefix stops here
break
}
}
# return the shared prefix
return $A.Substring(0, $prefixLength)
}
Now we can determine the shared prefix between two strings:
PS ~> $sharedPrefix = Get-CommonPrefix 'Adobe Acrobat Reader DC Continuous MUI' 'Adobe Acrobat Reader DC v2022.002.20191'
PS ~> Write-Host "The shared prefix is '$sharedPrefix'"
The shared prefix is 'Adobe Acrobat Reader DC '
Now we just need to put it to use in your nested loop:
# Import the first list
$Products01 = Import-CSV 'C:\Temp\ProductsList01.csv' -Delimiter ";"
# Import the second list
$Products02 = Import-CSV 'C:\Temp\ProductList02.csv' -Delimiter ";"
# now let's find the best match from list 2 for each item in list 1:
foreach($productRow in $Products01) {
# we'll use this to keep track of shared prefixes encountered
$matchDetails = [pscustomobject]#{
Index = -1
Prefix = ''
Product2 = $null
}
for($i = 0; $i -lt $Products02.Count; $i++) {
# for each pair, start by extracting the common prefix and see if we have a "better match" than previously
$commonPrefix = Get-CommonPrefix $productRow.Product $Products02[$i].Product
if($commonPrefix.Length -gt $matchDetails.Prefix.Length){
# we found a better match!
$matchDetails.Index = $i
$matchDetails.Prefix = $commonPrefix
$matchDetails.Product2 = $Products02[$i]
}
}
if($matchDetails.Index -ge 0){
Write-Host "Best match found for '$($productRow.Product)': '$($matchDetails.Product2.Product)' "
# put code that needs to work on both rows here ...
}
}
Note: in cases where multiple entries in the second list matches the same-length prefix from the first list, the code simply picks the first match.
sorry if this is a rookie question, bit new to this... I'm trying to upload data from a .csv file to an online table using JSON.
The script below is recognised, especially the string values, but the rest of the columns appear but every value is 0. Even the 'Computer Name' section, when it should be 'Computer-01'.
I'm not entirely sure what i've done wrong, but imagine it's something syntax related. I've tried swapping out the intergers with string, but that usually causes the '0' to disappear and it's just blank.
Any direction would be appreciated!
Thank you.
#SU tile
$data = Import-Csv -Path "C:\Temp\file.csv" -Delimiter ','
$data | Select-Object #{
Name = "Domain";
Expression ={[string]$_.Domain}
},
#{
Name = "Name";
Expression ={[string]$_.Name}
},
#{
Name = "Computer Name";
Expression ={[int]$_.ComputerName}
},
#{
Name = "IP Address";
Expression ={[int]$_.IPAddress}
},
#{
Name = "Approved Updates Installed";
Expression ={[int]$_.ApprovedUpdatesInstalled}
},
#{
Name = "Last Reported Status Date";
Expression = {[LastReportedStatusDate]::ParseExact($($_.LastReportedStatusDate), 'dd/MM/yyyy',[Globalization.CultureInfo]::CreateSpecificCulture('en-GB'))}
},
#{
Name = "Make";
Expression = {[String]$_.Make}
}
I've tried swapping out the integers with string, but that usually causes the '0' to disappear and it's just blank.
I'm expecting the numbers on the spreadsheet, so 2,25,54 etc and ip addresses e.g. 123.11.23
I need help comparing two Excel files in Powershell.
I have an Excel-file which contains 6 000 rows and 4-5 columns with headers:
"Number" "Name" "Mobile data".
Let's call it: $Services
Now, I want to compare that file with other Excel-files. For example:
one file containing 50 rows with header columns: "Number", "Name", etc.
Let's call it $Department
The important thing is that in $Services, it contains more important columns like "Mobile data",
so my mission is to compare column: "Number" from $Services with column "Number" from each other Excel file.
Then if they match, write "the whole row" from $Services
I'm not that familiar with Excel, so I thought, this should be possible to do in Powershell.
I'm novice in Powershell, so I only know basic stuff. I'm not that familiar with pscustomobject and param.
Anyway, what I tried to do was to first declare them in variables with ImportExcel:
$Services = Import-Excel -Path 'C:\Users\*.xlsx'
$Department = Import-Excel -Path 'C:\Users\*.xlsx'
Then I made a foreach statement:
foreach ($Service in $Services) {
if (($Service).Number -like ($Department).Number)
{Write-Output "$Service"}
}
The problem with this is that it is collecting all empty columns from ($Services).Number and writing the output of each row in $Services.
I tried to add a nullorEmpty to $Department, if the .Number is empty, but it didn't make any difference. I also tried to add that if the row is empty in .Number, add "1234", but still it collects all .Number that is empty in $Services.
I also tried to do a: $Services | ForEach-Object -Process {if (($_).Number -match ($Department).Number)
{Write-Output $_}} But it didn't match any. When I tried -notmatch it took all.
I don't know but it seems that I have to convert the files to objects, like the columns to object so each string becomes an object. But right now my head is just spinning and I need some hints on where I can start with this.
I would recommend downloading the Module ImportExcel from the PSGallery.
Import-Excel can easily import your Excel sheet(s) to rows of objects, especially if your sheets are 'clean', i.e., only contain (optional) headers and data rows.
Simply import the cells to PowerShell objects and use Compare-Object to discover differences.
EDIT (after reading the additional questions by poster in the comments):
To compare using specific properties you'll need to add these to the Compare-Object parameters.
Using a trivial "PSCustomObject" to create a simple set of objects to show this idea it might look like this:
$l = 1..4 | ForEach-Object { [pscustomobject]#{a=$_;b=$_+1} }
$r = 1,2,4,5 | ForEach-Object { [pscustomobject]#{a=$_;b=$_+1} }
compare-object $l $r -Property B
B SideIndicator
- -------------
6 =>
4 <=
You may also compare multiple properties this way:
compare-object $l $r -Property A,B
A B SideIndicator
- - -------------
5 6 =>
3 4 <=
FYI: I find myself typing "Get-Command -Syntax SomeCommand" so often every day that I just made a function "Get-Syntax" (which also expands aliases) and then aliased this to simply "syn".
90% of the time once you understand the structure of PowerShell cmdlets (at least well-written ones) there is no need to even look at the full help -- the "syntax" blocks are sufficient.
Until then, type HELP (Get-Help) a lot -- 100+ times per day. :)
So the solution for my whole problem was to add -PassThru.
Because my mission was to compare the numbers of the two Excel-files, select the numbers that equals and then take all the properties from one file. So my script became like this:
$Compare = Compare-Object $Services $Department -Property Numbers -IncludeEqual -ExcludeDifferent -PassThru
$Compare | Export-Excel -Path 'C:\Users\*
But I wonder, -PassThru sends all the objects from ReferenceObject, how can I send all the objects from DifferenceObject?
I've found myriad methods to retrieve data FROM a string with substrings, but what I want to do is create a new string that contains substrings. The reason for this is that I want to pass that string to a CSV through the Export-CSV cmdlet. This is in a PowerShell Forms created app.
So the plan would be to
1). Read the contents of each text box:
(e.g. $endusername.text $endusernumber.text $locationname.text)
2). Store those into a new string with substrings
($formoutput.endusername $formoutput.endusernumber $formoutput.locationname)
3). Output the string to a .CSV
Export-CSV -InputObject $formoutput "c:\output\formoutput.csv"
Basically, if I take any existing cmdlet (say, Get-Mailbox), store its output as a string, and then pass that string through the Export-CSV in the way explained above, it performs exactly the way I like - creating a .CSV with each of the substrings as a column, and the contents of that substring in the appropriately headed column. I just want to be able to do that with a string containing substrings that I define.
I think you are confusing nomenclature a little bit. It sounds like what you want is a custom object not a string. Here is some pseudo-code to get you going in the right direction:
$formOutput = New-Object PsCustomObject -Property #{'EndUserName' = $endUserName.Text;
'EndUserNumber' = $endUserNumber.Text;
'LocationName' = $locatioName.Text}
$formOutput | Export-CSV .\FileName.csv -NoTypeHeader
I need to find a way so that I can read values from an excel file and then replace all the corresponding values in another file accordingly. Basically, I found some discrepancy in one of the automated task we run and I need to convert some values within the file before I send it to the automated task. I have an excel file that list the "wrong" values and their corresponding "correct" values and I need to how Power shell can help me in this.
$docID = $args[0] $docid #Read Z ticker file
$Zfile = 'I:\IS\Rishabh\Z tickers Active.xls' # Find the .rps file imported automatically from schwab trust
$RPSFile= 'L:\Trading\Schwab Trust\Import\CS<%dmmdd-01yy>.RPS'
While (Get-Content $ZFile)
{
$_-cmatch 'A$','B$'| Set-Variable X-ticker # End Loop
}
(Get-Content $RPSfile) | ForEach-Object { $_-replace '%, ' ,'X-ticker' #End Loop }
Set-Content $RPSFile
You don't need to use Powershell. Excel itself has built in mechanisms for doing what you want. For example you could use the LOOKUP function in Excel.