2017年9月30日 星期六

Google Cloud Platform 探索經驗 (5) - 將 Google Storage 中的檔案當網站

雖然 Google 有提供部落格 Blogger 可以使用,網路上也有教學將個人部落格改成公司網站使用,但畢竟是部落格的使用方式,在設計上難免會困難度較大。

所以 Google Cloud Platform 有另一個工具 - Storage 可以將寫好的網頁或檔案放在裡面(個人覺得類似於 Google 文件),可以公開連結給需要的人,就變成像是網站的感覺。

接下來就將個人的經驗寫下來供參考

【網站檔案設定】
步驟一:當然要先有 Google Cloud Platform (以下簡稱 GCP)的權限
步驟二:到 GCP 的控制台,展開左邊 ≡ 符號,然後點選 Storage

步驟三:建立 BUKET (此 BUKET 的名稱要和你的網域名稱相同)
步驟四:點選剛才建立 BUKET ,然後將 首頁錯誤頁 的網頁上傳

步驟五:在 BUKET 清單頁找到剛才建立的 BUKET 右邊會有一個 (三個黑點)的符號,點下去之後選擇 "編輯網站設定",將首頁和錯誤頁設好

步驟六:此時點選 BUKET 下的 index.html 的 公開連結,就可以看到網站的首頁了,但是此時網址還是你 Google Storage 的樣子,所以接下來要到你的網域申請的網站上設定DNS對應到的網址。


【網域申請與設定】-這邊是以免費網域申請(https://my.freenom.com/)為範例

步驟一:進入官網後,找到 SERVICE 下的 Register a New Domain,將想要的網域名稱打進去之後,按下 Check Availability,確認看看是否可用和所需費用,選擇清單中想要的那一個,按下 Get it now,然後按下上面的 checkout 後,選擇要用的區間(既然有 12 個月免費可以選,哪有不選的道理),選擇之後按下 Continue,在左下角填入你的 Email Address(這會用來確認並啟用),並按下 Verify My Email Address,然後到你的信箱去點確認連結。

步驟二:點下確認信中的連結後,會要你填寫一些資料(好像全部都是必填),然後勾選I have read and agree to the Terms & Conditions,然後按下 Complete Order,完成申請。

步驟三:完成申請後,要將 Google Storage 和 DNS 做連結,所以找到官網上的 Services 下的 My Domains,選擇剛才申請的 Domain 的 Manage Domain,再點選 Manage Freenom DNS 來設定關聯。


步驟四:先跳到 Google 的 Cloud Storage 文件(Hosting a Static Website)來看一下如何做確認,這邊說明要到你的DNS申請的地方做的設定,但設定前需要先做一下確認,所以先跳到Google 網站網理員中心,網頁告訴你驗證的方法。


步驟五:Google 網站網理員中心 ,按下新增資源,輸入要驗證的網域後按下繼續
,選擇 其他方法 > 網域名稱供應商 > 其他,選擇下方的 新增 CNAME 紀錄
這是要填入步驟三中的設定,供確認用

步驟六:我們將【網域申請與設定】步驟一申請的那個網域填入上列相對資訊,按下 Save Change
然後再回到步驟五的地方按下下方的"驗證",(驗證可能不會馬上生效,需要幾分鐘時間後,才會生效),如果驗證過了,表示你是該網域的擁有者。就會在你的資源清單中看到剛才的資源了


步驟七:開始瀏覽器,在網址列打上你設定的網域,就可以看到和 Google Storage 中一樣的網頁內容了 (如同【網站檔案設定】中的步驟六)


2017年7月25日 星期二

GridView 自訂分頁

一般 GridView 可以交給自動分頁產生出分頁效果,只需要將 GridView 的屬性 AllowPaging 設為 true,再搭配取得資料的語法,即可完成。
GridView 會依據資料筆數 和 GridView.PageCount 自動計算出頁數。
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        GridView1.DataSource = GetData();
        GridView1.DataBind();
    }
}

private DataTable GetData()
{
    // 讀取資料
}

// 翻頁時改變 PageIndex 後重新綁定 GridView 的資料
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    GridView gridview = (GridView)sender;
    GridView.PageIndex = e.NewPageIndex;
    GridView.DataSource = GetData();
    GridView.DataBind();
}
因為GridView其實是將全部的資料都載入後,只顯示某一頁的資訊出來,所以當讀取的資料太多時就會造成載入的間很久。


