2012年7月10日 星期二

檢查DWG檔版本小程式


我寫了一支小程式方便自己用來檢查DWG檔版本,分享給大家使用。
作法很簡單就是打開DWG檔取前六碼,判斷版本。人懶~~科技始終來自人性,哈哈!

電腦需要安裝.net framework 2.0,我想WinXP SP3以後OS版本應該內建都有,若沒有,請Google找一下或到微軟官網下載安裝。


只有執行檔

執行檔含原始碼(c#)

p.s.請點壓縮檔名下方「檔案」->「下載」,以下載整個壓縮檔。

---
Welly

2012年6月26日 星期二

AutoCAD開發人員手冊英文版

Autodesk原廠在2012版以後只維護Online Help。
官網Online Help:
http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=12272439&linkID=10809853
----------
官網上最後一版(2011版)Offline Help(*.chm)下載點,但此檔只有操作說明,沒有附開發人員相關文件:
http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=15068206&linkID=9240618
----------
為方便自己系統開發,我將AutoCAD 2010開發人員手冊英文版,網上找到壓縮檔後,另存到我自己Google Cloud Driver。
檔案明細如下:
The acad_dev180.chm is in a folder which, to be complete, must also contain :
- acad_aag.chm (this one contains the ActiveX/COM/VBA Developer's Guide)
- acad_acg.chm (this one contains the Customization Guide)
- acad_alg.chm (this one contains the AutoLISP Developer's Guide)
- acad_alr.chm (this one contains the AutoLISP Reference Guide)
- acad_alt.chm (this one contains the AutoLISP Tutorial)
- acad_acg.chm (this one contains the AutoCAD User's Guide)
- acad_dxf.chm (this one contains the DXF File Format Docs)
- acad_sso.chm (this one contains the Sheet Set Object Reference)
- acadauto.chm (this one contains the ActiveX/COM/VBA Object Model Reference)
現分享給網友下載:
https://docs.google.com/open?id=0B0K1KBjQFbftYUd1NlVrWHBscXc
----------
Autodesk原廠文件(*.chm),2MB左右,大陸網友將其翻譯成簡體中文字,右方說明頁面會有廣告。
我放在我Google Cloud Driver,不喜歡大陸文件的版友請勿下載。
https://docs.google.com/open?id=0B0K1KBjQFbftRGZGTEIwUkRlZjg
上述文件官方原文網址:
http://exchange.autodesk.com/autocad/enu/online-help/browse#WS73099cc142f48755a52158612bd434e551-7fd5.htm
----------

Welly Lin

2012年6月13日 星期三

T-SQL 分頁從資料庫就做好 Row_number()

SQL 2005之後才有的Row_number()這個Function可以用來做分頁. 從一些參考網站所做的效能評比中,也算是效能數一數二的做法.

以下就是說明Row_number()的基本做法:
select a.UserName,a.UserID
from
(select
  row_number() over (order by UserID) as UID,
  UserName,
  UserID
 from UserDataInfo
 where bmi>20) as a
where a.UID between @SP and @EP

這段語法就是關鍵所在,正常來說,上面的語法只有紅字部份,帶出所有bmi>20的人員,一次把資料全部回傳,但這裡卻多了一段藍字在裡面,Row_Number()就是將符合條件的結果,再從1開始,依序給予編號,所以回傳的結果就會是
UID     UserName     UserID
1          Jeff                   A0001
2          Jerry              C0014
3          Judy               C0096
4          Mark               D0002
5          Jason               D0010
6          Rober               D0011
7          Martin            D0022
所以黑色部份的語法,就依這個的查詢結果,取出UID介於幾號到幾號之間. 所以就可以在DataAccess端,依據設定的PageSize,來算頁次,再依目前的頁次與PageSize去帶回所需顯示的資料範圍.

如果不分頁的話,一次載入上萬筆資料是很可怕的,尤其是透過2M/256K的頻寬,這是ERP系統,不是P2P下載平台,使用者不可能等,如果用分頁方式,就只會一次傳回指定的筆數,大幅的減少網路的負擔,而且這是在DB就做好的動作,所以從DataBase到WebService這段的網路問題也解決了.

這做法也不是沒有缺點,例如在換頁過程中,突然又有幾筆資料符合或不符合了,其順序就會異動,就有可能剛好在換頁時,某筆資料會沒看到,可能跳到前頁或下頁去了. 這部份就看各家使用者了.

以上文章節錄自:Jeff隨手記 http://www.dotblogs.com.tw/jeff-yeh/archive/2008/04/08/2614.aspx

2012年6月7日 星期四

C# 存取修飾詞 public, protected, private, internal, protected internal 的區別


public
型別或成員可由相同組件或參考該組件的另一個組件中的任何其他程式碼存取。
protected
型別或成員只能由相同類別或結構中,或是衍生類別中的程式碼存取
private
型別或成員只能由相同類別或結構中的程式碼存取。
internal
型別或成員可由相同組件中的任何程式碼存取,但是不包括其他組件中的程式碼。
protected internal
型別或成員可由相同組件中的任何程式碼,或是其他組件中的任何衍生類別存取。



節錄自:

2012年6月1日 星期五

C# 繼承


要 C# 中做到跟 Delphi 以下 inherited 一樣效果,C#作法測試說明:

type
  TfrmPrnSuCount1 = class(TfrmPrnList)
:
:
procedure TfrmPrnSuCount1.QuickRep1BeforePrint(Sender: TCustomQuickRep;
  var PrintReport: Boolean);
begin
  //此指令,會呼叫 基底Form 
  //frmPrnList.QuickRep1BeforePrint()執行後
  //再回來往下執行
  inherited; 

  case g_iMode of
    0:  //全部列印
    begin
      QRLabel5.Caption:= '列印範圍:全部列印';
    end;
    1:  //日期範圍
    begin
      QRLabel5.Caption:= 
        '列印範圍:'+ 
        C_StoC(g_sBdate)+ '~'+ 
        C_StoC(g_sEdate);
    end;
  end;
end;


------------------------------
使用了 Virtual 配合 Override 的變通應用


namespace GISTools
{
    //基底Form frmAsk
    public partial class frmAsk : Form
    {
        public frmAsk()
        {
            InitializeComponent();
        }


        //確定按鈕
        public virtual void btnOk_Click(object sender, EventArgs e)
        {
            //btnOk.DialogResult = DialogResult.OK;
            MessageBox.Show("ASK 基底Form!!");
        }
    }
:
:
    //繼承Form frmM301, 繼承自frmAsk
    public partial class frmM301 : GISTools.frmAsk
    {
        public frmM301()
        {
            InitializeComponent();
        }


        //確定按鈕
        //三種不同結果測試
        //第一種:只會秀"ASK 基底Form!!"
        //new public void btnOk_Click(object sender, EventArgs e)
        //{
        //    MessageBox.Show("M301 World!!");
        //}




        //第二種:只會秀"M301 World!!"
        //public override void btnOk_Click(object sender, EventArgs e)
        //{
        //    MessageBox.Show("M301 World!!");
        //}




        //第三種:會先秀"ASK 基底Form!!",
        //      再秀 "M301 繼承Form!!"
        public override void btnOk_Click(object sender, EventArgs e)
        {
            //因為基底frmAsk.btnOk_Click()用了Virtual, 
            //無法再用static, 故要先把物件實體化才能用
            frmAsk frmAsk1 = new frmAsk();  
            frmAsk1.btnOk_Click(sender, e);
            frmAsk1.Dispose();


            MessageBox.Show("M301 繼承Form!!");
        }
    }
}

---
Welly

2012年5月12日 星期六

.NET使用NPOI Library開發Server端不須安裝Office但能存取Office檔案程式


在 Server 端存取 Excel 檔案的利器:NPOI Library



Codeplex 軟體套件(Package)資訊
套件名稱NPOI
作者tonyqus, huseyin, atao
目前版本1.2.1 Stable(正式版)
URLhttp://npoi.codeplex.com/
使用難易度
使用此套件時可用的輔助工具Visual Studio 2008
POIFS Browser 1.2
基礎知識基本物件導向。
Excel 基礎操作。

在 Server 端控制 Excel 的難處

在今日 Microsoft Excel 被廣為業界接受之際,Excel 已幾乎是每個人必會的工具,不論是在校園或是職場,接觸到 Excel 的機率很高,而且 Excel 靠著簡單易用以及高度容錯的能力,讓使用者可以近乎無痛的操控 Excel,它內建的強大試算以及資料整理的功能,也讓很多使用者樂於使用它,這一點由 Excel 的高市佔率得以印證,用 Excel 來整理與包裝資料已經是司空見慣的事,因此很多的使用者會利用它來處理日常的業務資料或是基本檔等等,不過這可就苦了 IT 人員了。
在論壇上經常會看到一種需求,因為使用者不論如何都要用 Excel 檔來放資料,所以總是要求 IT 人員在系統中直接產出 Excel 檔案直接下載給使用者,目前由官方公布,由伺服器端存取 Excel 表格兩種方法:

2012年4月19日 星期四

看完這篇文章,也許對人生想法會不一樣...


看完這篇文章,
也許對人生想法會不一樣......



記得小時候,我很憧憬長大。

因為我覺得等長大了,父母就再也管不著我了。

可以想喝汽水就喝汽水,

中午想不睡覺就不睡覺,那一定很幸福。

等我真的長大,父母也的確管不著了,

可是當初認為的幸福並沒有到來。

因為,雖然沒有人再管我喝汽水,

但我發現當初那個理想太微不足道。

而且,在得到這個微不足道的自由的同時,

又有了新的更大的不自由。

比如說:八點上班,

哪怕遲到5分鐘,老闆也要給臉色看。

而且那個臉色,比小時候父母的難看得多。

於是,我反而開始懷念

小時候那無憂無慮的生活,

覺得那似乎才是幸福。

同時,又開始了新的憧憬:

什麼時候才能實行彈性的工時,

那一定是很幸福的,

可以想睡到幾點就睡到幾點,

再不用被鬧鈴驚醒好夢,

再不用連臉都不洗、牙沒刷,

就往辦公室狂奔。

若干年後,終於實現了彈性的工時。

不僅如此,隨著自己混成資深人員,

可以想幾點上班就幾點上班,
哪怕在家辦公也沒人說你。



可是我發現,

當初期望的幸福又跑得無影無蹤。

因為,隨著年齡的增長,

沒有鬧鈴,早上也沒了睡懶覺的福氣。
甚至天不亮就醒來,

無所事事的瞪眼到天明。

雖然沒人再要求你,

可是按時起床、工作卻成了習慣,

彈性工時與幸福哪有什麼關係!

回憶幾十年的工作經歷,

我還發現,每換到另一個單位時,

都會有一個感覺令人討厭的主管,
往往都會找我的麻煩。



於是,每每總是希望這個主管調走,
並固執地認為:只要這個人調走,

工作就會很開心。

有幾次,他不走我走,

此處不留爺,自有留爺處。

可是,每一次都會發現,無論到哪,

各形各色的和我作對的主管都如影隨形。

於是又開始憧憬:哪天媳婦熬成了婆,

到我能說了算,不用再受主管的氣,

那一定很幸福。

若干年後,終於熬出了頭:

自己當上高級主管,可以頤指氣使,

讓別人看我的臉色了。

可是我發現,當初渴望的幸福還是沒有來。

因為,雖然沒有人再對你說三道四,
但是,怎麼什麼責任都要我負,

大事小情都要我拍板,心怎麼這麼累呢?

而且,周邊的人怎麼都變得如此虛偽,

自己放個屁,別人都會說香。

於是,天天開會、應酬、聽彙報、佈置工作,

忙得像個陀螺一樣的我,又開始新的憧憬:
哪天能夠活得悠哉遊哉,

不用再管那麼多事,

想釣魚就釣魚,想打牌就打牌,

不 用再看那麼多虛偽的面孔、

聽那些肉麻的假話、看那些枯燥的檔案,

那才是幸福。

光陰似箭,轉眼退休了,

真的再沒有人要我負任何責任,

當初煩人的電話也不再打來,
門庭也真的冷落到鞍馬稀,

所有時間都屬於了自己,

我卻發現,當初渴望的幸福,

哪裡是什麼幸福?

簡直就是人走茶涼的冷落和無盡的孤獨。

於是,一個人坐在殘陽下,

開始思考人生:

我這一生,從小到大,從大到老,
都覺得如果怎樣,明天就會得到幸福,

可為為何在一個個願望實現後,

幸福依舊沒有來?

這時候,才算真正明白了一句話:



“過去心不可得,未來心不可得。”

一切其實盡在當下。

如果你覺得現在不幸福,

總覺得改變了才是幸福,

或者過去了的才是幸福,
那麼恐怕一輩子都難有真正的幸福感!

不是嗎?未來的還沒有來,過去的已經過去。

如果每一個當下,

我們不抓住,不去認真對待,

總想著看不見的明天或已經遠去的昨天,
我們就會永遠生活在緊張和失落中。

隨著生命一點點溜走,

到頭來留下的只能是三個字:“空悲切”。

所以,

如果想知道20年後會不會幸福,

就個人心態而言,
看看現在的狀態就可以知道:



如果你當下感到幸福,

20年後也應該會幸福;

如果你有太多的東西寄于明天,20年後,

這些願望無論是否實現,

你都可能不會感到真正的幸福。

幸福就在當下,

就在你手中的每一天,甚至每一刻,

而絕不在過去或者未來。

2012年4月10日 星期二

Google Chrome 搜尋結果靠左顯示

有時候不知按到那些鍵或設定到什麼, Google Chrome 搜尋結果會變成「置中」顯示。

若想要回復成預設值「靠左」顯示,可在Google Chrome 畫面上右上角,
按下「小板手」圖示,進入選像設定畫面,
左手邊功能選單中選「進階選項」
 -> 按下「內容設定」按鈕
 -> 按下「所有 cookie和網站資料」按鈕
 -> 在 cookie和網站資料 畫面右上角「搜尋 cookie」格位中,打入「google」字樣,找出與 Google 相關 cookie,然後將之刪除,儲存設定
 ->關閉 Google Chrome
 ->再次開啟 Google Chrome 即可。

---
Welly

2012年2月5日 星期日

ASP.NET 使用MasterPage跨網頁傳遞參數問題

一般跨網頁傳遞參數,很簡單到很多書都不講,大致有五種方法。
以送出頁為SendToB.aspx,接收頁為RecvFromA.aspx為例。

1.透過Http Html Form Get:
    送出頁:Response.Redirect("~/RecvFromA.aspx?id=" + TextBox1.Text);
    接收頁:string sId = Request.QueryString["id"];
    ◎通用性最佳,但不宜傳送可能有資訊安全疑慮之參數,且要注意參數編碼與轉碼問題。

2.透過Http Html Form Post:
    送出頁:Response.Redirect("~/RecvFromA.aspx"); 或使用 Button的PostBackUrl屬性填入~/RecvFromA.aspx。
    接收頁:string sId = Request.Form["id"];
    ◎通用性次佳,但在Master Page下無效。

3.透過ASP.NET PreviousPage:
    送出頁:Response.Redirect("~/RecvFromA.aspx"); 或使用 Button的PostBackUrl屬性填入~/RecvFromA.aspx。
    接收頁: TextBox oTB = (TextBox)this.PreviousPage.FindControl("TextBox1");
                     this.Label1.Text = oTB.Text;
    ◎只能用於本身且是ASP.NET網站。在Master Page下需要修改程式碼。

4.透過ASP.NET PreviousPage加自訂公用屬性:
    送出頁:先在Class內加上自訂公用屬性。
                  public String SearchString
                  {
                       get
                      {
                           return  TextBox1.Text;
                      }
                   }
                    再使用 Button的PostBackUrl屬性填入~/RecvFromA.aspx 。
    接收頁:將RecvFromA.aspx頁面的第一列後插入以下指令列,<%@ PreviousPageType VirtualPath="~/SendToB.aspx" %>
                    接著在RecvFromA.cs的Page_Load()函式中使用Label1.Text = PreviousPage.SearchString; 取得前頁公用屬性。
    ◎ 只能用於本身且是ASP.NET網站 ,且送出頁與接收頁無法二對一傳遞。不論一般跨網頁或Master Page下都不需要修改程式碼。

5.透過ASP.NET Session傳遞
    送出頁:使用 Button的onClick事件填入Session["SearchString"] = TextBox1.Text;
                    Response.Redirect("~/RecvFromA.aspx");
    接收頁:Page_Load()函式中使用Label1.Text =  Session["SearchString"].ToString();
    ◎ 只能用於本身且是ASP.NET網站,簡單好用跟寫 AP 觀念一樣。

但是,若使用MasterPage跨網頁傳遞參數,第一種方法可以,第二種方法會抓不到,第三種方法則接收頁需要修改語法如下,第四種方法可以,第五種方法可以。

    protected void Page_Load(object sender, EventArgs e)
    {
        if (Page.PreviousPage != null)
        {
            if (PreviousPage.IsCrossPagePostBack)
            {
                //使用MasterPage時, 使用此語法來查找到前一頁中Content Page內的控制項
                TextBox oTB = (TextBox)PreviousPage.Master.FindControl("ContentPlaceHolder1").FindControl("TextBox1");
             
                //使用MasterPage時, 使用此語法來查找到前一頁中Master Page內的控制項
                //TextBox oTB = (TextBox)this.PreviousPage.Master.FindControl("TextBox1");
             
                //顯示上頁欄位中傳遞過來的參數
                this.Label1.Text = oTB.Text;
            }
        }
    }

---
Welly

2012年2月4日 星期六

淺析 ASP.NET Form Submit Keypress 事件 by Enter key

老一輩程式設計師都知道,以前在DOS下寫資料庫 AP,在畫面下按Enter鍵跳下一個欄位是預設再平常不過的事,但到了Windows AP下這功能是要自己在 Form.OnKeyPress事件寫處理指令,可是,到了ASP.NET WEB AP下這功能卻又成了預設功能,挺有趣。

ASP.NET Form Submit Keypress 事件 by Enter key其實說到底並不是ASP.NET 的程式設計問題,卻是關於Html Form 中的Submit 按鈕如何運作問題。


ASP.NET Form Submit Keypress 事件 by Enter key測試一:
當你的游標焦點進入某個表單控制項的時候,會啟動該表單中第一個(依Form 上控制項佈局,從左到右,從上至下算起) type="submit" 的按鈕(假如有),等待回應鍵盤及滑鼠的 Keypress 事件,以Submit該Form。
你可以測試一下以下程式碼:
   1. ﹤form action=""﹥
   2. ﹤input type="text" /﹥
   3. ﹤input type="submit" value="submit" /﹥
   4. ﹤/form﹥
   5. ﹤form action=""﹥
   6. ﹤input type="text" /﹥
   7. ﹤input type="button" value="submit" /﹥
   8. ﹤/form﹥


ASP.NET Form Submit Keypress 事件 by Enter key測試二:
在 ASP.NET 2.0 中的 Button 控制項,預設轉換成 Html 為 ﹤input type="submit"﹥,此時不一定要在 Form 的屬性宣告 submit 事件,因為,submit 型態按鈕就是用來提交Form ,在 ASP.NET 1.x時是轉換成 ﹤input type="button" onclick="_doPostBack(...)" /﹥,此普通 button 就不具備 submit 的上述預設提交行為。


ASP.NET Form Submit Keypress 事件 by Enter key測試三:
依上述,若想要禁用此項預設行為有二種方法。

(1)設置 Form 控制項的 DefualtButton 為你希望回應 Enter 的真正按鈕:
   1. ﹤form id="form1"
   2.
   3. runat="server"
   4.
   5. defaultbutton="Button1"﹥

◎注意 DefaultButton = ﹤ ﹤TargetButton.ID﹥﹥,因此這對複合控制項中,比如Login樣版的 Button 可能無效。
◎也可用程式動態指定 this.Form.DefaultButton = "ContentPlaceHolder1$btsubmit";
值得注意的是,如果用了Master Page,那麼要在按鈕ID前加上 Master 的ID:ContentPlaceHolderID和一個金錢符號($)。
◎例如:
‧在Master Page內用:
   1. protected void Page_Load(object sender, EventArgs e)
   2. {
   3.   this.Form.DefaultButton = "ctl00$ContentPlaceHolder1$Login2$LoginButton";
   4. }
‧在Content Page內用:
   1. protected void Page_Load(object sender, EventArgs e)
   2. {
   3.   this.Page.Form.DefaultButton = "ctl00$ContentPlaceHolder1$Login2$LoginButton";
   4. }
‧在一般(未使用Master Page)情況頁面內:
   1. protected void Page_Load(object sender, EventArgs e)
   2. {
   3.   this.Form.DefaultButton = "LoginButton ";
   4. }
‧在使用者自定控制項(.ascx)內:
   1.請先在引用該控制項的表單外部加一個 Panel 包住,
     <asp:Panel ID="Panel1" runat="server">
        .....//使用者自定控制項的內容
     </asp:Panel>
   2.然後再指定 Panel1.DefaultButton = "btsubmit";


(2)修改 Button 呈現方式 UseSubmitBehavior="false":
   1. ﹤asp:Button ID="Button1"
   2.
   3. runat="server" Text="Button"
   4.
   5. onclick="Button1_Click"
   6.
   7. UseSubmitBehavior="false" /﹥

◎個人建議採用(2)作法,簡單易記,效果明確。


另外,可以使用控制焦點的方式,過濾(擋掉) Enter 鍵按下的處理,做法是:
(1)記錄下需要設定過濾的焦點控制項ID,若不知可用獲取當前頁面焦點所在控制項的ID方法:
document.ActiveElement

(2)以ASP.NET Form上在TextBox1中輸入內容後,按下Enter鍵後,就執行Button1的click方法範例下,我們可在Page_Load事件方法中動態指定 TextBox1的屬性,依下寫入:
   1. TextBox1.Attributes.Add("onkeydown",
   2.
   3. "if(event.which || event.keyCode){
   4.
   5. if ((event.which == 13) || (event.keyCode == 13)) {
   6.
   7. document.getElementById('"+
   8.
   9. Button1.UniqueID+"').click();return false;}}
   10.
   11. else {return true}; ");

◎以上作法其實是針對 TextBox1的onKeydown 事件(或改成 Keypress 事件亦可)內,若按下的是 Enter 鍵時不執行下去,但若按下的是滑鼠左鍵,則執行下去。只能針對特定 TextBox 指定,萬一 Form 上有10個 TextBox 則要用 foreach 逐個指定。


參考資料來源:
1.浅析ASP.NET回车提交事件(转)
http://www.cnblogs.com/jiajiayuan/archive/2011/08/26/2154596.html

2. HtmlForm.DefaultButton 屬性
http://msdn.microsoft.com/zh-tw/library/system.web.ui.htmlcontrols.htmlform.defaultbutton(v=vs.80).aspx

3.Master page button event Overloading by content page button event when enter key is pressed
http://stackoverflow.com/questions/4303009/master-page-button-event-overloading-by-content-page-button-event-when-enter-key

4.ASP.NET 2.0 - Enter Key - Default Submit Button
http://geekswithblogs.net/ranganh/archive/2006/04/12/74951.aspx

5.如何讓使用MasterPage啟用 DefaultButton 屬性
http://www.wretch.cc/blog/bigdstut/14296848

6.Setting the default Button for a TextBox in ASP.NET
http://weblogs.asp.net/rajbk/archive/2003/12/11/setting-the-default-button-for-a-textbox-in-asp-net.aspx


---
Welly Lin

2012年1月3日 星期二

[碎碎念] 彼得原理


銀行中有一個怪制度,就是服務好的行員就會升遷做主管到後面蓋圖章,而服務不好的行員,因為升不了官,繼續留在第一線服務客戶。結果,在第一線服務客戶的,要嘛就是沒經驗的新手,不然就是表現不好的老員工,凡是第一線表現良好的員工,就被調成第二線的主管,從此不再面對客戶。

軟體公司好像也是如此,舉凡程式寫得好的程式設計師,就會升任為經理,而程式寫不好的員工,因為無法升遷,留在基層繼續寫程式。結果,留在基層寫程式的,要嘛就是新手,不然就是程式寫不好的程式設計師。凡是表現良好的程式設計師,就被調任成主管。從此不再寫程式。

如果這個現象再發展下去,就是做得傑出的經理,將會升官成副總,不再繼續做經理。

而繼續做經理的,多半是做不好現職而無法升遷的人。這樣下去,一個穩定的組織,每個位置都是升不上去,或是不適任現職的人。

這個現象早在勞倫斯. 彼得(Laurence J. Peter)於1969年出版 的「彼得原理」一書就發現了,也就是人們會因為自己的能力特質限制,升遷到一個無法勝任的位置就停住了,導致穩定組織中到處充滿不適任的人。

彼得原理告訴我們,企業不應該以升遷做為獎勵的方式,於是,好的銀行行員可以繼續做行員,但是待遇需要比照經理。好的程式設計師可以繼續留在基層寫程式,待遇甚至可以比照副總。

如此一來,彼得原理的現象就可以稍微解除。 

不過,當經理人所在的組織仍以升遷做為獎勵途徑的話,就要注意每次的升遷,都代表著自己能力與特質的改變。通常基層員工之所以優秀是因為他注意瑣碎事務的邏輯關係,但高階主管之所以成功是因為他強調直覺的人際關係。如果升遷後自己的特質沒有改變,自己可能就是下一個彼得原理的產物。或許,對一個升遷的經理人,要記住:「換了位置,一定要換腦袋」。  

在組織中,不同階層的人應該有著不同的腦袋。

聽說有一位貴婦到一家精品店買東西,買回去覺得不適合,第二天來退貨,不料基層店員說,我們公司的政策是貨既售出、概不退還,是不接受退貨的。這位貴婦搞不過這位店員,就大聲嚷嚷說要你們老闆出來。這位老闆在後台聽見了,一見這位貴婦是大戶,急忙出來,並馬上就改口說,退,當然退,誰說不可退貨的。

這位店員還很生氣的跟老闆說,你怎麼這麼搞不清楚,你不是才告訴我們不接受退貨的。

誰才是搞不清楚的人?

基層員工的腦袋通常是「搞不清楚的清清楚楚」,搞不清楚的是不知老闆的想法,清清楚楚的是做事的細節。

員工沒有錯,只是搞不清楚為什麼要那麼做。

公司有標準作業程式,但那是應付公司的標準狀況,眼看的就要得罪一位公司重要的客戶,這不是標準狀況,當然不適用標準作業程式。「搞不清楚的清清楚楚」的人最愛說按規定要如何。

基層經理人應該按制度來做事,只是他們搞不清楚,組織不是為制度而存在,應該是制度是為企業組織而存在。

當你升遷成中階主管時,你的腦袋就要變成「搞得清楚的清清楚楚」

你要先搞清楚老闆的想法,再去清清楚楚的做事。如果你凡事按制度來,你就是彼得原理的產物。

中階主管知道,制度不是目的,制度是幫助企業完成使命的工具,當老闆的意見與制度不一致時,通常改的是制度,而不是老闆的想法。聽起來很狗腿,企業中不正是有能力又狗腿的人升官嗎?

當你有機會成為高階主管,你就要學習「清清楚楚的搞不清楚」。清清楚楚的是企業的方向,搞不清楚的是對人對事的細節。高階主管面對的情境常常不是標準狀況,搞不清楚是給自己留彈性,但是心裡卻是清清楚楚的在盤算。他們知道「難得糊塗」的重要,得饒人處且饒人,和氣不就生財了嘛。

管理學院就在訓練這三種人,大學生沒有老闆,若不用功讀書,就會成為搞不清楚的搞不清楚。

研究生漸漸知道你的指導教授就是老闆,開始學習取悅老闆,所以畢業後有機會當中階主管,是清清楚楚的清清楚楚。

而 EMBA 的學生呢? 自己可能就是老闆,所以學校對 EMBA 課程的設計可是清清楚楚,對期末的考試呢? 就難得糊塗 ~

---
Welly

[ASP.NET+C#] GridView內建分頁加強版

ASP.NET 2.0 的 GridView內建分頁功能,預設是以「數字+符號」呈現,例如「<< ... 1 2 3 4 5 6 7 8 9 10 ... >>」,碰到客戶說看不懂符號的意思,只好想辦法把它改成中文字,變成「第一頁 上十頁 1 2 3 4 5 6 7 8 9 10 下十頁 最後頁」。

貼上程式碼如下,請參閱。使用Northwind的Customers資料表。
=======================
GridView_Pager_Number.aspx
=======================
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GridView_Pager_Number.aspx.cs" Inherits="GridView_Pager_Number" %>

<!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 runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <p>
        <br />
        <asp:GridView ID="GridView1" runat="server" AllowPaging="True"
            AllowSorting="True" AutoGenerateColumns="False" CellPadding="4"
            DataKeyNames="CustomerID" DataSourceID="SqlDataSource1" ForeColor="#333333"
            GridLines="None" onrowdatabound="GridView1_RowDataBound" PageSize="4">
            <PagerSettings Mode="NumericFirstLast" />
            <RowStyle BackColor="#EFF3FB" />
            <Columns>
                <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" ReadOnly="True"
                    SortExpression="CustomerID" />
                <asp:BoundField DataField="CompanyName" HeaderText="CompanyName"
                    SortExpression="CompanyName" />
                <asp:BoundField DataField="ContactName" HeaderText="ContactName"
                    SortExpression="ContactName" />
                <asp:BoundField DataField="ContactTitle" HeaderText="ContactTitle"
                    SortExpression="ContactTitle" />
                <asp:BoundField DataField="Address" HeaderText="Address"
                    SortExpression="Address" />
                <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
                <asp:BoundField DataField="Region" HeaderText="Region"
                    SortExpression="Region" />
                <asp:BoundField DataField="PostalCode" HeaderText="PostalCode"
                    SortExpression="PostalCode" />
                <asp:BoundField DataField="Country" HeaderText="Country"
                    SortExpression="Country" />
                <asp:BoundField DataField="Phone" HeaderText="Phone" SortExpression="Phone" />
                <asp:BoundField DataField="Fax" HeaderText="Fax" SortExpression="Fax" />
            </Columns>
            <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
            <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
            <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
            <EditRowStyle BackColor="#2461BF" />
            <AlternatingRowStyle BackColor="White" />
        </asp:GridView>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server"
            ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            SelectCommand="SELECT * FROM [Customers]"></asp:SqlDataSource>
    </p>
    <div>
 
    </div>
    </form>
</body>
</html>

=======================
GridView_Pager_Number.aspx.cs
=======================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class GridView_Pager_Number : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        //取得Pager Row
        if (e.Row.RowType == DataControlRowType.Pager)
        {
            //取得內崁的TableRow
            TableRow trPager = (TableRow)e.Row.Controls[0].Controls[0].Controls[0];
            for (int i = 0; i < trPager.Controls.Count; i++)
            {
                TableCell tcPager = (TableCell)trPager.Controls[i];
                for (int j = 0; j < tcPager.Controls.Count; j++)
                {
                    //...格式必為LinkButton
                    if (tcPager.Controls[j].ToString() == "System.Web.UI.WebControls.DataControlPagerLinkButton")
                    {
                        //原Number顯示方式為"... 11 12 13 14 15 16 17 18 19 20 ..."
                        //故 (i=0 && LinkButton.Text="..."), 即目前頁數>10
                        LinkButton lbtn = (LinkButton)tcPager.Controls[j];
                        if ((lbtn.Text == "&lt;&lt;") && (i == 0))
                        {
                            lbtn.Text = "第一頁 ";
                        }
                        else if ((lbtn.Text == "...") && (i == 0))
                        {
                            lbtn.Text = "上十頁 ";
                        }
                        else if (lbtn.Text == "...")
                        {
                            lbtn.Text = " 下十頁";
                        }
                        else if (lbtn.Text == "&gt;&gt;")
                        {
                            lbtn.Text = " 最後頁";
                        }
                    }
                }
            }
        }
    }
}
=======================

---
Welly