作業報告書ツールをJavaScriptで作ってみた

 相変わらずへっぽこですが、8hくらい使って作業報告書の作業時間を計算するツールを作ってみました。基本的なルールは以下の通り。

  1. 9:00〜18:00が定時。
    1. それ以外は残業。
    2. 18:30〜19:00は休憩時間。22:00〜22:30も休憩時間*1
    3. 早出はしないっていう事にする。
    4. 0.5h単位で入力。
  2. 土日は全日残業扱い。
  3. 入力ミスはしないものとする。
  4. 総作業時間と、そのうちの残業時間が出ればOK。

 以下プログラム。

<html>
<head>
	<script language="JavaScript" type="text/javascript">
	function $(id){ return document.getElementById(id); }
	function F(elm){ elm.select(); }
	function BuildInputArea(){
		var days	= new Date($('year').value, $('month').value, 0);
		var strHTML	= "";
		
		$('divInputArea').innerHTML = '';
		
		strHTML += "<table>\n";
		for(var i=1;i<=days.getDate();i++){
			var dw = (new Date($('year').value, $('month').value - 1, i)).getDay();
			var strStyle;
			var strDefSt, strDefEd;
			
			switch(dw){
				case  0: strStyle = "color:#F00"; strDefSt="";     strDefEd="";      break;
				case  6: strStyle = "color:#00F"; strDefSt="";     strDefEd="";      break;
				default: strStyle = "color:#000"; strDefSt="9:00"; strDefEd="18:00"; break;
			}

			strHTML += "<tr>\n";
			strHTML += '<td align="center" style="' + strStyle + '">' + i + '</td>';
			strHTML += '<td style="' + strStyle + '">';
			strHTML += '日月火水木金土'.substr(dw,1);
			strHTML += '</td>';
			strHTML += '<td>';
			strHTML += '<input type="text" id="st' + i + '" size="5" value="' + strDefSt + '" onFocus="F(this)">';
			strHTML += '〜';
			strHTML += '<input type="text" id="ed' + i + '" size="5" value="' + strDefEd + '" onFocus="F(this)">';
			strHTML += '</td>';
			
			strHTML += "</tr>\n";
		}
		strHTML += "</table>\n";
		strHTML += '<input type="button" value="CSV作成!" onClick="BuildWorkResult()" ><br>' + "\n";
		strHTML += '<textarea id="csv_out" cols="40" rows="4" onFocus="F(this)">';
		
		$('divInputArea').innerHTML += strHTML;
	}

	function ConvHour(id) {
		var strTime = $(id).value.match(/\d+/g);
		return strTime==null ? 0:parseInt(strTime[0]) + (strTime[1] < 30 ? 0:0.5);
	}

	function BuildWorkResult(){
		var strTime		= "";
		var strOutput	= "";
		var days		= new Date($('year').value, $('month').value, 0);
		
		for(var i=1;i<=days.getDate();i++){
			var iWorkTime = ConvHour('ed' + i) - ConvHour('st' + i);
			var iOverTime = 0;

			if(iWorkTime >  8)    iWorkTime -= 1;
			if(iWorkTime >  8)    iWorkTime -= 0.5;
			if(iWorkTime >= 12.5) iWorkTime -= 0.5;
			if(iWorkTime >= 15)   iWorkTime -= 0.5;

			switch((new Date($('year').value, $('month').value - 1, i)).getDay()){
				case  0, 6: iOverTime = iWorkTime;     break;
				default   : iOverTime = iWorkTime - 8; break;
			}
			if(iWorkTime < 0) iWorkTime = 0;
			if(iOverTime < 0) iOverTime = 0;

			strOutput += i + "\t" +  $('st' + i).value +  "\t" + $('ed' + i).value +  "\t" + iWorkTime + "\t" + iOverTime + "\n";
		}
		$('csv_out').value  = strOutput;
	}
	</script>
</head>
<body>
	<h1>作業報告書</h1>
	<form>
		<input id="year" type="text" size="5" value="">年<input id="month" type="text" size="2" value="">月度<br>
		<input id="cmdStart" type="button" value="入力開始" onClick="BuildInputArea()"><br>
		<br>
		<div id="divInputArea">
		</div>
	</form>
</body>
</html>

今回学習したポイント

 innerHTMLを更新すると負荷が高くなる。
 →変数に文字列を放り込んで、最終的な結果をinnerHTMLに貼り付ける。

追記

 ちょっと出力するデータを改造しました。
 タブ区切りの方がエクセルと相性がいいもんで。

*1:確か1:00ぐらいからまた休憩時間があったような気がするんだけど、そこまで覚えてないし、そんな時間まで働かないようにしないと。