仕事でExcelをつかって記事を納品することがあるのですが、長文をExcelで扱うのはどうなんでしょうか?
Excelは名前、住所、メールアドレス、このような文字数が短いものを大量に扱うのであれば便利だと思いますが、長文をいくつも詰め込むべきではないと思うのです。セルが小さいのであとで見ようとしたとき見づらいです。また複数のセルにかかれた文章を同時にみながら作業をする場合は非常に作業がやりにくいです。
各セルにかかれた文章をテキストエディタで直接編集することはできないのでしょうか? そこで自作することにしました。必要は発明の母です。不自由も発明の母です。
このようなアプリケーションを作成するのは、Excelが公開するCOMコンポーネントへの参照をプロジェクトに追加する必要があります。Visual Studio 2019であれば
これでOK。
まずはExcelのファイルを開く必要があります。フォームにドラッグアンドドロップすればよいようにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); AllowDrop = true; } protected override void OnDragOver(DragEventArgs drgevent) { if(drgevent.Data.GetDataPresent(DataFormats.FileDrop)) { drgevent.Effect = DragDropEffects.All; } } protected override void OnDragDrop(DragEventArgs drgevent) { if(drgevent.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string [])drgevent.Data.GetData(DataFormats.FileDrop); if(files.Length == 1) { OpenExcel(files[0]); } } } } |
これでファイルをドロップすればOpenExcelメソッド(後述)によってファイルが開かれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System; using System.Windows.Forms; using Excel = Microsoft.Office.Interop.Excel; public partial class Form1 : Form { // フィールド変数 Excel.Application AppXls; // Excelオブジェクト Excel.Workbook WorkBook; // workbookオブジェクト void OpenExcel(string fileName) { // Excelを起動する AppXls = new Excel.Application(); // Excelのウィンドウを表示させる AppXls.Visible = true; // Excelファイルをオープンする WorkBook = (Excel.Workbook)(AppXls.Workbooks.Open( fileName, // オープンするExcelファイル名 Type.Missing, // 以下の引数は省略可能なのでType.Missingを指する Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing )); } } |
あとはセルの位置を指定してから編集ボタンを押せばセルの編集ができるようになります。
例外処理をしています。例外が発生する場合として考えられるのは、テキストボックスに数字ではないものを入力した、Excelのファイルをドロップするまえにボタンをクリックした、Excelのファイルを閉じてしまったあとなのにボタンをクリックしたなどが考えられます。
現在編集中のワークシートを調べて編集するセルに書かれている文字列を取得します。必要なデータがそろったら新しいフォームを開きます。必要なデータとして、ワークシートオブジェクト、セルの場所、セルの文字列が考えられます。
ワークシートオブジェクトはこれで取得できます。
1 |
Excel._Worksheet worksheet = (Excel._Worksheet)WorkBook.ActiveSheet; |
そこにはリッチテキストボックスがあり、ここで編集を行ないます。
新しいフォームはShowDialog()メソッドではなくShow()メソッドで表示させるので、複数のフォームを見ながら編集作業ができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { try { int col = int.Parse(textBoxColum.Text); int row = int.Parse(textBoxRow.Text); Excel._Worksheet worksheet = (Excel._Worksheet)WorkBook.ActiveSheet; Excel.Range rng = (Excel.Range)worksheet.Cells[row, col]; string str = rng.Text.ToString(); Form2 f = new Form2(worksheet, row, col, str); f.Show(); } catch { MessageBox.Show("セルのオープンに失敗しました", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } |
それからセルを指定するのではなく、現在選択されているセルを編集できるようにもしてみます。
現在、選択されているセルを取得するためには
1 2 3 |
Excel.Range rng = AppXls.ActiveCell; // AppXlsはExcelを起動するさいの // Excel.Application AppXls = new Excel.Application(); で保存したフィールド変数 |
でいいし、
セルの場所やセル内の文字列は
1 2 3 |
int row = rng.Row; int column = rng.Column; string str = rng.Text.ToString(); |
で取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { private void button2_Click(object sender, EventArgs e) { Excel._Worksheet worksheet = (Excel._Worksheet)WorkBook.ActiveSheet; Excel.Range rng = AppXls.ActiveCell; string str = rng.Text.ToString(); Form2 f = new Form2(worksheet, rng.Row, rng.Column, str); f.Show(); } } |
Form2はこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
public partial class Form2 : Form { // 編集中のセルの情報 Excel._Worksheet Worksheet; int Row = 0; int Col = 0; public Form2() { InitializeComponent(); richTextBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; button1.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; } public Form2(Excel._Worksheet worksheet, int row, int col, string str) { InitializeComponent(); richTextBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; button1.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; Worksheet = worksheet; Row = row; Col = col; richTextBox1.Text = str; richTextBox1.Modified = false; // ステータスバーとタイトルバーに編集中のシート名とセルの場所を表示させる string str2 = String.Format(Worksheet.Name + " {0}{1} を編集中です", ColumToStrig(col), row); toolStripStatusLabel1.Text = str2; Text = str2; } string ColumToStrig(int i) { string str = ""; i--; if(i / 26 > 25) return i.ToString() + ", "; if(i / 26 != 0) str += IntToAlphabet(i / 26 -1); str += IntToAlphabet((i) % 26); return str; } string IntToAlphabet(int i) { if(i == -1) return ""; string[] s = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; return s[i]; } } |
[反映する]のボタンがクリックされたらリッチテキストボックスの文字列をExcelのファイルに書き込みます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form2 : Form { private void button1_Click(object sender, EventArgs e) { UpdateCell(); } void UpdateCell() { try { Worksheet.Cells[Row, Col] = richTextBox1.Text; richTextBox1.Modified = false; } catch { MessageBox.Show("更新に失敗しました", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } |
反映ボタンをクリックするのを忘れてフォームを閉じてしまうかもしれません。そこで反映させていないにもかかわらず閉じようとした場合は確認のメッセージを表示させることにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public partial class Form2 : Form { protected override void OnClosing(CancelEventArgs e) { if(!richTextBox1.Modified) return; string str1 = "反映をクリックしないとデータが反映されません。反映させますか?\n\n"; string str2 = "反映させて終了するときは「はい」\n"; string str3 = "反映させずに終了するときは「いいえ」\n"; string str4 = "終了しないときは「キャンセル」を\n\n"; string str5 = "選択してください"; string str = str1 + str2 + str3 + str4 + str5; DialogResult dr = MessageBox.Show(str, "確認", MessageBoxButtons.YesNoCancel); if(dr == DialogResult.Yes) { UpdateCell(); } if(dr == DialogResult.No) { } if(dr == DialogResult.Cancel) { e.Cancel = true; } } } |
これでExcel内の長文データの編集も簡単にできると思います。(自信がない)