【入門編】プロジェクトの「リソースプール」を複数人で同時編集する際の競合回避VBA – Project VBA解析バイブル

スポンサーリンク

Project VBAで「リソースプール」を複数人で安全に編集!競合回避の鉄則を伝授します

皆さん、こんにちは!Project VBAの世界へようこそ。

今回は、プロジェクト管理で避けては通れない「リソースプール」の複数人同時編集という、まさに「あるある」な課題に焦点を当てて、その解決策をVBAで実現する方法を、基礎から応用まで、図解も交えながら分かりやすく解説していきます。

「マクロの記録」で作成したコードを眺めるだけでは、なかなか先に進めない…そんな風に感じているあなたも大丈夫!この記事を読み進めれば、Project VBAの奥深さを理解し、現場で即戦力となるファイル操作術が身につくはずです。

さあ、一緒にProject VBAの扉を開き、リソース管理の効率化を達成しましょう!

1. なぜ「リソースプール」の同時編集は難しいのか? ~競合発生のメカニズム~

まず、なぜ複数人で同じファイルに同時に書き込もうとすると問題が起きるのか、そのメカニズムを理解することが大切です。

1.1. ファイルロックの壁:独占的な書き込み権

皆さんが普段、Excelなどのファイルを編集している時を想像してみてください。誰かがファイルを開いていると、「このファイルは〇〇さんが開いています。読み取り専用で開くか、通知を受け取るか選択してください。」といったメッセージが表示された経験はありませんか?

これは、ファイルが「ロック」されている状態です。ファイルを開いた人が、そのファイルに対して「独占的な書き込み権」を持っているため、他の人は通常、書き込みができないようになっています。

Project VBAも、リソースプールファイルを直接操作する際には、このファイルロックの仕組みを考慮する必要があります。

1.2. 競合発生のシナリオ:上書きとデータ消失の恐怖

もし、このファイルロックの仕組みを無視して、複数の人が同時にリソースプールファイルにアクセスし、編集・保存しようとしたらどうなるでしょうか?

想像してみてください。

  • Aさんがリソースプールを開き、新しいリソースを追加しました。
  • Bさんも同時にリソースプールを開き、別のリソースの情報を更新しました。
  • Aさんが編集を終え、保存しました。
  • Bさんも編集を終え、保存しました。

この時、Bさんが保存した内容がAさんの保存内容を上書きしてしまう可能性があります。結果として、Aさんが追加したリソースの情報が失われてしまう…なんて悲劇が起こりうるのです。

これが「競合」と呼ばれる状態です。プロジェクト管理において、リソース情報は非常に重要です。このようなデータ消失は、プロジェクトの遅延やコスト超過に直結しかねません。

2. 堅牢なファイル操作術:競合回避のためのVBAテクニック

では、どうすればこの競合を防ぎ、安全にリソースプールを共有できるのでしょうか?Project VBAでは、いくつかの堅牢なファイル操作テクニックを組み合わせることで、この課題をクリアできます。

2.1. 排他制御(File Locking)の実装:他のユーザーを「待たせる」工夫

最も基本的な対策は、ファイルへのアクセスを制御することです。つまり、「誰かがファイルを編集している間は、他の人は編集できないようにする」という仕組みをVBAで実装します。

2.1.1. ファイルロックの確認と設定

VBAでは、`FileSystemObject` を使うことで、ファイルの存在確認やロック状態の確認、そしてファイルを開く際のロック設定が可能です。

まず、`FileSystemObject` を使うために、VBAエディタで 「ツール」→「参照設定」 を開き、「Microsoft Scripting Runtime」 にチェックを入れてください。(※VB.NETの場合は、`System.IO` 名前空間を使用します。)

‘ VBAコード例:ファイルロックの確認と設定
Sub CheckAndLockResourcePool()

Dim fso As Object ‘ FileSystemObject
Dim filePath As String
Dim fileLock As Object ‘ FileLock object (Not directly in VBA, but conceptually)
Dim attempt As Integer
Const MAX_ATTEMPTS As Integer = 5 ‘ 試行回数
Const DELAY_SECONDS As Integer = 2 ‘ 待機時間(秒)

