見出し画像

Webixライブラリを使えば、簡単にEXCELデータを確認してシステムに取り込むことが可能です。No.040

webixライブラリ(Javascript)とPHP言語(サーバサイド)を使ったWebアプリの事例を何度か紹介していますが、今回、この機能でサービスを構築したので、事例紹介として公開します。EXCELで編集したファイルをファイルダイアログ画面で選択し、一度、ブラウザ画面上で内容を確認してからサーバにデータとして取込み、DBに保存する事例です。Webixライブラリが持つ、多くのコンポーネントの中で、ui.uploaderを使います。ui.uploaderは、ファイルを選択して、そのままサーバに転送する機能が基本ですが、転送ファイルを選択した時点で、onBeforeFileAddというイベントを使って、ファイルをブラウザに取り込む処理内で別の処理に変更することで、EXCEL情報)シート内のセル情報)を判断して取り出すことができます。

以下のようなEXCELファイルを準備し、そのファイルを指定して、処理すれば、画面上にEXCELシートの情報を取り出すことができます。(この事例では、黄色背景色の部分だけピックアップしています)

以下の画面が取り込んだ情報を確認する画面です。

この事例では、EXCEL取込操作(ブラウザで対象ファイルを選択する操作)時に、商品IDの値が指定されているかを事前チェックし、未入力ならメッセージを出したかったので、通常のonBeforeFileAddイベントで受ける処理ではなく、別の方式にしています。
商品IDを指定しないで、EXCEL取込をクリックしたときのメッセージです。

商品ID情報を指定して、EXCEL取込したときは、ファイルを選択するダイアログ表示となります。

指定EXCELファイルを選択して開くをクリックすれば、EXCELファイルを取込みます。

