Loading all these package dependencies with repetitive try
/ catch
blocks:
$libPath = ".\packages\DocumentFormat.OpenXml.3.3.0\lib\netstandard2.0"
$libFPath = ".\packages\DocumentFormat.OpenXml.Framework.3.3.0\lib\netstandard2.0"
$libSPath = ".\packages\System.IO.Packaging.8.0.0\lib\netstandard2.0"
$libMPath = ".\packages\System.Memory.4.5.4\lib\netstandard2.0"
$libBPath = ".\packages\System.Buffers.4.5.1\lib\netstandard2.0\System.Buffers.dll"
$libVPath = ".\packages\System.Numerics.Vectors.4.5.0\lib\netstandard2.0\System.Numerics.Vectors.dll"
$libCSPath = ".\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll"
#[System.Reflection.Assembly]::LoadFrom("$memoryPath\System.Memory.dll") | Out-Null
#Write-Host "Loaded: System.Memory.dll"
### Load all DLLs in the folder via reflection
Get-ChildItem -Filter "*.dll" -Path $libBPath | ForEach-Object {
try {
[System.Reflection.Assembly]::LoadFrom($_.FullName) | Out-Null
Write-Host "Loaded: $($_.Name)"
}
catch {
Write-Warning "Failed to load $($_.Name): $($_.Exception.Message)"
}
}
Then I try to open an excel file doing the following:
### Load path to excel file
try {
$excelFile = (Resolve-Path "./excel.xlsx").Path
Write-Host "Path resolved: $excelFile"
}
catch {
Write-Error "The file doesn't exist!"
}
### Load/Open excel file
try{
$doc = [DocumentFormat.OpenXml.Packaging.SpreadsheetDocument]::Open($excelFile, $false)
Write-Host "File opened successfully"
$doc.Close()
}
catch{
Write-Host "Error during excel file processing: $_"
Write-Host "Error during excel file processing .Message : $($_.Exception.Message)"
}
And receiving these exceptions:
Exception calling "Open" with "2" argument(s): "You cannot call a method on a null-valued expression." Error during excel file processing.
Message : Exception calling "Open" with "2" argument(s): "You cannot call a method on a null-valued expression."
Any ideas? Pretty much new to PowerShell.
The error implies you haven't loaded the OpenXml
library or is not correctly loaded. The likable reason is that the dependencies package versions aren't compatible, the most reliable way to determine this is to use the dotnet
CLI to download all dependencies, as shown in this answer.
Using the CLI on a project I've created, these are the required packages with the corresponding resolved versions. As you may see, some packages have a different resolved version than the ones you have.
PS \> dotnet list package --include-transitive
# Project 'DocumentFormat.OpenXml.Package' has the following package references
# [netstandard2.0]:
# Top-level Package Requested Resolved
# > DocumentFormat.OpenXml 3.3.0 3.3.0
# > NETStandard.Library (A) [2.0.3, ) 2.0.3
#
# Transitive Package Resolved
# > DocumentFormat.OpenXml.Framework 3.3.0
# > Microsoft.NETCore.Platforms 1.1.0
# > System.Buffers 4.5.1
# > System.IO.Packaging 8.0.1
# > System.Memory 4.5.5
# > System.Numerics.Vectors 4.4.0
# > System.Runtime.CompilerServices.Unsafe 4.5.3
#
# (A) : Auto-referenced package.
Based on the above, the first step I'd recommend is to re-download all packages with the exact version the CLI is giving us. For that you can use below code that will place all required assemblies in a folder named DocumentFormat.OpenXml
in your current directory:
$ProgressPreference = 'SilentlyContinue'
New-Item DocumentFormat.OpenXml -ItemType Directory | Push-Location
$package = @(
'DocumentFormat.OpenXml.3.3.0'
'DocumentFormat.OpenXml.Framework.3.3.0'
'System.Buffers.4.5.1'
'System.IO.Packaging.8.0.1'
'System.Memory.4.5.5'
'System.Numerics.Vectors.4.4.0'
'System.Runtime.CompilerServices.Unsafe.4.5.3'
)
$uri = 'https://api.nuget.org/v3/flatcontainer/{0}/{1}/{2}.nupkg'
foreach ($pkg in $package) {
$name, $version = $pkg -split '\.(?=\d)', 2
$zip = $name + '.zip'
$invokeWebRequestSplat = @{
OutFile = $zip
Uri = $uri -f $name, $version, $pkg
}
# download the package
Invoke-WebRequest @invokeWebRequestSplat
# extract it
Expand-Archive $zip
# move dlls to the current directory
Move-Item "$name\lib\netstandard2.0\*" -Destination . -EA 0
# remove the zip file and the extracted zip folder
Remove-Item $zip, $name -Recurse
}
Pop-Location
Then you can try loading them all and testing with OpenXml.Packaging.SpreadsheetDocument
, note here after testing, the class doesn't have a .Close()
method, use .Dispose()
instead:
# load all assemblies
Add-Type -Path .\DocumentFormat.OpenXml\*.dll
# resolve the path to the excel file
$excelFile = (Resolve-Path './test.xlsx' -ErrorAction Stop).Path
# load the document
$pkg = [DocumentFormat.OpenXml.Packaging.SpreadsheetDocument]::Open($excelFile, $false)
# dispose it
$pkg.Dispose()