Уважаемый krosav4ig уже один раз помог мне на этом форуме, поэтому я решил обратиться за помощью ещё раз, но уже по другому вопросу.
Мне нужно выцепить цену на серебро с сайта ЦБ РФ. Вот тут есть кое-какие примеры, но для драгметаллов там выводится архив котировок за период, а мне нужно на сегодняшний день: http://www.cbr.ru/scripts/Root.asp?PrtId=SXML
Нужен модуль и функция.
Помогите, пожалуйста.
Здравствуйте ещё раз.
Уважаемый krosav4ig уже один раз помог мне на этом форуме, поэтому я решил обратиться за помощью ещё раз, но уже по другому вопросу.
Мне нужно выцепить цену на серебро с сайта ЦБ РФ. Вот тут есть кое-какие примеры, но для драгметаллов там выводится архив котировок за период, а мне нужно на сегодняшний день: http://www.cbr.ru/scripts/Root.asp?PrtId=SXML
Обязательно ли работать через XML? Предлагаю другое решение.
Первая кнопка грузит данные с сайта ЦБ РФ по металлам за сегодня. Через несколько секунд информация отображается и можно жмакнуть вторую кнопу - чтобы данные добавились в базу.
Осторожно, в качестве исторических данных использую случайно сгенерированые цифры, Вам нужно будет всё заполнять с нуля.
[vba]
Код
Sub Rio_loads_metals_from_CBR()
'Author: Roman Rioran Voronov 'Date: the 10-th of October, 2014 'Feedback: voronov_rv@mail.ru
Dim shtA As Worksheet 'Load sheet Set shtA = ThisWorkbook.Worksheets("Load")
shtA.Cells.Clear
Do While shtA.QueryTables.Count > 0 shtA.QueryTables(1).Delete Loop
With shtA.QueryTables.Add(Connection:="URL;http://www.cbr.ru", Destination:=shtA.Range("A1")) .WebSelectionType = xlSpecifiedTables .WebTables = "4" .Refresh End With
Обязательно ли работать через XML? Предлагаю другое решение.
Первая кнопка грузит данные с сайта ЦБ РФ по металлам за сегодня. Через несколько секунд информация отображается и можно жмакнуть вторую кнопу - чтобы данные добавились в базу.
Осторожно, в качестве исторических данных использую случайно сгенерированые цифры, Вам нужно будет всё заполнять с нуля.
[vba]
Код
Sub Rio_loads_metals_from_CBR()
'Author: Roman Rioran Voronov 'Date: the 10-th of October, 2014 'Feedback: voronov_rv@mail.ru
Dim shtA As Worksheet 'Load sheet Set shtA = ThisWorkbook.Worksheets("Load")
shtA.Cells.Clear
Do While shtA.QueryTables.Count > 0 shtA.QueryTables(1).Delete Loop
With shtA.QueryTables.Add(Connection:="URL;http://www.cbr.ru", Destination:=shtA.Range("A1")) .WebSelectionType = xlSpecifiedTables .WebTables = "4" .Refresh End With
UltrasRW, зачем бегать циклом по элементам, когда есть XPath и нужный элемент можно выбрать одним запросом, и дату ЦБР вполне себе понимает в формате ДД.ММ.ГГГГ forest1333, собственно вот мой вариант функции [vba]
Код
Function МетЦБР#(Optional Code% = 2, Optional dDate As Date, Optional sell% = 0) Dim d As Object: Set d = CreateObject("msxml.DOMDocument") dDate = IIf(dDate, dDate, Date): d.async = 0 d.Load ("http://www.cbr.ru/scripts/xml_metall.asp?date_req1=" & dDate & "&date_req2=" & dDate) МетЦБР = CDbl(d.SelectSingleNode("*/Record[@Code='" & Code & "']").ChildNodes(Abs(sell)).Text) Set d = Nothing End Function
[/vba] у функции 3 необязательных атрибута Первый: Код металла (1-золото,2-серебро,3-платина,4-палладий), если параметр не указан, то по умолчанию берется 2 Второй: дата в текстовом формате или ссылка на ячейку с датой в числовом формате. если параметр не указан, то по умолчанию берется текущая СИСТЕМНАЯ дата (дата, установленная в компьютере, может не совпадать с фактической) в качестве разделителей между числами дня, месяца и года может использоваться любой символ из " " , "/" , "." , "-" , "," , запись даты в формате "1 янв 14" и "1 января 2014" тоже корректно распознаются По моему курсы на покупку и продажу у ЦБР одинаковые, но на всякий случай сделал третий атрибут: тип курса банка- 0-покупка, 1-продажа, если параметр не указан, то по умолчанию берется 0 формула
Код
=МетЦБР()
вернет текущий курс банка на покупку серебра.
UltrasRW, зачем бегать циклом по элементам, когда есть XPath и нужный элемент можно выбрать одним запросом, и дату ЦБР вполне себе понимает в формате ДД.ММ.ГГГГ forest1333, собственно вот мой вариант функции [vba]
Код
Function МетЦБР#(Optional Code% = 2, Optional dDate As Date, Optional sell% = 0) Dim d As Object: Set d = CreateObject("msxml.DOMDocument") dDate = IIf(dDate, dDate, Date): d.async = 0 d.Load ("http://www.cbr.ru/scripts/xml_metall.asp?date_req1=" & dDate & "&date_req2=" & dDate) МетЦБР = CDbl(d.SelectSingleNode("*/Record[@Code='" & Code & "']").ChildNodes(Abs(sell)).Text) Set d = Nothing End Function
[/vba] у функции 3 необязательных атрибута Первый: Код металла (1-золото,2-серебро,3-платина,4-палладий), если параметр не указан, то по умолчанию берется 2 Второй: дата в текстовом формате или ссылка на ячейку с датой в числовом формате. если параметр не указан, то по умолчанию берется текущая СИСТЕМНАЯ дата (дата, установленная в компьютере, может не совпадать с фактической) в качестве разделителей между числами дня, месяца и года может использоваться любой символ из " " , "/" , "." , "-" , "," , запись даты в формате "1 янв 14" и "1 января 2014" тоже корректно распознаются По моему курсы на покупку и продажу у ЦБР одинаковые, но на всякий случай сделал третий атрибут: тип курса банка- 0-покупка, 1-продажа, если параметр не указан, то по умолчанию берется 0 формула
Код
=МетЦБР()
вернет текущий курс банка на покупку серебра.krosav4ig
По моему курсы на покупку и продажу у ЦБР одинаковые, но на всякий случай сделал третий атрибут
У ЦБ всегда один курс на валюты и драгоценные металлы, потому что он является регулятором. Цены на покупку и продажу разнятся у остальных банков, потому что они занимаются перепродажей валюты.
Большое спасибо за помощь, ребята. Особенно krosav4ig, ваш вариант для меня наиболее подходящий оказался.
По моему курсы на покупку и продажу у ЦБР одинаковые, но на всякий случай сделал третий атрибут
У ЦБ всегда один курс на валюты и драгоценные металлы, потому что он является регулятором. Цены на покупку и продажу разнятся у остальных банков, потому что они занимаются перепродажей валюты.forest1333
нарисовал еще одну функцию. возвращает текущую цену на драгметалл с главной страницы ЦБР для работы необходимо подключить Microsoft HTML Object Library [vba]
Код
Private Declare Function DeleteUrlCacheEntry& Lib "wininet" (ByVal lpszUrlName$) Function МетЦБР2#(code) Application.Volatile False Dim oHTML As HTMLDocument, oDoc As HTMLDocument, elem As HTMLBaseElement, url$, n%, str$: Set oHTML = New HTMLDocument url = "http://www.cbr.ru/" DeleteUrlCacheEntry (url) Set oDoc = oHTML.createDocumentFromUrl(url, "") Do DoEvents Loop Until oDoc.readyState = "complete" oHTML.body.innerHTML = oDoc.getElementById("widget_metal").innerHTML Set oDoc = Nothing n = InStr(1, "_auagptpg", LCase(code)) / 2 - 1 + Val(code) Set elem = oHTML.getElementsByTagName("span")(n) МетЦБР2 = CDbl(elem.innerText) 'With Application.Caller ' If Not .Comment Is Nothing Then .Comment.Delete ' str = oHTML.getElementsByTagName("ins")(n).ParentNode.innerText ' str = str & CStr(CDate(Mid(Replace(oHTML.LastModified, "/", "/" & Left(oHTML.LastModified, 3)), 7, 10))) ' .AddComment str & Right(oHTML.LastModified, 9) 'End With Set elem = Nothing Set oHTML = Nothing End Function
[/vba] закомментированные строки кода добавляют в ячейку примечание с названием металла, его буквенным кодом, датой и временем code - числовой или буквенный код металла: золото - 1 или "au", серебро - 2 или "ag", платина -3 или "pt", палладий - 4 или "pd"
нарисовал еще одну функцию. возвращает текущую цену на драгметалл с главной страницы ЦБР для работы необходимо подключить Microsoft HTML Object Library [vba]
Код
Private Declare Function DeleteUrlCacheEntry& Lib "wininet" (ByVal lpszUrlName$) Function МетЦБР2#(code) Application.Volatile False Dim oHTML As HTMLDocument, oDoc As HTMLDocument, elem As HTMLBaseElement, url$, n%, str$: Set oHTML = New HTMLDocument url = "http://www.cbr.ru/" DeleteUrlCacheEntry (url) Set oDoc = oHTML.createDocumentFromUrl(url, "") Do DoEvents Loop Until oDoc.readyState = "complete" oHTML.body.innerHTML = oDoc.getElementById("widget_metal").innerHTML Set oDoc = Nothing n = InStr(1, "_auagptpg", LCase(code)) / 2 - 1 + Val(code) Set elem = oHTML.getElementsByTagName("span")(n) МетЦБР2 = CDbl(elem.innerText) 'With Application.Caller ' If Not .Comment Is Nothing Then .Comment.Delete ' str = oHTML.getElementsByTagName("ins")(n).ParentNode.innerText ' str = str & CStr(CDate(Mid(Replace(oHTML.LastModified, "/", "/" & Left(oHTML.LastModified, 3)), 7, 10))) ' .AddComment str & Right(oHTML.LastModified, 9) 'End With Set elem = Nothing Set oHTML = Nothing End Function
[/vba] закомментированные строки кода добавляют в ячейку примечание с названием металла, его буквенным кодом, датой и временем code - числовой или буквенный код металла: золото - 1 или "au", серебро - 2 или "ag", платина -3 или "pt", палладий - 4 или "pd"krosav4ig
нарисовал еще одну функцию. возвращает текущую цену на драгметалл с главной страницы ЦБР
Да, спасибо большое. Но вот хотел на что обратить внимание.
По предыдущему варианту, что вы сделали, ваша функция отказывается корректно работать по субботам, воскресеньям и понедельникам, видимо потому, что в пятницу ЦБ устанавливает курс на 3 дня вперёд. А недостаток второй функции заключается в том, что во второй половине дня ЦБ публикует курс серебра на завтра, и в итоге excel во второй половине дня вытягивает в таблицу не сегодняшнее значение, а завтрашнее.
Можно ли сделать так, чтобы в течение всего дня каждый день, включая субботу, воскресенье, понедельник и праздники, когда ЦБ не работает и устанавливает курс на несколько дней вперёд заранее, в таблицу вставлялся актуальный курс? Ну или курс по дате, расположенной в соседней ячейке (я там могу использовать функцию "сегодня")?
нарисовал еще одну функцию. возвращает текущую цену на драгметалл с главной страницы ЦБР
Да, спасибо большое. Но вот хотел на что обратить внимание.
По предыдущему варианту, что вы сделали, ваша функция отказывается корректно работать по субботам, воскресеньям и понедельникам, видимо потому, что в пятницу ЦБ устанавливает курс на 3 дня вперёд. А недостаток второй функции заключается в том, что во второй половине дня ЦБ публикует курс серебра на завтра, и в итоге excel во второй половине дня вытягивает в таблицу не сегодняшнее значение, а завтрашнее.
Можно ли сделать так, чтобы в течение всего дня каждый день, включая субботу, воскресенье, понедельник и праздники, когда ЦБ не работает и устанавливает курс на несколько дней вперёд заранее, в таблицу вставлялся актуальный курс? Ну или курс по дате, расположенной в соседней ячейке (я там могу использовать функцию "сегодня")?forest1333
я правильно понял, что в пятницу ЦБ устанавливает курс, который вступает в силу с субботы и действует по понедельник включительно? и по поводу праздников. К примеру тут написано
Цитата
1, 2, 3, 4, 5, 6 и 8 января — Новогодние каникулы; 7 января — Рождество Христово; 9 января — выходной;
это означает, что 31 декабря устанавливается курс, который вступает в силу 1 янв и действует по 12 янв включительно (1-9 янв нерабочие дни, 10 янв-суббота)?
я правильно понял, что в пятницу ЦБ устанавливает курс, который вступает в силу с субботы и действует по понедельник включительно? и по поводу праздников. К примеру тут написано
Цитата
1, 2, 3, 4, 5, 6 и 8 января — Новогодние каникулы; 7 января — Рождество Христово; 9 января — выходной;
это означает, что 31 декабря устанавливается курс, который вступает в силу 1 янв и действует по 12 янв включительно (1-9 янв нерабочие дни, 10 янв-суббота)?krosav4ig
Вот по поводу конкретных дат праздников ничего не могу сказать. Не проследил график работы ЦБ в этом вопросе.
Знаете, у меня есть модуль для цепляния курса валют с сайта ЦБ:
[vba]
Код
Sub ВывестиСегодняшниеКурсыВсехВалют() On Error Resume Next Set xmldoc = CreateObject("Msxml.DOMDocument"): xmldoc.async = False url_request = "http://www.cbr.ru/scripts/XML_daily.asp?date_req=" + Format(Now, "dd\/mm\/yyyy") If xmldoc.Load(url_request) <> True Then Exit Sub Set nodeList = xmldoc.SelectNodes("ValCurs"): Set xmlNode = nodeList.Item(0).CloneNode(True) Set node_attr = xmlNode.Attributes(0): strDate = node_attr.Value Set nodeList = xmldoc.SelectNodes("*/Valute") For i = 0 To nodeList.Length - 1 Set xmlNode = nodeList.Item(i).CloneNode(True) Debug.Print "Курс " & xmlNode.ChildNodes(1).Text & " (установлен " & strDate & "): " & _ xmlNode.ChildNodes(4).Text & " рублей за " & xmlNode.ChildNodes(2).Text & _ " " & xmlNode.ChildNodes(3).Text Next End Sub
Function GetRate(ByVal CurrencyName As String, ByVal RateDate As Date) As Single ' функция возвращает курс валюты CurrencyName на дату RateDate ' в случае ошибки (неверная дата или название валюты) возвращается 0 On Error Resume Next CurrencyName = UCase(CurrencyName): If Len(CurrencyName) <> 3 Then Exit Function Set xmldoc = CreateObject("Msxml.DOMDocument"): xmldoc.async = False url_request = "http://www.cbr.ru/scripts/XML_daily.asp?date_req=" + Format(RateDate, "dd\/mm\/yyyy")
If xmldoc.Load(url_request) <> True Then Exit Function ' Запрос к серверу ЦБР
' Обработка полученного ответа Set nodeList = xmldoc.SelectNodes("ValCurs"): Set xmlNode = nodeList.Item(0).CloneNode(True) Set node_attr = xmlNode.Attributes(0): strDate = node_attr.Value Set nodeList = xmldoc.SelectNodes("*/Valute") For i = 0 To nodeList.Length - 1 ' поиск нужной валюты Set xmlNode = nodeList.Item(i).CloneNode(True) If xmlNode.ChildNodes(1).Text = CurrencyName Then CurrencyRate = CDbl(xmlNode.ChildNodes(4).Text) divisor = Val(xmlNode.ChildNodes(2).Text) GetRate = CurrencyRate / divisor Exit Function End If Next End Function
Sub ПримерИспользованияФункции_GetRate() MsgBox "Сегодня курс доллара к рублю составил " & GetRate("USD", Now), vbInformation MsgBox "А вчера курс евро к рублю был равен " & GetRate("EUR", Now - 1), vbInformation End Sub
[/vba]
Выцепил его на каком-то сайте, подозреваю, что, может быть, кто-то из местных спецов его мутил. Вот он работает хорошо, то есть даже в выходные и праздники цепляет курсы валют по указанному символу на указанную дату. Его бы переписать для металлов, потому что сейчас для металлов он работать не хочет (ну или я просто не знаю, какой символ для серебра вписать - перепробовал кучу разных вариантов, не сработало).
Вот по поводу конкретных дат праздников ничего не могу сказать. Не проследил график работы ЦБ в этом вопросе.
Знаете, у меня есть модуль для цепляния курса валют с сайта ЦБ:
[vba]
Код
Sub ВывестиСегодняшниеКурсыВсехВалют() On Error Resume Next Set xmldoc = CreateObject("Msxml.DOMDocument"): xmldoc.async = False url_request = "http://www.cbr.ru/scripts/XML_daily.asp?date_req=" + Format(Now, "dd\/mm\/yyyy") If xmldoc.Load(url_request) <> True Then Exit Sub Set nodeList = xmldoc.SelectNodes("ValCurs"): Set xmlNode = nodeList.Item(0).CloneNode(True) Set node_attr = xmlNode.Attributes(0): strDate = node_attr.Value Set nodeList = xmldoc.SelectNodes("*/Valute") For i = 0 To nodeList.Length - 1 Set xmlNode = nodeList.Item(i).CloneNode(True) Debug.Print "Курс " & xmlNode.ChildNodes(1).Text & " (установлен " & strDate & "): " & _ xmlNode.ChildNodes(4).Text & " рублей за " & xmlNode.ChildNodes(2).Text & _ " " & xmlNode.ChildNodes(3).Text Next End Sub
Function GetRate(ByVal CurrencyName As String, ByVal RateDate As Date) As Single ' функция возвращает курс валюты CurrencyName на дату RateDate ' в случае ошибки (неверная дата или название валюты) возвращается 0 On Error Resume Next CurrencyName = UCase(CurrencyName): If Len(CurrencyName) <> 3 Then Exit Function Set xmldoc = CreateObject("Msxml.DOMDocument"): xmldoc.async = False url_request = "http://www.cbr.ru/scripts/XML_daily.asp?date_req=" + Format(RateDate, "dd\/mm\/yyyy")
If xmldoc.Load(url_request) <> True Then Exit Function ' Запрос к серверу ЦБР
' Обработка полученного ответа Set nodeList = xmldoc.SelectNodes("ValCurs"): Set xmlNode = nodeList.Item(0).CloneNode(True) Set node_attr = xmlNode.Attributes(0): strDate = node_attr.Value Set nodeList = xmldoc.SelectNodes("*/Valute") For i = 0 To nodeList.Length - 1 ' поиск нужной валюты Set xmlNode = nodeList.Item(i).CloneNode(True) If xmlNode.ChildNodes(1).Text = CurrencyName Then CurrencyRate = CDbl(xmlNode.ChildNodes(4).Text) divisor = Val(xmlNode.ChildNodes(2).Text) GetRate = CurrencyRate / divisor Exit Function End If Next End Function
Sub ПримерИспользованияФункции_GetRate() MsgBox "Сегодня курс доллара к рублю составил " & GetRate("USD", Now), vbInformation MsgBox "А вчера курс евро к рублю был равен " & GetRate("EUR", Now - 1), vbInformation End Sub
[/vba]
Выцепил его на каком-то сайте, подозреваю, что, может быть, кто-то из местных спецов его мутил. Вот он работает хорошо, то есть даже в выходные и праздники цепляет курсы валют по указанному символу на указанную дату. Его бы переписать для металлов, потому что сейчас для металлов он работать не хочет (ну или я просто не знаю, какой символ для серебра вписать - перепробовал кучу разных вариантов, не сработало).forest1333
Сообщение отредактировал forest1333 - Вторник, 14.10.2014, 01:16
ну с валютами все намного проще. ЦБ сам выдает действующий курс на запрашиваемую дату, а с металлами он этого делать не хочет кстати вот переписанная мной функция, которая делает то же самое, что и GetRate, только в случае ошибки она возвращает #ЗНАЧ [vba]
Код
Function ЦБР#(Optional Curr$, Optional dDate As Date) Dim d As Object, date_req$ Set d = CreateObject("msxml.DOMDocument") If Not CBool(Len(Curr)) Then Curr = "USD" date_req = "?date_req=" & IIf(dDate, dDate, Date) d.async = 0: d.Load ("http://www.cbr.ru/scripts/XML_daily.asp" & date_req) With d.SelectSingleNode("*/Valute[CharCode='" & UCase(Curr) & "']") ЦБР = CDbl(.ChildNodes(4).Text) / Val(.ChildNodes(2).Text) End With Set d = Nothing End Function
[/vba] 1 атрибут- буквенный код валюты, если не указан - по умолчанию "USD" 2 атрибут -дата (как в МетЦБР), если не указана - по умолчанию текущая системная дата
есть мысля по поводу исправления МетЦБР2, если после 14:00 мысля подтвердится, выложу исправленный код
ну с валютами все намного проще. ЦБ сам выдает действующий курс на запрашиваемую дату, а с металлами он этого делать не хочет кстати вот переписанная мной функция, которая делает то же самое, что и GetRate, только в случае ошибки она возвращает #ЗНАЧ [vba]
Код
Function ЦБР#(Optional Curr$, Optional dDate As Date) Dim d As Object, date_req$ Set d = CreateObject("msxml.DOMDocument") If Not CBool(Len(Curr)) Then Curr = "USD" date_req = "?date_req=" & IIf(dDate, dDate, Date) d.async = 0: d.Load ("http://www.cbr.ru/scripts/XML_daily.asp" & date_req) With d.SelectSingleNode("*/Valute[CharCode='" & UCase(Curr) & "']") ЦБР = CDbl(.ChildNodes(4).Text) / Val(.ChildNodes(2).Text) End With Set d = Nothing End Function
[/vba] 1 атрибут- буквенный код валюты, если не указан - по умолчанию "USD" 2 атрибут -дата (как в МетЦБР), если не указана - по умолчанию текущая системная дата
есть мысля по поводу исправления МетЦБР2, если после 14:00 мысля подтвердится, выложу исправленный кодkrosav4ig
Option Explicit Private Declare Function DeleteUrlCacheEntry& Lib "wininet" (ByVal lpszUrlName$) Function МетЦБР2#(code) Application.Volatile False Dim oHTML As HTMLDocument, oDoc As HTMLDocument, elem As HTMLBaseElement, url$, n%, str$, diff#: Set oHTML = New HTMLDocument url = "http://cbr.ru/" DeleteUrlCacheEntry (url) Set oDoc = oHTML.createDocumentFromUrl(url, "") Do DoEvents Loop Until oDoc.readyState = "complete" oHTML.body.innerHTML = oDoc.getElementById("widget_metal").innerHTML Set oDoc = Nothing n = InStr(1, "_auagptpg", LCase(code)) / 2 - 1 + Val(code) Set elem = oHTML.getElementsByTagName("span")(n) With oHTML.getElementsByTagName("i") If Not .Item(n + 1) Is Nothing Then diff = CDbl(.Item(n + 1).Title) End With МетЦБР2 = CDbl(elem.innerText) - diff 'With Application.Caller ' If Not .Comment Is Nothing Then .Comment.Delete ' str = oHTML.getElementsByTagName("ins")(n).ParentNode.innerText ' str = str & CStr(CDate(Mid(Replace(oHTML.LastModified, "/", "/" & Left(oHTML.LastModified, 3)), 7, 10))) ' .AddComment str & Right(oHTML.LastModified, 9) 'End With Set elem = Nothing Set oHTML = Nothing End Function
[/vba] Если при вычислении этой функции появляется окошко c предупреждением о безопасности, то нужно внести cbr.ru в доверенные узлы: пуск->выполнить->Inetcpl.cpl->безопасность->надежные узлы->узлы->убрать галочку, ввести cbr.ru->добавить->закрыть->ОК или пуск->выполнить->Inetcpl.cpl->безопасность->местная интрасеть->узлы->дополнительно->убрать галочку, ввести cbr.ru->добавить->закрыть->ОК->ОК
Option Explicit Private Declare Function DeleteUrlCacheEntry& Lib "wininet" (ByVal lpszUrlName$) Function МетЦБР2#(code) Application.Volatile False Dim oHTML As HTMLDocument, oDoc As HTMLDocument, elem As HTMLBaseElement, url$, n%, str$, diff#: Set oHTML = New HTMLDocument url = "http://cbr.ru/" DeleteUrlCacheEntry (url) Set oDoc = oHTML.createDocumentFromUrl(url, "") Do DoEvents Loop Until oDoc.readyState = "complete" oHTML.body.innerHTML = oDoc.getElementById("widget_metal").innerHTML Set oDoc = Nothing n = InStr(1, "_auagptpg", LCase(code)) / 2 - 1 + Val(code) Set elem = oHTML.getElementsByTagName("span")(n) With oHTML.getElementsByTagName("i") If Not .Item(n + 1) Is Nothing Then diff = CDbl(.Item(n + 1).Title) End With МетЦБР2 = CDbl(elem.innerText) - diff 'With Application.Caller ' If Not .Comment Is Nothing Then .Comment.Delete ' str = oHTML.getElementsByTagName("ins")(n).ParentNode.innerText ' str = str & CStr(CDate(Mid(Replace(oHTML.LastModified, "/", "/" & Left(oHTML.LastModified, 3)), 7, 10))) ' .AddComment str & Right(oHTML.LastModified, 9) 'End With Set elem = Nothing Set oHTML = Nothing End Function
[/vba] Если при вычислении этой функции появляется окошко c предупреждением о безопасности, то нужно внести cbr.ru в доверенные узлы: пуск->выполнить->Inetcpl.cpl->безопасность->надежные узлы->узлы->убрать галочку, ввести cbr.ru->добавить->закрыть->ОК или пуск->выполнить->Inetcpl.cpl->безопасность->местная интрасеть->узлы->дополнительно->убрать галочку, ввести cbr.ru->добавить->закрыть->ОК->ОКkrosav4ig
Set XML = Nothing sURL = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx" Set XML = Nothing On Error Resume Next Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP") With oXMLHTTP .Open "POST", sURL, False .setRequestHeader "SOAPAction", "http://web.cbr.ru/DragMetDynamicXML" .setRequestHeader "Content-Type", "text/xml; charset=utf-8" .send s Set XML = .responsexml End With Set oXMLHTTP = Nothing If XML Is Nothing Then DragMetDynamic = "": Exit Function For Each x In XML.SelectNodes("//CodMet") If Val(x.Text) = Met Then DragMetDynamic = Val(x.ParentNode.ChildNodes(2).Text) End If Next Set XML = Nothing End Function
[/vba]
Проверте мой вариант
[vba]
Код
ЦЕНА= DragMetDynamic(Date, 2)
Function DragMetDynamic(Dt As Date, Met) Dim sURL As String, XML As Object Dim s, ToDate As String ToDate = Format(Dt, "yyyy-MM-dd")
Set XML = Nothing sURL = "http://www.cbr.ru/DailyInfoWebServ/DailyInfo.asmx" Set XML = Nothing On Error Resume Next Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP") With oXMLHTTP .Open "POST", sURL, False .setRequestHeader "SOAPAction", "http://web.cbr.ru/DragMetDynamicXML" .setRequestHeader "Content-Type", "text/xml; charset=utf-8" .send s Set XML = .responsexml End With Set oXMLHTTP = Nothing If XML Is Nothing Then DragMetDynamic = "": Exit Function For Each x In XML.SelectNodes("//CodMet") If Val(x.Text) = Met Then DragMetDynamic = Val(x.ParentNode.ChildNodes(2).Text) End If Next Set XML = Nothing End Function
Function МетЦБР#(Optional Code% = 2, Optional dDate As Date) Dim d As Object, ddate1 As Date: Set d = CreateObject("MSXML2.DOMDocument.4.0") dDate = IIf(dDate, dDate, Date): ddate1 = Application.EDate(dDate, -1): d.async = 0 d.Load ("http://www.cbr.ru/scripts/xml_metall.asp?date_req1=" & ddate1 & "&date_req2=" & dDate) МетЦБР= CDbl(d.SelectSingleNode("*/Record[@Code='" & Code & "'][last()]/Buy").Text) Set d = Nothing End Function
[/vba]
переписал МетЦБР. Теперь работает как надо [vba]
Код
Function МетЦБР#(Optional Code% = 2, Optional dDate As Date) Dim d As Object, ddate1 As Date: Set d = CreateObject("MSXML2.DOMDocument.4.0") dDate = IIf(dDate, dDate, Date): ddate1 = Application.EDate(dDate, -1): d.async = 0 d.Load ("http://www.cbr.ru/scripts/xml_metall.asp?date_req1=" & ddate1 & "&date_req2=" & dDate) МетЦБР= CDbl(d.SelectSingleNode("*/Record[@Code='" & Code & "'][last()]/Buy").Text) Set d = Nothing End Function
Народ, подскажите пожалуйста, почему не работает такой код по извлечению цены на золото? Или напишите рабочий вариант. [vba]
Код
Sub GetZoloto() Dim xmldoc, nodeList On Error Resume Next Set xmldoc = CreateObject("Msxml.DOMDocument"): xmldoc.async = False 'страница выгрузки данных http://www.cbr.ru/scripts/xml_metall.asp?date_req1=12/02/2016&date_req2=12/02/2016 url_request = ("http://www.cbr.ru/scripts/xml_metall.asp?date_req1=" & _ Format(InputBox("Введите начальную дату поиска в формате ДД.ММ.ГГГГ", "Курс Золота", Date), "dd\/mm\/yyyy") & _ "&date_req2=" & _ Format(InputBox("Введите конечную дату поиска в формате ДД.ММ.ГГГГ", "Курс Золота", Date), "dd\/mm\/yyyy")) If Not xmldoc.Load(url_request) Then Exit Sub Set nodeList = xmldoc.SelectNodes("*/Record[@Code='"1"'][last()]/Buy") If nodeList.Length Then ActiveCell.Value = CDbl(nodeList.Item(0).ChildNodes(4).Text) End Sub
[/vba]
Народ, подскажите пожалуйста, почему не работает такой код по извлечению цены на золото? Или напишите рабочий вариант. [vba]
Код
Sub GetZoloto() Dim xmldoc, nodeList On Error Resume Next Set xmldoc = CreateObject("Msxml.DOMDocument"): xmldoc.async = False 'страница выгрузки данных http://www.cbr.ru/scripts/xml_metall.asp?date_req1=12/02/2016&date_req2=12/02/2016 url_request = ("http://www.cbr.ru/scripts/xml_metall.asp?date_req1=" & _ Format(InputBox("Введите начальную дату поиска в формате ДД.ММ.ГГГГ", "Курс Золота", Date), "dd\/mm\/yyyy") & _ "&date_req2=" & _ Format(InputBox("Введите конечную дату поиска в формате ДД.ММ.ГГГГ", "Курс Золота", Date), "dd\/mm\/yyyy")) If Not xmldoc.Load(url_request) Then Exit Sub Set nodeList = xmldoc.SelectNodes("*/Record[@Code='"1"'][last()]/Buy") If nodeList.Length Then ActiveCell.Value = CDbl(nodeList.Item(0).ChildNodes(4).Text) End Sub