‘ リソースプールファイルのパスを指定してください
filePath = ThisWorkbook.Path & “\ResourcePool.xlsx” ‘ 例: 現在のブックと同じフォルダにある場合

‘ FileSystemObjectを作成
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ ファイルが存在するか確認
If Not fso.FileExists(filePath) Then
MsgBox “リソースプールファイルが見つかりません。”, vbCritical
Exit Sub
End If

‘ ファイルロックの試行
attempt = 0
Do While attempt < MAX_ATTEMPTS On Error Resume Next ' エラーが発生しても処理を継続 ' ファイルを排他モードで開こうと試みる ' FileOpenMode.LockExclusive (共有モード) は、他のプロセスからの読み書きをブロックします。 ' FileOpenMode.LockRead (読み取り専用モード) は、他のプロセスからの書き込みのみをブロックします。 ' ここでは、排他モードで開くことを試みます。 ' VBAでは直接的なFileLockオブジェクトは提供されていませんが、 ' ファイルを開く際にエラーが発生するかどうかでロック状態を判断します。 ' 実際には、PowerShellや外部ツールと連携しないと、 ' VBA単体で細かなファイルロック制御は難しい側面があります。 ' ここでは、ファイルが存在し、かつ開ける(ロックされていない)と仮定して進めます。 ' より堅牢なロック機構が必要な場合は、データベースや共有フォルダのロック機能、 ' あるいは外部プログラムとの連携を検討します。 ' より現実的なアプローチとして、ファイルを開いてすぐに閉じることで、 ' 短時間でもロックをかけ、他のユーザーに「編集中」であることを通知する手法があります。 ' ただし、これは完全な排他制御ではありません。 ' ★★★ ここで、ファイルを開いてロックをかける処理を記述 ★★★ ' 例:Excelファイルを開いて、すぐに閉じる(ロックをかけるため) Dim wb As Workbook On Error Resume Next ' エラーが発生しても処理を継続 Set wb = Workbooks.Open(filePath, ReadOnly:=True, UpdateLinks:=0) ' 読み取り専用で開いてみる If Err.Number <> 0 Then
‘ ファイルがロックされている場合
attempt = attempt + 1
Debug.Print “ファイルはロックされています。試行回数: ” & attempt
Err.Clear
Application.Wait Now + TimeValue(“00:00:” & DELAY_SECONDS) ‘ 指定時間待機
Else
‘ ファイルを開くことができた(ロックされていない)
Debug.Print “ファイルを開けました。ロックをかけます。”
‘ ★★★ ここで、リソースプールへの編集処理を実行 ★★★
‘ 例: Call EditResourcePool(filePath)

‘ 編集が終わったら、ファイルを閉じてロックを解除
wb.Close SaveChanges:=False ‘ 保存せずに閉じる(今回はロック確認のみのため)
Set wb = Nothing
Exit Do ‘ ループを抜ける
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
Loop

If attempt = MAX_ATTEMPTS Then
MsgBox “リソースプールファイルへのアクセスに失敗しました。他のユーザーが編集中の可能性があります。”, vbExclamation
Set fso = Nothing
Exit Sub
End If

‘ ★★★ ここで、リソースプールへの編集処理を実行 ★★★
‘ Call PerformActualEditing(filePath)

MsgBox “リソースプールへのアクセスに成功しました。”, vbInformation
Set fso = Nothing

End Sub

‘ 実際の編集処理を行うサブルーチン(仮)
Sub PerformActualEditing(ByVal targetFilePath As String)
MsgBox targetFilePath & ” にて、リソースプールの編集処理を実行します。”, vbInformation
‘ ここに、実際にリソースプールファイルを開き、データを編集・保存するコードを記述します。
‘ 注意:この部分でも、保存時に再度ロック確認やエラーハンドリングが必要です。
End Sub

