2010年5月12日 星期三

SyntaxHighlighter 讓文章的程式碼顯示行號

常常看到有些網友的文章,有關程式碼的段落都可以處理得很漂亮,原來是有個SyntaxHighlighter 好幫手。可以直接到 http://alexgorbatchev.com/wiki/SyntaxHighlighter 網站下載完整程式來測試一下。而以下則是一段簡單 Demo :

function getValue()
{
  var i=0;
  i=i+1;
  alert(i);
  
}  

套用了SyntaxHighlighter  JS 後,只需在想要呈現效果的地方,加上 <pre class="brush: html"> ... </pre>,就可以很輕鬆的完成,只是要等一會兒時間,效果才會出來,可能因為要下載比較多的 js 與 css 檔,所以沒有這麼即時。

接著紀錄自己修改 blogspot 的步驟。
1. 點選右上角的[自訂],並進入[版面配置],選擇修改 HTML。

2.在修改範本裡,找到 <head> 標籤,並在裡面加上以下程式:

<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css'  rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'></script>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
</script>

3.最後按下「儲存範本」,如此,日後只要使用<pre class="brush: html"> ... </pre>,就可以出現顯示行號的效果了。

以前曾經介紹過 Blog 文章中貼程式碼,現在再推薦另一種顯示方式,可以多多比較。

【補充20101001】
在上述範例中,我過於信任作者每次 release 的版本應該是最新最好的,所以我都是參考他 current 的版本。但沒想到作者釋出 3.0.83 版後,畫面真的有點怪,行號出現的位置似乎都會亂掉,但發現許多網友使用舊的版本 2.x 版都還蠻穩定的,所以後來自己將原先使用 current 改為指定舊的版本 2.1.382 ,反而比較美觀。

可以參考作者歷次 release 的版本:
http://alexgorbatchev.com/SyntaxHighlighter/hosting.html


【補充20120214】
補充一篇德瑞克的說明。請參考:

接 store procedure 的回傳結果

如果已經有人寫好了一支共用 store procedure,他回傳值可能是:

欄位A   欄位B   欄位C
====     ====     ====
A001     A002    A003
B001     B002    B003
C001     C002   C003

那我們可能會建一個暫存資料表
去接收 stroe procedure 的回傳值。

create table #tmp ( fieldA  nvarchar(max), fieldB nvarchar(max), fieldC nvarchar(max) )

insert into #tmp ( fieldA, fieldB, fieldC)
exec mystoreprocedure

然而,如果共用的 store procedure 回傳了30 幾個欄位,如果用上述方法,就得建立一個30幾個欄位的暫存資料表。這作法真的會讓人很無力,且容易發生「 An INSERT EXEC statement cannot be nested 的錯誤訊息[注3]」。所以這情況,可以考慮 OPENROWSET[注1] 來完成。雖然共用的 store procedure 回傳了30幾個欄位,但我真正會使用的,可能只有其中二、三個。所以可以寫成:


SELECT com_empno,com_cname FROM
OPENROWSET('SQLOLEDB',
'.';'sql_account';'sql_password',
'exec swapdb.dbo.pr_Find_ITRI_BossID')

此外,有個重要的地方需注意,就是使用  OPENROWSET 時的查詢字串,一定要「常數」,不可以是「變數」。因此,如果你的共用 store procedure 需要傳參數進去,則不可以將查詢字串寫成  'exec swapdb.dbo.pr_Find_ITRI_BossID  '+@seqsn   (參考[注2])

如果遇到需要傳參數的 store procedure,則可以透過先宣告一個字串變數( declare @str),來組出 OPENROWSET 的所有指令,最後再用 exec 去執行它 ( exec (@str) )來完成,這樣就可以避開 OPENROWSET 的查詢字串,一定要「常數」的限制。



參考:
[注1]OPENROWSET (Transact-SQL)
[注2]OpenDataSource、OPENQUERY、OPENROWSET用法
[注3]An INSERT EXEC statement cannot be ne...
[注4]感謝 Ken 熱心指導

2010年5月1日 星期六

