2019年1月21日 星期一

開啟報表突然出現「應用程式中發生伺服器錯誤。」 -- 20190121

緣由:

因最近公司的報表程式在點閱時,突然無法正常開啟,且出現了錯誤訊息。原本很正常都沒問題,且開發網站的同事也沒做什麼動作,登入網站後點閱或開啟查看就會掛掉,如下圖:


































解決方式:


步驟一、開啟Web.config檔案,並將原先的程式改成為:

在Web.config找到

 <customErrors mode="RemoteOnly" >  
       <error redirect="~/ErrorPage.aspx" statusCode="404" />
    </customErrors>

將其改成
<customErrors mode="Off"/>


步驟二、執行後,出現 System.IO.IOException:檔案存在。

























步驟三、根據爬文找到一篇文章有提到 System.IO.IOException:檔案存在。

原因是因為TEMP資料夾內的檔案超過65535,導致臨時檔案丟擲出現異常,將TEMP資料夾內的檔案清除後,即恢復正常。(圖為伺服器內暫存資料夾內的檔案數)




























心得:

雖然不是我解決這問題的,但還是把它紀錄下來,以防止下次再次發生的時候,可以快速地將問題解決。












2016年3月2日 星期三

網頁資料套用表單格式 -- 20160302

緣由:

最近想把將自己手邊上的工作,藉由網路的方式來處理,由於自己寫程式算是初學者,所以東湊西湊的寫出這簡單的網頁(網址),但朋友建議我若可以寫出套表的話,那網站就會更棒,在好奇心的驅使一下,結果我花了半天時間就搞定了。挖塞~真不敢相信我自己的能力。

※軟體:Visual Studio 2012開發軟體、作業系統為Windows 10



---------------以下是網頁套表的寫法:------------------------


步驟一、先下載Open XML SDK 2.0 for Microsoft Office套件,且下載時會有兩個檔案(OpenXMLSDKv2.msi、OpenXMLSDKTool.msi),記得兩個檔案都要下載,並且安裝起來。

備註:OpenXMLSDKv2.msi 報表開發所需的軟體
            OpenXMLSDKTool.msi 觀察OpenXML的工具軟體






步驟二、在專案中開啟Bin資料夾,並將DocumentFormat.OpenXml.dllWindowsBase.dll兩個檔案,複製到Bin資料夾中。

備註:
  • DocumentFormat.OpenXml.dll 放置路徑
            →  C:\Program Files (x86)\Open XML SDK\V2.0\lib
  • WindowsBase.dll 放置路徑 
             → C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0


































































































步驟三、準備好報表樣式,並將報表格式存檔成*.docx格式(目前這方法僅適用於docx檔案),並將已設計好的報表樣式(FixTable.docx)放置report資料夾中。






























































步驟四、簡易製作網頁,且網頁的欄位可以套用到表格樣版中。








































步驟五、開始寫程式碼。

































[程式碼一]

using System.Text;
using DocumentFormat.OpenXml.Packaging;
using System.IO;



[程式碼二]

namespace Darkthread.OpenXml
{
    /// <summary>
    /// Ver 1.0 By Jeffrey Lee, 2009-07-29
    /// </summary>
    public class DocxHelper
    {
        /// <summary>
        /// Replace the parser tags in docx document
        /// </summary>
        /// <param name="oxp">OpenXmlPart object</param>
        /// <param name="dct">Dictionary contains parser tags to replace</param>
        
        private static void parse(OpenXmlPart oxp, Dictionary<string, string> dct)
        {
            string xmlString = null;
            using (StreamReader sr = new StreamReader(oxp.GetStream()))
            { xmlString = sr.ReadToEnd(); }
            foreach (string key in dct.Keys)
                xmlString = xmlString.Replace("[$" + key + "$]", dct[key]);
            using (StreamWriter sw = new StreamWriter(oxp.GetStream(FileMode.Create)))
            { sw.Write(xmlString); }
        }

        /// <summary>
        /// Parse template file and replace all parser tags, return the binary content of
        /// new docx file.
        /// </summary>
        /// <param name="templateFile">template file path</param>
        /// <param name="dct">a Dictionary containing parser tags and values</param>
        /// <returns></returns>
        
        public static byte[] MakeDocx(string templateFile, Dictionary<string, string> dct)
        {
            string tempFile = Path.GetTempPath() + ".docx";
            File.Copy(templateFile, tempFile);

            using (WordprocessingDocument wd = WordprocessingDocument.Open(tempFile, true))
            {
                //Replace document body
                parse(wd.MainDocumentPart, dct);
                foreach (HeaderPart hp in wd.MainDocumentPart.HeaderParts)
                    parse(hp, dct);
                foreach (FooterPart fp in wd.MainDocumentPart.FooterParts)
                    parse(fp, dct);
            }

            byte[] buff = File.ReadAllBytes(tempFile);
            File.Delete(tempFile);
            return buff;
        }

    }
}


※上述的程式碼出處為:來源



[程式碼三]

