Excel VBA中使用相对路径而不是绝对路径

51

我编写了一个Excel VBA宏,可以从本地存储的HTML文件导入数据,然后对这些数据进行计算。

目前,这个HTML文件是通过绝对路径引用的:

Workbooks.Open FileName:="C:\Documents and Settings\Senior Caterer\My Documents\Endurance Calculation\TRICATEndurance Summary.html"

然而,我希望使用相对路径来引用它,而不是绝对路径(因为我想将电子表格分发给可能没有使用相同文件夹结构的同事)。由于html文件和Excel电子表格位于同一文件夹中,我认为这不应该很难,但我完全无法做到。我在网上搜索过,并且所提供的解决方案似乎都非常复杂。

我在工作中使用的是Excel 2000和2002,但是因为我计划进行分发,所以希望它能与尽可能多的Excel版本兼容。

非常感谢您的任何建议。

8个回答

80

仅为澄清yalestar所说的,这将给您相对路径:

Workbooks.Open FileName:= ThisWorkbook.Path & "\TRICATEndurance Summary.html"

我在 Mac 上使用 Excel 时遇到了类似的问题。后来发现,在 Mac 上,路径需要使用“:”而不是“\”指定。 - remudada
4
对于Windows用户,另一个有用的技巧是可以通过添加..\来指定更高级别的路径。例如:如果您想要访问名为MyFile.txt的文件夹,它位于Endurance Calculation文件夹中,则可以使用以下命令: Workbooks.Open FileName:= ThisWorkbook.Path & "..\ MyFile.txt"。请注意,这将返回到上一级文件夹并打开该文件。 - KayakinKoder

21

您可以使用以下任何一个作为相对路径的根目录:

ActiveWorkbook.Path
ThisWorkbook.Path
App.Path

2
如果当前操作系统目录是您正在使用的工作簿的路径,则Workbooks.Open FileName:= "TRICATEndurance Summary.html"就足够了。如果您要使用路径进行计算,可以将当前目录表示为 . ,然后\告诉文件在该目录中,在必须将操作系统的当前目录更改为工作簿的路径时,您可以使用ChDriveChDir来完成。"最初的回答"
ChDrive ThisWorkbook.Path
ChDir ThisWorkbook.Path
Workbooks.Open FileName:= ".\TRICATEndurance Summary.html"

2
嗨!虽然这可能为OP的问题提供了解决方案,但在StackOverflow上不鼓励仅代码回答。重要的是让OP理解为什么这是一个解决方案,因为这将有助于他们更长远地解决问题,并对该网站的未来访问者更有益。谢谢! - d_kennetz
@robotik 你能测试一下这段代码吗?我刚试了一下,但是它对我不起作用。我收到了一个1004运行时错误:“应用程序定义或对象定义的错误”。 - d4rk_1nf1n1ty
@d4rk_1nf1n1ty,这可能是文件路径的问题或者是表格/范围的问题。1004是一个非常通用的错误。它是否发生在“Workbooks.Open”? - robotik
@robotik 是的,那就是那一行。(是啊,那个错误非常通用,真让人烦恼。)我创建了一个名为“test2.xlsx”的工作簿,以及一个名为“test folder”的文件夹,其中包含一个名为“test_code.xlsm”的工作簿。我的代码与您上面的代码相同(在名为test的子程序中),只是我将FileName更改为“.\test2.xlsx”。 - d4rk_1nf1n1ty
@d4rk_1nf1n1ty,我刚试了一下你给的完整文件名,它表现得非常好。我把文件夹深深地放在谷歌文件流中,并尝试打开或关闭文件,但无法重现此问题。只有当我更改文件名时才会出现1004错误,因为文件找不到。这可能也是访问权限、写保护、其他应用程序使用文件或其他事情的问题。 - robotik

2
我认为问题在于,如果您的“当前目录”设置不正确,则不带路径打开文件将无法正常工作。
请在即时窗口中输入“Debug.Print CurDir”,这应该显示您在“工具…选项”中设置的默认文件位置。
我不确定我是否完全满意它,可能是因为它是VB命令的一种遗留方式,但您可以这样做:
ChDir ThisWorkbook.Path

