黙々とC#

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

ソート

本記事は、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
{
  //例外発生の有無にかかわらず実行したいコード
  //リソースの開放などを行う
}

goto

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

goto

無条件に処理を分岐させたい場合には、goto ステートメントを使用することができます。ただし、gotoステートメントを多用するとプログラムが分かりにくくなるので積極的には使わない方が良いでしょう。

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

LABEL: // ジャンプ先を示すラベル
var x = 1;
goto LABEL;

//※このサンプルコードは無限ループします

goto ステートメントの使いドコロの1つとしては、階層の深い入れ子のループから抜ける際に使います。

for(var i = 1; i < 100; i++)
{
    for(var j = 1; j < 100; j++)
    {
          if( i > 50 && i == j )
          {
                goto EXITLOOP;
          }
    }
}

EXITLOOP:

goto case

また、goto は switch ステートメントの特定の switch-case ラベルまたは default ラベルに制御を移動するのに使用することができます。

var n = Excel.ActiveWorkbook.ActiveSheet.Range("A1").Value;
var cost = 0;
switch (n)
{
    case 1:
        cost += 25;
        break;
    case 2:
        cost += 25;
        goto case 1;
    case 3:
        cost += 50;
        goto case 1;
    default:
        break;
}

Excel.ActiveWorkbook.ActiveSheet.Range("A2").Value = cost;

return, break

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

return, break

return

C# スクリプトの処理を途中で抜ける場合、returnステートメントを使用します。

var x = 1;
return;    //ここでスクリプト終了

var y = 2; //この処理は実行されない。

なお、メソッド内でreturnを使用した場合は、通常のC#と同様、当該メソッドを抜けるのみです。

break

whileステートメントやforステートメントを処理途中で抜けるには、breakステートメントを使用します。

for(var i = 1; i < 100 ; i++)
{
    if( i = 10) { break; }
}

using

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

using

usingステートメントは、IDisposableインターフェースを実装したオブジェクトを呼び出した際に、確実にDispposeメソッドが呼ばれるように保証するための簡易構文です。

#r "System.Drawing"
using System.Drawing;

using (var font1 = new Font("Arial", 10.0f)) 
{
    var charset = font1.GdiCharSet;
}

上記例のFontオブジェクトのように、アンマネージ リソース (この場合はデバイス コンテキスト) にアクセスするマネージ型の例です。アンマネージ リソースや、それをカプセル化するクラス ライブラリ型は他にもたくさんあります。そのような型はすべて、IDisposable インターフェイスを実装する必要があります。

一般に、IDisposable オブジェクトを使用するときは、それを using ステートメントで宣言して、インスタンス化する必要があります。 using ステートメントは、ステートメントブロックを抜けると必ず Dispose メソッドを呼び出します。 Disposeメソッド が呼び出されるとすぐに、オブジェクト自体がスコープの外側に出されます。 オブジェクトは、using ブロック内では読み取り専用です。変更したり再割り当てしたりすることはできません。

using ステートメントを使うと、オブジェクトでのメソッドの呼び出し中に例外が発生した場合でも Dispose が必ず呼び出されます。 usingステートメントは、オブジェクトを try ブロックに配置し、finally ブロックで Dispose を呼び出すコードと等価です。