2010年12月30日 星期四

在WSH環境下存取Access資料庫─使用ADODB物件

上一篇文章「在WSH環境下存取Access資料庫」中,使用組合SQL語法的方式將資料寫進資料庫,但這樣的方式在資料欄位數量較多時,是種相當痛苦的處理方法。

這篇嘗試使用ADODB.RecordSet物件來跟資料庫打交道,雖然以前只用過Delphi程式語言設計資料庫軟體,好在ADODB物件的用法差異並不會太大,語法、結構也都很類似(就是開資料庫連線、建立資料集、最後記得關閉資料庫連線‧‧‧等等),參考網路上的一些資料後,就試著動手寫寫看。


改以ADODB物件寫入Access的完整程式碼如下:

<?xml version="1.0" standalone="yes" encoding="big5"?>

<package>
    <job>
        <script src="JScript/adojavas.js" type="text/javascript" language="javascript" charset="utf-8"></script>

        <script type="text/javascript" language="javascript" charset="utf-8">
        <![CDATA[
            /**
             *
             * 取得資料。
             *
             * @author ace
             *
             * @version 2010/11/11 v0.1
             *
             * @param {String} astrStockCode 股票代碼。
             *
             * @returns {String} 網頁資料。
             *
             * @requires Microsoft.XMLHttp
             *
             */
            function getHttp(astrStockCode) {

                var strReturn = new String("");

                var strURL = new String("http://tw.stock.yahoo.com/q/q?s=" + astrStockCode);

                var objXMLHttp = new ActiveXObject("Microsoft.XMLHttp");
                objXMLHttp.open("GET", strURL, false, "");
                objXMLHttp.send();

                // todo: 加入是否正確取得資料之判斷式。
                var strReturn = new String(objXMLHttp.responseText);

                return strReturn;
            }

            /**
             *
             * 剖析html資料。
             *
             * @author ace
             *
             * @version 2010/11/11 v0.1
             *
             * @param {String} astrTrnDate 交易日期。
             * @param {String} astrStockCode 股票代碼。
             *
             * @returns {Array} 陣列資料。
             *
             */
            function parseHTML(astrTrnDate, astrStockCode, astrContent) {

                var objReturn = new Array();

                /**
                 *
                 * 建立瀏覽器物件。
                 *
                 * @author ace
                 *
                 * @version 2010/11/16 v0.1
                 *
                 * @see <a href="http://us.generation-nt.com/answer/parsing-html-jscript-help-59686112.html">Parsing HTML with JScript</a>
                 * @see <a href="http://www.eggheadcafe.com/software/aspnet/36239301/jquery.aspx">Jquery</a>
                 *
                 */
                var htmlfile = new ActiveXObject("htmlfile");
                var window = htmlfile.parentWindow;
                var navigator = window.navigator;
                var document = window.document;
                var location = document.location;

                window.ActiveXObject = {};

                // todo:載入html檔案發生錯誤時,無法被JavaScript的catch語法攔截?!
                htmlfile.open();
                htmlfile.write("<script type=\"text/javascript\">window.onerror = function () {};</script>");
                htmlfile.write(astrContent);
                htmlfile.close();

                var objTR = document.getElementsByTagName("tr");

                for (var intIndex = 0; intIndex < objTR.length; intIndex++) {

                    var objTD = objTR[intIndex].getElementsByTagName("td");

                    if (objTD.length == 12) {
                        objReturn.push(astrTrnDate);
                        objReturn.push(astrStockCode);
                        objReturn.push(objTD[2].firstChild.innerHTML);  // 成交金額多了<b>標籤,再往下一個結點取資料。
                        objReturn.push(objTD[3].innerHTML);
                        objReturn.push(objTD[4].innerHTML);
                        objReturn.push(objTD[6].innerHTML.replace(",", ""));
                        objReturn.push(objTD[7].innerHTML);
                        objReturn.push(objTD[8].innerHTML);
                        objReturn.push(objTD[9].innerHTML);
                        objReturn.push(objTD[10].innerHTML);

                        break;
                    }
                }

                return objReturn;
            }

            /**
             *
             * 寫入Access資料表。
             *
             * @author ace
             *
             * @version 2010/11/30 v0.1
             *
             * @param {String} astrTrnDate 交易日期。
             * @param {String} astrStockCode 股票代碼。
             * @param {Array} aobjData 資料陣列。
             *
             * @return
             *
             * @description 2010/11/30 陣列資料內容:
             *                           aobjData[0]:交易日期。
             *                           aobjData[1]:股票代碼。
             *                           aobjData[7]:開盤價格。
             *                           aobjData[8]:最高價格。
             *                           aobjData[9]:最低價格。
             *                           aobjData[2]:收盤價格。
             *                           aobjData[5]:成交張數。
             * @description 2010/12/26 改以RecordSet物件寫入資料。 
             *
             */
            function insertAccess(astrTrnDate, astrStockCode, aobjData) {

                var objConn = WScript.CreateObject("ADODB.Connection");
                var objRS   = WScript.CreateObject("ADODB.RecordSet");
                try {

                    strDatabase = new String("Stock.mdb");
                    objConn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strDatabase;
                    objConn.Open();

                    var strSQL = "select * from stocks_day_trn_log where 1=1 and trn_date='" + aobjData[0] + "' and stock_code='" + aobjData[1] + "' ";
                    objRS.Open(strSQL, objConn, adOpenStatic, adLockOptimistic, adCmdText);

                    // 若查無資料則新增。
                    if (objRS.EOF == true) objRS.AddNew();

                    objRS("trn_date")    = aobjData[0];
                    objRS("stock_code")  = aobjData[1];
                    objRS("open_price")  = aobjData[7];
                    objRS("high_price")  = aobjData[8];
                    objRS("low_price")   = aobjData[9];
                    objRS("close_price") = aobjData[2];
                    objRS("trn_qty")     = aobjData[5];

                    objRS.Update();
                }
                catch (e) {
                    throw e;
                }
                finally {
                    objRS.Close();
                    objConn.Close();
                }
            }

            // Program Start Here
            try {
                var objToday = new Date();

                // 以系統日期當作交易日期,理想作法應以網頁記載時間為準。
                var strTrnDate = new String("");
                strTrnDate = objToday.getFullYear().toString() + (objToday.getMonth() + 1).toString() + objToday.getDate().toString();

                var strStockCode = new String("2002");

                insertAccess(strTrnDate, strStockCode, parseHTML(strTrnDate, strStockCode, getHttp(strStockCode)));
            }
            catch (e) {
                WScript.Echo("執行過程有誤,錯誤訊息:" + e.description);
            }
        ]]>
        </script>
    </job>
</package>

與前一篇文章「在WSH環境下存取Access資料庫」的作法對照,寫法更加簡潔,至少不用自己計算單引號的位置與個數(這是很容易出錯的地方)。看來想在WSH環境下跟資料庫打交道,把ADODB物件的用法摸熟會是一個比較好的資料處理方式。

補充記錄:在上面的程式碼第5行中所載入的adojavas.js檔案是藉由修改ASP環境所提供的adojavas.inc檔案而來;如果電腦上有安裝ADO元件,可以在C:\Program Files\Common Files\System\ado資料夾下找到adojavas.inc檔案,把副檔名修改成js,並將檔案內容前後的「<%」與「%>」符號移除,就可以直接引用該檔案已經定義好的常數值(例如程式碼第145行的adOpenStatic),省去自行訂義的麻煩。

沒有留言:

張貼留言

Related Posts Plugin for WordPress, Blogger...