Excel VBAを利用したテンプレートワードファイルの一部分の置換と保存処理の問題

このQ&Aのポイント
  • Excel VBAを利用して、テンプレートとなるワードファイルの一部分をエクセルデータで置換し、新しいワードファイルとして保存する処理を作成しています。しかし、最後の閉じる処理の際に「wordは、動作を停止しました」というエラーメッセージが頻繁に出てしまいます。処理自体に問題がある可能性があります。初心者なので、他に良い方法があれば教えてください。
  • Excel VBAを使って、テンプレートワードファイルの一部分をエクセルデータで置換し新しいワードファイルとして保存する処理を作成しました。しかし、閉じる処理の際に「wordは動作を停止しました」というエラーメッセージが頻繁に出てしまいます。ファイル自体は正常に読み込めるので、処理に問題がある可能性があります。初心者なので、改善策があれば教えてください。
  • Excel VBAを使って、テンプレートワードファイルの一部分をエクセルデータで置換し新しいワードファイルとして保存する処理を作成しました。しかし、最後の閉じる処理を行う際に「wordは、動作を停止しました」というエラーメッセージが頻繁に表示されます。処理自体に問題があるのか、他の方法で実現できるのか、初心者なのでわかりません。助言をいただけると幸いです。
回答を見る
  • ベストアンサー

excel VBAを利用し、テンプレートとなるワードファイルの一部分を

excel VBAを利用し、テンプレートとなるワードファイルの一部分をエクセルデータで 置換を行い、新しいワードファイルとして保存するという処理を作成しています。 [環境] Windows Vista Office 2007 差し込み文書ではなく個別にファイルを作りたいという条件があります。 処理としては、 テンプレートを開く→置換を実施→別名で保存→テンプレートを変更せず閉じる を繰り返し実施しています。 ただ、このやり方ですと最後の閉じる処理を行った際に、 「wordは、動作を停止しました」というエラーメッセージが頻繁に出てしまいます。 出来上がったファイル自体は問題なく読めているんですが。 処理自体に問題があるんでしょうか? VBA自体初心者であり、他に良い方法などありましたらご教示いただけたら助かります。 #処理内容はだいぶ簡略化しています。 Public Function output_word2()   Dim word        As New word.Application   Dim document      As word.document   Dim file_name      As String   Dim output       As String   Dim path        As String   Dim row        As Integer      Sheets(CALC_SHEET).Select 'データ取得用シート   path = Application.ActiveWorkbook.path   file_name = path & "\xxxxxx.doc"          '元の文書   row = 3   Do     If Range("B" & row).Value = "" Then       Exit Do     End If          With word       .Documents.Open Filename:=file_name       Set document = .ActiveDocument     End With          word.Selection.Find.Text = "{置換対象文字}"     word.Selection.Find.Forward = True     word.Selection.Find.Replacement.Text = Range("C" & row).Value     word.Selection.Find.Execute , , , , , , , , , , wdReplaceAll          output = path & "\output\" & Range("C" & row).Value  & ".doc"          document.SaveAs Filename:=output   '置換後のword文書を別名で保存     document.Close SaveChanges:=False     word.Quit     row = row + 1     Set word = Nothing     Set document = Nothing   Loop End Function

質問者が選んだベストアンサー

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.1

