iimon TECH BLOG

iimonエンジニアが得られた経験や知識を共有して世の中をイイモンにしていくためのブログです

CSVとExcelファイルの構造について調べてみた

■はじめに

こんにちは。

株式会社iimonでエンジニアをしている「白水(しらみず)」です。

弊社では、主にChromeExtensionを開発しています。

Extensionを使って「CSV」や「Excel」ファイルを出力することが多々あります。各ファイルの特徴について、知らないことが多かったので調べてみました。

また、最近ではExcelファイルでセルに色をつけたり、列や行を固定したいなどExcelファイルの構造を知っている必要がある要望もあったため、この機会に調べてみました。

CSVファイルについて

CSVファイルとは?

CSVファイルとは、「Comma Separated Values(カンマ セパレーティド ヴァリューズ)」の略で、各項目がカンマ(,)で区切られたテキストデータのことです。

CSVファイルはデータの容量が軽く、互換性があるのでExcelやメモ帳、エディタで開く事ができます。

CSVファイルの中身を確認してみる

Googleスプレッドシートを開いて、ファイルをCSVで保存するとCSVファイルを取得できます。

cat sample.csv

catコマンドで、csvファイルを開いてみると、行ごとにカンマで区切ってデータ形式を表現していることがわかります。

金額で用いられるカンマ(,)などが含まれる場合は、ダブルクォート(")で囲む必要があります。

プログラムでCSVファイルを作る場合は、文字列をカンマで区切って、行ごとに改行すればファイルが作れるシンプルな形式です。

CSVファイルの特徴

●メリット

  • テキストファイル

    CSVはプレーンテキスト形式なので、様々なソフトウェア(ExcelGoogleスプレッドシートテキストエディタなど)で開くことができます。

  • カンマで区切る

    各データ(セルの値)がカンマ(,)で区切られています。例えば、「名前,年齢,住所」といった形式です。

  • 拡張子 .csv

    ファイル名の末尾に「.csv」が付きます。

  • 互換性が高い

    さまざまなアプリケーションやプログラミング言語で読み書きが容易です。

  • 軽量

    余計な書式情報が無く、純粋なデータだけを記録するためファイルサイズが小さくなります。

●デメリット

  • 装飾・数式・グラフなどを保持できない

    セルの色やフォント、数式、グラフ、画像など、表現力のある情報は保存できず、データ(値)のみが保存されます。

  • 複雑なデータ構造には不向き

    複数シートに渡る表など、複雑な情報は格納できません。

  • カンマや改行など特殊文字の扱いが面倒

    データ中にカンマや改行がある場合は、ダブルクオーテーションで囲うなどの「エスケープ処理」が必要で、これを怠るとデータがずれてしまいやすいです。

Excelファイルについて

Excelファイルとは?

Excel(.xlsx)は、国際標準の「Office Open XML」というデータ仕様で定義されている、国際的なオープンフォーマットです。

主な拡張子は「.xlsx」や「.xls」などがあり、データの分析・計算・グラフ作成など多機能なデータ管理が可能です。

Excelファイルの特徴

  • 複数のシートに対応

    1つのファイルに複数のワークシートを持たせることができます。

  • 書式や装飾情報の保持

    セルの色やフォント、罫線、コメント、セル結合などの装飾情報を保持できます。

  • 数式・関数・グラフ・画像の保存

    複雑な計算式や関数、グラフ、図形や画像なども格納・再編集可能です

  • XMLベース+ZIP圧縮

    データはXML形式で保存され、全体をZIPで圧縮して保存が可能です。

Excelファイルを解凍してみる

Chromeスプレッドシートで、セルに「文字列」「数値」「少数」のデータを持たせてみます。

また、「セルの色変更」「行の固定」「シートを2つ作成」してみます。

ファイル→ダウンロードから、xlsxファイルをダウンロードします。

$ unzip sample.xlsx -d sample-unzip
Archive:  sample.xlsx
  inflating: sample-unzip/xl/drawings/drawing1.xml  
  inflating: sample-unzip/xl/drawings/drawing2.xml  
  inflating: sample-unzip/xl/worksheets/sheet1.xml  
  inflating: sample-unzip/xl/worksheets/_rels/sheet1.xml.rels  
  inflating: sample-unzip/xl/worksheets/sheet2.xml  
  inflating: sample-unzip/xl/worksheets/_rels/sheet2.xml.rels  
  inflating: sample-unzip/xl/theme/theme1.xml  
  inflating: sample-unzip/xl/sharedStrings.xml  
  inflating: sample-unzip/xl/styles.xml  
  inflating: sample-unzip/xl/workbook.xml  
  inflating: sample-unzip/xl/_rels/workbook.xml.rels  
  inflating: sample-unzip/_rels/.rels  
  inflating: sample-unzip/[Content_Types].xml  

先ほどダウンロードしたExcelファイルをunzipコマンドで解凍します。

そうすると、ExcelファイルはXMLファイルがZIP圧縮されているので、XMLファイルが複数取得できます。

sample-unzip/
├── [Content_Types].xml
├── _rels
└── xl
    ├── _rels
    │   └── workbook.xml.rels
    ├── drawings
    │   ├── drawing1.xml
    │   └── drawing2.xml
    ├── sharedStrings.xml
    ├── styles.xml
    ├── theme
    │   └── theme1.xml
    ├── workbook.xml
    └── worksheets
        ├── _rels
        │   ├── sheet1.xml.rels
        │   └── sheet2.xml.rels
        ├── sheet1.xml
        └── sheet2.xml

8 directories, 12 files

ディレクトリ構成としては、上のようになっています!

◆各ファイルの中身を確認してみる

●[Content_Types].xml

<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
    <Default ContentType="application/xml" Extension="xml"/>
    <Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" PartName="/xl/worksheets/sheet1.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" PartName="/xl/worksheets/sheet2.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" PartName="/xl/sharedStrings.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.drawing+xml" PartName="/xl/drawings/drawing1.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.drawing+xml" PartName="/xl/drawings/drawing2.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" PartName="/xl/styles.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.theme+xml" PartName="/xl/theme/theme1.xml"/>
    <Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" PartName="/xl/workbook.xml"/>
</Types>

[Content_Types].xml は、Excel(.xlsx)ファイルの中で「各ファイルの種類(ContentType)を定義する」ための構成ファイルです。

これは Open XML パッケージの仕様に従っており、ZIPの中にある各ファイルの MIMEタイプの一覧表 のような役割を果たします。

<Default ContentType="application/xml" Extension="xml"/>
<Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>

.xml → application/xml として扱います。

.rels → リレーションシップファイル(_rels/.relsなど)は特別なMIMEタイプとして扱います。

<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
          PartName="/xl/worksheets/sheet1.xml"/>

PartNameが/xl/worksheets/sheet1.xmlは、ワークシートでContentTypeはapplication/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml(ワークシート用のXML)として扱います。

.xlsx 内の各ファイルは ZIP の中の単なる XML ファイルであり、見た目で意味が分からないです。

そのため どのファイルがどの種類なのかを明示する必要があります。

Excel やライブラリが .xml や .rels などを見て「これはワークシートだ」「これは文字列のデータだ」と認識できるようにしています。

●_rels/.rels

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
 <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
</Relationships>

_rels/.rels ファイルの役割は、Open XML パッケージのエントリーポイント(開始点)を定義することです。

Excelを開くとき、まず _rels/.rels を見て、xl/workbook.xml が メインのワークブック だと分かります。

そこからシート情報(xl/worksheets/sheet1.xmlなど)にリンクが張られていく形になります。

●xl/workbook.xml

<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
    <workbookPr/>
    <sheets>
        <sheet state="visible" name="シート1" sheetId="1" r:id="rId4"/>
        <sheet state="visible" name="シート2" sheetId="2" r:id="rId5"/>
    </sheets>
    <definedNames/>
    <calcPr/>
</workbook>

xl/workbook.xml は .xlsx ファイル内のメインのワークブック構成ファイルです。

Excelファイル全体の「シートの定義」や「名前の定義」、全体の構成情報がここにまとまっています。

<sheet state="visible" name="シート1" sheetId="1" r:id="rId4"/>
<sheet state="visible" name="シート2" sheetId="2" r:id="rId5"/>
属性 意味
state="visible" シートが表示状態(非表示なら hidden)
name="シート1" ユーザーが見るシート名
sheetId="1" シートの一意な ID
r:id="rId4" xl/_rels/workbook.xml.relsファイルで定義された XMLファイルとの関連付け ID(例:rId4 → xl/worksheets/sheet1.xml

●xl/_rels/workbook.xml.rels

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
    <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
    <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Target="sharedStrings.xml"/>
    <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
    <Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet2.xml"/>
</Relationships>

xl/_rels/workbook.xml.rels は、Excel(.xlsx)ファイルの内部で workbook.xmlと他のリソース(シート、スタイル、テーマなど)との「つながり(関係)」を記述するファイルです。

workbook.xml.relsを参照することで、xl/workbook.xmlのr:id="rId4"は"worksheets/sheet1.xml"だとわかる。

さらに、worksheets/sheet1.xmlを作成するために必要なその他のパーツのファイルへのパスもきさいされています

●xl/sharedStrings.xml

すべてのシート中で共有利用される文字列リストを一括管理します。

例えばExcelで「あ、い、う、え」を書きましたが、それはsharedStrings.xmlで定義されます。

同じ文字は1回しか定義されないようになっています。

数値は、sharedStrings.xmlでは管理されません。

●xl/theme/theme1.xml

全体で共通して使うデザインルール(テーマカラー・テーマフォント)を定義するファイルです。

例えば、Excelで使うフォントを全体で共通なので、<a:fontScheme name="Sheets">で定義します。

●xl/styles.xml

<fonts count="2">
    <font>
        <sz val="10.0"/> // フォントサイズ 10pt
        <color rgb="FF000000"/> // 黒 (ARGB: FF=不透明, 000000=黒)
        <name val="Arial"/> // フォント名 Arial
        <scheme val="minor"/>
    </font>
    <font>
        <color theme="1"/>
        <name val="Arial"/>
        <scheme val="minor"/>
    </font>
</fonts>

fontsがフォントの種類や、文字色などを定義しています。

<fills count="3"> // 塗りつぶしスタイルが 3種類 定義されています。
    <fill>
        <patternFill patternType="none"/> // 塗りつぶしなし
    </fill>
    <fill>
        <patternFill patternType="lightGray"/> // グレーパターン塗りつぶし。Excel が持つ標準的なグレー模様
    </fill>
    <fill>
        <patternFill patternType="solid"> // patternType="solid"が、単色で塗りつぶす
            <fgColor rgb="FFFF0000"/> // fgColor(前景色)を赤で塗りつぶし
            <bgColor rgb="FFFF0000"/> // bgColor(背景色)を赤で塗りつぶし
        </patternFill>
    </fill>
</fills>

fillsが、塗りつぶしスタイルの定義になります。

<borders count="1"> // ボーダースタイルは 1種類のみ 定義されている。
    <border/> // 枠線なし(デフォルトの空のボーダー) を意味します。
</borders>

要素は、Excelセルの枠線(ボーダー)スタイルを定義するためのセクションです。

<cellStyleXfs count="1">
    <xf borderId="0" fillId="0" fontId="0" numFmtId="0" applyAlignment="1" applyFont="1"/>
</cellStyleXfs>
属性名 説明
borderId="0" borders の0番目(つまり「線なし」のボーダー)を使う
fillId="0" fills の0番目(パターンなしの背景)を使う
fontId="0" fonts の0番目(Arial/10pt)を使う
numFmtId="0" 標準の表示形式(General)
applyAlignment="1" 位置合わせ(alignment)の適用を明示
applyFont="1" フォントの設定を適用する

要素は、セルのスタイルの基本スタイルとなるものです。

<cellXfs count="5">
    <xf borderId="0" fillId="0" fontId="0" numFmtId="0" xfId="0" applyAlignment="1" applyFont="1">
        <alignment readingOrder="0" shrinkToFit="0" vertical="bottom" wrapText="0"/>
    </xf>
    <xf borderId="0" fillId="2" fontId="1" numFmtId="0" xfId="0" applyAlignment="1" applyFill="1" applyFont="1">
        <alignment readingOrder="0"/>
    </xf>
    <xf borderId="0" fillId="0" fontId="1" numFmtId="0" xfId="0" applyAlignment="1" applyFont="1">
        <alignment readingOrder="0"/>
    </xf>
    <xf borderId="0" fillId="0" fontId="1" numFmtId="3" xfId="0" applyAlignment="1" applyFont="1" applyNumberFormat="1">
        <alignment readingOrder="0"/>
    </xf>
    <xf borderId="0" fillId="0" fontId="1" numFmtId="1" xfId="0" applyAlignment="1" applyFont="1" applyNumberFormat="1">
        <alignment readingOrder="0"/>
    </xf>
</cellXfs>
属性名 意味
borderId="0" borders 配列のインデックス。枠線のスタイルを指定します。0はデフォルト(なし)を指すことが多い。
fillId="0" fills 配列のインデックス。背景塗りつぶしのスタイルを指定します。0は「塗りつぶしなし」。
fontId="0" fonts 配列のインデックス。使用するフォントの定義を指定します。
numFmtId="0" 数値フォーマットの ID。例:0 は「標準」:自動で整数や小数などを調整(見た目依存)、3:桁区切りあり(例:1234 → 1,234)
xfId="0" cellStyleXfs のどのテンプレート(xf)を継承するかを指定。スタイルのベースとして使います。
applyFont="1" fontId で指定されたフォントを実際に使用する(1: 使用する / 0: 無視)
applyFill="1" fillId の塗りつぶしを使用する
applyAlignment="1" タグで指定した整列情報を使用する
applyNumberFormat="1" numFmtId の数値書式を使用する
readingOrder テキストの読み方向:0 は左→右、1 は右→左

<xf> は eXtended Format(拡張書式)を意味し、セルに適用される見た目のルールを定義します。

●xl/worksheet/sheet1.xml

各ワークシート(シート)ごとのデータ本体を定義しています。

<pane ySplit="1.0" topLeftCell="A2" activePane="bottomLeft" state="frozen"/>
  • pane: ウィンドウ枠の分割設定
    • ySplit="1.0":1行目で 水平に分割(=1行目が固定)
    • state="frozen":固定表示
    • topLeftCell="A2":分割後、左上に来るセルは A2

sheet1.xmlのsheetDataの各セルが、sharedStrings.xmlやstyles.xmlの情報を参照しているという形になっています。

■まとめ

普段何気なく触っているCSVファイルやExcelファイルがどんな構造なのか?ファイルのメリット・デメリットを知ることができ、勉強になりました。

特にExcelファイルは構造は複雑で、Excelライブラリのメンテナンスをしたい場合は、Excelの構造をぼんやりとでも知っている必要があるため、良い機会になりました。

現在弊社ではエンジニアを募集しています!

この記事を読んで少しでも興味を持ってくださった方は、ぜひカジュアル面談でお話ししましょう!

iimon採用サイト / Wantedly / Green

■参考記事

ECMA-376 - Ecma International

CSVファイルとExcel(エクセル)ファイルの違いとは?使い分けの方法や注意点・対策法も紹介

ECMA376のリファレンスを使ってxlsxファイルの中身を見る。 - 好きなことを書いていく

Office Open XML ファイルフォーマット