我正在尝试在 C# Word interop (NetOffice) 中复制以下方法
Selection.PasteSpecial Link:=True, DataType:=wdPasteMetafilePicture, _
Placement:=wdInLine, DisplayAsIcon:=False
Run Code Online (Sandbox Code Playgroud)
我说“复制”是因为我不想实际使用该PasteSpecial方法,因为我需要更新许多field类型link一次性,并且不喜欢依靠复制和粘贴来与excel进行通信。
我已经有以下代码,它主要完成我想要的但有一些我无法克服的问题。
Selection.InlineShapes.AddOLEObject ("Excel.Sheet.12", fileName + $"!{label}", true)
Run Code Online (Sandbox Code Playgroud)
此方法失败并显示错误消息
Word 无法创建指向您指定的对象的链接。请将对象直接插入到您的文件中,而无需创建链接
当且仅当我使用带有标签的网络驱动器或 unc 路径时,我才会收到此错误消息。例如。
T:\TestFile.xlsx!Sheet1!TestRange
T:\TestFile.xlsx!Sheet1!R1C1:R2C2
//notice that T is a network drive and not a local drive
\\TestShare\TestFile.xlsx!Sheet1!TestRange
\\TestShare\TestFile.xlsx!Sheet1!R1C1:R2C2
Run Code Online (Sandbox Code Playgroud)
如果我不使用标签,例如。
T:\TestFile.xlsx
T:\TestFile.xlsx
//notice that T is a network drive and not a local drive
\\TestShare\TestFile.xlsx
\\TestShare\TestFile.xlsx
Run Code Online (Sandbox Code Playgroud)
或本地驱动器,例如。C:(有无标签)
C:\TestFile.xlsx
C:\TestFile.xlsx
C:\TestFile.xlsx!Sheet1!TestRange
C:\TestFile.xlsx!Sheet1!R1C1:R2C2
Run Code Online (Sandbox Code Playgroud)
一切正常。
因此,只有组合网络驱动器或 unc + a 标签会产生该错误消息。
我想,好吧没问题我已经知道如何更改生成的路径和标签,field并编写了以下代码以在第二步中包含标签。
var inlineShape = Selection.InlineShapes.AddOLEObject("Excel.Sheet.12", fileName, true);
field = inlineShape.Field;
if (!string.IsNullOrEmpty(label))
{
var fieldCode = field.Code.Text;
//replace the produced empty label "" with the label I desire eg. "Sheet1!R1C1:R2C2"
fieldCode = fieldCode.Replace(" \"\" ", $" \"{label}\"");
//write the updated fieldcode back to the field
field.Code.Text = fieldCode;
//update the field
field.Update();
}
Run Code Online (Sandbox Code Playgroud)
但是这个解决方案,将图像的底层格式从 WMF(Windows 元文件)更改为 EMF(增强型元文件),但我需要它以 WMF 格式存储,因为 Office 2010无法正确呈现 EMF。
为了获取底层文件,我将 my 重命名docx为 tozip并将其解压缩以查看word\media目录。
PasteSpecial 不会抛出该错误,并生成所需的 WMF 格式,但我似乎无法 100% 复制发生的例程 PasteSpecial.
正如我旁注的那样,我不想有png或bmp要么,因为这些是在字体周围模糊生成的,所以最好的结果wmf是Office 2010.
对于Office 2013及更高版本,我使用以下代码emf从一开始就正确处理,并且不会遇到有关网络驱动器/unc + 标签错误的问题。
var field = range.Fields.Add(range, WdEnums.WdFieldType.wdFieldLink);
field.LinkFormat.SourceFullName = fileName + $"!{label}";
Run Code Online (Sandbox Code Playgroud)
编辑:
在这里,我试图解决的主要问题的屏幕截图,因为我的提醒,这是它的外观在Office 2010中Office 2013和更高看起来都不错的:

