Webエンジニア 新人日記

Webエンジニアになりました。元々はCOBOLやらBASICやらでプログラムしてました。C言語やVisualBasicは趣味でやっていましたが、久々に現場復帰ということです。資格はエンベデッドスペシャリスト、DBスペシャリスト、ネットワークスペシャリスト、セキュリティスペシャリスト、システムアーキテクト、プロジェクトマネージャ他を所有

【Javascript】ダブルクリックによる二重送信の防止

ITリテラシーの無い方は、シングルクリックとダブルクリックの区別がつかないことも多い。
なんでもかんでもダブルクリック。ブラウザ上でもダブルクリックすることも多い。

formから送信する時にダブルクリックすると二重送信されてしまうので、クリックは一度のみ有効にする。


Javascript
disapbled属性をtrueにして押せないようにする(見た目もグレーアウトする)。
ボタンのメッセージを変更するともっとわかりやすいかも。

function DisableButton(btn){
//二重送信防止
    btn.disabled=true;
    btn.value='送信中...';
    btn.form.submit();
}

【html】
onclickでJavascriptを呼び出すようにする。
引数としてボタンそのものを渡す。

<input type="submit" value="送信" id="SubmitButton" onclick="DisableButton(this);">

【PHP】Excelからデータを読み取り連想配列にセットする

PHPExcelを読み取るにはPHPExcelを使う。
ライブラリをあらかじめダウンロードしておいて展開しておく。

//PHPExcelファイルの読み込み
include_once ( dirname(__FILE__) . '/Classes/PHPExcel.php');
include_once ( dirname(__FILE__) . '/Classes/PHPExcel/IOFactory.php');

エラーチェックは入念に。といいつつ、社内向けなので手抜きしてます。

//拡張子の取得
$fileext = mb_strtolower((new SplFileInfo($_FILES["upload"]["name"]))->getExtension());
//エラーチェック
if($_FILES['upload']['error'] == UPLOAD_ERR_INI_SIZE || $_FILES['upload']['error'] == UPLOAD_ERR_FORM_SIZE){
	$msg = 'ファイルが大きすぎます';
} else if($_FILES['upload']['error'] != 0){
	$msg = 'その他のエラーが発生しました:コード=' . $_FILES['upload']['error'];
} else if($fileext != 'xls' && $fileext != 'xlsx'){
	$msg = 'Excelファイルのみアップロードできます';
}

実際の読み取り部分は

//ファイル形式(拡張子)により読み取りを変える
$reader=null;
if($fileext == 'xls'){
	$reader = PHPExcel_IOFactory::createReader( 'Excel5' );
} else if($fileext == 'xlsx') {
	$reader = PHPExcel_IOFactory::createReader( 'Excel2007' );
}
if($reader){
//Excelファイルの読み込み
//必ず最初のシートにデータを保存すること
	$excel = $reader->load( $_FILES['upload']['tmp_name'] );
	$excel->setActiveSheetIndex(0);
	$sheet = $excel->getActiveSheet();
//配列で返す
	$obj = $sheet->toArray( null, true, true, true );

}

ファイルはサーバ上の一時領域に保存してある。
スクリプト終了時に削除される(はず)。

この場合、$objに連想配列で格納されている。
連想配列のキーは、行番号(1, 2, 3, ...)と列番号(A, B, C, ...)であり、わかりにくいかも。

そこで、1行めにカラム名を設定しておけば、連想配列のキーとして設定できる。

$keyarray=array();
$dataarray=array();
foreach($obj as $rowindex=>$rowdata){
	if($rowindex == '1'){
		//1行目にカラム名として連想配列のキーが入っている
		foreach($rowdata as $key=>$value){
			$keyarray[$key]=mb_strtolower(substr($value, 2));
		}
	} else {
		//2行目以降は、1行目で求めたカラム名を連想配列のキーとする
		foreach($rowdata as $key=>$value){
			$dataarray[$rowindex-1][$keyarray[$key]] = $value;
		}
	}
}

この場合、$dataarrayにデータが格納されており、キー項目は
行番号(1, 2, 3, ...)とカラム名(テーブル毎に異なる)。

【jQuery】テーブルの表頭を固定してスクロールさせる

色々と方法はあるようだが、微妙に調整が必要だったりタグ構造に依存してたりあるようで、ズレることもしばしば。

参考にしたのは、
jquery.tablefix.js – OTCHY.NET

