カテゴリー別アーカイブ: XBRL財務分析

XBRL財務分析

いろいろやってみよう

XBRLからEXCELを使って財務指標を計算する方法は一通り説明しました。後は、実践あるのみです。
実際に、さまざまな企業の有価証券報告書XBRLデータを使って財務分析をしてみてください。
例えば、特定の企業の過去の全XBRLデータを集めてきて、時系列分析をするのもよいでしょう。EDINETにはXBRLデータは2008年7月以降に開示された有価証券報告書(半期・四半期報告書)分がありますので、過去3年分くらい集めることができます。
ツールを使って四半期ごとの売上高や利益の推移をまとめ、EXCELのグラフ機能を使えば簡単・きれいに説得力のある資料を作成できることと思います。
ライバル企業のデータを集めて比較分析する、なんていうのも同じです。
EDINETだけでなく、TDnetで開示されている決算短信や業績予想などもXBRLで開示されています。ツールはEDINETのXBRL向けに作成しましたが、TDnetのXBRLでも問題なく動作しますので、投資家はXBRLデータから投資判断を自動で行うようなロジックをEXCELだけで作成することができるでしょう。

ダウンロードがめんどくさい

XBRLを使えば使うほど感じるのは、現在のEDINET/TDnetだとXBRLを集める作業がめんどくさい、という点につきます。XBRLがコンピュータで使われることを想定しているのにもかかわらず、EDINETもTDnetも、ダウンロードを手作業でやらせることを想定しています。これは、EDINETやTDnetに対して、XBRLのほうが後付けの機能なので仕方がないところもあります。
この点に関しては、[有報キャッチャーウェブサービス AtomAPI]で、簡単なAtomAPIでXBRLデータを取得できるサービスが展開されています。
とはいえ、やはり開示元であるEDINETやTDnetから1次ソースをいち早く確実に取得したい、というのが情報利用者の本音だと思います。
2013年に稼動が予定されている次世代EDINETでは、この点が改善されることを大いに期待しています。

総資産当期純利益率(ROA)

総資産当期純利益率(ROA)を計算します。
引き続き、サンプルデータには、三菱重工の2011年3月期の有価証券報告書のXBRLデータを使います。
有報キャッチャーからも直接ダウンロードできます[直リンク])
ここでは、ROAの計算式は、以下のとおりとします。

ROA = 純利益 ÷ 総資産 × 100

必要な数値は、「純利益」と「総資産」です。勘定科目リストから、「純利益」は『NetIncome』、「総資産」は『Assets』がよさそうです。
注意すべきはコンテキストです。NetIncomeは期間コンテキスト、Assetsは時点コンテキストですので、以下のように入力すればよさそうです。(緑のセルは計算式です)
総資産当期純利益率(ROA)1
計算結果は以下のようになります。
総資産当期純利益率(ROA)2
うん、ばっちり。
それにしても三菱重工、昨年に比べると資産を圧縮する一方で純利益が倍増したので、ROAがずいぶん改善したのがわかります。それでも低いけど。ちなみに筆者はもう5年以上もこの会社の株主です(ちょっとだけどね)。

もう少しだけ厳密に

ところで、ROAのように、財務指標の計算で期間コンテキストの値と時点コンテキストの値を両方用いるときは、時点コンテキストの値は、期間の開始時点と終了時点の平均をとる場合があります。(ちょっとググってみたら、アルパカの会社なんかが、採用していました)
ROAでいうと、計算式が以下のようになります。

ROA = 純利益 ÷ ((総資産(期首時) + 総資産(期末時)) ÷ 2) × 100

ROAの理論としては、こちらのほうがより厳密(理論に近い)と言えます。
この計算式で計算してみましょう。
総資産当期純利益率(ROA)3
さて、期首のコンテキストはどうすればよいでしょう。コンテキストの命名規約を見ても、時点コンテキストは各期間コンテキストの終了時点しか存在しません。
結論から言うと、期首時点コンテキストは、その前の期間の期末時点コンテキストになります。
例えば、『今期の期首のコンテキスト = 前期末のコンテキスト』なのです。
基本的な会計の知識があれば、当たり前ですね。前期末の現金残高が今期の期首の現金残高は同じでしょ、と。
この点、XBRLの仕様上は以下のように記述されています。

