はじめに
Visual Studioで作成したアプリケーションは、意外と計測プログラムにも使われることがあります。作りやすいインターフェースとRS232などを使った通信機能で、計測機器とデータのやり取りができます。
しかし、問題となるのはデータの保存方法です。できれば汎用のフォーマットで保存し、いろいろなアプリケーションで加工できるようにしたいものです。
PowerTools XLS for .NETのC1XLBookは、アプリケーションにMicrosoft Excelファイルの読込/書込機能を実装できるコントロールです。Excelのブックやワークシートをアプリケーションから作成し、セルにデータを保存できます。もちろん、保存したブックはExcelと完全互換しています。
そこで今回は、乱数ジェネレータで作成した乱数をラベルに表示し、そのデータをExcelのブックに保存する計測アプリケーションを作成してみました。なお、データの計測状況を表示するために、PowerTools Ribbon for Windows Formsのステータスバーも使用しています。
対象読者
Visual Basic、Visual C# 2010を使ってプログラムを作ったことのある人
必要な環境
Visual Basic 2010、Visual C# 2010、Visual Studio 2010でプログラムが作れる環境。なお、本プログラムはWindows 7(64bit)で動作するVisual Studio 2010を使用して作成し、動作確認を行っています。
プログラム実行時の注意事項
PowerTools XLS for .NETおよびRibbon for Windows Formsを使って作成したアプリケーションを配布する場合、PowerTools XLS for .NETとRibbon for Windows Formsのアセンブリファイルを添付する必要があります。これは、Common Language RuntimeのDLLをアプリケーションと一緒に配布するのと同じです。
本記事のサンプルアプリケーションを正常に動作させるためには、次のファイルをインストールする必要があります。
ファイル名 | 説明 |
C1.C1Excel.2.dll | 本体アセンブリ |
C1.C1Excel.4.dll | 本体アセンブリ(※.NET Framework 4でのみ使用可) |
C1.Win.C1Ribbon.2.dll | 本体アセンブリ |
C1.Win.C1Ribbon.4.dll | 本体アセンブリ(※.NET Framework 4でのみ使用可) |
上記のファイルを、プログラムを実行するフォルダに格納します。.NET Framework 2.0から追加されたクラスやメンバを使用しているため、バージョン2.0以上の.NET Frameworkがインストールされていることが必須条件です。
コンポーネントのインストール
この記事の手順を試すには、Visual Studio、Visual Basic、Visual C#の開発環境にComponentOne Studio Enterprise 2012J をインストールする必要があります。インストーラは、グレープシティのWebページからダウンロードできます。
製品のトライアル版一覧ページにてダウンロードしたい製品にチェックを入れ、ページ右上部の[申込フォーム]をクリックしてグレープシティのWebサイトへ必要情報を登録すると、添付トライアルライセンスキーファイルとダウンロードサイトを記載したEメールが送られてきますので、ここからダウンロードします。制限事項などの詳細については、インストーラに同梱されているリリースノートを参照ください。
コントロールの追加
インストールが終了したら、ツールボックスに専用のタブを作成し、プロジェクトに使用する次の2つのコントロールを追加します。
アセンブリ名 | コントロール |
C1.C1Excel | C1XLBook |
C1.Win.C1Ribbon | C1StatusBar |
C1XLBookコントロールについて
C1XLBookは、これから作成するアプリケーションにMicrosoft Excelファイルの読み書き機能を追加するコントロールです。Microsoft Excelファイルの読み書きに、Excel97以降で採用されているBIFF8(.xls)形式、およびMicrosoft Office System 2007でMicrosoft Excelファイルのデフォルト形式として使用されるOpen XML形式(.xlsx)のファイルを利用できます。XLSX形式のファイルは再利用性に優れ、簡単なファイル交換、圧縮性など豊富な機能を提供します。
このコントロールを使うと、アプリケーションのデータをMicrosoft Excelで開くことができる「XLS」ファイルを作成できます。さらに、複数のワークシートで構成されるXLSブックのセルの内容と書式もそのままロードできるようになっています(ただしMicrosoft Excelに保存されているすべての要素を認識できるわけではないため、注意してください)。
C1XLBookコントロールの大きな特徴は、高度な操作性です。たった1つのコマンドでブックをロードしたり、行や列、セルで構成されているシートをグリッドコントロールのような使い勝手で編集できるのです。また、編集後はXLSファイルをブックとして保存することもできます。
なお、C1XLBookコントロールはUIを持たず、プロセスとしてその機能を提供するため、フォームには表示されません。
C1XLBookコントロールの主な機能
C1XLBookコントロールは、次のような機能を持っています。
-
Excelブックの新規作成、保存
コードから、新しいExcelブックを作成できます。また、作成したブックを保存できます。
-
ワークシートの作成
作成したブックに、複数のワークシートを組み込むことができます。ワークシートにはデータを格納するセルを持っています。このセルには、文字や数字、画像データを挿入できます。
-
セルの操作、セルへのアクセス
ワークシート上には、行列番号で管理されるセルを持っています。このセルに値を入れたり、幅や高さを設定できます。セルへは、先頭行、先頭列ともに「0」から始まる行列番号(インデックス番号)でアクセスします。
-
セルのスタイル設定
セルの背景色や文字色、フォント、レイアウト、書式設定などのスタイルを設定できます。スタイルは複数持つことができますので、行列あるいはセルごとに別々のスタイルを設定できます。
-
Open XML形式のファイルのロード・保存
Microsoft Excel 2007で採用されたOpen XML形式のファイルのロード・保存ができます。Open XML形式のファイルをロード・保存するには、ファイル拡張子を「.xlsx」に設定します。これだけで、データをOpen XML形式のファイルとして保存したり読み出すことができます。
C1StatusBarコントロールについて
C1StatusBarは、本来はリボンフォームの下部に表示され、データや情報の表示やボタン、プログレスバー、各種ピッカー、各種入力ボックスを組み込むことができる多機能ステータスバーです。しかし、通常のWindowsフォームに組み込んで使うこともできます。
このコントロールは、右ペインと左ペインに分かれ、それぞれ次のアイテムを組み込むことができます。
また、アイテムには画像とテキストを表示できます。デフォルトで多くの画像がプリセットされています。
ステータスバーに組み込んだアイテムのイベント処理は、それぞれのアイテムごとに設定されているイベントを利用します。また、両ペインとも、アイテムの追加や編集を行うコレクションエディタを持っています。
フォームの作成
では、フォームを作成します。このプログラムでは、計測機器から読み込んだデータをExcelのブック形式で保存します。ただし、実際に計測機器を接続したプログラムにしてしまうとハードウェアに依存してしまい、サンプルアプリケーションとしてふさわしくないため、ここでは乱数を利用してプログラム側で擬似的にデータを作成し表示する方法を使いました。
作成した乱数の表示にはLabelコントロールを使います。また、ステータスバーには、ラベル、プログレスバー、ボタンの3つのコントロールを組み込みます。プログラムでは、1秒ごとに1つのデータを作成するため、TimerコントロールのTickイベントを利用します。
GUIのデザイン
Labelコントロールは全部で21個使用します。データを表示するLabelコントロールでは3Dの枠線を設定し、Label2,4,6...と偶数のコントロール名になるように作成します。これは、コードからループ処理を利用して乱数を表示させるためです。
Timerコントロールは[計測開始]ボタンをクリックすると始動するようにします(C1XLBook、C1StatusBarの設定については後述します)。
コントロールの配置
コントロールの配置手順は、以下のような流れになります。
- このプログラムのポイントの1つは、データ表示処理を自動化するためにLabelコントロールの名前を揃える点です。前述したように、21個のLabelコントロールのうち、データ表示用は偶数の名前になるよう設定しています。
- Buttonコントロールには、Timerコントロールの動作を制御するのに使用するため、Clickイベントハンドラを作成します。
- Timerコントロールでは、1秒おきにデータ表示処理を行うため、Intervalプロパティを「1000」ミリ秒に設定します。EnabledプロパティをFalseのままにし、Tickイベントハンドラを作成します。
- C1XLBookコントロールは、処理をすべてコードから行うため、プロパティ設定などはありません。
- フォームは、FormBordeStyleプロパティを「Fixed3D」にします。
C1StatusBarコントロールの設定
C1StatusBarコントロールは、左側のペインにラベルを、右のペインにプログレスバーとボタンを設定します。
まず、ツールボックスからC1StatusBarコントロールをフォーム下部にドラッグ&ドロップします。左ペインから、フローティングツールバーの[アクション]ボタンをクリックするとアイテム一覧のリストが表示されるので、[ラベルの追加]をクリックします。これで、左ペインにラベル(RibbonLabelコントロール)が組み込まれます。
組み込まれたラベルをクリックすると、プロパティウィンドウがRibbonLabelコントロールのプロパティに切り替わるため、Textプロパティを「ボタンを押すと計測を開始します」に変更します。
次に、C1StatusBarコントロールの右ペインをクリックし、フローティングツールバーの[アクション]ボタンをクリックします。左ペインと同じようにアイテム一覧のリストが表示されたら、「プログレスバーの追加」をクリックして、右ペインにプログレスバー(RibbonProgressBarコントロール)を組み込みます。
組み込まれたプログレスバーをクリックしてプロパティウィンドウをRibbonProgressBarコントロールに切り替え、次のプロパティを設定します。
プロパティ | 設定値 |
Maximum | 10 |
Minimum | 0 |
Step | 1 |
Width | 150 |
プログレスバーは、MaximumプロパティとMinimumプロパティの範囲で動作します。Stepプロパティはバーの進行の増加分を設定するプロパティです。ここでは、0から10の範囲で1ずつ増えていくようプログレスバーを設定します。
ここで、右ペインがプログレスバーで一杯になったので、右ペインの幅を広げます。C1StatusBarコントロール全体をクリックして、プロパティウィンドウをC1StatusBarに切り替えます。そして、RightPaneWidthプロパティを「300」に設定します。これで、右ペインの幅が広がりプログレスバーの横に他のアイテムを挿入するスペースができます。
再度右ペインから、フローティングツールバーの[アクション]ボタンをクリックします。アイテム一覧のリストから[ボタンの追加]をクリックし、右ペインにボタン(RibbonButtonコントロール)を追加します。
追加したボタンをクリックし、フローティングツールバーから「テキストの設定」を選びます。そして、テキストを「データをExcelで表示」に変更します。
もう一度フローティングツールバーを表示し、「画像の変更」を選びます。そして「小画像」の「画像の選択」リストから「Table」を選びます。これで、アイコン付きのボタンができあがります。
RibbonButtonコントロールをクリックしてプロパティウィンドウをRibbonButtonコントロールに切り替え、VisibleプロパティをFalseに設定し、ボタンを非表示にしておきます。プロパティ表示をイベント表示に変更し、[Click]をダブルクリックしてイベントハンドラを作成します。
コードの作成
フォームのデザインができあがったら、コードを作成します。コードは、TimerコントロールのTickイベントハンドラがメインの処理になりますが、データの保存処理は独自のプロシージャ(メソッド)「write_xls」を作成してここに記述します。
タイマーのイベント処理
TimerコントロールのTickイベントハンドラでは、乱数を作成しその値を10個のLabelコントロールに表示する処理を行います。Tickイベントが発生する1000ミリ秒(1秒)ごとに1つのデータを作成し、LabelコントロールのTextプロパティにセットします。
併せて、ステータスバーに作成したプログレスバー(RibbonProgressBarコントロール)のValueプロパティを1つ増やし、プログレスバーを表示させます。
10個のデータを作成し終わった時点で、ステータスバーのラベル(RibbonLabelコントロール)に計測終了のメッセージを表示し、データをExcelブック形式で保存する処理を呼び出します。なお、名前空間「C1.C1Excel」を宣言しておいてください。
Imports C1.C1Excel Public Class Form1 Private rd As Double = 0 Private cnt As Integer = 0 Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick '乱数の作成 Dim rdm As Random = New Random() rd = rdm.NextDouble() Dim cntlname As String = "Label" + cnt.ToString 'Labelコントロールへのアクセス用コントロール名の作成 Me.Controls(cntlname).Text = rd.ToString 'Labelコントロールに乱数を代入 RibbonProgressBar1.Value += 1 ' プログレスバーを表示 cnt += 2 '次のLabelコントロール名の作成 '計測終了処理 If cnt > 20 Then Timer1.Enabled = False RibbonLabel1.Text = "計測が終了しました。" write_xls() 'Excelブック形式の保存処理を呼び出す Exit Sub End If End Sub
using C1.C1Excel; namespace data_xlsave_cs { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private double rd = 0; private int cnt = 0; private void timer1_Tick(object sender, EventArgs e) { //乱数の作成 Random rdm = new Random(); rd = rdm.NextDouble(); string cntlname = "Label" + cnt.ToString(); //Labelコントロールへのアクセス用コントロール名の作成 this.Controls[cntlname].Text = rd.ToString(); //Labelコントロールに乱数を代入 ribbonProgressBar1.Value += 1; // プログレスバーを表示 cnt += 2; //次のLabelコントロール名の作成 //計測終了処理 if (cnt > 20) { timer1.Enabled = false; ribbonLabel1.Text = "計測が終了しました。"; write_xls(); //Excelブック形式の保存処理を呼び出す return; } }
計測開始・リセット処理
計測を開始する処理と、一度計測が終了したあとに再度計測を行う時のリセット処理を、[計測開始」ボタンのClickイベントハンドラに作成します。
ここでは、タイマーを開始してステータスバーのラベルに「計測中」の文字を表示し、プログレスバーの値を「0」にセットします。
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click Timer1.Enabled = True 'タイマースタート RibbonLabel1.Text = "計測中" 'ステータスバーの表示 '計測リスタート時のリセット処理 RibbonProgressBar1.Value = 0 cnt = 2 End Sub
private void button1_Click(object sender, EventArgs e) { timer1.Enabled = true; //タイマースタート ribbonLabel1.Text = "計測中"; //ステータスバーの表示 //計測リスタート時のリセット処理 ribbonProgressBar1.Value = 0; cnt = 2; }
データの保存処理
Labelコントロールで表示したデータを、Excelのブック形式で保存する処理を作成します。これは、専用のプロシージャ(メソッド)「write_xls」を作成して記述します。このプロシージャ(メソッド)は戻り値も引数も持ちません。処理を実行するだけです。
最初に、データを保存するフォルダ名を作成します。これは、アプリケーションが実行するフォルダと同じフォルダに格納するようにします。この変数は、2つのプロシージャ(メソッド)で共有するので、クラス変数として宣言します。
Private savefname As String = Application.StartupPath + "\MeasureData.xls"
private string savefname = Application.StartupPath + "/MeasureData.xls";
プロシージャ(メソッド)「write_xls」では、最初にC1XLBookコントロールのワークシートへの参照を作成します。ワークシートは「XLSheetCollection」というコレクションオブジェクトになっており、C1XLBookコントロールの「Sheets」プロパティを使い、0から始まるインデクサを引数に指定して個々のシートを指定します。
Dim sheet As XLSheet = C1XLBook1.Sheets(0) 'ワークシートへの参照を作成
XLSheet sheet = c1XLBook1.Sheets[0]; //ワークシートへの参照を作成
個々のワークシートは「XLSheet」というオブジェクトになっており、セルは「XLCell」オブジェクトで操作します。セルへのアクセスはワークシートの参照を格納している変数に、行列番号のインデクサを指定して行います。
行列番号は一番左上のセルを(0,0)とし、列は右方向に、行は下方向に番号が増えていきます。このセルへのアクセスは、実はXLSheetオブジェクトのGetCellメソッドを呼び出しており、引数は(行番号,列番号)の順番で指定するようになっています。
ここでは、先頭のセルに「計測結果」という文字列を代入し、その隣の列のセルに作成日時を格納します。
sheet(0, 0).Value = "計測結果" sheet(0, 1).Value = System.DateTime.Now.ToString()
sheet[0, 0].Value = "計測結果"; sheet[0, 1].Value = System.DateTime.Now.ToString();
そして、For...Nextステートメントを使って、Labelコントロールで表示しているデータをセルの2列目に代入していきます。1列目のセルには、「Data1, Data2, Data3...」とデータの位置を表す文字列を代入します。セルに値を代入するには、セルを表すオブジェクトの「XLCell」クラスのValueプロパティに値を代入します。
For i = 1 To 10 sheet(i, 0).Value = "Data" + i.ToString() cntlname = "Label" + (i * 2).ToString() sheet(i, 1).Value = Convert.ToDouble(Me.Controls(cntlname).Text) Next i
for(i=1; i<=10; i++) { sheet[i, 0].Value = "Data" + i.ToString(); cntlname = "Label" + (i * 2).ToString(); sheet[i, 1].Value = Convert.ToDouble(this.Controls[cntlname].Text); }
セルに値を代入したら、セルの文字装飾を行います。まず、セルの装飾は「XLStyle」クラスのインスタンスを作成してメンバプロパティを操作し、「XLStyle」オブジェクトをセルのStyleプロパティにセットします。
スタイルはいくつも作成できるため、セルごとや行列ごとに違うスタイルを設定することが可能です。ここでは、データ表示用に文字色が「DarkBlue」でセルの値を右詰めで表示するスタイルと、データ番号のラベル用に文字色を「MediumSeaGreen」にセットするスタイルの2つを作成します。そして、このスタイルをColumnsプロパティを使用して、1列目と2列目のセルそれぞれに適用します。
また、XLColumnクラスのWidthプロパティを使用して列幅を設定します。Widthプロパティは列の幅をtwips単位で取得または設定するプロパティです。設定値をピクセルで行いたい場合は、TwipsToPixels(Double)とPixelsToTwips(Double)メソッドを用いて単位変換します。
'セルのスタイル設定 Dim style1 As New XLStyle(C1XLBook1) style1.ForeColor = Color.DarkBlue style1.AlignHorz = XLAlignHorzEnum.Right 'セルの値を右詰で表示 Dim style2 As New XLStyle(C1XLBook1) style2.ForeColor = Color.MediumSeaGreen sheet.Columns(0).Style = style1 sheet.Columns(0).Width = 1000 sheet.Columns(1).Style = style2 sheet.Columns(1).Width = 1500
//セルのスタイル設定 XLStyle style1 = new XLStyle(c1XLBook1); style1.ForeColor = Color.DarkBlue; style1.AlignHorz = XLAlignHorzEnum.Right; //セルの値を右詰で表示 XLStyle style2 = new XLStyle(c1XLBook1); style2.ForeColor = Color.MediumSeaGreen; sheet.Columns[0].Style = style1; sheet.Columns[0].Width = 1000; sheet.Columns[1].Style = style2; sheet.Columns[1].Width = 1500;
データをセルに代入したら、ブックを保存します。これは、C1XLBookコントロールのSaveメソッドを実行します。引数はファイル名をフルパスで指定します。
そして、保存が完了したらステータスバーに組み込んで非表示にしていた[データをExcelで表示]ボタンを表示状態にします。
C1XLBook1.Save(savefname) 'ブック保存処理 RibbonButton1.Visible = True 'ステータスバーのボタンを表示
c1XLBook1.Save(savefname); //ブック保存処理 ribbonButton1.Visible = true; //ステータスバーのボタンを表示
データの保存が完了したら、Excelでブックを開きます。これは、ProcessクラスのStartメソッドを実行します。
Dim rtn As DialogResult = MessageBox.Show("Excelで表示しますか?", "データの表示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) If rtn = DialogResult.Yes Then System.Diagnostics.Process.Start(savefname) End If
DialogResult rtn = MessageBox.Show("Excelで表示しますか?", "データの表示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if(rtn == DialogResult.Yes) { System.Diagnostics.Process.Start(savefname); }
ステータスバーの[データをExcelで表示]ボタンがクリックされた時も、同じようにExcelを起動して保存したブックを表示します。
Private Sub RibbonButton1_Click(sender As System.Object, e As System.EventArgs) Handles RibbonButton1.Click System.Diagnostics.Process.Start(savefname) End Sub
private void ribbonButton1_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start(savefname); }
write_xlsのコードをまとめると、次のようになります。
'アプリケーションと同じフォルダにXLSファイルを保存 Private savefname As String = Application.StartupPath + "\MeasureData.xls" Private Sub write_xls() 'Excelブック形式の保存処理 Dim i As Integer Dim sheet As XLSheet = C1XLBook1.Sheets(0) 'ワークシートへの参照を作成 Dim cntlname As String = "" 'セルへの入力処理 sheet(0, 0).Value = "計測結果" sheet(0, 1).Value = System.DateTime.Now.ToString() For i = 1 To 10 sheet(i, 0).Value = "Data" + i.ToString() cntlname = "Label" + (i * 2).ToString() sheet(i, 1).Value = Convert.ToDouble(Me.Controls(cntlname).Text) Next i 'セルのスタイル設定 Dim style1 As New XLStyle(C1XLBook1) style1.ForeColor = Color.DarkBlue style1.AlignHorz = XLAlignHorzEnum.Right 'セルの値を右詰で表示 Dim style2 As New XLStyle(C1XLBook1) style2.ForeColor = Color.MediumSeaGreen sheet.Columns(0).Style = style1 sheet.Columns(0).Width = 1000 sheet.Columns(1).Style = style2 sheet.Columns(1).Width = 1500 C1XLBook1.Save(savefname) 'ブック保存処理 RibbonButton1.Visible = True 'ステータスバーのボタンを表示 Dim rtn As DialogResult = MessageBox.Show("Excelで表示しますか?", "データの表示", MessageBoxButtons.YesNo, MessageBoxIcon.Question) If rtn = DialogResult.Yes Then System.Diagnostics.Process.Start(savefname) End If End Sub Private Sub RibbonButton1_Click(sender As System.Object, e As System.EventArgs) Handles RibbonButton1.Click System.Diagnostics.Process.Start(savefname) End Sub End Class
//アプリケーションと同じフォルダにXLSファイルを保存 private string savefname = Application.StartupPath + "/MeasureData.xls"; private void write_xls() { int i=0; XLSheet sheet = c1XLBook1.Sheets[0]; //ワークシートへの参照を作成 string cntlname = ""; //セルへの入力処理 sheet[0, 0].Value = "計測結果"; sheet[0, 1].Value = System.DateTime.Now.ToString(); for(i=1; i<=10; i++) { sheet[i, 0].Value = "Data" + i.ToString(); cntlname = "Label" + (i * 2).ToString(); sheet[i, 1].Value = Convert.ToDouble(this.Controls[cntlname].Text); } //セルのスタイル設定 XLStyle style1 = new XLStyle(c1XLBook1); style1.ForeColor = Color.DarkBlue; style1.AlignHorz = XLAlignHorzEnum.Right; //セルの値を右詰で表示 XLStyle style2 = new XLStyle(c1XLBook1); style2.ForeColor = Color.MediumSeaGreen; sheet.Columns[0].Style = style1; sheet.Columns[0].Width = 1000; sheet.Columns[1].Style = style2; sheet.Columns[1].Width = 1500; c1XLBook1.Save(savefname); //ブック保存処理 ribbonButton1.Visible = true; //ステータスバーのボタンを表示 DialogResult rtn = MessageBox.Show("Excelで表示しますか?", "データの表示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if(rtn == DialogResult.Yes) { System.Diagnostics.Process.Start(savefname); } } private void ribbonButton1_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start(savefname); }
まとめ
データの保存フォーマットに、Windows PCではもはや定番となっているExcel形式を取り入れることで、データの加工やポータビリティ性が高くなります。現代では、ブラックボックス化されたバイナリデータよりも、誰でも閲覧可能なデータ形式のほうが受け入れられやすくなってきています。
一方、C1StatusBarコントロールは、ただ単に情報を表示するだけでなく、ボタンやラベル、プログレスバーなど多くのコントロールをペインに組み込むことができるため、すっきりと情報整理ができ、フォームの視覚効果も高くなります。
C1XLBookコントロールは、Excelを使ったことがある人ならすぐに使えるオブジェクト構成になっています。アプリケーションのデータ保存に頭を悩ませている方は、ぜひ導入を検討してみてはいかがでしょうか。