2011年9月21日 星期三

標點符號自救法


以前用 office word,都會習慣要設定好符號表,但如果不是在 word 裡面編輯文章且需要使用到標點符號,就會覺得有點不方便。如果你所使用的中文輸入法有提供標點符號,這就不會有問題,但如果你在沒有額外安裝中文輸入法的電腦(如:公用圖書館),學會野外基本求生術,其實是一件很重要的事情。

目前大部分微軟的作業系統(xp、win7),只要安裝完後,基本上都會出現新注音、新倉頡之類的輸入法,如果你沒打算安裝其他輸入法,當你需要輸入標點符號時,可以用以下方式輸入全形或半形符號。

一、如果是基本需求,如:

,。;、【】


可以左手壓著 Ctrl 鍵,右手試著敲「,」、「.」、「;」、「'」、「[」、「]」
就可以出現上面的符號。

二、如果是中度需求,如:

「『〔︹︻﹁﹃﹝[「   Ctrl+[  然後再按 ↓挑選
」』〕︺︼﹂﹄﹞]」   Ctrl+]  然後再按 ↓挑選
‘’′                Ctrl+'  然後再按 ↓挑選
‧                    Ctrl+.  然後再按 ↓挑選

二、如果是中上需求,如:

:
\↖↘﹨
|↑↓∣∥︴
±﹢≠≡≦≧
‥…←→﹉_ ̄
*×※╳﹡
︿〈《︽﹤<
€¢£¥
@⊕⊙㊣

可先按 ` 鍵一下(位於 Esc 下方,Tab 上方),
再試著敲:
Shift+;
Shift+\
\
Shift+\
Shift+=
-
Shift+8
Shift+4
Shift+2


三、重度使用者需求,如:
♠♢♣

這需要打開內碼符號表來輸入。
先按 ` 鍵一下(位於 Esc 下方,Tab 上方),
再按 U
接著輸入內碼符號。

可以參考網友所整理的內碼符號表:新注音符號表♪




2011年9月20日 星期二

處理 ASP.NET 匯出 Excel 時,檔名或內容出現亂碼



匯出 Excel 最讓人頭疼的事,就是出現亂碼,尤其是中文字的處理,還分簡體與繁體。如果碰上 big-5 沒定義的字,例如「炁」,又要開始掉頭髮了。為了讓大家擁有豐厚的髮量,路上不被人叫阿伯,整理了目前測試後有效的解決方式,早晚服用,三日見效,7天後讓你在夜市從街頭逛到巷尾都被攤販老闆喊「帥哥」!


    StringBuilder sb = new StringBuilder();
    protected void Page_Load(object sender, EventArgs e)
    {
        BindData();

        //匯出至 excel format.
        Response.Clear();
        
        string strFileName = "导出后";
        
        if(Request.Browser.Browser=="IE")
            strFileName = Server.UrlEncode(strFileName);

        Response.AddHeader("Content-Disposition", "attachment;filename="+strFileName+".xls");
        Response.ContentType = "application/vnd.ms-excel";

        Response.Write(sb.ToString());

        Response.Flush();
        Response.End();

    }

    private void BindData()
    {
        sb.Append("<html>");
        sb.Append("<head>");
        sb.Append("<style type='text/css'>");
        //將所有td的欄位格式改為"文字"
        sb.Append("td{mso-number-format:\"\\@\";}"); 
        sb.Append("</style>");
        sb.Append("</head>");
        sb.Append("<body>");
        //避免內容出現亂碼
        sb.Append("<meta http-equiv=Content-Type content=text/html; charset=utf-8>"); 
        //此處可撰寫迴圈讀取資料--開始
        sb.Append("<table>");
        sb.Append("<tr><td>炁</td></tr>");
        sb.Append("</table>");
        //此處可撰寫迴圈讀取資料--結束
        sb.Append("</body>");
        sb.Append("</html>");

    }
下載 Excel 檔名的部分,參考了保哥的建議,只針對 IE 瀏覽器進行 Server.UrlEncode()。而內容的部分,則是增加一行:

<meta http-equiv=Content-Type content=text/html; charset=utf-8>

將所有內容都以 utf-8 編碼,不再出現有些中文字無法顯示的情況。

此外,提供了 style 設定,讓匯出的 Excel 都能夠以「文字」的格式呈現,這對於有數字的欄位很有幫助。


