セルに「取り消し線」が設定されているかを判定してみた

2021年2月25日

どもです。

前回前々回と、エクセルのセル内の文字列から、「取り消し線」が設定された文字列を削除する方法について書きました。
今回は、エクセルの「セルに設定された」「取り消し線」を判定する方法について書きます。

1.開発環境

今回の開発環境です。
前回、前々回から一切の変更はありません。

項目 内容
OS Windows10 Pro(1909)
CPU i7-8700
メモリ 16GB
IDE VisualStudioCommnuity 2019
version 16.5.1
.NET Framework 4.7
OpenXml 2.11.3
Excel Office 2013

2.セルに設定された取り消し線

「セルに設定された取り消し線」は、「セルの書式設定」画面の「フォント」タブから設定する取り消し線です。
cs_openxml_remove_strikethrough_003_001
この設定が、xlsxファイルの無いのどこに格納されているかから、確認します。

2.1.セルのフォント設定

セルのフォント設定を取得する前に、(今更ですが)xlsxファイルの中身を、簡単にですが確認します。
xlsxファイルの中身は、下図のようになっています。
(今回のエントリで必要な部分の一部抜粋)
cs_openxml_remove_strikethrough_003_002
セルのフォント設定は、上図の「styles.xml」ファイルに格納されています。

2.2.styles.xmlの中身

styles.xmlファイルのツリー構成は、下図のようになっています。
cs_openxml_remove_strikethrough_003_003
このうち、セルのフォント設定は「cellXfs」要素の子要素から辿ることができます。

2.3.cellXfsの中身

cellXfs要素は、以下のコードが記載されています。

<cellXfs count="6">
	<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>
	<xf numFmtId="0" fontId="1" fillId="0" borderId="0" xfId="0" applyFont="1"/>
	<xf numFmtId="0" fontId="1" fillId="0" borderId="2" xfId="0" applyFont="1" applyBorder="1"/>
	<xf numFmtId="0" fontId="1" fillId="0" borderId="3" xfId="0" applyFont="1" applyBorder="1"/>
	<xf numFmtId="0" fontId="4" fillId="2" borderId="1" xfId="0" applyFont="1" applyFill="1" applyBorder="1" applyAlignment="1">
		<alignment horizontal="center"/>
	</xf>
	<xf numFmtId="0" fontId="3" fillId="0" borderId="3" xfId="0" applyFont="1" applyBorder="1"/>
</cellXfs>

上のコードを見ると、cellXfs要素の中で明確にフォントは設定されていません。
その代り、fontIdという属性、およびそれに設定された値があります。
このfontIdは、fonts要素の子要素であるfont要素のインデックスが対応しています。
なお、fonts要素も同じstyles.xmlの中にあります。

2.4.font要素

font要素の中身を見てみます。

<fonts count="5" x14ac:knownFonts="1">
	<font>
		<sz val="11"/>
		<color theme="1"/>
		<name val="MS Pゴシック"/>
		<family val="2"/>
		<scheme val="minor"/>
	</font>
	<font>
		<sz val="9"/>
		<color theme="1"/>
		<name val="Meiryo UI"/>
		<family val="3"/>
		<charset val="128"/>
	</font>
	<font>
		<sz val="6"/>
		<name val="MS Pゴシック"/>
		<family val="3"/>
		<charset val="128"/>
		<scheme val="minor"/>
	</font>
	<font>
		<strike/>
		<sz val="9"/>
		<color theme="1"/>
		<name val="Meiryo UI"/>
		<family val="3"/>
		<charset val="128"/>
	</font>
	<font>
		<b/>
		<sz val="9"/>
		<color theme="1"/>
		<name val="Meiryo UI"/>
		<family val="3"/>
		<charset val="128"/>
	</font>
</fonts>

こんなカンジで、順番にフォントが設定されています。
この要素の中から、font要素を子要素に持つ要素を見つけます。
上のコードでは、4番目の要素がそれに当たります。
(fontIdは0ベースですので、fontId=3が該当します。)

2.5.処理順

上記のことから、セルに設定された取り消し線の有無は、下記のような手順で確認ができます。

  1. エクセルの情報から、全体のフォント情報(styles.xml)を取得する。
  2. 全体のフォント情報から、cellXfs要素を特定するインデックスを取得する。
  3. cellXfs要素に対応する情報から、セルのフォーマット情報を取得する。
  4. 取得したフォーマット情報から、フォント情報を取得する。
  5. フォント情報内の、取り消し線情報の有無を確認する。

3.実装

前述の処理を、C#/OpenXmlで実装します。

3.1.全体のフォント情報の取得

全体のフォント情報、即ちstyles.xmlファイルの内容は、次のコードで取得ができます。

var workbookPart = document.WorkbookPart;
var sheet = workbookPart.Workbook.Descendants<Sheet>().Where(sheetItem => sheetItem.Name == "sheetName").FirstOrDefault();
var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
var styleSheet = workbookPart.WorkbookStylesPart.Stylesheet;,

目的の情報は、変数styleSheetに格納されます。

3.2.セルのフォーマットの取得

特定のセルのフォーマットの情報は、次のコードで取得します。

var cellFormat = (CellFormat)styleSheet.CellFormats.ElementAt(int.Parse(sharedStringCell.StyleIndex));

ここで、sharedStringCellが対象のセル情報です。

3.3.セルのフォント情報の取得

セルのフォント情報は、以下のコードで取得します。

var cellFontId = cellFormat.FontId;
var cellFont = styleSheet.Fonts.ElementAt(int.Parse(cellFontId));

3.4.取り消し線の有無を確認

取得したフォント情報内の取り消し線情報の有無を確認します。
これは、strike要素の件数から確認します。
即ち、以下のコードになります。

var cellFontStrikeElement = cellFont.ChildElements.Where(cellFontItem => cellFontItem is Strike);
if (0 < cellFontStrikeElement.Count())
{
	//Code to handle the result.
}

4.まとめ

今回は、セルに「取り消し線」が設定されているか否かを判定する方法について、書きました。
これまで複数回にわたって、C#/OpenXmlでエクセルの取り消し線を扱う処理(削除する方法ばっかりですが…)を書いてきました。
それらのエントリで、取り消し線削除の処理方法は一通り紹介/説明できたかと思います。
「エクセルから取り消し線を削除したい」という方の、少しでも助けになれば幸いです。
ではっ!

ex.公開しています

今回紹介したコードは、過去に紹介したコードと併せてGitHubで公開しています。
全体を確認する場合には、リンク先のコードを参照してください。