Word (VBA)

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

 
(Windows 10 Pro : Word 2019)
行ごとの、先頭空白を削除したい
投稿日時: 23/05/31 09:36:56
投稿者: わん0623

WordにVBAのコードを張り付けて、コードを選択して、下記のVBAを動かすと、行単位で、先頭の空白が削除されると思いきや、上手く動きません。
何故でしょうか?
LTrimの行をコメントアウトすれば、行ごとにSelectされるので、ループ自体は問題ないと考えています。
 
Sub Test()
    Dim myPara As Paragraph
    For Each myPara In Selection.Range.Paragraphs
        myPara.Range.Select ⇐これだけだと、行ごとに選択されていく
        myPara.Range.Text = LTrim(myPara.Range.Text) ⇐行ごとに先頭空白が削除されない
    Next
End Sub
 
詳しい方、お手数ですが教えて下さい。
宜しくお願い致します。

回答
投稿日時: 23/05/31 11:29:08
投稿者: QooApp

現状の症状についてもう少し詳しく書けそうでしょうか?
 
・VBA実行前のワードファイルの状態について、全ての段落頭に空白が入っている?
>>NO or 量が少ない:
___手動で消した方が早いかも?
 
・参考に下ウェブサイトがあればURLを教えてもらえますか?
 
・症状はVBAを実行した時に終了しない(=フリーズ=無限ループ状態)で間違いない?

回答
投稿日時: 23/05/31 11:45:53
投稿者: QooApp

原因は今眺めていますが、Alt+F8>実行 ではなく、VBAのソースコード側でF8キーを押すと1行ずつ実行してくれます。
 
これでF8キーを押しながらコードがどのような進行をしているか眺めることができます。
カーソルを合わせれば内部データも表示されたりします。
 
私が適当に作ったダミーデータをもとに提示されたプログラムを実行すると、MyParaのオブジェクト内のParaID=行管理ID番号とTextID=文章管理ID番号が上書きされ、それが原因で次の行に進行できていないように思えます。
 
myPara.Range.Text = LTrim(myPara.Range.Text)をコメントアウトするとFor文のループが発生せずそのまま終了するので多分上書き方法が誤っているのではないかと。

回答
投稿日時: 23/05/31 14:09:55
投稿者: QooApp

すみません、同型ソフトではないのでオフィス365で状況再現をしておりますが、段落末の改行コードが改行コードで上書きされると次の行への移動ができなくなるようです。
 
段落末の改行コードを消すように指示を出しながらプログラムを実行すると行の移動ができることを確認しました。
 
現象的に
「1行検索して行頭のスペースを削除した後、元の行へ再挿入する」
を1回のループ処理中に行うと行管理IDが再発行され、旧IDの次の行=新IDとなってしまい、延々と新規作成扱いの行(行頭処理しただけの元の行)が処理されることによって発生する無限ループ状態のようです。
 
いったん、ただの文字列の変数へ書き出し、ループ処理後に一括挿入してはいかがか?

回答
投稿日時: 23/05/31 14:25:34
投稿者: QooApp

Option Explicit

Sub Test()
    
    'あとから結合する扱いで一時的に文字列を保持する
    Dim allText As String
    allText = ""
    
    Dim myPara As Paragraph
    
    '選択している範囲を段落ごとにループ
    For Each myPara In Selection.Range.Paragraphs
        '処理する行を指定
        myPara.Range.Select
        
        '一時保管して処理中の行を削除
        allText = allText & LTrim(myPara.Range.Text)
        myPara.Range.Text = ""
    Next
    
    'ループ終了後の行へ一時保管中の文章を再挿入
    Selection.InsertBefore allText
End Sub

 
とりあえず実行しても動作することは確認できましたが、文章や段落に対して事前に装飾が行われていると装飾情報が消えます。
原因は文字列型で一時保管変数を定義しているのでそれです。
 
プレーンテキスト化してでもとりあえず行頭のスペースを削除したいだけであれば実行できます。

回答
投稿日時: 23/05/31 14:29:03
投稿者: QooApp

追記:
最後の一括挿入後、挿入末尾に不用意な改行コードが1文字=1行追加されてしまいます。
末尾の改行1文字は手動で消すか、文字列型変数の末尾1文字を削除したうえでインサートしてください。
 
パラグラフ型のデータの段階で1段落=末尾に改行が含まれているのが原因で、最後に挿入しようとするカーソル位置がすでに1改行分なので余計な改行コードが1回発生しています。

回答
投稿日時: 23/05/31 17:38:31
投稿者: sk

引用:
単位で、先頭の空白が削除

正しくは段落単位であるとして。
 
引用:
Dim myPara As Paragraph

引用:
myPara.Range.Text = LTrim(myPara.Range.Text)

段落内の文字列全体を書き換える方式だと、個々の文字列に
設定されている書式を維持できませんので、あまりお奨めしません。
 
この場合は「段落の先頭において半角/全角スペースが 1 文字以上
連続している範囲」のみを探し当てて削除するようにして下さい。
 
(標準モジュール)
----------------------------------------------------------------------
Sub DeleteLeftSpacesInParagraphs()
 
    Dim docTarget As Word.Document
    Dim paraTarget As Word.Paragraph
    Dim rngTarget As Word.Range
    Dim lngIndex As Long
    Dim lngLeftSpacesCount As Long
     
    Set docTarget = ActiveDocument
     
    For lngIndex = docTarget.Paragraphs.Count To 1 Step -1
        Set paraTarget = docTarget.Paragraphs(lngIndex)
        Set rngTarget = paraTarget.Range
        With rngTarget
            .MoveEnd wdCharacter, -1
            lngLeftSpacesCount = Len(.Text) - Len(LTrim(.Text))
            If lngLeftSpacesCount > 0 Then
                .SetRange .Start, .Start + lngLeftSpacesCount
                .Delete Unit:=wdCharacter, Count:=1
            End If
        End With
        Set rngTarget = Nothing
        Set paraTarget = Nothing
    Next
 
    Set docTarget = Nothing
 
End Sub
----------------------------------------------------------------------

投稿日時: 23/06/01 08:41:48
投稿者: わん0623

QooApp様、sk様
御指南ありがとうございます。
 
教えて頂いたコードについて、勉強し自分のスキルアップを図りたいと思います。
大変、助かりました。
今後とも宜しくお願い致します。