參考:
01:ASP.NET 如何設定強制下載檔案並正確處理中文檔名的問題
02:檔案下載或開啟時出現亂碼檔名(不支援簡體)

2011年9月16日 星期五

讓 GridView 的 checkbox 狀態於分頁後還能保留


當 GridView 為每一筆資料列擺上 checkbox 時,別以為這樣對 user 很貼心喔,其實是夢靨的開始。 因為聰明的 user 在換頁後很快就會發現,前一頁有勾選的資料,在換頁之後,勾選狀態就不見了。原本你期待的是讚美與鼓勵,一夕間就變成 bug 與缺失了。想到下班後還要繼續加班改程式,所言至此 ,就不禁潸然流下男兒淚了...

不過,寫程式的最高心法就是:Copy Right (Copy is right,拷貝是對的)。往好處想,至少下次再遇到同樣的問題時,就可以不用再這麼辛苦從無到有了。如此累積下去,幾年後,每個人肯定都會身懷絕技。於是將這次解決的方法寫下來,日後再遇到同樣問題,有時間的話可以再去進一步最佳化;如果沒時間,至少也不會開天窗。 

我參考了網路上的文章,針對這問題提出兩種解決的版本,一種是從後端(server side)來處理,另一種則是從前端(client side)來處理。兩者的差別,在於勾選後是否會觸發 postback。當然,個人是比較偏好 client side 來處理,主要是因為程式碼比較簡潔、程式執行比較快速。

 ------ server side -------
說明:
將已勾選資訊存放在 List<string> lcb ,並將它透過 viewstate 來包裝。在 gridview 的 RowDataBound 事件,針對每個 checkbox 去註冊 GetPostBackEventReference(),讓 checkbox 一被勾選就會觸發 postback,同時將唯一可識別的資訊當作 postback 的參數。並於 Page_Load 攔截所 有 postback 事件,判斷是否是 checkbox 所發出,如果是,就更新 List<string> lcb 與 gridview 上 checkbox 的勾選與否資訊。

 .aspx
        <asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" 
            EnableModelValidation="True" AllowPaging="True" DataSourceID="dsData" 
            onrowdatabound="gv_RowDataBound" PageSize="5">
            <Columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:CheckBox ID="cb" runat="server" />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="id" HeaderText="ID" />
                <asp:BoundField DataField="name" HeaderText="Name" />
            </Columns>
        </asp:GridView>
    </div>
.aspx.cs
    List<string> lcb = new List<string>();

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ViewState["cbList"] = lcb;
        }

    

        string strTarget = "" + Request.Form["__EVENTTARGET"];
        string strCtl = strTarget.Split('$')[strTarget.Split('$').Length - 1];
        string strArg = "" + Request.Form["__EVENTARGUMENT"];

  
        HandleEvent(strCtl, strArg);
    }
    protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            lcb = (List<string>)ViewState["cbList"];
            CheckBox cb = (CheckBox)e.Row.FindControl("cb");           
            cb.Attributes["OnClick"] = this.ClientScript.GetPostBackEventReference(cb, 

DataBinder.Eval(e.Row.DataItem,"id").ToString());

            if (lcb.Find(x => x.Equals( DataBinder.Eval(e.Row.DataItem, "id").ToString

().Trim())) != null)
                cb.Checked = true;
            else
                cb.Checked = false;
        }
    }

    private void HandleEvent(string strCtl, string strArg)
    {
        switch (strCtl)
        {
            case "cb":
                UpdateCBList(strArg);
                break;
        }
    }

    private void UpdateCBList(string strArg)
    {
        lcb = (List<string>)ViewState["cbList"];
        if (lcb.Find(x => x.Equals(strArg)) == null)
        {
            //no match,insert
            lcb.Add(strArg);
    
        }
        else
        {   
            //match,remove
            lcb.Remove(strArg);
        }

        //final
        ViewState["cbList"] = lcb;
       
    }
------ client side -------
說明:
在 gridview 的 RowDataBound 事件,將每一個 checkbox 都加上 key 的屬性,裡面存放唯一且可識別的資訊。再透過 jQuery 為每個 checkbox 註冊勾選時都要觸發函式:UpdateHiddenValue()。在這函式裡,會判斷被觸發的 checkbox 的 key ,是否已存在於隱藏欄位 hValue (注意,必須將這隱藏欄位加上 runat="server",即使分頁後,依然可以保存 hValue 裡面的值),如果不存在,則將 key 值加入 hValue ,否則則從 hValue 裡面移除。最後,讓 DataGridView 裡的 checkbox 都隨時與 hValue 保持勾選與否的資訊同步。

 .aspx