その元のコードは、癖になりますから、エラーが発生するとかいう以前に直した方がよいですね。時々、非VBAのプログラマの人にいますが、VBAは、ほとんど、予約語が存在しないので、変数名は、何でも付けられますが、それをそのまま使うと、他人からは、まったくコードを読めなくなってしまいます。エラーが発生しても原因がわかりにくくなります。 それから、ハングした後は、タスクマネージャーで、WinWord を削除しないと、エラーが繰り返すはずです。それで、メモリに残らないように、以下のように、エラーが発生したら、必ず、wdApp を外すようにします。 '//  Sub WordDocDupulicate()  Dim wdApp As Word.Application  Dim wdDoc As Word.Document  Dim wdRng As Word.Range  Dim Fname  As String  Dim sOutput As String    Dim mPath  As String  Dim mRow As Long  Dim sh As Worksheet  Set wdApp = New Word.Application    Const CALC_SHEET As String = "Sheet1" '←シート名  Set sh = Worksheets(CALC_SHEET) 'データ取得用シート  sh.Select    mPath = ActiveWorkbook.Path & "\"  Fname = mPath & "xxxxxx.doc"    sOutput = mPath & "\"  On Error GoTo ErrHandler  '元の文書  If Dir(Fname) = "" Then   MsgBox "元の文書がありません。", vbExclamation   GoTo ErrHandler  End If  mRow = 3  Do   With wdApp    Set wdDoc = .Documents.Open(Fname)    Set wdRng = wdDoc.Content   End With   With wdRng.Find    .Text = "[置換対象文字]"    .Forward = True    .Replacement.Text = Range("C" & mRow).Value    .MatchCase = False    .MatchWildcards = False    .MatchFuzzy = True    '.Execute Replace:=wdReplaceAll 'Ver Word2003    .Execute , , , , , , , , , , wdReplaceAll   End With   sOutput = mPath & "test1\" & Range("C" & mRow).Value & ".doc"   wdDoc.SaveAs sOutput '置換後のword文書を別名で保存   wdDoc.Close False   mRow = mRow + 1  Loop Until sh.Range("C" & mRow).Value = ""  wdApp.Quit ErrHandler:  If Err.Number > 0 Then   MsgBox Err.Number & " : " & Err.Description  Else   Beep '正常終了  End If  Set wdRng = Nothing  Set wdDoc = Nothing  Set wdApp = Nothing  Set sh = Nothing End Sub

nekomikekamo
質問者

お礼

修正ソースまで提示いただきありがとうございます。 VBAの例外処理など全く知らずに修正していた自分がちょっと怖くなりました@@; 知らない部分が多すぎて、前提が前提ではなくなっていました。 回答いただいたソースを元に修正をかけたところ 無事動作させることができました。 この度はご協力いただき、ありがとうございました。 VBAの奥深さも痛感いたしました・・。反省です。

その他の回答 (1)

  • mimeu
  • ベストアンサー率49% (39/79)
回答No.2

お役に立てるかどうかわかりませんが、ご質問で気がついた点を二つ。 (1) > 「wordは、動作を停止しました」というエラーメッセージが頻繁に出てしまいます。 とのことですが > word.Quit と Word を止めているからで、これは Loop 文の後に記述するべきです。 (2) Excel のC列に新しく保存する文書の名前が入っているから Excel VBA になさったのでしょうが、Word文書が対象ですから、Word VBA の方も トライなさることをおすすめします。世界が広がりますよ。

nekomikekamo
質問者

お礼

早速の回答ありがとうござました。 他の方の作成したVBAを修正していけるかと思って安易に考えていた部分があり、 VBAの奥深さを痛感いたしました。 きちんと学ばなければなりませんね^^; word.Quitの件、アドバイスいただいた通り(先のWendy02さんのアドバイスも含めて) 修正しましたところエラーの頻発はなくなりました。 この度は、アドバイス頂きありがとうございました。 無事解決することができました。