工作病

常見的工作病:

「推」:遇到棘手事情,都推給別人。
「拖」:沒有執行力,老是愛拖延。
「怕」:害怕不熟悉的事物,缺乏膽識。
「蓋」:明明自己沒出半點力,卻都吹噓是自己的功勞。
「爽」:只顧自己爽快,不會替他人想想。


藥方一:在時間體力可負荷之下,樂當「Yes Man」。
藥方二:列出你的待辦清單,從最不想做的事情開始動手。
藥方三:功不唐捐。今天你的努力,會是明天你的資產。
藥方四:你今天撒一個謊,明天會用更多的謊言來掩飾今天的行為。
藥方五:心裡放不下別人,是沒有慈悲;心裡放不下自己,是沒有智慧。

仔細想想,自己好像也得了一些工作病了ㄟ...
這五種病,好像跟燙傷處理的 沖、脫、泡、蓋、送 很相似。

2010年4月28日 星期三

透過 CSS 讓列印時 Table 的標頭內容可以每頁重複

希望透過 CSS 在使用 window.print() 時,列印出來的 Table 內容(假設資料量很大),可以在每一頁都能重複標頭(Header)內容。首先,可以使用 CSS 裡的 page-break-before: always,可以強迫換頁。所以,我在範例中定義了:

<style type="text/css">
.newpage
{
page-break-before: always; 
}
</style>

假設我目前的 Table 內容如下:

<table border="1" id="tbDemo" >
  <thead>
  <tr><th id="pageHeader">編號</th></tr>
  </thead>
  
  <tbody>
  <tr><td>1</td></tr>
  <tr><td>2</td></tr>
  <tr><td>3</td></tr>
  <tr><td>4</td></tr>
  <tr><td>5</td></tr>
  <tr><td>6</td></tr>                             
  </tbody>
</table>    
接下來,使用 jQuery 讓 Table 每兩筆資料(實際上是情況而調整筆數設定)就自動產生一個標頭內容,且將這標頭內容套用剛剛加入的 CSS 設定。

<script>
$(function(){

var $rows=$("#tbDemo > tbody > tr");  
$rows.each(function(i) {
//取2的倍數,排除最後一筆
if((i+1) % 2==0 && i!=($rows.size()-1))
{
   $(this).after("<tr class='newpage'><th>"+$("#pageHeader").text()+"</th></tr>");      
}
})
})
</scrip>

如此,在使用預覽列印時,就可以看到以下每兩筆資料一頁且有標頭的結果:

原本以為,故事這樣就結束了,但...唉,看一下 FireFox 的結果~

在 FireFox (ver 3.6.3) 的標頭檔,卻重複了兩次。主要原因,是因為我的 Table 定義,用了 <thead> 與 <tbody> 的樣式。在 FireFox 裡,如果遇到換頁的時候,他會自動為每一頁的 Table 內容加上 <thead>  ,而我剛剛又手動用 jQuery 新增了一次,所以才會得到這結果。換言之,使用 FireFox 的瀏覽器,只要你的 Table 內容有用<thead> 與 <tbody> 的樣式,那每一頁自動都會幫你加上標頭喔。只是,目前我真的不希望他主動幫我加。

此時,或許加上判斷瀏覽器的程式,來決定是否要使用 jQuery 來手動增加標頭,會是一個辦法。但,我沒有這麼做。我索性就不用<thead> 與 <tbody> 的樣式。我將 Table 的定義改成以下:

<table id="tGen"  border="1" >
<tr class="trHeader"><td>編號</td></tr>
<tr class="trBody"><td>1</td></tr>
<tr class="trBody"><td>2</td></tr>
<tr class="trBody"><td>3</td></tr>
<tr class="trBody"><td>4</td></tr>
<tr class="trBody"><td>5</td></tr>
<tr class="trBody"><td>6</td></tr>
</table>

