黙々とC#

"In a mad world of VBA, only the mad are sane" 『VBAという名の狂った世界で狂っているというのなら私の気は確かだ』

C# Scriptの入力と実行

本記事は、Excel C# Script入門講座の1記事です。

C# Scriptの入力と実行

実際にC# Scriptを入力して、実行するまでを簡単に説明します。

C# Scriptを保存するフォルダの指定

f:id:d_ymkw:20160808113855p:plain

まず、Select Folderをクリックして、C# Scriptが保存されている/これから保存するフォルダを指定してください。

f:id:d_ymkw:20160808114006p:plain

選択したフォルダ内に既にC# Scriptファイル(*.csx)が存在する場合には、ドロップダウンボックスにファイル名が表示されます。

C# Scriptの新規作成

ここでは、新規にC# Scriptを入力してみます。

NewScriptボタンをクリックします。

エディタ(この場合、VisualStudioCode)が自動的に立ち上がります。

とりあえず、以下のコードを入力してください。

Excel.ActiveWorkbook.ActiveSheet.Range("A1").Value = "Hello C# Script";

f:id:d_ymkw:20160808114245p:plain

"hello.csx"という名前で保存します。

C# Scriptの編集

この記事では取り上げませんが、既に存在する*.csxを編集したい場合は、ドロップダウンボックスで選択した後、Editボタンをクリックするとファイルを選択した状態でエディタが立ち上がります。*1

C# Scriptの実行

Reloadをクリックした後*2

Script File:のドロップダウンボックスで"hello.csx"を選択します。

Runボタンをクリックすると、スクリプトが実行されます。

f:id:d_ymkw:20160808114511p:plain

Excelを立ち上げてから初回の実行のみ若干実行までに時間がかかります。スクリプト実行中は、Runボタンはグレーアウトされ、スクリプトの実行が終了すると、水色に戻ります。

*1:厳密には、単にOptionsで選択したエディタを、ファイル名を引数で渡して実行するだけです。

*2:Reloadボタンをクリックすると、SelectFolderで選択されたフォルダ内の*.csxを読み込み、ドロップダウンボックスに一覧表示します。

ExcelCSXの導入

本記事は、Excel C# Script入門講座の1記事です。

ExcelCSXの導入

インストールに必要な要件

  • OSがWindows7 以降であること
  • .NET Framework 4.6 がインストールされていること
  • Excel2007 以降 がインストールされていること

インストール手順

githubで公開されているExcelCSX のレポジトリのreleasesページを開きます。

ExcelCSXのパッケージ(zipファイル)をダウンロードします。

ダウンロードしたファイルを展開します。

f:id:d_ymkw:20160808111728p:plain

フォルダの中にある"ExcelCSX.vsto"を実行します。

f:id:d_ymkw:20160808111936p:plain

警告画面が表示されますが、そのままインストールしてください。

f:id:d_ymkw:20160808112010p:plain

正常にインストールされると上記画面が表示されます。

最初にすべきこと

EXcelCSX導入後に、Excelを起動するとアドインタブに以下の機能が追加されています。

f:id:d_ymkw:20160808112310p:plain

(インストールしたにも関わらず表示されない場合は、「リボンのユーザー設定」から「アドイン」タブのチェックをON/OFFすると表示される場合があります。)

「Options」ボタンをクリックし、設定画面を表示します。

f:id:d_ymkw:20160808112550p:plain

"Editor Path" に、C# Scriptの編集に使いたいエディタを指定してください。

(デフォルトではVisual Studio Codeのパスを指定しています。)

オススメのエディタはVisual Studio Codeです。

C# エクステンションを入れると、C# Scriptファイル(*.csx)を開いた際に、ハイライトが有効になるほか、一部の補完機能・入力支援機能が使えるようになります。素のテキストエディタに比べてぐっと書きやすくなります。

"Default Folder Path"は、起動時にデフォルトで読み込まれるフォルダを指定します。C# Scriptを保存するフォルダを指定すると良いです。

オートフィルタ

本記事は、Excel C# Script入門講座の1記事です。

オートフィルタ

Excelのオートフィルタ機能を利用して、データを抽出するには、データの抽出元を示すRangeオブジェクト(*)を用意し、当該RangeオブジェクトのAutoFilterメソッドを使用します。引数により抽出条件を設定できます。

(*) Rangeオブジェクトは、データの抽出範囲全体を示すものでなくても、Excelが自動的にフィルタの対象範囲を判定します。

AutoFilterメソッドの構文

