SoFunction
Updated on 2025-04-12

Detailed explanation of how to use PowerShell to extract images embedded in wps tables

Open table image in Excel to display #NAME? The editing bar is displayed as =@_xlfn.DISPIMG (for example formulas, generally, under the wps program, Ctrl+F, search the range and select the value, enter =DISPIMG, and select all, and then right-click to convert it to a floating picture. If it is in Excel, it is the search formula DISPIMG.

After checking the online information, you can decompress the table file, and then look at the correspondence between name (its value is the first parameter of the dispimg function) and r:embed (its value starts with rId) in the xl_rels\ directory based on the first parameter in the formula (usually starting with ID), and then look at the correspondence between Id (starting with rId) and Target (image path) to obtain the path of the picture.

With the help of LLM, we will then have the following PS scripts.

function Get-ExcelDispImages {
    param (
        [Parameter(Mandatory=$true)]
        [string]$ExcelPath,
        
        [Parameter(Mandatory=$false)]
        [string]$OutputFolder = ".\ExcelImages"
    )

    # Helper function: Safely read file contents    function Read-FileContent {
        param (
            [string]$Path
        )
        try {
            # Use .NET method to directly read files to avoid PowerShell path resolution problems            if ([]::Exists($Path)) {
                return []::ReadAllText($Path)
            }
            Write-Host "File not found: $Path" -ForegroundColor Yellow
            return $null
        }
        catch {
            Write-Host "Error reading file $Path : $_" -ForegroundColor Yellow
            return $null
        }
    }

    try {
        # Verify that Excel file exists        if (-not (Test-Path -LiteralPath $ExcelPath)) {
            throw "Excel file not found: $ExcelPath"
        }

        # Make sure ExcelPath is the absolute path        $ExcelPath = (Get-Item $ExcelPath).FullName

        # Create an output folder (using absolute path)        $OutputFolder = []::GetFullPath($OutputFolder)
        if (-not (Test-Path -Path $OutputFolder)) {
            New-Item -ItemType Directory -Path $OutputFolder -Force | Out-Null
        }

        # Create Excel COM object        $excel = New-Object -ComObject 
        $ = $false
        $ = $false
        $workbook = $($ExcelPath)
        
        # Used to store the found DISPIMG ID and information        $dispImgIds = @()
        $imageMapping = @{}

        # traverse all worksheets        foreach ($worksheet in $) {
            $usedRange = $
            $rowCount = $
            $colCount = $
            
            for ($row = 1; $row -le $rowCount; $row++) {
                for ($col = 1; $col -le $colCount; $col++) {
                    $cell = $($row, $col)
                    $formula = $
                    
                    # Check whether the DISPIMG function is included and extract all parameters                    if ($formula -match 'DISPIMG\("([^"]+)"') {
                        $imageId = $matches[1]
                        Write-Host "Found DISPIMG: $formula" -ForegroundColor Gray
                        
                        # Create parameter list                        $params = @{
                            'ID' = $imageId
                            'Cell' = $()
                            'Formula' = $formula
                            'Worksheet' = $
                        }
                        
                        # Extract all parameters, including image ID                        $paramValues = @()
                        $formula -match 'DISPIMG\((.*?)\)' | Out-Null
                        $paramString = $matches[1]
                        $paramValues = $paramString -split ',' | ForEach-Object { 
                            $_ -replace '"', '' -replace '^\s+|\s+$', ''
                        }
                        
                        # Store all parameters                        for ($i = 0; $i -lt $; $i++) {
                            $params["Param$i"] = $paramValues[$i]
                        }
                        
                        $imageMapping[$imageId] = $params
                        $dispImgIds += $imageId
                    }
                }
            }
        }

        # Create a temporary directory        $tempPath = Join-Path ([]::GetTempPath()) "ExcelTemp"
        if (Test-Path $tempPath) {
            Remove-Item $tempPath -Recurse -Force
        }
        New-Item -ItemType Directory -Path $tempPath -Force | Out-Null

        # Copy Excel file to a temporary directory and decompress        $tempExcel = Join-Path $tempPath ""
        $tempZip = Join-Path $tempPath ""
        Copy-Item -Path $ExcelPath -Destination $tempExcel -Force
        if (Test-Path $tempZip) { Remove-Item $tempZip -Force }
        Rename-Item -Path $tempExcel -NewName "" -Force
        Expand-Archive -Path $tempZip -DestinationPath $tempPath -Force

        # Check media folder and process pictures        $mediaPath = Join-Path $tempPath "xl\media"
        if (Test-Path $mediaPath) {
            # Show the corresponding relationship between DISPIMG parameters and pictures            Write-Host "`nFound $($) DISPIMG functions" -ForegroundColor Cyan
            
            if ($ -gt 0) {
                Write-Host "`n=== DISPIMG Functions Found ===" -ForegroundColor Cyan
                Write-Host "Found $($) DISPIMG functions" -ForegroundColor Cyan
                
                # Show all DISPIMG functions found                Write-Host "`n=== DISPIMG Functions Details ===" -ForegroundColor Yellow
                foreach ($id in $) {
                    $params = $imageMapping[$id]
                    Write-Host "Cell: [$($)]$($)" -ForegroundColor Gray
                    Write-Host "Formula: $($)" -ForegroundColor Gray
                }
                
                # First get the mapping from DISPIMG ID to rId                $dispImgToRid = @{}
                $cellImagesPath = Join-Path $tempPath "xl\"
                Write-Host "`n=== Reading  ===" -ForegroundColor Yellow
                Write-Host "Path: $cellImagesPath" -ForegroundColor Gray
                
                if (Test-Path $cellImagesPath) {
                    try {
                        $xmlContent = Get-Content $cellImagesPath -Raw -EnCoding UTF8
                        Write-Host "`nRaw XML Content:" -ForegroundColor Gray
                        Write-Host $xmlContent
                        
                        # Use regular expression to extract all cellImage elements                        $matches = [regex]::Matches($xmlContent, '<etc:cellImage>.*?</etc:cellImage>', []::Singleline)
                        Write-Host "`nFound $($) cellImage elements" -ForegroundColor Gray
                        
                        foreach ($match in $matches) {
                            $cellImageXml = $
                            Write-Host "`nProcessing cellImage element:" -ForegroundColor Gray
                            
                            # Extract name attribute (including DISPIMG ID)                            if ($cellImageXml -match 'name="([^"]+)"') {
                                $dispImgId = $matches[1]
                                Write-Host "Found DISPIMG ID: $dispImgId" -ForegroundColor Gray
                                
                                # Extract the r:embed attribute (including rId)                                if ($cellImageXml -match 'r:embed="(rId\d+)"') {
                                    $rId = $matches[1]
                                    $dispImgToRid[$dispImgId] = $rId
                                    Write-Host "  Mapping: DISPIMG ID $dispImgId -> rId $rId" -ForegroundColor Green
                                }
                            }
                        }
                    }
                    catch {
                        Write-Host "Error reading : $($_.)" -ForegroundColor Red
                        Write-Host $_. -ForegroundColor Red
                    }
                }
                else {
                    Write-Host " not found!" -ForegroundColor Red
                }
                
                # Map from getting rId to actual picture                $ridToImage = @{}
                $cellImagesRelsPath = Join-Path $tempPath "xl\_rels\"
                Write-Host "`n=== Reading  ===" -ForegroundColor Yellow
                Write-Host "Path: $cellImagesRelsPath" -ForegroundColor Gray
                
                if (Test-Path $cellImagesRelsPath) {
                    try {
                        [xml]$relsXml = Get-Content $cellImagesRelsPath -Raw
                        Write-Host "`nXML Content:" -ForegroundColor Gray
                        Write-Host $
                        
                        $ | ForEach-Object {
                            if ($_.Target -match "media/") {
                                $ridToImage[$_.Id] = $_.Target
                                Write-Host "  rId $($_.Id) -> $($_.Target)" -ForegroundColor Green
                            }
                        }
                    }
                    catch {
                        Write-Host "Error reading : $($_.)" -ForegroundColor Red
                        Write-Host $_. -ForegroundColor Red
                    }
                }
                else {
                    Write-Host " not found!" -ForegroundColor Red
                }
                
                Write-Host "`n=== Summary of Mappings ===" -ForegroundColor Yellow
                Write-Host "DISPIMG ID -> rId mappings:" -ForegroundColor Gray
                $() | ForEach-Object {
                    Write-Host "  $($_.Key) -> $($_.Value)" -ForegroundColor Gray
                }
                
                Write-Host "`nrId -> Image mappings:" -ForegroundColor Gray
                $() | ForEach-Object {
                    Write-Host "  $($_.Key) -> $($_.Value)" -ForegroundColor Gray
                }
                
                # Process each DISPIMG function                Write-Host "`n=== Processing DISPIMG Functions ===" -ForegroundColor Yellow
                foreach ($id in $) {
                    $params = $imageMapping[$id]
                    
                    Write-Host "`nProcessing: [$($)]$($)" -ForegroundColor Green
                    Write-Host "Formula: $($)" -ForegroundColor Gray
                    Write-Host "DISPIMG ID: $id" -ForegroundColor Gray
                    
                    # Find the corresponding rId from DISPIMG ID                    $rId = $dispImgToRid[$id]
                    if ($rId) {
                        Write-Host "Found rId: $rId" -ForegroundColor Green
                        
                        # Find the corresponding image path from rId                        $imagePath = $ridToImage[$rId]
                        if ($imagePath) {
                            Write-Host "Found image path: $imagePath" -ForegroundColor Green
                            $imageName = Split-Path $imagePath -Leaf
                            
                            # Find the corresponding picture file                            $mediaFile = Get-ChildItem -LiteralPath $mediaPath | Where-Object { $_.Name -eq $imageName }
                            if ($mediaFile) {
                                $outputPath = Join-Path $OutputFolder "$id$($)"
                                Copy-Item -LiteralPath $ -Destination $outputPath -Force
                                Write-Host "Successfully copied: $imageName -> $outputPath" -ForegroundColor Cyan
                           # Copy with the file name under the media folder                           #    Copy-Item  $  $(Join-Path $OutputFolder $(Split-Path $imagePath -Leaf))
                            }

                            else {
                                Write-Host "Image file not found: $imageName" -ForegroundColor Red
                            }
                        }
                        else {
                            Write-Host "No image path found for rId: $rId" -ForegroundColor Red
                        }
                    }
                    else {
                        Write-Host "No rId found for DISPIMG ID: $id" -ForegroundColor Red
                    }
                }
            } else {
                Write-Host "No DISPIMG functions found in the workbook." -ForegroundColor Yellow
            }
        }
    }
    catch {
        Write-Host "mistake: $($_.)" -ForegroundColor Red
    }
    finally {
        # Clean up        if ($workbook) {
            $($false)
        }
        if ($excel) {
            $()
            []::ReleaseComObject($excel) | Out-Null
        }
        if (Test-Path $tempPath) {
            Remove-Item $tempPath -Recurse -Force
        }
        []::Collect()
        []::WaitForPendingFinalizers()
    }
}

A possible usage is as follows

Get-ExcelDispImages -ExcelPath "C:\Users\demo\Documents\dispimg_wps.xlsx" -OutputFolder $pwd\output

The generated image is in the output folder in the current directory.

The above is a detailed explanation of how to use PowerShell to extract pictures embedded in the wps table. For more information about the pictures in the PowerShell extraction form, please pay attention to my other related articles!