此時可以使用自訂分頁的方式,自訂分頁除了要將 GridView 的屬性 AllowPaging 設為 true 之外,還要將 GridView 的屬性 AllowCustomPaging 設為 true,然後再在程式碼中指定 GridView.VirtualItemCount (虛擬 GridView 總共有幾筆資料),然後 GridView 會依據 VirtualItemCount 和 GridView.PageCount 自動計算出頁數,具體做法大致如下:
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        // GridView.VirtualItemCount:虛擬 GridView 總共有幾筆資料
        GridView1.VirtualItemCount = GetAllDataCount();
        GridView1.DataSource = GetSpecPageData(0);
        GridView1.DataBind();
    }
}
private int GetAllDataCount()
{
    // 讀取全部資料的筆數
}

/// 只讀取指定頁的資料
private DataTable GetSpecPageData(int PageIndex)
{
    // 比方每頁要顯示 15 筆
    // 讀取第一頁要顯示的資料,那就只讀取 TOP 15
    // 或是若要讀取第三頁 31 到第 45 筆,則可以用 OFFSET 30 ROWS FETCH NEXT 15 ROWS ONLY
    // 意思是是位移 30 筆之後,再往下取 15 筆資料
   請參考MIS2000 Lab
}

翻頁時改變 PageIndex 後重新綁定 GridView 的資料
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    GridView gridview = (GridView)sender;
    GridView.PageIndex = e.NewPageIndex;
    GridView.DataSource = GetSpecPageData(e.NewPageIndex);
    GridView.DataBind();
}
此時遇到的題目是 GridView 的每頁筆數不一致(比方某個欄位要固定只顯示幾種資料),所以除了上述的寫法之外,還要加上一點點修正,如下:

加上一個全域變數,用以儲存每頁的筆數資訊
Dictionary<int, int> dictCountPerPage;
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        dictPerPageCount = GetPerPageCount();
        GridView1.PageCount = dictPerPageCount[0];  // 指定第一頁的筆數
        // GridView.VirtualItemCount:計算虛擬 GridView 總共有幾筆資料(因為每頁筆數不一,所以以要顯示的該頁的筆數當基準,用以計算出虛擬總筆數,好產生頁數(碼)         GridView1.VirtualItemCount = GridView1.PageCount * dictPerPageCount.Count;         GridView1.DataSource = GetSpecPageData(0);         GridView1.DataBind();     } } /// 依需求記錄每頁要顯示的資料筆數 /// Key: 頁碼, Value: 每頁到第幾筆資料 private Dictionary<int, int> GetPerPageCount() {     // 讀取全部每頁的資料的筆數     // 例如:     // Dictionary<int, int> dict = new Dictionary<int, int>();     // dict.Add(0, 10); // 第 1 頁: 0~10 筆     // dict.Add(1, 16); // 第 2 頁: 11~16 筆    // dict.Add(2, 18); // 第 3 頁: 17~18 筆     // dict.Add(3, 22); // 第 4 頁: 19~22 筆     // Session.Add("PerPageCount", dictPerPageCount); 將分頁資訊記錄在 Session     // return dict; }
/// 只讀取指定頁的資料 private DataTable GetSpecPageData(int PageIndex) {     // 比方每頁要顯示 15 筆     // 讀取第一頁要顯示的資料,那就只讀取 TOP 15     // 或是若要讀取第三頁 31 到第 45 筆,則可以用 OFFSET 30 ROWS FETCH NEXT 15 ROWS ONLY     // 意思是是位移 30 筆之後,再往下取 15 筆資料     請參考MIS2000 Lab     // SQL 語法:    StringBuilder SQL = new StringBuilder("...");     SQL.Append(" ORDER BY 1, 2, 3, 4");     // 取回第幾筆~第幾筆資料     if (CurrentPage == 0)         SQL.AppendFormat(" OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY", 0, dicRowCountPerPage[CurrentPage]);     else         SQL.AppendFormat(" OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY", dictCountPerPage[PageIndex- 1], dictCountPerPage[PageIndex] - dictCountPerPage[PageIndex- 1]);     // 每次都重新指定 PageCount 和 VirtualItemCount     if (PageIndex== 0)         GridView1.PageSize = dictCountPerPage[PageIndex];     else         GridView1.PageSize = dictCountPerPage[PageIndex] - dictCountPerPage[PageIndex - 1];     GridView1.VirtualItemCount = GridView1.PageSize * dictCountPerPage.Count; } /// 翻頁時改變 PageIndex 後重新綁定 GridView 的資料 protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e) {     GridView gridview = (GridView)sender;     GridView.PageIndex = e.NewPageIndex;     if (dictCountPerPage == null)         dictCountPerPage = (Dictionary<int, int>)Session["PerPageCount"];     GridView.DataSource = GetSpecPageData(e.NewPageIndex);     GridView.DataBind(); }

2017年6月16日 星期五

ASP.NET AJAX 的 UpdateProgress

