私のところでも例に漏れず、事務員が作ったwordの表に作業者が入力してサーバーに登録しなさい、メールに添付して送りなさいというシステムが定着しつつあります。
現場の人達がこのwordの表を体裁を崩さず入力出来ると思っているのでしょうね。
出来ない人がいれば、wordの勉強をしてもらわないと困ると言い出す始末。いえ、あなたが体裁を崩さずに入力できるword文書を作る方法を勉強するべきでしょう!人には役割があるのですよ。
と、前置きと愚痴はさておきこの事務員の作ったword文書の体裁を崩さないようにC#で入力システムを作りましょうというお話です。
環境は、VisualStudio2015+Office2010です。
参照の追加
まず、「参照」-「参照の追加」-「COM」で
Microsoft Office 14.0 Object Libraryにチェックを付ると「参照」に[
[Microsoft.Office.Core]と[Microsoft.Office.Interop.Word]が追加されます。
データを処理するClassの作成
Class6を使用しています。
using Word = Microsoft.Office.Interop.Word;
using Microsoft.Office.Interop.Word;
を追加しておきます。
ファイルがデスクトップに出力されるようにします。
string FILE_DIR = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
ファイル名に使用する月をコンボボックスから選びます。
string FILE_TSUKI = Form1.Form1Instance.comboBox1.Text;
Itemsに1~12の数字を入れれば月選択コンボボックスが出来上がります。
氏名入力等があれば既存のデータベースを利用します。
出来るだけ入力者に手間を掛けさせないのが使いやすいシステムですね。(笑)
事務員が作ったファイル
string JIMUIN_FILE = "//server/wwwroot/aaaaa.docx";
保存するファイル名
string FILE_NAME = "自動出力(" + FILE_TSUKI + "月度)" + aaaa + ".docx";
エラー対策でwordのオープン状態を監視するフラッグを作ります。
docOpenFlag = false;
クラスの下に、
class Class6
{
Class5 cs5 = new Class5();
public bool docOpenFlag;
としてフォームからも状態を取得できるようにしておきます。
// Word アプリケーションオブジェクトを作成
word = new Word.Application();
// Word の GUI を起動しないようにする
//word.Visible = false;
word.Visible = true;
visibleはプログラム中はtrueで完成したらfalseにしておくとwordを表示することなく提出用の文書が作れます。
//事務員が作ったwordを開く
document = word.Application.Documents.Open(@JIMUIN_FILE);
docOpenFlag = true;
文書中に文字を追加します。
cs5.addText(ref document, WdParagraphAlignment.wdAlignParagraphCenter, 14, 5, FILE_TSUKI);
センター揃え、サイズ14で5行目の文字の先頭にFILE_TSUKIに登録された値を追加します。
文書中の文字を置き換えます。
cs5.changeText(ref document, WdParagraphAlignment.wdAlignParagraphRight, 10.5, 10, SAKUSEI);
右揃え、サイズ10.5で10行目の文字をSAKUSEIという変数に登録された値に置き換えます。上の例では作成日
表に文字を入れます。
cs5.hyoText(ref document, WdParagraphAlignment.wdAlignParagraphRight, 10.5, 1, 1, 2, BUSHO);
右揃え、サイズ10.5 で部署名を登録しています。
文書中の1番目の表の1行2列目にBUSHOという変数に登録された値を書き出します。
// 名前を付けて保存
object filename = FILE_DIR + "/" + FILE_NAME;
document.SaveAs2(ref filename);
// 文書を閉じる
document.Close();
document = null;
word.Quit();
word = null;
docOpenFlag = false;
以上をフォームのボタンのクリックイベントに登録しておきます。
上の例ではClass6に上記を記述してFormから呼び出しています。
wordに書き込むクラス
Class5に登録しています。
/// <summary>
/// 文書にテキストを追加する.
/// </summary>
public void addText(ref Document document, WdParagraphAlignment align, double size, int gyo, string text)
{
Range rng = document.Paragraphs[gyo].Range;
rng.Select();
rng.Text = text + rng.Text;
rng.ParagraphFormat.Alignment = align;
}
/// <summary>
/// 文書のテキストを置き換える.
/// </summary>
public void changeText(ref Document document, WdParagraphAlignment align, double size, int gyo, string text)
{
Range rng = document.Range(Start:document.Paragraphs[gyo].Range.Start, End:document.Paragraphs[gyo].Range.End - 1);
rng.Select();
rng.Text = text;
rng.ParagraphFormat.Alignment = align;
}
public void changeText(ref Document document, WdParagraphAlignment align, double size, int gyo, int startString, int endString, string text)
{
Range rng = document.Range(Start: document.Paragraphs[gyo].Range.Start + startString, End: document.Paragraphs[gyo].Range.Start + endString);
rng.Select();
rng.Text = text;
rng.ParagraphFormat.Alignment = align;
}
今回は使用していませんが、gyoで指定された行のstartStringで指定された文字からendStringで指定された文字までを置き換えます。
public void hyoText(ref Document document, WdParagraphAlignment align, double size, int tables, int gyo, int retu, string text)
{
Cell cell = document.Tables[tables].Cell(gyo, retu);
cell.Range.Text = text;
cell.Range.ParagraphFormat.Alignment = align;
}
テキストの置き換えと追加の違い
置き換えは、
rng.Text = text;
前に追加する場合は、
rng.Text = text + rng.Text;
後ろに追加する場合は、
rmg.Text += text;
Formからの呼び出し
private void button1_Click(object sender, EventArgs e)
{
try
{
/////wordの文書を開いてデータを書き込む/////
string msg = cs6.editWord();
//入力漏れや入力ミスがあった場合、editWordを中止してエラーを返すようにしています。
if(msg != "")
{
MessageBox.Show(
msg,
"入力エラー!!",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
}
MessageBox.Show(
"作成しました。",
"Success!!",
MessageBoxButtons.OK,
MessageBoxIcon.Information
);
}
catch(Exception ex)
{
MessageBox.Show(
"システムエラー\r\n" + ex,
"エラー!!",
MessageBoxButtons.OK,
MessageBoxIcon.Error
);
//wordが開いているときの処理
if (cs6.docOpenFlag)
{
cs6.document.Close();
cs6.document = null;
cs6.word.Quit();
cs6.word = null;
cs6.docOpenFlag = false;
}
}
}
サービスです
dateTimePickerの値を文字列変換してtextboxに登録する。
textBox2.Text = string.Format("{0:yyyy年M月d日(ddd)}", dateTimePicker2.Value);
dateTimePickerをそのまま使えば良いと思われた方、(汗)
dateTimePickerって一度選択すると消せなくないですか?
textboxで一度受けておくとtextboxなら消せます。
注意:途中で例外が発生した場合、オリジナル文書(事務員が作った)が書き換えられる場合があります。例外処理を確実に行い、例外が発生したらとにかくwordを終了するようにして下さい。
あるいは、オリジナルのバックアップを残しておく。
相変わらず見辛いプログラムで申し訳御座いません。
その内どこかからタグを盗んできます。(笑)
あ、ちなみに事務員と仲が悪いわけではないです。
以上、お試し下さい。
(。・ω・)ノ゙