我认为最好使用ThisWorkbook.Path来构建HTML文件的路径。我非常喜欢Scripting Runtime中的FileSystemObject(似乎总是已安装),因此在设置对Microsoft Scripting Runtime的引用后,我更愿意这样做:

Const HTML_FILE_NAME As String = "my_input.html"

With New FileSystemObject
    With .OpenTextFile(.BuildPath(ThisWorkbook.Path, HTML_FILE_NAME), ForReading)
        ' Now we have a TextStream object that we can use to read the file
    End With
End With

我不太确定脚本运行时是否“始终安装”。在工作中,我们产品的数据库更新依赖于其已安装(我们使用它来打开SQL脚本文件),但我们很快发现(以困难的方式)scrrun.dll在某些情况下要么不存在,要么未注册。 - Mike Spross
如果你在处理Office相关的内容,那么是需要的,只有MSDE/SQL Express安装基础,可能不需要。就像你所说的,它可能不会被Windows默认注册。然而,Office使用它。 - Anonymous Type
所有版本的IE都有它,至少比IE6要新。我记得.NET Framework 4+也有它(可能我记错了!)。现在Windows不一定会预装IE(感谢欧盟 :)),而.NET 4仍然是相对较新的,因此客户端可能确实没有它。 - Cor_Blimey

