如何在VBA中使用唯一标识符引用Excel链接

如何使用唯一标识符在VBA中引用外部工作簿,该文件在打开文件时不会更改? 当包含完整的文件path并且没有打开同名文件时,它工作正常。 但是,打开文件时,文件path的完整格式不起作用,仅文件名不起作用。

我想创build一个更新Sub来更新所有的引用,如果电子表格是打开的(参考下面的第二点),这会自行消失。

这些是我觉得应该有可能的一些原因:

  1. 似乎在手动链接更新菜单中只有文件名参考;
  2. 也不能打开两个具有相同名称的工作簿,因此,如果您打开源链接,则单元格引用会从文件path更改为文件名(这是导致问题的原因。

这是我目前拥有的代码updCellRef是一个单元格引用的文件path(我只想使用文件名):

  Sub updateValues(updCellRef) updFilePath = ActiveWorkbook.Sheets("INPUTS").Range(updCellRef).Value ActiveWorkbook.updateLink Name:=updFilePath, Type:=xlExcelLinks End Sub 

为了澄清这个问题,当我使用上面的函数来更新值时出现,但是当源电子表格被打开的时候,它被它的文件名引用。 当它closures时,它被完整的文件path引用。

我在VBA v7.0中使用Excel Professional 2010 v14

注意:我不想使用包括Power Query在内的任何其他软件,因为它不能在没有pipe理员权限的情况下安装。

有两种方法可以将信息添加到文件名中,以使其唯一性是在Excel中打开文件,其中可以看到没有打开的文件共享相同的名称,或者包含整个path。 所以你不能“只使用文件名引用VBA中的外部工作簿”,除非它们是开放的,因为所有共享相同名称的文件都不确定。

这里是MS Office支持的来源说: “当源未打开,外部引用包括整个path”

更新:给原来的问题的意见,我想我们在这里:

  1. 我们很高兴打开的文件和任何链接到他们应该已经更新,因为他们是开放的
  2. 我们有一个我们喜欢强制更新的文件列表,如果我们可以find他们通过给定的path,如果没有另一个文件具有相同的文件名打开

现在试试这个:

  Sub updateValues(updFilepath As String) If Not FileInUse(updFilepath) Then ActiveWorkbook.UpdateLink Name:=updFilepath, Type:=xlExcelLinks 'else workbook is open and Excel have automatically updated linke End If End Sub Public Function FileInUse(sFileName As String) As Boolean On Error Resume Next Open sFileName For Binary Access Read Lock Read As #1 Close #1 FileInUse = IIf(Err.Number > 0, True, False) On Error GoTo 0 End Function 

文件testingfunction是由用户2267971回答这个问题也是如何testing一个文件是否打开

这是引用链接的另一种方式。

 Dim linkName As String, fileName As String, i As Integer For Each link In ActiveWorkbook.LinkSources On Error GoTo tryName ActiveWorkbook.UpdateLink linkName If False Then tryName: i = InStrRev(linkName, "\") ' 0 if no "\" found If i > 0 Then On Error Resume Next ' to ignore error if fileName does not work too fileName = Mid(linkName, i + 1) ActiveWorkbook.UpdateLink fileName End If End If On Error GoTo 0 ' reset the error handling Next 

但是,如前所述的link是一个文件path的string

更新

你可以张贴数据>编辑链接的截图,使其更清楚一点?

在我的testing中,前3个链接都很好,但最后一个有问题。

你可以尝试下面的东西

  1. testing链接是否来自打开的工作簿
  2. 如果它使用,然后使用ChangeLink来欺骗Excel进行更新
  3. 如果没有,运行现有的在封闭的书上工作的代码。

  Sub updateValues() Dim updFilePath As String Dim Wb As Workbook Dim bFound As Boolean updFilePath = ActiveWorkbook.Sheets("INPUTS").Range(updCellRef).Value For Each Wb In Application.Workbooks If Wb.FullName = updFilePath Then ActiveWorkbook.ChangeLink Wb.Name, Wb.Name bfound = True Exit For End If Next If Not bfound Then ActiveWorkbook.UpdateLink Name:=updFilePath, Type:=xlExcelLinks End Sub 

我可以想想你可能在这里有两个场景:

1.通过标题,我可以猜到问题依赖于这样一个事实,即您尝试引用的工作簿位于父工作簿的子文件夹中; 如果是这样的话,我注意到即使当你给出完整的path,它的工作一段时间,然后它错过了它的path – 这似乎是一个错误(我不知道是什么触发它)。 链接只适用于excel界面,但是当你试图使用vba中的超链接时,它会给出错误,因为完整的path已经被切断,这导致了一个不完整的path – validation它,它说不再有效 – 。 我没有其他的解决scheme,当发生这种情况时,再次询问用户的path(使用主单元的所有进程,依靠这个,使其更容易修复/解决方法)。 这可以解决它,以便通过VBA检索它。 请求时,确保单元格的值具有工作簿的全名,

  Sub Test() Dim HLToTest As String HLToTest = RetriveWBLink(Range("B2").Value) End Sub Function RetriveWBLink(WBName As String) As String Dim FileSystemLibrary As Object: Set FileSystemLibrary = CreateObject("Scripting.FileSystemObject") On Error GoTo Err01RetriveWBLink RetriveWBLink = FileSystemLibrary.GetFile(ThisWorkbook.Path & "\" & WBName) If 1 = 2 Then '99. If error Err01RetriveWBLink: 'this may happen for new workbooks that aren't saved yet RetriveWBLink = "False" End If '99. If error On Error GoTo -1 Set FileSystemLibrary = Nothing End Function 

2.如果(1)不是这种情况,这应该通过检索给定WB的完整path来解决它(这只是要更新链接,无论它是否已经打开都没关系)

 Sub Test() Dim HLToTest As String HLToTest = RetriveWBLink(ThisWorkbook) End Sub Function RetriveWBLink(WBName As Workbook) As String Dim FileSystemLibrary As New Scripting.FileSystemObject On Error GoTo Err01RetriveWBLink RetriveWBLink = FileSystemLibrary.GetFile(WBName.Path & "\" & WBName.Name) If 1 = 2 Then '99. If error Err01RetriveWBLink: 'this may happen for new workbooks that aren't saved yet RetriveWBLink = "False" End If '99. If error On Error GoTo -1 Set FileSystemLibrary = Nothing End Function 

我并不是说这是唯一的方法,但是我能想到的最简单的方法是使用这样的方式实际打开工作簿:

 Dim wb as Workbook Set wb = Excel.Workbooks.Open(Filename) updFilePath = wb.Sheets("INPUTS").Range(updCellRef).Value wb.Close 

我了解你的观点,如果电子表格与你打开的电子表格名称相同,就会呕吐。 也许一个简单的黑客就是捕获活动工作簿的文件名,将其保存为临时文件,然后保存在最后。 我确实说这是一个黑客。

我知道你可以使用ADO通过C#或MS Access访问Spreadsheet数据,就像数据库一样,所以我猜测也可以直接从Excel中做到这一点。 也就是说,这似乎不像上面的build议那么简单。 我认为ADO也必须阅读整个电子表格,甚至处理一个单元格,所以我不认为这样可以节省任何东西。