文档中链接对象的文件path的VBA列表

我有许多大型Microsoft Word文档,其中包含许多Microsoft Excel电子表格中的许多链接文件。 打开Word文档时,即使选中了“打开更新链接文件”选项:

在这里输入图像说明

Word通过打开和closures每个单独链接的相关Excel电子表格来检查每个链接的来源(即使从同一电子表格中,Word将打开并closures电子表格x次)。 这意味着打开文档需要很长时间

我发现如果包含链接对象源的电子表格已经打开,文档打开速度更快,所以Word不会打开,closures,重新打开它们。

到目前为止,我有一个解决scheme的开始是创build链接对象的所有文件path的列表,由以下VBA代码完成:

Sub TypeArray() Dim List(), Path As String Dim i, x As Integer Dim s As InlineShape Dim fso As FileSystemObject, ts As TextStream Set fso = New FileSystemObject Set ts = fso.OpenTextFile("C:\MyFolder\List.txt", 8, True) With ts .WriteLine (ActiveDocument.InlineShapes.Count) End With For Each s In ActiveDocument.InlineShapes Path = s.LinkFormat.SourcePath & "\" _ & s.LinkFormat.SourceName With ts .WriteLine (Path) End With Next s End Sub '-------------------------------------------------------------------------------------- Private Sub WriteStringToFile(pFileName As String, pString As String) Dim intFileNum As Integer intFileNum = FreeFile Open pFileName For Append As intFileNum Print #intFileNum, pString Close intFileNum End Sub '-------------------------------------------------------------------------------------- Private Sub SendFileToNotePad(pFileName As String) Dim lngReturn As Long lngReturn = Shell("NOTEPAD.EXE " & pFileName, vbNormalFocus) End Sub 

这样做效果不错,但是只能文档已经打开之后才能使用,这样就失去了它的目的。

所以,最后,我的问题是:

1) 打开一个Word文档之前 ,是否有办法运行这个代码(或者更好,更高效的代码 – 欢迎提出build议), 然后等待从源头检查每个链接的漫长过程?

2)有没有办法避免这一切,只是Word 检查链接,当我打开一个文件?

对不起,很长的问题,并感谢您的帮助!

如果我没有错,应该有根据msdn的Document_Open事件。 这实际上应该是一个打开文档之前,应该在更新链接之前被解雇(至less在Excel中它是在计算之前被解雇)。

尝试打开文档打开文件。 那么你将面临另一个问题,所以什么时候closures文件,但这是一个更容易的事情。 (可能document_close事件…)

EDITTED:

正如评论所言,这已经太迟了。 你可以创build一个开词(作为一个单一的应用程序或作为一个插件)。 逻辑基本上是:

 '1) on something_open run GetOpenFileName dialog '2) before opening the real thing, open all files accompanied '3) open the document itself '4) close all files '5) close the opener itself 

这不是最简单的方法,但我使用这个逻辑来检查,以确保我的应用程序总是运行在一个新的Excel副本等,但我明白,这是一个解决方法,而不是一个解决scheme。

如果你仍然在寻找这方面的东西,我用VBA和VB.NET的组合(在VS 2010中)创build了以下内容来展示使用该系统可以很容易地完成的工作。 如果VB.NET对你没有用处,对不起,但有一些原因,我不想花时间在纯粹的VBA方法。

目前,它是一个“控制台”应用程序,这意味着你可能会看到一个框在运行时闪现,也意味着你更有可能创build这个没有VS的应用程序,如果你绝对必须(AFAICR的VB.NET /编译器/实际上是免费的)。 它只是提取链接信息。 (即目前没有设施来修改链接)。

总的来说,你有一小块VBA(比如你的Normal模板),你需要一个打开的文档。 VBA启动一个Windows Shell,运行VB.NET程序并将它传递给您要打开的文档的完整path名。