コード解説:

  • `CreateObject(“Scripting.FileSystemObject”)`: ファイル操作を行うためのオブジェクトを作成します。
  • `fso.FileExists(filePath)`: 指定したパスにファイルが存在するかどうかを確認します。
  • `Workbooks.Open(filePath, ReadOnly:=True, UpdateLinks:=0)`: ファイルを読み取り専用で開こうと試みます。もし他のユーザーが書き込みモードで開いている場合、この処理でエラーが発生します(`Err.Number <> 0`)。
  • `Application.Wait Now + TimeValue(…)`: 指定した時間だけ処理を一時停止させます。これにより、短時間待ってから再度ファイルロックを確認します。
  • `On Error Resume Next`: エラーが発生しても、次の行のコードを実行します。これにより、ファイルがロックされている場合のエラーを無視して、待機処理に進むことができます。
  • `Err.Clear`: エラー情報をクリアします。
  • `On Error GoTo 0`: エラーハンドリングを通常の状態に戻します。

ポイント:

  • VBA単体で、他のプロセスがファイルを開いているかどうかを完璧に検知し、かつそれをブロックする機能は限定的です。上記のコードは、「ファイルを開こうとしてエラーになるかどうか」で間接的にロック状態を判断しています。
  • より厳密な排他制御が必要な場合は、データベースを利用したり、共有フォルダのロック機能(SMBロックなど)、あるいは外部のロックファイルを作成するなどの高度な手法を検討する必要があります。
  • `Workbooks.Open` の `ReadOnly:=True` は、書き込みロックされているファイルを開く際にエラーを発生させるためのトリガーとして利用しています。

2.1.2. 編集中の通知とロック期間の短縮

ファイルロックをかける期間は、できるだけ短くするのが理想です。ユーザーがファイルを長時間ロックしていると、他のユーザーが作業できなくなってしまうからです。

  • 編集処理は素早く終える: 必要なデータだけを読み込み、最小限の変更を行い、すぐに保存・閉じるようにコードを最適化しましょう。
  • 「編集中」の通知: VBAでファイルロックを検知した場合、他のユーザーに「現在、〇〇さんがリソースプールを編集中です。しばらくお待ちください。」といったメッセージを表示すると、親切です。

2.2. バックアップ作成:万が一のための「保険」

排他制御を完璧に実装したとしても、予期せぬ事態(停電、PCのフリーズなど)でファイルが破損する可能性はゼロではありません。そこで、変更を加える前に必ずバックアップを作成するという習慣をVBAで自動化しましょう。

2.2.1. バックアップファイルの命名規則

バックアップファイルは、元のファイルと区別できるような命名規則をつけます。例えば、元のファイル名に日付と時刻を追加する方法が一般的です。

‘ VBAコード例:バックアップファイル名の生成
Function CreateBackupFileName(originalFilePath As String) As String
Dim backupFileName As String
Dim timeStamp As String

‘ 現在の日付と時刻を取得(例: 20231027_153045)
timeStamp = Format(Now, “yyyymmdd_hhmmss”)

‘ ファイルパスとファイル名を分割
Dim folderPath As String
Dim fileNameWithoutExt As String
Dim fileExtension As String

folderPath = fso.GetParentFolderName(originalFilePath)
fileNameWithoutExt = fso.GetBaseName(originalFilePath)
fileExtension = fso.GetExtensionName(originalFilePath)

‘ バックアップファイル名を生成
backupFileName = folderPath & “\” & fileNameWithoutExt & “_backup_” & timeStamp & “.” & fileExtension

CreateBackupFileName = backupFileName
End Function

‘ FileSystemObject (fso) は、この関数が呼び出される前に初期化されている必要があります。
‘ 例:
‘ Dim fso As Object
‘ Set fso = CreateObject(“Scripting.FileSystemObject”)

コード解説:

  • `Format(Now, “yyyymmdd_hhmmss”)`: 現在の日時を「年年月月日日_時時分分秒秒」の形式の文字列に変換します。
  • `fso.GetParentFolderName(originalFilePath)`: ファイルのパスからディレクトリ部分を取得します。
  • `fso.GetBaseName(originalFilePath)`: ファイルのパスから拡張子を除いたファイル名部分を取得します。
  • `fso.GetExtensionName(originalFilePath)`: ファイルのパスから拡張子部分を取得します。
  • これらの要素を組み合わせて、ユニークなバックアップファイル名を生成します。

2.2.2. バックアップの実行タイミング

バックアップは、リソースプールファイルに書き込みを行う直前に実行するのが最も効果的です。

‘ VBAコード例:バックアップ実行とファイルコピー
Sub BackupResourcePool(ByVal originalFilePath As String)