<head runat="server">
    <title></title>
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script>
        $(function () {
            //定義 checkbox 被點選時所要觸發的動作
            $("input[id$=cb]").click(function () { UpdateHiddenValue(this.key); });

            //將隱藏欄位 hValue 的值與 DataGridView 的 checkbox 作對應更新
            $("input[id$=cb]").each(function (i) {
                if ((',' + $("input[id*=hValue]").val()).indexOf(',' + $(this).attr('key') 

+ ',') > -1) {
                    //已存在,將 checkbox 打勾
                    this.checked = true;
                }
                else {
                    //不存在,將 checkbox 勾選取消
                    this.checked = false;
                }
            });
        });


        function UpdateHiddenValue(strInput) {
            if ((',' + $("input[id*=hValue]").val()).indexOf(',' + strInput + ',') > -

1) {
                //已存在,將輸入的值從隱藏欄位 hValue 移除
                var v = ',' + $("input[id*=hValue]").val();
                v = v.replace(',' + strInput + ',', ',');
                v = v.substr(1, v.length - 1);
                $("input[id*=hValue]").val(v);
            }
            else {
                //未存在,將輸入的值加入隱藏欄位 hValue 
                $("input[id*=hValue]").val($("input[id*=hValue]").val() + strInput+',');
            }          

        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" 
            EnableModelValidation="True" AllowPaging="True" DataSourceID="dsData" 
            PageSize="5" onrowdatabound="gv_RowDataBound">
            <Columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:CheckBox ID="cb" runat="server" />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="id" HeaderText="ID" />
                <asp:BoundField DataField="name" HeaderText="Name" />
            </Columns>
        </asp:GridView>
        <input type="hidden" id="hValue" runat="server" />
    <asp:XmlDataSource ID="dsData" runat="server" DataFile="~/data.xml">
    </asp:XmlDataSource>
    <div>
    
    </div>
    </form>
</body>
.aspx.cs
    protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            CheckBox cb = (CheckBox)e.Row.FindControl("cb");           
            cb.InputAttributes["key"] = string.Format("{0}", DataBinder.Eval

(e.Row.DataItem, "id"));
        }

    }
參考:
01:利用ASP.NET的HIDDENFIELD記錄GRIDVIEW的CHECKBOX狀態,並且加入全選、取消全選、分頁保留CHECKBOX狀態,達到類似GMAIL的郵件清單功能
02:GridView 欄位 CheckBox 全選及取消全選
03:測試程式下載

2011年9月15日 星期四

玻璃罐打不開怎麼辦?


記得以前分享過如何處理超級難開的玻璃罐頭,那時候我只用吹風機吹一下瓶蓋,就可以輕鬆打開了。但今天還真的讓我遇上狠角色了,不開就是不開。正當我要學劉備摔阿斗的那一幕時,突然想起:「一天一 Google ,百萬 g 民站起來」的廣告。還真的找到一篇「罐頭打不開怎麼辦」的文章,裡面有提到用門板夾著的方式,自己跟廁所的門板夾了許久,還是打不開。最後在抽屜看到一個開罐器,拿著尖銳的一邊用力去扳瓶蓋較大的縫隙處,聽到「啵」的一聲後,就可以輕鬆旋開蓋子了。


雖然一開始會擔心蓋子會不會因此而不能使用,但其實只要力道控制好,只需讓空氣流進玻璃罐內,就可以輕鬆打開了。目前我看了一下我的蓋子,是沒有發現有嚴重變形的地方。

參考:
01: 罐頭打不開怎麼辦
02:很難轉開的玻璃罐頭

2011年9月7日 星期三

喔,是這樣嗎?



在職場上,有時不免碰到處處跟你作對的人。近日一個朋友也是面臨如此困境,對方老是找他麻煩,即便茶水間狹路相逢,擠著笑臉跟對方打招呼,人家還把你當空氣一樣視而不見。我這朋友三天兩頭的為此大生悶氣。

最近剛好看到一篇白隱禪師的事蹟,一方面說給朋友聽,其實也是說給自己聽。


白隱禪師是一個過著純潔生活的人。

