事務関係でよく使うエクセル連携について、シンプルな例を作成してみました!
毎回繰り返しな作業はどんどんシステム化していきたいよね~
エクセルの一覧表と連携する機能は、いろいろな場面で役に立ちます。特に、自分の作業を簡略化したり、事務作業を効率化したりする際にとても役に立ってくれています。また、本格的なデータベースの知識がなくて、社内運用のソフトを作成する際にも、データベース的なものをより視覚的に扱うようなソフトを作れたりするので、他の人も理解しやすいような気がします。
今回は、C#のWPFアプリで、エクセル一覧表から対応する値を取得するような、シンプルなアプリを例に、コピペで実装できるような形にまとめたいと思い、本記事を記載いたします。
シンプルなアプリの仕様
次のように、A~Jまでのデータに対応する数字を記載したエクセル「test.xlsx」をデスクトップに置いておきます。
テキストボックスにAと記載して、ボタンを押すと、デバッグ出力画面に、対応する数字が表示されます。
ボタンを押すことで、出力画面に表示する機能だけとなっていますが、この処理をメール作成処理や、そのほか、文書作成機能などとすることで、複雑な数字や、紐づいたデータを一括で処理して出力を得られるようなシステムが作成できますので、それぞれの事務作業に最適化することで、かなりの時間が節約できます。
私も、例えば、顧客へよく出すメールには、このように製品の番号や、それに紐づく情報を記載する場合は、このようにキーを使って、自動でメール文書を作成するようにしていますので、メールの誤記がない+毎回長文を入力する必要がないということで、かなりストレスの軽減になっています。
そのほかに、決まったフォーマットの文書にこれらの情報を埋め込む場合も、ワードファイルへの出力を行うことで、文書作成が一瞬で完了するような仕組みを作成していますので、かなり業務時間の短縮になっております。
ソフトを作るのは若干のハードルがあるかもしれませんが、数年単位で処理をすることを考えると、業務へのストレスが全然違います。
プロジェクトの作成
WPFアプリで作成しています。
今回、プロジェクト名は「TestExcelApp」という名称にしました。
C#でプログラムするので、左側の選択がVisual Basicになっていないことも確認しておきます。
ソフトの実装
①GUIの作成、②ライブラリのインストール、③プログラムの実装を行います。
GUIの作成
GUIには、テキストボックスとボタンが必要です。
テキストボックスには、この後プログラムで利用する識別名が必要なので、プロパティの名前を「TextBox1」としておきました。
※NuGetパッケージマネージャーは、プロジェクトのソリューションエクスプローラーのプロジェクトを右クリックした以下のメニューからアクセスできます。
ライブラリのインストール
C#をエクセルからコントロールするためのパッケージ、「ClosedXML」をNuGetパッケージマネージャーから取得します。
参照タブの、検索窓に、「ClosedXML」と入力することで、ClosedXMLが出てきますので、これをインストールしておきます。
プログラムの実装
MainWindow.xaml.csファイルへ、次のプログラムを入力します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ClosedXML.Excel;//[1]ClosedXMLのインポート
namespace TestExcelApp
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//[2]ボタンクリック時のハンドラです。
private void Button_Click(object sender, RoutedEventArgs e)
{
//[2-1]テキストボックスの文字列を取得します。
string original_text = TextBox1.Text;
//[2-2]エクセルファイルのディレクトリを文字列として定義しておきます。
string listdir = @"C:\Users\●●●\Desktop\test.xlsx";
//[2-3]エクセルシートのオブジェクトを作成します。
XLWorkbook workbook = new XLWorkbook(listdir);
IXLWorksheet worksheet = workbook.Worksheet(1);
int lastRow = worksheet.LastRowUsed().RowNumber();//get last row number
//[2-4]forループで、エクセルの行を最終行までサーチします。
for (int i = 1; i <= lastRow; i++)
{
IXLCell get_cell = worksheet.Cell(i, 1);
string compare_text = get_cell.Value.ToString();
if (original_text.Equals(compare_text))
{
IXLCell data = worksheet.Cell(i, 2);
string data_strings = data.Value.ToString();
Console.WriteLine(data_strings);
}
}
}
}
}
[1]で、ClosedXMLを利用できるようにしています。
[2]ボタンを押した時に走るイベントハンドラ(関数)です。
[2-1]WPFアプリのテキストボックスからは、このようにして、文字列としてテキストボックス内の値を取得することができます。
[2-2]では、エクセルファイルのパスを文字列として格納します。ここを、ダイアログボックスから指定などすると、任意の階層を選択できるようにすることもできます。今回は、固定値としておきます。
[2-3]ClosedXMLの機能を利用して、エクセルシートのオブジェクトを作成しています。先ほど指定した階層をXLWoekBookとしてnewすることで、任意のエクセルシートをプログラム中で扱うことができるようになります。次の行で、エクセルシートを指定しています。1枚目のシートという意味です。最後に、データが存在している最後の行を取得することで、この後のループの終わりの値とすることができるようにしています。
※ここで、エクセルシート側の仕様も決定してくる点に注意です。仮に、エクセルシートの管理が他の人の場合、これ以上下にメモ書き等を書かれたりした場合、処理が長くなったり、プログラムが正確に動作しなくなる可能性もあるので、その点は注意です。
[2-4]最後に、forループで、エクセルシートの行を上から下へテキストボックスで入力した値と同一のものがあるかどうか検索していきます。再度プログラムを掲載します。
//[2-4]forループで、エクセルの行を最終行までサーチします。
for (int i = 1; i <= lastRow; i++)
{
IXLCell get_cell = worksheet.Cell(i, 1);//[2-4-1]
string compare_text = get_cell.Value.ToString();//[2-4-2]
//[2-4-3]
if (original_text.Equals(compare_text))
{
IXLCell data = worksheet.Cell(i, 2);
string data_strings = data.Value.ToString();
Console.WriteLine(data_strings);
}
}
[2-4-1]では、セルを指定しています。iはループで増加していく値です。1回目のときは(1,1)、セルで言うと、(A,1)のセルが指定されます。2ループ目では、(2,1)、セルの(B,1)が入ります。このように、ループ毎に、セルの行が下へと変化していきます。
[2-4-2]では、セル内の値を文字列に変換して、文字列変数へと取得する処理となります。セル内の文字列をoriginal_textとして取得しています。
[2-4-3]では、セル内の文字列と、テキストボックスに入力された文字列が同一化どうかを判定しています。C#の文字列は、.Equalsメソッドによって、文字列の比較ができます。
文字列が一致した場合、(i,2)のセル、2列目のセルを指定して、文字列として取り出しています。そして、Console.WriteLine関数で出力を行います。