Dim fso As Object
Dim backupFilePath As String

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ バックアップファイル名を生成
backupFilePath = CreateBackupFileName(originalFilePath) ‘ 上記で定義した関数を使用

‘ ファイルをコピーしてバックアップを作成
On Error Resume Next
fso.CopyFile originalFilePath, backupFilePath, True ‘ True: 上書きを許可
If Err.Number <> 0 Then
MsgBox “バックアップファイルの作成に失敗しました: ” & Err.Description, vbCritical
Set fso = Nothing
Exit Sub
End If
On Error GoTo 0

MsgBox “バックアップファイルを作成しました: ” & backupFilePath, vbInformation
Set fso = Nothing

End Sub

‘ — CreateBackupFileName 関数は上記で定義済み —
‘ Function CreateBackupFileName(originalFilePath As String) As String …

コード解説:

  • `fso.CopyFile originalFilePath, backupFilePath, True`: 指定したファイルを、指定した新しいパスにコピーします。第3引数 `True` は、もしバックアップファイルが既に存在する場合に上書きすることを意味します。
  • `On Error Resume Next` と `Err.Clear`: ファイルコピー中にエラーが発生した場合(例:ディスク容量不足など)を捕捉します。

ポイント:

  • バックアップファイルは、元のファイルとは別の場所(例えば、別のフォルダやネットワークドライブ)に保存することも検討しましょう。これにより、元のファイルが破損した場合でも、バックアップファイルが安全に保たれます。
  • 定期的に古いバックアップファイルを削除する仕組みも加えると、ディスク容量の節約になります。

3. Project VBAでのリソースプール管理の実践コード例

それでは、これまでに解説した排他制御とバックアップ作成の考え方を組み合わせて、Project VBAにおけるリソースプール管理の具体的なVBAコード例を見ていきましょう。

ここでは、リソースプールがExcelファイル(`ResourcePool.xlsx`)として存在し、そのファイルに新しいリソース情報を追加するシナリオを想定します。

‘ Project VBA – リソースプール同時編集競合回避マクロ

‘ ★★★ 設定項目 ★★★
Const RESOURCE_POOL_FILE_NAME As String = “ResourcePool.xlsx” ‘ リソースプールファイル名
Const SHEET_NAME As String = “Resources” ‘ リソース情報が記載されているシート名
Const FIRST_DATA_ROW As Long = 2 ‘ データが開始される行番号(ヘッダー行を除く)
Const COLUMN_RESOURCE_NAME As Long = 1 ‘ リソース名が記載されている列番号 (A列なら1)
Const COLUMN_AVAILABILITY As Long = 2 ‘ 稼働率が記載されている列番号 (B列なら2)
‘ 他にも必要な列があれば追加してください(例: Cost, StartDate, EndDate など)

Const MAX_LOCK_ATTEMPTS As Integer = 10 ‘ ファイルロック試行回数
Const LOCK_WAIT_SECONDS As Integer = 3 ‘ ロック確認間の待機時間(秒)

‘ ★★★ メイン処理:新しいリソースを登録する ★★★
Sub AddNewResource(ByVal resourceName As String, ByVal availability As Double)

Dim fso As Object
Dim resourcePoolPath As String
Dim wb As Workbook
Dim ws As Worksheet
Dim lastRow As Long
Dim newRow As Long
Dim backupFilePath As String

‘ FileSystemObjectを作成
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ リソースプールファイルのフルパスを取得
resourcePoolPath = ThisWorkbook.Path & “\” & RESOURCE_POOL_FILE_NAME ‘ 現在のブックと同じフォルダにあると仮定

‘ — 1. ファイルロックの試行 —
If Not TryLockResourcePool(resourcePoolPath, MAX_LOCK_ATTEMPTS, LOCK_WAIT_SECONDS) Then
MsgBox “リソースプールファイルへのアクセスに失敗しました。” & vbCrLf & _
“他のユーザーが編集中の可能性があります。しばらくしてから再試行してください。”, vbExclamation
Set fso = Nothing
Exit Sub
End If