この記事で紹介するソースでは、EXCELファイルを取り込むときに、指定情報の有無などを確認し、画面にメッセージやコメントを赤で表示するロジックにしています。(サンプルでは、ホスト名のチェックのみ記載していますが、実際のソースでは、商品種別(4種類)によって、指定が必要なフィールドをチェックしたり、指定していない情報は、作業者が値を決める旨を表示するロジックにしています。

画面(Javascript)上で、チェックを実施し、妥当であれば、サーバに値をPOSTする方式です。通常のonBeforeFileAddイベントで実装すると、事前の商品IDチェックロジックを通過しないで、ファイル選択ダイアログが表示されてしまうので、別のボタンを実装し、以下のようなコードを記述しています。
チェックを通過したら、$$("ELXUPD_import_btn").fileDialog();を実行します。

{ margin:5, cols:[
	{width:200},
	{view:"button",  value: "EXCEL取込", align:"center", width:100,
		click:function(){
			var eqp_id = $$("eqp_id").getValue();
			var ptn_info = $$("ptn_info").getValue();
			if(eqp_id == ""){
				webix.alert("商品IDを入力してください。");
				return;
			}
			if(ptn_info == ""){
				webix.alert("商品種別を選択してください。");
				return;
			}
			$$("ELXUPD_import_btn").fileDialog();
		}
	},
	{view:"button",  value: menu_btn_name, align:"center", width: 80,css:"menu",
		click:function(){
			location.href = 'https://www.google.com/?hl=ja';
		}
	}
 ]},

onBeforeFileAddイベントの箇所は、以下のように実装します。

{ margin:5, cols:[
   	{view:"uploader", value:"EXCEL取込",width: 100,id:"ELXUPD_import_btn",
   		apiOnly: true, 
		on:{
			onBeforeFileAdd: function(upload){
			 //インポート処理を追加
				if(ELXUPD_getExt(upload.file.name) != "xlsx"){
 					webix.alert("指定ファイル『"+upload.file.name+"』はEXCELフォーマットでありません。<br>ファイルを再確認してください。");
				}
				else{
					webix.DataDriver.excel.toObject(upload.file).then(function(data){
						try{
							const records = data.data;
							var hostname      =records[11][2];
							var ipaddress     =records[12][2];
							var subnetmask    =records[13][2];
							var defaultgateway=records[14][2];
							var rootpassword   =records[15][2];
							var username      =records[16][2];
							var userpassword   =records[17][2];
							var domainname    =records[18][2];
							var dbrootpassword=records[20][2];
							var dbwebixpassword=records[21][2];
							var webixinstallfolder=records[23][2];

							$$("hostname").setValue(hostname);
							$$("ipaddress").setValue(ipaddress);
							$$("subnetmask").setValue(subnetmask);
							$$("defaultgateway").setValue(defaultgateway);
							$$("rootpassword").setValue(rootpassword);
							$$("username").setValue(username);
							$$("userpassword").setValue(userpassword);
							$$("domainname").setValue(domainname);
							$$("dbrootpassword").setValue(dbrootpassword);
							$$("dbwebixpassword").setValue(dbwebixpassword);
							$$("webixinstallfolder").setValue(webixinstallfolder);
							var ptn_info = $$("ptn_info").getValue();

							if(hostname==""){
								$$("hostname_label").define("label","ホスト名は、必須情報です");
								$$("hostname_label").refresh();
								webix.alert("ホスト名は、必須情報です。");
								return;
							}

但し、上記のままだと、uploaderのボタンも画面に表示されるので、画面起動時の最後で該当ボタンを非表示にする指定も必要です。

$$("ELXUPD_import_btn").hide();

EXCELファイルからデータを取り込むメソッドは、
webix.DataDriver.excel.toObject(upload.file)
です。
以下のように実装すれば、EXCLEの指定セル情報を取り出すことができます。例では、ホスト名の情報です。(EXCELシートの”C13”)
シート内のデータは、配列で参照できます。(日本語も正しくとりだせます)

webix.DataDriver.excel.toObject(upload.file).then(function(data){
	try{
		const records = data.data;
		var hostname      =records[11][2];

EXCELから取り込んだデータは、一度、画面上のフォームに転記します。

$$("hostname").setValue(hostname);
$$("ipaddress").setValue(ipaddress);
$$("subnetmask").setValue(subnetmask);
$$("defaultgateway").setValue(defaultgateway);
$$("rootpassword").setValue(rootpassword);
$$("username").setValue(username);
$$("userpassword").setValue(userpassword);
$$("domainname").setValue(domainname);
$$("dbrootpassword").setValue(dbrootpassword);
$$("dbwebixpassword").setValue(dbwebixpassword);
$$("webixinstallfolder").setValue(webixinstallfolder);

その後、転送していいかの確認ダイアログ(confirm)ではいと指定があったときに、転送します。(POSTでサーバに転送)

	function post_data_to_server(){
    	var data_list = $$("ELXUPD_form1").getValues();
 		var formData = new FormData();
		var access_key = Get_AccessKey();
		formData.append("accesskey",access_key);
		formData.append("userid",my_local_session.userid);
		formData.append("job_info","EX0010");
		formData.append("data_list",JSON.stringify(data_list));
  		var xhr =webix.ajax().sync().post("<?php  echo SUB_FOLDER; ?>/rest_api/EX0010/EX0011_save_excel_data.php",formData);
		var resp =  JSON.parse(xhr.responseText);
		if(resp.resp =="ok"){
			if(resp.conditon == "update"){
				webix.alert("環境設定情報を<br>更新しました。<br>画面を閉じてください。");
			}
			else{
				webix.alert("環境設定情報を<br>登録しました。<br>画面を閉じてください。");
			}
		}
		else{
			webix.message({type:"error",text:"登録処理でエラー発生 <br>error code ="+resp.error_code});
		}
	}

フォーム上のデータは、以下のように記述すれば、全てとりだせます。

var data_list = $$("ELXUPD_form1").getValues();

連想配列でとりだせるので、文字列化を実行してPOSTします。

formData.append("data_list",JSON.stringify(data_list));

PHP(サーバ側)では、
以下の記述で、$data_listに連想配列で取り込めます。

	if(isset($_POST['data_list'])){
		$data_list_str = $_POST['data_list'];
 		$data_list = json_decode($data_list_str ,true);
	}

例えば、ホスト名は、$data_list["hostname"]です。
サーバ(PHP)側では、UIから受信したデータを格納しますが、同じ商品IDでは、上書き更新、未登録ならINSERTするロジックにします。かつ、ステータスも持っていて、未作業なら上書き格納を許容しますが、作業中のステータスなら、エラー応答するように実装しています。

$id = intval($var_lists[0]["id"]);
$status_id = intval($var_lists[0]["status_id"]);	//0:申請中 1:作業中 2:完了 3:キャンセル
error_log($logheader.'eqp_id:'.$data_list["eqp_id"].' found id='.$id.' status_id ='.$status_id );
if($status_id == 0){
	error_log($logheader.'eqp_id:'.$data_list["eqp_id"].' update');
}
else if($status_id != 0){
	error_log($logheader.'eqp_id:'.$data_list["eqp_id"].' not update');
	//エラー応答
	$resp = "ng";
	$error_code = -10;
	$condition = "error";
	$json_data = json_encode(compact("resp","error_code","status_id","condition"),JSON_UNESCAPED_UNICODE);
	echo $json_data;
	exit;
}

画面(javascript)では、以下のように記述してサーバ(PHP)に格納依頼します。

function post_data_to_server(){
	var data_list = $$("ELXUPD_form1").getValues();
	var formData = new FormData();
	var access_key = Get_AccessKey();
	formData.append("accesskey",access_key);
	formData.append("userid",my_local_session.userid);
	formData.append("job_info","EX0010");
	formData.append("data_list",JSON.stringify(data_list));
	var xhr =webix.ajax().sync().post("<?php  echo SUB_FOLDER; ?>/rest_api/EX0010/EX0011_save_excel_data.php",formData);
	var resp =  JSON.parse(xhr.responseText);
	if(resp.resp =="ok"){
		if(resp.conditon == "update"){
			webix.alert("環境設定情報を<br>更新しました。<br>画面を閉じてください。");
		}
		else{
			webix.alert("環境設定情報を<br>登録しました。<br>画面を閉じてください。");
		}
	}
	else{
		webix.message({type:"error",text:"登録処理でエラー発生 <br>error code ="+resp.error_code});
	}
}

今回の事例は、EXCELの一覧情報ではなく、フォーム情報でしたが、一覧情報を連想配列で取り出し、同じように文字列化してサーバに転送すれば、一覧情報もDBに格納できます。(ループ処理できるので、簡単です)
画面側の主なソースを以下に記述します(一部のコードは省略しています)

<?php
	//EX0010_EXCEL_import_form.php
?>
<!DOCTYPE html>
<html lang="ja">
	<head>
	<meta charset="UTF-8">
    <script src="/webix_GPL_1020/webix.js"></script>
	<link href="/webix_GPL_1020/skins/compact.css?<?php echo date('Ymd-H'); ?>" rel="stylesheet" type="text/css">    
	<link href="<?php  echo SUB_FOLDER; ?>/commonlib/webix_custom_css.css?<?php echo date('Ymd-H'); ?>" rel="stylesheet" type="text/css">    
	<link rel="icon" href="<?php  echo SUB_FOLDER; ?>/image/webix_64.ico">
	<script src="<?php  echo SUB_FOLDER; ?>/commonlib/moment-with-locales.js"></script>
    <script src="<?php  echo SUB_FOLDER; ?>/commonlib/webix_common_lib.js"></script>
	<link rel="stylesheet" href="/webix_GPL_1020/css/materialdesignicons.min.css" type="text/css" charset="utf-8">
	<title><?php echo $TITLE_INFO.' ('.$VER_INFO.')' ?></title>
	</head>
	<style>
	.red {
  		color: #FF0000;
	}
    </style>
	<body>
	<script type="text/javascript" charset="utf-8">
	webix.i18n.setLocale("ja-JP");


	//ファイル名から拡張子を取得する関数
	function ELXUPD_getExt(filename)
	{
		var pos = filename.lastIndexOf('.');
		if (pos === -1) return '';
		return filename.slice(pos + 1);
	}
	function post_data_to_server(){
    	var data_list = $$("ELXUPD_form1").getValues();
 		var formData = new FormData();
		var access_key = Get_AccessKey();
		formData.append("accesskey",access_key);
		formData.append("userid",my_local_session.userid);
		formData.append("job_info","EX0010");
		formData.append("data_list",JSON.stringify(data_list));
  		var xhr =webix.ajax().sync().post("<?php  echo SUB_FOLDER; ?>/rest_api/EX0010/EX0011_save_excel_data.php",formData);
		var resp =  JSON.parse(xhr.responseText);
		if(resp.resp =="ok"){
			if(resp.conditon == "update"){
				webix.alert("環境設定情報を<br>更新しました。<br>画面を閉じてください。");
			}
			else{
				webix.alert("環境設定情報を<br>登録しました。<br>画面を閉じてください。");
			}
		}
		else{
			webix.message({type:"error",text:"登録処理でエラー発生 <br>error code ="+resp.error_code});
		}
	}
	var ELXUPD_form_collection = [
		{ view:"label", height:50, template:"<span style='font-weight:bold; font-size:180%;'>TRIGKEYセットアップデザインシート</span>",width:890},
 		{ view:"label", height:80,template:"注文時の商品IDを入力し、商品種別を確認後に、<BR>セットアップデザインシートEXCELをEXCEL取込で取り込んでください。",width:890},
        { margin:20,cols:[
        	{view:"text",id:"eqp_id",name:"eqp_id",label:"商品ID",width: 380,labelWidth: 200,labelAlign:"right",attributes:{maxlength:12,required:"true"},placeholder:"注文時の商品ID" },
    	 ]},
		{ margin:20, cols:[
			{width:100},
			{view:"select",width: 260,label: "商品種別",labelwidth:100,id:"ptn_info",name:"ptn_info",labelAlign:"right",value:"PTN4",options:["PTN1","PTN2","PTN3","PTN4"]},
		 ]},
		{ margin:20, cols:[
        	{view:"textarea",id:"memo",name:"memo",label:"連絡事項",width: 380,height:100,labelWidth: 60,labelAlign:"right",attributes:{maxlength:256},placeholder:"必要であれば、ここに連絡内容を\n記載ください。\n返信を希望の場合は、メールアドレスを\n記入してください。" },
		 ]},
		{ margin:5, cols:[
			{width:200},
			{view:"button",  value: "EXCEL取込", align:"center", width:100,
    			click:function(){
      				var eqp_id = $$("eqp_id").getValue();
      				var ptn_info = $$("ptn_info").getValue();
      				if(eqp_id == ""){
      					webix.alert("商品IDを入力してください。");
      					return;
      				}
      				if(ptn_info == ""){
      					webix.alert("商品種別を選択してください。");
      					return;
      				}
					$$("ELXUPD_import_btn").fileDialog();
      			}
    		},
    		{view:"button",  value: menu_btn_name, align:"center", width: 80,css:"menu",
    			click:function(){
					location.href = 'https://www.google.com/?hl=ja';
      			}
    		}
    	 ]},
		{ margin:5, cols:[
  		   	{view:"uploader", value:"EXCEL取込",width: 100,id:"ELXUPD_import_btn",
  		   		apiOnly: true, 
    			on:{
      				onBeforeFileAdd: function(upload){
      				 //インポート処理を追加
      					if(ELXUPD_getExt(upload.file.name) != "xlsx"){
         					webix.alert("指定ファイル『"+upload.file.name+"』はEXCELフォーマットでありません。<br>ファイルを再確認してください。");
      					}
      					else{
     						webix.DataDriver.excel.toObject(upload.file).then(function(data){
      							try{
      								const records = data.data;
      								var hostname      =records[11][2];
      								var ipaddress     =records[12][2];
      								var subnetmask    =records[13][2];
      								var defaultgateway=records[14][2];
      								var rootpassword   =records[15][2];
      								var username      =records[16][2];
      								var userpassword   =records[17][2];
      								var domainname    =records[18][2];
      								var dbrootpassword=records[20][2];
      								var dbwebixpassword=records[21][2];
      								var webixinstallfolder=records[23][2];

      								$$("hostname").setValue(hostname);
      								$$("ipaddress").setValue(ipaddress);
      								$$("subnetmask").setValue(subnetmask);
      								$$("defaultgateway").setValue(defaultgateway);
      								$$("rootpassword").setValue(rootpassword);
      								$$("username").setValue(username);
      								$$("userpassword").setValue(userpassword);
      								$$("domainname").setValue(domainname);
      								$$("dbrootpassword").setValue(dbrootpassword);
      								$$("dbwebixpassword").setValue(dbwebixpassword);
      								$$("webixinstallfolder").setValue(webixinstallfolder);
									var ptn_info = $$("ptn_info").getValue();

									if(hostname==""){
										$$("hostname_label").define("label","ホスト名は、必須情報です");
										$$("hostname_label").refresh();
										webix.alert("ホスト名は、必須情報です。");
										return;
									}
					                webix.confirm({
					                	title:"確認",
					                	ok:"はい", 
					                	cancel:"いいえ",
					                	text:"表示内容で登録していいですか?<br>同じ商品IDで操作した場合、<br>上書きで更新します。<br>必要であれば、いいえで<br>中断し、内容を確認してください。"
					                })
					                .then(function(result){  //はいのとき
					                	post_data_to_server();
					                }) 
					                .fail(function(){		//いいえの時		
					                	webix.message({type:"debug",text:"操作をキャンセルしました。"});
					                });
    	      					}catch(e){
    	      						webix.alert("EXCEL 取込みでエラーが発生しました。:"+ e.message);
    	      					}
							});
	 					}
       					return false;
      				}
    			}
    		},
        ]},
        { margin:20,cols:[
        	{view:"text",id:"hostname",name:"hostname",label:"ホスト名",width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        	{view:"label",label:"",width:250,id:"hostname_label",css:"red"},
    	]},
        { margin:20,cols:[
            {view:"text",id:"ipaddress",name:"ipaddress",label:"IPアドレス"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"subnetmask",name:"subnetmask",label:"サブネットマスク"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"defaultgateway",name:"defaultgateway",label:"デフォルトゲートウェィ"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"rootpassword",name:"rootpassword",label:"rootユーザパスワード"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"username",name:"username",label:"一般ユーザ名"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"userpassword",name:"userpassword",label:"一般ユーザパスワード"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"domainname",name:"domainname",label:"ドメイン名(ServerName)"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"dbrootpassword",name:"dbrootpassword",label:"MariaDB rootユーザパスワード"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
       ]},
        { margin:20,cols:[
            {view:"text",id:"dbwebixpassword",name:"dbwebixpassword",label:"MariaDB weixユーザパスワード"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
        { margin:20,cols:[
            {view:"text",id:"webixinstallfolder",name:"webixinstallfolder",label:"webixインストールフォルダ名"  ,width: 380,labelWidth: 200,labelAlign:"right",readonly:true},
        ]},
	];
	
	
	webix.ui({
		padding: 10,
			rows:[{
  				view:"form",	//作成されるエレメントの種類
  				id: "ELXUPD_form1",	//参照用のID情報
				scroll:false,	//構成画面のスクロール設定
  				elements:ELXUPD_form_collection ,	//フォームの構成要素を指定
  				margin:3,
 				},
  			]
		}
	);


$$("ELXUPD_import_btn").hide();
</script>
</body>
</html>

この記事が気に入ったらサポートをしてみませんか?