Reputation: 307
I have an excel file with multiple sheets which are populated with sku and quantity column. I need to search the entire workbook for multiple items and return their quantity. products.txt contains the sku IDs.
ABC1234
BCDH214
LDJI983
And the Excel workbook, inventory.xlsx contains the following columns
**sku** ***Quantity***
ABC1234 2
BCDH214 0
LDJI983 1
I would like to run prodcuts.txt against inventory.xlsx and return the quantity of each product.
Can this be done via powershell? or any other way to run this kind of query?
Upvotes: 1
Views: 646
Reputation: 7163
Use the code shown here Get Excel data without Excel and ensure you have the ACE.OLEDB provider installed.
I created a simple xlsx with:
SKU Quantity
one 1
two 4
three 9
Then I called into Excel:
$path = 'd:\test\exceldb.xlsx'
$results = Get-ExcelData -Path $path -Query 'SELECT * FROM [Sheet1$]'
$stuffFromProductsTxtFile = 'one', 'two', 'three'
foreach ($sku in $stuffFromProductsTxtFile)
{
$results.Rows | Where-Object {$_.SKU -eq $sku} | % {Write-Output "$($_.SKU) has quantity $($_.Quantity)"}
}
This gives the following output:
one has quantity 1
two has quantity 4
three has quantity 9
I think with this, you can change accordingly to whatever you require.
For completeness, I have copied the sample code from the aforementioned MSDN blog here:
function Get-ExcelData {
[CmdletBinding(DefaultParameterSetName='Worksheet')]
Param(
[Parameter(Mandatory=$true, Position=0)]
[String] $Path,
[Parameter(Position=1, ParameterSetName='Worksheet')]
[String] $WorksheetName = 'Sheet1',
[Parameter(Position=1, ParameterSetName='Query')]
[String] $Query = 'SELECT * FROM [Sheet1$]'
)
switch ($pscmdlet.ParameterSetName) {
'Worksheet' {
$Query = 'SELECT * FROM [{0}$]' -f $WorksheetName
break
}
'Query' {
# Make sure the query is in the correct syntax (e.g. 'SELECT * FROM [SheetName$]')
$Pattern = '.*from\b\s*(?<Table>\w+).*'
if($Query -match $Pattern) {
$Query = $Query -replace $Matches.Table, ('[{0}$]' -f $Matches.Table)
}
}
}
# Create the scriptblock to run in a job
$JobCode = {
Param($Path, $Query)
# Check if the file is XLS or XLSX
if ((Get-Item -Path $Path).Extension -eq 'xls') {
$Provider = 'Microsoft.Jet.OLEDB.4.0'
$ExtendedProperties = 'Excel 8.0;HDR=YES;IMEX=1'
} else {
$Provider = 'Microsoft.ACE.OLEDB.12.0'
$ExtendedProperties = 'Excel 12.0;HDR=YES'
}
# Build the connection string and connection object
$ConnectionString = 'Provider={0};Data Source={1};Extended Properties="{2}"' -f $Provider, $Path, $ExtendedProperties
$Connection = New-Object System.Data.OleDb.OleDbConnection $ConnectionString
try {
# Open the connection to the file, and fill the datatable
$Connection.Open()
$Adapter = New-Object -TypeName System.Data.OleDb.OleDbDataAdapter $Query, $Connection
$DataTable = New-Object System.Data.DataTable
$Adapter.Fill($DataTable) | Out-Null
}
catch {
# something went wrong :-(
Write-Error $_.Exception.Message
}
finally {
# Close the connection
if ($Connection.State -eq 'Open') {
$Connection.Close()
}
}
# Return the results as an array
return ,$DataTable
}
# Run the code in a 32bit job, since the provider is 32bit only
$job = Start-Job $JobCode -RunAs32 -ArgumentList $Path, $Query
$job | Wait-Job | Receive-Job
Remove-Job $job
}
Upvotes: 1