none
Wordファイルで正規表現をする際に他の情報を取得したい RRS feed

  • 質問

  • 初めて質問します。至らぬところがありましたら申し訳ありません。

    VisualC#2010にて、

    Wordファイルの検索置換を行うアプリケーションの作成を行っています。

    検索置換を実施する際に以下の情報を取得したいのですが

    どのように記述すればよいのでしょうか。

    ・該当ページ番号

    ・該当行番号(ページ単位)

    ・検索/置換対象の前後10文字

    また、検索および置換を実施する際は正規表現を使用するべきなのでしょうか。

    それともSelectionオブジェクトおよびRangeオブジェクトを使用すべきなのでしょうか。

    分からない個所が多すぎて調査作業すら捗らず質問させていただきました。

    ご教授頂ければと思います。よろしくお願いします。

    2015年3月9日 4:40

回答

  • こんな?
    #TextBox内の文字とかは考慮しません。

    using System;
    using Word = Microsoft.Office.Interop.Word;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                if (args.Length > 0 && System.IO.File.Exists(args[0]))
                {
                    Test(args[0], "A*C");//ABC
                }
            }
    
            private static void Test(string docPath, string pattern)
            {
                try
                {
                    var wa = new Microsoft.Office.Interop.Word.Application();
                    try
                    {
                        wa.Visible = true;
                        var doc = wa.Documents.Open(docPath);
    
                        Console.WriteLine(Result.Header);
    
                        doc.GoTo(Word.WdGoToItem.wdGoToPage, Word.WdGoToDirection.wdGoToFirst);
                        var sel = doc.ActiveWindow.Selection;
                        sel.Find.ClearFormatting();
                        sel.Find.Forward = true;
                        sel.Find.Wrap = Word.WdFindWrap.wdFindContinue;
                        sel.Find.MatchAllWordForms = false;
                        sel.Find.MatchFuzzy = false;
                        sel.Find.MatchSoundsLike = false;
                        sel.Find.MatchWildcards = true;
                        sel.Find.Text = pattern;
    
                        while (sel.Find.Execute())
                        {
                            Result result = new Result();
                            result.Start.Index = sel.Start;
                            result.End.Index = sel.End;
    
                            Word.Range r;
                            r = doc.Range(sel.Start, sel.End);
    
                            r.Start = sel.Start;
                            r.End = sel.Start;
    
                            //結果先頭ページ取得
                            result.Start.PageNumber = (int)r.get_Information(Word.WdInformation.wdActiveEndAdjustedPageNumber);
                            //結果先頭行取得
                            result.Start.RowNumberInPage = (int)r.get_Information(Word.WdInformation.wdFirstCharacterLineNumber);
    
                            //結果先頭直前の10文字を取得
                            r.Start = Math.Max(0, r.Start - 10);
                            r.End = sel.Start;
                            result.Start.Text = r.Text;
    
    
    
                            r.Start = sel.End;
                            r.End = sel.End;
    
                            //結果末尾ページ取得
                            result.End.PageNumber = (int)r.get_Information(Word.WdInformation.wdActiveEndAdjustedPageNumber);
                            //結果末尾行取得
                            result.End.RowNumberInPage = (int)r.get_Information(Word.WdInformation.wdFirstCharacterLineNumber);
    
                            //結果末尾直後の10文字取得
                            r.Start = sel.End;
                            r.End = Math.Min(sel.End + 10, doc.Range().End);
                            result.End.Text = r.Text;
    
                            Console.WriteLine(result.ToString());
                        }
                    }
                    finally
                    {
                        ((Word._Application)wa).Quit();
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }
    
            class Result
            {
                public readonly ResultPart Start = new ResultPart();
                public readonly ResultPart End = new ResultPart();
    
                public override string ToString()
                {
                    return "START\t" + Start.ToString() + "\r\n" + "END\t" + End.ToString() + "\r\n";
                }
                public static string Header
                {
                    get { return "\tIndex\tPage\tRow\tText"; }
                }
            }
            class ResultPart
            {
                public int Index;
                public int PageNumber;
                public int RowNumberInPage;
                public string Text;
    
                public override string ToString()
                {
                    return string.Format("{0}\t{1}\t{2}\t{3}", Index, PageNumber, RowNumberInPage, Text).Replace("\r", "\\r");
                }
            }
        }
    }

    もしかして、正規表現というのはWordの正規表現ではなく、全文を取り込んでC#の正規表現を使っての検索置換ですか?
    その場合はWordのページや行位置の情報が無いので不可能ですね。Wordでの検索結果のRangeを使うしかありません。

    Wordの正規表現という意味であれば、正規表現を使うのは正規表現でしか検索できない場合があるからです。
    正規表現を使わずに完全一致の検索ができるなら、その方が処理が軽いです。
    (正規表現はいろいろな可能性を調べながらになるので)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答の候補に設定 星 睦美 2015年3月10日 8:07
    • 回答としてマーク 星 睦美 2015年3月18日 5:21
    2015年3月9日 9:41