而 jQuery 也調整如下:
<script>
$(function(){
 var $rows=$("#tGen tr[class=trBody]");  
   $rows.each(function(i) {
   //取2的倍數,排除最後一筆
  if((i+1) % 2==0 && i!=($rows.size()-1))
  {     
      $(this).after("<tr class='newpage' ><td>"+$("#tGen tr[class=trHeader]").text()+"</td></tr>");
  }
   })    
});   
</script>

而最後出來的結果,就皆大歡喜了。

文章參考:
MEMO-網頁列印強迫分頁
CSS page-break-before Property
.after()
web打印中如何强制分页
Printing Tables
Printing Headers

測試程式下載:
https://sites.google.com/site/paladinsharefiles/home/filelist/RPT.zip?attredirects=0&d=1

使用 css 的 @media 控制列印樣式

想讓目前正在瀏覽的網頁直接列印出來,同時希望有些按鈕或控制項在列印時隱藏,以前我都會用 javascript 去隱藏列印時不想出現的物件。但當我看了 CSS Media Types 這篇文章後,真的就有不一樣的想法了。原來可以透過 css 裡的 media="screen" 或 media="print" 來宣告是要在螢幕上面顯示,還是只有在列印時顯示。

範例程式:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Print Friendly</title>
    <style type="text/css">
        
   .button
   {
   text-align:center;
   color:#00B3ED;
   border:1px solid #BBBBBB;
   background-color:#F0F0F0;
   line-height:12px;
   padding:4px 0px 0px;
   width: auto;
   font-size: 12px;
   }
          
    @media print 
    {
        /* 列印將物件隱藏 */
        .button { display: none; } 
    }
    </style>
    
</head>
<body>

<input type="button" id="btnPrint" value="列印" class="button" >
網頁列印
</body>
</html>

我在 style 裡面,定義了 .button  的樣式,但接著在 @media print 指定列印時,.button 的額外設定,也就是要隱藏所有有套用 .button 樣式的物件。

下圖是範例程式的執行結果,可以發現,在預覽列印時,畫面上的「列印」按鈕已經消失了。透過 CSS 來完成這功能,不管是使用瀏覽器選單選列印、預覽列印或Ctrl+P,都可以適用。



最後,附上一張沒有使用@media print 指定列印的結果,以供比較。可以看出在預覽列印時,畫面上的「列印」按鈕跑出來了。


參考文章:
活到老學到老-CSS Media Types

2010年4月23日 星期五

update from join

最近在寫一段 SQL,好不容易 join 了好幾個 table 之後,最後一個步驟就是要更新資料表。但是真的可以在 join table 裡面使用 update 嗎?還好,真的可以。


一個簡單範例:有兩個 資料表 #tmpA , #tmpB 讓他們 left join 起來

select * from #tmpA A
left join #tmpB B
on A.t_id=B.t_id
今天我希望針對 paladin 那筆紀錄,把 t_phone 欄位 用 t_name 取代。可以用以下的寫法:

update #tmpB 
--修改電話資訊
set #tmpB .t_phone=convert(nvarchar(max),A.t_name)
from  #tmpA A
left join #tmpB B
on A.t_id=B.t_id
where  A.t_id=1 --限定只改 paladin 

執行後的結果:


參考:http://www.dotblogs.com.tw/dotjum/archive/2008/06/23/4367.aspx

2010年4月21日 星期三

強迫GridView出現分頁

使用 GridView 時,如果有設定使用「分頁」功能,就會自動出現分頁效果。但你可能會發現,如果你的資料筆數少於你設定的 PageSize (預設是 10) 時,自動分頁的效果就消失了。或許這並不會有什麼影響,但如果你堅持即便是只有一筆資料,也要將分頁效果呈現的話,可以根據以下步驟來解決。

1.改寫 GridView 的 PreRender 事件
2.針對 BottomPagerRow,設定顯示狀態






protected void GridView1_PreRender(object sender, EventArgs e)
    {
        GridView gv = sender as GridView;
        if (gv != null)
        {
            GridViewRow gr = gv.BottomPagerRow;
            if (gr != null)
                gr.Visible = true;
        }

    }

參考:http://blog.sumantdubey.com/post/ASPGridView-making-Pager-always-visible.aspx