C#でExcelに文字列や数値や数式(関数)を書き込む方法
C#で作ったアプリから、Excelに文字列や数値や数式およびExcel関数を書き込む方法です。
目次
ライブラリの参照を追加する
C#からExcelを呼び出せるように、ライブラリの参照を追加します。
まず、ソリューションエクスプローラーの「参照」を右クリックして、右クリックメニューの中から「参照の追加」を選択します。
そうすると、参照マネージャーのウィンドウが表示されます。そうしたら、「COM」の中のMicrosoft Excel xx.x Object Libraryにチェックを付けて、「OK」をクリックします。
すると、ソリューションエクスプローラーの「参照」の下に、Microsoft.Office.Interop.Excelが追加されます。
コードのusingのところに、Microsoft.Office.Interop.Excelを追加します。その際、MainWindowクラスの継承元のWindowのところに警告が出ます。これは、Microsoft.Office.Interop.Excel名前空間と System.Windows名前空間の両方にWindowという定義があるためです。MainWindowクラスの継承元をSystem.Windows.Windowに指定すれば警告は解消されます。
using Microsoft.Office.Interop.Excel;
namespace excel_test
{
public partial class MainWindow : System.Windows.Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
Excelファイルを開いてシートに書き込みをする
概ね下記の手順で処理をします。
Applicationオブジェクトを作成。
Workbooksオブジェクトを作成。
Workbookオブジェクトを作成してファイルを開く。
Worksheetオブジェクトを作成して、シートを選択する。
Rangeオブジェクトを作成して、シートに書き込む範囲を選択する。
RangeオブジェクトのValue2かFormulaプロパティに、データを書き込む。
ファイルに書き出す。
クローズ処理。
Excelファイルに書き込みをする実施例
実施例として、既存のExcelファイルに文字列・数値・数式を書き込むアプリを作ってみます。
具体的には、アプリを起動してWindowがロードされたら、既存のExcelファイルにデータを書き込んで保存するアプリを作ります。
書き込む配列がstringの場合とobjectの場合、さらにRangeオブジェクトのValue2を使う場合とFormulaを使う場合で書き込んだ結果が変わりますので、それぞれを試してみます。
XAML
XAMLはWindowにLoadedイベントを追加しただけです。
実行すると、ただのウィンドウが表示されます。
<Window x:Class="excel_test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:excel_test"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
<Grid>
</Grid>
</Window>
コード
using System.Windows;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
namespace excel_test
{
public partial class MainWindow : System.Windows.Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// 書き込むデータを設定する。
string[] StringInput = new string[] { "a1", "1", "2", "=1+2", "=sum(B2+B3)" };
object[] ObjectInput = new object[] { "a1", 1, 2, "=1+2", "=sum(B2+B3)" };
// シートを開く。
Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
ExcelApp.Visible = true;
Workbooks ExcelWBs = ExcelApp.Workbooks;
Workbook ExcelWB = ExcelWBs.Open(@"C:\Users\xxx\source\repos\excel_test\excel_test\excel_test\bin\Debug\test.xlsx");
Worksheet ExcelWorksheet = ExcelWB.Sheets[1];
ExcelWorksheet.Select();
// シートへ書き込みする。
Range OutputRange1 = ExcelWorksheet.Range[ExcelWorksheet.Cells[1, 1], ExcelWorksheet.Cells[1, 5]];
OutputRange1.Value2 = StringInput;
Range OutputRange2 = ExcelWorksheet.Range[ExcelWorksheet.Cells[2, 1], ExcelWorksheet.Cells[2, 5]];
OutputRange2.Value2 = ObjectInput;
Range OutputRange3 = ExcelWorksheet.Range[ExcelWorksheet.Cells[3, 1], ExcelWorksheet.Cells[3, 5]];
OutputRange3.Formula = ObjectInput;
// ファイルへ書き込みする。
ExcelWB.SaveAs(@"C:\Users\xxx\source\repos\excel_test\excel_test\excel_test\bin\Debug\test.xlsx");
ExcelWB.Close();
// オブジェクトを破棄する。
Marshal.ReleaseComObject(OutputRange1);
OutputRange1 = null;
Marshal.ReleaseComObject(OutputRange2);
OutputRange2 = null;
Marshal.ReleaseComObject(OutputRange3);
OutputRange3 = null;
Marshal.ReleaseComObject(ExcelWorksheet);
ExcelWorksheet = null;
Marshal.ReleaseComObject(ExcelWB);
ExcelWB = null;
Marshal.ReleaseComObject(ExcelWBs);
ExcelWBs = null;
// ガベージコレクションを実行する。
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
// アプリケーションを終了する。
ExcelApp.Quit();
// Appricationオブジェクトを破棄する。
Marshal.ReleaseComObject(ExcelApp);
ExcelApp = null;
// Appricationオブジェクトのガベージコレクションを実行する。
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
}
}
基本的に、上記で書いた処理手順の通りのコードになっています。
実行結果
実行して出力されたExcelファイルを開くと、このようになります。
stringの配列をExcelに書き込んだデータは、各セルの書式が文字列になっています。
objectの配列の場合は、文字列は文字列に、数値は数値に、数式は数式になっています。
書き込み用のデータを作るときに、配列の段階で型を合わせておかなければいけないということですね。
オブジェクトの破棄とガベージコレクション
ファイルに書き込んだ後に、Excel関連のオブジェクトを破棄したり、意図的にガベージコレクションをしたりしています。
これをしないと、アプリを終了してもExcelのプロセスが消えずに残り続けます。
これは、Excelをアプリから起動するときにCOMオブジェクトというものの参照がのカウントが追加されるのですが、カウントを追加したままアプリを終了すると、Excelのプロセスが参照されたままという扱いになるためです。
そこで、Marshal.ReleaseComObjectメソッドを使ってこの参照カウントを減算し、Excelのプロセスを終了できるようにします。
詳しくは、 マイクロソフトの記事 を参照してください。 オブジェクトの解放 についても書かれています。
公開日
広告