├── LICENSE ├── Module_GetLocalPath.bas ├── OneDrive-Registry-1.png ├── OneDrive-Registry-2(en).png ├── OneDrive-Registry-2.png ├── OneDrive-Sync_vs_ShortCut_2(en).png ├── OneDrive-Sync_vs_ShortCut_2.png ├── README(en).md ├── README.md ├── SharePoint-Sync_ShortCut-1.png └── SharePoint-Sync_Shortcut-1(en).png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Excel-VBA-Diary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Module_GetLocalPath.bas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/Module_GetLocalPath.bas -------------------------------------------------------------------------------- /OneDrive-Registry-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/OneDrive-Registry-1.png -------------------------------------------------------------------------------- /OneDrive-Registry-2(en).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/OneDrive-Registry-2(en).png -------------------------------------------------------------------------------- /OneDrive-Registry-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/OneDrive-Registry-2.png -------------------------------------------------------------------------------- /OneDrive-Sync_vs_ShortCut_2(en).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/OneDrive-Sync_vs_ShortCut_2(en).png -------------------------------------------------------------------------------- /OneDrive-Sync_vs_ShortCut_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/OneDrive-Sync_vs_ShortCut_2.png -------------------------------------------------------------------------------- /README(en).md: -------------------------------------------------------------------------------- 1 | # GetLocalPath 2 | # Convert the URL returned by Workbook.Path Property in Excel VBA on OneDrive to a local path. 3 | Created: December 29, 2023 4 | Last Updated: April 10, 2024 5 | 6 | ## 1. Problem to be solved 7 | 8 | There is a problem with the Workbook.Path property returning a URL pass when I run Excel VBA on OneDrive. It is not possible to get the local path of that book, and the URL pass is inconvenient, as the Dir function causes a runtime error and FileSystemObject cannot be used. 9 | 10 | Several methods have been proposed to solve this problem. For a personal OneDrive, there is a way to convert the URL path to a local path by processing the URL path as a string. For a personal OneDrive, the URL returned by the Workbook.Path property would be in the following format \ is the 16-digit number assigned to the individual, followed by the path \ of the folder under the OneDrive. 11 | ``` 12 | https://d.docs.live.net// 13 | ``` 14 | At this time, the OneDrive local path can be converted as follows: 15 | ``` 16 | C:\Users\\OneDrive\ 17 | ``` 18 | For personal OneDrive, the conversion to a local path is relatively easy. In OneDrive for Business, however, this URL path becomes more complex. Here is a typical example: 19 | ``` 20 | https://.sharepoint.com/sites//Shared Documents/ 21 | ``` 22 | ``` 23 | https://-my.sharepoint.com/personal//Documents/ 24 | ``` 25 | When accessing the SharePoint or Teams document library, a menu of "Sync" and "Add Shortcut to OneDrive" will appear in the command bar. 26 | ![SharePoint-Sync_Shortcut-1(en)](SharePoint-Sync_Shortcut-1(en).png) 27 | 28 | Both are the same in that you can use Explorer to access SharePoint and Teams files, but the location of the folders is different. Sync" is added under the building icon, while "Add shortcut to OneDrive" is added under the cloud icon. 29 | (Assigning a SharePoint or Teams folder to OneDrive as a sync folder or shortcut folder is referred to here as "mounting.") 30 | ![OneDrive-Sync_vs_Shortcut_2(en)](OneDrive-Sync_vs_ShortCut_2(en).png) 31 | 32 | The names of the folders to be mounted in this case will not be similar. Usually, "Synchronize" is a hyphenated combination of the site name and the folder name (site name on the left, folder name on the right). On the other hand, "Add shortcut to OneDrive" can be a single folder name or a folder name and site name joined by a hyphen (-) (folder name on the left, site name on the right). 33 | 34 | The local path is different as follows. Synchronize" is just the tenant name, while "Add shortcut to OneDrive" is a concatenation of "OneDrive" and the tenant name. 35 | 36 | For "Sync": 37 | ``` 38 | C:\Users\\\ 39 | ``` 40 | For "Add Shortcut to OneDrive": 41 | ``` 42 | C:\Users\\OneDrive - \ 43 | ``` 44 | 45 | In both cases, in the local path does not necessarily match in the URL path. 46 | Furthermore, the included in the local-path does not necessarily match the included in the URL-path. The in a local path is relative to the folder from which the "Sync" or "Add Shortcut to OneDrive" is taken, whereas the in a URL path is an absolute path from the root of the document library. The URL paths listed here are also local paths. 47 | Both URL paths and local paths listed here are only examples, and it is virtually impossible to convert a URL path to a local path using string conversion alone. 48 | 49 | ## 2. Proposed Solution 50 | 51 | ### OneDrive mounting information 52 | 53 | OneDrive mount information is located under the following registry key 54 | ``` 55 | \HKEY_CURRENT_USER\Software\SyncEngines\Providers\OneDrive 56 | ``` 57 | Under this registry key are the entries (subkeys) that are mounted in OneDrive. The hierarchical structure is shown in the following figure in the Registry Editor. 58 | 59 | ![OneDrive-Registory-1](OneDrive-Registry-1.png) 60 | 61 | Each entry is registered with a pair of UrlNameSpace and MountPoint. 62 | 63 | ![OneDrive-Registory-2(en)](OneDrive-Registry-2(en).png) 64 | 65 | UrlNameSpace is the URL path to the SharePoint document library, and MountPoint is the local path under OneDrive. if there is an UrlNameSpace that matches the upper portion of the URL path returned by Workbook.Path the corresponding MountPoint for the UrlNameSpace can be found. 66 | 67 | In addition, OneDrive configuration information is located at the following local paths. 68 | ``` 69 | C:\Users\\AppData\Local\Microsoft\OneDrive\Settings 70 | ``` 71 | Depending on your Windows and OneDrive environment, there are three folders under this folder: Business1, Business2, and Personal. 72 | Using the "global.ini" file in this folder as a clue, check the related INI file to complete the OneDrive mount information. 73 | 74 | ### Overview of conversion mechanism 75 | 76 | For example, assume the following case. 77 | ``` 78 | UrlNameSpace : https://xxxx.sharepoint.com/sites/SITE1/Shared Documents/ 79 | MountPoint : c:\Users\diary\OneDrive - MyCompany\General - TestSite1 80 | Workbook.Path: https://xxxx.sharepoint.com/sites/SITE1/Shared Documents/General/folder1 81 | ``` 82 | Since the UrlNameSpace matches the upper portion of the URL path returned by the Workbook.Path property, we can determine that the Workbook exists in or under the local path of MountPoint. 83 | From the structure and notational relationship of the document library on the SharePoint site, we know that /General in the URL path returned by the Workbook.Path property corresponds to MountPoint's \General - TestSite1. 84 | Based on these, the URL path returned by Workbook.Path can be converted to the following local path 85 | ``` 86 | c:\Users\diary\OneDrive - MyCompany\General - TestSite1\folder1 87 | ``` 88 | 89 | ## 3. GetLocalPath Function 90 | 91 | The GetLocalPath function converts URL paths to local paths using OneDrive mount information. 92 | If the argument is a local path, it returns the local path as it is without conversion, so it can be used universally by replacing ThisWorkbook.Path in the code with GetLocalPath(ThisWorkbook.Path), for example. 93 | Module_GetLocalPath.bas is an exported VBA module, which contains the Get "LocalPath function. 94 | You can import Module_GetLocalPath.bas as is or copy and paste the necessary parts. 95 | 96 | ### Syntax 97 | GetLocalPath(UrlPath, [UseCache], [DebugMode]) 98 | 99 | |Part|Description| 100 | ----|---- 101 | |UrlPath|Required. String expression of URL path returned by Workbook.Path property.| 102 | |UseCache|Optional, Boolean; Specify True to use the cache or False to not use the cache. The GetLocalPath function reads the OneDrive mount information from the registry and stores it in the cache (Static variable), which is used on the second and subsequent calls to the GetLocalPath function to speed up processing. The cache is valid until the Excel book of the VBA macro is closed. Regardless of the UseCache setting, if 30 seconds have elapsed since the last time the cache was read, the registry is read again and the cache is updated.| 103 | |DebugMode|Optional, Boolean; if True, returns a cache (Collection type) of OneDrive mount information retrieved instead of the local path; if False, returns the local path. When omitted, the default value is False. This argument is used to parse the retrieved OneDrive information and is not normally used.| 104 | 105 | ### Return values 106 | 107 | GetLocalPath returns a local path. 108 | 109 | ### Examples of Use 110 | Normal case: 111 | ``` 112 | Dim localPath As String 113 | localPath = GetLocalPath(ThisWorkbook.Path) 114 | ``` 115 | Update the cache each time the function is called: 116 | ``` 117 | Dim localPath As String 118 | localPath = GetLocalPath(ThisWorkbook.Path, False) 119 | ``` 120 | To retrieve OneDrive mount information (debug mode): 121 | ``` 122 | Dim mpiCache As Collection 123 | Set mpiCache = GetLocalPath(vbNullString, False, True) 124 | ``` 125 | 126 | ### Module_GetLocalPath.bas Version 127 | Created: December 29, 2023 128 | Last Updated: April 10, 2024 129 | Version: 1.007 130 | 131 | ## 4. Known Issue 132 | 133 | ### (1) If there is an upper folder in OneDrive that has the same name as the mounted folder name 134 | The local path shown by MountPoint contains only the name of a target folder under the document library on the SharePoint site. For example, if the name of a target folder is the same as that of an upper-level folder, the upper-level folder may be mistakenly identified as the target folder. This issue will not happen if there is a subordinate folder with the same name as the target folder. Now investigating a workaround for this issue. 135 | 136 | ### (2) If a folder is renamed or moved after mounting it with "Add Shortcut to OneDrive" 137 | It is possible to rename a folder or move a folder after mounting it with "Add Shortcut to OneDrive". However, since these changes are not immediately reflected in the registry, the MountPoint in the registry will not match the actual folder name in OneDrive. Therefore, the folder indicated by the MountPoint is determined to not exist, and the GetLocalPath function returns a null character (a zero-length string). 138 | If you change the folder name or move the folder after mounting it with "Add Shortcut to OneDrive", please restart Windows. 139 | 140 | ## 5. LICENSE 141 | This code is available under the MIT License. 142 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GetLocalPath 2 | # OneDriveでWorkbook.Pathプロパティが返すURLパスをローカルパスに変換する。(#Excel VBA #OneDrive) 3 | [README(en).md](https://github.com/Excel-VBA-Diary/GetLocalPath/blob/main/README(en).md) for English version 4 | 初回投稿日:2023年12月29日 5 | 最終更新日:2024年4月10日 6 | 7 | ## 1. 解決したい問題 8 | 9 | OneDriveでExcel VBAを動かすとWorkbook.Path プロパティはローカルパスではなくURLパスを返すという問題が起きます。URLパスのままではDir関数が実行時エラーになったり、FileSystemObjectが使えなくなるなど不便な状態になります。 10 | 11 | この問題の解決にはいくつかの方法が提案されています。個人用OneDriveであればURLパスを文字列処理してローカルパスに変換する方法があります。 12 | 個人用OneDriveの場合、Workbook.Path プロパティが返すURLは次の形式となります。\は個人用に割り当てられた16桁の番号で、その後にOneDrive配下のフォルダーのパス\が続きます。 13 | ``` 14 | https://d.docs.live.net// 15 | ``` 16 | この時、OneDriveのローカルパスは次のように変換できます。 17 | ``` 18 | C:\Users\\OneDrive\ 19 | ``` 20 | 個人用OneDriveの場合、ローカルパスへの変換は比較的容易です。しかし、OneDrive for Business においては、このURLパスが複雑になります。以下はその典型例です。 21 | ``` 22 | https://.sharepoint.com/sites//Shared Documents/ 23 | ``` 24 | ``` 25 | https://-my.sharepoint.com/personal//Documents/ 26 | ``` 27 | SharePointやTeamsのドキュメントライブラリーにアクセスするとコマンドバーに「同期」と「OneDriveへのショートカットの追加」のメニューが表示されます。 28 | ![SharePoint-Sync_ShortCut-1](SharePoint-Sync_ShortCut-1.png) 29 | 30 | どちらもエクスプローラーを使ってSharePointやTeamsのファイルにアクセスできる点では同じですが、フォルダーの置き場所は異なります。「同期」は建物アイコンの下に、「OneDriveへのショートカットの追加」は雲アイコンの下に追加されます。 31 | (SharePointやTeamsのフォルダーをOneDriveに同期フォルダーまたはショートカットフォルダーとして割り当てることをここでは「マウント」と呼ぶことにします。) 32 | 33 | ![OneDrive-Sync-vs-ShortCut](OneDrive-Sync_vs_ShortCut_2.png) 34 | 35 | このときマウントされるフォルダーの名前は似て非なるものになります。通常、「同期」はサイト名とフォルダー名をハイフン(-)で連結した名前になります(サイト名が左でフォルダー名が右)。一方「OneDriveへのショートカットの追加」はフォルダー名だけの単独か、フォルダー名とサイト名をハイフン(-)で連結した名前になります(フォルダー名が左でサイト名が右)。 36 | 37 | またローカルパスは次のとおり異なります。「同期」はテナント名だけなのに対して、 「OneDriveへのショートカットの追加」は"OneDrive"とテナント名を連結したものになります。 38 | 39 | 「同期」の場合: 40 | ``` 41 | C:\Users\\<テナント名>\<フォルダーパス> 42 | ``` 43 | 「OneDriveへのショートカットの追加」の場合: 44 | ``` 45 | C:\Users\\OneDrive - <テナント名>\<フォルダーパス> 46 | ``` 47 | 48 | どちらの場合も、通常、ローカルパスに含まれる<テナント名>はURLパスに含まれる\とは異なります。 49 | さらにローカルパスに含まれる<フォルダーパス>はURLパスに含まれる\と必ずしも一致しません。ローカルパスに含まれる<フォルダーパス>は「同期」または「OneDriveへのショートカットの追加」の対象となるフォルダを起点とする相対パスであるのに対して、URLパスに含まれる\はドキュメントライブラリーのルートからの絶対パスになります。 50 | ここに挙げたURLパスもローカルパスも一例に過ぎず、文字列変換だけでURLパスをローカルパスに変換するのは事実上無理です。 51 | 52 | ## 2. 提案する解決策 53 | 54 | ### OneDriveのマウント情報 55 | 56 | OneDriveのマウント情報は次のレジストキー配下にあります。 57 | ``` 58 | \HKEY_CURRENT_USER\Software\SyncEngines\Providers\OneDrive 59 | ``` 60 | このレジストリーキーの配下にはOneDriveにマウントされているエントリー(サブキー)が登録されています。レジストリーエディターで見ると下図のような階層構造になっています。 61 | 62 | ![OneDrive-Registory-1](OneDrive-Registry-1.png) 63 | 64 | それぞれのエントリーにはUrlNameSpaceとMountPointが対になって登録されています。 65 | 次の図はその例です。 66 | 67 | ![OneDrive-Registory-1](OneDrive-Registry-2.png) 68 | 69 | UrlNameSpaceはSharePointのドキュメントライブラリーのURLパス、MountPointはOneDrive配下のローカルパスを示しています。Workbook.Pathが返すURLパスの上位部分と一致するUrlNameSpaceがあれば、そのUrlNameSpaceに対応するMountPointがわかります。 70 | 71 | さらにOneDriveの設定情報は次のローカルパスにあります。 72 | ``` 73 | C:\Users\\AppData\Local\Microsoft\OneDrive\Settings 74 | ``` 75 | WindowsやOneDriveの環境によりますが、この配下にはBusiness1、Business2、Personal という三つのフォルダーがあります。 76 | このフォルダーにある「global.ini」ファイルを手掛かりに関連するINIファイルを調べてOneDriveのマウント情報を補完します。 77 | 78 | ### 変換メカニズムの概略 79 | 80 | 例えば、次のようなケースを想定します。ここでは「OneDriveへのショートカットの追加」のケースを示しています。 81 | ``` 82 | Workbook.Path: https://xxxx.sharepoint.com/sites/SITE1/Shared Documents/General/SubFolder1 83 | UrlNamespace : https://xxxx.sharepoint.com/sites/SITE1/Shared Documents/ 84 | MountPoint : c:\Users\diary\OneDrive - 株式会社VBA\General - サイト1 85 | ``` 86 | Workbook.Pathプロパティが返すURLパスの上位部分とUrlNameSpaceが一致していますので、MountPointのローカルパスまたはその配下にWorkbookが存在していると判断できます。 87 | SharePoint サイトのドキュメントライブラリの階層構造とフォルダーの命名規則の関係から、Workbook.Pathプロパティが返すURLパスのうち「/General」が MountPoint の「\General - サイト1」に相当します。 88 | これらのことを踏まえ、Workbook.Pathが返すURLパスは次のローカルパスに変換できます。 89 | ``` 90 | c:\Users\diary\OneDrive - 株式会社VBA\General - サイト1\SubFolder1 91 | ``` 92 | 93 | ## 3. GetLocalPath 関数 94 | 95 | OneDriveのマウント情報を使ってURLパスをローカルパスに変換する関数が「GetLocalPath関数」です。 96 | 引き数がローカルパスの場合は、変換せずにローカルパスをそのまま返しますので、例えば、コードの中の ThisWorkbook.Path を GetLocalPath(ThisWorkbook.Path) に置き換えて汎用的に使うことができます。 97 | Module_GetLocalPath.bas はVBAモジュールをエクスポートしたものです。この中に「GetLocalPath関数」が含まれています。Module_GetLocalPath.basをそのままインポートするか必要な部分をコピペしてお使いください。 98 | 99 | ### 構文 100 | GetLocalPath(UrlPath, [UseCache], [DebugMode]) 101 | 102 | |引き数|説明| 103 | ----|---- 104 | |UrlPath|必須。String型。Workbook.Pathが返すURLパス(文字列)を指定します。| 105 | |UseCache|省略可。Boolean型。キャッシュを使う場合はTrue、使わない場合はFalseを指定します。省略時の規定値はTrueです。GetLocalPath関数はレジストリからOneDriveのマウント情報を読み込みキャッシュ(Static変数)に保存します。2回目以降のGetLocalPath関数呼び出し時に、このキャッシュを使うことで処理を高速化しています。キャッシュはVBAマクロのExcelブックを閉じるまで有効です。UseCacheの指定にかかわらず、前回のキャッシュ読み込みから30秒経過した場合は再度レジストリを読み込みキャッシュを更新します。| 106 | |DebugMode|省略可。Boolean型。Trueの場合はローカルパスを返すかわりに取得したOneDriveマウント情報のキャッシュ(Collection型)を返します。Falseの場合はローカルパスを返します。省略時の規定値はFalseです。この引数は取得したOneDrive情報を解析するためのもので通常は使いません。| 107 | 108 | ### 戻り値 109 | 110 | GetLocalPath関数はローカルパスを文字列で返します。 111 | DebugModeがTrueの場合はUrlPathの指定にかかわらずOneDriveマウント情報のキャッシュ(Collection型)を返します。 112 | 113 | ### 例 114 | 通常の場合: 115 | ``` 116 | Dim localPath As String 117 | localPath = GetLocalPath(ThisWorkbook.Path) 118 | ``` 119 | 関数呼び出しの都度キャッシュを更新する場合: 120 | ``` 121 | Dim localPath As String 122 | localPath = GetLocalPath(ThisWorkbook.Path, False) 123 | ``` 124 | OneDriveマウント情報を取得する場合(デバッグモード): 125 | ``` 126 | Dim mpiCache As Collection 127 | Set mpiCache = GetLocalPath(vbNullString, False, True) 128 | ``` 129 | 130 | ### Module_GetLocalPath.bas バージョン 131 | Created: December 29, 2023 132 | Last Updated: April 10, 2024 133 | Version: 1.007 134 | 135 | ## 4. 既知の問題 136 | 137 | ### (1) OneDriveにマウントしたフォルダー名と同一の上位フォルダーが存在する場合 138 | MountPointで示されるローカルパスには、SharePointサイトのドキュメントライブラリー配下にある、特定のフィルダーの名前だけの情報しかありません。ドキュメントライブラリーのルートからのフルパスを示していませんので、そのフォルダーがドキュメントライブラリーの階層構造のどの位置のどのフォルダーに該当するかを突きとめる必要が出てきます。このとき、該当フォルダーの名前が上位フォルダーと同一名の場合、上位フォルダーを当該フォルダーだと誤って認識する場合があります。ただし、この事象は「OneDriveへのショートカットの追加」でマウントした場合や当該フォルダーと同じ名前のフォルダーが下位にある場合は起きません。「同期」でマウントした場合のみの事象です。この事象を回避するための方法は現在調査中です。 139 | 140 | ### (2) 「OneDriveへのショートカットの追加」でマウントした後にフォルダー名を変更したり移動した場合 141 | 「OneDriveへのショートカットの追加」でマウントした後にフォルダー名を変更したりフォルダーを移動することは可能です。しかし、この変更は直ちにレジストリに反映されないため、レジストリに登録されているMountPointとOneDriveの実際のフォルダー名は一致しなくなります。このためMountPointで示されるフォルダーが存在しないと判定され、GetLocalPath関数はヌル文字(長さ0の文字列)を返します。 142 | 「OneDriveへのショートカットの追加」でマウントした後にフォルダー名を変更したりフォルダーを移動した場合はWindowsを再起動してください。 143 | 144 | ## 5. ライセンス 145 | 146 | このコードはMITライセンスに基づき利用できます。 147 | 148 | -------------------------------------------------------------------------------- /SharePoint-Sync_ShortCut-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/SharePoint-Sync_ShortCut-1.png -------------------------------------------------------------------------------- /SharePoint-Sync_Shortcut-1(en).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Excel-VBA-Diary/GetLocalPath/ecc857b090d16ef736288c76bea1a02fff5d3c7f/SharePoint-Sync_Shortcut-1(en).png --------------------------------------------------------------------------------