VB.NET程序打开.docx(或其他),并查看所有从Main文档部分引用的“oleObject”types的关系(现在,代码将忽略页眉,页脚,脚注和其他任何地方你可能有一个链接)

VB.NET程序自动化Word(我们知道正在运行),并将每个链接URL写入活动文档中的一系列文档variables。 这些variables被称为“Link1”,“Link2”等。如果没有链接(我没有正确testing过这个path),或者程序找不到文件,那么应该把Link0设置为“0” 。 否则应该设置为链接计数。

shell同步执行,所以你的VBA完成后恢复。 那么你要么有0个链接,要么你可以处理一组链接。

VBA是这样的:

 Sub getLinkInfo() ' the full path name of the program, quoted if there are any spaces in it ' You would need to modify this Const theProgram As String = """C:\VBNET\getmaindocumentolelinks.exe""" ' You will need a VBA reference to the "Windows Script Host Object Model" Dim oShell As WshShell Set oShell = CreateObject("WScript.Shell") ' plug your document name in here (again, notice the double quotes) If oShell.Run(theProgram & " ""c:\a\testdocexplorer.docx""", , True) = 0 Then With ActiveDocument.Variables For i = 1 To CInt(.Item("Link0").Value) Debug.Print .Item("Link" & CStr(i)) Next End With Else MsgBox "Attempt to retrieve links failed" End If End Sub 

对于VB.NET,您需要Office Open XML SDK(我认为它是2.5版本)。 你需要引用这个和Microsoft.Office.Interop.Word。

代码如下:

 Imports System.Collections.Generic Imports System.Linq Imports System.Text Imports System.IO Imports System.Xml Imports System.Xml.Linq Imports DocumentFormat.OpenXml.Packaging Imports Word = Microsoft.Office.Interop.Word Module Module1 Const OLEOBJECT As String = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject" Sub Main() Dim s() As String = System.Environment.GetCommandLineArgs() If UBound(s) > 0 Then Dim wordApp As Word.Application Try wordApp = GetObject(, "Word.Application") Dim targetDoc As Word.Document = wordApp.ActiveDocument Try Dim OOXMLDoc As WordprocessingDocument = WordprocessingDocument.Open(path:=s(1), isEditable:=False) Dim linkUris As IEnumerable(Of System.Uri) = From rel In OOXMLDoc.MainDocumentPart.ExternalRelationships _ Where rel.RelationshipType = OLEOBJECT _ Select rel.Uri For link As Integer = 0 To linkUris.Count - 1 targetDoc.Variables("Link" & CStr(link + 1)).Value = linkUris(link).ToString Next targetDoc.Variables("Link0").Value = CStr(linkUris.Count) OOXMLDoc.Close() Catch ex As Exception targetDoc.Variables("Link0").Value = "0" End Try Finally wordApp = Nothing End Try End If End Sub End Module 

我最初编写的.NET代码是一个COM对象,从VBA中使用起来会稍微简单一些,但是在.NET上设置起来要困难得多,而且(坦率地说)更难于修改和debugging,因为你经常closuresWord释放对COM DLL的引用。

如果你真的想修复LINKpath,据我所知,在关系logging中修改它们足以让Word在打开Word时更新相关的LINK字段,从而无需修改XML代码LINK领域以及。 但是这是另一个故事

我刚刚发现,您可以设置/修改DelayOleSrvParseDisplayNameregistry项和NoActivateOleLinkObjAtOpenregistry项来修改全局行为:

请参阅http://support.microsoft.com/kb/970154

我还发现activedocument.fields可以包含到外部对象的链接(在我的情况下,一个Excel工作表)。

使用此代码来parsing它们:

 for each f in activedocument.fields debug.print f.code next 

并使用activedocument.fields(FIELDNUMBER)来select每个对象,找出它在文档中的位置。

也许activedocument.Variablesactivedocument.Hyperlinks可以包含外部对象的链接? (不在我的情况)。