instant 要素の内容に時刻指定がない日付を指定したときには,同日のT00:00:00 のP1D後,すなわち,一日後をdateTime として指定したものとする。これは,日が終了する午後12 時を表す。

ちょっとわかりづらいのですが、「instant要素の内容に時刻指定がない日付を指定したとき」というのが、時点コンテキストになります。時点コンテキストの時間指定がない場合(普通はない)は、その日の終了する午後12時、つまりその日から次の日に変わる瞬間、を表す、ということなのです。
具体的な例で見てみましょう。
ある期間コンテキストのinstant要素が「2011-03-31」であった場合、それは、2011年3月31日から2011年4月1日に変わる瞬間を意味します。それは、2011年3月31日で終わる期間の期末時点であり、かつ、2011年4月1日から始まる期間の期首時点でもあるわけです。
では、CurrentYearConsolidatedDuration(今年度・連結・期間)の期首時点のコンテキストはなんでしょうか?それは、前年度・連結・時点コンテキスト、すなわち「Prior1YearConsolidatedInstant」です。さらに、Prior1YearConsolidatedDuration(前年度・連結・期間)の期首時点のコンテキストは、前々年度・連結・時点コンテキスト、すなわち「Prior2YearConsolidatedInstant」となるわけです。
総資産当期純利益率(ROA)4
今期のROAは計算できましたが、前期のROAがエラーになっています。このXBRLインスタンスには、Prior2YearConsolidatedInstantのAssetsのファクトが存在しないようです。
現在では、EDINETの有価証券報告書のXBRLには、財務諸表の本表部分の数値が記述されているだけです。Assetsは貸借対照表上の数値ですが、貸借対照表は今期と前期の数値しかありません。ですので、前々期のAssetsは存在しないのです。
前期(2010年3月期)のROAを計算するためには、2010年3月期の有価証券報告書のXBRLを使って同じ計算をすればよいのです。三菱重工の2010年3月期のXBRLインスタンスはURL「http://resource.ufocatch.com/xbrl/edinet/ED2010062400796/jpfr-asr-E02126-000-2010-03-31-01-2010-06-24.xbrl」で直接参照することができます。セルA1にこのURLを入力するだけで再計算されますので、興味がある方は、ぜひご自分で試してみてください。

売上高経常利益率

売上高経常利益率を計算します。
引き続き、サンプルデータには、三菱重工の2011年3月期の有価証券報告書のXBRLデータを使います。
有報キャッチャーからも直接ダウンロードできます[直リンク])
売上高経常利益率の計算式は、以下のとおりです。

売上高経常利益率 = 経常利益 ÷ 売上高 × 100

必要な数値は、「経常利益」と「売上高」です。
対応する要素を決めますので、勘定科目リストから、「経常利益」と「売上高」に該当しそうな要素を探していきます。「経常利益」は『OrdinaryIncome』、「売上高」は『NetSales』がよさそうです。
では、計算式がほとんど同じなので、流動資産のときのシートをコピーして、売上高経常利益率を計算してみます。分子のCurrentAssetsをOrdinaryIncomeに、分母のCurrentLiabilitiesをNetSalesに変更すればよさそうですね。
売上高経常利益率を
あれ?エラーになりました。
そういえば、コンテキストの確認を忘れていました。
OrdinaryIncomeやNetSalesは、勘定科目リストによると、periodTypeがdurationになっています。CurrentAssets/CurrentLiabilitiesはinstantでした。ということは、コンテキストが違うので修正する必要がありそうです。コンテキストの命名規約によると、時点コンテキストを期間コンテキストに直すには、最後の「Instant」を「Duration」に変更するだけでよさそうです。
売上高経常利益率2
これでよさそうですね。
PDFの有価証券報告書と同じ(正しい)数値が取得できていることが確認できます。

