Word (一般機能)

Wordの一般機能に関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 7 Professional : Word 2010)
表の空白行を削除したい
投稿日時: 19/06/13 10:27:26
投稿者: 花野

以下について何か方法がありましたら、教えてください。
 
WORDの表、各セルに差込印刷を行っています。
表の差し込みデータは1ページにつき最大15件、最少は1件なので、表は1列×15行を作成し
それぞれデータを差し込みました。
 
その際、データが1件の場合は、表に1行のみデータが挿入され、2〜15行のセルは空白の行となります。
この空白行を手作業で1件1件削除する以外に、なにか一括で削除する方法はないでしょうか。
数百ページなので、手作業でできないことはありませんが、今後ページ数が増えた場合
他に方法があるようでしたらお聞きしたく質問しました。
なお、文書の表をなくすということはできないのです。(フォーマットが決められています)
宜しくお願いいたします。

回答
投稿日時: 19/06/13 17:50:44
投稿者: Suzu

Word を使わないといけないのでしょうか。
 
Excelのリストが既にあるのであれば、ピボットテーブルで出力したいページレイアウトにできませんでしょうか。
 
出来たのなら、改ページを入れたいフィールドを選択した状態で
「フィールドの設定」の レイアウトと印刷 の アイテムの後ろに改ページを入れるにチェック
 
で、希望のレイアウトに近くなりませんか?

投稿日時: 19/06/14 09:05:20
投稿者: 花野

Suzuさん、アドバイスありがとうございます。
 
WORDで作成しているのは、表の前後に長い文章が入っていて、その体裁を整えるのに
便利だからという理由だと思います。
文書は他の者が作っており、差込部分だけやり方が分からないとのことで、
作成をお願いされています。
 
担当者とも相談し、対応できるかどうか確認してみます。

回答
投稿日時: 19/06/14 15:28:42
投稿者: sk

引用:
WORDの表、各セルに差込印刷を行っています。
表の差し込みデータは1ページにつき最大15件、最少は1件なので、表は1列×15行を作成し
それぞれデータを差し込みました。

フィールドコードを使用して、一定のグループごとに
改ページが行なわれるようにしている、ということでしょうか。
 
引用:
この空白行を手作業で1件1件削除する以外に、
なにか一括で削除する方法はないでしょうか。

・差し込みを実行して生成された文書上にある
 全ての表から全ての空白行を削除する VBA のコードを実行する。
 
・最初から 15 行固定の表を設けるのではなく、
 差し込み実行時に異なる行数の表がページごとに
 生成される仕組みを構築する。
 (例えばフィールドコード DATABASE を使うなど)
 
今のところ考えられるのは以上の 2 つ。
 
引用:
なお、文書の表をなくすということはできないのです。
(フォーマットが決められています)

仮に後者を採用する場合、表のフォーマットについて
特に拘らないのであれば、VBA なしでも一応は実行可能なはずですが、
表のフォーマットがガチガチにカスタマイズされている
ということであれば、そうもいかないでしょうね。
(データソースの種類の問題もありますし)

投稿日時: 19/06/14 16:55:15
投稿者: 花野

skさん、アドバイスありがとうございます。
 
表の差し込みは、フィールドコードを使用して、一定のグループごとに
改ページが行なわれるようにしています。
 

引用:
差し込みを実行して生成された文書上にある
 全ての表から全ての空白行を削除する VBA のコードを実行する。

 
VBAは触ったことがなく、とりあえずどのようにすればよいか検索し、試にマクロの記録を
行ったのですが、その行が空白であることをどうやって調べるかもわからず、
以下のマクロの記録で予め選択した行を削除することしかできませんでした。
 
Sub Macro1()
'
' Macro1 Macro
'
'
    Selection.Rows.Delete
End Sub
 
VBAで削除はハードルが高いです。
 
引用:
最初から 15 行固定の表を設けるのではなく、 差し込み実行時に異なる行数の表がページごとに
生成される仕組みを構築する。(例えばフィールドコード DATABASE を使うなど)

 
これからフィールドコードの DATABASE というものを調べ、担当者にも相談してみます。
 

回答
投稿日時: 19/06/14 17:17:56
投稿者: sk

引用:
VBAで削除はハードルが高いです。

例えば、次のようなコードを記述することになります。
 
(標準モジュール)
-------------------------------------------------------------
Option Explicit
 
Sub DeleteBlankRowsInTables()
 
    Dim wrdTable As Word.Table
    Dim wrdRow As Word.Row
    Dim lngRowCount As Long
 
    For Each wrdTable In ActiveDocument.Tables
        For lngRowCount = wrdTable.Rows.Count To 1 Step -1
            Set wrdRow = wrdTable.Rows(lngRowCount)
            If IsBlankRow(wrdRow) Then
                wrdRow.Delete
            End If
            Set wrdRow = Nothing
        Next
    Next
     
End Sub
 