関連するQ&A

  • Excel VBA 引数が2個のマクロの呼び出し方

    ExcelのVBAで、 シート上のボタンがクリックされた時に呼び出す マクロ(プロシージャ)の引数が1個の時は、 コード1のようにできましたが、 引数が2個ある時は、コード2のように記述しても、 ボタンをクリックするとエラーになりますが、 【?】の部分をどのように記述すればよいのでしょうか。 (Windows10,Excel2010) -------------------コード1---------------------------------------- Sub test1()  Dim row As Integer  Dim wave_file_path As String  For row = 1 To 2   wave_file_path = ThisWorkbook.Worksheets("Sheet1").Cells(row, 1).Value   Call ボタン作成(row, wave_file_path)  Next row End Sub Sub ボタン作成(ByVal row As Integer, ByVal wave_file_path As String)  Dim cell_loc As String  cell_loc = ThisWorkbook.Worksheets("Sheet1").Cells(row, 3).Address  ThisWorkbook.Worksheets("Sheet1").Select  With ActiveSheet.Buttons.Add(Range(cell_loc).Left, _   Range(cell_loc).Top, _   Range(cell_loc).Width, _   Range(cell_loc).Height)   .name = "ボタン_" & cell_loc   .OnAction = "'WAVE_PLAY """ & wave_file_path & "" & "'"   .Characters.Text = "再生"  End With End Sub Sub WAVE_PLAY(ByVal wave_file_path As String)  If Dir(wave_file_path) = "" Then   MsgBox wave_file_path & vbCrLf & "がありません。", vbExclamation   Exit Sub  End If  Shell "C:\Program Files\Windows Media Player\wmplayer.exe /play /close " & wave_file_path End Sub ------------------------------------------------------------------- -------------------コード2---------------------------------------- Sub test2()  Dim row As Integer  Dim wave_file_path As String  For row = 1 To 2   wave_file_path = ThisWorkbook.Worksheets("Sheet1").Cells(row, 1).Value   Call ボタン作成(row, wave_file_path)  Next row End Sub Sub ボタン作成(ByVal row As Integer, ByVal wave_file_path As String)  Dim cell_loc As String  cell_loc = ThisWorkbook.Worksheets("Sheet1").Cells(row, 3).Address  ThisWorkbook.Worksheets("Sheet1").Select  With ActiveSheet.Buttons.Add(Range(cell_loc).Left, _   Range(cell_loc).Top, _   Range(cell_loc).Width, _   Range(cell_loc).Height)   .name = "ボタン_" & cell_loc   .OnAction = "'WAVE_PLAY """ & wave_file_path & "" & "," & row & "'" <==【?】   .Characters.Text = "再生"  End With End Sub Sub WAVE_PLAY(ByVal wave_file_path As String, ByVal row As Integer)  If Dir(wave_file_path) = "" Then   MsgBox wave_file_path & vbCrLf & "がありません。", vbExclamation   Exit Sub  End If  Shell "C:\Program Files\Windows Media Player\wmplayer.exe /play /close " & wave_file_path  ThisWorkbook.Worksheets("Sheet1").Cells(row, 4).Value = "再生済" End Sub -------------------------------------------------------------------

  • Excel シートにボタンを作成するVBA

    ExcelシートのA列にWAVEファイルのフルパス名が書かれている状態で、 このWAVEファイルを再生するボタンをC列に作成するVBAを作りたいのですが、 ボタンが押されたときに実行されるプロシージャに引数がないときは、 コード1のようにすればできますが、 ボタンが押されたときに実行されるプロシージャに引数があるときは、 コード2のように記述してもエラーになりますが、 どのように記述すればよいのでしょうか。(Windows10,Excel2010) '-----------------コード1------------------------------------------ Sub test()  Dim row As Integer  Dim wave_file_path As String  row = 1  wave_file_path = ThisWorkbook.Worksheets("Sheet1").Cells(row, 1).Value  Call 再生ボタン作成(row, wave_file_path) End Sub Sub 再生ボタン作成(ByVal row As Integer, ByVal wave_file_path As String)  Dim cell_loc As String  cell_loc = ThisWorkbook.Worksheets("Sheet1").Cells(row, 3).Address  ThisWorkbook.Worksheets("Sheet1").Select  With ActiveSheet.Buttons.Add(Range(cell_loc).Left, _   Range(cell_loc).Top, _   Range(cell_loc).Width, _   Range(cell_loc).Height)   .name = "ボタン_" & cell_loc   .OnAction = "WAVE_PLAY"   .Characters.Text = "再生"  End With End Sub Sub WAVE_PLAY()  Dim wave_file_path As String  wave_file_path = "Z:\Document\4_Data\CD_DVD_USB\USB_20200222\REC\JBP001\JBP00101.WAV"  If Dir(wave_file_path) = "" Then   MsgBox wave_file_path & vbCrLf & "がありません。", vbExclamation   Exit Sub  End If  Shell "C:\Program Files\Windows Media Player\wmplayer.exe /play /close " & wave_file_path End Sub '------------------------------------------------------------------- '-------------------コード2---------------------------------------- Sub test()  Dim row As Integer  Dim wave_file_path As String  For row = 1 To 100   wave_file_path = ThisWorkbook.Worksheets("Sheet1").Cells(row, 1).Value   Call 再生ボタン作成(row, wave_file_path)  Next row End Sub Sub 再生ボタン作成(ByVal row As Integer, ByVal wave_file_path As String)  Dim cell_loc As String  cell_loc = ThisWorkbook.Worksheets("Sheet1").Cells(row, 3).Address  ThisWorkbook.Worksheets("Sheet1").Select  With ActiveSheet.Buttons.Add(Range(cell_loc).Left, _   Range(cell_loc).Top, _   Range(cell_loc).Width, _   Range(cell_loc).Height)   .name = "ボタン_" & cell_loc   .OnAction = "WAVE_PLAY " & wave_file_path ' <==== ◆ここでエラーになります◆   .Characters.Text = "再生"  End With End Sub Sub WAVE_PLAY(ByVal wave_file_path As String)  If Dir(wave_file_path) = "" Then   MsgBox wave_file_path & vbCrLf & "がありません。", vbExclamation  Exit Sub  End If  Shell "C:\Program Files\Windows Media Player\wmplayer.exe /play /close " & wave_file_path End Sub '-------------------------------------------------------------------

  • エクセルVBAの実行スピードが落ちます

    エクセルで検索を行うVBAを使用していますが、エクセル立ち上げ時はサクサク動きますが、検索を繰り返し使っていくと、実行速度が落ちてしまいます。 エクセルを再起動すれば、元どおりの速さに戻ります。 何が原因でしょうか?どうすれば防ぐことはできるでしょうか? よろしくお願い申し上げます。 実行環境 WindowsXPproSP3 Pen4 3.0Ghz メモリ1GB HDD80GB Office2003 VBAの検索部分 Function Kensaku3(Key1 As String, Range1 As String) As Long '縦方向の検索   Dim myRng As Range   Dim Job1 As String   Dim Col1 As Long   Dim Row1 As Long   Col1 = Range(Range1).Column   Row1 = Range(Range1).row   Cells(Row1, Col1).Select   Set myRng = Range(Range1).Find(what:=Key1, _     After:=ActiveCell, LookIn:=xlValues, _     LookAt:=xlPart, SearchOrder:=xlByRows, _     SearchDirection:=xlNext, MatchCase:=False)   If myRng Is Nothing Then     Kensaku3 = 0   Else     Kensaku3 = myRng.row   End If   Set myRng = Nothing End Function

  • ワード VBA

    ワードのマクロについて教えてください。 以下のようなマクロをボタンに登録しています。 Sub Macro10() Dim myReg As Object Dim st As String Dim match As Variant Set myReg = CreateObject("VBScript.Regexp") myReg.Pattern = "\x0d\x0d(|$)" myReg.Global = True st = ActiveDocument.Range.Text ActiveDocument.Range(1, 1).Select For Each match In myReg.Execute(st) With Selection .Find.Text = match.Value .Find.Replacement.Text = vbCr .Find.Execute , , , , , , , , , , wdReplaceAll End With Next st = ActiveDocument.Range.Text If myReg.Test(st) Then _ ActiveDocument.Range.Text = myReg.Replace(st, "") Set myReg = Nothing End Sub ここで教えていただきたいのは,上記のマクロを実行するためにボタンを押した際,実行前にカーソルが置かれていたのと同一の場所に実行後のカーソルを戻す方法です。(ちなにみ上記のマクロを実行する際にカーソルが置かれているのは,空白行ではない行の先頭です。※処理とは関係ないかもしれませんが,念のために。) そのような処理を行うには,上記のマクロにどのような記述を追加すればよいのでしょうか。 どなたかご教示いただければと思います。 どうぞよろしくお願いいたします。

  • Excel VBAで呼び出したWordが文書への差し込みボタンが効かない状態で開く

    以下のExcel VBAでWordは開くのですが、新規文書への差し込みボタンが、活きていないです。参照設定は、Microsoft Word 11.0 Object Libraryを入れています。 どうしたらいいのでしょうか?困っています。 Sub Wordを開き、差し込み印刷する() Dim ワード As Object Dim ワード文書 As Object Dim フルパス As String フルパス = "D:\案内状.doc"          'フルパスを作成 Set ワード = CreateObject("Word.Application") 'Wordを起動 ワード.Visible =True 'Wordを表示 Set ワード文書 = ワード.documents.Open(フルパス) 'Word文書を開く End Sub

  • エクセルVBA どうしても処理が重いのを改善したい

    下記のコードを作りましたが、どうしても処理が2分を越えてしまいます。 書き方が下手なのか。。。修正案があればぜひともご教授願います。 行っている事は。。。 1.上から順番に最後の文字が入っている所まで検索をする。 2.1の際A2とA3セル内容を取得する。(この際にA2セルに入っているドメイン取得している)この取得した値を検索元のデータとしている。 3.2にて取得したデータを元に、検索対象セルの次行から一致する値を検索する。 4.ヒットしたら、ヒットした値がある行のE列に「1」を代入 5.全ての処理が終了したら、E列に「1」がある行全て削除 6.フィルター解除 Sub 案件抽出の重複削除() Debug.Print Time & " - 案件抽出の重複削除スタート" Application.ScreenUpdating = False Application.Calculation = xlCalculationManual Dim s As String '// 検索元データ Dim i As Long Dim SI As String '// 検索元データの結合データ Dim TD As String Dim SS As String Dim II As Long Dim AJS As Range '// 検索元データのステートメント Dim CAJS As Range '// 検索されるデータのステートメント On Error Resume Next For Each AJS In Range("A2:A" & Cells(100000, 1).End(xlUp).Row) s = Cells(AJS.Row, 2) i = InStrRev(s, "@") + 1 SI = Mid(s, i, Len(s) - i) & Cells(AJS.Row, 3) For Each CAJS In Range(Cells(AJS.Row + 1, 2), Cells(Rows.Count, 1).End(xlUp)) If Cells(CAJS.Row, 5) = "" Then SS = Cells(CAJS.Row, 2) II = InStrRev(SS, "@") + 1 TD = Mid(SS, II, Len(SS) - i) & Cells(CAJS.Row, 3) If SI = TD Then Cells(CAJS.Row, 5) = 1 End If TD = "" End If Next Next ActiveSheet.Range("$A$1:$E$2564").AutoFilter Field:=5, Criteria1:="1" Rows(2).Select Range(Selection, Selection.End(xlDown)).Select Selection.Delete Shift:=xlUp Selection.End(xlUp).Select ActiveSheet.AutoFilterMode = False Debug.Print Time & " - 案件抽出の重複削除終了" End Sub 宜しくお願い致します。

  • vbaでメモリ不足となる原因は?

    ワードのマクロを使って、tifファイル500個ほどを読み込もうとしたところ、読み込みの途中で「メモリ不足です」というメッセージが表示されます。 タスクマネージャで確認すると、たしかに50ファイルほど読み込んだところでメモリが2Gを超えてしまっていました。 メモリ不足になる原因と、解決方法を教えていただけますか? ご参考までに作成したマクロと使用しているPCのスペックを追記します。 Sub Macro1() Dim file_path As String Dim file_name As String Dim I As Integer file_path = "C:\Documents and Settings\user\デスクトップ\説明書\ページ" For I = 1 To 500 file_name = file_path + StrConv(I, 1) + ".tif" With ActiveDocument.Shapes.AddPicture(Anchor:=Selection.Range, FileName:= _ file_name, LinkToFile:=False, SaveWithDocument:=True) .WrapFormat.Type = 3 .ZOrder 5 End With Selection.EndKey Unit:=wdStory Selection.InsertBreak Type:=wdPageBreak Next I End Sub PCのスペック OS:Windows XP メモリ:2G word:2003 よろしくお願いします。

  • ExcelのVBA ListBox.RowSourceの範囲について教えてください。

    下記のように範囲を変数で検索指定したいのですが、うまくいきません。VBAは初心者です。誰か助けて。 内容は・・・五十音順にあるリストを作り、ウ音のみをListBoxに表示したいのですが。 Private Sub ToggleButton3_Click() Dim A As Range Dim BBB As String Dim C As Range Dim DDD As String Set A = Cells.Find(what:="ウ", lookat:=xlWhole) BBB = Cells(A.row, A.Column + 1).Address Set C = Cells.Find(what:="エ", lookat:=xlWhole) DDD = Cells(C.row - 1, C.Column + 1).Address ListBox商品名.RowSource = "BBB:DDD" End Sub PS 違う方法でもいいのでどなたか教えてください。

  • VBAでExcelのセルの一覧からファイル名の変更が

    こんにちは。会社で大量のファイル名を変更していますが、Excelで一覧からを変更できれば能率的なので作っていますが、困っています。下記のものです。 Sub リネーム() Dim i As Long  Dim NEWファイル As String  Dim OLDファイル As String  Dim パス As String For i = 1 To Range("B65536").End(xlUp).Row パス = Cells(2, 1).Value OLDファイル = パス & Cells(i, 2).Value NEWファイル = パス & Cells(i, 3).Value If Dir(OLDファイル) <> "" Then Name OLDファイル As NEWファイル End If Next i End Sub ※A2にはC:\Documents and Settings\M.Co,\デスクトップ\リネームと入っています。B1には変更前の001.jpg、C1には変更するa-1.jpgとファイル名が入っています。実行してもファイル名は変更されません。エラーもでません。よろしくお願いします。

  • VBAで、エクセルからワードへの変換について

    VBAは、全くの初心者で、テキスト等のサンプルコードを参照して書いているのですが 期待通りの動きをしないので、教えてください。 やりたい事は、Excelファイル(A-Fカラム、400行程度)を 1行ページのワードに変換し、400枚のワードファイルを作成します。 その際に、添付画面のように、各カラムを、タイトル、連番、内容などと区分けをして フォントも変えたいです。 下のコードでは、転送は、出来るのですが、1行1ページにならず、また、 エクセルの枠も転送されてしまいます。 ワードVBAも試したのですが、特定文字での検索が難しく、各ページでの 改行位置が異なるため、自分の理解では出来ませんでした。 ワードでテンプレートを作って、Excel VBAから差込になるのでしょうか? よろしくお願い致します。 Sub CopyExcelDataToWord() Dim wsSource As Excel.Worksheet Dim cell As Excel.Range Dim collUniqueHeadings As Collection Dim lngLastRow As Long Dim i As Long Dim appWord As Word.Application Dim docWordTarget As Word.Document Set wsSource = ThisWorkbook.Worksheets(1) With wsSource lngLastRow = .Range("A" & Rows.Count).End(xlUp).Row Set collUniqueHeadings = New Collection For Each cell In .Range("A2:A" & lngLastRow) On Error Resume Next collUniqueHeadings.Add Item:=cell.Value, Key:=cell.Value On Error GoTo 0 Next cell End With Set appWord = CreateObject("Word.Application") With appWord .Visible = True Set docWordTarget = .Documents.Add .ActiveDocument.Select End With For i = 1 To collUniqueHeadings.Count With wsSource .Range("A1").AutoFilter Field:=1, Criteria1:=collUniqueHeadings(i) .Range("A1:D" & lngLastRow).Copy End With With appWord.Selection .PasteExcelTable linkedtoexcel:=False, wordformatting:=True, RTF:=False .TypeParagraph End With Next i For i = 1 To collUniqueHeadings.Count collUniqueHeadings.Remove 1 Next i Set docWordTarget = Nothing Set appWord = Nothing End Sub

専門家に質問してみよう