コンテキストを決める

インスタンスファイルから要素を指定してファクトを取り出すと、複数のファクトが出てきます。これらは同じ要素のコンテキスト違いのファクトです。ファクトは、要素名とコンテキストでユニークになっています。
 コンテキストとは、日本語で文脈という意味です。XBRLでは、そのファクトがどのような文脈(事業体・報告期間・シナリオ)に属するのかを示しています。
EDINETで開示されるXBRLデータでは、ガイドラインによってコンテキストの命名ルールが決められています。

EDINETのコンテキスト命名ルール

引用元:報告書インスタンス作成ガイドライン

コンテキストID:{相対年度}{連結・個別}{期間・時点}

相対年度

設定値 説明
CurrentYear 当年度
Interim 中間期
Prior1Year 前年度
Prior1Interim 前中間期
Prior2Year 前々年度
Prior{数値}Year {数値}年度前
CurrentYTD 当四半期累計期間
CurrentQuarter 当四半期会計期間
Prior{数値}YTD {数値}年度前同四半期累計期間
Prior{数値}Quarter {数値}年度前同四半期会計期間
LastQuarter 前四半期会計期間
Prior{数値}LastQuarter {数値}年度前の前四半期会計期間

連結・個別

設定値 説明
Consolidated 連結
NonConsolidated 個別(非連結)

期間・時点

設定値 説明
Instant 時点
Duration 期間

ファクトが期間のコンテキストに属するか、時点のコンテキストに属するかは、要素のperiodType属性によって決まります。基本的には、BS科目(資産・負債・資本に属する勘定科目の要素)はある時点の状態を表す概念なので、時点コンテキストに属し、PL科目(収益・費用に属する勘定科目の要素)はある期間の成績を表す概念なので、期間コンテキストに属します。
例えば、流動比率の計算のときの「CurrentYearConsolidatedInstant」は、その有価証券報告書の『当年度・連結・時点』、「Prior1YearConsolidatedInstant」は、『前年度・連結・時点』を表すコンテキストです。CurrentAssetsやCurrentLiabilitiesが時点コンテキストに属すため、これらのコンテキストのファクトを抜き出しています。
コンテキスト

要素を決める

財務指標を計算するためには、各指標の計算に必要な項目に該当する要素を決めなければいけません。流動比率であれば、「流動資産」と「流動負債」に該当する要素を決めます。

タクソノミから候補の要素を見つける

要素を決めるためには、まずどのような要素が存在しているかを調べて、その中から適切なものをピックアップしていきます。
XBRLでは、要素はタクソノミに定義されています。各企業が独自に増やすこともできますが、一般的な勘定科目はあらかじめタクソノミに定義されており、XBRLインスタンスの作成者はできるだけその中から適切な科目を選んで利用することが推奨されています。ですから、一般的な財務指標の計算については、独自に拡張されるものは無視して問題ないと思われます。(どのような名前の要素になるか予想できませんので、現実的には無視するしかない)
では、EDINETのタクソノミを見てみましょう、、、といいたいところですが、EDINETのタクソノミの場合には、金融庁が「勘定科目リスト」を提供してくれてますので、手っ取り早くそちらを参照しましょう。
勘定科目リストを開くとB列からM列がその要素に紐付けられているラベル(表示名)です。そのうちB列の日本語標準ラベルとC列の日本語冗長ラベルを見れば、どのような要素かは想像がつきます。
「流動資産」に該当しそうな科目を探していくと、いきなり「一般商工業」シートの5行目B列に『流動資産』というラベルがあります。しかし、この科目はC列が『流動資産、タイトル項目』となっていることから、実際に金額を持つ要素ではなく、タイトル行として使用される要素です。(V列のabstract属性が『true』になっているのも、金額を持たない要素であることを示しています)
さらに見ていくと、122行目B列にまたも『流動資産』というラベルがあります。C列も『流動資産』となっており、どうやらこれが探していた要素のようです。O列の要素名は『CurrentAssets』となっています。
同様に「流動負債」を探すと、454行目の『CurrentLiabilities』が見つかります。

