【问题标题】:Return Excel VBA Macro OneDrive Local Path - Possible Lead返回 Excel VBA 宏 OneDrive 本地路径 - 可能的线索
【发布时间】:2022-05-05 23:33:31
【问题描述】:

我有一个很多人需要访问的电子表格(在 sharepoint 上),出于某些原因,我们需要在本地执行此操作(同步)。

然而,由于每个用户的知识水平不断出现问题和错误,电子表格需要具有结构和一致性,所以为了实现这一点,我创建了一个带有一组参数的用户表单来帮助人们输入准确的数据,避免错误。

它是一个投标登记簿,用于输入客户、客户联系方式和投标信息,生成报价单号、文件夹和文件名等。

在 OneDrive/Sharepoint 路径更改之前(以前文件路径是本地的,现在是共享点 URL) 我有一个宏,当用户单击一个按钮时会运行,它将在相关的本地共享点目录中创建一个适当命名的文件夹,在该文件夹中创建一组标准文件夹(客户文档、合同、产品文件、图纸等)然后打开一个投标表格并将其保存在创建的文件夹中。文件名(报价单号)用于从投标登记簿中查找查询以返回所有客户/联系人/报价信息。

由于 sharepoint 已将其路径协议从本地更改为 URL,我无法使其工作,因此需要手动处理,从而导致错误和不一致。

我已经到处搜索了使用 VBA 在共享点上创建文件夹和文件的方法,以及与本地路径交互的方法,而不是禁用“使用 Office 应用程序同步我打开的 Office 文件”(此功能是由于文件协作而需要。) 当我找到一种将 URL 转换为本地路径的方法时,我有一个希望,但是,这不是最好的解决方案,因为每个用户都在不同级别同步文件夹(也许有人可以帮助我确定路径,一个宏,用于在 OneDrive 目录中搜索文件夹“2021 Tenders”并返回路径……尽管这可能会很慢)

但是,我注意到如果我转到文件 > 信息,有一个“打开文件位置”按钮,它直接将我带到文件的本地路径文件夹,它告诉我这个信息在 excel 中的某个地方,必须有一种检索它的方法,我在我的任何搜索中都没有看到对此的引用,在指出它之后,是否有人对它如何或是否可以工作有任何想法? 我试图录制一个宏,但它根本没有注册它。

任何帮助将不胜感激,并提前感谢您。

File > Info - Screenshot

