EPPlusで作成したOpenXmlの構成

前回はOpenXmlをラップするEPPlusでExcel作成しました。 今回は作成されたOpenXMLの中身を確認してみます。

tech.sanwasystem.com

フォルダ構成~セル値

作成されたダウンロードファイル名.xlsxの拡張子を変更しダウンロードファイル名.zipにし解凍します。
フォルダ構成は以下の通りになっている事がわかります。

ダウンロードファイル名
├─[Content_Types].xml
├─xl
│ │ sharedStrings.xml
│ │ styles.xml
│ │ workbook.xml
│ ├─charts
│ │ chart1.xml
│ ├─drawings
│ │ │ drawing1.xml
│ │ └─rels
│ │ drawing1.xml.rels
│ ├─media
│ │ 1sanwa.png
│ ├─worksheets
│ │ │ sheet1.xml
│ │ └─
rels
│ │ sheet1.xml.rels
│ └─rels
│ workbook.xml.rels
└─
rels
.rels

[Content_Types].xmlは本Excelドキュメントを構成するファイルのContentTypeとパスが指定されています。
それ以外のxml

workboox.xmlワークブックの定義。ワークブックを構成するシートの定義
sheet1.xmlシートの各カラムの値や計算式、ページフッタヘッダの定義
chart1.xmlグラフ・画像の定義
sharedStrings.xmlセル値の定義
style.xml書式設定の定義

となっています。

ワークシートワークシート名XMLsheet1.xmlなのでこのファイルにセル情報がどのように定義されているのか確認します。
以下ワークシートの5行目と6行目の抜粋です。
f:id:ihisa:20151112111400p:plain

    <row r="5" >
      <c r="A5" s="4" t="s">
        <v>1</v>
      </c>
      <c r="B5" s="4" t="s">
        <v>2</v>
      </c>
    </row>
    <row r="6" >
      <c r="A6" s="3" t="s">
        <v>5</v>
      </c>
      <c r="B6" s="5" >
        <v>100</v>
      </c>
      <c r="C6" s="5" >
        <v>25</v>
      </c>
      <c r="D6" s="3">
        <f>B6 * C6</f>
      </c>
      <c r="E6" s="1" />
    </row>

A5のセルに着目してみていきます。
A5には<c r="A5" s="4" t="s"><v>1</v></c>と定義されています。
sはstyle.xmlへの参照を表し、tはsharedStrings.xmlへの参照、vはセル値を表します。
ワークシート上のA5には商品という文字と、背景が青色・文字が白色というスタイルが定義されています。
style.xmlは以下の通りになっています。

<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <numFmts count="0" />
  <fonts count="4">
    <font>
      <sz val="11" />
      <name val="Calibri" />
    </font>
    <font>
      <sz val="10" />
      <name val="MS Pゴシック" />
    </font>
    <font>
      <b />
      <sz val="10" />
      <color rgb="FFFF0000" tint="0" />
      <name val="MS Pゴシック" />
    </font>
    <font>
      <sz val="10" />
      <color rgb="FFFFFFFF" tint="0" />
      <name val="MS Pゴシック" />
    </font>
  </fonts>
  <fills count="3">
    <fill>
      <patternFill patternType="none" />
    </fill>
    <fill>
      <patternFill patternType="gray125" />
    </fill>
    <fill>
      <patternFill patternType="solid">
        <fgColor rgb="FF0000FF" tint="0" />
      </patternFill>
    </fill>
  </fills>
  <borders count="2">
    <border>
      <left />
      <right />
      <top />
      <bottom />
      <diagonal />
    </border>
    <border>
      <left style="thin" />
      <right style="thin" />
      <top style="thin" />
      <bottom style="thin" />
      <diagonal />
    </border>
  </borders>
  <cellStyleXfs count="1">
    <xf fontId="0" />
  </cellStyleXfs>
  <cellXfs count="6">
    <xf fontId="0" applyFont="1" xfId="0" />
    <xf fontId="1" applyFont="1" xfId="0" />
    <xf fontId="2" applyFont="1" xfId="0">
      <alignment horizontal="center" />
    </xf>
    <xf fontId="1" applyFont="1" borderId="1" applyBorder="1" xfId="0" />
    <xf fontId="3" applyFont="1" fillId="2" applyFill="1" borderId="1" applyBorder="1" xfId="0">
      <alignment horizontal="center" />
    </xf>
    <xf numFmtId="2" applyNumberFormat="1" fontId="1" applyFont="1" borderId="1" applyBorder="1" xfId="0" />
  </cellXfs>
  <cellStyles count="1">
    <cellStyle name="Normal" xfId="0" builtinId="0" />
  </cellStyles>
  <dxfs count="0" />