Private Function IsBlankRow(Row As Word.Row) As Boolean
 
    Dim wrdCell As Word.Cell
     
    IsBlankRow = False
     
    For Each wrdCell In Row.Cells
        With wrdCell.Range
            .End = .End - 1
            If .Text <> "" Then
                Exit Function
            End If
        End With
    Next
     
    IsBlankRow = True
     
End Function
-------------------------------------------------------------
 
引用:
これからフィールドコードの DATABASE というものを調べ、担当者にも相談してみます。

Office サポート より:
https://support.office.com/ja-jp/article/%e3%83%95%e3%82%a3%e3%83%bc%e3%83%ab%e3%83%89-%e3%82%b3%e3%83%bc%e3%83%89-database-%e3%83%95%e3%82%a3%e3%83%bc%e3%83%ab%e3%83%89-04398159-a2c9-463f-bb59-558a87badcbc?ui=ja-JP&rs=ja-JP&ad=JP
 
ちなみに、今回のようなケースにおいて DATABASE フィールドを使用する場合、
ある意味では前述の VBA のコードを書くことよりも難易度が遥かに上である
と言えます。
 
SQL の知識が必要となったり、メイン文書のデータソース設定の方にも
手を加えたりすることになるからです。
(ネット上にも実例を紹介している記事があまり見当たりませんし)

投稿日時: 19/06/14 19:15:18
投稿者: 花野

skさん、VBAのご提示までありがとうございます。
少しずつ意味を調べてみます。
 
そしてフィールドコードの database リンク先を見てみました。
SQLという言葉は聞いたことがありますが、私の頭では
イメージさえわきません。
 
ご提示頂いたVBAを、来週に実行してみます。

回答
投稿日時: 19/06/17 13:54:49
投稿者: んなっと

おそらく今回の例では役に立たない情報ですが、単純な文書であれば使えるので書き込んでおきます。
別の機会に試してみてください。
 
差し込みフィールドを挿入した表は1行だけとして、
差し込み印刷の文書の種類を「レター」や「ラベル」ではなく、「名簿」にする方法です。
 
 
1.元データ 
《分類》フィールドを作成してグループ化の基準とする。
 
   A  B   C
1 分類 No. 氏名
2  あ 101  名1
3  あ 102  名2
4  あ 103  名3
5  い 104  名4
6  い 105  名5
7  う 106  名6
 
 
2.差し込み元文書 
挿入する表は必ず1行。
表の下の文章はフッターの高さを広くして配置。
                  
      ○○○○ 
             ○○○○ 
 ○○○○ 《分類》 へのお知らせ 
 ○○○○ ○○○○        
┌――――┬――――┐       
| 《No.》|《氏名》|       
└――――┴――――┘       
 ◎◎◎◎◎◎◎◎◎◎   ←フッターに移動
 
 
3.下のマクロ実行(手作業でもできますが、説明が面倒)
 
