最初に
テキストファイルの数値データを読み込み、Excelなど他のソフトに自動で入力してくれるプログラムを組んでみました。
今回の目的
VisualStudio2019のWindowsフォームアプリケーション(.NET Framework)を作成して、あるフォルダーの中のテキストファイルを読み込み、Excelなどの外部アプリに自動入力するフォームアプリを作成します。
今回はテキストファイルから「X」、「Y」を判別し文字列から数字を抽出後、Excelに「X」の数字は左の列に、「Y」の数字は右の列に入力します。手動でExcelに数字を入力する場合、操作は「Xの数字」→「TAB」→「Yの数字」→「ENTER」→「次のXの数字」→...と入力していくのですが、この操作を自動でするプログラムを作ります。
完成したフォームアプリはこんな感じ
フォルダーを参照、ファイル名を入力して、入力開始ボタンを押すとテキストファイルの数字をExcelに自動で打ち込んでくれます。
開発環境
Visual Studio 2019
プロジェクトの作成
Visual Studio 2019を開き、新しいプロジェクトの作成します。
Windowsフォームアプリケーション(.NET Framework)を選択して次へ。
プロジェクト名を入力後、プロジェクトの保存場所を任意の場所にして、作成をクリック。
プロジェクト名は自分のわかりやすい名前であればなんでもいいです。
フォームの作成
ボタンやテキストボックス、ラベルなどを配置します。
・画面の設定
画面のサイズは赤丸のところで調整できます。右下のプロパティ画面でも調整でき、細かい調整ができます。
ウインドウの名前がForm1になっていますが、変更したい場合はこれも右下のプロパティ画面で変更できます。Textの欄がForm1となっているので変えたい名前に変更しましょう。
・ボタンなどの配置
画面左にツールボックスがあるので使いたいものをドラックアンドドロップすることで追加できます。Buttonを追加します。
ツールボックスがない場合は上のバーの「表示」にツールボックスがあるのでそこをクリックすると出てきます。
プロパティで背景の色やフォントのサイズ、字体、ボタンのテキストなど設定できます。
同様にしてButton、TextBox、Labelを配置します。ツールボックスの検索機能を使うと便利です。
こんな感じに配置↓
・フォルダーの参照
「フォルダの選択」ダイアログを表示するのにFolderBrowserDialogを追加します。これで下準備はOKです。
コードの記述
コード編集画面が開き、Clickイベントハンドラ(button1_Click メソッド)が作成されます。
このbutton1_Click メソッド内にボタンクリック時に実行するコードを記述します。
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;
namespace TextFileInputOutput
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
};
フォルダーの参照ボタンのClickイベントハンドラも同様に作成しましょう。
・イベントハンドラメソッドの名前について
メソッドには任意の名前を付けることができます。
例えば、今回のフォルダーの参照のbutton2というボタンのClickイベントのイベントハンドラーメソッドには button2_Click()という名前が付けられます。詳しくはこちらを参考にしてください。
また、イベントハンドラーメソッドを作成した後にやっぱりそのメソッドを削除したいと思ったときは、フォームデザインの画面に戻り、イベントのアクションのClickを消してから削除するようにしてください。先にコードに記述してあるメソッドを消してしまうとエラーが出てしまいます。
↓イベントのアクションのClickの名前を削除してからコードのほうを消す。(button2_Clickメソッドを削除したい場合)
・usingディレクティブ追加
まず、次のusingディレクティブを使うので追加しておきましょう。
using System.Threading;
using System.IO;
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 System.Threading;
using System.IO;
namespace TextFileInputOutput
{//省略
}
・フォルダーの参照のコードの記述
テキストボックスにフォルダー参照ダイアログボックスで選択したフォルダのパスを表示します。
private void button2_Click(object sender, EventArgs e)
{
DialogResult dr = folderBrowserDialog1.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
textBox1.Text = folderBrowserDialog1.SelectedPath;
}
}
下記のコードでフォルダー参照ダイアログを表示します。
DialogResult dr = folderBrowserDialog1.ShowDialog();
ダイアログボックスが[OK]ボタンで閉じられた場合、テキストボックスにフォルダー参照ダイアログボックスで選択したフォルダのパスを表示します。
if (dr == System.Windows.Forms.DialogResult.OK)
{
textBox1.Text = folderBrowserDialog1.SelectedPath;
}
・自動入力のコードの記述
private void button1_Click(object sender, EventArgs e)
{
Microsoft.VisualBasic.Interaction.AppActivate("Excel");
string filePass = $@"{textBox1.Text}\{textBox2.Text}.txt";
var lines = File.ReadAllLines(filePass);
Thread.Sleep(1000);
foreach (var line in lines)
{
if (line.Contains("X"))
{
string xNum = line.Replace("X=", "").Replace(" ", "");
SendKeys.Send(xNum);
SendKeys.Send("{TAB}");
}
if (line.Contains("Y"))
{
string yNum = line.Replace("Y=", "").Replace(" ", "");
SendKeys.Send(yNum);
SendKeys.Send("{ENTER}");
}
Thread.Sleep(100);
}
}
「型または名前空間の名前'Interaction'が名前空間'Microsoft.VisualBasic'に存在しません。」と出てきた場合は、ソリューションエクスプローラーから参照の追加でMicrosoft.VisualBasicにチェックマークを入れます。
Microsoft.VisualBasicにチェックを入れてOK。
コードの解説
Microsoft.VisualBasic.Interaction.AppActivate("Excel");
アクティブにしたいウィンドウのタイトルを指定して呼び出し、そのウィンドウをアクティブ状態にします。(今回はExcel)
string filePass = $@"{textBox1.Text}\{textBox2.Text}.txt";
テキストボックス(textBox1、textBox2)の値を取得し、文字列として定義します。
var lines = File.ReadAllLines(filePass);
System.IO.FileクラスのReadAllLinesメソッドを使います。
引数に定義した文字列を渡し、そのテキストファイルを開き、ファイルのすべての行を読み取った後、ファイルを閉じます。
foreach (var line in lines)
{
if (line.Contains("X"))
{
string xNum = line.Replace("X=", "").Replace(" ", "");
SendKeys.Send(xNum);
SendKeys.Send("{TAB}");
}
if (line.Contains("Y"))
{
string yNum = line.Replace("Y=", "").Replace(" ", "");
SendKeys.Send(yNum);
SendKeys.Send("{ENTER}");
}
Thread.Sleep(100);
}
foreach文で読み込んだ文字列を1つずつ取り出し、if文でその文字列に「X」が含まれていた場合、「Y」が含まれていた場合で処理を分け、この処理をある文字列の分繰り返します。
if文の中の処理では、まずReplaceメソッドで文字列を置換し、文字列を数字のみにします。次にその数字をSendKeys.Send() メソッドでキーボードから入力したかのように、1つ以上のキーボード操作をアクティブなウィンドウに送信します。その後、「X」の場合はTABの入力操作、「Y」の場合はENTERの入力操作を送信します。
最後にThread.Sleepメソッドで一定時間待機するために指定した時間の長さ(単位はミリ秒)、現在のスレッドを中断します。
今回は100ミリ秒(0.1秒)ごとに処理を繰り返すことになります。
キー操作には他にも様々な操作があるため、他に加えたいキー操作がある場合はこちらを参考にしてみてください。
・try~catchで例外処理を行う。
private void button1_Click(object sender, EventArgs e)
{
try
{
Microsoft.VisualBasic.Interaction.AppActivate("Excel");
//省略
Thread.Sleep(100);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
try~catchで例外処理を行います。入力開始ボタン(button1)を押したときに、処理に問題が発生すると、エラーのメッセージボックスが開きます。
全コード
usingディレクティブの使わないものは消していいです。
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 System.Threading;
using System.IO;
namespace TextFileInputOutput
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Microsoft.VisualBasic.Interaction.AppActivate("Excel");
string filePass = $@"{textBox1.Text}\{textBox2.Text}.txt";
var lines = File.ReadAllLines(filePass);
Thread.Sleep(1000);
foreach (var line in lines)
{
if (line.Contains("X"))
{
string xNum = line.Replace("X=", "").Replace(" ", "");
SendKeys.Send(xNum);
SendKeys.Send("{TAB}");
}
if (line.Contains("Y"))
{
string yNum = line.Replace("Y=", "").Replace(" ", "");
SendKeys.Send(yNum);
SendKeys.Send("{ENTER}");
}
Thread.Sleep(100);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button2_Click(object sender, EventArgs e)
{
DialogResult dr = folderBrowserDialog1.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
textBox1.Text = folderBrowserDialog1.SelectedPath;
}
}
}
}
実行する
フォルダーを参照(テキストボックスに直接フォルダーの場所を入力でもOK)、ファイル名を入力して、入力開始ボタンを押すとテキストファイルの数字をExcelに自動で打ち込んでくれます。
追記(2023/10/5)
非同期処理の導入や処理の中断機能の追加などをしました。
→テキストファイルを読み込み、外部アプリに自動入力するフォームアプリの機能の追加と変更
参考文献
・ ボタン コントロールの名前を設定する
・ File.ReadAllLines メソッド
・ SendKeys
・ Thread.Sleep メソッド
・ Application.SendKeys メソッド
・ .NET TIPS[フォルダの参照]ダイアログを使用するには?
・ 外部アプリケーションのウィンドウをアクティブにする