【问题讨论】:

    标签: excel vba sharepoint onedrive


    【解决方案1】:

    这是我根据另一个答案组装的(参见代码中的 cmets)。

    代码属于我放在一起的一系列类,但为了给你一个复杂简单的答案,把它放在一个模块中:

    Option Explicit
    Private Const ONEDRIVE_TENANTS_REGISTRY_FOLDER As String = "Software\Microsoft\OneDrive\Accounts\Business1\Tenants\"
    Private Const ONEDRIVE_TOTAL_VERSIONS As Long = 3
    Private Const ONEDRIVE_PATH_SLASHES As Long = 4
    Const HKEY_CURRENT_USER = &H80000001
    Public Function GetLocalWorkbookName(ByVal fullName As String, Optional ByVal PathOnly As Boolean = False) As String
        ' Credits: https://stackoverflow.com/a/57040668/1521579
        'returns local wb path or empty string if local path not found
    
        Dim localFolders As Collection
        Dim localFolder As Variant
        
        Dim evalPath As String
        Dim result As String
        
        Dim isOneDrivePath As Boolean
        
        'Check if it looks like a OneDrive location
        isOneDrivePath = InStr(1, fullName, "https://", vbTextCompare) > 0
        
        If isOneDrivePath = False Then
            result = fullName
        Else
            Set localFolders = GetLocalFolders
            
            evalPath = RemoveTopFoldersByQty(fullName, ONEDRIVE_PATH_SLASHES)
            For Each localFolder In localFolders
                result = GetFilePathByRootFolder(localFolder, evalPath)
                If result <> vbNullString Then Exit For
            Next localFolder
        End If
        If PathOnly Then
            GetLocalWorkbookName = RemoveFileNameFromPath(result)
        Else
            GetLocalWorkbookName = result
        End If
        
    End Function
    Public Function GetLocalFolders() As Collection
        
        Dim tempCollection As Collection
        Dim tenantFolders As Variant
        Dim localFolders As Variant
        
        Dim tenantCounter As Long
    
        Set tempCollection = New Collection
        
        ' Look in onedrive for business tenant's folders
        tenantFolders = GetRegistrySubKeys(ONEDRIVE_TENANTS_REGISTRY_FOLDER)
        
        For tenantCounter = 0 To UBound(tenantFolders)
            localFolders = GetRegistryValues(ONEDRIVE_TENANTS_REGISTRY_FOLDER & "\" & tenantFolders(tenantCounter) & "\")
            AddArrayItemsToCollection tempCollection, localFolders
        Next tenantCounter
        
        ' Add the onedrive consumer folder
        tempCollection.Add Environ$("OneDriveConsumer")
        
        Set GetLocalFolders = tempCollection
        
    End Function
    Public Function RemoveTopFolderFromPath(ByVal ShortName As String) As String
        RemoveTopFolderFromPath = Mid$(ShortName, InStr(ShortName, "\") + 1)
    End Function
    
    Public Function RemoveTopFoldersByQty(ByVal FullPath As String, ByVal FolderQty As Long) As String
        Dim counter As Long
        Dim evalPath As String
        evalPath = Replace(FullPath, "/", "\")
        For counter = 1 To FolderQty
            evalPath = RemoveTopFolderFromPath(evalPath)
        Next counter
        RemoveTopFoldersByQty = evalPath
    End Function
    
    Public Function RemoveFileNameFromPath(ByVal ShortName As String) As String
        RemoveFileNameFromPath = Mid$(ShortName, 1, Len(ShortName) - InStr(StrReverse(ShortName), "\"))
    End Function
    
    Public Function GetFilePathByRootFolder(ByVal RootFolder As String, ByVal SearchPath As String) As String
        Dim result As String
        Dim evalPath As String
        Dim testFilePath As String
        
        Dim oneDrivePathFound As Boolean
           
        evalPath = IIf(InStr(SearchPath, "\") = 0, "\", vbNullString) & SearchPath
        
        Do While evalPath Like "*\*"
            testFilePath = RootFolder & IIf(Left$(evalPath, 1) <> "\", "\", vbNullString) & evalPath
            If Not (Dir(testFilePath)) = vbNullString Then
                oneDrivePathFound = True
                Exit Do
            End If
            'remove top folder in path
            evalPath = RemoveTopFolderFromPath(evalPath)
        Loop
        
        If oneDrivePathFound = True Then
            result = testFilePath
        Else
            result = vbNullString
        End If
        
        GetFilePathByRootFolder = result
        
    End Function
    Public Function GetRegistrySubKeys(ByVal pathToFolder As String) As Variant
    ' Credits: https://stackoverflow.com/a/8667984/1521579
        Dim registryObject As Object
        Dim computerID As String
        Dim subkeys() As Variant
        'Dim key As Variant
    
        computerID = "."
        Set registryObject = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
        computerID & "\root\default:StdRegProv")
    
        registryObject.EnumKey HKEY_CURRENT_USER, pathToFolder, subkeys
        GetRegistrySubKeys = subkeys
        'For Each key In subKeys
        '    Debug.Print key
        'Next
    End Function
    
    Public Function GetRegistryValues(ByVal pathToFolder As String) As Variant
    ' Credits: https://stackoverflow.com/a/8667984/1521579
        Dim registryObject As Object
        Dim computerID As String
        Dim values() As Variant
        Dim valuesTypes() As Variant
        'Dim value As Variant
        
    
        computerID = "."
        Set registryObject = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
        computerID & "\root\default:StdRegProv")
    
        registryObject.EnumValues HKEY_CURRENT_USER, pathToFolder, values, valuesTypes
        GetRegistryValues = values
        'For Each value In values
        '    Debug.Print value
        'Next
    End Function
    
    
    
    Public Sub AddArrayItemsToCollection(ByVal evalCollection As Collection, ByVal evalArray As Variant)
        
        Dim item As Variant
        
        For Each item In evalArray
            evalCollection.Add item
        Next item
        
    End Sub
    

    然后这样称呼它:

    ? GetLocalWorkbookName(ThisWorkbook.fullName, true)
    

    希望对你有帮助,如果有效,请告诉我

    【讨论】:

    • 里卡多,你我的朋友是个传奇!我必须对代码进行一些调整才能让它做我想做的事,我会把它作为答案发布,这可能不是最传统的方法,但看看你的想法,因为你可以改进/简化更改
    • 很高兴它有帮助。我花了几天时间遇到同样的问题。干杯!
    【解决方案2】:

    该代码非常适合每个 onedrive/sharepoint 根同步文件夹(顶级)的子文件夹中的文件 但如果文件本身位于顶层,则不会

    我单步执行了代码以查看每个斜线的过滤位置 我在“GetFilePathByRootFolder”函数中从“do while”更改为“for”。 用你的“do while”循环计算斜线的数量,然后对斜线的数量+1到“RemoveTopFolderFromPath”进行一个“for”循环,再运行一次,只留下最后一次搜索根文件夹的文件名文件名。

    希望这是有道理的。

        Public Function GetFilePathByRootFolder(ByVal RootFolder As String, ByVal SearchPath As String) As String
        Dim result As String
        Dim evalPath As String
        Dim testFilePath As String
        Dim slashCounter As Integer                                                                         'added by AC
        Dim i As Integer                                                                                    'added by AC
        
        Dim oneDrivePathFound As Boolean
           
        evalPath = IIf(InStr(SearchPath, "\") = 0, "\", vbNullString) & SearchPath
        
        slashCounter = 0                                                                                    'added by AC
        Do While evalPath Like "*\*"                                                                        'added by AC
            slashCounter = slashCounter + 1                                                                 'added by AC
            evalPath = RemoveTopFolderFromPath(evalPath)                                                    'added by AC
        Loop                                                                                                'added by AC
        slashCounter = slashCounter + 1
        evalPath = IIf(InStr(SearchPath, "\") = 0, "\", vbNullString) & SearchPath
    
        For i = 1 To slashCounter                                                                           'added by AC
            testFilePath = RootFolder & IIf(Left$(evalPath, 1) <> "\", "\", vbNullString) & evalPath        'added by AC
            Debug.Print testFilePath                                                                        'added by AC
            If Not (Dir(testFilePath)) = vbNullString Then                                                  'added by AC
                oneDrivePathFound = True                                                                    'added by AC
                Exit For                                                                                    'added by AC
            End If                                                                                          'added by AC
            'remove top folder in path                                                                      'added by AC
            evalPath = RemoveTopFolderFromPath(evalPath)                                                    'added by AC
        Next i                                                                                              'added by AC
        
    '    Do While evalPath Like "*\*" ' change loop to "for each \ in evalPath +1"
    '        testFilePath = RootFolder & IIf(Left$(evalPath, 1) <> "\", "\", vbNullString) & evalPath
    '        Debug.Print testFilePath
    '        If Not (Dir(testFilePath)) = vbNullString Then
    '            oneDrivePathFound = True
    '            Exit Do 'exit for
    '        End If
    '        'remove top folder in path
    '        evalPath = RemoveTopFolderFromPath(evalPath)
    '    Loop
        
        If oneDrivePathFound = True Then
            result = testFilePath
        Else
            result = vbNullString
            
        End If
        
        GetFilePathByRootFolder = result
        
    End Function
    

    【讨论】:

    • 太棒了!!我正在寻找非常相似但用于不同目的的东西......可以修改代码以列出共享点或 onedrive 文件夹中所有 Excel 文件的 URL 吗?我需要获取 URL,因为我将 Excel 文件嵌入网页中,因此无法使用本地路径。我会很感激的! :-)
    【解决方案3】:

    这对我有用。我使用了环境变量。

    OneDrive = Environ("OneDrive")
    CurPath = Application.ThisWorkbook.Path
    If (InStr(1, Left(CurPath, 4), "http", vbTextCompare)) Then
        SubPathPos = InStr(30, CurPath, "/", vbTextCompare)
        CurPath = OneDrive & Right(CurPath, Len(CurPath) - SubPathPos + 1)
    End If
    ChDir (CurPath)
    

    【讨论】:

    • 这对我来说不起作用,但 Environ("OneDrive") 返回我正在使用的系统上 OneDrive 根目录的本地路径。谢谢。
    • 谢谢。您是对的,“OneDrive”是要使用的正确变量。如果您同时拥有个人和公司帐户,“OneDriveConsumer”选择个人帐户,“OneDriveCommercial”选择公司帐户。我已经更新了代码。
    猜你喜欢
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2018-11-14
    • 2015-06-13
    相关资源
    最近更新 更多