社内でワードとエクセルを使い分けることがあると思います。エクセルに統一すればいいですが、そうとはいかない場合にはワードの内容を自動で転記しましょう。今回はワード形式での申請書をエクセル台帳に転記する方法です。
挙動
社内のDX勉強会参加のワード形式の申請書をエクセル台帳に転記するという、無さそうで在りそうな題材です。
ワードの内容をエクセルに転記する必要がある場合には、紹介のマクロを一部変更すれば応用できます。
コード
プロシージャ:ワードから台帳転記()を親に、ワード転記、ファイル作成等をしています。
ワードから台帳転記のコード
Option Explicit
Public OKdate As String, wd As Word.Application, doc As Word.Document
Sub ワードから台帳転記()
Dim parts As String, ファイル保管場所 As String
'記載元のワードが保存されたパスを入力。このマクロではデスクトップの想定です。
ファイル保管場所 = Environ("USERPROFILE") & "\Desktop"
Call 申請登録
If OKdate = "" Then Exit Sub
If MsgBox("フォルダ作成保管", vbYesNo + vbSystemModal) = vbYes Then
'フォルダの作成と保管
If Dir(ファイル保管場所 & "\" & OKdate, vbDirectory) <> "" Then
MsgBox "フォルダ作成できませんでした。すでにフォルダがある可能性があります。"
Else
MkDir (ファイル保管場所 & "\" & OKdate)
'引数にパスワード設定すれば,保護もできます。
'doc.Protect wdAllowOnlyReading
doc.SaveAs2 ファイル保管場所 & "\" & OKdate & "\" & doc.Name
End If
End If
End Sub
Sub 申請登録()
Dim yymm As String, mm As String, 連番 As String, pnt As Range
Dim plant As String, r As Long, i As Long, cel13 As String
Dim wdname As String
Set wd = New Word.Application 'ここでエラー
Dim prg As Long, rng0 As Variant
Worksheets(1).Activate
' 台帳から承認Noを取得設定
Set pnt = Worksheets(1).Range("A" & Rows.Count).End(xlUp).Offset(1)
yymm = Format(CStr(Date), "yymm")
' 新しい月の場合
If yymm <> Mid(pnt.Offset(-1).Value, 4, 4) Then
OKdate = "ABC" & yymm & "01"
pnt = OKdate
' その月の場合
Else
連番 = Format(Val(Mid(pnt.Offset(-1).Value, 8)) + 1, "00")
OKdate = "ABC" & yymm & 連番
pnt = OKdate
End If
' ワードを開き、承認No記入と台帳へのコピペ
wdname = Application.GetOpenFilename
If wdname = "False" Or wdname = "" Then Exit Sub
On Error Resume Next
Set doc = wd.Documents.Open(wdname, , True)
If doc Is Nothing Then Exit Sub
wd.Visible = True
doc.Paragraphs(4).Range.Select
wd.Selection.InsertAfter OKdate
On Error GoTo 0
' 台帳へ転記
' 発行番号
pnt.Offset(, 2) = doc.Paragraphs(kensaku("*発*行*番*号") + 1).Range
' 発行日
pnt.Offset(, 1) = doc.Paragraphs(7).Range
If InStr(1, pnt, " ", vbTextCompare) <> 0 Then
pnt.Offset(, 1) = Replace(pnt, " ", "", , , vbTextCompare)
End If
' 会社
On Error Resume Next
plant = doc.Paragraphs(kensaku("所*属*") + 1).Range
pnt.Offset(, 3) = plant
' 所属部門、課
pnt.Offset(, 5) = Left(doc.Paragraphs(kensaku("*部門*") + 1).Range, _
VBA.InStr(doc.Paragraphs(kensaku("*部門*") + 1).Range, "/", , vbTextCompare) - 1)
pnt.Offset(, 6) = Mid(doc.Paragraphs(kensaku("*部門*") + 1).Range, _
VBA.InStr(doc.Paragraphs(kensaku("*部門*") + 1).Range, "/", , vbTextCompare) + 1)
' 氏名
pnt.Offset(, 4) = doc.Paragraphs(kensaku("氏*名") + 1).Range
' 理由
pnt.Offset(, 7) = doc.Range(doc.Paragraphs(kensaku("理*由") + 1).Range.Start, _
doc.Paragraphs(kensaku("採*用*") - 1).Range.End)
' 文章内の改行削除
r = pnt.Row
For i = 2 To 28
Cells(r, i) = WorksheetFunction.Clean(Replace(Cells(r, i), " ", "", , , vbTextCompare))
Next
' Wordの許可に丸を付ける
Dim shape As Object
Set shape = doc.Shapes.AddShape(Type:=msoShapeOval, _
Left:=440, _
Top:=105, _
Width:=20, _
Height:=20)
shape.Fill.Visible = msoFalse ' 塗りつぶしなし
shape.WrapFormat.Type = wdWrapBehind ' テキストとの折り返しを「背面」に設定
On Error GoTo 0
End Sub
Function kensaku(検索値 As String)
Dim prg0 As Variant, prg As Long
Dim rng As Object
Dim firstSectionRange As Object
Dim startPos As Long
' 最初のセクションの範囲を取得
Set firstSectionRange = doc.Sections(1).Range
' 最初の段落を除外するために開始位置を調整
startPos = firstSectionRange.Paragraphs(1).Range.End
Set rng = doc.Range(startPos, firstSectionRange.End)
' 最初のセクション内で検索を実行
'Set rng = firstSectionRange.Duplicate ' 元の範囲を複製するやり方もあります。(参考)
With rng.Find
' ドキュメント指定範囲から検索
.Text = 検索値
.MatchFuzzy = False
.MatchWildcards = True
If .Execute Then
' 検索結果が見つかった場合の処理
Set prg0 = doc.Range(.Parent.Start, .Parent.End)
prg0.Start = 0 ' 開始位置をドキュメントの先頭にリセット
prg = prg0.Paragraphs.Count
Else
' 検索結果が見つからなかった場合
prg = -1 ' 見つからなかった場合の返却値(任意で変更可能)
End If
End With
' 結果を返す
kensaku = prg
End Function
また今回使用したワードの様式は下記です。
ポイント機能
ざっとした挙動は以下です。
・エクセル台帳から、"yymm"+連番で承認番号を採番し、転記元ワードに番号を転記。
・台帳の項目文字列を転記元ワードから検索して情報記載の段落を取得し、台帳に転記。
・デスクトップに採番で保管フォルダを作成し、ワードを保管。
・転記元ワードの承認の箇所に円形図形を挿入する。
"yymm"+連番で承認番号を採番
250101や251231のような、年の下二桁+採番した二桁の月+その月に採番した連番のような番号を取得するケースに対応しています。
台帳に記載された承認番号から、現在の日付をもとに採番します。
例えば、台帳にすでに250401と記載されている場合での4月と5月実施した際の挙動は下記となります。
・今日が2025年4月31日の場合・・・連番は250402となります。
・今日が2025年5月1日の場合・・・連番は250501となります。
ワード内文字検索関数
kensaku関数を使い、引数に入れた文字をワードから検索します。見つかった文字のワード内でのパラグラフ(絶対的な位置)を取得します。その後パラグラフに+1をすることで、表形式のワードから項目に記載された値を取得できます。

' 最初のセクションの範囲を取得Set firstSectionRange = doc.Sections(1).Range ここでは、ワード申請書の一ページ目を対象範囲としています。
' 最初の段落を除外するために開始位置を調整
startPos = firstSectionRange.Paragraphs(1).Range.End
Set rng = doc.Range(startPos, firstSectionRange.End)
doc.Content.Selectで文書全体を選択し、wd.Selection.Collapse wdCollapseStartにて選択解除+カーソル選択肢地をワード文書の一番初め=rangeでいう0の位置に移動させる方法もありますが、全体を選択するという処理によ処理速度が落ちます。その為、ワード一ページ目の範囲を直接指定し、検索をかけています。
その後、ワードで指定ワードを検索します。その際の関数が、Find関数です。下記は基本的なプロパティと設定です。

引数の検索文字を見つけたら、rangeをオブジェクト変数rng0に代入します。

該当文字のrangeをrng0に代入し、rng0.start = 0 を設定することで、変数のrangeを0から見つかった範囲までに設定します。
そこからrng0.paragraph.countとすることで見つかった検索文字の絶対的位置を取得できます。+1をすることでその右側にある値(取得したい値)を取得できます。
ワードに「氏 名」があれば、下記で取得できます。(ワードでは「氏 名」と隙間があるため、ワイルドカードを使用)。
' 氏名
pnt.Offset(, 4) = doc.Paragraphs(kensaku("氏*名") + 1).Range
保管フォルダを作成と保管
最終的にワード申請書はデスクトップのフォルダに保管されます。ここでは「Environ」を使用し、動的なデスクトップパスを取得しています。

「Environ」はプログラミングにおいて環境変数を扱うために使用されます。
環境変数とは、OSが管理する設定情報で、プログラムの動作に影響を与える変数です。環境変数には様々あり、ホームディレクトリのパスや言語設定などが環境変数として保存されています。VBAで使用することで、どの環境でも動的な動作が期待できます。
環境変数の例:
MsgBox Environ("USERNAME") ' ログインユーザー名を取得
MsgBox Environ("COMPUTERNAME") ' コンピュータ名を取得
MsgBox Environ("TEMP") ' 一時ファイルの保存場所を取得
上記のデスクトップパスをファイル保管場所変数に入れ、MkDirでファイル作成、その後保管しています。

転記元ワードの承認の箇所に円形図形を挿入
ワードでの図形はdocumentのShapesプロパティで操作が可能です。今回は図形を追加するため、AddShapeメソッドを使います。

引数としては主に4種類で、図形の種類、位置(左と上の位置)、大きさ(横と高さ)を設定します。
Set shape = doc.Shapes.AddShape( Type:=msoShapeOval, _
Left:=440, _
Top:=105, _
Width:=20, _
Height:=20)
対象の文書で挿入したい位置に応じて値を変更可能です。
選択位置の座標は下記スクリプトで取得できます。下記では対象文書の選択された位置の左右位置、幅、高さを取得できます。(参考:Window.GetPoint メソッド (Word) | Microsoft Learn)
Sub 位置取得()
Dim pLeft As Long
Dim pTop As Long
Dim pWidth As Long
Dim pHeight As Long
ActiveWindow.GetPoint pLeft, pTop, pWidth, pHeight, _
Selection.Range
MsgBox "Left = " & pLeft & vbLf _
& "Top = " & pTop & vbLf _
& "Width = " & pWidth & vbLf _
& "Height = " & pHeight
End Sub