- Refval關聯元件可以使用WhereItem過濾資料,如果過濾條件較複雜無法以WhereItem設定時,應如何處理?可以從server的該關聯的infocommand裡用SQL語法去過濾資料。以出貨單為例,如果想要過濾 已審核 且 客戶編號為'1' 的"報價單號" :可以先在server端的infocommand寫入SQL語法過濾出已審核的報價單。
再從DataForm的column中的"報價單號"欄位設定WhereItem
- 如何在前端下SQL語法取得資料?基於資訊安全的原因,eepcloud是不允許在前端直接執行SQL語法的,只能夠過後端的 Server Method來執行。後端的ServerMethod寫法,如下:exports.dosql = function(param, callback){var clientInfo = this.clientInfo;var id=param.id;var sql = "select 名稱 from 客戶資料表 where 客戶編號 = '"+id+"'"; //SQL條件句this.queryRaw(clientInfo, clientInfo.database, sql, {}, callback);}Client端的調用,如下的JSfunction Test(){var result =$.callSyncMethod('客戶資料表', 'dosql',{id:001}); //非同步調用var param = $.parseJSON(result); //傳回result為JSON格式if (param.length != 0){alert(param[0].名稱); //假設只傳回1筆資料}}
- 如何在前端執行後端的SQL?舉一個去後端更改一個Table某個欄位的日期格式例子,前端的JS:function mymethod(){$.callMethod('庫存進出明細表','dosql',{},function(result){alert('執行成功!');});}庫存進出明細表 ->後端模組名稱dosql -> callServerMethod 的名稱(請自行命名)後端的JS:exports.dosql = function(param, callback){var clientInfo = this.clientInfo;this.query(clientInfo, clientInfo.database, ['update [庫存進出明細表] set F010=LEFT(CONVERT(varchar(50),F003,112),6)'],{}, callback);};
- 如何在後端資料存檔後,下達自己的SQL?可以使用UpdateComp的onAfterUpdate事件寫一段後端JS來完成,如下:
sqls.push()為送出的自訂SQL語法,row._客戶編號 為該更改資料的欄位名稱。
- 如何Call Stored?後端的jsexports.testMethod = function(param, callback){var clientInfo = this.clientInfo;var module = this;var sql =" exec test '"+param.userid+"' "; //SQL條件句module.query(clientInfo,clientInfo.database,[sql],{},function(err, result){if(err){callback(err)}else{callback(null,result);}});};前端的jsfunction callservermethod(){var user = $.getVariableValue('user');$.callMethod('test', 'testMethod', {userid:user}, function(result){alert('成功執行');});}test -> 後端模組名稱testMethod -> callServerMethod 的名稱(請自行命名)userid:user -> 上傳的參數(如果沒有的話可以填null)
- 如何在Server端存檔前(新增或更改) 再決定某個欄位的內容並存入資料庫?後端的js:exports.uc盤點單明細_onBeforeInsert = function(row, sqls, callback){var dm = this.dataModule;var clientInfo = dm.clientInfo;var sql = "select max(年月) AS LASTYM from 庫存結帳表";dm.queryRaw(clientInfo, clientInfo.database, sql, {}, function(err, datas) {var last_period = datas[0].LASTYM;sql = "select 平均成本 from 庫存結帳表 Where 產品編號='"+row.產品編號+"' and 年月='"+last_period+"'";dm.queryRaw(clientInfo, clientInfo.database, sql,{}, function(err, datas) {if (datas.length>0) {row.單價 = datas[0].平均成本;}callback(null, true);});});}
- 為何在server端的infocommand寫sql語法使用(不等於<>)會報錯?因網頁安全問題『<>』要改用『 != 』會報錯的語法 :SELECT vUSERS.* FROM vUSERSwhere STATE <> '離職'ORDER BY USERID須改為下列正確語法 :SELECT vUSERS.* FROM vUSERSwhere STATE != '離職'ORDER BY USERID
- 如何在EEPCloud中開發Stored Procedure? 如何呼叫?在EEPCloud的Table節點中, 可以右鍵"儲存過程"(預存程序), 打開頁面後可以用"+新增"來增加一個Stored Procedure, 如下, 填寫 Name為Stored Procedure Name, Parameters為Input/Output參數, Text代表Stored Procedure的程式內容,並按下確定即可。
如果在Server端要執行此SP, 只要使用 "Exec" 來執行即可, 如下的Server Method:exports.doCreate = function(param,callback){var year = param.year; // 取出年度var clientInfo = this.clientInfo;var dm = this;dm.query(clientInfo, clientInfo.database, ['exec sp_vacation '+year],{}, callback); //執行sp};
- TRS交易時, 是否可以控制某些條件成立在過帳, 否則就不過帳?可以的, 在EEPCloud的Transaction組件中, 每一個交易都有一個onBeforeTrans事件, 可以控制是否要持續交易或動態改變對方的交易欄位, 如下為控制是否交易的例子:exports.trs請假單_年度特休假表_onBeforeTrans = function(row, oldRow, fields){if (row.請假類型!='特休假') return false; //不為特休假就不過帳return true;};上面的情況是針對'請假類型'不能更改的情況, 如果請假類型可以更改的話, 要改成這樣:exports.trs請假單_年度特休假表_onBeforeTrans = function(row, oldRow, fields){if (row.請假類型!='特休假' && oldRow.請假類型!='特休假') { //考慮更改時新舊值都不為特休假return false;}else if (oldRow.請假類型=='特休假') { //如果是特休假改為其他假時row.請假天數=0;}return true;};
- Server端的JS程式非常不好Debug, 常常不知道錯誤在哪? 有沒有比較好的方法可以Debug?Server端在主機, 服務大眾用戶, 確實很難Debug, 可以如下的方式來debug:1. 可以在Server端中使用 dataModule.echo()方法, 回應到SQL Profiler的"Server"訊息中, 如使用 echo('pass 1'); 等等了解JS的程式邏輯與執行到哪個階段出錯, 或echo()你自己的變數, 看看是否變數的內容有錯。2. 另一個方法, 就是當Server端程式比較複雜, 需要調用非同步的程式時, 如果非同步程式內出錯, 會回不來, 此時最好在非同步程式中, 使用 try/catch的方式來避免回不來, 如下:
- 後端Command中的SQL比較複雜, 用了很多Left Join與欄位AS別名後, 前端的Query送出後會發生Where錯誤, 因為前端並不知道後端的實際的欄名, 如何解決?可以透過後端Command的onBeforeExecuteSQL事件來重新替換Where的欄位名稱, 如下的範例:exports.GPT010RA_onBeforeExecuteSQL = function(sql, whereStrs){for (var i = 0; i < whereStrs.length; i++) {whereStrs[i] = whereStrs[i].replace(/M_SVS/g, 'A.M_MA'); //將M_SVS別名欄位換成實際的A.M_MA欄位}return sql;};
- 執行後端的Server Method如果時間較長,如何告知使用者執行中,並於結束後關閉此訊息?如下, 可以透過 $.loading()與$loaded() 這兩個方法來處理:function sendMail(){$.confirm( "確認發送薪資eMail嗎?", function() {$.loading($('#dgMaster').closest('div'), '處理中...');$.callMethod('薪資明細表','doSendMails',{},function(result){$.alert(yymm+' 薪資eMail發送成功!','info');$.loaded($('#dgMaster').closest('div')) //關閉訊息框});});}}
- 如何在後端利用資料表內容發送不同對象的eMail?發送多封不同對象的EMail時, 因為EMail發送為非同步的機制, 所以這裡要採用一個 async非同步機制來執行, 可以透過Server端infoMail這個組件來發送eMail, 如下的範例, 其中, 可透過InfoMail.htmlrow()以網格形式來輸出欄位內容到Email內容中:exports.doSendMails = function(param,callback){this.echo('do send mail begin');var yymm = param.yymm; // 取得薪資發放月份var co = param.co; //取得子公司var dm = this;var async = this.getModule('async'); // 改用新的方式來引用 async 非同步模組this.getComponent('InfoMail1','infomail',function(err,mail){var sql = "SELECT A.薪資年月,A.員工編號,A.部門,A.姓名,A.子公司,A.實發薪資,B.電子郵件 FROM 薪資發放作業 A,員工資料表 B";sql = sql + " WHERE A.員工編號=B.員工編號 AND (B.電子郵件 IS NOT NULL AND B.電子郵件<>'') AND A.薪資年月='"+ yymm +"' AND A.子公司='"+ co +"'"; //取得當月員工薪資資料dm.queryRaw(dm.clientInfo, dm.clientInfo.database, sql, {},function(err, rows) {if(err){callback(err);}else{async.eachSeries(rows,function(row,cb){dm.echo(row.電子郵件);var subject = yymm+"月份薪資發放通知";var table1 = mail.HtmlRow(row, [{ field: '薪資年月', title: '薪資年月'},{ field: '員工編號', title: '員工編號'},{ field: '姓名', title: '姓名'},{ field: '子公司', title: '子公司'},{ field: '部門', title: '部門'},{ field: '實發薪資', title: '實發薪資'}]);var param = {'subject':subject,'to':row.電子郵件,'body':table1};mail.Send(param,cb); // 發送郵件},callback);}});});};
- 為何我在 Server端的 InfoCommand中使用Group By命令, 沒Select到Key的欄位時, 會報錯 "Group By子句"的錯誤?這是因為InfoCommand預設SelectPaging=True的屬性(資料快速分頁功能), 如果要特殊使用Group by時, 須配合SelectPaging=False即可。
- 執行Server Method時, 如何控制後端所發生的錯誤或訊息, 來告知前端?通常後端的錯誤透過 callback(err) 傳送回前端, 如果想自定訊息內容, 可以透過 Error() 來定義, 如下:exports.doCreate = function(param,callback){var clientInfo = this.clientInfo;var sql =" exec sp_create"; // call spvar dm=this;this.query(clientInfo,clientInfo.database,[sql],{},function(err, result){if(err) callback(new Error('後端的過帳程式出現錯誤, 請聯絡資訊人員!'));else callback(null);});};
- 如何正確使用Server端infocommand的SecStyle和SecExcept屬性?SecExcept要配合SecStyle, SecStyle=User那SecExcept要填Userid,如果SecStyle=Group, SecExcept則填Groupid,如果SecExcept要填多個以”,”或”;”隔開
- 請問Server端的 JS 如何讓別人共用, 或互相調用?可以使用 getServerModule來取得對象並直接調用, 如以下為被調用的 出貨單 ServerModule:exports.readData = function(param,callback){var dm=param.dm; // 不能用 this.dataModule要從原來的方法中傳進來var clientInfo = dm.clientInfo;dm.queryRaw(clientInfo, clientInfo.database, "Select * from INVO WHERE F001='"+param.no+"'", {},callback)}如下, 有一個 出貨單的Server Method要調用上面的readData()方法:exports.writeData = function(param,callback){var clientInfo = this.clientInfo;var dm=this;var no=param.no;this.getServerModule('出貨單').readData({no:no,dm:dm}, function(err, result){ // call 出貨單.readData() export方法try {if (result.length != 0){dm.query(clientInfo, clientInfo.database, ["update INVO set F018='"+result[0].F016+"'"],{}, callback);}}catch(e){callback(e);}});}
- 自動編號中, 如何使用指定欄位作為前引碼來編號?透過 AutoNumber組建的 onGetFixed事件即可, 如下:exports.an出貨單_onGetFixed = function(fixedString, rows){fixedString = rows[0].客戶編號; // 以客戶編號為前引碼return fixedString;};
- 為何我CallServerMethod幾次以後, Server會掛掉不回應? 及Server Method如何傳回執行結果?通常都是Server Method中,沒有執行Callback回不來的原因, 或是執行了兩次Callback,在Server端的Callback注意事項如下:1. 一定要有callback,而且不能執行2次callback。2. callback傳回參數的方法,通常會傳兩個參數,第一個參數:Err, 第二個參數: 自訂傳回值(如果有的話)。如下幾種:callback(err); // 只傳回是否錯誤callback(err,datas); // 傳回是否錯誤及datas資料內容callback(null); // 回應正常無錯誤callback(new Error('程式發生錯誤, 請聯絡IT部門處理…')); // 回應自訂的錯誤訊息callback; // 預設傳遞兩個參數, 第1個err,第2個Data如以下兩種寫法是一樣的結果, 上面為省略的寫法:this.queryRaw(clientInfo, clientInfo.database, sql, {}, callback); // 第一種寫法this.queryRaw(clientInfo, clientInfo.database, sql, {}, function(err,datas) {callback(err,datas);}); // 第二種寫法
- 為何我在 TRS的onBeforeTrans中, 取不到 this.clientInfo的變數內容?在UpdateComp或Transaction的事件對象中的 this 並非 dataModule本身, 而是更外層, 所以需使用 this.dataModule來取出 dataModule, 如下:exports.trs你的表單_TRS_onBeforeTrans = function(row, oldRow, fields){var dm = this.dataModule; //取出 dataModulevar user = dm.clientInfo.user; // 取得 user等.....return true;}
- TRS中如何使用後端來編明細表的自動序號?自動序號通常在前端使用 AutoSeq組件來處理,如果要在TRS中使用自動序號的功能,需要在TRS中設定onBeforeTrans事件,如先在TRS設定好來源是"銷貨單明細.序號",目的是"庫存進出明細表.序號"(Replace模式),其實並要真正讀取來源的序號,而是利用這個機制,透過onBeforeTrans事件來動態替換來源數據來達到目的,如下:exports.trs銷貨單明細_庫存進出明細表_onBeforeTrans = function(row, oldRow, fields,callback){var dm = this.dataModule;if (oldRow==null) { // 新增的狀態才處理var clientInfo = dm.clientInfo;var sql = "SELECT MAX(序號) AS 序號 from 庫存進出明細表 Where 單據號碼='"+row.銷貨單號+"'"; // 取出對應的最大序號dm.queryRaw(clientInfo, clientInfo.database, sql, {}, function(err,datas) {if (err) callback(err);else if (datas.length==0 || (! datas[0].序號)) row.序號='001'; // 第一筆明細為 '001'else if (datas.length>0) row.序號= ((parseInt(datas[0].序號)+1001).toString()).substring(1); // 序號+1callback(null, true); // callback要return true讓TRS繼續交易});}else {fields.splice(5,1); //刪除 '序號' 過帳欄位, 避免被覆蓋return true; // 沒有使用 callback請return true;}};
- 如何在後端取得系統變數(如今天及時間等)?舉例://後端servermethod的取值this.getDateValue('today').Format("yyyy/MM/dd"); // 今天this.getDateValue('firstday').Format("yyyy/MM/dd"); // 本月第一天new Date().Format("yyyy/MM/dd hh:mm:ss"); //取得目前時間//後端在UpdateComp的事件裡則用this.dataModule.getDateValue('today').Format("yyyy/MM/dd");this.dataModule.getDateValue('firstday').Format("yyyy/MM/dd");系統變數如下:變數名稱 內容today 今天日期todayc8 今天日期(varchar8)firstday 本月首日lastday 本月末日firstdaylm 上月首日lastdaylm 上月末日firstdayty 本年首日lastdayty 本年末日firstdayly 去年首日lastdayly 去年末日
- 如果只是要到後端取關聯的名稱, 一定要寫Server Method嗎?如果只是單純的取某個資料表的每一個欄位值, 可以透過 getDisplayText() 系統方法來取值, 省去後端的Server Method,如下:var userMail = getDisplayText('購物車.User','USERID','EMAIL', $('#dfMaster_客戶編號').val() ); // 用客戶編號去取USERS的EMAIL欄位內容$('#dfMaster_電子郵件').val( userMail ); // 設值到電子郵件欄位以上需注意: "購物車.User"是一個RemoteName,需事先在"購物車"Server端模組中, 設定好"Select * From Users"這個Command
- 後端如何傳送非資料表結構的訊息回到前端回?如下的範例:後端的JS:exports.test = function(param, callback){if (param.no=='1') callback(null,'傳送你的訊息!'); // 傳回你的訊息else callback(new Error('錯誤!')); // 送出錯誤訊息}前端的JS:function test(){$.callMethod('出貨單4','test',{no:'1'},function(result){$.alert(result,'info'); // 傳回正常的訊息});}