209人参与 • 2025-02-13 • Powershell
针对excel下打开表格图片显示 #name?编辑栏显示为 =@_xlfn.dispimg( 样公式的问题,一般需要在 wps 程序下,ctrl+f 查找范围选值,输入 =dispimg 全选,然后再右键转换为浮动图片。如果是excel中,则是查找公式 dispimg。
查阅网上得资料得知,可以通过解压表格文件,然后 根据公式中的第一参数(通常以 id 开头)看 xl_rels\cellimages.xml.rels 目录下的 name (其值为 dispimg 函数的第一参数)和 r:embed (其值以 rid 开头)的对应关系,然后再看 id ( rid 开头 ) 和 target(图片路径) 的对应关系,进而得到图片的路径。
在 llm 的帮助下进而有以下 ps 脚本。
function get-exceldispimages {
param (
[parameter(mandatory=$true)]
[string]$excelpath,
[parameter(mandatory=$false)]
[string]$outputfolder = ".\excelimages"
)
# 辅助函数:安全地读取文件内容
function read-filecontent {
param (
[string]$path
)
try {
# 使用.net方法直接读取文件,避免powershell路径解析问题
if ([system.io.file]::exists($path)) {
return [system.io.file]::readalltext($path)
}
write-host "file not found: $path" -foregroundcolor yellow
return $null
}
catch {
write-host "error reading file $path : $_" -foregroundcolor yellow
return $null
}
}
try {
# 验证excel文件是否存在
if (-not (test-path -literalpath $excelpath)) {
throw "excel file not found: $excelpath"
}
# 确保excelpath是绝对路径
$excelpath = (get-item $excelpath).fullname
# 创建输出文件夹(使用绝对路径)
$outputfolder = [system.io.path]::getfullpath($outputfolder)
if (-not (test-path -path $outputfolder)) {
new-item -itemtype directory -path $outputfolder -force | out-null
}
# 创建excel com对象
$excel = new-object -comobject excel.application
$excel.visible = $false
$excel.displayalerts = $false
$workbook = $excel.workbooks.open($excelpath)
# 用于存储找到的dispimg id和信息
$dispimgids = @()
$imagemapping = @{}
# 遍历所有工作表
foreach ($worksheet in $workbook.worksheets) {
$usedrange = $worksheet.usedrange
$rowcount = $usedrange.rows.count
$colcount = $usedrange.columns.count
for ($row = 1; $row -le $rowcount; $row++) {
for ($col = 1; $col -le $colcount; $col++) {
$cell = $usedrange.cells($row, $col)
$formula = $cell.formula
# 检查是否包含dispimg函数并提取所有参数
if ($formula -match 'dispimg\("([^"]+)"') {
$imageid = $matches[1]
write-host "found dispimg: $formula" -foregroundcolor gray
# 创建参数列表
$params = @{
'id' = $imageid
'cell' = $cell.address()
'formula' = $formula
'worksheet' = $worksheet.name
}
# 提取所有参数,包括图片id
$paramvalues = @()
$formula -match 'dispimg\((.*?)\)' | out-null
$paramstring = $matches[1]
$paramvalues = $paramstring -split ',' | foreach-object {
$_ -replace '"', '' -replace '^\s+|\s+$', ''
}
# 存储所有参数
for ($i = 0; $i -lt $paramvalues.count; $i++) {
$params["param$i"] = $paramvalues[$i]
}
$imagemapping[$imageid] = $params
$dispimgids += $imageid
}
}
}
}
# 创建临时目录
$temppath = join-path ([system.io.path]::gettemppath()) "exceltemp"
if (test-path $temppath) {
remove-item $temppath -recurse -force
}
new-item -itemtype directory -path $temppath -force | out-null
# 复制excel文件到临时目录并解压
$tempexcel = join-path $temppath "temp.xlsx"
$tempzip = join-path $temppath "temp.zip"
copy-item -path $excelpath -destination $tempexcel -force
if (test-path $tempzip) { remove-item $tempzip -force }
rename-item -path $tempexcel -newname "temp.zip" -force
expand-archive -path $tempzip -destinationpath $temppath -force
# 检查media文件夹并处理图片
$mediapath = join-path $temppath "xl\media"
if (test-path $mediapath) {
# 显示dispimg参数和图片对应关系
write-host "`nfound $($imagemapping.count) dispimg functions" -foregroundcolor cyan
if ($imagemapping.count -gt 0) {
write-host "`n=== dispimg functions found ===" -foregroundcolor cyan
write-host "found $($imagemapping.count) dispimg functions" -foregroundcolor cyan
# 显示所有找到的dispimg函数
write-host "`n=== dispimg functions details ===" -foregroundcolor yellow
foreach ($id in $imagemapping.keys) {
$params = $imagemapping[$id]
write-host "cell: [$($params.worksheet)]$($params.cell)" -foregroundcolor gray
write-host "formula: $($params.formula)" -foregroundcolor gray
}
# 首先从cellimages.xml获取dispimg id到rid的映射
$dispimgtorid = @{}
$cellimagespath = join-path $temppath "xl\cellimages.xml"
write-host "`n=== reading cellimages.xml ===" -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
# 使用正则表达式提取所有cellimage元素
$matches = [regex]::matches($xmlcontent, '<etc:cellimage>.*?</etc:cellimage>', [system.text.regularexpressions.regexoptions]::singleline)
write-host "`nfound $($matches.count) cellimage elements" -foregroundcolor gray
foreach ($match in $matches) {
$cellimagexml = $match.value
write-host "`nprocessing cellimage element:" -foregroundcolor gray
# 提取name属性(包含dispimg id)
if ($cellimagexml -match 'name="([^"]+)"') {
$dispimgid = $matches[1]
write-host "found dispimg id: $dispimgid" -foregroundcolor gray
# 提取r:embed属性(包含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 cellimages.xml: $($_.exception.message)" -foregroundcolor red
write-host $_.exception.stacktrace -foregroundcolor red
}
}
else {
write-host "cellimages.xml not found!" -foregroundcolor red
}
# 从cellimages.xml.rels获取rid到实际图片的映射
$ridtoimage = @{}
$cellimagesrelspath = join-path $temppath "xl\_rels\cellimages.xml.rels"
write-host "`n=== reading cellimages.xml.rels ===" -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 $relsxml.outerxml
$relsxml.relationships.relationship | foreach-object {
if ($_.target -match "media/") {
$ridtoimage[$_.id] = $_.target
write-host " rid $($_.id) -> $($_.target)" -foregroundcolor green
}
}
}
catch {
write-host "error reading cellimages.xml.rels: $($_.exception.message)" -foregroundcolor red
write-host $_.exception.stacktrace -foregroundcolor red
}
}
else {
write-host "cellimages.xml.rels not found!" -foregroundcolor red
}
write-host "`n=== summary of mappings ===" -foregroundcolor yellow
write-host "dispimg id -> rid mappings:" -foregroundcolor gray
$dispimgtorid.getenumerator() | foreach-object {
write-host " $($_.key) -> $($_.value)" -foregroundcolor gray
}
write-host "`nrid -> image mappings:" -foregroundcolor gray
$ridtoimage.getenumerator() | foreach-object {
write-host " $($_.key) -> $($_.value)" -foregroundcolor gray
}
# 处理每个dispimg函数
write-host "`n=== processing dispimg functions ===" -foregroundcolor yellow
foreach ($id in $imagemapping.keys) {
$params = $imagemapping[$id]
write-host "`nprocessing: [$($params.worksheet)]$($params.cell)" -foregroundcolor green
write-host "formula: $($params.formula)" -foregroundcolor gray
write-host "dispimg id: $id" -foregroundcolor gray
# 从dispimg id查找对应的rid
$rid = $dispimgtorid[$id]
if ($rid) {
write-host "found rid: $rid" -foregroundcolor green
# 从rid查找对应的图片路径
$imagepath = $ridtoimage[$rid]
if ($imagepath) {
write-host "found image path: $imagepath" -foregroundcolor green
$imagename = split-path $imagepath -leaf
# 查找对应的图片文件
$mediafile = get-childitem -literalpath $mediapath | where-object { $_.name -eq $imagename }
if ($mediafile) {
$outputpath = join-path $outputfolder "$id$($mediafile.extension)"
copy-item -literalpath $mediafile.fullname -destination $outputpath -force
write-host "successfully copied: $imagename -> $outputpath" -foregroundcolor cyan
# 以 media 文件夹下的文件名复制
# copy-item $mediafile.fullname $(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 "错误: $($_.exception.message)" -foregroundcolor red
}
finally {
# 清理
if ($workbook) {
$workbook.close($false)
}
if ($excel) {
$excel.quit()
[system.runtime.interopservices.marshal]::releasecomobject($excel) | out-null
}
if (test-path $temppath) {
remove-item $temppath -recurse -force
}
[system.gc]::collect()
[system.gc]::waitforpendingfinalizers()
}
}
一个可能的用法如下
get-exceldispimages -excelpath "c:\users\demo\documents\dispimg_wps.xlsx" -outputfolder $pwd\output
生成的图片在当前目录下的 output 文件夹下。
以上就是详解如何利用powershell提取wps表格中嵌入的图片的详细内容,更多关于powershell提取表格中图片的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论