Загрузка курсов валют с сайта НБРБ (HTML)
Материал из GedeminWiki
Вариант с "ручным" разбором HTML документа.
option explicit ' системные требования: Windows XP SP1, Windows 2000 SP3 ' Windows 2003 Server ' sub Curr_LoadRates Dim Creator Set Creator = New TCreator ' словарь CurrCode нужен нам для двух целей: ' во-первых, в нем задается список валют, курсы ' которых мы будем загружать с сайта ' во-вторых, в нем мы устанавливаем соответствие ' между кодом (буквенной аббревиатурой) валюты ' используемой на сайте (Key) и кодом валюты ' используемым в нашей базе данных (Item). Очевидно, ' что они могут как совпадать, так и различаться ' например, доллар США на сайте может обозначаться ' как USD, а у нас в базе он будет проходить как ' USD NBRB, что означает курс доллара США, установленный ' Национальным банком Республики Беларусь. ' Обратите внимание, что коды валют могут меняться во времени ' например в одно время сайт может вернуть курс польского злотого ' под кодом PLZ, а в другое -- PLN ' в таком случае, все коды одной и той же валюты, которые ' могут использоваться на сайте, должны быть перечислены ' через запятую Dim CurrCode Set CurrCode = CreateObject("Scripting.Dictionary") CurrCode.Add "USD", "USD" CurrCode.Add "EUR", "EUR" CurrCode.Add "RUB,RUR", "RUB" CurrCode.Add "PLN,PLZ", "PLN" CurrCode.Add "UAH", "UAH" CurrCode.Add "LTL", "LTL" CurrCode.Add "LVL", "LVL" CurrCode.Add "GBP", "GBP" ' идентификатор записи валюты, относительно которой ' задаются курсы валют на сайте ' в данном случае -- это наш родной белорусский рубль Dim BaseCurrID BaseCurrID = gdcBaseManager.GetIDByRUIDString("200010_17") ' даты: с какой и по какую загружать курсы валют с сайта ' по какую -- возьмем текущую системную дату ' с какой -- определим следующим образом: будем искать в нашей ' базе для каждой из заданных валют самую последнюю ' дату курса. из всех найденных дат возьмем наиболее раньнюю. Dim FromDate, ToDate ToDate = Date FromDate = ToDate Dim q, qFind, Tr Set Tr = Creator.GetObject(Application, "TIBTransaction", "") Set q = Creator.GetObject(Application, "TIBSQL", "") Set qFind = Creator.GetObject(Application, "TIBSQL", "") Set Tr.DefaultDatabase = gdcBaseManager.Database Set q.Transaction = Tr Set qFind.Transaction = Tr Tr.StartTransaction ' уберем коды валют которых нет нашей базе или ' которые встречаются более одного раза q.SQL.Text =_ "SELECT COUNT(c.code) " &_ "FROM gd_curr c " &_ "WHERE c.code = :C " Dim I For Each I in CurrCode q.ParamByName("C").AsString = CurrCode.Item(I) q.ExecQuery if q.Fields(0).AsInteger <> 1 then _ CurrCode.Remove(I) q.Close Next q.SQL.Text =_ "SELECT MAX(r.fordate) " &_ "FROM gd_currrate r JOIN gd_curr c ON r.fromcurr = c.id " &_ "WHERE c.code = :FC and r.tocurr = :TC" q.ParamByName("TC").AsInteger = BaseCurrID For Each I in CurrCode q.ParamByName("FC").AsString = CurrCode.Item(I) q.ExecQuery if Int(q.Fields(0).AsDateTime) < FromDate then _ FromDate = Int(q.Fields(0).AsDateTime) q.Close Next ' проверим, может в базе уже есть все курсы if ToDate < FromDate then _ exit sub ' если интервал слишком большой -- ограничим его if (ToDate - FromDate) > (365 * 1) then _ FromDate = ToDate - 365 * 1 ' подготовим запрос для вставки курса валюты q.SQL.Text = _ "INSERT INTO gd_currrate (fromcurr, tocurr, fordate, coeff) " &_ "SELECT ID, :TC, :FD, :R FROM gd_curr WHERE code = :FC " q.ParamByName("TC").AsInteger = BaseCurrID ' подготовим запрос для поиска курса валюты на указанную дату qFind.SQL.Text =_ "SELECT * " &_ "FROM gd_currrate r JOIN gd_curr c ON r.fromcurr = c.id " &_ "WHERE c.code = :FC and r.tocurr = :TC AND r.fordate = :FD" qFind.ParamByName("TC").AsInteger = BaseCurrID Dim strResult Dim WinHttpReq Dim strURL ' если объект не удается создать (например, неподходящая ' версия Windows), то просто завершаем выполнение On Error Resume Next Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1") if Err.Number <> 0 then _ Exit Sub On Error GoTo 0 ' если используется прокси для выхода в интернет ' откоментируйте следующую строку и укажите адрес прокси ' последний параметр, указывает адреса, к которым подключение ' будет происходить минуя прокси ' WinHttpReq.SetProxy 2, "proxy_server:80", "*.domain.com" Dim D, K, J, E, SS, Mo, Da, Arr, A For D = FromDate to ToDate Step 1 qFind.Close qFind.ParamByName("FD").AsDateTime = D q.ParamByName("FD").AsDateTime = D if Month(D) < 10 then Mo = "0" & Month(D) else Mo = Month(D) end if if Day(D) < 10 then Da = "0" & Day(D) else Da = Day(D) end if strURL = "http://www.nbrb.by/statistics/rates/RatesDaily.asp?fromDate=" &_ Year(D) & "-" & Mo & "-" & Da ' в случае если сайт не доступен -- просто ' заверши процедуру On Error Resume Next WinHttpReq.Open "GET", strURL, false WinHttpReq.Send strResult = WinHttpReq.ResponseText if Err.Number <> 0 then _ Exit Sub On Error GoTo 0 For Each I in CurrCode ' для каждой валюты проверим: нет ли в базе курса на ' указанную дату. если есть, то пропускаем эту валюту qFind.ParamByName("FC").AsString = CurrCode.Item(I) qFind.ExecQuery if qFind.EOF then Arr = Split(I, ",") For Each A in Arr K = InStr(strResult, ">" & A & "</td>") if K > 0 then For J = 1 to 4 K = InStr(K + 1, strResult, ">") if K = 0 then _ Exit For Next if K > 0 then K = K + 1 E = InStr(K, strResult, "<") if E > 0 then SS = Replace(Mid(strResult, K, E - K), " ", "") SS = Replace(SS, " ", "") SS = Replace(SS, Chr(160), "") ' на сайте используется точка в качестве десятичного ' разделителя. Заменим ее на разделитель, использующийся в нашей ' системе SS = Replace(SS, ".", Application.DecimalSeparatorSys) if SS > "" then ' в случае если строку не удается перевести в число ' или возникнет ошибка при добавлении записи -- ' проигнорируем их On Error Resume Next q.ParamByName("R").AsCurrency = CCur(SS) q.ParamByName("FC").AsString = CurrCode.Item(I) if Err.Number = 0 then _ q.ExecQuery On Error GoTo 0 end if end if end if end if Next end if qFind.Close Next Next ' подтверждаем запись в базу данных, только если все прошло успешно ' и не возникало ошибок Tr.Commit end sub