(Rangeオブジェクト).AutoFilter(Field, Criteria1, Operator, Criteria2, VisibleDropDown )

AutoFilterメソッドの戻り値

何かの値が戻ってくるが、使うことはないと思われる。(未確認)

AutoFilterメソッドの引数

引数名 必須 / オプション 内容
Field 省略可能 フィルターの対象となるフィールド番号を指定します。
Criteria1 省略可能 抽出条件となる文字列を指定します。
Operator 省略可能 フィルターの種類を指定します。
Criteria2 省略可能 2番目の抽出条件となる文字列を指定します。
VisibleDropDown 省略可能 オートフィルタのドロップダウン矢印(▼)を表示するか否かを指定します。
引数Field

フィールド番号は、リストの左側から何番目かを指定します。

つまり、最も左側にあるフィールドはフィールド番号 1 になります。

引数Criteria1, Criteria2

通常、抽出条件とする文字列(例えば「りんご」)を指定します。

"=" と指定すると、空白セルが抽出され、"<>" と指定すると空白以外のフィールドが抽出されます。

"A"と指定すると、Aに後方一致する場合、"A"と指定すると、Aに前方一致する場合、"A"と指定すると、Aに部分一致する場合が抽出されます。

また、数値の場合は、不等号(">"や"<", "<=", ">=")を先頭に付けて範囲指定することができます。

この引数を省略すると、抽出条件は All になります。

引数 Operator に xlTop10Items が指定されている場合は、引数 Criteria1 に項目数を指定します (たとえば "10")。

なお、Criteria2 を指定できるか否かは、引数Operatorに何を指定するかで決まります。

引数Operator

XlAutoFilterOperator 列挙型を指定します。

名前 説明
xlAnd 1 Criteria1 とCriteria2 の論理演算子 AND
xlBottom10Items 4 表示される最低値項目 (Criteria1 で指定される項目数)
xlBottom10Percent 6 表示される最低値項目 (Criteria1 で指定される割合)
xlFilterCellColor 8 セルの色
xlFilterDynamic 11 日付の範囲を指定したい場合。Criteria1には XlDynamicFilterCriteria列挙型を指定する。
xlFilterFontColor 9 フォントの色
xlFilterIcon 10 フィルター アイコン
xlFilterValues 7 Criteria1 を配列で指定する場合に指定する。なお、日付を配列で指定したい場合は、Criteria2を指定する。
xlOr 2 Criteria1 またはCriteria2 の論理演算子 OR
xlTop10Items 3 表示される最高値項目 (Criteria1 で指定される項目数)
xlTop10Percent 5 表示される最高値項目 (Criteria1 で指定される割合)
引数VisibleDropDown

trueまたはfalseを指定します。

trueを指定すると、オートフィルタ処理を実行した時にドロップダウン矢印が表示されます。

デフォルト値はtrueです。

全ての引数を省略した場合

フィルタ処理は行わず、オートフィルタのドロップダウン矢印を表示します。

サンプルコード

//Sheet1のA1セルを含む適当な範囲にオートフィルタを設定(ドロップダウン矢印を表示)する。
Excel.Worksheets("Sheet1").Cells(1, 1).AutoFilter();

f:id:d_ymkw:20160805201448p:plain

//フィールド番号5(E列)の値が50以下のデータを抽出
Excel.Worksheets("Sheet1").Cells(1, 1).AutoFilter(Field:5, Criteria1:"<20");
//フィールド番号5(E列)の中から40以上60未満の条件に一致するデータを抽出
var range = Excel.Worksheets("Sheet1").Cells(1, 1);
range.AutoFilter(Field:5, Criteria1:"<60", Operator:1, Criteria2:">=40");

f:id:d_ymkw:20160805201550p:plain

以下の例では、抽出条件を3つ以上指定しています。この場合、引数Operatorに XlFilterValue(7)を指定し、Criteria1に配列を指定します。なお、XlFilterValueはExcel2007以降でのみ利用可能です。

//フィールド番号8(H列)の中から、愛媛県、岡山県、茨城県のいずれかに一致するデータを抽出
var range = Excel.Worksheets("Sheet1").Cells(1, 1);
range.AutoFilter(Field:8, Criteria1:new []{"愛媛県","岡山県","茨城県"}, Operator:7);

f:id:d_ymkw:20160805202155p:plain

ソート

本記事は、Excel C# Script入門講座の1記事です。

ソート

Excelのソート機能を利用するには、ソートしたい範囲を示すRangeオブジェクトを用意し、当該RangeオブジェクトのSortメソッドを使用します。引数により昇順、降順などを指定できます。

