C#で、IVフォント(異体字)を安全に取り扱う方法

きっかけ

指導要録作成ソフトを他学校の先輩の先生に作ってくれと言われたので、ちゃちゃっと作ってみた。

 

自分の職場では、まだ手書きだったし、自分自身が指導要録を書く機会が現在のところないので、テンションが上がらない。

しかも、Excel限定で。VBAなんて何年も触ってないなぁと思いながら、いじってみると、想像以上につかれた。

 

Excel VBAは、設計が古いというかVB6いじっているみたいな感覚で懐かしいなぁ。クラスもあるんだ。へぇー。

なんか、変数宣言するのに as integer とか長すぎるわ。

なんか、ワークシートいじるのに、 Worksheet とか長すぎるわ。

With でくくるのか。

シートの番号探すに、一回一回、シート名 for で回してさがすのか。

めんどくさいわ。

変数 大文字小文字区別しないのに、勝手にソースコードの変数修正すんな!

 

と、だんだん慣れないせいもあり、ぶつぶつ悪態をつきながらプログラムを組んだのでした。

 

そしたら、開発している途中で、先輩から「あ、言い忘れてたけど、これ何年も使う予定だから、学年が上がるにつれて、新しいメンバー追加できるようにしてね。」→めんどくさいからオートフィルタ

「ちなみに、そうなったら学年ごとにクラスのメンバー変わるんで、それをうまいことしてね。」→めんどくさいからオートフィルタ

「ちなみに、オートフィルターはだめ。それ、あとでコピペで他に成績移せないし。コピペで貼り付けたら他のセルまではみ出るよね。」→先に言ってくれ。プログラム的にソートしてからセルクリアして上書きすることに。

「ほかの先生に試してもらったら、うまく動かないっていってるよ。直して。→セルの行削除していた。」セルの行を削除できないように、他の入力してはいけない場所を入力できないように変更→

「なんかポンポンエラーがでてきてうっとおしい。でなくして。」

「なんか、遅い」→内部で処理して、一括してワークシートを吐き出すように仕様変更。ソート時はRangeで一括して貼り付ける。実行時間を常に計測してステータスバーに表示して自分なりに常にチェックするように。目標Core2 Quadで7秒以内。Core i7Haswel(番号忘れた)で3秒以内。

「印刷する前にプレビューできないの?」→マクロでやっているので、プレビューそのものはできないことを1時間かけて説得→仲裁案として印刷モードのほかにPDFを吐く機能を実装

「児童名辻を点1つで出せるようにして。」→IPAMJフォントを紹介

Excel 2007だったら出ないよ。」→自分で調べてくれ。そういうソフトあるから。イーストなんとかの会社を紹介。っていうか、Excelのバージョン上げるとか。

 

こういうのが、2,3日に一回のペースでメールをもらうので、遅れに遅れて、夜な夜な業務と関係ない自宅で3か月かかりましたさ。こっちもVBA初心者なんじゃ!20時間くらいしかさわったことないわ!と言いたいのをこらえる日々。というか、無償でやっていることわかっているんか。

 

で、令和2年になり、指導要録の参考様式が文科省から出された。実際に参考様式が発表されたのは、もうちょっとだけ前。

 

ずいぶん、変更してきた。観点が統一され、外国語科が新設され、外国語活動の学年と分離され、外国語科の評定が入っているね。

昨年、道徳科の新設による指導要録変更の対応にもそれなりに面倒だった。

前置きが長くなったら、そういうわけで、もうVBAは嫌なのです。

 

プログラム言語の検討

VCしんどい。

今のVBしらん。

こういうのは、SQLite+Webでやるのが、超らくちんなんですけど。ダメ元で提案。

→サーバを用意しないとダメと説明すると、やっぱり駄目ですよね。

そういえば、学校に配布にPCの.net Frameworkが4.5.1になってたので、C#で作ろうか。

ここで、人名をByte変換する必要ができたのです。

そのまんまコピーしてもいいのですが。

 

private void button1_Click(object sender, EventArgs e)
{
//実行
String sz = this.textBox1.Text;
label1.Text = "\u897f";
// データを共有しているので…
// var s1 = new Utf8String("西󠄂");
// var s2 = new Utf8String("西");
sz = "\u897F\uDB40\uDD02";
//label3.Text = "'"+Regex.Escape(sz)+"'";
sz = String.Format("{0}", sz);
label2.Text = sz;
String str = "西󠄂";
byte byteData = System.Text.Encoding.UTF8.GetBytes(str);
string bytestr = BitConverter.ToString(byteData); //例えば str = 西󠄂 のとき、bytestrは E8-A5-BF-F3-A0-84-82 になる。
label2.Text = bytestr;
//今度はbytestrから、文字を出す
byte
newData = this.ConvertStringToBit(bytestr);
String ss = System.Text.Encoding.UTF8.GetString(newData);
label3.Text = ss;

}

///

/// BitConverterを使用して文字列へ変換したByte配列を復元します。
/// @see https://blog.beaglesoft.net/entry/%3Fp%3D39

/// 対象の文字列
/// 変換したByte配列
/// が16進数をハイフンで区切った文字列でない場合nullを返します。
public byte[] ConvertStringToBit(string item)
{
string itemString = item;

// ハイフンを含まない場合はNullを返す
if (!itemString.Contains("-")) return null;

var array = itemString.Split('-');

var bytes = new byte[array.Length];
for (int i = 0; i < array.Length; i++)
{
bytes[i] = Convert.ToByte(array[i], 16);
}

return bytes;
}