</styleSheet>

<c r="A5" s="4" t="s"><v>1</v></c>s="4"style.xml<cellXfs count="6">タグ配下のxfタグの5番目を指します(0始まり)
つまりここです。

<xf fontId="3" applyFont="1" fillId="2" applyFill="1" borderId="1" applyBorder="1" xfId="0">
  <alignment horizontal="center" />
</xf>

fontId="3"は同じstyle.xml<fonts count="4">タグ配下の<font>タグの4番目を指します。 つまりここです。

<font>
  <sz val="10" />
  <color rgb="FFFFFFFF" tint="0" />
  <name val="MS Pゴシック" />
</font>

同様にfillId="2"<fills count="3">タグ配下の<fill>タグの3番目

<fill>
  <patternFill patternType="solid">
    <fgColor rgb="FF0000FF" tint="0" />
  </patternFill>
</fill>

※fgColorの指定はARGB

borderId="1"<borders count="2">タグ配下の<border>タグの2番目

<border>
  <left style="thin">
    <color auto="1"/>
  </left>
  <right style="thin">
    <color auto="1"/>
  </right>
  <top style="thin">
    <color auto="1"/>
  </top>
  <bottom style="thin">
    <color auto="1"/>
  </bottom>
  <diagonal/>
</border>

となります。 Excelをみたまんまの定義がされています。わかりやすい!

肝心のセルの値は<c r="A5" s="4" t="s"><v>1</v></c><v>1</v>の部分なので、sharedStrings.xmlの2つめの値になります。

<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="8" uniqueCount="8">
  <si>
    <t>今日の売上!</t>
  </si>
  <si>
    <t>商品</t>
  </si>
  <si>
    <t>単価</t>
  </si>
  <si>
    <t>売上数</t>
  </si>
  <si>
    <t>合計</t>
  </si>
  <si>
    <t>りんご</t>
  </si>
  <si>
    <t>みかん</t>
  </si>
  <si>
    <t>ばなな</t>
  </si>
</sst>

.relsファイル

拡張子が.relsのファイルはファイルとXMLスキーマのリレーションが記載されています。
ワークシートワークシート名には画像とグラフが挿入されています。sheet1.xml内には

<drawing r:id="rId1" />

とidが記載されています。 sheet1.xmlと同一フォルダにある_rels/sheet1.xml.relsをみるとそのidで

<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" Target="../drawings/drawing1.xml"/></Relationships>

という記載があることががわかります。

../drawings/drawing1.xmlを見ると画像とグラフの位置が指定されていることがわかります。またidが指定されています。

<c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId1" />
<a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="rId2" cstate="print" />

またまたdrawing1.xmlと同一フォルダにある_rels/drawing1.xml.relsをみると

<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart" Target="../charts/chart1.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/1sanwa.png"/>

ようやくグラフと画像の本体にたどりつきました。
もちろん直接xmlを編集して保存すればExcelの内容も変わります。
EPPlusで作成したOpenXmlも通常のOpenXml同様の中身となっていることがわかりました。

なおOpenXMLでゴリゴリ書くには以下よりライブラリを作成し、参照設定すればいいです。
github.com

こちらが参考になります。
Creating basic Excel workbook with Open XML - CodeProject

実際にxlsxファイルの中身を逐一見ることは業務としてほぼないと思いますが、構成を知っておくとOpen-XML-SDKを用いる場合理解しやすいので覚えておいて損はないかと思います。
なんかよくわからんがファイルサイズが大きいときとかってありますよね、そういう場合は直接中見るほうが早い場合もありそうです。