鄰居中有一位美麗的女孩,美麗的女孩未婚懷孕了,她的父母非常生氣;就嚴厲的逼問女孩的生父是誰?

女孩因為深怕父母譴責,於是說出了白隱禪師名字。

不明真相的父母聽信女兒讒言,抱著剛生下的嬰兒,扔給白隱禪師並說道:「你這個敗壞佛門清規戒律的假和尚,以前我們沒有看清你的醜惡面目,蒙受你的欺騙。沒想到你竟然作出如此禽獸不如的勾當,這是你的兒子,你拿去吧!」。白隱禪師聽完後,只是說了一句:「喔,是這樣嗎?」,就默默地接過孩子了。

此時的白隱禪師已經名聲掃地,然而他自己並未因此而受到干擾;仍然默默忍受著種種白眼非議;獨自準備孩子所需的一切東西,並細心照料這個幼小的生命。

一年以後,年輕的媽媽良心倍受痛苦的煎熬,她不能再忍受人們對白隱禪師的不公平待遇,終於向父母坦白了一切,說明孩子真正的生父是村外的一個年輕人;她的父母親得知真相後大吃一驚,立即去找白隱禪師,向他表示深深的歉意,誠懇的請求她的寬恕,並將孩子領回。

白隱禪師把孩子送還給他們時,只輕輕的說了一句:「喔,是這樣嗎?」


《入菩薩行論》云:「罪惡莫過瞋,難行莫勝忍,故應以眾理,努力修安忍。」對於佛教徒來說,白隱禪師的安忍境界已經深到不可思議的地步。但對於我來說,第一次的「喔,是這樣嗎?」,聽起來有點懦弱無能的感覺。直到真相大白後,第二次所說的「喔,是這樣嗎?」,真的有重重一巴掌打在我臉上的感覺。不過是這麼一句平淡的話,其展現的力道,還真的是「柔弱勝剛強」哩。

2011年9月4日 星期日

生命的恆沙


水,本是清淨、無染。生命的初始,亦何嘗不是。從一個生命停留於一個身體開始,就好像將水開始注入一個杯子,隨著時間的推移,注入杯子裡的水也就慢慢變多了。

人與非人之間的差異,在於懂得思考,但同時也因為思考而讓每個人存在著太多的相異性。眼睛所見,耳朵所聽,鼻子所聞,舌頭所嚐,身體所感受,絕對每天不同、每人不同、每次不同。


「坐井觀天」、「三人成虎」、「瞎子摸象」的故事,告訴了我們眼見不能為憑、耳聞不能成真、所知並非全貌的道理。很多小朋友小時候很怕黑,是因為他們把原本無害的東西視為妖怪野獸,即便是一件衣服掛在昏暗的角落裡,他都會生起無比的恐懼感。

當你接受了負面的訊息,就像是將一粒沙放進了你的水杯。多年之後,原本清澈的水杯,早已不知累積了多少沙子。直到有一天,你的心緒已無法獲得寧靜時,才赫然發現你的那杯水,正因被攪動而混濁不已。有人建議你,時間是療傷良藥,但其實並不是如此,留下沙子的水杯,不管加注再多的水,沙子依然存在。唯一你能做的,就是讓杯子安靜下來,待沙子沈澱之後,即可再見水的清澈。或許你會問,那裡頭的沙子怎麼辦?如何徹底把它們清乾淨呢?這問題問得好,而答案是永遠不可能清除乾淨。試問,你過去所做過的事,犯過的錯,今天可以抹煞掉它嗎?即便是經過五年、十年之後,過去所發生的事,依然不可能憑空消失,這樣的道理,你就應該可以理解為何無法消除杯子裡的沙了。

而我們也毋需因此而難過,因為身邊周遭的人,乃至大部分的人,都存在著相同的問題。若是如此,你所擔憂的就不再是如何去清除沙子,而是如何讓水杯靜下來,讓沙子上面再次呈現水的清淨與無染。

這很難嗎?可以說是,也可以說不是?於「觀照身體.修復心靈」一書有個例子可分享:

有一個小男孩在沙灘上玩耍。尚未漲潮時,他用沙子堆了一座有護城河的城堡。開始漲潮時,起初的海浪都會剛好流進護城河。小男孩也因此感到自豪且開心。但隨著潮水越漲越高,最終還是把他的城堡給沖毀了,最後留下來的,只剩下擺著臭臉直跺腳的小男孩。