‘ — 2. バックアップの作成 —
backupFilePath = CreateBackupFileName(resourcePoolPath)
If Not CreateBackup(resourcePoolPath, backupFilePath) Then
MsgBox “バックアップファイルの作成に失敗しました。編集を中止します。”, vbCritical
‘ ロックを解除(ファイルを開かなかったので、ここで明示的な解除は不要)
Set fso = Nothing
Exit Sub
End If

‘ — 3. リソースプールファイルを開く(編集モード) —
On Error Resume Next
‘ 読み取り/書き込みモードで開く
Set wb = Workbooks.Open(resourcePoolPath, UpdateLinks:=0)
If Err.Number <> 0 Then
MsgBox “リソースプールファイルを開けませんでした: ” & Err.Description & vbCrLf & _
“バックアップファイル: ” & backupFilePath, vbCritical
Err.Clear
‘ ロックを解除(ファイルを開かなかったので、ここで明示的な解除は不要)
Set fso = Nothing
Exit Sub
End If
On Error GoTo 0

‘ シートを取得
On Error Resume Next
Set ws = wb.Sheets(SHEET_NAME)
If Err.Number <> 0 Then
MsgBox “シート ‘” & SHEET_NAME & “‘ が見つかりません。”, vbCritical
wb.Close SaveChanges:=False
Set wb = Nothing
Set fso = Nothing
Exit Sub
End If
On Error GoTo 0

‘ — 4. 新しいリソース情報を追加 —
‘ データ最終行を取得
lastRow = ws.Cells(ws.Rows.Count, COLUMN_RESOURCE_NAME).End(xlUp).Row

‘ 新しい行番号を決定
If lastRow < FIRST_DATA_ROW Then newRow = FIRST_DATA_ROW ' シートが空の場合 Else newRow = lastRow + 1 ' 最終行の次 End If ' リソース名と稼働率を書き込む ws.Cells(newRow, COLUMN_RESOURCE_NAME).Value = resourceName ws.Cells(newRow, COLUMN_AVAILABILITY).Value = availability ' 例: 1.0 (100%) ' 他の列にも必要に応じてデータを書き込む... ' --- 5. ファイルを保存して閉じる --- Application.DisplayAlerts = False ' 保存確認メッセージなどを非表示にする On Error Resume Next wb.Close SaveChanges:=True ' 変更を保存して閉じる If Err.Number <> 0 Then
MsgBox “リソースプールファイルの保存に失敗しました: ” & Err.Description & vbCrLf & _
“バックアップファイル: ” & backupFilePath, vbCritical
Err.Clear
‘ 保存に失敗した場合でも、ファイルは閉じられているはず
Else
MsgBox “新しいリソース ‘” & resourceName & “‘ を追加しました。”, vbInformation
End If
Application.DisplayAlerts = True ‘ アラート表示を元に戻す
On Error GoTo 0

‘ — 6. ファイルロックを解除 —
‘ Excelファイルは閉じることで自動的にロックが解除されます。
‘ FileSystemObjectも解放します。
Set wb = Nothing
Set ws = Nothing
Set fso = Nothing

End Sub

‘ ★★★ ファイルロックを試行するサブルーチン ★★★
Private Function TryLockResourcePool(ByVal filePath As String, ByVal maxAttempts As Integer, ByVal waitSeconds As Integer) As Boolean
Dim fso As Object
Dim attempt As Integer
Dim wbTemp As Workbook ‘ 一時的にファイルを開くための変数

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ ファイルが存在しない場合はロック不要(作成処理があれば別途考慮)
If Not fso.FileExists(filePath) Then
TryLockResourcePool = True ‘ 存在しない場合はロック不要として成功とする
Set fso = Nothing
Exit Function
End If

attempt = 0
Do While attempt < maxAttempts On Error Resume Next ' エラーが発生しても処理を継続 ' ファイルを読み取り専用で開こうと試みる ' これにより、他のプロセスが書き込みモードで開いている場合にエラーが発生する Set wbTemp = Workbooks.Open(filePath, ReadOnly:=True, UpdateLinks:=0) If Err.Number <> 0 Then
‘ ファイルがロックされている(開けない)場合
Debug.Print “ファイルロック試行 ” & (attempt + 1) & “/” & maxAttempts & “: ファイルはロックされています。”
Err.Clear
Application.Wait Now + TimeValue(“00:00:” & waitSeconds) ‘ 指定時間待機
attempt = attempt + 1
Else
‘ ファイルを開くことができた(ロックされていない)
Debug.Print “ファイルロック試行 ” & (attempt + 1) & “/” & maxAttempts & “: ファイルを開けました。”
wbTemp.Close SaveChanges:=False ‘ すぐに閉じる
Set wbTemp = Nothing
TryLockResourcePool = True ‘ ロック成功
Exit Function ‘ ループを抜ける
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
Loop