※ Excel2007以降では、Sortメソッドに代えて、RangeオブジェクトにSortオブジェクトが用意されています。Sortオブジェクトの方が、オプションが豊富に用意されています。

Sortメソッドの構文

(Rangeオブジェクト).Sort(Key1, Order1, Key2, Type, Order2, Key3, Order3, Header, OrderCustom, MatchCase, Orientation, SortMethod, DataOption1, DataOption2, DataOption3)

Sortメソッドの戻り値

何かが返ってくるが、使うことはないと思われる(未調査)。

Sortメソッドの引数

引数名 必須 / オプション 内容
Key1 省略可能 最初の並べ替えフィールドを指定します。
Order1 省略可能 Key1で指定した値の並び替え順序を指定します。
Key2 省略可能 2番目の並べ替えフィールドを指定します。
Type 省略可能 並べ替え基準にする要素を指定します。
Order2 省略可能 Key2で指定した値の並び替え順序を指定します。
Key3 省略可能 3番目の並べ替えフィールドを指定します。
Order3 省略可能 Key3で指定した値の並び替え順序を指定します。
Header 省略可能 最初の行にヘッダー情報が含まれているかどうかを指定します。
OrderCustom 省略可能 ユーザー設定の並べ替え基準を指定します。
MatchCase 省略可能 大文字小文字の区別を行うか指定します。
Orientation 省略可能 並べ替えを列単位で行うか、行単位で行うかを指定します。
SortMethod 省略可能 並べ替えの方法を指定します。
DataOption1 省略可能 Key1 で指定した範囲でテキストを並べ替える方法を指定します。
DataOption2 省略可能 Key2 で指定した範囲でテキストを並べ替える方法を指定します。
DataOption3 省略可能 Key3 で指定した範囲でテキストを並べ替える方法を指定します。
引数Key1, Key2, Key3

Rangeオブジェクトまたは文字列(範囲名かピボットテーブル名)で指定します。

Key2, Key3については、ピボットテーブルレポートを並び替える場合には使用できません。

引数Order1, Order2, Order3

XlSortOrder 列挙型を指定します。

名前 説明
xlAscending 1 指定したフィールドを昇順で並べ替えます。(デフォルト値)
xlDescending 2 指定したフィールドを降順で並べ替えます。
引数Type

XlSortType 列挙型を指定します。

この引数は、ピボットテーブル レポートを並べ替えるときにだけ使用します。

名前 説明
xlSortValues 1 ピボットテーブル レポートをで並べ替えます。
xlSortLabels 2 ピボットテーブル レポートをラベルで並べ替えます。
引数Header

XlYesNoGuess列挙型を指定します。

名前 説明
xlGuess 0 見出しがあるかどうか、ある場合はその場所を Excel が自動判定します。
xlYes 1 範囲全体が並べ替えられません。
xlNo 2 範囲全体が並べ替えの対象になります。 (デフォルト値)
引数OrderCustom

『ユーザー設定リストの何番目』の基準を用いるかを整数値で指定します。

ユーザー設定の並べ替え基準は、あらかじめユーザー設定リストに登録されているものしか使えません。

引数MatchCase

true の場合、大文字と小文字を区別して並べ替えを行います。false の場合、大文字と小文字を区別しないで並べ替えを行います。

この引数は、ピボットテーブルの並べ替えには使用できません。

引数Orientation

XlSortOrientation 列挙型を指定します。

名前 説明
xlSortColumns 1 |列単位で並べ替えます。
xlSortRows 2 行単位で並べ替えます。(デフォルト値)
引数SortMethod

XlSortMethod 列挙型を指定します。

名前 説明
xlPinYin 1 中国語の発音表記の順で並べ替えます。(デフォルト値)
xlStroke 2 各文字の総画数で並べ替えます。
引数DataOption1, DataOption2, DataOption3

XlSortDataOption 列挙型を指定します。

名前 説明
xlSortNormal 0 数値データとテキスト データを別々に並べ替えます。(デフォルト値)
xlSortTextAsNumbers 1 テキストを数値データとして並べ替えます。

サンプルコード

//Sheet1のセル範囲"A1:B100"を、2列目をキーにして昇順にソートする
Excel.Worksheets("Sheet1").Activate();
var range = Excel.Worksheets("Sheet1").Range(Cells(1, 1), Cells(100, 2));
range.Sort(Key1:Worksheets("Sheet1").Cells(1, 2), Order1:xlAscending);

