【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」という名前で保存されてます。

こんな感じです。

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

副業から独立まで「稼げる」Webスキルを習得する(PR)

ここまで読んでいただきありがとうございます。 最後に宣伝をさせてください。

「副業を始めたいが、何から手をつければいいかわからない」「独学でスキルはついたが、収益化できていない」という悩みを持つ方には、マンツーマン指導のWebスクール**「メイカラ」**が適しています。

このスクールは、単に技術を教えるだけでなく、**「副業として具体的にどう稼ぐか」**という実務直結のノウハウ提供に特化している点が特徴です。

講師陣は、実際に「副業Webライターから1年で独立して月収100万円」を達成したプロや、現役で利益を出し続けているブロガーなど、確かな実績を持つプレイヤーのみで構成されています。そのため、机上の空論ではない、現場で通用する戦術を学ぶことができます。

副業に特化した強み

  • 最短ルートの提示: 未経験からでも実績を出せるよう、マンツーマンで指導。
  • AI活用の習得: 副業の時間対効果を最大化するための、正しいAI活用スキルも網羅。
  • 案件獲得のチャンス: 運営がWebマーケティング会社であるため、実力次第で社内案件の紹介など、仕事に直結する可能性があります。

受講者の多くは、「在宅でできる仕事を探している」「副業を頑張りたい」という20代・30代・40代が中心です。

受講前には、講師による無料説明が行われます。無理な勧誘はなく、自分に合った副業スタイルやプランを相談できるため、まずは話を聞いてみることから始めてみてはいかがでしょうか。

ブログで稼ぎたいなら「メイカラ」

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

この記事を書いた人

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

目次