1
你可以通过提供浏览器按钮为用户提供更多的灵活性。
Private Sub btn_browser_file_Click()
Dim xRow As Long
Dim sh1 As Worksheet
Dim xl_app As Excel.Application
Dim xl_wk As Excel.Workbook
Dim WS As Workbook
Dim xDirect$, xFname$, InitialFoldr$
InitialFoldr$ = "C:\"
With Application.FileDialog(msoFileDialogFolderPicker)
    .InitialFileName = Application.DefaultFilePath & "\"
    .Title = "Please select a folder to list Files from"
    .InitialFileName = InitialFoldr$
    .Show
    Range("H13").Activate
    If .SelectedItems.Count <> 0 Then
        xDirect$ = .SelectedItems(1) & "\"
         Range("h12").Value = xDirect$
        xFname$ = Dir(xDirect$, 7)
        Do While xFname$ <> ""
         If (Format(FileDateTime(xDirect$ & "\" & xFname$), "MM/DD/YYYY") > Format(Range("H10").Value, "MM/DD/YYYY")) Then
            ActiveCell.Offset(xRow) = xFname$
            xRow = xRow + 1
            xFname$ = Dir
            Else
            xFname$ = Dir
            xRow = xRow
        End If
        Loop
    End If
End With

使用这段代码,您可以轻松地实现这一点。 测试过的代码

0
这是我快速简单的函数,用于从相对路径获取绝对路径。
与被接受的答案不同的是,此函数可以处理向上移动到父文件夹的相对路径。
例如:
Workbooks.Open FileName:=GetAbsolutePath("..\..\TRICATEndurance Summary.html")

代码:

' Gets an absolute path from a relative path in the active workbook
Public Function GetAbsolutePath(relativePath As String) As String
    
    Dim absPath As String
    Dim pos As Integer
    
    absPath = ActiveWorkbook.Path
    
    ' Make sure paths are in correct format
    relativePath = Replace(relativePath, "/", "\")
    absPath = Replace(absPath, "/", "\")
    
    Do While Left$(relativePath, 3) = "..\"
    
        ' Remove level from relative path
        relativePath = Mid$(relativePath, 4)
        
        ' Remove level from absolute path
        pos = InStrRev(absPath, "\")
        absPath = Left$(absPath, pos - 1)
    
    Loop
    
    GetAbsolutePath = PathCombine(absPath, relativePath)
    
End Function

-2

我认为这可能会有所帮助。以下宏检查文件夹是否存在,如果不存在,则创建该文件夹并将其保存为xls和pdf格式,保存在该文件夹中。恰好该文件夹与相关人员共享,因此每个人都可以得到更新。

Sub PDF_laudo_e_Prod_SP_Sem_Ajuste_Preco()
'
' PDF_laudo_e_Prod_SP_Sem_Ajuste_Preco Macro
'

'


Dim MyFolder As String
Dim LaudoName As String
Dim NF1Name As String
Dim OrigFolder As String

MyFolder = ThisWorkbook.path & "\" & Sheets("Laudo").Range("C9")
LaudoName = Sheets("Laudo").Range("K27")
NF1Name = Sheets("PROD SP sem ajuste").Range("Q3")
OrigFolder = ThisWorkbook.path

Sheets("Laudo").Select
Columns("D:P").Select
Selection.EntireColumn.Hidden = True

If Dir(MyFolder, vbDirectory) <> "" Then
Sheets("Laudo").ExportAsFixedFormat Type:=xlTypePDF, filename:=MyFolder & "\" & LaudoName & ".pdf", Quality:=xlQualityMinimum, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:= _
False

Sheets("PROD SP sem ajuste").ExportAsFixedFormat Type:=xlTypePDF, filename:=MyFolder & "\" & NF1Name & ".pdf", Quality:=xlQualityMinimum, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:= _
False

ThisWorkbook.SaveAs filename:=MyFolder & "\" & LaudoName

Application.DisplayAlerts = False

ThisWorkbook.SaveAs filename:=OrigFolder & "\" & "Entregas e Instrucao Barter 2015 - beta"

Application.DisplayAlerts = True

Else
MkDir MyFolder
Sheets("Laudo").ExportAsFixedFormat Type:=xlTypePDF, filename:=MyFolder & "\" & LaudoName & ".pdf", Quality:=xlQualityMinimum, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:= _
False

Sheets("PROD SP sem ajuste").ExportAsFixedFormat Type:=xlTypePDF, filename:=MyFolder & "\" & NF1Name & ".pdf", Quality:=xlQualityMinimum, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:= _
False

ThisWorkbook.SaveAs filename:=MyFolder & "\" & LaudoName

Application.DisplayAlerts = False

ThisWorkbook.SaveAs filename:=OrigFolder & "\" & "Entregas e Instrucao Barter 2015 - beta"

Application.DisplayAlerts = True

End If

Sheets("Laudo").Select
Columns("C:Q").Select
Selection.EntireColumn.Hidden = False
Range("A1").Select

End Sub

-2

这也许不是最好的方法。但我找到的唯一获取绝对路径的方法是计算字符串中语法“..”出现的次数,然后使用函数gotoparent多次,直到该语法在超链接地址中出现相应的次数。(在我的情况下,我的字段是一个超链接地址。 附注:此代码需要引用Microsoft Scripting Runtime。

Function AbsolutePath(strRelativePath As String, strCurrentFileName As String) As String
Dim fso As Object
Dim strCurrentProjectpath As String
Dim strGoToParentFolder As String
Dim strOrigineFolder As String
Dim strPath As String
Dim lngParentFolder As Long


''Pour retrouver le répertoire parent
Set fso = CreateObject("Scripting.FileSystemObject")

'' détermine le répertire du projet actif
strCurrentProjectpath = CurrentProject.Path

'' détermine le nom du répertoire dans lequel le fichier d'origine se trouve
strOrigineFolder = Replace(Replace(Replace(strRelativePath, strCurrentFileName, ""), "..", ""), "\", "")

''Extraction du chemin relatif (ex. ..\..\..)
strGoToParentFolder = Replace(Replace(strRelativePath, strOrigineFolder, ""), strCurrentFileName, "")

''retourne le nombre de fois qu'il faut remonter au répertoire parent
lngParentsFolder = Len(Replace(strGoToParentFolder, "\", "")) / 2

''détermine la valeur d'origine du répertoire du début
strPath = strCurrentProjectpath

Vérifie s 'il faut aller au répertoire parent
If lngParentsFolder < 1 Then
    'si non, alors répertoire parent et répertoire d'origine du fichier
    strPath = strCurrentProjectpath & "\" & strOrigineFolder
Else
    ''si oui, nous faisons la boucle pour retourner au répertoire d'origine
    For i = 1 To lngParentsFolder
        strPath = fso.GetParentFolderName(strPath)
    Next i
End If

''retournons le répertoire parent du fichier et son répertoire d'origine [le OUTPUT]
AbsolutePath = strPath & strOrigineFolder & "\"

End Function

1
感谢您回答第一个问题。文件系统对象包含 .GetAbsolutePathName() 方法,您可以使用它来获取绝对路径。然而,用户询问如何从绝对路径获取相对路径。 - cadvena

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接