幾公尺外的沙灘上,也有一個小女孩在玩同樣的遊戲。但當她的城堡被沖毀時,掙扎的情緒並沒有維持很久,因為她開始發現了新玩法。每當潮水退去,她就馬上在地上挖洞,當海水再次湧上來,她看著海水如她所料的一一填滿這些坑洞,她就覺得很開心。

生命本是無常,既是無常,又何須執著呢?靜下來看看自己的杯子,面對生命的恆沙,你在乎的是裡頭的沙,亦或清淨無染的水呢?

各種宗教教義,皆不離「與人為善,修福修慧」。你今日做一善行,生命的水杯即會掉入一顆七彩琉璃,累積越多善行,琉璃的數目就越多。日後端視水杯時,見到沙子裡點綴者好多七彩琉璃,就會心生好歡喜。此外,也有另一派人,強調持戒斷惡,讓過往所留下的沙,就此停住,冀望日後所得唯有清淨無染。更甚者,有人既做善行,也恆持戒。言至於此,如此看待人生,「累不累啊」?

水,不因一粒沙,而改其清淨無染的本質。
水,不因一琉璃,而改其清淨無染的本質。
水,不因外相的混濁,而改其清淨無染的本質。

如果你能明瞭水的本質,不管你是看杯子裡的沙,還是杯子裡的水,終究也都是清淨無染的。大家都曾聽過六祖的傳世之句:

「菩提本無樹,明鏡亦非台,本來無一物,何處惹塵埃」。

以古照今,其華不減。聖人前賢有其大智慧,而我凡夫豈能不起效尤?

近日有幸重讀「古今背書方法」,有段與我相應的話:

「余嘗謂讀書有三到:謂心到、眼到、口到,心不在此,則眼不看仔細;心眼既不專一,卻只漫浪誦讀,決不能記,記亦不能久也。三到之法,心到最急,心既到矣,眼口豈不到乎!」

為學,為人,為事之本,存乎一心,若能修習「心如止水」的功夫,則塵土必落,靈台也能獲得清明。

參考:
01:古今背書方法(宋 朱熹 朱子童蒙須知)
02:「觀照身體.修復心靈」。瓊恩.波利森科(Joan Borysenko),出版社:張老師文化

2011年9月1日 星期四

讓我們擠在一起


越來越多美編喜歡用 DIV 來設計樣板,不像我們傳統工程師,都是用 Table 去 layout 畫面。或許在未來新的瀏覽器裡,對 CSS 的支援更強大、更統一之後,以 DIV + CSS 為設計的方式將會越來越普遍。但將來的事,現在說什麼都還算太早,眼下我先搞定如何將兩個 DIV 放在同一列比較重要。

原先我都以為使用 DIV ,就一定會佔用一行的空間。沒想到透過 {float:left;} 的 CSS 定義後,就可以讓好幾個 DIV 擠在一起。

參考一下 HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title></title>
<style>
.oneline
{
float:left;
}

div{
border-width:1px;
border-color:red;
border-style:solid;
border-color: #336699;
padding:1px;
}

</style>
</head>
<body>
<div style="padding-top:30px" class="oneline">元素A</div>
<div class="oneline">元素B</div>
<div style="clear:left;">元素C</div>

</body>
</html>
透過 float:left ,讓元素A、元素B 都擠在同一列。但如果希望這行為不要發生在元素C,則可以透過 clear:left 來結束。

此外,除了使用 float:left 之外,還可以用 display:inline; 來達到擠在同一列的效果,差別在於 display:inline 會有靠下對齊的效果,而  float:left 則是靠上對齊。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title></title>
<style>
.oneline
{
display:inline;
}

div{
border-width:1px;
border-color:red;
border-style:solid;
border-color: #336699;
padding:1px;
}

</style>
</head>
<body>
<div style="padding-top:30px" class="oneline">元素A</div>
<div class="oneline">元素B</div>
<div style="clear:left;">元素C</div>

</body>
</html>
參考:

1.關於CSS DIV並排的問題
http://www.lslnet.com/linux/f/docs1/i30/big5240138.htm

2.CSS display 屬性用法介紹 display:block 與 display:inline
http://www.webtech.tw/info.php?tid=37

3.Float vs. Inline-Block
http://www.ternstyle.us/blog/float-vs-inline-block