*

セル内の「取り消し線で消された文字列」を削除してみた

公開日: : 最終更新日:2020/11/22 C#, 開発

どもです。

今回は、C#/OpenXmlの組み合わせで、エクセルのセル内の文字列から
「取り消し線で消されていない文字列のみを取得する方法」
について書きます。

1.何があったか

最近、所々でエクセルで作成したドキュメントの変更履歴/修正履歴を、ドキュメント内に残している場面に出くわしました。
現物は(もちろんですが)公開できませんが、イメージはこんなカンジ。
cs_openxml_remove_strikethrough_001
※本当はもう少し書かれている内容は多いのですが、今回のエントリに不要な情報は削除しています。
このような取り消し線は、セル内に1つとか2つ、ドキュメント全体を通しても3箇所とか4箇所に登場しないのであれば、そんなに問題ありません。
しかし、当該のエクセルでは、このような記載が複数個所、それこそ「セル内の文字列の半分が取り消し線で消されている」とか、「取り消し線で10文字消した後、1文字消されていない文字があって、その後再度20文字(くらい)取り消し線で消されている」なんて箇所もあったりしました。
そのようなエクセル、読み難くてしょうがない。
(現に、この1文字を読み損ねてエライ目に遭いました。)
そこで、セル内の「取り消し線で消された文字列」を取り除いた文字列を取得できるようにしてみた、というわけです。

2.開発環境

今回の調査で使用した環境を、以下に示します。

項目 内容
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

3.データ解析

3.1.エクセルの中の見える化

拡張子が「.xlsx」のエクセルファイルは、その実体はXMLファイルをzip形式で圧縮したファイルです。
そのため、Windowsのエクスプローラ上で拡張子をzipに書き換えて解凍することで、その中身を確認することができます。
例えば、先に見せたエクセルを展開した場合、展開したフォルダ内の「sharedStrings.xml」の中に、各セルの情報を見つけることができます。
cs_openxml_remove_strikethrough_002

3.2.エクセルの中を見てみるか

上記のsharedStrings.xmlをテキストエディタで開いてみると、中身は下記のようになっています。
(全部表示すると、長くなるので、必要な箇所のみの抜粋です。)

これは、最初の図でB2セルの情報になります。
この情報から分かるように、取り消し線が設定された文字列では、rPr要素の子要素にstrikeという要素が存在します。
この要素の有無を判断することで、セル内の文字列に取り消し線が設定されているか否かが判断できそうです。

4.実装

ここまでで、rPr要素がstrike要素を持つか否かで取り消し線があるか否かを判断できそうだと分かりました。
これを元に実装を行います。

4.1.シートのセル全体の読み出し

エクセルファイルをオープンして、ファイル/シートのセル情報を取得するまでの処理は、下記になります。

このコードでは、「image」という名前のシートのセル情報を全て取得しています。
取得したセル情報は、変数「cells」に格納されています。

4.2.セル内の情報の取得

各セルに設定された情報は、そのSharedStringItemオブジェクトとして取得します。
SharedStringItemオブジェクトは、下記のようにして取得します。

上記コードの「cells」は、imageシートのセル情報を格納したcellsと同じです。
SharedStringItemの変数itemに、1つのセルの文字列情報が格納されています。
なお、このitemが前述のエクセルの内容を見える化したXMLのsi要素に対応します。

4.3.セル内のstrike情報の取得

取り消し線の有無はstrike要素の有無によって、判断が可能です。
そのために、変数itemのChildElements(si要素の子要素)、およびその孫要素を解析して、strike要素の有無を調べます。
コードは、下記のようになります。

上記のコードの大まかな処理内容を書くと、以下のようになります。

  1. r要素の子要素から、rPr要素を取得
  2. rPr要素の子要素から、strike要素を取得
    • strike要素が無い場合は、取り消し線で消された文字列ではない

      →そのまま取得
    • strike要素がある場合は、取り消し線で消された文字列

      →スキップ

これにより、セル内の文字列から、取り消し線で消されていない文字列のみを抜き出すことができます。
エクセルのXMLの各要素とC#のクラスの対応を、示しておきます。

要素 クラス
r Run
rPr RunProperties
strike Strike

5.実行

