##エクセルを別プロセスで開きたい
日々の業務の中で、何個もエクセルを開いて作業をしている方は多いのではないでしょうか。私も日次の集計・分析作業があり10個以上のエクセルを開いて業務をしています。
効率よく作業を行うために考えたのが、エクセルが開く仕組みを知ることでした。
どういうことかというと、エクセルは普通に何個も開くと同じプロセス内で開かれています。A,B,Cのエクセルを開いているとしてAで重たいマクロを実行しているとAのマクロが終わらない限りはB,Cの操作ができません。
分かりやすく例えると、船が一隻あります。
その中に乗組員が4名いるとします。全員男性としましょう。船の中にはトイレが1個しかありません
。たまたま全員が同じタイミングで用を足したくなりました。さあどうしますか。全員が一斉にトイレでするという荒業はさておき、順番に並んで前の人が終わったら次の人というような流れになりますよね。
もし、トイレが4つあればすべて解決です
。
そう、私たちが日々エクセルで並行して作業する場合は作業分トイレを用意すればよいのです(違う)
##別プロセスってどんな感じ??
試しに何個かエクセルを開いた後に、タスクマネージャーを開いて確認してみてください。
こんな感じになっているかと思います。
黄色く(汚くてすみません)ハイライトしたように(4)となっています。これは4つのエクセルが同じプロセスで開いていることになります。
ではどうなればよいのか。
以下のようになれば別プロセスで開いていることになります。
いかがでしょうか。図1ではタスクの終了をすると開かれているエクセルが全部閉じてしまいます。
図2の場合は複数のエクセルが独立しています。
この状態になれば、並行して作業をしても問題ありません。
先ほどのトイレが4つあるので待つ必要はない状態と同じです。
##エクセルを作業する分一気に開きたい。
そんなマクロを作成してみます。
完成形はこんな感じです。
A列 | B列 | C列 | D列 | E列 |
---|---|---|---|---|
ディレクトリのパス | ファイル名 | 開く対象 | 結果 | 備考 |
このようになっています。
あらかじめA列B列C列を入れておき、ボタンを押下して実行する。
完了やエラーはD列に表示する。 E列は備考なのでVBAのマクロにはなりません。
まずはこれらのサンプルコードをいかに貼ります。
リファクタリング要素は多いのでご了承ください。。。
別プロセスで開く点に集中して解説したいと思います。
Public mySheet As Worksheet
'ファイルパスの読み取り開始行
Const COUNT_START_ROW = 5 '開始セル行
'グレー色にしているセルには数式が入っています。 3行目は変更禁止
Const IN_FUNCTION_ROW = 3 '対象を数える数式が入っているセル(行数)
Const IN_FUNCTION_COUNT_OPEN_CHECK_COLUMN = 3 '対象を数える数式が入っているセル(列数)
Const IN_FUNCTIION_READ_ONLY_CHECK_COLUMN = 1 '読み取り専用で開くかどうかを確認する式が入っている列数
Const IN_FILE_PATH_COLUMN = 1 'ファイルのパスが入っているセルの列数
Const IN_FILE_NAME_COLUMN = 2 'ファイル名が入っているセルの列数
Const OPEN_CHECK_COLUMN = 3 'ファイルを開く対象を判別する■が入っている列数
Const RESULT_MSG_COLUMN = 4 '結果を表示する列数
Public Sub init()
Set mySheet = ActiveSheet
End Sub
Sub OpenSepProSample()
Call init
Call resultMsgClear
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim filePath As String
Dim myApp As Excel.Application
Dim yesNo As Integer
Dim openCheck As String
Dim readOnlyCheck As String
Dim inFunctionRow As Integer
inFunctionRow = IN_FUNCTION_ROW
'ファイルを読み取りで開くかどうかのチェック
Dim inFunctionReadOnlyCol As Integer
inFunctionReadOnlyCol = IN_FUNCTIION_READ_ONLY_CHECK_COLUMN
'Trueかfalseの文字列を格納
readOnlyCheck = mySheet.Cells(inFunctionRow, inFunctionReadOnlyCol).Value
'実行の確認
Dim inFunctionCheckOpenCol As Integer
inFunctionCheckOpenCol = IN_FUNCTION_COUNT_OPEN_CHECK_COLUMN
mySheet.Cells(inFunctionRow, inFunctionCheckOpenCol).Formula = "=COUNTA(C5:C1048576)"
If mySheet.Cells(inFunctionRow, inFunctionCheckOpenCol) = 0 Then
MsgBox "対象ファイルを1つ以上選択してください。"
Exit Sub
Else
yesNo = MsgBox("対象のファイルをすべて開きますか。", vbYesNo + vbQuestion, "実行の確認")
If yesNo = vbYes Then
'ファイルを開く処理
'セルA5から一覧記載 ループ処理
Dim targetSearchRow As Integer
Dim filePathColumn As Integer
Dim fileNameColumn As Integer
Dim openCheckCoumn As Integer
Dim resultMsgColumn As Integer
targetSearchRow = COUNT_START_ROW '検索開始行
filePathColumn = IN_FILE_PATH_COLUMN
fileNameColumn = IN_FILE_NAME_COLUMN
openCheckCoumn = OPEN_CHECK_COLUMN
resultMsgColumn = RESULT_MSG_COLUMN
Dim openCheckCountNum As Integer
Dim loopNum As Integer
openCheckCountNum = 0
loopNum = mySheet.Cells(inFunctionRow, inFunctionCheckOpenCol)
'Do While Cells(targetSearchRow, filePathColumn) <> ""
Do While (openCheckCountNum < loopNum)
Set myApp = CreateObject("Excel.Application")
filePath = mySheet.Cells(targetSearchRow, filePathColumn).Value
Filename = mySheet.Cells(targetSearchRow, fileNameColumn).Value
fileFull = filePath & "\" & Filename
'Debug.Print fileFull
openCheck = mySheet.Cells(targetSearchRow, openCheckCoumn).Value 'B列
'B列に■が入っているファイルを開く
If openCheck = "■" Then
openCheckCountNum = openCheckCountNum + 1
'パスが見つからない場合は①のエラー分へ文岐する。
If filePath <> "" Then
If Filename <> "" Then
If Dir(fileFull) <> "" Then
myApp.Workbooks.Open fileFull, ReadOnly:=readOnlyCheck
myApp.Visible = True
mySheet.Cells(targetSearchRow, resultMsgColumn).Value = "完了"
Set myApp = Nothing
Else
'ファイルパス+ファイル名で検索できなかった場合のエラー処理
mySheet.Cells(targetSearchRow, resultMsgColumn).Value = "ファイルパスが不正です。"
End If
Else
'ファイル名のセルが空だった場合のエラー処理
mySheet.Cells(targetSearchRow, resultMsgColumn).Value = "ファイル名の指定がありません。"
End If
Else
'ファイルパスのセルが空だった場合のエラー処理
mySheet.Cells(targetSearchRow, resultMsgColumn).Value = "パスの指定がありません。"
End If
End If
'■が入っていないセルは飛ばし下のセルへ移動する。
targetSearchRow = targetSearchRow + 1
Loop
'ループの終了
'MsgBox "ファイルをすべて開きました。"
Else
'マクロ起動時のYes/NoボタンのNoが押された場合の処理
MsgBox "終了します。"
End If
End If
End Sub
Public Sub resultMsgClear()
ActiveSheet.Range("D5:D3000").ClearContents
End Sub
ざっとこれです。
コピペで使えると思います。
今回の記事のメインであるエクセル別プロセスのコードは以下です。
'CreateObject("Excel.Application")を宣言し変数を作成します。
Set myApp = CreateObject("Excel.Application")
'以下のコードがエクセルを別プロセスで開くための肝になる点です。
myApp.Workbooks.Open "開く対象のファイルのフルパス" '※オプション指定も可能
作業用エクセルの一覧があると効率も上がると思いますので
ぜひ活用してみてください!