Esempio n. 1
0
        private void F_Data_LoadCompleted(object sender, FrameLoadCompleteEventArgs e)
        {
            log.Debug($"++ Enter F_Data_LoadCompleted from {e.Message}.");
            if (e.Message == FrameLoadStates.DocumentLoadCompletedButNotFrame)
            {
                return;
            }
            // 每當刷新後都要重新讀一次
            // d 是parent HTML document
            HTMLDocument d = (HTMLDocument)g.Document;

            #region 感知目前位置, 與current_op比較, 如果不是,就還是要再按一次

            // 目標: current_op.TAB_ID
            // 實際: d.getElementById(current_op.TAB_ID.Replace("_a_", "_li_")).className == "active"
            if (d.getElementById(current_op.TAB_ID.Replace("_a_", "_li_")).className != "active")
            {
                // 不active反而可以用按鍵, 自動會觸發F_Data_LoadCompleted
                // 20210719 有時候不fire
                Thread.Sleep(150);
                d.getElementById(current_op.TAB_ID).click();
                log.Info($"[Action] push TAB {current_op.TAB_ID} Button.");
                log.Debug($"++ Exit F_Data_LoadCompleted (1/4). Not in the right page, click again.");
                return;
            }
            #endregion

            /// 20210719: 將QDATE設定為1901/1/1, 是傳達這是最後一頁了, 設定在F_Pager_LoadCompleted
            /// 20210719: 刪除掉蠢蠢的current_op?.QDate = 1901/1/1
            ///if (current_op?.QDate == DateTime.Parse("1901/01/01"))
            ///{
            ///    // 不用再讀取資料了, 直接到存入資料庫部分
            ///    log.Info($"Entered F_Data_LoadCompleted, {current_op?.UID} 已經讀完所有資料, 最後存入資料庫.");
            ///}
            ///else
            ///{
            /// 還需要讀取資料
            log.Info($"Current OP: {current_op?.UID} {current_op?.Short_Name}");
            //}
            log.Debug($"@@ delete delegate F_Data_LoadComplated. [{current_op?.UID}]");
            fm.FrameLoadComplete -= F_Data_LoadCompleted;

            // 這時候已經確保是 active
            // f 是frame(0) HTML document
            HTMLDocument f = d?.frames.item(0).document.body.document;

            /// 3. 網頁操弄與擷取資料: sequential
            ///     3-1. 判斷分頁, 有幾頁, 現在在第幾頁, 換頁不會觸發LoadCompleted; 疑問會不會來不及? -done
            ///     3-2. 要先排序, 排序也不會觸發LoadCompleted; 疑問會不會來不及?  -done, 不用再管排序
            ///     3-2. 都放在記憶體裡, 快速, in the LIST
            ///

            // special remark: current_op.QDate set to null 是表示來自多頁結束那裏

            // 20210719: 將QDATE設定為1901/1/1, 是傳達這是最後一頁了, 設定在F_Pager_LoadCompleted
            // 20210719: 刪除掉蠢蠢的current_op?.QDate = 1901/1/1
            //if ((current_op != null) && (current_op?.QDate != DateTime.Parse("1901/01/01")))
            if (current_op != null)
            {
                // 表示不是最後一頁, 還要讀取資料
                log.Info($"[Action] Reading HTML: {current_op.Short_Name}, [{current_op?.UID}]");

                #region 讀取資料, 存入記憶體, 存入檔案

                foreach (Target_Table tt in current_op.Target)
                {
                    // 是否有多tables, 端看tt.Children, 除了管制藥物外, 其餘都不用
                    if (tt.Children == null)
                    {
                        try
                        {
                            // 20210718: 好像就是這裏出了問題
                            ListRetrieved.Add(new VPN_Retrieved(tt.Short_Name, tt.Header_Want, f.getElementById(tt.TargetID).outerHTML, current_op.UID, current_op.QDate));

                            // 20200606 stop recording tables in html
                            // 20210716 resume recording tables in html
                            SaveHTML($"{tt.Short_Name}_{current_op.UID}", f.getElementById(tt.TargetID).outerHTML);
                        }
                        catch (Exception ex)
                        {
                            // 存入空的HTML
                            ListRetrieved.Add(new VPN_Retrieved(tt.Short_Name, tt.Header_Want, "", current_op.UID, current_op.QDate));
                            log.Error($"  Failed to read html. From:  {tt.Short_Name}. Error: {ex.Message}");
                        }
                    }
                    else
                    {
                        // 有多個table, 使用情形僅有管制藥物
                        ListRetrieved.Add(new VPN_Retrieved(tt.Short_Name, tt.Header_Want, f.getElementById(tt.TargetID).children(tt.Children).outerHTML, current_op.UID, current_op.QDate));

                        SaveHTML($"{tt.Short_Name}_{tt.Children}_{current_op.UID}", f.getElementById(tt.TargetID).outerHTML);
                    }
                }

                #endregion 讀取資料, 存入記憶體, 存入檔案

                #region 判斷多頁

                // 目前重點, 如何判斷多頁?
                // 設定total_pages = ????
                HtmlDocument p = new HtmlDocument();
                if (f.getElementById(@"ctl00$ContentPlaceHolder1$pg_gvList_input") == null)
                {
                    log.Info($"[Info] Only one page detected, {current_op?.UID} {current_op?.Short_Name}.");
                    total_pages = 1;
                }
                else
                {
                    // 如果多頁, 轉換loadcomplete, 呼叫pager by click
                    // 20200502: outerHTML的XPATH="//selection/option", innerHTML的XPATH="//option"
                    p.LoadHtml(f.getElementById(@"ctl00$ContentPlaceHolder1$pg_gvList_input").innerHTML);
                    HtmlNodeCollection o = p.DocumentNode.SelectNodes("//option");
                    total_pages = o.Count;
                    log.Info($"[Info] {total_pages} pages detected, {current_op?.UID} {current_op?.Short_Name}");

                    // 剛剛已經讀了第一頁了, 從下一頁開始
                    current_page = 2;
                    // 按鈕機制
                    fm.FrameLoadComplete += F_Pager_LoadCompleted;
                    // 轉軌
                    log.Debug($"@@ add delegate F_Pager_LoadCompleted.");
                    Thread.Sleep(150);
                    foreach (IHTMLElement a in f.getElementById("ContentPlaceHolder1_pg_gvList").all)
                    {
                        if (a.innerText == ">")
                        {
                            log.Info("[Action] 按了下一頁.");
                            log.Debug($"++ Exit F_Data_LoadCompleted (2/4). Multipage, go to next page.");
                            a.click();
                            // 20200504 發現這裡執行完後還會執行後面的程序, 造成兩個程序的衝突
                            // 此段程式的一個出口點
                            return;
                        }
                    }
                }
                #endregion 判斷多頁
            }

            // 判斷是否最後一tab, 程序群的出口
            if (QueueOperation.Count == 0)
            {
                // 兩個出口之一, 最後一個tab, 另一個出口是, 最後一個tab, 同時沒有其他page, 另一個在F_Pager_LoadCompleted
                // 20210719: 讀完實體資料就開始解析HTML吧
                string o = $"++ Exit F_Data_LoadCompleted (3/4). The REAL END! [{current_op.UID}]";
                ParsingTables(o);

                return;
            }
            else
            {
                // 下一個tab
                current_op            = QueueOperation.Dequeue();
                fm.FrameLoadComplete += F_Data_LoadCompleted;
                log.Debug($"@@ add delegate F_Data_LoadCompleted. [{current_op.UID}]");
                Thread.Sleep(150);
                d.getElementById(current_op.TAB_ID).click();
                log.Debug($"[Action] {current_op.TAB_ID} tab key pressed. [{current_op.UID}]");
                log.Debug($"++ Exit F_Data_LoadCompleted (4/4). Go to next tab. {QueueOperation.Count + 1} tabs to go.. [{current_op.UID}]");
                return;
            }
        }
        private void F_LoadCompleted(object sender, FrameLoadCompleteEventArgs e)
        {
            log.Debug($"++ Enter F_LoadCompleted from {e.Message}.");
            // 20200509 因為沒有先 -= F_LoadComplted, 造成了幽靈, 因此一定要 -= F_LoadComplted 在任何Exit之前.
            // 每次作業F_LoadCompleted只會被呼叫一次,沒有被洗掉的情形
            fm.FrameLoadComplete -= F_LoadCompleted;
            log.Debug($"@@ delete delegate F_LoadCompleted.");

            // 使用DocumentLoadCompletedButNotFrame, 會造成偶而不動作的症狀, 要找別的方式來處理沒插健保卡的判別
            // 方法

            if (e.Message == FrameLoadStates.DocumentLoadCompletedButNotFrame)
            {
                // 沒有lbluserID, 例如沒插健保卡
                // activate hotkeys 1
                Activate_Hotkeys();
                log.Debug($"++ Exit F_LoadCompleted (1/5). No NHI card inserted.");
                log.Info("===========================================================================");
                log.Info($" ");
                return;
            }
            /// 會有兩次
            /// 第一次讀完檔案會再執行javascript, 在local用來認證健保卡, 沒過就不會有第二次
            /// 如果認證OK, 會再透過javascript下載個案雲端資料, 觸發第二次
            /// 這段程式的目的:
            /// 1. 取得身分證字號
            /// 2. 讀取有哪些tab

            // 20210719: mark this line to simplify logging
            // log.Info($"Entered F_LoadCompleted");

            HTMLDocument d = (HTMLDocument)g.Document;
            // 確定身分證字號
            string strUID = MakeSure_UID(d.getElementById("ContentPlaceHolder1_lbluserID").innerText);

            // if (strUID = string.Empty) 離開
            if (strUID == string.Empty)
            {
                tb.ShowBalloonTip("醫療系統資料庫查無此人", "請與杏翔系統連動, 或放棄操作", BalloonIcon.Warning);

                // activate hotkeys 2
                Activate_Hotkeys();
                log.Debug($"++ Exit F_LoadCompleted (2/5). NHI card inserted but no such person.");
                log.Info("===========================================================================");
                log.Info($" ");
                return;
            }
            else
            {
                /// 表示讀卡成功
                /// show balloon with built-in icon
                tb.ShowBalloonTip("讀卡成功", $"身分證號: {strUID}", BalloonIcon.Info);
                log.Info($"  Successful NHI card read, VPN id: {strUID}.");

                /// 讀卡成功後做三件事: 讀特殊註記, 讀提醒, 開始準備讀所有資料

                /// 2. 讀取提醒, 如果有的話
                ///    這是在ContentPlaceHolder1_GV
                ///    也是個table
                IHTMLElement List_NHI_lab_reminder = d?.getElementById("ContentPlaceHolder1_GV");
                if (List_NHI_lab_reminder != null)
                {
                    HtmlDocument Html_NHI_lab_reminder = new HtmlDocument();
                    Html_NHI_lab_reminder.LoadHtml(List_NHI_lab_reminder?.outerHTML);

                    // 寫入資料庫
                    foreach (HtmlNode tr in Html_NHI_lab_reminder.DocumentNode.SelectNodes("//table/tbody/tr"))
                    {
                        HtmlDocument h_ = new HtmlDocument();
                        h_.LoadHtml(tr.InnerHtml);
                        HtmlNodeCollection tds = h_.DocumentNode.SelectNodes("//td");

                        if ((tds == null) || (tds.Count == 0))
                        {
                            continue;
                        }
                        string Lab_Name = string.Empty, Last_Date = string.Empty;
                        // tds[0] 是檢查(驗)項目類別名稱
                        Lab_Name = tds[0]?.InnerText;
                        // tds[1] 是最近1次檢查日期
                        Last_Date = tds[1]?.InnerText;

                        using (Com_clDataContext dc = new Com_clDataContext())
                        {
                            var q1 = from p1 in dc.tbl_NHI_lab_reminder
                                     where (p1.uid == strUID) && (p1.lab_name == Lab_Name) && (p1.last_date == Last_Date)
                                     select p1;
                            if (q1.Count() == 0)
                            {
                                tbl_NHI_lab_reminder newReminder = new tbl_NHI_lab_reminder()
                                {
                                    uid       = strUID,
                                    QDATE     = DateTime.Now,
                                    lab_name  = Lab_Name,
                                    last_date = Last_Date
                                };
                                dc.tbl_NHI_lab_reminder.InsertOnSubmit(newReminder);
                                dc.SubmitChanges();
                            }
                        };
                    }
                }

                /// 準備: 初始化, 欄位基礎資料/位置, 可在windows生成時就完成

                #region 準備 - 製造QueueOperation

                // Initialization
                QueueOperation?.Clear();
                ListRetrieved?.Clear();
                current_page = total_pages = 0;

                log.Info($"  start reading Operation(s).");
                // 讀取所有要讀的tab, 這些資料位於"ContentPlaceHolder1_tab"
                // IHTMLElement 無法轉型為 HTMLDocument
                // 20200429 tested successful
                IHTMLElement List_under_investigation = d?.getElementById("ContentPlaceHolder1_tab");
                // li 之下就是 a
                List <string> balloonstring = new List <string>();
                string        BalloonTip    = string.Empty;
                foreach (IHTMLElement hTML in List_under_investigation?.all)
                {
                    if (tab_id_wanted.Contains(hTML.id))
                    {
                        // 僅將要讀入的排入, 並沒有真的讀取資料
                        VPN_Operation vOP = VPN_Dictionary.Making_new_operation(hTML.id, strUID, DateTime.Now);
                        QueueOperation.Enqueue(vOP);
                        log.Info($"    讀入operation: {vOP.Short_Name}, [{strUID}]");
                        balloonstring.Add(vOP.Short_Name);
                    }
                }

                for (int i = 0; i < balloonstring.Count; i++)
                {
                    if (i == 0)
                    {
                        BalloonTip = balloonstring[i];
                    }
                    else if ((i % 3) == 0)
                    {
                        BalloonTip += $";\r\n{balloonstring[i]}";
                    }
                    else
                    {
                        BalloonTip += $"; {balloonstring[i]}";
                    }
                }
                log.Info($"  end of Reading Operation(s), 共{QueueOperation?.Count}個Operation(s).");

                #endregion 準備 - 製造QueueOperation

                #region 執行

                if (QueueOperation.Count > 0)
                {
                    // 流程控制, fm = framemonitor

                    // 載入第一個operation
                    //log.Info($"  the first operation loaded.");
                    current_op = QueueOperation.Dequeue();
                    tb.ShowBalloonTip($"開始讀取 [{current_op.UID}]", BalloonTip, BalloonIcon.Info);

                    // 判斷第一個operation是否active, (小心起見, 其實應該不可能不active)
                    // 不active就要按鍵
                    // 要注意class這個attribute是在上一層li層, 需把它改過來
                    if (d.getElementById(current_op.TAB_ID.Replace("_a_", "_li_")).className == "active")
                    {
                        // 由於此時沒有按鍵, 因此無法觸發LoadComplete, 必須人工觸發
                        fm.FrameLoadComplete += F_Data_LoadCompleted;
                        log.Debug($"@@ Add delegate F_Data_LoadCompleted.");
                        FrameLoadCompleteEventArgs ex = new FrameLoadCompleteEventArgs()
                        {
                            Message = FrameLoadStates.DirectCall
                        };
                        log.Debug($"++ Exit F_LoadCompleted (3/5). Goto F_Data_LoadCompleted by direct call.");
                        F_Data_LoadCompleted(this, ex);
                        return;
                    }
                    else
                    {
                        // 不active反而可以用按鍵, 自動會觸發F_Data_LoadCompleted
                        fm.FrameLoadComplete += F_Data_LoadCompleted;
                        log.Debug($"@@ Add delegate F_Data_LoadCompleted.");
                        // 20210719 有時候不fire
                        Thread.Sleep(150);
                        d.getElementById(current_op.TAB_ID).click();
                        log.Info($"[Action] push TAB {current_op.TAB_ID} Button.");
                        log.Debug($"++ Exit F_LoadCompleted (4/5). Go to next tab by pushing tab button.");
                        return;
                    }
                }
                else
                {
                    // 做個紀錄
                    // 一個都沒有
                    log.Info($"  no record at all.");
                    tb.ShowBalloonTip("沒有資料", "健保資料庫裡沒有資料可讀取", BalloonIcon.Info);
                    // 製作紀錄by rd
                    tbl_Query2 q = new tbl_Query2()
                    {
                        uid         = strUID,
                        QDATE       = DateTime.Now,
                        cloudmed_N  = 0,
                        cloudlab_N  = 0,
                        schedule_N  = 0,
                        op_N        = 0,
                        dental_N    = 0,
                        allergy_N   = 0,
                        discharge_N = 0,
                        rehab_N     = 0,
                        tcm_N       = 0
                    };
                    using (Com_clDataContext dc = new Com_clDataContext())
                    {
                        dc.tbl_Query2.InsertOnSubmit(q);
                        dc.SubmitChanges();
                    };

                    // activate hotkeys 3
                    Activate_Hotkeys();
                    log.Debug($"++ Exit F_LoadCompleted (5/5). NHI inserted and verified but completey no data.");
                    log.Info("===========================================================================");
                    log.Info($" ");
                }

                #endregion 執行
            }
        }
