共有文字列テーブルを操作する
このトピックでは、Open XML SDK SharedStringTable クラスと、Open XML ファイル形式 SpreadsheetML スキーマとの関係について説明します。 SpreadsheetML ドキュメントを構成するパーツと要素の全体的な構造の詳細については、「 SpreadsheetML ドキュメントの構造」を参照してください。
SpreadsheetML での SharedStringTable
ISO/IEC 29500 仕様の次の情報では、SharedStringTable
(<sst/>
) 要素について説明します。
このパーツ タイプのインスタンスには、ブックの全ワークシートに出現する一意の各文字列が 1 つずつ格納されます。
パッケージにはただ 1 つの共有文字列テーブル パーツが含まれる必要があります
このコンテンツ タイプのパーツのルート要素は、sst である必要があります。
1 つのブックに、文字列 (非数値) データが格納されたセルが多数含まれる場合があります。 さらに、普通は、多数の行または列にこのデータが繰り返し出現します。 ブック全体で共有される単一の文字列テーブルを実装するのは、反復する情報の読み取りおよび書き込みを 1 回だけ行うことにより、ファイルを開くときと保存するときのパフォーマンスを向上させることが目的です。
© ISO/IEC 29500: 2016
共有文字列を使用すると、スプレッドシートに同じ文字列の複数のインスタンスが含まれるときに必要な領域が最適化されます。 ビジネス データまたは分析データが格納されているスプレッドシートには、反復する文字列が含まれることがよくあります。 このような文字列をインライン文字列マークアップを使用して格納したとすると、ワークシート内に同じマークアップが何回も出現することになります。 このような方法を使用しても間違いではありませんが、いくつかの欠点があります。 第 1 に、コンテンツが冗長なため、ディスクで必要な領域が増加します。 また、読み込みと保存に要する時間も長くなります。
スプレッドシートでの文字列の使用を最適化するため、SpreadsheetML では、共有文字列テーブルと呼ばれるテーブルに文字列の単一のインスタンスを格納します。 セルでは、セルの値にインラインで値を格納するのではなく、インデックスで文字列を参照します。 Excel では、ファイルを保存するときに、常に、共有文字列テーブルが作成されます。 ただし、共有文字列テーブルを使用しなくても、有効な SpreadsheetML ファイルを作成できます。 スプレッドシート ドキュメントをプログラムで作成し、スプレッドシートに含まれる文字列が少ない場合、または反復文字列が含まれない場合は、通常、共有文字列テーブルによって得られる最適化はごくわずかです。
共有文字列テーブルは、パッケージ内の独立したパーツです。 各ブックには共有文字列テーブル パーツが 1 つだけ含まれ、テーブルには 1 つまたは複数のシートに複数回出現する可能性のある文字列が格納されます。
次の表は、SharedStringTable クラスを操作するときに使用される一般的な Open XML SDK クラスの一覧です。
SpreadsheetML の要素 | Open XML SDK クラス |
---|---|
<si/> |
SharedStringItem |
<t/> |
Text |
Open XML SDK SharedStringTable クラス
Open XML SDK SharedStringTable
クラスは、SpreadsheetML ドキュメントの Open XML ファイル形式スキーマで定義されている段落 (<sst/>
) 要素を表します。
SharedStringTable
クラスを使用して、SpreadsheetML ドキュメント内の個々の<sst/>
要素を操作します。
Shared String Item クラス
SharedStringItem
クラスは、共有文字列テーブル内の個々の文字列を表す共有文字列項目 (<si/>
) 要素を表します。
セル レベルで書式設定を適用された単純な文字列の場合、共有文字列項目にはその文字列を表すために使用される単一のテキスト要素が格納されます。 一方、文字レベルで書式設定を適用されている文字列のように、セル内の文字列がさらに複雑な場合は、文字列項目は、集団で文字列を表すために使用される複数のリッチ テキスト セクションで構成されます。
たとえば、次の XML コードは、セル レベルと文字レベルで書式を設定されたテキストが含まれるワークシートの共有文字列テーブルです。 最初の 3 つの文字列 ("Cell A1"、"Cell B1"、"My Cell") はセル レベルで書式設定されたセルのものであり、共有文字列テーブルにはテキストだけが格納されます。 次の 2 つの文字列 ("Cell A2" と "Cell B2") には、文字レベルの書式設定が含まれます。 "セル" という単語は "A2" と "B2" とは異なる形式で書式設定されるため、セルの書式設定は、 RichTextRun
(<r/>
) 要素と RunProperties
(<rPr/>
) 要素を使用して、共有文字列項目内のテキストと共に格納されます。 書式設定が異なるテキスト間の空白を保持するために、text
(<t/>
) 要素のspace
属性は preserve
と等しく設定されます。 リッチ テキスト セクションおよびセクション プロパティの要素の詳細については、ISO/IEC 29500 の仕様を参照してください。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="6" uniqueCount="5">
<si>
<t>Cell A1</t>
</si>
<si>
<t>Cell B1</t>
</si>
<si>
<t>My Cell</t>
</si>
<si>
<r>
<rPr>
<sz val="11"/>
<color rgb="FFFF0000"/>
<rFont val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</rPr>
<t>Cell</t>
</r>
<r>
<rPr>
<sz val="11"/>
<color theme="1"/>
<rFont val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</rPr>
<t xml:space="preserve"> </t>
</r>
<r>
<rPr>
<b/>
<sz val="11"/>
<color theme="1"/>
<rFont val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</rPr>
<t>A2</t>
</r>
</si>
<si>
<r>
<rPr>
<sz val="11"/>
<color rgb="FF00B0F0"/>
<rFont val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</rPr>
<t>Cell</t>
</r>
<r>
<rPr>
<sz val="11"/>
<color theme="1"/>
<rFont val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</rPr>
<t xml:space="preserve"> </t>
</r>
<r>
<rPr>
<i/>
<sz val="11"/>
<color theme="1"/>
<rFont val="Calibri"/>
<family val="2"/>
<scheme val="minor"/>
</rPr>
<t>B2</t>
</r>
</si>
</sst>
Text クラス
Text
クラスは、文字列の一部として表示されるテキスト コンテンツを表すテキスト (<t/>
) 要素を表します。
Open XML SDK コード例
次のコードは、 String
と SharedStringTablePart
を受け取り、指定されたテキストが共有文字列テーブルに存在するかどうかを確認します。 存在しないテキストは、共有文字列項目として共有文字列テーブルに追加されます。
SharedStringTable
クラスを使用してセルにテキストをプログラムで挿入する方法の詳細については、「方法: スプレッドシート ドキュメントのセルにテキストを挿入する」を参照してください。
static int InsertSharedStringItem(string text, SharedStringTablePart shareStringPart)
{
// If the part does not contain a SharedStringTable, create one.
if (shareStringPart.SharedStringTable is null)
{
shareStringPart.SharedStringTable = new SharedStringTable();
}
int i = 0;
// Iterate through all the items in the SharedStringTable. If the text already exists, return its index.
foreach (SharedStringItem item in shareStringPart.SharedStringTable.Elements<SharedStringItem>())
{
if (item.InnerText == text)
{
return i;
}
i++;
}
// The text does not exist in the part. Create the SharedStringItem and return its index.
shareStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
return i;
}