对于两者,我都使用特殊粘贴 https://support.office.com/en-us/article/paste-special-e03db6c7-8295-4529-957d-16ac8a778719
word文档中的第一个表格产生一个EMF文件,同时使用粘贴特殊格式“图片(增强型元文件)”,宏录制产生以下代码:
Selection.PasteSpecial Link:=False, DataType:=wdPasteEnhancedMetafile, _
Placement:=wdInLine, DisplayAsIcon:=False
Run Code Online (Sandbox Code Playgroud)
word文档中的第二个表生成一个WMF文件,同时使用粘贴特殊格式“图片(Windows元文件)”,宏录制生成以下代码:
Selection.PasteSpecial Link:=True, DataType:=wdPasteMetafilePicture, _
Placement:=wdInLine, DisplayAsIcon:=False
Run Code Online (Sandbox Code Playgroud)
在右侧,您可以看到我复制粘贴到左侧word文档中的excel文件。
正如您可以清楚地看到的,Office 2010渲染/绘制 WMF 文件(word 文档中的第二个表)更好,所以这将是我想要的输出,但正如我提到的,我很难复制PasteSpecial并保持WMF更好地呈现/绘制的文件.
编辑2:
我记录了我的屏幕以显示错误,请原谅我的环境是德语。 https://imgur.com/a/50wcBGQ
我使用的代码是这样的:
Selection.PasteSpecial Link:=True, DataType:=wdPasteMetafilePicture, _
Placement:=wdInLine, DisplayAsIcon:=False
Run Code Online (Sandbox Code Playgroud)
我C5在excel文件中写了“UsedRange”,如果标签正在使用或未使用,则在word中显示不同的输出,如果我不指定标签,它使用UsedRange第一张纸的。
仅供参考,我已经编写了简单的代码vba来证明它与此无关,C#并且可以在没有任何特殊情况的情况下进行本地复制。最后,如果有解决方案,将包含在我的C#应用程序中。
编辑3:
只是为了澄清,如果有人知道一种更好地Office 2010渲染/绘制EMF文件的方法,这对于我的问题来说也是一个有效的解决方案,因为在一天结束时,我只想在我的word文档。我真的不在乎是否EMF或WMF,我只是想尝试使用WMF它,因为它看起来更好,并且有我描述的问题,告诉Office 2010继续WMF格式。
因为只有这样,我知道的,克服了错误信息,是通过操纵Field,如上图所示,但一旦我打电话field.Update()的WMF文件被替换为EMF,我结束了与难看渲染/绘制的EMF文件。
编辑4:
根据要求,我查看了文档的内部结构并查看了差异。实际差异基本上是 0,只有一些应该无关紧要的东西,比如修订号、字符数等等。
但我注意到以下内容,即使这段代码
Selection.PasteSpecial Link:=True, DataType:=wdPasteMetafilePicture, _
Placement:=wdInLine, DisplayAsIcon:=False
Run Code Online (Sandbox Code Playgroud)
生成一个WMF文件,我可以通过查看word\media文件夹并查看生产image1.wmf的文件,或者查看word\_rels\document.xml.rels具有以下条目的文件来查看该文件
<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.wmf"/>
Run Code Online (Sandbox Code Playgroud)
XMLOLE 对象的实际有以下内容word\document.xml
<o:OLEObject Type="Link" ProgID="Excel.Sheet.12" ShapeID="_x0000_i1025" DrawAspect="Content" r:id="rId8" UpdateMode="Always"><o:LinkType>EnhancedMetaFile</o:LinkType><o:LockedField>false</o:LockedField></o:OLEObject>
Run Code Online (Sandbox Code Playgroud)
如您所见,LinkType定义为EnhancedMetaFile(EMF)。
由于 OLE 对象是这样定义的,我尝试了一个简单的调用是否field.Update会触发从WMFto的更改EMF,可悲的是就是这种情况,所以即使我不修改field代码,像这样的简单调用
Selection.InlineShapes(1).Field.Update
Run Code Online (Sandbox Code Playgroud)
将已经触发从WMF到的转换,EMF因为 OLE 对象只是像这样简单地定义,转换也可以在没有任何自定义代码的情况下实现,只需选择内联形状并点击F9或右键单击并选择Update Links(从我的德国环境翻译)
请注意,无论出于何种原因,这段代码
Selection.InlineShapes.AddOLEObject("Excel.Sheet.12", "E:\rfa\TestFile.xlsx", True).Field.Update
Run Code Online (Sandbox Code Playgroud)
不会触发转换,但如果您保存word文档并再次打开它,则可以调用field.Update以触发转换。
因此,要一次性完成转换,而无需保存/关闭 Word 文档,您至少需要调用它
With Selection.InlineShapes.AddOLEObject("Excel.Sheet.12", "E:\rfa\TestFile.xlsx!Tabelle1!Z1S1:Z2S2", True).Field
.Code.Text = Replace(.Code.Text, "Z1S1:Z2S2", "Z2S2:Z3S3")
.Update
End With
Run Code Online (Sandbox Code Playgroud)