Esempio n. 3
0
        private async void ParsingTables(string o)
        {
            tb.ShowBalloonTip($"讀取完成 [{current_op?.UID}]", "開始解析與寫入資料庫", BalloonIcon.Info);
            log.Info($"[Info] all HTML loaded into memory. start to analyze. [{current_op?.UID}]");

            // Count = 0 代表最後一個 tab
            // 20200504 這裡一個BUG, 漏了把F_DATA_Loadcompleted刪掉,以至於不斷重複多次. ******

            /// 確定是最後一個tab這段程式到此結束
            /// 4. Parsing & Saving to SQL: async
            ///     4-1. 多工同時處理, 快速
            ///     4-2. 依照欄位資料/位置 Parsing
            ///     4-3. 存入SQL
            ///     4-4. 製作Query
            /// 查核機制?
            log.Debug($"[Start] async process, {current_op?.UID}");
            List <Response_DataModel> rds = await VPN_Dictionary.RunWriteSQL_Async(ListRetrieved);

            log.Debug($"[End] async process, {current_op?.UID}");

            /// 1. 讀取特殊註記, 如果有的話
            ///    這是在ContentPlaceHolder1_tab02
            ///    是個table
            // 每當刷新後都要重新讀一次
            // d 是parent HTML document
            HTMLDocument d = (HTMLDocument)g.Document;

            IHTMLElement Special_remark  = d?.getElementById("ContentPlaceHolder1_tab02");
            string       _special_remark = Special_remark?.innerText;

            // 製作紀錄by rd
            try
            {
                short?med_N = (short?)(from p1 in rds
                                       where p1.SQL_Tablename == SQLTableName.Medicine
                                       select p1.Count).Sum(),
                     lab_N = (short?)(from p1 in rds
                                      where p1.SQL_Tablename == SQLTableName.Laboratory
                                      select p1.Count).Sum(),
                     schedule_N = (short?)(from p1 in rds
                                           where p1.SQL_Tablename == SQLTableName.Schedule_report
                                           select p1.Count).Sum(),
                     op_N = (short?)(from p1 in rds
                                     where p1.SQL_Tablename == SQLTableName.Operations
                                     select p1.Count).Sum(),
                     dental_N = (short?)(from p1 in rds
                                         where p1.SQL_Tablename == SQLTableName.Dental
                                         select p1.Count).Sum(),
                     allergy_N = (short?)(from p1 in rds
                                          where p1.SQL_Tablename == SQLTableName.Allergy
                                          select p1.Count).Sum(),
                     discharge_N = (short?)(from p1 in rds
                                            where p1.SQL_Tablename == SQLTableName.Discharge
                                            select p1.Count).Sum(),
                     rehab_N = (short?)(from p1 in rds
                                        where p1.SQL_Tablename == SQLTableName.Rehabilitation
                                        select p1.Count).Sum(),
                     tcm_N = (short?)(from p1 in rds
                                      where p1.SQL_Tablename == SQLTableName.TraditionalChineseMedicine_detail
                                      select p1.Count).Sum();
                Com_clDataContext dc = new Com_clDataContext();
                tbl_Query2        q  = new tbl_Query2()
                {
                    uid    = ListRetrieved.First().UID,
                    QDATE  = ListRetrieved.First().QDate,
                    EDATE  = DateTime.Now,
                    remark = _special_remark
                };
                q.cloudmed_N  = med_N;
                q.cloudlab_N  = lab_N;
                q.schedule_N  = schedule_N;
                q.op_N        = op_N;
                q.dental_N    = dental_N;
                q.allergy_N   = allergy_N;
                q.discharge_N = discharge_N;
                q.rehab_N     = rehab_N;
                q.tcm_N       = tcm_N;
                dc.tbl_Query2.InsertOnSubmit(q);
                dc.SubmitChanges();
                log.Info($"[Final Step]Successfully write into tbl_Query2. From: {ListRetrieved.First().UID}, [{ListRetrieved.First().QDate}]");
                tb.ShowBalloonTip($"寫入完成 [{current_op?.UID}]", "已寫入資料庫", BalloonIcon.Info);
            }
            catch (Exception ex)
            {
                log.Error($"[Final Step]Failed to write into tbl_Querry2. From:  {ListRetrieved.First().UID}, [{ListRetrieved.First().QDate}] Error: {ex.Message}");
            }

            // 更新顯示資料
            string tempSTR = s.m.Label1.Text;

            s.m.Label1.Text = string.Empty;
            s.m.Label1.Text = tempSTR;
            s.m.Web_refresh();

            // activate hotkeys 4
            Activate_Hotkeys();

            log.Debug(o);
            log.Info("===========================================================================");
            log.Info($" ");
        }
