🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ClosedXML

ClosedXMLは、Excel形式ファイル(.xlsx, .xlsm)の操作や読み書きのための.NETライブラリです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

7793閲覧

ClosedXMLでセル内の指定した文字に色を付けた後で、指定の記号の前に改行を入れたい

morinokuma0621

総合スコア81

ClosedXML

ClosedXMLは、Excel形式ファイル(.xlsx, .xlsm)の操作や読み書きのための.NETライブラリです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2021/02/16 08:23

編集2021/02/17 02:45

以前別の方が『C# ClosedXMLでセル内の指定した文字に色を付けたい』という内容で投稿されていましたが、
参考になりませんでしたので、質問させてください。

質問内容はタイトルの通りなのですが、
ClosedXMLでセルの中の特定の文字だけ色を変えるとともに、
指定の記号(※など)の前に改行を入れたいと思っています。

そこで次のようにコードを書いてみました。
「※かきくけこ」の文字色だけを灰色にし、
※の前に改行を入れる、というコードです。

C#

1string n = "※あいうえお※かきくけこ※さしすせそ"; 2int x = n.IndexOf("※かきくけこ"); 3 4ws.Cell(1, 1).SetValue<string>(n); 5if (x >= 0) 6{ ws.Cell(1, 1).RichText.Substring(x, 5).SetFontColor(XLColor.Gray); } 7 8ws.Cell(1, 1).SetValue<string>(ws.Cell(1, 1).Value.ToString().Replace("※", Environment.NewLine + "※"));

このときは、改行は正しくできましたが、文字色は全く変わっていませんでした。

ちなみに、「先に改行を入れてから文字色を変える」というパターンでは、
次のような書き方で成功しています。

C#

1string n = "※あいうえお※かきくけこ※さしすせそ"; 2 3ws.Cell(1, 1).SetValue<string>(n.Replace("※", Environment.NewLine + "※")); 4n = ws.Cell(1, 1).Value.ToString(); 5int x = n.IndexOf("※かきくけこ"); 6 7if (x >= 0) 8{ ws.Cell(1, 1).RichText.Substring(x, 6).SetFontColor(XLColor.Gray); }

このときは、セル内の特定の文字列だけ色を変えることができていたため、
やはりReplaceによる改行を入れることで、
セル内の色情報が初期色の黒に戻ってしまうのではないかと考えました。

これでも一見成功していると言えば成功しているのですが、
ただ諸事情により、できれば改行は最後にしたいと考えています。

『セル内の特定の文字列の文字色を変えたあとでReplaceで改行しても、
文字色が黒に戻らないようにする』

には、どうすればよろしいでしょうか。
ご教示よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

回答もつかないし、公式にもそのような機能は無さそうなのでリッチテキストの情報を保持したまま文字の挿入を行える関数を作ってみました。
手作り感満載ですが多少でも参考になれば...

C#

1 private class WorkRichStringInfo { 2 public string Text { set; get; } 3 public IXLRichString RichString { set; get; } 4 } 5 6 /// <summary> 7 /// 対象セルのリッチテキストを保持したまま検索文字が見つかった個所に指定文字を追加 8 /// </summary> 9 /// <param name="cell">セル</param> 10 /// <param name="skipFirstTextReplace">先頭文字が検索文字の場合に処理をスキップするかどうか</param> 11 /// <param name="searchText">検索文字</param> 12 /// <param name="insertText">検索文字の前に挿入する文字</param> 13 public void InsertText(IXLCell cell, bool skipFirstTextReplace, string searchText, string insertText) { 14 15 var oldItems = new List<WorkRichStringInfo>(); 16 var jointText = new StringBuilder(); 17 18 // [処理1]1文字づつ分解 19 foreach (var obj in cell.RichText) { 20 21 for (var i = 0; i < obj.Text.Length; i++) { 22 oldItems.Add(new WorkRichStringInfo() { Text = obj.Text.Substring(i, 1), RichString = obj }); 23 } 24 25 jointText.Append(obj.Text); 26 } 27 28 // 文字が無い 29 if (jointText.Length == 0) { 30 return; 31 } 32 33 // 対象箇所検索 34 var matches = System.Text.RegularExpressions.Regex.Matches(jointText.ToString(), searchText); 35 36 // 最後に処理した位置 37 var lastIndex = 0; 38 39 // 一旦、リッチテキストをクリア 40 cell.RichText.ClearText(); 41 42 // 指定範囲の[処理1]でばらしたリッチテキストを再セット 43 int addText(int startIndex, int endIndex) { 44 45 // 元々、同じリッチテキストになってた範囲でグループ化 46 var groupItems = oldItems.GetRange(startIndex, endIndex - startIndex).GroupBy(x => x.RichString); 47 48 foreach (var obj in groupItems) { 49 50 var oldRichString = obj.First().RichString; 51 var text = string.Join("", obj.Select(x => x.Text)); 52 53 var richString = cell.RichText.AddText(text); 54 55 richString.Bold = oldRichString.Bold; 56 richString.FontColor = oldRichString.FontColor; 57 richString.FontFamilyNumbering = oldRichString.FontFamilyNumbering; 58 richString.FontName = oldRichString.FontName; 59 richString.FontSize = oldRichString.FontSize; 60 richString.Italic = oldRichString.Italic; 61 richString.Shadow = oldRichString.Shadow; 62 richString.Strikethrough = oldRichString.Strikethrough; 63 richString.Underline = oldRichString.Underline; 64 richString.VerticalAlignment = oldRichString.VerticalAlignment; 65 66 } 67 68 return endIndex - startIndex; 69 } 70 71 // 文字の挿入処理 72 foreach (System.Text.RegularExpressions.Match obj in matches) { 73 74 // 先頭の一致をスキップする場合 75 if (obj.Index == 0 && skipFirstTextReplace) { 76 continue; 77 } 78 79 // 一致箇所より前の文字を追加 80 lastIndex += addText(lastIndex, obj.Index); 81 82 cell.RichText.AddText(insertText); 83 84 } 85 86 // 最後の余った文字を追加 87 if (lastIndex <= jointText.Length) { 88 addText(lastIndex, jointText.Length); 89 } 90 }