jQuery プラグインで実現する。

普通にテーブルをデザインして

<table id="tablefix1">
    <thead>
    <tr>
        <th rowspan="2">ヘッダA</th>
        <th rowspan="2">ヘッダB</th>
        <th colspan="2">ヘッダC</th>
        <th rowspan="2">ヘッダD</th>
        <th rowspan="2">ヘッダE</th>
    </tr>
    <tr>
        <th>ヘッダ C-1</th>
        <th>ヘッダ C-2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>データ</td>
        <td>データ</td>


プラグインを呼び出すだけ

$('.table').tablefix({
	width: 600,
	height: 400,
	fixRows: 1
});

【jQuery】ダイナミックにDOM要素を変更する

例えば、本人控と会社控で2部印刷するような場合。
プリンタドライバの指定で2とすれば簡単にできるとする。

しかし、例えばその2部を区別したいような場合は、表頭のみ書き換えるようにしてみる場合。

<h3 class="noscreen" id="title"></h3>

※ブラウザでは表示させないが、印刷時のみ表示させる

印刷ボタンはonclickで自作関数を呼び出す。

<form class="noprint">
   <input type="button" value="印刷" onclick="print2();" id="print_button">
</form>

Javascriptの関数部は

function print2(){
	$("#title").text('講習会(本人 控)');
	window.print();
	$("#title").text('講習会(会社 控)');
	window.print();
	
	return true;
}

$("#title")でIDを指定し、text('講習会(本人 控)')でテキストを変更する。

【PHP】httpsにリダイレクトする

個人情報等、機密情報を扱うようなページの場合に無理やりにでもhttps通信を強制させたい。

if (empty($_SERVER['HTTPS'])) {
	//SSLでなかったらSSLのページにリダイレクトする
    header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
    exit;
}

SSLの場合は$_SERVER['HTTPS']に"on"等が入っている。
SSLでない場合は何も入っていない。


{$_SERVER['HTTP_HOST']}にはドメインに相当する値が入っており、
$_SERVER['REQUEST_URI']にはドメイン以下のパスやスクリプトファイル名がある。
つまり、{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}でサーバからのフルパス。
で、通信プロトコルhttpsを頭につけたURIにリダイレクトすればOK。

ちなみに、これはxamppでも使える。

【PHP】CSVを出力する

DB上のデータをExcelに吐き出したいような場合。
Excel側にODBCドライバを組み込み読みこむようにすることもできるけど、諸事情によりできないような場合。

CSVで吐き出し、Excelにコピペをしてもらうことにしよう。


まずは配列の作成。

$csvarray = array($space, $yobiclass, $space, $studentname, $studentkana, $space, 
	$schoolname, $telno, $space, $zipcode, $address.$address2, $space, $space, $paydate, $space, $space, "1");

次に、メモリ上のテンポラリ領域に作成。自動的に一時ファイルは削除させる。fputcsvは、データ区切りを自動的に付与する。

//メモリ上のテンポラリ領域に出力
$fp = fopen('php://temp', 'r+b');
fputcsv($fp, $csvarray);

データをダウンロードさせるためのheader出力

header('Content-Type: text/csv');
header("Content-Disposition: attachment; filename=" . $studentname . ".csv");

一時ファイルから読み込み、文字コードを変換しながら書き込む。SJISでなくてSJIS-win。
ExcelUTF-8を読み込むと文字化けしてしまうので。

//ファイルポインタを先頭へ
rewind($fp);
//リソースを読み込み文字列取得
$csv = stream_get_contents($fp);

//CSVをエクセルで開くことを想定して文字コードをSJIS-winSJISへ
$csv = mb_convert_encoding($csv,'SJIS-win','utf8');

print $csv;

fclose($fp);

【html+css】印刷ボタンを画面上に固定

画面が下に長くスクロールしても、印刷ボタンは固定したいような場合。

htmlでは、ボタンにidを割り当てておく。
onClickにwindow.print()を割り当てることでブラウザの印刷機能を呼び出す。
ちなみに、印刷時にはボタンそのものは印刷しないようにしている。

<form class="noprint">
   <input type="button" value="印刷" onclick="window.print();" id="print_button">
</form>

CSS側で、position: fixed;で固定する。topとrightは、それぞれ端からのピクセル数。

input#print_button {
	position: fixed;
	padding: 15px 40px;
	font-size: 1.2em;
	top: 10px;
	right: 10px;
}