すべての返信

  • こんな?
    #TextBox内の文字とかは考慮しません。

    using System;
    using Word = Microsoft.Office.Interop.Word;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                if (args.Length > 0 && System.IO.File.Exists(args[0]))
                {
                    Test(args[0], "A*C");//ABC
                }
            }
    
            private static void Test(string docPath, string pattern)
            {
                try
                {
                    var wa = new Microsoft.Office.Interop.Word.Application();
                    try
                    {
                        wa.Visible = true;
                        var doc = wa.Documents.Open(docPath);
    
                        Console.WriteLine(Result.Header);
    
                        doc.GoTo(Word.WdGoToItem.wdGoToPage, Word.WdGoToDirection.wdGoToFirst);
                        var sel = doc.ActiveWindow.Selection;
                        sel.Find.ClearFormatting();
                        sel.Find.Forward = true;
                        sel.Find.Wrap = Word.WdFindWrap.wdFindContinue;
                        sel.Find.MatchAllWordForms = false;
                        sel.Find.MatchFuzzy = false;
                        sel.Find.MatchSoundsLike = false;
                        sel.Find.MatchWildcards = true;
                        sel.Find.Text = pattern;
    
                        while (sel.Find.Execute())
                        {
                            Result result = new Result();
                            result.Start.Index = sel.Start;
                            result.End.Index = sel.End;
    
                            Word.Range r;
                            r = doc.Range(sel.Start, sel.End);
    
                            r.Start = sel.Start;
                            r.End = sel.Start;
    
                            //結果先頭ページ取得
                            result.Start.PageNumber = (int)r.get_Information(Word.WdInformation.wdActiveEndAdjustedPageNumber);
                            //結果先頭行取得
                            result.Start.RowNumberInPage = (int)r.get_Information(Word.WdInformation.wdFirstCharacterLineNumber);
    
                            //結果先頭直前の10文字を取得
                            r.Start = Math.Max(0, r.Start - 10);
                            r.End = sel.Start;
                            result.Start.Text = r.Text;
    
    
    
                            r.Start = sel.End;
                            r.End = sel.End;
    
                            //結果末尾ページ取得
                            result.End.PageNumber = (int)r.get_Information(Word.WdInformation.wdActiveEndAdjustedPageNumber);
                            //結果末尾行取得
                            result.End.RowNumberInPage = (int)r.get_Information(Word.WdInformation.wdFirstCharacterLineNumber);
    
                            //結果末尾直後の10文字取得
                            r.Start = sel.End;
                            r.End = Math.Min(sel.End + 10, doc.Range().End);
                            result.End.Text = r.Text;
    
                            Console.WriteLine(result.ToString());
                        }
                    }
                    finally
                    {
                        ((Word._Application)wa).Quit();
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }
    
            class Result
            {
                public readonly ResultPart Start = new ResultPart();
                public readonly ResultPart End = new ResultPart();
    
                public override string ToString()
                {
                    return "START\t" + Start.ToString() + "\r\n" + "END\t" + End.ToString() + "\r\n";
                }
                public static string Header
                {
                    get { return "\tIndex\tPage\tRow\tText"; }
                }
            }
            class ResultPart
            {
                public int Index;
                public int PageNumber;
                public int RowNumberInPage;
                public string Text;
    
                public override string ToString()
                {
                    return string.Format("{0}\t{1}\t{2}\t{3}", Index, PageNumber, RowNumberInPage, Text).Replace("\r", "\\r");
                }
            }
        }
    }

    もしかして、正規表現というのはWordの正規表現ではなく、全文を取り込んでC#の正規表現を使っての検索置換ですか?
    その場合はWordのページや行位置の情報が無いので不可能ですね。Wordでの検索結果のRangeを使うしかありません。

    Wordの正規表現という意味であれば、正規表現を使うのは正規表現でしか検索できない場合があるからです。
    正規表現を使わずに完全一致の検索ができるなら、その方が処理が軽いです。
    (正規表現はいろいろな可能性を調べながらになるので)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答の候補に設定 星 睦美 2015年3月10日 8:07
    • 回答としてマーク 星 睦美 2015年3月18日 5:21
    2015年3月9日 9:41
  • さっそくご回答いただきまして、ありがとうございます。

    まだ実装できていないので取り急ぎお礼と回答だけさせて頂きます。

    >もしかして、正規表現というのはWordの正規表現ではなく、全文を取り込んでC#の正規表現を使っての検索置換ですか?

    ご回答いただいた通り、Wordの正規表現で問題ありません。

    文章の書き方が悪くて余計な勘繰りをさせてしまし申し訳ありません。

    >Wordの正規表現という意味であれば、正規表現を使うのは正規表現でしか検索できない場合があるからです。
    正規表現を使わずに完全一致の検索ができるなら、その方が処理が軽いです。

    とありますが、作成するアプリケーションの目的が検索と置換なのですが正規表現を使用しない方がやはり処理が速いのですか?

    ファイルに対して完全一致のみ検索置換をすることを目的としています。

    検索、置換で検索をかけても私の求める情報を取得するコードをどこに何を追加すればいいかわからず

    このような聞き方をしてしまいました。いずれは正規表現も実装したいところですが、今回の仕様は検索置換だけなので。

    説明が足りず申し訳ありませんでした。

    2015年3月10日 7:57