あとは

C#

1string n = "※あいうえお※かきくけこ※さしすせそ"; 2int x = n.IndexOf("※かきくけこ"); 3 4ws.Cell(1, 1).SetValue<string>(n); 5ws.Cell(1, 1).RichText.Substring(x, 9).SetFontColor(XLColor.Red); // わざと9文字にして"※さし"まで赤色になるようにしてます。 6 7InsertText(ws.Cell(1, 1), true, "※", Environment.NewLine); 8 9ws.Cell(1, 1).Style.Alignment.WrapText = true;

のような感じで使用します。ざっくり作ったので間違ってる箇所があれば指摘してください。
※勝手に最初の"※"は無視する機能も追加してみました。
実行後イメージ

投稿2021/02/17 14:17

dekaaki

総合スコア292

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dekaaki

2021/02/17 14:52

最初は置き換え機能で作ってたのでskipFirstTextReplaceという変数名にしましたが現在の機能ではこの変数名ではおかしいですね...
morinokuma0621

2021/02/18 01:13

うわーここまでしていただけるとは思ってもいませんでした。ありがとうございます。ちょっと今別件で確認ができませんので、確認でき次第、再度ご返答させていただきます。ありがとうございます!
morinokuma0621

2021/03/19 06:26

ご返答が大変遅くなり申し訳ありません。ようやく時間が取れ、検証いたしましたところ、完全に望んでいたものができていました!ありがとうございます! 本来ならお金払って依頼するようなレベルのものを作って頂き、本当に申し訳ない限りです……。自分でもこれぐらいのことができるように精進してまいります。本当にありがとうございました!
guest

0

RichText.Substring(StartIndex, NoOfChar) を使用した場合、文字の入力と書式の変更は別処理に分ける必要があったと思います。
あくまでセルの書式変更のみを行うものだと思います。。。

SetValue 時にフォントのスタイルを変更するには、.Style -> .Font の指定が必要です。

C#

1sheet.Cell(1, 1).SetValue(n) 2 .Style.Font.SetFontColor(XLColor.Gray)

他者様のブログ記事で申し訳ございませんが、以下が参考になると思いますのでご確認ください。
http://nineworks2.blog.fc2.com/blog-entry-56.html

投稿2021/02/17 01:19

haihaikazuma

総合スコア181

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

morinokuma0621

2021/02/17 02:40

申し訳ありません、せっかくご回答いただきましたが、上述していますとおり、 ws.Cell(1, 1).RichText.Substring(x, 6).SetFontColor(XLColor.Gray); という書き方で、Substringを使って セル内の特定の文字列だけ色を変えることができることはわかっているのです。 しかし、その色変えをしたあとでReplaceを使った改行をすると、 直前に変えた色が全て黒に戻ってしまうため、質問させていただきました。 色を変えたあとでどうしても改行を後からしたいのです……。 質問文の書き方がちょっと悪かったですね、書き直しておきます。 引き続き、ご回答いただければ幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問