使用C#创建WPS EXCEL单元格内联图片的一些个人纪录

发布时间 2023-04-09 17:13:08作者: 斯汪

在WPS中单元格内插入图片会生成一个公式,该公式MS Excel中没有,通过录制宏的方式也无法得知具体的生成API,只会录制出硬编码的设置单元格的公式的代码

例如

 

 通过解压缩单元格内嵌图片保存的xlsx文件,可以大概得知如下关系(重新压缩回去并且将扩展名改回xlsx是行不通的,我试了(╯‵□′)╯︵┻━┻)

图片保存在"/xl/media/"下面

"/xl/_rels/cellimages.xml.rels" 文件里面保存着图片路径与对应映射的"短ID"(我自己起的名字.(*^_^*))

"/xl/cellimages.xml" 文件里面保存着"短ID"与"长ID"的映射关系,"长ID"就是单元格公式内的字符串像这样"ID_8E1D29414F5E421B8B73BDF52F471863"

"/xl/_rels/workbook.xml.rels" 文件里面保存有一条"/xl/cellimages.xml"文件的记录,假如没有这一条WPS貌似认为不存在"/xl/cellimages.xml"文件导致公式计算为错误值

添加完这些地方就可以在单元格中使用公式引用"长ID"内联图片了 例如 "=DISPIMG("ID_472f7988ddc44502965c36a386f5202f",1)"

 

 

 

 

 

 

 

 

 

 

 

 因为无法通过简单的解压缩-修改-压缩的方式自己重新编辑xlsx文件,所以需要借助一些库

例如可以借助"System.IO.Packaging"库来获取xlsx文件中的内容,这个库在dotnet 7中属于扩展库,需要通过NUGET安装

下面的代码会打印XLSX文件中所有的PART名字(或者路径)与类型

根据我个人理解xlsx中的xml,jpeg,rels文件都被视为PART,只不过类型不一样,可以创建,更改,删除PART,然后存储更改

但是我发现_rels路径下面的资源文件会与对应名称的xml文件关联,手动删除对应的xml文件貌似会导致资源文件也被删除,因为不了解打包的这个特性导致我浪费了好长的时间

var pack = System.IO.Packaging.Package.Open("test.xlsx");
        
        foreach (var item in pack.GetParts())
        {
            Console.WriteLine($"{item.Uri} {item.ContentType}");
        }

 

使用C#的XmlDocument类编辑xml,假如需要创建带有命名空间前缀的元素,那么需要调用对应的重载,否则前缀会被去掉,但是,仅仅调用重载的话,会遇到这么一个问题,就是每一个子元素可能都会把命名空间在元素的特性里写一遍,解决办法是手动把所有的命名空间添加到父元素身上,这样类就会自动识别父元素已存在命名空间声明,而不会在每一个子元素上重复声明

假如需要添加带有命名空间前缀的元素特性则需要这样,例如如下

XmlDocument doc = new XmlDocument();
XmlElement element = doc.CreateElement("example");
XmlAttribute attr = doc.CreateAttribute("prefix", "localName", "namespaceURI");
attr.Value = "value";
element.Attributes.Append(attr);
doc.AppendChild(element);