ここまで書いてきたコードを実行すると、以下のようになります。
入力:
cs_openxml_remove_strikethrough_003
出力:
cs_openxml_remove_strikethrough_004
一番左がセルの名前、真ん中がセル内の取り消し線で消されていない文字列、カッコ内がセル内の生文字列です。
(カッコ内の文字列については、漢字の読み仮名が表示されていますが、テーマとは関係ないので無視しています。)
出力を確認すると、セル内の文字列から「取り消し線で消された文字列」を削除した文字列が取得できていることが確認できます。

6.まとめ

今回は、OpenXmlを使用して、エクセルのセル内の文字列から、「取り消し線で消された文字列」を取り除いた文字列を取得する処理について書きました。
これまでは、手動で取り消し線で消された文字列は1つ1つ手動で消していましたが、これにより一気に目的の文字列を取得できるようになりました。
この処理を用いることで、少しでも作業の効率が上がればいいな、と思います。

なお、本エントリで紹介したコードは、処理の内容を示すことを優先してエラー処理を削除しています。
全コードは、GitHubで公開しているコード(完全版)を参照してください。
ではっ!

ex.ぼやき

なんで、変更履歴/修正履歴をドキュメント内に残したりしてるんだろう…?
そんなの、バージョン管理/構成管理のツール使えばいいのに。
フリーで使用可能なツール、山ほどあるし。
うーむ。
ワカラン。
(変更履歴/修正履歴をドキュメント内に残すメリット、どなたか教えていただけないでしょうか。)

ex2.続き

セル内の「取り消し線で消された文字列」の削除を簡単にしてみた

関連記事

Splash

EV3開発サポートツール(3)-Ev3Controller

どもです。 今回は、以前ちらりと紹介した、Ev3のモーターの出力を調整するアプリケーションについて

記事を読む

raspberry-pi

QtでRaspberryPi/GUI開発(9)-SPI通信をしてみた

どもです。 えー。 「Qtで…」とか書いておきながら、今回はQtは出てきません。 今回のエ

記事を読む

iot_at_home_eye_catch

IoT開発(3)-ESP-WROOM-02でデータを送信

どもです。 この記事は、IoT開発(1)-ESP-WROOM-02のセットアップ、IoT開発(

記事を読む

no image

C言語でEV3開発(7)

どもです。 今回のエントリーでは、いよいよEV3を動かしていきます。 新しい環境に対して、最もよ

記事を読む

no image

Windows-QtCreatorでのデバッグ

どもです。 更新の間隔が空いてしまいました。 久しぶりの更新です。 最近、Qtを触り始めま

記事を読む

Arduino_Logo

ホールセンサーの種類と使い方(割込み編)

どもです。 前回に引き続き、今回もホールセンサーについてです。 1.前回からの違い 前回の

記事を読む

iot_raspberrypi_gateway_001_eye_catch

IoT開発(7)
RaspberryPiをIoTゲートウェイにする(II)
VM上の開発環境にWEBサーバーをインストール

どもです。 このエントリは、前回の続きです。 今回は、前回のエントリで作成したVM上のRaspb

記事を読む

think_about_utest

単体テストの効率化を考える(1)-はじめに

どもです。 突然ですが、今回から数回にわたって「単体テストの効率化」についてのエントリになりま

記事を読む

GitHub

Windowsでのカバレッジ測定-OpenCppCoverageを使ってみた(2)

どもです。 前回のエントリーで、OpenCppCoverageというカバレッジを測定する、フリーの

記事を読む

toppers

C言語でEV3開発(25)-Q_Learningを実装してみた…が!?

どもです。 今回の内容は、「失敗しました」という内容です。 最近、流行になっている深層学習/

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

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

どもです。 前回、前々回と、エクセルのセル内の文字列から、「取り

c_sharp_eye_catch
セル内の「取り消し線で消された文字列」の削除を簡単にしてみた

どもです。 前回、C#/OpenXmlを用いて、エクセルのセル内

c_sharp_eye_catch
セル内の「取り消し線で消された文字列」を削除してみた

どもです。 今回は、C#/OpenXmlの組み合わせで、エクセル

c_sharp_eye_catch
C#でバッファの内容を表示する処理を実装してみた-
データ型に従って動的に書式を設定する

どもです。 最近、C#でバッファ/配列の値をコンソールに表示した

arduino_relay_switch_003_self_preservation_circuit_eye_catch
Arduinoでリレースイッチ(3)-自己保存回路

どもです。 前回の記事で、リレースイッチ「AE-G5V-DRV」

→もっと見る

PAGE TOP ↑