【Windowsアプリ】検索アプリ【C#】

目次

経緯

事実を確認してもらうため、議事録が入ってるフォルダの中の文章を証拠として、見せようとしたときに、

議事録フォルダのファイルを一つ一つ開いて、文章を探すのが手間だったので、

「”検索アプリ”のようなものがあればな~」と思い、C#で作ってみました。

レイアウト

まず、アプリのレイアウトを書きます。

ツール名Text名(Name)
label調べたいフォルダ:label1
label保存先:label2
label検索文字:label3
TextBoxtextBox_search_folder
TextBoxtextBox_save
TextBoxtextBox_search_word
Button選択button_search_folder_choose
Button選択button_save_choose
Button実行button_run

という構成です。配置は(Name)で表すと

label1,textBox_search_folder,button_search_folder_choose

label2,textBox_save,button_save_choose

label3,textBox_search_word

button_run

という並びとなります。

コード

以下がコードです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.IO;
using System.IO.Packaging;


namespace foldersearchApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // ドラッグ&ドロップのイベントハンドラを設定
            textBox_search_folder.AllowDrop = true;
            textBox_search_folder.DragEnter += new DragEventHandler(textBox_search_folder_DragEnter);
            textBox_search_folder.DragDrop += new DragEventHandler(textBox_search_folder_DragDrop);
        }


        private void button_search_folder_choose_Click(object sender, EventArgs e)
        {
            using (var folderBrowserDialog = new FolderBrowserDialog())
            {
                // ダイアログの説明文を設定
                folderBrowserDialog.Description = "検索するフォルダを選択してください。";

                // ダイアログを表示
                DialogResult result = folderBrowserDialog.ShowDialog();

                // ユーザーが「OK」を選択した場合、選択されたパスをテキストボックスに設定
                if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(folderBrowserDialog.SelectedPath))
                {
                    textBox_search_folder.Text = folderBrowserDialog.SelectedPath;
                }
            }
        }

        private void textBox_search_folder_DragEnter(object sender, DragEventArgs e)
        {
            // ドラッグされているデータがファイルのパスであるかどうかを確認
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy; // カーソルにコピーのアイコンを表示
            }
            else
            {
                e.Effect = DragDropEffects.None; // ドラッグ操作を受け入れない
            }
        }

        private void textBox_search_folder_DragDrop(object sender, DragEventArgs e)
        {
            // ドロップされたすべてのファイルのパスを取得
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

            // ここでは単純化のため、最初のファイル/フォルダのパスを使用
            if (files != null && files.Length > 0)
            {
                // フォルダパスをテキストボックスに設定
                textBox_search_folder.Text = files[0];
            }
        }

        private void button_save_choose_Click(object sender, EventArgs e)
        {
            using (var folderBrowserDialog = new FolderBrowserDialog())
            {
                folderBrowserDialog.Description = "保存先のフォルダを選択してください。";
                // 新しいスタイルのダイアログを使用する設定(.NET 5.0以降で有効)
                // folderBrowserDialog.UseDescriptionForTitle = true; // 必要に応じてコメントアウト

                DialogResult result = folderBrowserDialog.ShowDialog();

                if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(folderBrowserDialog.SelectedPath))
                {
                    // 選択されたフォルダのパスをテキストボックスに設定
                    textBox_save.Text = folderBrowserDialog.SelectedPath;
                }
            }
        }

        private void button_run_Click(object sender, EventArgs e)
        {
            string sourceFolderPath = textBox_search_folder.Text;
            string destinationFolderPath = Path.Combine(textBox_save.Text, "FilteredFiles");
            string searchWord = textBox_search_word.Text;

            if (!Directory.Exists(destinationFolderPath))
            {
                Directory.CreateDirectory(destinationFolderPath);
            }

            var files = Directory.EnumerateFiles(sourceFolderPath, "*.*", SearchOption.AllDirectories)
                .Where(file => file.ToLower().EndsWith(".xlsx") || file.ToLower().EndsWith(".xlsm") // Excelマクロ含む形式を追加
                || file.ToLower().EndsWith(".docx") || file.ToLower().EndsWith(".docm") // Wordマクロ含む形式を追加
                || file.ToLower().EndsWith(".pptx") || file.ToLower().EndsWith(".pptm")); // PowerPointマクロ含む形式を追加

            foreach (var file in files)
            {
                // マクロを含むファイルの検出を追加
                if (FileContainsMacro(file) || CheckFileContainsText(file, searchWord))
                {
                    string destinationFilePath = Path.Combine(destinationFolderPath, Path.GetFileName(file));
                    File.Copy(file, destinationFilePath, true);
                }
            }

            MessageBox.Show("処理が完了しました。", "情報", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }


        private bool CheckFileContainsText(string filePath, string text)
        {
            string extension = Path.GetExtension(filePath).ToLower();
            switch (extension)
            {
                case ".xlsx":
                    return CheckExcelFileContainsText(filePath, text);
                case ".docx":
                    return CheckWordFileContainsText(filePath, text);
                case ".pptx":
                    return CheckPowerPointFileContainsText(filePath, text);
                default:
                    return false;
            }
        }

        private bool CheckExcelFileContainsText(string filePath, string text)
        {
            try
            {
                using (SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, false))
                {
                    var strings = document.WorkbookPart.SharedStringTablePart.SharedStringTable.Elements<SharedStringItem>().Select(item => item.InnerText);
                    return strings.Any(s => s.Contains(text));
                }
            }
            catch
            {
                return false;
            }
        }

        private bool CheckWordFileContainsText(string filePath, string text)
        {
            try
            {
                using (WordprocessingDocument document = WordprocessingDocument.Open(filePath, false))
                {
                    var texts = document.MainDocumentPart.Document.Body.Descendants<Text>().Select(t => t.Text);
                    return texts.Any(t => t.Contains(text));
                }
            }
            catch
            {
                return false;
            }
        }

        private bool CheckPowerPointFileContainsText(string filePath, string text)
        {
            try
            {
                using (PresentationDocument document = PresentationDocument.Open(filePath, false))
                {
                    var slides = document.PresentationPart.SlideParts;
                    foreach (var slide in slides)
                    {
                        var texts = slide.Slide.Descendants<DocumentFormat.OpenXml.Drawing.Text>().Select(t => t.Text);
                        if (texts.Any(t => t.Contains(text))) return true;
                    }
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        private bool FileContainsMacro(string filePath)
        {
            string extension = Path.GetExtension(filePath).ToLower();
            switch (extension)
            {
                case ".docm":
                case ".dotm":
                    return true; // Word マクロ含む形式
                case ".xlsm":
                case ".xltm":
                case ".xlam":
                    return true; // Excel マクロ含む形式
                case ".pptm":
                case ".potm":
                case ".ppam":
                case ".ppsm":
                case ".sldm":
                    return true; // PowerPoint マクロ含む形式
                default:
                    if (extension == ".docx" || extension == ".xlsx" || extension == ".pptx")
                    {
                        try
                        {
                            // OpenXML 形式のドキュメントでマクロを直接検出
                            using (Package package = Package.Open(filePath, FileMode.Open, FileAccess.Read))
                            {
                                string macroContentType = "application/vnd.ms-office.vbaProject";
                                return package.GetParts().Any(part => part.ContentType.Equals(macroContentType, StringComparison.OrdinalIgnoreCase));
                            }
                        }
                        catch
                        {
                            // ファイルアクセス例外などのエラー処理
                            return false;
                        }
                    }
                    return false; // その他の形式ではマクロを含まないと判断
            }
        }
    }
}

使い方は、

まず、textBox_search_folderにドラックドロップか「選択」ボタンを押して、検索したいフォルダを選択します。

次にtextBox_saveに検索に引っかかったファイルのフォルダを保存したい場所を「選択」ボタンを押して、設定してください。

次にtextBox_search_wordに検索したい文字を入れます。

最後に「実行」を押すと、textBox_search_wordで指定した文字が入っているファイル(Excel、word、PowerPoint)がフォルダが指定された先「FilterdFiles」という名前で保存されてます。

こんな感じです。

何かの参考になれば、幸いです。

ここまで読んでいただきありがとうございました。

スクールの紹介

最後に宣伝をさせてください。

夢見るAIエンジニアへ、今こそ一歩を踏み出せ!

最近、AI技術やデータサイエンスに興味を持ち始めたあなた。将来、AIエンジニアやデータサイエンティストとして活躍したいと考えているかもしれません。また、AIを使って業務課題や研究課題を解決したい、あるいは教養としてAIの知識を深めたいと思っている方もいるでしょう。

しかし、学び始めるとなると「どこから手をつけて良いのか分からない」「専門的すぎて理解できない」といった悩みが生じることも。そんなあなたのために、この3ヶ月間集中してAIプログラミングを習得するオンラインコーチングサービスがオススメです!

なぜこのサービスが選ばれるのか?その理由はこちら

  1. 初心者から上級者まで
    完全なプログラミング初心者から研究者まで、幅広い方々に優良なコンテンツが提供されます。
  2. 徹底的な進捗管理
    受講者の進捗をしっかりとチェックし、つまずきやすいポイントでのフォローが万全です。
  3. 専属メンターによる徹底サポート
    AIの学び方から、実際の適用まで、専属のメンターが手厚くサポートします。
  4. 場所を選ばず学べるオンライン完結
    東京以外の地域からも、気軽に学び始めることができます。

信頼の実績多数!
・日本最大級のプログラミングスクール実績
・受講者総数700名以上
・SaaS型学習サービス会員65,000名以上
・企業導入実績120社以上
・グッドデザイン賞受賞
・著名な賞受賞歴や経団連加盟も実現

夢を叶えるための第一歩を、一緒に踏み出しませんか?今なら、あなたもその一員として学び始めることができます!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次