【C#】週報作成ツールを完成させた話

#目的意識を持てない作業はやりたくない
過去の記事でも述べてますが私は現在新卒2年目の駆け出しエンジニアです。
弊社では1,2年目はOJT期間として設けられ（手厚い）教育を施されます。
OJT期間には社会人の鉄則「報連相」を身につけるため、会社単位で毎月報告書の提出が義務付けられています。この作業に関しては納得して快く提出していました。
また、担当プロジェクトの定例会議での進捗報告やマネージャーへの報告は欠かさず実施していました。
しかし部内の決まりとして若手はOJT期間に簡易的な週報を作成するというものがあります。
週報のフォーマットは以下です。

```20200110_週報.txt
【週報】 1/6～1/10
■今週の報告
1/6 ○○作業
→完了

1/7 ★★作業
⇒進捗率80%

1/8 ★★作業
⇒完了

1/9 休み

1/10 ××作業
⇒進捗率30%

■来週の取り組み
・××作業の続き
・△△作業
```
この週報は部のファイルサーバに毎週格納するという決まりでした。
書く内容はプロジェクトの業務進捗とその他OJT作業などの進捗を総括したものです。

このフォーマットではまず書く意味があるのかと疑問を抱きます。
また最初のうちはOJT指導者などが週報を閲覧している形跡がありましたが入社して1年が過ぎたころには誰も閲覧しなくなりました。

週報を書きたくないと理由をつけて説明しても「OJT期間はやろう」の一点張りで、要求を受け入れてくれませんでした。

これが会社か。。。
と思いながらもOJT期間中は渋々週報を書くことにしました。

#せめて楽したい
やりたくないことはせめて楽したい！
週報作成を自動化しようと思い立ち、何で作ろうかと考えました。
いくつか候補はありましたが（Excelに入力し、VBAを使ってtxtファイルを出力するなど）
ちょうどその時業務でC#を扱っていたので、Windows Formで作ろう！と思いました。

#アプリについて
##前提
・WindowsFormなのでもちろんWindows環境での動作になります。
 
##機能
・フォームの入力内容から上記フォーマットのテキストファイルを作成する。
・フォーム上で作成日の日付を指定するだけで作業日を含めた過去5営業日を週報に自動出力（土日は非営業日とする）。
・自動的にファイル名を作成日の日付で"YYYYMMdd_週報.txt"にする。

#使用方法
①WeekReportForm.exeを実行しアプリを起動する。
![main.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533788/e6c1ee03-ac7d-7bd0-21ca-6e483bfc7a2c.jpeg)


②1～5日目の実績と来週の予定を記入する。
![main2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533788/12242262-7f15-bda0-6404-dfbbdefe1fbf.jpeg)

③作成日を指定する。（直接入力orカレンダーから選択）
![date.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533788/fd795f5b-b6d9-8a52-b9bc-fad38927ec63.jpeg)

④フォーム右下のExportボタンをクリックしてダイアログで保存先パスを指定する。
![export.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533788/742d6f14-a9af-c486-879f-c3e44b08655f.jpeg)

⑤ダイアログのOKボタンをクリックすると週報が作成される。

※入力内容をクリアしたい場合はフォーム右上のクリアボタンをクリックする。


#ソースコード
ほとんどコードを書いてません。
IDEが勝手にやってくれます。ありがとうございます。
Visual StudioでメインフォームにTabControlを置いてその上にそれぞれテキストボックスを置きました。日付入力はDateTimePickerを使用しました。

あとはExportボタンとクリアボタンにクリックイベントハンドラを紐づけて、その中にコードを書きました。