下記例では、複数のキーを用いてソートする場合を示しています。

//セル範囲"A1:C100"を1列目は降順、2列目は昇順、3列目は降順にソート

var range = Excel.Worksheets("Sheet1").Range(Cells(1, 1), Cells(300, 3));
var col_1 = Excel.Worksheets("Sheet1").Cells(1, 1);
var col_2 = Excel.Worksheets("Sheet1").Cells(1, 2);
var col_3 = Excel.Worksheets("Sheet1").Cells(1, 3);
range.Sort(Key1:col_1, Order1:2, Key2:col_2, Order2:1, Key3:col_3, Order3:2);

下記例では、列Aに並んでいる色をSortメソッドで並べ替えます。

f:id:d_ymkw:20160804191843p:plain

ソートを行うにあたっては、ColorIndex プロパティを使用して、列 A 内のセルの色の値を取得し、その値を使用しています。

 //A列の色の 値(ColorIndex)をC列に表示
 var s = Excel.ActiveWorkbook.ActiveSheet;
 for(var i = 2; i < 11; i++)
 {
     s.Cells(i, 3).Value = s.Cells(i, 1).Interior.ColorIndex;
 }
s.Range("C1").Value = "Index"; //Phase1

//C列を基準にA~C列の範囲を並べ替え
s.Columns("A:C").Sort(Key1:s.Range("C2"), Order1:1, header:1); //Phase2

//C列を削除
s.Columns(3).ClearContents();

f:id:d_ymkw:20160804192515p:plain

連続検索

本記事は、Excel C# Script入門講座の1記事です。

検索

シート内で文字列を検索するは、下記記事で解説したようにRangeオブジェクトのFindメソッドを使用します。

mokumokucsharp.hateblo.jp

連続して検索する(検索条件に一致する箇所を次々に見つけたい)場合には、Findメソッドを用いた後、FindNextメソッドを使用します。

FindNextメソッドは、Findメソッド使用時の検索条件はそのままに前方向に検索を行います。

なお、FindPreviousメソッドを用いると、後ろ方向に検索を行います。

FindNextメソッドの構文

(Rangeオブジェクト).FindNext(After)

FindNextメソッドの引数

引数名 必須 / オプション 内容
After 省略可能 検索を開始する1つ前のセルを指定します。

サンプルコード

以下の例では、セル範囲 A1:A500 で、値に 2 が含まれているセルを検索し、その値を 5 に変更します。

var range = Excel.Worksheets(1).Range("a1:a500");
var hitCell = range.Find(2, LookIn:-4163);
if (hitCell != null)
{
    var firstAddress = hitCell.Address;
    do
    {
         hitCell.Value = 5;
         hitCell = range.FindNext(hitCell);
    }
    while (hitCell != null && hitCell.Address == firstAddress)
}

検索

本記事は、Excel C# Script入門講座の1記事です。

検索

シート内で文字列を検索するは、検索したい範囲を表すRangeオブジェクトを用意し、RangeオブジェクトのFindメソッドを使用します。引数で、検索条件を指定します。

Findメソッドの構文

(Rangeオブジェクト).Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)

Findメソッドの戻り値

検索範囲の先頭のセルを表す Rangeオブジェクトが戻ってきます。

一致するデータが見つからなかった場合、null が戻ってきます。

Findメソッドの引数

引数名 必須 / オプション 内容
What 必須 検索するデータです。文字列など、セル内のデータに該当する値を指定します。
After 省略可能 検索を開始する1つ前のセルを指定します。
LookIn 省略可能 検索対象を指定します。
LookAt 省略可能 「セル内容が完全に同一のものだけを検索するか」どうかを指定します。
SearchOrder 省略可能 検索の際、行列のいずれの方向(順序)に検索するかを指定します。
SearchDirection 省略可能 検索を前方向、後ろ方向のどちら向きに検索するかを指定します。
MatchCase 省略可能 大文字と小文字を区別するには、true を指定します。既定値は false です。
MatchByte 省略可能 半角、全角を区別するには、trueを指定します。既定値は false です。
SearchFormat 省略可能 検索において、書式条件を検索対象とするかを指定します。規定値はfalseです。
引数After

引数 After には、セル範囲内(Rangeオブジェクト内)の1つのセルを指定する必要があります。

これは、ユーザーが通常の画面上で検索を実行する際のアクティブなセルの場所に対応しています。このセルの次のセルから検索が開始され、範囲内の他のセルがすべて検索されたあとに、指定されたセルが検索されます。

