Excel の拡張機能を作るためのフレームワークです。Excel 表の操作(データの読み取りと更新)を簡略化します。
機能
ワークブックやワークシートから Excel の表(ListObject) を見つける機能と、表のデータを読み取る機能、および、表をデータで更新したり置換したりする機能を提供します。Excel 表を新しく挿入することもできます。
// 例1: Excel 表から ID列、Title列、Value列 の値を読み取るケース(C#)
private class Sample1
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
// アクティブな Excel 表を読み取る
IEnumerable<Sample1> rows = ExcelMacaron.ActiveTable.ReadTable<Sample1>( );
}
Excel 表・セルを見つける
- ExcelMacaron.ActiveTable : アクティブな Exce 表 を返します。(他に ExcelMacaron の ActiveCell, ActiveSheet, ActiveWorkbook もあり、表の操作とセル・ワークシート・ブックの操作で ExcelMacaron と Application を書き分ける必要がありません)
- FindTable : Excel 表を見つけます。
- GetCell : ワークシートのセルを取得します。行インデックスと列インデックスを数値で指定するか、セルの位置を(”A1″ のような形式で)テキストで指定します。(オーバーロードで使い分けできて、Worksheet の Cells や Range を書き分ける必要がありません)
表の読み取り
- ReadTable : Excel 表を読み取ります。指定した型のオブジェクトとして受け取ります。
表の作成・更新・置換
- InsertTable : 新しい Excel 表 を挿入し、各行に指定されたデータを設定します。
- UpdateTable : 指定したデータで Excel 表を更新します。(Excel 表の挿入は行いません。)
- UpdateInsertTable : 指定したデータで Excel 表を更新します。Excel 表に含まれない行は新たに挿入されます。
- ReplaceTable : Excel 表のデータを置換します。置換を行うラムダ式・匿名関数を指定します。
- SetReadOnlyUsingDataValidation : データの入力規制 を使用して、セルを読み取り専用にします。
Excel の制御
- SuspendScreenUpdating : Excel の画面描画を停止し、using ブロック終了時に自動的に再開します。時間のかかる処理を高速化できます。
導入
VSTO Excel アドインのプロジェクトに、SakuraMacaron2.Excel の NuGet パッケージをインストールしてください。
アドインの Startup か、リボンの Load イベントで、ExcelMacaron.Application を初期化すると、ExcelMacaron の各機能が使用できます。
private void SampleRibbon_Load(object sender, RibbonUIEventArgs e)
{
// ExcelMacaron.Application を初期化
ExcelMacaron.Application = Globals.ThisAddIn.Application;
}
サンプルコード
ここでは ExcelMacaron の各機能の使い方を、サンプルコードとして示します。それぞれのコードは、リボンボタンが押されたときのイベント処理の例として記載しています。
これらのコードを試すには、次の手順に従ってください :
- Excel VSTO アドインのプロジェクトに、新しい項目の追加から「リボン(ビジュアルなデザイナー)」を選んで追加してください。
- まだ ExcelMacaron.Application が初期化されていないときは、各機能を使う前に初期化します。
- ツールボックスから Officeリボンコントロール の Button を追加してください。
- そのボタンのイベント処理として、以下のサンプルコードを記載してください。
もし Excel 表を挿入する方法を知りたいときは、こちらのMicrosoft 公式ドキュメントを参照してください:
これらのサンプルを使うことで、ExcelMacaron の機能を素早く理解し、自分の Excel VSTO アドインプロジェクトに組み込むことができるようになります。
例1 : アクティブな Excel 表から値を読み取る
現在開かれている Excel ワークブックの中で、現在アクティブな表を取得するには ExcelMacaron.ActiveTable を使用します。
また、Excel 表の値を読み取るには ReadTable を使用します。
表の中で、値を読み取りたいカラム(列)とそのデータ型を指定するためにクラスを定義してください。ReadTable にそのクラスを指定すると、Excel表から各行を読み取り、クラス オブジェクトにデータを格納して、列挙型(IEnumerable<T>)として返します。
// 例1: Excel 表から ID列、Title列、Value列 の値を読み取るケース(C#)
private class Sample1
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
// アクティブな Excel 表を読み取る
IEnumerable<Sample1> rows = ExcelMacaron.ActiveTable.ReadTable<Sample1>( );
foreach (var row in rows)
{
// デバッグ出力に各行の内容を出力する
Debug.WriteLine($"ID:{row.Id}, Title:{row.Title}, Value:{row.Value}");
}
}
もし、Excel 表のカラム名と、クラスのプロパティの名前を別にしたい場合は、ExcelColumnName 属性を使用します。
例えば Excel表のカラム名が ID の場合に、C#のクラスプロパティを Id という名前で作成し、ExcelColumnName 属性に ID という名前を指定します。
他に例えば、Excel表のカラム名にスペースが含まれていたり、日本語だったり、クラスプロパティにそのままでは使えない名前が使用されている場合にも、ExcelColumnName 属性が使えます。
例2 : Excel 表を更新する
また、Excel 表の値を更新するには UpdateTable を使用します。
表の中で、値を更新したいカラム(列)の名前と、そのデータを指定するためのクラスを定義してください。
また、更新する行を特定するために使用する一意キーを Identifier属性で指定してください。次の例では、Excel 表の ID列の値が 1 と 2 の行の値を更新します。
更新したい値を格納した列挙型オブジェクト(IEnumerable<T>)を UpdateTable に指定すると、各行の値が更新されます。この例では List<T>を指定しています。
// 例2: Excel 表の ID列が一致する行の Title列、Value列 の値を更新するケース(C#)
private class Sample2
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
private void button2_Click(object sender, RibbonControlEventArgs e)
{
// 表を変更するためのデータを作成する
// ID列で探して、Tilte と Value を更新します
var data = new List<Sample2>() {
new Sample2 { Id = 1, Title = "Updated Title 1", Value = "Updated Value 10" },
new Sample2 { Id = 2, Title = "Updated Title 2", Value = "Updated Value 20" } };
// アクティブな Excel 表を、指定したデータで更新する
ExcelMacaron.ActiveTable.UpdateTable(data);
}
ExcelColumnName 属性を使用するとカラム(列)と、プロパティを別の名前にすることができます。
この例では、Id プロパティには Identifier 属性と ExcelColumnName 属性が指定されています。UpdateTable は IDという名前の列を探して、Id プロパティと値が一致する行の Title 列と Value 列の値を更新します。
例1 と 例2 を組み合わせて、ReadTable で取得した値の一部を更新した後に、UpdateTable でExcel表を更新するということも可能です。
UpdateInsertTable を使用した行の更新と挿入
既存の行を更新するだけでなく、表に存在しないIDの行を新たに挿入したい場合は、UpdateTable の代わりに UpdateInsertTable メソッドを使用します。
以下の例では、UpdateInsertTable の動作を示します。既存のID(更新される)と新しいID(新しい行として挿入される)の両方を含むデータを提供した場合:
// 例2b: UpdateInsertTable を使用して既存行の更新と新規行の挿入を行うケース(C#)
private class Sample2b
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
private void button2b_Click(object sender, RibbonControlEventArgs e)
{
// 表を更新・挿入するためのデータを作成する
// 既存のID(1, 2)は更新され、新しいID(3, 4)は挿入されます
var data = new List<Sample2b>() {
new Sample2b { Id = 1, Title = "Updated Title 1", Value = "Updated Value 10" },
new Sample2b { Id = 2, Title = "Updated Title 2", Value = "Updated Value 20" },
new Sample2b { Id = 3, Title = "New Title 3", Value = "New Value 30" },
new Sample2b { Id = 4, Title = "New Title 4", Value = "New Value 40" }
};
// アクティブな Excel 表を、指定したデータで更新・挿入する
// 既存の行は更新され、新しい行は挿入されます
ExcelMacaron.ActiveTable.UpdateInsertTable(data);
}
UpdateTable と UpdateInsertTable の主な違い:
- UpdateTable: 既存の行のみを更新します。指定されたIDの行が表に存在しない場合、無視されます。
- UpdateInsertTable: 既存の行を更新し、さらに表に存在しないIDの行を新たに挿入します。
例3 : InsertTable で新しい Excel 表を作成する
まだ表が存在しない状態で、完全に新しい Excel 表を作成する必要がある場合は、InsertTable メソッドを使用します。このメソッドは指定された場所に新しい表を作成し、データを設定します。
データの準備とクラス定義は前の例と同様ですが、InsertTable は既存の表を更新するのではなく、新しい表を作成したい場合に使用します。
// 例3: 初期データを使用して新しい Excel 表を作成するケース(C#)
private class Sample3
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
private void button3_Click(object sender, RibbonControlEventArgs e)
{
// 新しい表に設定する初期データを作成する
var data = new List<Sample3>() {
new Sample3 { Id = 1, Title = "最初の項目", Value = "値 1" },
new Sample3 { Id = 2, Title = "2番目の項目", Value = "値 2" },
new Sample3 { Id = 3, Title = "3番目の項目", Value = "値 3" }
};
// アクティブなセルに、指定したデータで新しい Excel 表を挿入する
ListObject newTable = ExcelMacaron.ActiveSheet.InsertTable(data);
// メソッドは新しく作成された表を返すので、さらなる操作に使用できます
Debug.WriteLine($"新しい表を作成しました。行数: {newTable.ListRows.Count}");
}
特定のセルに表を挿入する場所を指定することもできます:
// 特定のセルに表を挿入
ListObject table2 = ExcelMacaron.ActiveSheet.GetCell("C5").InsertTable(data);
各メソッドを使用するタイミング:
- InsertTable: 新しい表を作成する場合(既存の表がない場合)に使用します。
- UpdateTable: 新しい行を追加せずに既存の表を更新する場合に使用します。
- UpdateInsertTable: 既存の表を更新し、新しい行を追加する可能性がある場合に使用します。
例4 : ReadOnlyCell属性を使用して読み取り専用列を作成する
ReadOnlyCell 属性を使用すると、Excel 表の特定の列を読み取り専用にすることができます。この属性をプロパティに適用すると、対応する Excel 列がデータの入力規制を使用して保護され、ユーザーが簡単に値を変更できなくなります。
重要な注意事項: 読み取り専用保護は、パスワードベースのワークシート保護ではなく、Excel のデータの入力規制機能を使用して実装されています。これにより通常のユーザー入力は防げますが、絶対に変更不可能というわけではありません。ユーザーは Excel の高度な機能を使用して値を変更することも可能です。ただし、通常の Excel 使用中の誤った変更は効果的に防ぐことができます。
読み取り専用列を持つ表の作成
まず、読み取り専用にしたいプロパティに ReadOnlyCell 属性を適用したクラスを定義します:
// 例4: 読み取り専用の Title 列を持つ表を作成するケース(C#)
private class Sample4
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
[ReadOnlyCell]
public string Title { get; set; }
public string Value { get; set; }
}
private void button4_Click(object sender, RibbonControlEventArgs e)
{
// 新しい表に設定する初期データを作成する
var data = new List<Sample4>() {
new Sample4 { Id = 1, Title = "読み取り専用タイトル 1", Value = "編集可能な値 1" },
new Sample4 { Id = 2, Title = "読み取り専用タイトル 2", Value = "編集可能な値 2" },
new Sample4 { Id = 3, Title = "読み取り専用タイトル 3", Value = "編集可能な値 3" }
};
// 新しい Excel 表を挿入する - Title 列は読み取り専用になる
ListObject newTable = ExcelMacaron.ActiveCell.InsertTable(data);
Debug.WriteLine($"読み取り専用の Title 列を持つ表を作成しました: {newTable.ListRows.Count} 行");
}
UpdateTable と UpdateInsertTable での動作
ReadOnlyCell プロパティを持つ表で UpdateTable や UpdateInsertTable を使用した場合、データに新しい値を指定しても、これらの列は更新されません:
// 例4b: 更新時の読み取り専用動作を示すケース(C#)
private void button4b_Click(object sender, RibbonControlEventArgs e)
{
// 読み取り専用の Title 値を含む表の更新を試行する
var data = new List<Sample4>() {
new Sample4 { Id = 1, Title = "これは変更されません(読み取り専用)", Value = "更新された値 1" },
new Sample4 { Id = 2, Title = "これは変更されません(読み取り専用)", Value = "更新された値 2" },
new Sample4 { Id = 4, Title = "新しい読み取り専用タイトル 4", Value = "新しい値 4" } // 新しい行
};
// UpdateInsertTable は以下のように動作します:
// - 既存行(Id 1, 2)の Value 列を更新する
// - 既存行の Title 列は更新しない(読み取り専用保護)
// - 新しい行(Id 4)は Title を含むすべての値で挿入される(挿入時は許可)
ExcelMacaron.ActiveTable.UpdateInsertTable(data);
Debug.WriteLine("更新完了 - 既存の Title 値は変更されませんでした");
}
ReadOnlyCell 動作の重要なポイント:
- InsertTable:
ReadOnlyCell属性を含む、すべてのプロパティの値を設定します - UpdateTable/UpdateInsertTable: 既存行については ReadOnlyCell 以外のプロパティのみを更新します
- 新しい行の挿入: 完全に新しい行を挿入する際は ReadOnlyCell 値も設定されます
- データの読み取り: ReadTable は読み取り専用列を含む、すべての値を常に読み取ります
例5 : ReplaceTable メソッドを使用して条件付きでデータを置換する
ReplaceTable メソッドは、条件に基づいて Excel 表のデータを置換する強力な機能です。UpdateTable や UpdateInsertTable と異なり、ReplaceTable は第1引数のラムダ式(条件)が true を返す行のみに対して、第2引数のラムダ式(置換処理)を実行します。
条件付きデータ置換の実装
// 例5: ReplaceTable を使用して条件付きデータ置換を行うケース(C#)
private class Sample5
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
[ReadOnlyCell]
public string Title { get; set; }
public int Value { get; set; } // int型のValueを使用
}
private void button5_Click(object sender, RibbonControlEventArgs e)
{
// ReplaceTable を使用して条件付きでデータを置換する
// 第1引数: 条件ラムダ式(Value が 0 未満の行のみ対象)
// 第2引数: 置換ラムダ式(Value を 0 に変更)
ExcelMacaron.ActiveTable.ReplaceTable<Sample5>(
(data) => data.Value < 0, // 条件: Value が負の値の場合のみ
(data) =>
{
// ReadOnlyCell 属性により data.Title を変更しても表のTitleは変更されません
data.Value = 0; // 負の値を0に置換
});
Debug.WriteLine("ReplaceTable 完了 - 負の値のみが0に置換されました");
}
ReplaceTable の動作説明
ReplaceTable と UpdateTable の重要な違い:
- UpdateTable: 指定したデータで表の行を更新します(データ全体を使用)
- ReplaceTable: 条件に合致する行のみを対象に、個別の変換処理を実行します
ReplaceTable の実行フロー:
- Excel 表の各行を読み取り、データオブジェクトを作成
- 第1引数のラムダ式(
where条件)を評価 - 条件が
trueの場合のみ、第2引数のラムダ式(replace処理)を実行 - 変更されたデータを Excel 表に書き戻し
ReadOnlyCell との組み合わせ:
ReadOnlyCell属性が付与されたプロパティ(例:Title)は、置換処理で値を変更しても Excel 表には反映されません- 上記の例では、
Titleを変更するコードを書いても、表の Title は変更されません - 変更可能なプロパティ(例:
Value)のみが実際に Excel 表で更新されます
この例では、Value が負の値の行のみが対象となり、それらの行の Value を 0 に置換します。条件に合致しない行(Value が 0 以上の行)は一切変更されません。
例6 : SuspendScreenUpdating を使用してパフォーマンスを向上させる
SuspendScreenUpdating メソッドを使用すると、時間のかかる操作中に Excel の画面更新を無効にして、パフォーマンスを大幅に向上させることができます。このメソッドは ScreenUpdateSuspender オブジェクトを返し、using ブロック内で使用する必要があります。これにより、エラーが発生した場合でも画面更新が適切に再開されます。
この方法は、try-finally ブロックで Excel の ScreenUpdating プロパティを手動で管理するよりもはるかに安全で便利です。
// 例6: SuspendScreenUpdating を使用して表作成時のパフォーマンスを向上させるケース(C#)
private class Sample6
{
[ExcelColumnName("ID")][Identifier]
public int Id { get; set; }
public string Title { get; set; }
public string Value { get; set; }
}
private void button6_Click(object sender, RibbonControlEventArgs e)
{
// パフォーマンス向上を実証するために大量のデータを作成
var data = new List<Sample6>();
for (int i = 1; i <= 1000; i++)
{
data.Add(new Sample6 { Id = i, Title = $"タイトル {i}", Value = $"値 {i}" });
}
// SuspendScreenUpdating を使用してパフォーマンスを向上させる
using (ExcelMacaron.SuspendScreenUpdating())
{
// このブロック内では画面更新が無効になる
// 表を挿入する - 画面更新なしでずっと高速になる
ListObject newTable = ExcelMacaron.ActiveSheet.InsertTable(data);
Debug.WriteLine($"パフォーマンスが向上した状態で {newTable.ListRows.Count} 行の表を作成しました");
}
// ここで画面更新が自動的に再開される(エラーが発生した場合でも)
Debug.WriteLine("SuspendScreenUpdating 完了 - 画面更新が復元されました");
}
SuspendScreenUpdating の利点:
- パフォーマンスの向上: 画面更新なしで操作がはるかに高速に実行される
- 自動復元: using ブロック終了時に画面更新が常に復元される
- エラー安全性: 例外が発生しても画面更新が復元される
- 簡単な使用法: try-finally ブロックや手動での ScreenUpdating 管理が不要
SuspendScreenUpdating を使用するタイミング:
- 大きな Excel 表を作成または更新する場合
- 複数の Excel 操作を順次実行する場合
- 視覚的な変更を伴う時間のかかる Excel 操作を行う場合