TextBox2.Text = DateTime.Now.ToString();




在Button2_Click事件中,將下列的程式碼貼至事件中。(黃色框是依據您自行撰寫的表格樣版的擺放位置、表格欄位而定義的,其欄位名稱可自由調整。)









































[程式碼四]

string template = Server.MapPath("report/FixTable.docx");

Dictionary<string, string> dct = new Dictionary<string, string>()
    { 
        { "Unit", DropDownList1.SelectedValue },
        { "Today", DateTime.Today.ToString("yyyy/MM/dd") },
        { "UserName", TextBox1.Text },
        { "ProType", DropDownList2.SelectedValue },
        { "Content", TextBox3.Text } 
    };

Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename=Notice.docx");

Response.BinaryWrite(    Darkthread.OpenXml.DocxHelper.MakeDocx(Server.MapPath("report/FixTable.docx"),dct));

Response.End();



步驟六、程式碼與表單欄位互相對應。開啟表單樣版,在欄位上輸入[$欄位名稱$],然而,表格上面的欄位名稱要與程式碼相同。別忘了,表單欄位內容編輯好之後記得儲存。







































步驟七、執行設計好的網頁,且查看是否有將網頁內容套用到表單中。




※開啟下載後的檔案,結果發現部分欄位無法套用文字(時常會出現這種情況)。由於無法得知哪裡出問題,所以可透過「Open XML SDK 2.0 Productivity Tool」工具來檢查問題發生的原因。


























※正常的情況,因該是如下圖所顯示的畫面。


























補充:如何使用Open XML SDK 2.0 Productivity Tool呢?

首先,開啟已安裝完成的Open XML SDK 2.0 Productivity Tool工具。





































開啟表格樣版,開啟 File → Open File → FixTable.docx。




































按下「Reflect Code」,可看見該表格樣版的所有程式碼。(老實說,我很懶得看。)








































本人採用的方法,先點選該檔案,按下滑鼠右鍵,會出現Find..功能,透過搜尋功能直接找到「關鍵表格欄位名稱」。'































正常的情況,搜尋到因該是[$Today$]格式。


















將問題發生的欄位,採用關鍵字搜尋時,發現理當因該是[$UserName$],但出現卻是"UserName",肯定是這地方有問題。於是重新將表單樣版的Keyin一次。








































在嘗試直行網頁程式,查看套表是否至正常。






下載後,開啟檔案發現已恢復正常,及製作完成套表。
















































參考網址:ola的家黑暗執行諸






結論:

老實說,我寫程式真的算是初學者,甚至連基礎都不太會了,當在網路爬文的時候,很多時候都是看不懂得,但自己總是保持者「別人都可以,為何我不行?的心態去嘗試看看」往往這樣都會有不錯的結果,就算是做不出來,也是一個很不錯的經驗,這例子我只花了半天時間就可以製作出來,不瞞您們,這程式碼有三分之二看不懂,但最終還是被我亂矇亂搞給弄出來,真的很爽拉。網路上有提到工具可以查出問題,但只有點到為止,一開始我還真的不會用這工具,後來不小心把它稍微搞懂,於是也順便寫下來幫助其他網友,希望大家都能一起進步。









2015年11月26日 星期四

VS 2012 C# 巡覽控制項筆記 -- 20151126

巡覽控制項主要分三類(如下圖):

  • Menu
  • TreeView
  • SiteMapPath










首先要先知道「巡覽控制項」主要是呈現的網站導覽樣式(畫面),其需要搭配「SiteMapDataSource」取得各節點資料,然而「SiteMapDataSource」的資料來源取決於「Web.sitemap」檔案。
































※何謂「網頁瀏覽檔案(Web.sitemap)」?其功能有下列三項。

它是一個具備描述網站階層的XML檔案。透過修改Web.sitemap檔案來管理頁面巡覽,不需要修改網站內所有網頁中的超連結。


功能:

1. 網站導覽功能

2. 可繫結SiteMapPath網站地圖路徑

3. 可繫結TreeView與Menu控制項


Web.sitemap檔案,其預設基本架構(如下圖):









解說上述:

<?xml version="1.0" encoding="utf-8" ?>敘述,是用來宣告此份文件文XML結構,若沒加入此行敘述,則輸入中文字之後網站導覽路徑會以亂碼顯示。

<siteMap>標籤:用來定義網站導覽的架構。

<siteMapNode>標籤:用來設定每一個網頁的節點,且標籤可使用url、title、description三個屬性。




簡單來說,網站要用到導覽的話,須注意三個重點:

第一、優先製作Web.sitemap檔案(XML檔案)。

第二、使用Menu控制項與TreeView控制項要搭配SiteMapDataSource。

第三、可直接使用SiteMapPath控制項。





實際案例:



步驟一、先建置新的網站導覽檔案。







































開啟空白Web.sitemap檔案













建置相對應的導覽網頁內容,並儲存該檔案。





































步驟二、開啟已建好網頁(需要再Web.sitemap檔案內),將SiteMapPath控制項拖拉至「設計」網頁中,及即可。


































