顯示具有 C# 標籤的文章。 顯示所有文章
顯示具有 C# 標籤的文章。 顯示所有文章

2020年10月19日 星期一

{WebForm}Forms驗證 登入登出頁

 四年前有寫過利用MVC架構建立Form 表單驗證

這次又有新的前輩寫的火星文web form版本的表單驗證

以下就來一一破解一下

首先,

利用web form的架構下都會以web.config去設定一些有的沒的

首先,在config 中利用authenticution 設定好的login 的頁面

<authentication mode="Forms">

      <forms protection="All" timeout="480" slidingExpiration="true" cookieless="UseDeviceProfile" loginUrl="backend/login.aspx" defaultUrl="backend/index.aspx" requireSSL="false" enableCrossAppRedirects="false">

        <credentials passwordFormat="SHA1" />

      </forms>

</authentication>

上面提到可見文件來了解每個項目的定義

接著實作backend/login.aspx,進行帳密的驗證

驗證成功後透過FormsAuthentication類別去寫入cookie

FormsAuthentication.RedirectFromLoginPage

(UsernameTextbox.Text, NotPublicCheckBox.Checked);


但天殺的前輩就要用FormsAuthenticationticket用自已的力量寫一次cookie

結果就會像下面這樣

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Name, DateTime.Now, DateTime.Now.AddHours(8), true, user.Serno.ToString());

string encryptedTicket = FormsAuthentication.Encrypt(ticket);

HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

authCookie.Expires = ticket.Expiration;

 Response.Cookies.Add(authCookie);

那...config其實也不用設到這麼多參數了!!


那經過幾年後,問題來了,這個網站有四個相似的網站,分別for不同的狀態去操作

都架在同一個網域下的情況,就會發生明明是不同網站卻cookie互蓋的問題

主要就是同網域都把cookie寫在path:/ 下,那有二個解法:

1.cookie 名稱都取不同

2.path改位置

這裡用2這個項目進行調整,因為網站本來就放在同一個網域不同的子資料夾下,就直覺用path區分不同網站所存取的驗證cookie

首先在web.confg增加path這個參數設定

<forms protection="All" timeout="480" slidingExpiration="true" cookieless="UseDeviceProfile" loginUrl="backend/login.aspx" defaultUrl="backend/index.aspx" requireSSL="false" enableCrossAppRedirects="false" path="/a">

接著因為在login.aspx.cs中前輩又自已寫了add cookie段,也需要跟著調整,參數可見

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.Name, DateTime.Now, DateTime.Now.AddHours(8), true, user.Serno.ToString(),FormsAuthentication.FormsCookiePath);


於似乎就能解決同一個網域下發生明明是不同網站卻cookie互蓋的問題


後記:因為logout.aspx.cs 也被「手動」的remove一些cookie,這些都是key point要注意連同修改cookie 路徑,以省的還是有被蓋的問題


2016年2月18日 星期四