雖然 VISUAL STUDIO 有提供 UpdateProgress 可以使用,而且也會在更新時出現,更新後就消失,但總覺得顯示的位置不太好控制,所以就乾脆把整個畫面都變色,這樣就可以達到提醒的作用了,方法如下,將 updateprogress 裡面放上想要顯示的字或 gif,然以用 span 將它包起來,然後再用另一個 div,將全部包起來,再用 css  的效果顯示半透明色和調整位置。

Sample.aspx
<style>
.LoadingCover {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    color: white;
    font-size: 20px;
    line-height: 100%;
    background: rgba(0%,0%,0%,0.6);
    z-index: 998;
}

.LoadingContent {
    width: 200px;
    height: 100px;
    position: relative;
    top: 50%;
    left: 50%;
    margin-top: -50px;
    margin-left: -100px;
}
</style>

<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" OnLoad="UpdatePanel1_Load">
    <ContentTemplate>
         要更新的內容
    </ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="UpdateProgress1" runat="server" AssociatedUpdatePanelID="UpdatePanel1">
    <ProgressTemplate>
        <div class="LoadingCover">
            <span class="LoadingContent">Loading...</span>
        </div>
    </ProgressTemplate>
</asp:UpdateProgress>      

2017年5月5日 星期五

Google Cloud Platform 探索經驗 (1) - 專案建立

1.當然要先有一個 GOOGLE 帳號,然後登入 Google Cloud Platform 首頁
2.點選網頁左上方"請選取專案"來建立或選擇專案

     如果都沒建立過任一專案,則會出現以下畫面,然後點選畫面右方的"+"來建立新專案
建立新專案 / 選擇專案

輸入專案名稱與專案ID
       專案新專案會需要一段時間,待右上方出現訊息時,表示建立完成
建立專案中

專案建立完成
3.完成後再點擊一次左上角的 ≡ 符號,可看到目前的資訊主頁




Windows 下安裝 MySQL Client

1.到MySQL 官網下載安裝檔
2.安裝過程中選擇 Client Only 選項即可
3.安裝過程中會檢查必要安裝,
      若缺少 Visual Studio Tools For Office 2010,則到微軟官網下載
      若缺少 Python 3.4,則到 Python官網下載(for Windows 版本),或參考這篇文章
       先把 Visual Studio For Office 2010 和 Python 3.4 安裝起來

4.安裝完之後,可以選擇畫面中的單選鈕後,按下下方的"Check"鈕後,即可往下一步安裝
5.按下Execute,後即完成安裝,過程中可能會有些東西要手動按下 "try again",其中 "MySQL for Visual Studio 1.2.7" 會安裝比較久

       全部安裝完成,即可按下下一步
6.這邊會顯示接下來會做哪些東西的設定
 7.MySQL Router 的設定:如果要設定,可以勾選之後,就會可以編輯相關的連線資訊,或者之後再設定,則把勾勾拿掉,直接按下一步




2017年3月29日 星期三

發佈網站時 IIS 的預設文件(自訂首頁)都會被清掉

每次在 Visual Studio 按下發行到網站時,自訂的首頁都會被重置,
















需要手動再加一遍,此時可以在 Web.Config 檔案裡加入以下幾行即可排除。

<configuration>
  <system.webServer>  
    <defaultDocument>
      <files>
        <add value="MyLoginPage.aspx"/> ←MyLoginPage.aspx 是自訂的首頁
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>

2017年3月15日 星期三

出現找不到 icsharpcode.sharpziplib ..的錯誤時

如題,在config檔中加上
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="ICSharpCode.SharpZipLib" publicKeyToken="1b03e6acf1164f73" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-0.86.0.518" newVersion="0.86.0.518" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

2017年3月13日 星期一

INSERT 後取回最新的 ID

假設有一 [TABLE1],其下欄位為 ID、COLUMN_1 和 COLUMN_2
欄位 ID 設為自動增長

在下了 INSERT 後要取得剛才新增的 ID 時,可以這麼做:
INSERT INTO [TABLE1] (COLUMN_1, COLUMN_2) OUTPUT INSERTED.ID VALUES (DATA1, DATA2)

其中 INSERTED 為 SQL 在建立新資料列時,會暫存的位置,
所以 INSERTED 會找到 [TABLE1] 中的相關資料

同樣的,上述語法也可以用在 UPDATE 上
UPDATE [TABLE1] SET COLUMN_1 = @DATA1, COLUMN_2 = @DATA2 OUTPUT DELETED.ID WHERE ID = 'SomeData'
此時可以取得 UPDATE 是否有影響預期中的資料筆數,可得知是否有更新資料,進而處理下一步(比方:若沒有任何更新表示查詢的資料不存在)
而不需要先查詢有沒有存在,再判斷動作