‘ 最大試行回数に達してもロックできなかった場合
TryLockResourcePool = False
Set fso = Nothing
End Function

‘ ★★★ バックアップファイル名を生成する関数 ★★★
Private Function CreateBackupFileName(ByVal originalFilePath As String) As String
Dim fso As Object
Dim backupFileName As String
Dim timeStamp As String

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 現在の日付と時刻を取得(例: 20231027_153045)
timeStamp = Format(Now, “yyyymmdd_hhmmss”)

‘ ファイルパスとファイル名を分割
Dim folderPath As String
Dim fileNameWithoutExt As String
Dim fileExtension As String

folderPath = fso.GetParentFolderName(originalFilePath)
fileNameWithoutExt = fso.GetBaseName(originalFilePath)
fileExtension = fso.GetExtensionName(originalFilePath)

‘ バックアップファイル名を生成
backupFileName = folderPath & “\” & fileNameWithoutExt & “_backup_” & timeStamp & “.” & fileExtension

CreateBackupFileName = backupFileName
Set fso = Nothing
End Function

‘ ★★★ バックアップファイルを作成するサブルーチン ★★★
Private Function CreateBackup(ByVal originalFilePath As String, ByVal backupFilePath As String) As Boolean
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)

On Error Resume Next
fso.CopyFile originalFilePath, backupFilePath, True ‘ True: 上書きを許可
If Err.Number <> 0 Then
Debug.Print “バックアップ作成エラー: ” & Err.Description
Err.Clear
CreateBackup = False
Else
Debug.Print “バックアップ作成成功: ” & backupFilePath
CreateBackup = True
End If
On Error GoTo 0
Set fso = Nothing
End Function

‘ — 実行例 —
Sub TestAddNewResource()
‘ 例:リソース名 “New Developer”、稼働率 0.8 (80%) を追加
AddNewResource “New Developer”, 0.8
End Sub

コード解説:

1. 設定項目: `Const` を使って、リソースプールファイル名、シート名、列番号などを定数として定義します。これにより、後で設定を変更するのが容易になります。
2. `AddNewResource` サブルーチン:

  • ファイルロックを試行します (`TryLockResourcePool`)。失敗したら処理を中断します。
  • バックアップを作成します (`CreateBackup`)。失敗したら処理を中断します。
  • リソースプールファイルを編集モードで開きます。
  • 新しいリソース情報を、指定されたシートの最終行の次に追加します。
  • ファイルを保存して閉じます。この際、`Application.DisplayAlerts = False` で不要なダイアログを非表示にし、`On Error Resume Next` で保存時のエラーを捕捉できるようにしています。
  • Excelファイルは閉じることで自動的にロックが解除されます。

3. `TryLockResourcePool` 関数:

  • 指定された回数、ファイルを読み取り専用で開こうと試みます。
  • 開けなければ待機し、再度試行します。
  • 成功すれば `True` を、失敗すれば `False` を返します。

4. `CreateBackupFileName` 関数:

  • `CreateBackup` サブルーチンが使用する、タイムスタンプ付きのバックアップファイル名を生成します。

5. `CreateBackup` サブルーチン:

  • `fso.CopyFile` を使用して、元のファイルをバックアップファイルにコピーします。

