隠し文字

17.3.2.41 vanish(Hidden Text)[p.329]

runの表示・非表示を定義する要素。
モデルはCT_OnOffでval属性の値によって表示(true)・非表示(false)を指定する。
val属性が存在しない場合は表示(true)として扱われる。

段落に対する設定

スタイルに指定

段落スタイルのデフォルトの文字飾りとして隠し文字を設定することが可能。
styles.xml

<style type="paragraph" styleId="Hidden">
  <rPr>
    <vanish/>
  </rPr>
</style>
document.xml

<p>
  <pPr>
    <pStyle val="Hidden"/>
  </pPr>
</p>

直接指定

段落の文字列に文字飾りとして隠し文字を設定することが可能。
document.xml

<p>
  ...
  <r>
    <rPr>
      <vanish/>
    </rPr>
  </r>
</p>

段落マークに対する隠し文字

 以下の場合は、段落スタイルの隠し文字の設定がXの値で上書きされる。
document.xml

<p>
  <pPr>
    <pStyle val="Hidden"/>
    <rPr>
      <vanish val="X">
    </rPr>
  </pPr>
</p>

XML

XML(eXtensible Markup Language)

文章の見た目や構造を記述するためのマークアップ言語の一種。
主にデータのやりとりや管理を簡単にする目的で使用される。

マークアップ言語

タグと呼ばれる特殊な文字列を使用して、文章の構造やタイトル、文字の修飾情報などを埋め込む言語

XML Schema(XSD:XML Schema Definition Language)

スキーマ

Schema:図式、図表、図解、概要

スキーマ言語

マークアップ言語を用いる際に、要素や属性の定義を行うための言語

名前空間

名前空間接頭辞

QName(Quolified name)

名前空間+要素(属性)名
  1. accom:pension
  2. welf:pension

Local Name

要素(属性)名
  1. accom:pension
  2. welf:pension

Target Namespace

XML Schemaが定義されている言語
ルート要素のshcema要素の属性であるtargetNamespaceの値に指定する。

データ型

複雑型(Complex type)

子要素または属性をもつ要素のデータ型

単純型(Simple type)

子要素および属性をもたない要素のデータ型

複雑型の子要素

順序指定

<sequence>で並べられた子要素はその順番で出現する必要がある。

単純型(Simple type)

<choice>で並べられた子要素はどれか1つが出現する。

複雑型の出現回数

minOccurs属性

要素の最低出現回数を定義する。定義がない場合は"1"

maxOccurs属性

要素の最大出現回数を定義する。定義がない場合は"1"

デリゲート

デリゲート

メソッドへの参照を表す型(デリゲート型)
Delegateは委譲という意味で、委譲する内容は処理
定義方法は、処理を記述しない以外は、通常のメソッドと同様で、それにdelegateキーワードを指定する。
デリゲート型の変数には、戻り値と引数リストが一致するメソッドを代入できる(派生クラス(ダウンキャスト)は可能)
delegate 戻り値 デリゲート名(引数リスト);

マルチキャスト

+,-演算子で複数のメソッドを代入することができる。
複数のメソッドが代入されているデリゲートを呼び出すと、代入順に逐次実行される。

述語

デリゲートの主要な用途の1つで、条件を満たすかどうかを調べるメソッド(述語)を代入し、ほかのメソッドに渡す方法がある。

代入するメソッドについて

デリゲート型の変数に代入するメソッドは、クラス(static)メソッド、インスタンスメソッドのどちらでも代入することができる。
つまり、代入するメソッドの使用回数によらず、どこかに必ず1回は定義しなければならない。
C#では、これを簡単にする仕組みが存在する。
匿名関数
デリゲート用の仕組みで、後述するラムダ式はさらに簡素化されて、機能も充実している。(デリゲート以外の用途がある)
delegate (引数リスト){処理}
ラムダ式
関数を整数などの変数と同じように扱う。
一般的な定義は以下の①であるが、引数が明確な場合には②のように省略することができる。
(int n) => n > 0; // ①
n => n > 0; // ② 0と比較しているため、引数がint型であることは明確