Sub MergeDirectory()
  Dim Tbl As Table
  Dim Rng As Range, Rng2 As Range
  Dim r As Range
  Dim St As Long, En As Long
  Dim s As String
  Application.ScreenUpdating = False
  With ActiveDocument
    .ActiveWindow.View.ShowFieldCodes = True
    Set Tbl = .Tables(.Tables.Count)
    Set Rng = .Range(0, Tbl.Range.Start - 1)
    Set Rng2 = .Range(0, Tbl.Range.Start - 1)
  End With
  En = Rng.End
  Rng2.InsertAfter "{IF {MERGESEQ}=""1"" {STR}}{IF {MERGEFIELD 分類}<>{PREV} ""●{STR}""}{SET PREV {MERGEFIELD 分類}}"
  Rng2.SetRange En, Rng2.End + 1
  Rng.SetRange 0, En
  Rng.InsertBefore "SET STR """
  Rng.InsertAfter """"
  Rng.Fields.Add Rng, wdFieldEmpty, , False
  St = InStr(1, Rng2.Text, "{")
  Do While St > 0
    En = InStr(1, Rng2.Text, "}")
    Set r = ActiveDocument.Range(Rng2.Start + St - 1, Rng2.Start + En)
    With r
      Do While Len(Replace(.Text, "{", "")) <> Len(Replace(.Text, "}", ""))
        En = InStr(En + 1, Rng2.Text, "}")
        .SetRange .Start, Rng2.Start + En
      Loop
      .Characters.First.Delete
      .Characters.Last.Delete
      s = .Text
      With r.Fields.Add(r, wdFieldEmpty, , False)
        .Code.Text = s
      End With
    End With
    St = InStr(1, Rng2.Text, "{")
  Loop
  Rng2.Characters.Last.Font.Hidden = True
  With Rng2.Find
    .Text = "●"
    .Replacement.Text = "^m"
    .Execute Replace:=wdReplaceOne
  End With
  ActiveWindow.View.ShowAll = False
  ActiveWindow.View.ShowHiddenText = False
  ActiveDocument.ActiveWindow.View.ShowFieldCodes = False
  ActiveDocument.Fields.Update
  Application.ScreenUpdating = True
End Sub
 
 
4.差し込み実行
 
      ○○○○       
             ○○○○ 
 ○○○○ あ へのお知らせ 
 ○○○○ ○○○○        
┌――――┬――――┐       
|   101|   名1|       
├――――┼――――┤       
|   102|   名2|       
├――――┼――――┤       
|   103|   名3|       
└――――┴――――┘ 
 ◎◎◎◎◎◎◎◎◎◎      
 ―改ペ―    
      ○○○○        
             ○○○○ 
 ○○○○ い へのお知らせ 
 ○○○○ ○○○○        
┌――――┬――――┐       
|   104|   名4|       
├――――┼――――┤       
|   105|   名5|       
└――――┴――――┘       
 
 ◎◎◎◎◎◎◎◎◎◎  
 ―改ペ―       
      ○○○○        
             ○○○○ 
 ○○○○ う へのお知らせ 
 ○○○○ ○○○○        
┌――――┬――――┐       
|   106|   名6|       
└――――┴――――┘       
 
 
 ◎◎◎◎◎◎◎◎◎◎  

投稿日時: 19/06/17 15:41:18
投稿者: 花野

skさん、ご提示いただいたVBAをテストファイルにて実行してみました。
無事空白行が削除できました。ありがとうございます。
 
ご提示いただいたコードを、理解して使いたいと思うので、検索等をしながら
意味を考えています。
wrdTable.Rows.Count To 1 Step -1 というのは、1行ごとに、という意味でしょうか。
また、IsBlankRow が空白行だと思うのですが、この部分を選択して右クリックすると
プロパティ/メソッドの一覧で出てくるのですが、ヘルプを見ても出てきません。
本を買ってみて、調べてみようと思います。
VBA入門編から勉強しなくてはならないことを痛感しています。
 
本当にありがとうございました。

投稿日時: 19/06/17 15:44:41
投稿者: 花野

んなっとさん、コメントありがとうございます。
 
差し込み印刷の文書の種類を「名簿」にする方法を教えていただき
ありがとうございます。
そもそも空白行を作らない文書を作成すればいいのですね。
これからの作業の参考にさせていただきます。
また、サンプルデータを使って試してみます。

回答
投稿日時: 19/06/17 16:37:37
投稿者: sk

sk さんの引用:
For lngRowCount = wrdTable.Rows.Count To 1 Step -1

花野 さんの引用:
というのは、1行ごとに、という意味でしょうか。

変数 lngRowCount の値を、参照中の表( wrdTable )の
全ての行( Rows )の数( Count )から 1 までの範囲で
1 ずつ引く( Step -1 )、というループ処理を行なっています。
 
例えば表の行数が 3 行であれば、3, 2, 1 の順に
変数 lngRowCount の値を遷移させながら、
For の行と Next の行の間に記述されているコードが
3 回実行されることになります。
 
そしてそのブロックの中には、
 
sk さんの引用:
Set wrdRow = wrdTable.Rows(lngRowCount)

変数 lngRowCount の値と同じ行番号の行
( 1 回目は 3 行目、2 回目は 2 行目、3 回目は 1 行目)
への参照を変数 wrdRow に渡して、
 
sk さんの引用:
If IsBlankRow(wrdRow) Then
    wrdRow.Delete
End If

その行が空白行であるか否かを判定した結果が True(真)であれば、
その行全体を削除する、というコードを記述しています。
 
花野 さんの引用:
また、IsBlankRow が空白行だと思うのですが、この部分を選択して右クリックすると
プロパティ/メソッドの一覧で出てくるのですが、ヘルプを見ても出てきません。

それは今回のために私が作成したユーザー定義関数ですので、
ヘルプには載っていません。
 
sk さんの引用:
Private Function IsBlankRow(Row As Word.Row) As Boolean
  
    Dim wrdCell As Word.Cell
      
    IsBlankRow = False
      
    For Each wrdCell In Row.Cells
        With wrdCell.Range
            .End = .End - 1
            If .Text <> "" Then
                Exit Function
            End If
        End With
    Next
      
    IsBlankRow = True
      
End Function

端的に言えば、引数 Row に渡された行の全てのセルを
1 つずつ参照し、何らかのテキストが入力されている
セルが 1 つでも含まれている(空白行ではない)場合は
その関数の戻り値として False(偽)を返し、
そうでない(空白行である)場合は True(真)を返す、
という形を取っています。
 
そしてその関数を、同じモジュールの下記の箇所で呼び出しています。
 
sk さんの引用:
If IsBlankRow(wrdRow) Then
    wrdRow.Delete
End If

投稿日時: 19/06/17 16:59:23
投稿者: 花野

skさん、見当違いな質問にも丁寧に解説をいただき、本当にありがとうございました。
 
正直、すぐには理解できない感じですが、参考書も見ながら、解読してみます。