步驟三、同樣開啟主頁面,並將Menu控制項TreeView控制項拖拉至「設計」畫面中。此時出現「選擇資料來源:無。」




























根據上述Menu控制項需要資料來源,故再拖拉「SiteMapDataSource」在畫面中。
































再將Menu控制項的資料來源指向「SiteMapDataSource1」,即可。




























步驟四、按下F5鍵,看最後完成的畫面。























來源出處:ASP.NET 4.0 從零開始-使用C#2010  碩博文化













2015年8月24日 星期一

VS 2012 C# 有關GridView的光棒效果 -- 20150824

緣由:

早期光棓效果需要寫JavaScript才能做到,但現在Visual Studio內建就有光棒效果可以使用,容易讓使用者辨識目前所選擇的資料列。以下介紹三個方法可以輕鬆地呼叫出光棒效果。



方法一、點選GridView,選擇小箭頭,並勾選「樞紐分析表選取模式」。









































方法二、點選GridView,再透過GridView屬性,將AutoGenerateSelectButton:True。



方法三、點選GridView,選擇小箭頭,並選擇「編輯資料行」。
























選擇「CommandField」選項內的「選取」鈕,按下「加入」到選取的欄位中。最後按下「確定」鈕。


















備註:

假若您同時(方法一)和(方法二)--勾選「樞紐分析表選取模式」和修改--AutoGenerateSelectButton:True 時,這時會出現兩個「選擇」鈕,所以只需要修改一個地方就可以了。另外,這裡有發現一個BUG,當先將「樞紐分析表選取模式」取消勾選時,這時兩個「選擇」鈕會同時消失掉,若先AutoGenerateSelectButton屬性改為Fasle時,只會消失一個「選擇」鈕。





補充:若要修改光棒的顏色...等,可以SelectedRowStyle這屬性下手。(如下圖)
















































2015年7月24日 星期五

VS 2012 C# Page物件 -- 20150724

何謂網頁的「存留週期」?

當連線ASP.NET網頁時,伺服器端會有一連串處理過程,伺服器端處理完畢後才會將網頁送出,此處理過程便稱為「存留週期」。由此可知,一個網頁從開始到卸載,其生命其實在伺服器送出後便已經結束。(補充:20151126)



最常用到Page物件的重要屬性與方法:

  • Page.IsPostBack:檢查網頁是否為第一次連線或因PostBack而被載入
  →  屬性為False:表示用戶端是第一次連線
  →  屬性為True:網頁是因為PostBack而重新被執行。

※當網頁第一次連線時,進行變數、控制項的初始化、開啟檔案、連線資料庫取得所需資料,都可藉由此屬性來避免重複執行這些動作。
  • Page.IsValid:檢查網頁上所有驗證是否都已通過
  • Page.Title:取得或設定網頁的標題

--------重點:---------------------------------------------------------------------------------------

在Web畫面上「做的任何動作」,都會引起PostBack(回傳)動作,進而重新觸發Page_Load事件。例如:點TextBox、按任何一個Button按鈕.....等。所以在網頁設計中,加入一段If(!Page.PostBack) IF Not Page.PostBack的判別是來判斷「網頁是否第一次被執行?」。

----------------------------------------------------------------------------------------------------------------

案例:

當在網頁上按下Button按鈕的時候,會觸發Button1_Click事件,這是會導致回傳。根據ASP.NET為例的執行順序,如下:

1.先執行Page_Load事件。

2.接者才執行TextBox1_TextChanged事件。

3.最後才是Button1_Click事件。









2015年7月1日 星期三

VS 2012 C# 快速製作簡單搜尋引擎 -- 20150701

緣由:

想要學寫程式,但又覺得全部都是用寫的很累人,所以找尋最簡單不用寫太多的程式碼的方式,於是就嘗試、測試....再測試....最終成功後,把它一點一滴的紀錄下來,順便分享給網友們。



步驟一、透過元件先將畫面設計好。





















步驟二、設定SqlDataSource1的資料來源。






































※選擇資料來源的[資料表]與設定「Where查詢條件」。




































※選擇資料表中的[查詢欄位(CustName)]與設定查詢所用到的[控制項(TextBox1)]






























※確認[Where條件子句]已建立完成。









































































































步驟三、設定GridView1的資料來源為SqlDataSource1。
























步驟四、網頁畫面切換至「原始檔模式」,查看自動產生的程式碼。













































※稍微修改Where條件字句,將其改為「模糊查詢」條件。(如下圖)

程式碼:

       Select * From 資料表 Where 欄位A like '%欄位A%'















































※修改完程式碼後,切回至[設計模式]。





步驟五、測試查詢功能














結論:

透過工具能快速地解決問題才是王道,同樣能達到目的,為何不選擇簡單又快速的方式呢?我不排斥寫程式碼,但要我每個網頁都要用程式碼一個一個寫,對不起~我真的是做不到。只有頭殼壞掉的人才這樣做。