まとめ

デリゲートの基礎をまとめるために、以下のプログラムを考える。
配列内の、5以上の偶数を表示する
internal class Summary
{
    private delegate bool DGCondition(int n);

    internal static void DispGT5Even(int[] nums)
    {
        DGCondition prediction = n => n >= 5;
        prediction += n => n % 2 == 0;
        GetGT5Even(nums, prediction);
    }

    private static void GetGT5Even(int[] nums, DGCondition prediction)
    {
        foreach (var num in nums)
        {
            var condition = prediction(num);
            condition &= prediction(num);
            if (!condition) continue;
            System.Console.WriteLine(num);
        }
    }
}

【Office Open XML】stylesのnumFmtについて

numFmtについて

 

ttkcd.hatenablog.com

 

に記載した通り、numFmts要素の子要素であるnumFmtは0ベースのインデックスではなく、numFmtのnumFmtIdを指定することによって参照される。
numFmtIdが同じだが、フォーマットが異なる値が存在した場合は?
numFmtの定義は以下の通り
<complexType name="CT_NumFmt">
  <attribute name="numFmtId" type="ST_NumFmtId" use="required"/>
  <attribute name="formatCode" type="ST_Xstring" use="required"/>
</complexType>
上記の通り、numFmtIdは同じだが、formatCodeが異なる場合は起きうる。
Excelで確認すると、後に定義された要素が適用される。

【C#】単体テスト

Visual Studio

公式としては、1プロジェクトに対応して1つの単体テストプロジェクトを推奨
以下のような、TargetProjectについて考える。
namespace TargetProject
{
  internal class InternalClz
  {
    public void PublicAdd(int a, int b) => a + b;
    internal void InternalAdd(int a, int b) => a + b;
    private void PrivateAdd(int a, int b) => a + b;
  }
}
対象のプロジェクトのソリューションで右クリック⇒[追加]⇒[新しいプロジェクト]⇒[MSTestテストプロジェクト] (※.NET Coreの場合)でプロジェクト(UnitTestProject)を作成

アクセス修飾子