この引数を省略すると、対象セル範囲(Rangeオブジェクトの範囲)における左上端のセルが検索の開始点になります。

引数LookIn

引数 LookIn には、XlFindLookIn 列挙型を指定します。各メンバの意味は以下のとおり。

名前 説明
xlComments -4144 コメント
xlFormulas -4123 数式
xlValues -4163
引数LookAt

使用できる定数は、XlLookAt 列挙型の xlWhole または xlPart です。

名前 説明
xlWhole 1 検索文字列全体に一致する(完全に一致する)候補のみを取得します。
xlPart 2 検索文字列の一部に一致する候補を取得します。
引数SearchOrder

使用できる定数は、XlSearchOrder 列挙型の xlByRows または xlByColumns です。

名前 説明
xlByRows 1 行を横方向に検索し終えた後、次の行を検索します。
xlByColumns 2 行を下方向に検索し終えた後、次の列を検索します。
引数SearchDirection

使用できる定数は、XlSearchDirection列挙型の xlNextまたはxlPreviousです。

名前 説明
xlNext 1 後方検索(通常の検索方向)
xlPrevious 2 前方検索
引数MatchByte

「半角と全角を区別する」場合にtrueを指定にします。半角・全角の区別を行わない場合にはfalseを指定します。

この引数は、OSに 2 バイト (全角) 文字の言語サポートが導入されている場合にだけ使用できます。

引数SearchFormat

検索において書式条件を有効する(文字だけでなく書式も含めて検索する)場合にtrueにします。デフォルトはfalseです。

書式条件は、ApplicationオブジェクトのFindFormatプロパティで設定します。

サンプルコード

下記の例では、"Sheet1"に文字列"りんご"が存在するか検索し、存在した場合その位置を表示します。

var keyword = "りんご";
var hitRange = Excel.Worksheets("Sheet1").Cells.Find(keyword);
var message = "";
if (hitRange == null)
{
    message = $"{keyword} は見つかりませんでした";
}
else
{
    var r = hitRange.Row;
    var c = hitRange.Column;
    message = $"{keyword} は {r}行目{c}列目にあります";
}
Excel.StatusBar = message;

下記例では、"Sheet1"に文字列"C#"と完全一致するセルが存在するか検索し、存在した場合そのセルを太字にします。

var keyword = "C#";
var hitRange = Excel.Worksheets("Sheet1").Cells.Find(What:keyword, LookIn:-4163, LookAt:1);
if (hitRange != null)
{
    hitRange.Font.Bold = true;
}

try ~ catch

本記事は、Excel C# Script入門講座の1記事です。

try ~ catch

スクリプト内でエラーが発生した場合のプログラムの制御には、try ~ catch ステートメントを使用します。

try ~ catch ステートメントは、try ブロックと、それに続く 1 つ以上の catch 句で構成されます。catch句には例外処理を記載します。これにより、 例外が起こったときでもプログラムが異常な動作をしない堅牢なスクリプトを作ることが可能となります。

例えば以下のように使います。

object o2 = null;
try
{
    int i2 = (int)o2;   //例外の発生
}
catch (NullReferenceException e)  //発生する例外に合わせた例外クラスの指定
{
    //エラー処理
}

エラーには、大きく分けて実行時エラーと構文エラー(コンパイルエラー)とがあります。

実行時エラーとはシステムで処理できない動作を実行しようとした場合に発生するエラーです。C#(C# Script)では、実行時にエラーが発生すると、例外がスローされます。

構文エラーとは文法上の規則に違反した場合に発生するエラーで、プログラム実行前のコンパイル時に発生します。C# Scriptでは、構文エラーに関しては、実行前にエラーが表示されます。

tryブロックには、実行時エラーが発生する(例外がスローされる)可能性のあるコードを含ませます。このブロックは、例外がスローされるか、ブロックが正常に終了するまで実行されます。

catch 句は、引数なしで使用してすべての種類の例外をキャッチすることが可能ですが、そのようなコードは推奨されません。通常は、回復方法(例外が発生した場合の処理方法)が分かっている例外のみキャッチします。

try ~ finally

tryブロックでエラーが発生した場合でも、確実に実行したい処理がある場合には、finallyブロックを使用することができます。

finallyブロックは、たとえばtryブロック内で確保したリソースを確実に開放したい場合に利用することができます。

try
{
  //例外が投げられる可能性のあるコード
}
finally
{
  //例外発生の有無にかかわらず実行したいコード
  //リソースの開放などを行う
}