実データで確かめる

候補としてピックアップした要素が適切かどうか実際のデータで確かめていきます。
確かめる方法は、実データのなかからいくつかをサンプリングして、その要素のファクト(値)を抽出したものと、EDINETのHTMLやPDFで記述されている財務諸表の値とを比較していく、という地味なものです。
例えば、三菱重工の2011年3月期の有価証券報告書のケースを見てみると、ツールで取得した値(下図)と、有価証券報告書(PDFファイル)の連結貸借対照表の流動資産・流動負債の金額(74-75/168ページ)を見比べると、きちんと一致していることがわかります。
計算結果

流動比率を計算してみる

作成したツールを利用して、代表的な安全性指標である流動比率を計算してみます。
[ツールのダウンロード]

流動比率 = 流動資産 ÷ 流動負債 × 100

サンプルデータには、三菱重工の2011年3月期の有価証券報告書のXBRLデータを使います。XBRLデータはEDINETからダウンロードしておいてください。
有報キャッチャーからも直接ダウンロードできます[直リンク])

手順

  1. ダウンロードしたXBRLデータを解凍し、インスタンスファイル(jpfr-asr-E02126-000-2011-03-31-01-2011-06-23.xbrl)をツール(EXCELファイル)と同じフォルダに置く。
  2. ツール(EXCELファイル)を開く
  3. 新規シートを追加し、そのシートに下の図のように入力します。(緑色のセルは計算式です)計算式
  4. 計算結果は以下のようになります。
    計算結果
    もし、計算結果がエラー(#N/A)になった場合、A1のインスタンスファイルをフルパス(C:\~から)で指定してください。

セルの入力内容

  • A1:インスタンスファイル名
  • B2:コンテキスト「連結の今期末時点」のコンテキストID
  • C2:コンテキスト「連結の前期末時点」のコンテキストID
  • A3:要素「流動資産」の要素名
  • A4:要素「流動負債」の要素名
  • B3:C4:インスタンスファイルから「同列のコンテキスト」の「同行の要素」のファクト(値)を取得するワークシート関数
  • B5:C5:流動比率の計算式

説明

行方向に要素名、列方向にコンテキストIDを並べて、CurrentAssets(流動資産)とCurrentLiabilities(流動負債)の値(ファクト)を取得し、流動比率を計算しています。
XBRLで財務指標を計算する場合、最も難しいのが要素名の決定です。
流動比率の場合、必要なデータは「流動資産」と「流動負債」です。ある程度会計の知識がある人が貸借対照表を見れば、流動資産と流動負債の金額を見つけるのは簡単です。しかし、そこは融通の利かないコンピュータ、XBRLから抜き出すためには、きっちり要素名を指定してあげる必要があります。ここでは「流動資産」は「CurrentAssets」、「流動負債」は「CurrentLiabilities」、として計算しました。
では、どうすれば正しい要素名を見つけられるのでしょうか。

完成したツールと使い方

完成したツールは、こちらからダウンロードできます。
ダウンロードしたファイル(EXCELワークブック)にワークシート関数がVBAで実装されています。それらワークシート関数は、そのファイルの中では普通のワークシート関数として使用できます。ツールにあらかじめ設定されているサンプルデータにも、ワークシート関数が使われています。
もし、これらの関数を任意のEXCELファイルでも使いたい、という場合には、アドイン化しておくと便利です。

ファクト取得関数

続いて、ファクト取得関数を実装します。

Function XBRLFact(ByVal instanceFilePath As String, Optional ByVal ContextID As String = “”, Optional ByVal namespaceURI As String = “”, Optional ElementName As String = “”)

On Error GoTo ErrorHandler

Dim inst As TInstance
Dim i As Integer
Dim result() As Variant
Dim selectedFacts() As TFact

‘インスタンスを取得する
inst = ParseInstanceFile(instanceFilePath)
‘インスタンスのファクトから、出力対象のファクトを選択する
selectedFacts = FilterFact(inst.Facts, ContextID, namespaceURI, ElementName)

‘結果を格納する2次元配列の大きさでReDimする。
‘該当のデータが見つからなかったら、UBound(facts)でエラーになるため、ErrorHandlerに
ReDim result(0 To UBound(selectedFacts), 0 To 6)
For i = 0 To UBound(selectedFacts)
result(i, 0) = selectedFacts(i).Value
result(i, 1) = selectedFacts(i).ElementName
result(i, 2) = selectedFacts(i).ElementNamespace
result(i, 3) = selectedFacts(i).ContextID
result(i, 4) = selectedFacts(i).Nil
result(i, 5) = selectedFacts(i).Unit
result(i, 6) = selectedFacts(i).Decimals
Next

XBRLFact = result
Exit Function

ErrorHandler:
Err.Clear
XBRLFact = CVErr(xlErrNA)

End Function

‘ファクトの配列から、対象のファクトを選択する
Private Function FilterFact(Facts() As TFact, ContextID As String, namespaceURI As String, ElementName As String) As TFact()

Dim i As Integer
Dim j As Integer
Dim selectedFacts() As TFact

For i = LBound(Facts) To UBound(Facts)
If (ContextID = “” Or Facts(i).ContextID = ContextID) And _
(namespaceURI = “” Or Facts(i).ElementNamespace = namespaceURI) And _
(ElementName = “” Or Facts(i).ElementName = ElementName) Then

ReDim Preserve selectedFacts(0 To j)
selectedFacts(UBound(selectedFacts)) = Facts(i)
j = j + 1

End If
Next

FilterFact = selectedFacts

End Function

こちらもXBRLの解析が完了しているインスタンスが取得できてしまえば、きわめて簡単です。メンバー変数であるファクトの配列から、条件に合致するファクトを選別し、出力しています。ファクトの配列から条件に合致するファクトだけを選別するため、下請関数FilterFactを作成しました。
なお、この関数をワークシート関数として使う場合、配列数式として入力する必要があります。配列数式として入力するためには、ワークシートの出力範囲のセルを選択して、F2 キーを押し、Ctrl キーと Shift キーを押しながらEnter キーを押します。この数式が配列数式として入力されていない場合、単一の値(1行1列目の値)のみが計算結果として返されます。

コンテキスト取得関数

XBRLインスタンスファイルを解析する関数が完成したので、ユーザがワークシートに入力して呼び出すことができるワークシート関数を実装していきます。
最初に、コンテキスト取得関数を実装します。

Function XBRLContext(ByVal instanceFilePath As String, Optional ByVal ContextID As String = “”)

On Error GoTo ErrorHandler

Dim inst As TInstance
Dim i As Integer
Dim j As Integer
Dim result() As Variant

‘インスタンスを取得する
inst = ParseInstanceFile(instanceFilePath)

If (ContextID = “”) Then
‘コンテキストIDを省略した場合、n行6列(n:インスタンスのコンテキスト配列の長さ)
ReDim result(0 To UBound(inst.Contexts), 0 To 5)
Else
‘コンテキストIDを指定した場合、1行6列
ReDim result(0 To 0, 0 To 5)
End If

‘配列にコンテキスト情報を出力する
For i = 0 To UBound(inst.Contexts)
If (ContextID = “” Or inst.Contexts(i).ContextID = ContextID) Then
result(j, 0) = inst.Contexts(i).ContextID
result(j, 1) = inst.Contexts(i).StartDate
result(j, 2) = inst.Contexts(i).EndDate
result(j, 3) = inst.Contexts(i).Instant
result(j, 4) = inst.Contexts(i).Scenario
result(j, 5) = inst.Contexts(i).ScenarioNonConsolidate
j = j + 1
End If
Next

If (j = 0) Then
‘j=0の場合は、出力対象のコンテキストが見つからなかったケース
‘その場合は、#N/A を返す
XBRLContext = CVErr(xlErrNA)
Else
XBRLContext = result
End If
Exit Function

ErrorHandler:
Err.Clear
XBRLContext = CVErr(xlErrNA)
End Function

XBRLの解析が完了しているインスタンスが取得できてしまえば、きわめて簡単です。メンバー変数であるコンテキストの配列から、名前が一致する(引数が省略された場合は全ての)コンテキストを選別し、出力します。

出力結果を格納するresult()は、2次元配列です。結果をワークシートに出力する場合、最初の添え字が行方向に展開されて、2つめの添え字が列方向に展開されます。

なお、この関数をワークシート関数として使う場合、配列数式として入力する必要があります。配列数式として入力するためには、ワークシートの出力範囲のセルを選択して、F2 キーを押し、Ctrl キーと Shift キーを押しながらEnter キーを押します。この数式が配列数式として入力されていない場合、単一の値(1行1列目の値)のみが計算結果として返されます。

XBRLインスタンスファイル解析

ここから実際にEXCEL VBAでの実装の説明に入ります。

ユーザ定義型

まず、ワークシート関数を実装する前に、XBRLインスタンスファイルをユーザ定義型の変数に読み込む処理を実装していきます。
最初に必要なユーザ定義型を3つ定義します。

‘コンテキスト
Public Type TContext
‘コンテキストID
ContextID As String
‘開始日
StartDate As Variant
‘終了日
EndDate As Variant
‘基準日
Instant As Variant
‘シナリオ
Scenario As Variant
‘NonConsolidateシナリオかどうか
ScenarioNonConsolidate As Boolean
End Type

‘ファクト
Public Type TFact
‘要素名
ElementName As String
‘名前空間
ElementNamespace As String
‘コンテキストID
ContextID As String
‘値
Value As Variant
‘単位
Unit As Variant
‘Nil属性
Nil As Boolean
‘デシマル属性
Decimals As Variant
End Type

‘XBRLインスタンス
Public Type TInstance
‘XBRLインスタンスのファイルパス
FilePath As String
‘コンテキスト
Contexts() As TContext
‘ファクト
Facts() As TFact
End Type

TContext型の開始日・終了日・基準日を(Date型にせず)Variant型にしたのは、VBAではDate型の初期値の関係で未設定の場合の扱いが面倒になるからです。値を設定するさいに、Date型の値を設定し、未設定の状態では初期値のEmptyとなるようにします。
TContext型のScenarioNonConsolidateは、シナリオにNonConsolidate要素が含まれているかを示します。EDINETのXBRLインスタンスにおいては、コンテキストのシナリオにNonConsolidate要素が含まれているということは、非連結(単独)のコンテキストであることを示します。

TFact型の値は、要素によって、文字列だけでなく日付・真偽・金額などが設定されるため、Variant型にしています。XBRLインスタンスから読み取った文字列の形式により、適当に型変換して設定します。

TInstance型は、XBRLインスタンスの情報を保持します。インスタンスには、コンテキストとファクト以外にも、参照しているスキーマのリファレンスや、単位やフットノートなどが記述されていますが、このツールでは意図的に無視しています。コンテキストとファクトは動的配列で保持します。

XMLファイルの読み込み

XBRLインスタンスはXMLで記述されています。本ツールでは、Microsoft.XMLDOMを使ってXMLを処理することにします。<

‘パースしたXBRLインスタンスを保持しておく領域
Private parsedInstanceFile(1024) As TInstance

‘指定されたパスのインスタンスファイルを読み込んでパースし、
‘XBRLインスタンス型にして変換する
Function ParseInstanceFile(ByVal path As String) As TInstance

‘モジュールレベル変数に保持されているかチェックし、
‘保持されている場合にはそれを返す
Dim i As Integer

For i = 0 To UBound(parsedInstanceFile)
If (parsedInstanceFile(i).FilePath = path) Then
ParseInstanceFile = parsedInstanceFile(i)
Exit Function
End If
‘FilePathが””のものがあったら、その先はないのでExitする。
If (parsedInstanceFile(i).FilePath = “”) Then
Exit For
End If
Next

‘XMLオブジェクト(インスタンスファイルをセットする)
Dim xml As Object
‘パースしたインスタンスを設定する
Dim newInstance As TInstance

‘XMLファイル(インスタンスファイル)をロードする
Set xml = CreateObject(“Microsoft.XMLDom”)
‘同期処理にする(ロードが完了するまで処理を待つ)
xml.async = False
‘ロードする
xml.Load path
‘インスタンスのメンバーを設定
newInstance.FilePath = path
newInstance.Contexts = GetContexts(xml)
newInstance.Facts = GetFacts(xml)

‘モジュールレベル変数に保管しておく
If (i <= UBound(parsedInstanceFile)) Then
parsedInstanceFile(i) = newInstance
End If

Set xml = Nothing
ParseInstanceFile = newInstance

End Function

ParseInstanceFile関数は、引数でXBRLインスタンスのパスを受け取り、そのパスのファイルをロードして解析(パース)して、TInstance型に格納します。
XMLをロードして解析する処理は重くなるため、一度解析したらモジュールレベルの変数に保存し、同じパスのファイルは何度も解析しないようにします。なお、保存する配列の長さは1025(添字0~1024まで)となっていますが、この長さに深い意味はありません。

この関数のキモは、TInstance型の変数 newInstance のメンバーContextsとFactsに値を設定するところですが、それはそれぞれ下請け関数のGetContexts/GetFacts関数で行います。

コンテキストの取得

XBRLインスタンスをロードしたXMLオブジェクトからコンテキスト(の配列)を取得します。

‘インスタンスファイルのXMLオブジェクトから、コンテキストを取得する
Function GetContexts(ByVal xml As Object) As TContext()

Dim nodeContexts As Collection
Dim result() As TContext
Dim idxNode As Object
Dim i As Integer

Set nodeContexts = myGetElementsByTagNameNS(xml, NAMESPACE_XBRLI, “context”)

ReDim result(0 To nodeContexts.Count – 1)
i = 0
For Each idxNode In nodeContexts
result(i) = ToContext(idxNode)
i = i + 1
Next
GetContexts = result

End Function

‘XMLノードからTContextに変換する
Function ToContext(ByVal xml As Object) As TContext
Dim result As TContext
Dim element As Object
Dim dateElements As Collection
Dim att As Object
Dim scenarioElements As Collection

‘コンテキストIDの設定
For Each att In xml.Attributes()
If (att.baseName = “id”) Then
result.ContextID = att.Text
Exit For
End If
Next

‘開始日の設定
Set dateElements = myGetElementsByTagNameNS(xml, NAMESPACE_XBRLI, “startDate”)
If (dateElements.Count > 0) Then
result.StartDate = CDate(dateElements(1).Text)
End If

‘終了日の設定
Set dateElements = myGetElementsByTagNameNS(xml, NAMESPACE_XBRLI, “endDate”)
If (dateElements.Count > 0) Then
result.EndDate = CDate(dateElements(1).Text)
End If

‘基準日の設定
Set dateElements = myGetElementsByTagNameNS(xml, NAMESPACE_XBRLI, “instant”)
If (dateElements.Count > 0) Then
result.Instant = CDate(dateElements(1).Text)
End If

‘シナリオ、NonConsolidateシナリオかどうかの設定
Set scenarioElements = myGetElementsByTagNameNS(xml, NAMESPACE_XBRLI, “scenario”)
If (scenarioElements.Count > 0) Then
result.Scenario = scenarioElements(1).Text
For Each element In scenarioElements(1).getElementsByTagName(“*”)
If (element.baseName = “NonConsolidated”) Then
result.ScenarioNonConsolidate = True
Exit For
End If
Next
End If

ToContext = result

End Function

GetContexts関数は、XMLオブジェクトから、名前空間「http://www.xbrl.org/2003/instance」、名称「context」のノードを取得します。この各ノードが1つのTContext型の変数に該当します。

contextノードは、典型的には以下のようなXMLノードです。

<xbrli:context id=”CurrentYearNonConsolidatedDuration”>
<xbrli:entity>
<xbrli:identifier scheme=”http://info.edinet-fsa.go.jp”>EDINETコード</xbrli:identifier>
</xbrli:entity>
<xbrli:period>
<xbrli:startDate>2010-01-01</xbrli:startDate>
<xbrli:endDate>2010-12-31</xbrli:endDate>
</xbrli:period>
<xbrli:scenario>
<jpfr-oe:NonConsolidated />
</xbrli:scenario>
</xbrli:context>

ToContext関数は、各contextノードからTContext型の変数に変換します。id属性の値をContextIDに、startDateタグの値をStartDateに、endDateタグの値をEndDate、Instantタグの値をInstant、scenarioタグの内容をScenarioにそれぞれ設定していきます。scenarioタグの中にNonConsolidatedという要素があるかないかをチェックし、あった場合にはScenarioNonConsolidateの値をTrueにしています。

scenarioタグの中にNonConsolidatedという要素があるかないかというのは、EDINETのデータの場合、そのコンテキストが連結(Consolidated)なのか非連結(NonConsolidated)なのかを意味しています。

ファクトの取得

XBRLインスタンスをロードしたXMLオブジェクトからファクト(の配列)を取得します。

‘インスタンスファイルのXMLオブジェクトから、ファクトを取得する
Function GetFacts(ByVal xml As Object) As TFact()

Dim xbrlNodes As Object
Dim result() As TFact
Dim element As Object
Dim nodeFacts As Collection
Dim idx As Integer

Set nodeFacts = New Collection
‘xbrlのノード(ルートノード)を取得する
Set xbrlNodes = myGetElementsByTagNameNS(xml, NAMESPACE_XBRLI, “xbrl”)
If (xbrlNodes.Count > 0) Then
‘ルートノードの子ノードには、ファクトのほか、コンテキストや
‘フットノートリンクやSchemaRefなどが定義される。
‘それらの名前空間は特定のものであるため、それ以外の名前空間
‘に属したものをファクトとする。
For Each element In xbrlNodes(1).ChildNodes()
If (element.namespaceURI <> NAMESPACE_LINKBASE And _
element.namespaceURI <> NAMESPACE_XBRLI) Then
nodeFacts.Add element
End If
Next
End If

ReDim result(0 To nodeFacts.Count – 1)
idx = 0
For Each element In nodeFacts
result(idx) = ToFact(element)
idx = idx + 1
Next
GetFacts = result

End Function

‘XMLノードからTFactに変換する
Function ToFact(ByVal xml As Object) As TFact
Dim result As TFact
Dim att As Object

result.ElementName = xml.baseName
result.ElementNamespace = xml.namespaceURI
For Each att In xml.Attributes()
If (att.baseName = “contextRef”) Then
result.ContextID = att.Text
ElseIf (att.baseName = “unitRef”) Then
result.Unit = att.Text
ElseIf (att.baseName = “decimals”) Then
result.Decimals = att.Text
ElseIf (att.namespaceURI = NAMESPACE_XMLSI And att.baseName = “nil”) Then
result.Nil = CBool(att.Text)
End If
Next
result.Value = IIf(result.Nil, CVErr(xlErrNull), ToValue(xml.Text))

ToFact = result
End Function

‘TFactのValueに設定する値を、文字列の形式から適切な型に変換して返す
Private Function ToValue(ByVal str As String) As Variant

If (IsNumeric(str)) Then
ToValue = Val(str)
ElseIf (UCase(str) = “TRUE” Or UCase(str) = “FALSE”) Then
ToValue = CBool(str)
ElseIf (IsDate(str)) Then
ToValue = CDate(str)
Else
ToValue = str
End If

End Function

GetFacts関数は、XMLオブジェクトから、xbrlノード(ルートノード)の子ノードのうちFactを表すノードを取得します。各ノードが1つのTFact型の変数に該当します。

ToFact関数は、そのノードをTFactに変換します。contextRef属性、unitRef属性、decimals属性、nil属性の値をそれぞれメンバー変数に格納し、ノードのTextをValueに設定します。Value設定するときに、ToValue関数で文字列のフォーマットからデータ型を判定し、キャストしています。