上記のクラスはinternalなので、他のプロジェクトから呼び出すことが出来ない。
そこで、TargetProjectを以下のように修正する
#if DEBUG
using System.Runtime.CompilerServices;
[assembly: InternalVisibleTo("UnitTestProject")
#endif
namespace TargetProject
{
  internal class InternalClz
  {
    public void PublicAdd(int a, int b) => a + b;
    internal void InternalAdd(int a, int b) => a + b;
    private void PrivateAdd(int a, int b) => a + b;
  }
}
上記を追加することによって、Debug時に、対象のクラスをUnitTestProjectプロジェクトから呼び出すことが出来る

private

方法はありそうだが、今回は調査しない。
privateメソッドについては、要否の議論もあるが、自分は必要と思っている。
単体テストでの確認方法は、アクセス可能な他のメソッドからの確認で、カバー出来ないのならば不適切という方針がしっくりきた。

実際にテストしてみる

以下のメソッドを作成
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject
{
  [TestClass()]
  public class InternalClzTests{
    InternalClz internalClz = new InternalClz();
    
    [TestMethod()]
    public void PublicAddTest()
    {
      Assert.AreEqual(internalClz.PublicAdd(3, 4), 7); // Assert.AreEqual(結果,期待値) ①
    }
    
    [TestMethod()]
    public void InternalAddTest()
    {
      Assert.AreEqual(internalClz.InternalAdd(3, 4), 7); // ②
      Assert.AreEqual(internalClz.InternalAdd(4, 4), 7); // ③
    }
  }
}
テストの簡単な実行方法は、対象のプロジェクトで右クリック⇒[テストの実行]
上記の場合③がエラーのため、×が表示される。(Assert.AreEqual failed, Expected:<7>.Actual:<8>

【Office Open XML】stylesパーツ

stylesパーツ

以下で、主要な要素について簡単な説明をしたが、いまいち分かりづらかったので、再度

 

ttkcd.hatenablog.com

 

styles.xml

SpreadSheetのワークシートのセルは、塗りつぶしをして色を設定したり、フォントを変えたりすることが出来る。
この情報をすべてのセル要素に記載するとファイルサイズが膨大になってしまうため、 stylesパーツを使用してワークブックのセルに適用されているスタイルの情報をまとめる

styleSheet(Style Sheet)要素

stylesパーツのルート要素
この子要素に、塗りつぶしやフォント情報が定義される。
子要素は11種類あるが、以下の4つに分類できる。
  • 将来の拡張用の要素
  • セル内部のスタイル情報
  • セル自身の情報
  • セル自身の情報2
上記の、将来の拡張用の要素は、extLst要素のみで、ここでは説明しない。

セル内部のスタイル情報

numFmts, fonts, fills, borders, tableStyles, colorsは大まかにここに分類できるように思える。
ワークブック全体で使用されているフォント情報等が、該当する各要素の子要素として定義されている。
少しわかりづらいのが、colors要素で、これはレガシーやカスタムされた色情報が子要素に定義される。
セル全体として、どれを使用するかは、セル自身の情報,セル自身の情報2の属性で、これらを指定する。
このとき、tableStyles, colorsは直接指定されず、例えばカスタムされた色が塗りつぶしに使用されていれば、これがfillsの子要素に定義される。
セル自身の情報,セル自身の情報2の属性は、numFmts要素以外は、子要素の0ベースのindexが対応する属性の値として指定される。
numFmt要素のみ、numFmtIdを持ち、対応する属性の値として指定される。

セル自身の情報

上記のスタイルのどれを使うかを指定している要素で、cellStyleXfs, cellXfs, cellStylesがここに分類できるように思える。
この3つの要素のうち最も基本となるのが、cellStyleXfs要素で、ワークブックで使用されている名前付きセルスタイルを定義している要素
次に、cellStyles要素が似たような要素で、cellStyleXfs要素からの少しの差を示す。実際にxfId属性で、cellStyleXfs要素の子要素の0ベースのインデックスを指定する
最後に、cellXfs要素で、シートのセル要素が参照する要素はこの要素の子要素で、参照方法は、0ベースのインデックス

セル自身の情報2

dxfs要素で、使用するセル内部のスタイル情報のみが定義されている。
条件付き書式設定で使用される要素で、ワークシートのcfRuleのdxfId属性が子要素の0ベースのインデックスで参照する

【Java】FileとPath(+Files)

FileクラスとPathインタフェース(+Filesクラス)のどちらを使えばよいのか

 

ttkcd.hatenablog.com

に書いたように、PathはFileで可能な操作は基本的に可能

はじめに、似たような機能を持つのにそもそもパッケージが異なる
Fileクラスがjava.ioなのに対して、Pathインタフェースはjava.nio.file
nはnewで、PathインタフェースはJava7で追加されたもの。つまり、Oracleはすでにある機能を改めて新しいAPIを作成した

結論

いかに主な違いを記載するが、基本的に新規のシステムではPathとFilesを使用したほうがよさそう
おそらく、Pathが追加されるタイミングで、FileクラスのtoPath()が追加された。
違い1(エラー処理)
それぞれを使用してファイルを削除する場合を考える。
var file = new File("");
var path = Paths.get("");
boolean isDeleted = file.delete(); // ①
Files.delete(path); // ②
上記のコードの場合、①は削除できたか否かを返すが、②はコンパイルエラー(IOExceptionの処理が必要)が発生する。
つまり、削除を試みたが削除できなかった原因がわかる。
違い2(メタデータ
ファイルには許可・所有者などのメタデータが含まれているが、Fileクラスはサポートされていない。Pathはサポートしている
例)ファイルの所有者:Files.getOwner(Path path, LinkOption... options)
違い3(パフォーマンス)
FileはPathに比べるとパフォーマンスが悪くなる場合がある。
例)ディレクトリに多数のファイルがあった場合