陥りやすいエラーと対策:

  • ファイルパスの間違い: `ThisWorkbook.Path` は、VBAコードが保存されているブックのパスを返します。リソースプールファイルが別の場所にある場合は、適切なパスを指定する必要があります。
  • シート名や列番号の間違い: 定数で定義している箇所を、実際のファイル構成に合わせて正確に設定してください。
  • `Workbooks.Open` でのロック解除漏れ: `Workbooks.Open` でファイルを開いた後、何らかのエラーで処理が中断した場合、ファイルがロックされたままになる可能性があります。`On Error …` の処理を適切に記述し、最終的に `wb.Close` が実行されるように注意が必要です。
  • バックアップ失敗時の処理: バックアップに失敗した場合、重要な変更を加える前に処理を中断することが重要です。
  • 同時実行の頻度が高い場合: `LOCK_WAIT_SECONDS` が短すぎると、ロックされていないにも関わらず「ロックされている」と誤判定してしまう可能性があります。逆に長すぎると、ユーザーの待ち時間が長くなります。適切なバランスを見つけることが重要です。

4. さらに高度なテクニック:VB.NETとの連携

VBAだけでも上記のような競合回避は可能ですが、もしあなたがVB.NETでの開発経験もある、あるいはこれから学習したいと考えているのであれば、より強力で柔軟なファイル操作が可能になります。

VB.NETでは、C#などの他の.NET言語と同様に、`System.IO` 名前空間を利用することで、ファイルのロック、コピー、削除などをより細かく制御できます。

4.1. VB.NETでのファイルロック(`FileShare` オプション)

VB.NETでファイルを開く際には、`FileShare` オプションを指定することで、他のプロセスからのアクセス方法を制御できます。

.net
‘ VB.NETコード例:ファイルを開く際の共有オプション
Imports System.IO

‘ …

Dim filePath As String = “C:\Path\To\ResourcePool.xlsx”
Dim fileStream As FileStream = Nothing

Try
‘ FileShare.ReadWrite: 他のプロセスからの読み取り/書き込みを許可
‘ FileShare.Read: 他のプロセスからの読み取りのみを許可 (書き込みはブロック)
‘ FileShare.Write: 他のプロセスからの書き込みのみを許可 (読み取りはブロック)
‘ FileShare.Delete: 他のプロセスからの削除を許可
‘ FileShare.None: 他のプロセスからのアクセスを一切許可しない (排他ロック)

‘ 排他ロックをかける場合
fileStream = New FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)

‘ ここでファイルに対する処理を実行
‘ …

Catch ex As IOException
‘ ファイルがロックされているなどのエラー処理
Console.WriteLine(“ファイルアクセスエラー: ” & ex.Message)
Else
‘ 処理が成功した場合
Finally
‘ ファイルストリームを閉じる(ロック解除)
If fileStream IsNot Nothing Then
fileStream.Close()
fileStream.Dispose()
End If
End Try

VB.NETの利点:

  • 明確な排他制御: `FileShare.None` を指定することで、他のプロセスからのアクセスを完全にブロックし、確実な排他制御を実現できます。
  • 豊富なファイル操作: ファイルのコピー、移動、削除、ディレクトリ操作などが、より直感的かつ強力に行えます。
  • エラーハンドリングの強化: `try-catch-finally` ブロックにより、エラー発生時の処理を構造的に記述できます。

もし、より高度なファイル管理や、VBAでは実現しにくい複雑な処理を行いたい場合は、VB.NET(または他の.NET言語)との連携を検討する価値は十分にあります。例えば、VBAからVB.NETで作成したDLLを呼び出す、といった方法も可能です。

5. まとめ:Project VBAで「安全・安心」なリソース管理を!

今回は、Project VBAにおけるリソースプール共有の課題と、その解決策として「排他制御」と「バックアップ作成」の重要性、そして具体的なVBAコード例を解説しました。

  • ファイルロックの仕組みを理解し、他のユーザーとの競合を防ぐための排他制御を実装すること。
  • 万が一の事態に備えて、変更前に必ずバックアップを作成すること。
  • これらの処理をVBAで自動化することで、手作業によるミスを防ぎ、効率的かつ安全にリソースプールを管理できること。

これらのテクニックをマスターすれば、皆さんのプロジェクト管理は格段にスムーズになるはずです。

「マクロの記録」から一歩踏み出し、VBAの力を借りて、より堅牢で効率的なプロジェクト管理環境を構築していきましょう!

もし、「こんなケースはどうすればいい?」といった疑問や、「もっとこんな機能が欲しい!」といったリクエストがあれば、ぜひコメントで教えてくださいね。

それでは、また次回のProject VBAの世界でお会いしましょう!

タイトルとURLをコピーしました