```cs:Form1.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace WeekReportForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// Exportボタンクリック時動作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            // 各テキストボックスの値を取得
            string text1 = textBox1.Text;
            string text2 = textBox2.Text;
            string text3 = textBox3.Text;
            string text4 = textBox4.Text;
            string text5 = textBox5.Text;
            string next = textBox6.Text;

            string filepath = "";
            // 日付を取得
            DateTime Today = dateTimePicker1.Value;
            string day = Today.ToString("M/d");

            FolderBrowserDialog fbDialog = new FolderBrowserDialog();

            // ダイアログの説明文を指定する
            fbDialog.Description = "週報保存先フォルダを選択";

            // デフォルトのフォルダを指定する
            fbDialog.SelectedPath = @"C:";

            // 「新しいフォルダーの作成する」ボタンを表示する
            fbDialog.ShowNewFolderButton = true;

            //フォルダを選択するダイアログを表示する
            if (fbDialog.ShowDialog() == DialogResult.OK)
            {
                filepath = fbDialog.SelectedPath + @"\";
            }
            else
            {
                return;
            }
            // ファイル名決定
            string filename = filepath + 
                Today.Year.ToString() + 
                CheckNum(Today.Month.ToString()) +
                CheckNum(Today.Day.ToString()) +
                "_週報.txt";

            List<int> dayList = WeekCheck(Today.DayOfWeek);

            if (dayList[0] == -1)
            {
                MessageBox.Show("休日に週報は作成できません。");
                return;
            }

            DateTime first = Today.AddDays(-dayList[0]);
            string firstday = first.Month.ToString() + "/" + first.Day.ToString();

            DateTime second = Today.AddDays(-dayList[1]);
            string secondday = second.Month.ToString() + "/" + second.Day.ToString();

            DateTime third = Today.AddDays(-dayList[2]);
            string thirdday = third.Month.ToString() + "/" + third.Day.ToString();

            DateTime fourth = Today.AddDays(-dayList[3]);
            string fourthday = fourth.Month.ToString() + "/" + fourth.Day.ToString();


            // タイトル作成
            StringBuilder sb = new StringBuilder();
            sb.Append("【週報】 " + firstday + "～" + day + "\n");

            // 今週の報告
            sb.Append("■今週の報告\n");
            sb.Append(firstday + " " + text1 + "\n\n");
            sb.Append(secondday + " " + text2 + "\n\n");
            sb.Append(thirdday + " " + text3 + "\n\n");
            sb.Append(fourthday + " " + text4 + "\n\n");
            sb.Append(day + " " + text5 + "\n\n");
            sb.Append("■来週の取り組み\n");
            sb.Append(next);

            File.AppendAllText(filename,sb.ToString());
            MessageBox.Show("週報が作成されました。");

        }

        /// <summary>
        /// 5営業日判定
        /// </summary>
        /// <param name="dow">作成日の曜日</param>
        /// <returns>営業日リスト</returns>
        private List<int> WeekCheck(DayOfWeek dow)
        {
            List<int> retList = new List<int>();
            switch (dow)
            {
                case DayOfWeek.Monday:
                    retList.Add(6);
                    retList.Add(5);
                    retList.Add(4);
                    retList.Add(3);
                    break;
                case DayOfWeek.Tuesday:
                    retList.Add(6);
                    retList.Add(5);
                    retList.Add(4);
                    retList.Add(1);
                    break;
                case DayOfWeek.Wednesday:
                    retList.Add(6);
                    retList.Add(5);
                    retList.Add(2);
                    retList.Add(1);
                    break;
                case DayOfWeek.Thursday:
                    retList.Add(6);
                    retList.Add(3);
                    retList.Add(2);
                    retList.Add(1);
                    break;
                case DayOfWeek.Friday:
                    retList.Add(4);
                    retList.Add(3);
                    retList.Add(2);
                    retList.Add(1);
                    break;
                default:
                    retList.Add(-1);
                    break;
            }
            return retList;
        }

        /// <summary>
        /// ファイル名0追加メソッド
        /// 作成日の月または日が一桁の場合先頭に0を付け二桁にする。
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        private string CheckNum(string i)
        {
            string str = "";

            if (i.Length == 1)
            {
                str = "0" + i;
            }
            else
            {
                str = i;
            }
            return str;
        }

        /// <summary>
        /// クリアボタンクリック時動作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            // 全てのテキストボックスの値をクリアする
            textBox1.ResetText();
            textBox2.ResetText();
            textBox3.ResetText();
            textBox4.ResetText();
            textBox5.ResetText();
            textBox6.ResetText();
        }
    }
}
```

アイテムの名前などは指定しなかったのでこんなクソみたいなコードになりました。
本当にすみません。

#あとがき
開発の原点は便利にしたい、楽したい、だと思うので結果的には"いい開発"になったかなと思います。
毎年入社してくる後輩にはこっそりこのツールを配布して楽してもらおうと思います。

ちなみにGitHubで全てコードは公開しています。同じような境遇の方がいらっしゃったら、コードをいじってフォーマットを整えて使ってみてください！
[GitHub/WeekReportForm](https://github.com/yukibacho/WeekReportForm)