Esempio n. 4
0
        private void F_Pager_LoadCompleted(object sender, FrameLoadCompleteEventArgs e)
        {
            log.Debug($"++ Entered F_Pager_LoadCompleted from {e.Message}");
            if (e.Message == FrameLoadStates.DocumentLoadCompletedButNotFrame)
            {
                return;
            }
            log.Debug($"@@ delete delegate F_Pager_LoadComplated. [{current_op?.UID}]");
            fm.FrameLoadComplete -= F_Pager_LoadCompleted;

            // 每當刷新後都要重新讀一次
            // d 是parent HTML document
            HTMLDocument d = (HTMLDocument)g.Document;
            // f 是frame(0) HTML document
            HTMLDocument f = d.frames.item(0).document.body.document;

            // 讀取資料
            foreach (Target_Table tt in current_op.Target)
            {
                // 這裡不用管多table, 因為多table只發生在管制藥那裏
                ListRetrieved.Add(new VPN_Retrieved(tt.Short_Name, tt.Header_Want, f.getElementById(tt.TargetID).outerHTML, current_op.UID, current_op.QDate));

                SaveHTML($"{tt.Short_Name}_{current_op.UID}", f.getElementById(tt.TargetID).outerHTML);
            }
            log.Info($"[Action] Reading HTML: {current_op.Short_Name}, [{current_op.UID}]. page: {current_page}/{total_pages}");

            // 判斷是否最後一頁, 最後一tab
            if ((current_page == total_pages) && (QueueOperation.Count == 0))
            {
                // 兩個出口之一, 最後一個tab, 另一個出口是, 最後一個tab, 同時有其他page且為最後一頁,
                // 另一個在F_Data_LoadCompleted

                // 最後一頁
                // 處理index
                current_page = total_pages = 0;

                // 20200506: current_op 歸零似乎是不行的
                //current_op = null;
                // 20210719: 將QDATE設定為1901/1/1, 是傳達這是最後一頁了, 設定在F_Pager_LoadCompleted
                // 20210719: 移除這個愚蠢的方法
                //current_op.QDate = DateTime.Parse("1901/01/01");

                //// 這是沒有用的add delegate, 但是為了平衡, 避免可能的錯誤
                //fm.FrameLoadComplete += F_Data_LoadCompleted;
                //log.Info("  add delegate F_Data_LoadCompleted.");

                //// 沒有按鍵無法直接觸發, 只好直接呼叫
                //FrameLoadCompleteEventArgs ex = new FrameLoadCompleteEventArgs()
                //{
                //    Message = FrameLoadStates.DirectCall
                //};
                //F_Data_LoadCompleted(this, ex);
                // 此段程式的一個出口點

                // 20210719: 讀完實體資料就開始解析HTML吧
                string o = $"++ Exit F_Pager_LoadCompleted (1/3). last page, last tab, go to finalization directly. [{current_op.UID}]";
                ParsingTables(o);

                return;
            }
            else if (current_page == total_pages)
            {
                // 最後一頁
                // 處理index
                current_page = total_pages = 0;
                // 轉軌
                fm.FrameLoadComplete += F_Data_LoadCompleted;
                log.Debug($"@@ add delegate F_Data_LoadCompleted. [{current_op.UID}]");
                Thread.Sleep(150);
                // 下一個tab
                log.Info($"[Action]  {current_op.TAB_ID} tab key pressed.");
                current_op = QueueOperation.Dequeue();
                log.Debug($"++ Exit F_Pager_LoadCompleted (2/3). last page, go to next tab by clicking. [{current_op.UID}]");
                d.getElementById(current_op.TAB_ID).click();
                // 此段程式的一個出口點
                return;
            }
            else
            {
                current_page++;
                // 按鍵到下一頁, 此段程式到此結束
                // HOW TO ?????????????????????????????????????????
                // 如何下一頁, 可能要用invokescript
                // 按鈕機制
                fm.FrameLoadComplete += F_Pager_LoadCompleted;
                log.Debug($"@@ add delegate F_Pager_LoadCompleted. [{current_op.UID}]");
                Thread.Sleep(150);
                log.Info($"[Action] 下一頁按下去了.(多頁) [{current_op.UID}]");
                log.Debug($"++ Exit F_Pager_LoadCompleted (3/3). go to next page by clicking. [{current_op.UID}]");
                foreach (IHTMLElement a in f.getElementById("ContentPlaceHolder1_pg_gvList").all)
                {
                    if (a.innerText == ">")
                    {
                        a.click();
                    }
                }
                // 此段程式的一個出口點
                return;
            }
        }