2013年5月24日 星期五

如何讓TextBox的MaxLength對中文字元的長度計算也起作用?

在TextBox元件中設定的MaxLength,測試結果是對字數的限制,但是對應到資料庫的欄位長度就不符合,若輸入中文(double bytes)可能常常造成Oracle吐錯誤訊息「ORA-01401: Inserted value too large for column」,提供參考方向: 自訂控制項。

1. 繼承原有的TextBox,並修改MaxLength的實作AddAttributesToRender

using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System;

namespace CONTROL
{
  [ToolboxData("<{0}:TxtCommon runat=\"server\"></{0}:TxtCommon>")]//指定當自訂控制項從工具箱拖曳出來時,為此自訂控制項產生的預設標記。
  public class TxtCommon : TextBox
  {
    protected override void OnInit(System.EventArgs e)
    {
      base.OnInit(e);

      // 開始註冊JS在頁面上, 如果已經註冊便跳過
      Type type = this.GetType();
      string strJsLoc = "";
      string key = "CONTROL.JavaScript.Utility.js";
      if (!Page.ClientScript.IsClientScriptIncludeRegistered(key))
      {
        strJsLoc = this.Page.ClientScript.GetWebResourceUrl(type, key);
        this.Page.ClientScript.RegisterClientScriptInclude(key, strJsLoc);
      }
    }
   
    /// <summary>
    /// 寫入控制項額外屬性
    /// </summary>
    /// <param name="writer"></param>

    protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
    {
      base.AddAttributesToRender(writer);
      string strOnBlur = "";
      
      if (this.MaxLength != 0)
      {
          strOnBlur += string.Format("ChkBLen(this,{0});", this.MaxLength.ToString());
      }

      if (strOnBlur != "")
      {
          writer.AddAttribute("onblur", strOnBlur);
      }
    }
  }
}


2. 在註冊的JS中實作ChkBLen:

 //檢核長度
function ChkBLen(obj,intMaxByte)
{
    obj.value=obj.value;
    if(obj.value.Blength()>intMaxByte)
    {
        alert("超過最大長度限制:"+intMaxByte);
        while(obj.value.Blength()>intMaxByte)
        {
            obj.value=obj.value.substr(0,obj.value.length-1)
        }
        obj.focus();
    }
  
}

//傳回字串的byte長度
String.prototype.Blength = function() {
    var arr = this.match(/[^\x00-\xff]/ig);
    return  arr == null ? this.length : this.length + arr.length;



如此一來,在新增 TxtCommon自訂控制項時,若設定MaxLength,則在onblur事件發生時,就會自動呼叫ChkBLen,自動截斷多於的長度。

2013年5月9日 星期四

字串處理,如何得知在substring時,是否拆到中文字?



使用length()取string長度,會遇到中文字長度只有回傳1,所以如果是要算真正的長度,則需要將字串轉為byte陣列,但在做substring時,可能會截到中文字,故可先作byte是否為中文的判斷後,再做位置調整。主要是利用isChineseCharacter類別中所寫中文內碼範圍判斷,範例如下:

public class getByteTest {
    /**
     * 測試中文拆解,isChineseCharacter可判斷是否為中文字
     * @param args
     * @throws Throwable
     */
    public static void main(String[] args) throws Throwable{
        // TODO Auto-generated method stub
        String aaa="ABC小妹妹test123";
        byte[] dataByte = null;
         try {
             dataByte = aaa.getBytes("Big5");
         } catch (Throwable e) {
             System.out.println("傳入字串轉成Big5編碼的byte array 失敗 ");
         }
         String tmp = new String(dataByte, 0, dataByte.length, "Big5");
         boolean isChinese;
         for(int i=0; i<tmp.length();i++){
             isChinese=isChineseCharacter(tmp.charAt(i));
             System.out.println(tmp.charAt(i)+" : "+isChinese);
        }
    }
    public static boolean isChineseCharacter (char c){  
        return (19968<=(int)c)&&((int)c<=171941);
    }
}

2013年5月8日 星期三

利用SQL*Plus執行SQL->匯出成txt檔->FTP上傳

今天接到的需求是定期要把資料庫的資料格式化後,匯出成txt檔,並上傳到指定FTP。

 1.製作讓批次檔呼叫的sql檔
[spool.sql]
set newpage none --換頁空幾行

set space 0 --欄位間空幾個space
set colsep '|' --分隔符號,需搭配space <> 0時使用
set heading off --是否顯示欄位表頭
set pagesize 30 --一頁行數,設定0時是沒有分頁
set trimspool on --刪除行尾空白
set linesize 2000 --每行長度(超過自動斷行)
set feedback off --是否回寫總筆數
set termout off --是否將執行的command顯示在畫面上

spool C:\test.txt  --指定匯出檔名路徑
select 'test' from dual;
spool off
exit


2.製作file.bat批次檔
連線到sqlplus並執行上述sql,接著上傳ftp
[file.bat]
sqlplus ID/PassWord@DB @spool.sql

ftp 位址
id
pw
put 檔名

exit

3.排程file.bat檔,以後就可以自動執行。

ASP.NET FileUpload取不到完整路徑+遇到Postback將元件值清除問題的解法

在頁面中,任何postback都會將FileUpload元件上所選取的欄位清空,可能是資料檢核、下拉選單的change事件等等,造成使用者已經選取檔案路徑,操作其他元件卻又遺失的問題。

IE8 Security
上面關鍵字File Upload Control有說明
我試過firefox、chrome、IE8 above瀏覽器都有問題,無法用網路上說明的解法使用Fileupload.PostedFile.FileName取得檔案路徑。其他解法是說明要加入安全性網站,但我不想要做這種需要特殊設定才能執行的功能。

解決方法:使用javascript及Callback取代Postback

實作ICallbackEventHandler
用戶端回呼實作 (C#) 範例 

1.須繼承System.Web.UI.ICallbackEventHandler

public partial class ClientCallback : System.Web.UI.Page,
     System.Web.UI.ICallbackEventHandler
 
2.實作以下兩個Method

public void RaiseCallbackEvent(String eventArgument)
{
//javascript 呼叫function 
//eventArgument為javascript傳入的參數,如本範例中的sCardNO
 }
public String GetCallbackResult()
{
   //javascript可接收到的值 
 return returnValue;
}
 
3. javascript部份寫法
 
//呼叫RaiseCallbackEvent
function GetBoss1Info()
{
//傳入參數:sCardNO
//回傳接收的function
   <%= Page.ClientScript.GetCallbackEventReference(this, "sCardNO", "ProcessResult1", null) %>;
}
//GetCallbackResult回傳
function ProcessResult1(returnmessage, context)
{
  //returnmessage為回傳資料
}

C#中呼叫command console執行動作


 ProcessStartInfo 類別

ProcessStartInfo cmd = new System.Diagnostics.ProcessStartInfo("cmd.exe");
cmd.RedirectStandardInput = true;
cmd.RedirectStandardOutput = true; 
cmd.RedirectStandardError = true; 
cmd.UseShellExecute = false;


Process 類別

Process console = Process.Start(cmd);
console.StandardInput.WriteLine("D:");
console.StandardInput.WriteLine("exit");
string output = console.StandardOutput.ReadToEnd()
console.Close();