#目的意識を持てない作業はやりたくない
過去の記事でも述べてますが私は現在新卒2年目の駆け出しエンジニアです。
弊社では1,2年目はOJT期間として設けられ(手厚い)教育を施されます。
OJT期間には社会人の鉄則「報連相」を身につけるため、会社単位で毎月報告書の提出が義務付けられています。この作業に関しては納得して快く提出していました。
また、担当プロジェクトの定例会議での進捗報告やマネージャーへの報告は欠かさず実施していました。
しかし部内の決まりとして若手はOJT期間に簡易的な週報を作成するというものがあります。
週報のフォーマットは以下です。
【週報】 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を実行しアプリを起動する。
④フォーム右下のExportボタンをクリックしてダイアログで保存先パスを指定する。
⑤ダイアログのOKボタンをクリックすると週報が作成される。
※入力内容をクリアしたい場合はフォーム右上のクリアボタンをクリックする。
#ソースコード
ほとんどコードを書いてません。
IDEが勝手にやってくれます。ありがとうございます。
Visual StudioでメインフォームにTabControlを置いてその上にそれぞれテキストボックスを置きました。日付入力はDateTimePickerを使用しました。
あとはExportボタンとクリアボタンにクリックイベントハンドラを紐づけて、その中にコードを書きました。
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.Month.ToString() + "/" + Today.Day.ToString();
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();
}
}
}
アイテムの名前などは指定しなかったのでこんなクソみたいなコードになりました。
本当にすみません。
#あとがき
会社が無駄な文化を残しておいてくれたお陰でC#の勉強をすることができました。
機会を与えて下さって感謝しています。
開発の原点は便利にしたい、楽したい、だと思うので結果的には"いい開発"になったかなと思います。
毎年入社してくる後輩にはこっそりこのツールを配布して楽してもらおうと思います。
ちなみにGitHubで全てコードは公開しています。同じような境遇の方がいらっしゃったら、コードをいじってフォーマットを整えて使ってみてください!
GitHub/WeekReportForm