Загрузка курсов валют с сайта НБРБ
Материал из GedeminWiki
(Различия между версиями)
SYSDBA (обсуждение | вклад) м (Правки DomelTouno (обсуждение) откачены к версии SYSDBA) |
|||
| Строка 2: | Строка 2: | ||
option explicit | option explicit | ||
| − | ' | + | ' системные требования: Windows XP SP1, Windows 2000 SP3 |
' Windows 2003 Server | ' Windows 2003 Server | ||
' | ' | ||
| Строка 10: | Строка 10: | ||
Set Creator = New TCreator | Set Creator = New TCreator | ||
| − | ' | + | ' словарь CurrCode нужен нам для двух целей: |
| − | ' | + | ' во-первых, в нем задается список валют, курсы |
| − | ' | + | ' которых мы будем загружать с сайта |
| − | ' | + | ' во-вторых, в нем мы устанавливаем соответствие |
| − | ' | + | ' между кодом (буквенной аббревиатурой) валюты |
| − | ' | + | ' используемой на сайте (Key) и кодом валюты |
| − | ' | + | ' используемым в нашей базе данных (Item). Очевидно, |
| − | ' | + | ' что они могут как совпадать, так и различаться |
| − | ' | + | ' например, доллар США на сайте может обозначаться |
| − | ' | + | ' как USD, а у нас в базе он будет проходить как |
| − | ' USD NBRB, | + | ' USD NBRB, что означает курс доллара США, установленный |
| − | ' | + | ' Национальным банком Республики Беларусь. |
| − | ' | + | ' Обратите внимание, что коды валют могут меняться во времени |
| − | ' | + | ' например в одно время сайт может вернуть курс польского злотого |
| − | ' | + | ' под кодом PLZ, а в другое -- PLN |
| − | ' | + | ' в таком случае, все коды одной и той же валюты, которые |
| − | ' | + | ' могут использоваться на сайте, должны быть перечислены |
| − | ' | + | ' через запятую |
Dim CurrCode | Dim CurrCode | ||
Set CurrCode = CreateObject("Scripting.Dictionary") | Set CurrCode = CreateObject("Scripting.Dictionary") | ||
| Строка 39: | Строка 39: | ||
CurrCode.Add "GBP", "GBP" | CurrCode.Add "GBP", "GBP" | ||
| − | ' | + | ' идентификатор записи валюты, относительно которой |
| − | ' | + | ' задаются курсы валют на сайте |
| − | ' | + | ' в данном случае -- это наш родной белорусский рубль |
Dim BaseCurrID | Dim BaseCurrID | ||
BaseCurrID = gdcBaseManager.GetIDByRUIDString("200010_17") | BaseCurrID = gdcBaseManager.GetIDByRUIDString("200010_17") | ||
| − | ' | + | ' даты: с какой и по какую загружать курсы валют с сайта |
| − | ' | + | ' по какую -- возьмем текущую системную дату |
| − | ' | + | ' с какой -- определим следующим образом: будем искать в нашей |
| − | ' | + | ' базе для каждой из заданных валют самую последнюю |
| − | ' | + | ' дату курса. из всех найденных дат возьмем наиболее раньнюю. |
Dim FromDate, ToDate | Dim FromDate, ToDate | ||
ToDate = Date | ToDate = Date | ||
| Строка 65: | Строка 65: | ||
Tr.StartTransaction | Tr.StartTransaction | ||
| − | ' | + | ' уберем коды валют которых нет нашей базе или |
| − | ' | + | ' которые встречаются более одного раза |
q.SQL.Text =_ | q.SQL.Text =_ | ||
"SELECT COUNT(c.code) " &_ | "SELECT COUNT(c.code) " &_ | ||
| Строка 95: | Строка 95: | ||
Next | Next | ||
| − | ' | + | ' проверим, может в базе уже есть все курсы |
if ToDate < FromDate then _ | if ToDate < FromDate then _ | ||
exit sub | exit sub | ||
| − | ' | + | ' если интервал слишком большой -- ограничим его |
if (ToDate - FromDate) > (365 * 1) then _ | if (ToDate - FromDate) > (365 * 1) then _ | ||
FromDate = ToDate - 365 * 1 | FromDate = ToDate - 365 * 1 | ||
| − | ' | + | ' подготовим запрос для вставки курса валюты |
q.SQL.Text = _ | q.SQL.Text = _ | ||
"INSERT INTO gd_currrate (fromcurr, tocurr, fordate, coeff) " &_ | "INSERT INTO gd_currrate (fromcurr, tocurr, fordate, coeff) " &_ | ||
| Строка 109: | Строка 109: | ||
q.ParamByName("TC").AsInteger = BaseCurrID | q.ParamByName("TC").AsInteger = BaseCurrID | ||
| − | ' | + | ' подготовим запрос для поиска курса валюты на указанную дату |
qFind.SQL.Text =_ | qFind.SQL.Text =_ | ||
"SELECT * " &_ | "SELECT * " &_ | ||
| Строка 120: | Строка 120: | ||
Dim strURL | Dim strURL | ||
| − | ' | + | ' если объект не удается создать (например, неподходящая |
| − | ' | + | ' версия Windows), то просто завершаем выполнение |
On Error Resume Next | On Error Resume Next | ||
Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1") | Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1") | ||
| Строка 128: | Строка 128: | ||
On Error GoTo 0 | On Error GoTo 0 | ||
| − | ' | + | ' если используется прокси для выхода в интернет |
| − | ' | + | ' откоментируйте следующую строку и укажите адрес прокси |
| − | ' | + | ' последний параметр, указывает адреса, к которым подключение |
| − | ' | + | ' будет происходить минуя прокси |
' WinHttpReq.SetProxy 2, "proxy_server:80", "*.domain.com" | ' WinHttpReq.SetProxy 2, "proxy_server:80", "*.domain.com" | ||
| Строка 158: | Строка 158: | ||
'strUrl = "http://localhost/nbrb/ratesdaily.asp.htm" | 'strUrl = "http://localhost/nbrb/ratesdaily.asp.htm" | ||
| − | ' | + | ' в случае если сайт не доступен -- просто |
| − | ' | + | ' заверши процедуру |
On Error Resume Next | On Error Resume Next | ||
| Строка 172: | Строка 172: | ||
For Each I in CurrCode | For Each I in CurrCode | ||
| − | ' | + | ' для каждой валюты проверим: нет ли в базе курса на |
| − | ' | + | ' указанную дату. если есть, то пропускаем эту валюту |
qFind.ParamByName("FC").AsString = CurrCode.Item(I) | qFind.ParamByName("FC").AsString = CurrCode.Item(I) | ||
qFind.ExecQuery | qFind.ExecQuery | ||
| Строка 199: | Строка 199: | ||
SS = Replace(SS, Chr(160), "") | SS = Replace(SS, Chr(160), "") | ||
| − | ' | + | ' на сайте используется точка в качестве десятичного |
| − | ' | + | ' разделителя. Заменим ее на разделитель, использующийся в нашей |
| − | ' | + | ' системе |
SS = Replace(SS, ".", Application.DecimalSeparatorSys) | SS = Replace(SS, ".", Application.DecimalSeparatorSys) | ||
if SS > "" then | if SS > "" then | ||
| − | ' | + | ' в случае если строку не удается перевести в число |
| − | ' | + | ' или возникнет ошибка при добавлении записи -- |
| − | ' | + | ' проигнорируем их |
On Error Resume Next | On Error Resume Next | ||
| Строка 229: | Строка 229: | ||
Next | Next | ||
| − | ' | + | ' подтверждаем запись в базу данных, только если все прошло успешно |
| − | ' | + | ' и не возникало ошибок |
Tr.Commit | Tr.Commit | ||
| Строка 236: | Строка 236: | ||
</source> | </source> | ||
| − | [[Category: | + | [[Category:Учебный курс]] |
Версия 16:17, 10 июля 2009
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 'strUrl = "http://localhost/nbrb/ratesdaily.asp.htm" ' в случае если сайт не доступен -- просто ' заверши процедуру 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