{C#} 取連結Json資料作法

今天工作覺的無聊,打開「政府資料開放平臺」看看有什麼資料可以拿來用,創造出東西出來

第一次接觸這樣的東西,覺的相當有趣,而最初淺的就是直接看別人怎麼用這個網站的資訊創造出來東西



而身為最「弱」的程式開發員,今天就來試試,當不用前端程式呼叫某個網頁傳回的資料(俗稱Service),該怎麼做?
而一開始要準備好一個Service 網址,可以抓資料回來

2016年2月16日 星期二

{Interview 專區}什麼是Interface 與運用 by C#

這個年頭誰都可以當程式設計師,一直說服自已就是這樣所以沒啥好難
每個「很強」的部落客寫的落落長,裡面有多少的字看的懂,只能說我知道這是英文與中文

為何當一個程式設計師不能簡單一點?
今天,要講什麼是interface ,OO是三小,只有在課本上背著背著考,其他懶的管
現在回到正題「interface 是什麼」
interface 就是介面,好像一個好手寫I-N-T-E-R-F-A-C-E就很強,所以在自已的專案上也跟著寫,然後,不知道要幹麼用

在網路上不少範例,但簡單來說,介面就是在上面宣告幾個屬性、方法,然後給別人Implements。
interface Interface1
    {
        List<Class1> allData();
        Class1 Databycode(string code);
        string CreateData(Class1 newData);
    }

2016年2月15日 星期一

{C#}利用LDAP協定與AD Server驗證

主要語法:
//要驗證的username與pwd
string domainAndUsername = domain + @"\" + username;
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
DirectorySearcher search = new DirectorySearcher(entry);
//要驗證的username
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
result 為null即AD無此帳號或帳密錯誤


未驗證的要求會被重新導向到 Logon.aspx 頁面
Web.config 檔
<configuration>
  <system.web>
    <authentication mode="Forms">
      <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/">
      </forms>
    </authentication>
    <authorization>
      <deny users="?"/>
      <allow users="*"/>
    </authorization>
<!--此組態,所有對此應用程式發出的要求都會以已設定之帳戶的安全性內容執行。使用者必須提供認證以向 Active Directory 網域服務驗證,但只有已設定的帳戶可存取 Active Directory 網域服務。--!>
    <identity impersonate="true"/>
  </system.web>
 </configuration>


2015年10月5日 星期一

{C#}實作IEnumerable 介面 讀出列舉陣列

下列示範在MVC架構中,實作IEnumerable介面
在Yahoo 字典中,Enumerable的意思是「可列舉的」adj.
主要就是把一個集合中的資料一 一讀出的運作流程

1.首先建立一個Class 並繼承Franmework的IEnumerable介面
在IEnumerable介面上只有一個Function
這可以從MSDN上可以看到
https://msdn.microsoft.com/zh-tw/library/system.collections.ienumerable(v=vs.110).aspx
接著開始寫自已的列舉器

//1.繼承IEnumerable
//資料結構中的資料,是否可被列舉
public class IEnumeratorClass:IEnumerable {
private string[] EmployeeList = { "John", "Jay", "Bobo" };
//IEnumerable界面下的function
public IEnumerator GetEnumerator()
{ return new EmployeeEnumerator(this); }
//2.自定義「資料結構實作的列舉器」
public class EmployeeEnumerator : IEnumerator
{ //元素
string[] _elements;
//指標
int _flag = -1;
//建構子
public EmployeeEnumerator(IEnumeratorClass source) { _elements = source.EmployeeList; }
//實作Reset Void 重新設定Flag
public void Reset() { this._flag = -1; }
//實作Current 回傳當前的值
public object Current { get { if (this._flag == -1 || this._flag > this._elements.Length) { //Exception throw new InvalidOperationException(); } return this._elements[this._flag]; } }
//指標移至下一筆是否可行
public bool MoveNext() { if (this._flag + 1 == this._elements.Length) return false; else { this._flag++; return true; } }
//取資料結束後,要做任何Release、關閉資料庫連結等覆寫
public void Dispose() { } } }



在Controller中

public ContentResult EmployeeGet() { string allEmployee = ""; IEnumeratorClass employeeName = new IEnumeratorClass(); IEnumerator enumerator = employeeName.GetEnumerator(); //當可以移至下一筆時 while (enumerator.MoveNext()) { //Show出所有的集合資料 allEmployee += enumerator.Current; } return Content(allEmployee); }
參考資料:
http://xingulin.tumblr.com/post/48831985749/ienumerable-ienumerator

2015年10月2日 星期五

{MVC} Linq to sql 搭配MVC 基本運作

離開程式三個多月,重拾卻步步難走
不如就記錄一下,最最最基礎的東西
建立一個MVC專案
最簡單就是建一個Textbox 與一個Button
以db first的方式寫入資料庫
這是一個最簡單的例子

Views:
//整頁做Postback
@using (Html.BeginForm("Test", "Home", FormMethod.Post))
{
//建立一個address 的textbox
@Html.TextBox("address")
//建立一個按鈕
    <input type="submit" name="btnSubmit" value="Convert" />
}

按鈕Type為submit ,一點下就會Postback 到指定的Action


Control:
傳入為Textbox 的內容,放上Textbox 的name屬性
Linq to Sql 建立一個db連線,接著就可以將資料寫入db

 [HttpPost]
        public ContentResult Test(string address)
        {
            try {
           
                MyProject_GoogleMapLocation newItem = new MyProject_GoogleMapLocation();
                newItem.ADDRESSCHT = address;
                //Save Database
                using (var context = new HomeDataContext())
                {
                    context.MyProject_GoogleMapLocation.InsertOnSubmit(newItem);
                    context.SubmitChanges();
                }
            }
            catch(Exception e)
            {
                return Content( e.Message);
            }
           
            return Content("Successful");
        }

2014年7月10日 星期四

{JavaScript} Close 畫面 並將父畫面Reload

Close 畫面 並將父畫面Reload

Script:
window.opener.location.reload();
window.close();

C# 編寫JavaScript 語法
//直接關閉視窗
        public void Close()
        {
            Page p = (Page)System.Web.HttpContext.Current.Handler;
            ClientScriptManager CSM = p.ClientScript;
            String ScriptName = "close";
            String ScriptMsg = "window.opener.location.reload();window.close();";
            Type CsType = p.GetType();
            if (!CSM.IsStartupScriptRegistered(CsType, ScriptName))
            {
                CSM.RegisterStartupScript(CsType, ScriptName, ScriptMsg, true);
            }
        }

參考資訊:
http://stackoverflow.com/questions/19027959/how-to-refresh-parent-page-after-closing-popup-window-in-javascript


2014年4月21日 星期一

{LInq} Linq 方法。 最後新增日期:4/21

1.Except
譯:二陣列中,前有,後者沒有的
Ex:
    var a=[1,2,3];
    var b=[2,3];
a.Except(b); Result=1;

參考資訊:http://www.cnblogs.com/626498301/archive/2011/02/24/1963413.html



2.Zip
譯:二個相同長度陣列串連成一個;如不同長度,以最短長度為準
Ex:
    var a=[1,2,3];
    var b=[2,3,4];
a.Zip(b,(f,s)=>f+s); Result=[3,5,7]

參考資訊:http://msdn.microsoft.com/zh-tw/library/dd267698(v=vs.100).aspx
http://www.cnblogs.com/fox23/archive/2009/12/14/zip-operator-in-csharp4-vs-python3.html

{LInQ} 做Dictionary、Distinct ... 多屬性為Key 比對其Class覆寫方法

如需要將多個屬性做為Key供判斷,需要另外覆寫 Equals()與 GetHashCode() 才能達到判斷是否相同的結果....

        public class InventoryWODetail
        {
            public int SOItemId { set; get; }

            public string CPSPN { set; get; }

            public string WONo { set; get; }

            public int WOTotalQty { set; get; }

            public int WOCloseQty { set; get; }

            public int WOOpenQty { set; get; }

            public string CPSSONo { set; get; }

            public string CPSSOPlannedShipDate { set; get; }

            public string WOPlannedClose { set; get; }

            public override bool Equals(object obj)
            {
                if (!(obj is InventoryWODetail))
                    return false;
                else
                {
                    InventoryWODetail other = obj as InventoryWODetail;
                    return (other.SOItemId == this.SOItemId && other.CPSPN == this.CPSPN && other.WONo == this.WONo && other.WOTotalQty == this.WOTotalQty
                        && other.WOCloseQty == this.WOCloseQty && other.WOOpenQty == this.WOOpenQty && other.CPSSONo == this.CPSSONo && other.CPSSOPlannedShipDate == this.CPSSOPlannedShipDate
                        && other.WOPlannedClose == this.WOPlannedClose);
                }
            }

            public override int GetHashCode()
            {
                return string.Format("{0} | {1} | {2} | {3}  | {4}  | {5}  | {6}  | {7}  | {8} ", this.SOItemId, this.CPSPN, this.WONo, this.WOTotalQty, this.WOCloseQty, this.WOOpenQty, this.CPSSONo, this.CPSSOPlannedShipDate, this.WOPlannedClose).GetHashCode();
            }
        }


參考資訊:http://www.cnblogs.com/626498301/archive/2011/02/24/1963413.html

2014年3月26日 星期三

{C#} 預約系統 -時間判斷某一天預約時間區間是否衝突

下列判斷方式需為同一天的時間區間
//目前起始時間是否大於目前終止時間
if (!(start >= end))
                {
                    var tempDate = start.ToShortDateString();
                    //目前的起始時間到終止期間有連續多天欲預約
                   //ex:2014/03/26 10:00~2014/03/27 10:00
                    if(start.ToShortDateString()!=end.ToShortDateString())
                    {
                        var tempStart = start;
                        // 一天一天的比對
                        while (tempStart <= end)
                        {
                            var tempSource = call funcion(tempStart.ToShortDateString());//資料庫已預約完成某一天的資料
                            if (tempSource.Count() > 0)
                            {
                                //時分秒是否衝突
                                var queryCount = tempSource.Any(s => s.StartDate < end && s.EndDate > tempStart);
                                if (queryCount && !result) { result = true; msg = "預約時段衝突"; break; }
                                //完全相同---為安全確保而多寫的
                                queryCount = tempSource.Any(s => s.StartDate == start && s.EndDate == tempStart);
                                if (queryCount && !result) { result = true; msg = "預約時段衝突"; break; }
                            }
                            tempStart = tempStart.AddDays(1);
                        }
                    }
                    //目前起始時間小於當下
                    else if (start < now)
                    {
                        result = true;//起始日小於現在
                        msg = "預約時間已過期, 請更改預約時間";
                    }
                    //目前結束時間小於當下
                    else if(end <now)
                    {
                        result = true;//結束時間小於當下
                        msg = "預約時間已過期, 請更改預約時間";
                    }
                    else
                    {
                        //目前的起始時間到終止期間有同一日時間區間預約
                        //ex:2014/03/26 10:00~2014/03/26 18:00
                        var source =call funcion();//資料庫已預約完成的全部資料
                        if (source.Count() > 0)
                        {
                            var queryCount = source.Any(s => s.StartDate < end && s.EndDate > start);
                            if (queryCount && !result) { result = true; msg = "預約時段衝突"; }
                            //完全相同
                            queryCount = source.Any(s => s.StartDate == start && s.EndDate == start);
                            if (queryCount && !result) { result = true; msg = "預約時段衝突"; }
                        }
                    }
                }
                else{
                    result = true;//起始大於終止
                    msg = "開始時間不可大於結束時間";
                }
            }
            else
            {
                result = true;
                msg = "預約資訊異常-起始日為空、終止日為空、無此設備";
            }



參考資料:
http://bibby.be/2008/07/blog-post_10.html

2013年12月27日 星期五

{C#} 加解密Get Url 參數

原貌:http://abc.com.tw?_do=ABCDDAFDA==

#region 解加密過的參數
        private static string decode(String strData)
        {

            try { return System.Text.UTF8Encoding.UTF8.GetString(System.Convert.FromBase64String(strData)); }
            catch { return ""; }
        }
        private static Hashtable QueryValue(string _do)
        {
            _do = decode(_do);
            string[] s = _do.Split('&');

            Hashtable ht = new Hashtable();

            for (int i = 0; i < s.Length; i++)
            {
                if (s[i].IndexOf("=") > 0)
                {
                    string key = "";
                    string values = "";
                    key = s[i].Substring(0, s[i].IndexOf("="));
                    values = s[i].Substring(s[i].IndexOf("=") + 1);
                    ht.Add(key, values);
                }
            }
            return ht;
        }
        public static string GetQueryStringByKey(string pKey, string queryString)
        {
            Hashtable do_ht = QueryValue(queryString);
            return do_ht.ContainsKey(pKey) ? do_ht[pKey].ToString() : "";
        }
        #endregion

#region 加密
private static string encode(String strData)
        {
            try { return System.Convert.ToBase64String(System.Text.UTF8Encoding.UTF8.GetBytes(strData)); }

            catch { return ""; }

        }
        public static string GetCustNe(string pCustomerName)
        {
            return "?_do=" + encode("CustNe=" + pCustomerName);
        }
#endregion

參考資料:http://www.dotblogs.com.tw/joumingt/archive/2009/07/09/9271.aspx

2013年9月11日 星期三

{C#} Gridview 動態建立ITemplate

 class LinkColumn : ITemplate
        {
            public void InstantiateIn(System.Web.UI.Control container)
            {
                LinkButton link = new LinkButton();
                link.ID = "link";
                container.Controls.Add(link);
            }
        }
        private void CreateWoLinkColumn(string headerText)
        {
            var column = new TemplateField() { HeaderText = headerText };
            column.ItemTemplate=new LinkColumn();
            column.ItemStyle.HorizontalAlign = HorizontalAlign.Center;
            column.HeaderStyle.Wrap = false;
            MainDG.Columns.Add(column);
        }
//Page_init叫用
protected void Page_Init(object sender, EventArgs e)
        {
            CreateWoLinkColumn("aa");
        }

*動態生成Template 因每次Postback時,會重跑Page_Load function,故在第一次生成動態Template時,需寫在Page_Init 以保存控制項,爾後要取控制項的值才FindControl的到

*Page 生命週期:PreInit=>Init=>InitComplete=>PreLoad=>Load.....


參考資料:
http://blog.sina.com.cn/s/blog_8038620001012s9d.html

{C#} 取一整年 目前的週數

CultureInfo info = CultureInfo.CurrentCulture;
                //周一為新的一週;
                int iweekdNo = info.Calendar.GetWeekOfYear(DateTime.Now,CalendarWeekRule.FirstDay,DayOfWeek.Monday);

CalendarWeekRule列舉:
FirstDay    指示一年的第一週開始於該年的第一天,並結束於被指定為該週第一天的前一天。 該值為 0。
FirstFullWeek    指示一年的第一週開始於,一年的第一天當天或之後被指定為一週第一天的那天。
FirstFourDayWeek    指示一年的第一週有四天以上在被指定為該週的第一天之前。

FirstFullWeek Ex:
1/1 周五 設一週第一天為周日
=>第一周第一天日期為1/3(日)
1/1 周二 設一週第一天為周日
=>第一週第一天日期為1/1(二)



參考資料:
http://kevintsengtw.blogspot.tw/2011/09/blog-post_29.html#.Ui_AucanpBh
http://msdn.microsoft.com/zh-tw/library/system.globalization.calendarweekrule.aspx

2013年7月4日 星期四

{C#} Progressbar(JQuery UI) 搭配Ajax

搭配Ajax取資料其間 進度條展示
//CSS樣版
<style>
    .progress-label {
            float: left;
            margin-left: 50%;
            margin-top: 5px;
            font-weight: bold;
            text-shadow: 1px 1px 0 #fff;
        }

</style>
<script>
 $(function () {
//設定Progressbar
            var progressbar = $("#progressbar"),
            progressLabel = $(".progress-label");
            progressbar.progressbar({
                value: false,
                change: function () {
                    progressLabel.text(progressbar.progressbar("value") + "%");
                },

                complete: function () {
                    progressLabel.text("Complete!");
                }
            });
            var intervalID = setInterval(progress, 250);
           //觸發Read ajax
                        var strURL = "source.ashx";
                        $.ajax({
                            type: 'GET',
                            data: { parms: Math.random() },
                            url: strURL,
                            contentType: "application/json; charset=utf-8",
                            dataType: 'json',
                            error: function () {
                                alert('Ajax request 發生錯誤');
                            },
                            success: function (result) {
                                $("#progressbar").progressbar("value", 100);
                                $("#progressbar").hide();
                             
                            }
                        });
});
 function progress() {
                var val = $("#progressbar").progressbar("option", "value")
                if (val < 100) {
                    $("#progressbar").progressbar("value", val + 1);
                }
            }
</script>

<div id="progressbar"></div>



參考資訊:
http://horacerobot.blogspot.tw/2010/12/jquery-ajax-mvc-jquery-ui-progress-bar.html
http://jqueryui.com/progressbar/#label


2013年6月25日 星期二

{C#} TextBox ReadOnly Postback取不到值

Control中,如使用ReadOnly,在Post back時會取不到值的問題

.net Control--
<asp:TextBox ID="abc" runat="server"  Readonly=true ></asp:TextBox>
html Control--
<input type="text" id="abc" name="abc" readonly="readonly" />

解決方式:
在Load Page 時將控制項屬性加入,
不在.aspx就先設定,可避免Post Back 時Viewstate Control值不被改變而導致取不到回寫值
 if (!IsPostBack)
            {
                txtReceivingDate.Attributes.Add("readonly", "readonly");
            }


參考資訊:
http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/10/21/textbox-readonly-and-disabled.aspx
http://www.dotblogs.com.tw/newmonkey48/archive/2009/11/08/11479.aspx

2013年6月5日 星期三

{C#} yield 使用

Yield
Foreach 中使用

//逐一帶出Enumerable 內資料 並回傳IEnumerable<class>  型態結果
foreach (var aa in IEnumerable)
{
    yield return new class{
       orderNo=aa.orderNo,
       ProductName=aa.ProductName
    }
}

//只帶回第一筆資料
foreach (var aa in IEnumerable)
{
    return new class{
       orderNo=aa.orderNo,
       ProductName=aa.ProductName
    }
}

//當訂單號碼為1,就會結束迴圈
foreach (var aa in IEnumerable)
{
    if(aa.OrderNo==1)
       yield break;
}

PS.
1.Yield break;可在Try catch 中,但不可在Finally中
2.Yield return;不可在Try catch中,但可在Try-finally 的Try中

參考資訊:
http://www.dotblogs.com.tw/hatelove/archive/2012/05/10/introducing-foreach-ienumerable-ienumerator-yield-iterator.aspx
http://msdn.microsoft.com/zh-tw/library/9k7k7cf0.aspx
http://www.dotblogs.com.tw/dc690216/archive/2010/02/19/13697.aspx

2013年6月4日 星期二

{Linq} 相同Group 中資料分隔

Data:
Name No Qty
A        1     50
A        2     60
B       12    10
C       13    70

Result:
A  1,2  110
B   12    10
C   13    70


var groupResult = data.ToLookup(s => s.Name);
string symbol=",";
foreach (var c in groupCPSPNResult)
{
    result.Add(new
   {
      Name= c.Key.Name,
      No= string.Join(symbol, c.Select(s => s.No).ToArray()),
      Total= c.Sum(s => s.Qty)
  });
}


參考資訊:
http://www.dotblogs.com.tw/dyco/archive/2010/08/25/17401.aspx

2013年5月14日 星期二

{C#} NPOI 進階-讀Excel 儲存格公式 取其結果方法

Excel的公式有很多種,有
1.日期型的公式
2.字串組合變化公式
3.純數值(儲存格數值)加總等公式
4.其他(還沒想到)

ps.NPOI版本為2.0
NPOI讀取公式類型的儲存格,其依以上不同而有不同的寫法

//每一格儲存格的資料類型為公式
//EX:Date('2010','4','1')、Sum($A1,$A2)、$A1 & $A2
if(hssfRow.GetCell(k).CellType==CellType.FORMULA)
{
     //由NPOI內提供的類別庫判斷公式結果類型

     IFormulaEvaluator iFormula = WorkbookFactory.CreateFormulaEvaluator(workbook);
     var formulaType = iFormula.Evaluate(hssfRow.GetCell(k)).CellType;
    //結果類型為數值(日期結果會被轉為數值)
     if (formulaType == CellType.NUMERIC)
    {
        ICell cell = iFormula.EvaluateInCell((hssfRow.GetCell(k)));
        // 判斷是否日期
         if (DateUtil.IsCellDateFormatted(cell))
           dr[k] = hssfRow.GetCell(k).DateCellValue;
         else
           dr[k] = hssfRow.GetCell(k).NumericCellValue;
    }
    //字串公式
    else if (formulaType == CellType.STRING)
       dr[k] = hssfRow.GetCell(k).StringCellValue;
    else
       dr[k] = hssfRow.GetCell(k).ToString();

}


參考資訊:
http://www.dotblogs.com.tw/smartleos/archive/2010/10/11/18284.aspx
http://tonyqus.sinaapp.com/archives/tag/excel-2007

2013年5月13日 星期一

{JavaScript} JS中資料轉Json格式中文成Unicode(\u...)問題

以下情況僅IE 8會發生..........以下解法經用IE 8測試OK

當在JS中將資料利用JSON.stringify()方式
轉為Json遇到中文時,會被成Unicode編碼

紅框為中文字

傳到後端會自動將Unicode解碼
但也可以手動在解碼一次

string factoryName = Regex.Unescape(jsonResult.FactoryName);
string lineName = Regex.Unescape(jsonResult.LineName);


前端的部分,JSON.parse會自動轉中文字
var data = JSON.parse(jsonResult);

參考資訊:

2013年5月9日 星期四

{C#} Excel.dll & NPOI 分析

Microsoft.Office.Interop.Excel;
 原理:開啟Server端Excel Application 讀取內容後關閉
 需求:Server端機器需加裝office Excel
 Code:
           Excel.Application xExcel = new Excel.Application();
            Excel.Workbook xbook = null;
            Excel.Worksheet xsheet = null;
            Excel.Range xRange = null;
            try
            {
               .......
            }
            finally
            {
                xbook.Close();
                xExcel.Quit();
                xbook = null;
                xsheet = null;
                xRange = null;
                xExcel = null;
                //確認已經沒有excel工作再回收
                GC.Collect();
            }

圖一、每New一次Excel.Application 使office Automation 啟動 即產生一個Process


嘗試以回收源方式關閉Process 無效;直接手動寫Code Kill Process 有一定的風險

                xbook.Close();
                xExcel.Quit();
                xbook = null;
                xsheet = null;
                xRange = null;
                xExcel = null;
                //確認已經沒有excel工作再回收
                GC.Collect();


嘗試引用已啟動的Excel.Application,在WinServer2008 R2 x64 OS下,出現Error Message
「HRESULT: 0x800401E3」
原因為Excel.Application被認定Running 無法被調用

 //檢查PC有無Excel在執行
            bool flag = false;
            foreach (var item in Process.GetProcesses())
            {
                if (item.ProcessName == "EXCEL")
                {
                    flag = true;
                    break;
                }
            }

            if (!flag)
            {
                xExcel = new Excel.Application();
            }
            else
            {
                ////延遲5秒載入
                //Thread.Sleep(5000);
                try
                {
                    //發生錯誤的地方
                    xExcel = (Excel.Application)Marshal.GetActiveObject("Excel.Application");//引用已在執行的Excel
                }
                catch (Exception)
                {
                }
             
            }

            if (xExcel != null) xExcel.Visible = true;//設false效能會比較好


NPOI
 原理:利用Java 函式庫POI轉包成.NET版本。POI直接深入到 OLE Compound Document 複合式  文件格式內存取資料,並物件導向化,外部開發人員利用POI 屬性去控制Office 檔案
 需求:NPOI 2.0 版本需引出多個Dll
 Code:
            Stream fileConent = File.Open(xlsPath, FileMode.Open);

////辯別是2007還是2003
            IWorkbook workbook = WorkbookFactory.Create(fileConent);

.....

//讀完一個Sheet關閉一個Sheet
                hs = null;

圖二、Excel物件的組成


NPOI目前每匯一張Excel僅透過Stream方式讀出資料,但讀取xlsx時,速度會因為xlsx架構是XmlSerializer  ,檔案越大,讀的速度越慢。
http://npoi.codeplex.com/discussions/439282




OLE Compound Document 複合式文件:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms693383(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/dd942415.aspx

office運作與POI:
POI本身就是處理Office檔案的函式庫,Office都是微軟發展的OLE Compound Document 複合式文件,以結構化格式儲存在檔案中,由Excel物件模型去解析

參考來源:
http://www.dotblogs.com.tw/yc421206/archive/2012/03/09/70624.aspx