2017年3月1日 星期三

網頁另開視窗回傳值

【父網頁】

<javascript>

<script>
// 以Post的方式傳值
// url: 開的視窗網址
// name: 開的視窗名稱(可有可無)
// targetid: 回傳後要顯示在哪個元件上
// keys、values: 均以 ['key1','key2']、['value1','value2'] 成對表示
function openWindowWithPost(url, name, targetid, keys, values) {
           
            _targetid = targetid;
            var newWindow = window.open(url, name, "width=" + 600 + "px,height=" + 400 + "px,left=" + 0 + ",top=" + 0);
            //同时将焦点事件绑定,目的是,当点击父窗口时,如果子窗口尚未关闭,那依然回到子窗口,做到类似模式窗口的效果
            window.onfocus = function () { if (newWindow.closed == false) { newWindow.focus(); }; };

            var html = "";
            html += "<html><head></head><body><form id='formid' method='post' action='" + url + "'>";
            if (keys && values && (keys.length == values.length)) {
                for (var i = 0; i < keys.length; i++) {
                    html += "<input type='hidden' name='" + keys[i] + "' value='" + values[i] + "'/>";
                }
            }
            html += "</form><script type='text/javascript'>document.getElementById(\"formid\").submit()<\/script></body></html>";
            newWindow.document.write(html);
            return newWindow;
        }

// 子網頁回傳回來的值在這邊處理
function handleReturnValue(val) {          
            $("#" + _targetid)[0].value = val.join();          
        }
</script>

<html>

<input type="text" id="returnData" >
<input type="button" value="開子視窗" onclick="openWindowWithPost('子視窗的網頁','NewWindowName','returnData',['memberID'],['mem1','mem2'])" />



【子網頁】

<javascript>

<script type="text/javascript">
        // 判斷瀏覽器種類
        function getBrowserType() {
            var Sys = {};
            var ua = navigator.userAgent.toLowerCase();
            if (window.ActiveXObject)
                Sys.ie = ua.match(/msie ([\d.]+)/)[1]
            else if (document.getBoxObjectFor)
                Sys.firefox = ua.match(/firefox\/([\d.]+)/)[1]
            else if (window.MessageEvent && !document.getBoxObjectFor)
                Sys.chrome = ua.match(/chrome\/([\d.]+)/)[1]
            else if (window.opera)
                Sys.opera = ua.match(/opera.([\d.]+)/)[1]
            else if (window.openDatabase)
                Sys.safari = ua.match(/version\/([\d.]+)/)[1];

            if (Sys.ie) return "IE";
            if (Sys.chrome) return 'Chrome';
            if (Sys.firefox) return "Firefox";
            if (Sys.opera) return "Opera";
            if (Sys.safari) return "Safari";

            return "IE";
        }

        // 當關閉子網頁後,要做的動作
        function closeWindow() {    
            // val: 為要回傳給父網頁的物件(或值)    
            var val = $("#cbxMembers input:checked").map(function(){
                return $(this).val();
            }).get();  // 回傳父視窗的值          
           
            if ("IE" == getBrowserType())
                self.returnValue = val;   //IE:直接回傳
            else
                window.opener.handleReturnValue(val); //非IE,調用父視窗的函數來回傳值
            self.close();
        }
    </script>

<html>

<input type="button" value="確定"<input type="button" name="button1" value="確定" onclick="closeWindow();" />


參考:
http://www.weibo.com/p/230418671432cf0102v6rf?pids=Pl_Official_CardMixFeed__4&feed_filter=1

http://www.blogjava.net/kait/archive/2011/05/27/351138.html

2017年1月16日 星期一

Excel 巨集 - 開啟檔案→修正

Sub 巨集1()
'
' 巨集1 巨集
'

'
    For i = 1 To 11
        n = Right(String(2, "0") & i, 3)
        Workbooks.Open Filename:="C:\Users\Min\Downloads\TEMP\TEST_" & n & ".csv"
        Range("B1").Select
        ActiveCell.FormulaR1C1 = "新欄位名稱1"
        Range("D1").Select
        ActiveCell.FormulaR1C1 = "新欄位名稱2"
        Range("F1").Select
        ActiveCell.FormulaR1C1 = "新欄位名稱3"
        Range("F2").Select
        Cells.Replace What:="=-不分區", Replacement:="000-不分區", LookAt:=xlPart, _
            SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
            ReplaceFormat:=False
        ChDir "C:\Users\Min\Downloads\TEMP"
        ActiveWorkbook.SaveAs Filename:= _
            "C:\Users\Min\Downloads\TEMP\TEST_" & n & ".xlsx", FileFormat:= _
            xlOpenXMLWorkbook, CreateBackup:=False
    Next i
End Sub