Excelファイルへの保存処理
このプログラムでは、フォームに配置した[保存]ボタンをクリックすると、列セルに入力されたデータとヘッダセクションにある一部のデータを、Excelを起動してブックに保存します。
Excelの操作は、すべて[保存]ボタンのClickイベントハンドラで行い、Excelをオブジェクトとして扱います。Excelの各オブジェクトとそのメンバを操作するので、ある程度VBAの知識が必要になりますが、本稿ではVBAおよびExcelのオブジェクト構造に関しての詳細な説明は割愛させていただきます。
今回、データを入力するExcelのブック「売上集計.xls」は、次の手順でプロジェクトに組み込んであります。この方法であれば、データファイルを持ち歩く必要はありません。
- Visual Studioのメニューから、[プロジェクト]-[既存項目の追加]を選ぶ
- 「ファイルを開く」ダイアログのファイルフィルタのリストから[すべてのファイル(*.*)]を選択し、「売上集計.xls」を選択して[追加]ボタンをクリックする
- ソリューションエクスプローラで、プロジェクトに追加された「売上集計.xls」を選択する
- プロパティウィンドウの「出力ディレクトリにコピー」の値を、「新しい場合はコピーする」に変更する
事前準備
Excelをオブジェクトとして操作するため、参照設定が必要になります。
ソリューションエクスプローラの[参照設定]でショートカットメニューを表示し、[参照の追加]を選択します。そして、「Com」タブをクリックして「Microsoft Excel 11.0 Object Library」を選びます。「Excel 11.0」がExcel 2003、「Excel 12.0」がExcel 2007です(ちなみに「Excel 14.0」はExcel 2010のβバージョンです)。この参照設定を行わないと、Excelを操作することができません。
また、フォーム表示時の「受注年月日」に現在の日付を表示するように、Loadイベントハンドラに処理を作成します。
Imports GrapeCity.Win.MultiRow Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.GcMultiRow1.ColumnHeaders(0).Cells("LabelCell6").Value = Format(Date.Today, "D") End Sub
入力データの取得
最初に、Rowセクションのセルに入力されたデータおよび、ヘッダセクションに入力されたデータを配列に格納します。配列は2次元配列を使用し、1レコードずつ7つのセルデータを取得し、格納します。取得するデータは次のセルです。
- ヘッダーセクション
- 購入年月日
- 受注番号
- Rowセクション
- 商品名
- 商品番号
- 個数
- 単価
- 合計金額
GcMultiRowクラスのRowCountプロパティを参照すると入力されている行数が分かるので、これを使って配列を再確保します。
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cnt As Integer = 0 Dim i As Integer Dim getdata(0, 7) As String cnt = Me.GcMultiRow1.RowCount - 1 ReDim getdata(cnt, 7)
データの取得には、Do...Loop...Whileステートメントを使用し、この行数を使って1行ずつ列データを配列に格納していきます。また、購入年月日と受注番号も一緒に格納していきます。
Do getdata(i, 0) = Me.GcMultiRow1.ColumnHeaders(0).Cells("LabelCell6").Value getdata(i, 1) = Me.GcMultiRow1.ColumnHeaders(0).Cells("TextBoxCell5").Value getdata(i, 2) = Me.GcMultiRow1.GetValue(i, "TextBoxCell1") getdata(i, 3) = Me.GcMultiRow1.GetValue(i, "TextBoxCell2") getdata(i, 4) = Me.GcMultiRow1.GetValue(i, "NumericUpDownCell1") getdata(i, 5) = Me.GcMultiRow1.GetValue(i, "NumericUpDownCell2") getdata(i, 6) = Me.GcMultiRow1.GetValue(i, "SummaryCell1") i += 1 Loop While i < cnt
取得したデータをExcelのブックに保存する
配列にデータを格納したら、Excelのブックに転送します。実行ファイルに格納しているように、列見出しを付けた「売上集計.xls」をあらかじめ作成し、ここに転送させます。転送データは、ワークシート「集計表2009」の3行目に行を挿入し、常にこの位置に転送するようにします(既に入力されたデータは順番に下の行にさがっていきます)。
最初に、Excelのインスタンスを作成します。以降、Excelの各オブジェクトはこのインスタンスを使って操作します。Excelは、インスタンスを作成しただけではバックグラウンドで動作するだけなのでそのまま操作することも可能ですが、動作確認のために目に見えるようにVisibleプロパティを「True」にします。そして、WorkbooksコレクションのOpenメソッドでブックを開きます。
Dim fname As String = Application.StartupPath & "\" & "売上集計.xls" Dim ex As Microsoft.Office.Interop.Excel.Application ex = New Microsoft.Office.Interop.Excel.Application With ex .Visible = True .Workbooks.Open(fname)
この方法はExcelのCOM参照が追加されている場合のみ有効です。
なお、記事のサンプルソースをリビルドすると、ExcelのコアDLLであるInterop.Office.dllが削除されてビルドエラーになってしまう場合があります。回避策として、CreateInstanceメソッドを使用してExcelのインスタンスを作成する方法があります。
Dim excelApplicationType As Type = Type.GetTypeFromProgID("Excel.Application") If excelApplicationType Is Nothing Then MessageBox.Show("Excel.Applicationの読み込み中にエラーが発生しました。処理を中断します。") Return End If Dim ex As Object = Activator.CreateInstance(excelApplicationType) With ex .Visible = True .Workbooks.Open(fname)
そして、For...Nextステートメントで配列データをワークシートのセルに転送します。その際、1回ループが回るたびに(1レコード分の配列データを転送するたびに)、ワークシートの3行目に新しい行を挿入し、その行にデータを転送します。
With .Worksheets("集計表2009") For i = 0 To cnt - 1 .Rows(3).insert() .Cells(3, 1) = getdata(i, 0) .Cells(3, 2) = getdata(i, 1) .Cells(3, 3) = getdata(i, 2) .Cells(3, 4) = getdata(i, 3) .Cells(3, 5) = getdata(i, 4) .Cells(3, 6) = getdata(i, 5) .Cells(3, 7) = getdata(i, 6) Next End With
データがセルに転送されたら、Saveメソッドでブックを上書き保存し、QuitメソッドでExcelを終了します。バックグラウンドでExcelの処理を行わせている場合は、必ずQuitメソッドでExcelを終了させないとプロセスにいつまでもExcelが残ってしまいます。また、2番目のインスタンスでブックを開くと読み取り専用で開かれるため、ブックが保存できなくなるので注意してください。
.ActiveWorkbook.Save() '.Quit() End With End Sub
これで、[保存]ボタンを押すたびに次々とデータをブック「売上集計.xls」に蓄積されていくようになりました。