Журнал LinuxFormat - перейти на главную

LXF94:Макрос, загружающий данные

Материал из Linuxformat
Версия от 17:30, 27 апреля 2008; Lockal (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

Calc: Макрос для чтения данных

Перелопатили все биржевые котировки, только чтоб убедиться: BMW вам уже не купить? Марк Бэйн упростит вам жизнь...

Надеюсь, ваши акции поживают лучше, чем мои – если нет, вам остается только ронять слезы в пиво. Но не падайте духом! Здесь в Linux Format мы, может, и не улучшим ваши навыки по прогнозированию котировок, зато вы с ходу будете видеть, насколько плохи ваши дела.

Поможет, конечно же, OpenOffice.org. На нашем уроке мы сперва рассмотрим, как загрузить финансовую статистику с сайта прямо в таблицу Calc; затем – как по этим данным построить график; а в завершение научимся все это делать автоматически. Фактически, вы сумеете это делать, даже не открывая OOo (кроме как для просмотра результатов). Вообще-то, говоря, что вам не придется открывать OpenOffice.org, я имею в виду, что нужно будет написать пару макросов – но затем вы и вправду сможете обрабатывать данные без открытия OOo.

В любом случае, перво-наперво найдем финансовую статистику. У вас могут быть свои источники – ну, а мы воспользуемся финансовым порталом Yahoo Finance. Если вам безразличны финансовые сводки, не спешите захлопнуть страницу: навыки, полученные здесь, применимы и к другим источникам данных. Однако для целей нашего урока, алчность – это хорошо!

Получаем данные

Вы найдете Yahoo Finance по адресу http://finance.yahoo.com, им довольно легко пользоваться – там есть окошко, содержащее слова Enter Symbol(s) [Введите Символ(ы)] и кнопка с названием Get Quotes [Получить котировки]. Все, что вам надо сделать, это ввести символ компании, в которой вы заинтересованы; Yahoo Finance предоставляет ссылку, которая даст вам этот символ. Например, символ Microsoft на Лондонской фондовой бирже – MSFL. Как только вы введете этот символ и нажмете Получить Котировки, вы увидите самые последние данные о фирме. А сейчас начнется самое интересное: скачаем их!

Взглянув на экран котировок, вы увидите ссылку Скачать Данные [Download Data]. По ней мы добудем URL самих данных: http://download.finance.yahoo.com/d/quotes.csv?s=MSF.L&f=sl1d1t1c1ohgv&e=.csv. А зачем нам URL? Затем, что теперь можно в любой момент набрать его в браузере. Времени тут экономится немного, но главное – начать.

На следующем шаге мы сэкономим гораздо больше времени. Если вы нажмете на Скачать Данные или напечатаете URL, Calc загрузит CVS-файл в мастер импорта. С его помощью вы можете указать разделители данных в файле OpenOffice.org (в нашем случае это, очевидно, будут запятые), а затем OOo поместит каждое поле в свой столбец. Пока ничего нового – вы, возможно, проделывали такое уже сотни раз. Но вместо ручного ввода лучше написать макрос.

Первый макрос

Вы уже поняли, что можно получить котировки акций, написав символ, представляющий фирму, как часть URL в вашем браузере, а затем загрузить их как CSV-файл в OOo Calc через мастер импорта. Теперь, прежде чем писать макрос для импорта, проанализируем импортируемые данные. Заметьте, что поля, которые скачиваются, определяются параметром 'f' в URL. Поэкспериментировав с ними, вы поймете, как работает каждое из них, но сейчас нам нужны только три: 's', название фирмы, 'l1', последняя цена продажи, и 'd1', последняя дата сделки. Таким образом, наш URL превращается в http://download.finance.yahoo.com/d/quotes.csv?s=MSF.L&f=sl1d1&e=.csv, его мы и будем использовать в макросе.

ОК, пора писать макрос. Откройте OpenOffice.org (неважно, какое приложение – сгодится Calc или Writer), затем нажмите Tool > Macros > Organize Macros > OpenOffice.org Basic. Здесь есть список языков на выбор (Basic, Python, BeanShell или JavaScript), но нам сейчас нужен Basic. Появится диалоговое окно, в нем надо нажать на кнопку Organizer. Откроется другой диалог, со вкладкой Module; выберите пункт Standard. Вы, небось, уже недоумеваете: да зачем вообще? – а дело-то простое. Standard – библиотека; в библиотеках хранятся модули; в модулях хранятся макросы. Дошло? Тогда жмите на New, чтобы создать свой собственный модуль в библиотеке Standard.

Нажав на New, вы увидите, что OOo предложит имя вашему модулю: 'Module1'. Не используйте его. Довольно нудно работать с модулями, названными Module1, Module2, Module3, и так до бесконечности. Лучше дать модулю значимое имя – например, свой я назвал 'lxf94' (угадайте, почему). В новом модуле нажмите Edit, и OOo откроет экран редактирования Basic – именно тут мы и создадим макрос.

Тут вы обнаружите, что OpenOffice.org уже создал для вас макрос с именем Main. Предупреждаю: не путайте его с Main, знакомым вам по другим языкам программирования. Здесь это просто пустой макрос, чтобы OpenOffice.org было с чем работать, когда вы нажмете кнопку запуска (на ней изображены угол страницы и стрелка, указывающая вниз). На самом деле OOo запустит первый же макрос, который найдет в модуле. Например, если поместить Main1 выше Main, то он и будет запущен.

Вооруженные этими знаниями, мы готовы писать макрос (поместите этот код после процедуры Main):

Function open_csv_file (url as String) as Object
Dim oProperty(0) as New com.sun.star.beans.PropertyValue
oProperty(0).Name = "FilterOptions"
oProperty(0).Value = "44"
open_csv_file = starDeskTop.loadComponentFromUrl(url, "_blank", 0, oProperty())
End Sub

Созданная функция загружает любой CSV-файл без всякого мастера импорта, используя свойство FilterOptions при установке его значения в 44. Почему 44? Потому что 44 – это код ASCII для… верно, для запятой. А зачем здесь функция? Затем, что open_csv_file создает объект – сам документ – а нам потребуется к нему доступ из кода.

Если вы теперь попробуете запустить код, то ничего не произойдет – потому что Main пока ничего не содержит. Заставим его поработать:

Sub Main
Dim oDoc as Object
oDoc = open_csv_file _("http://download.finance.yahoo.com/d/quotes.csv?s=MSF.L&f=sd1l1&e=.csv")
End Sub

Теперь при нажатии на кнопку запуска произойдет следующее: после пары секунд ожидания (в зависимости от скорости соединения) появится файл Calc, содержащий последние цены на акции для Microsoft на Лондонской фондовой бирже. Уже неплохо, но вы явно думаете «Не проделывать же это для каждой из моих акций – хорошо бы отобразить сразу весь мой портфель.» Отлично, этим и займемся.

Макрос для групповухи

Мы уже видели, как легко автоматизировать загрузку данных по одной фирме. Чтобы сделать тоже самое для их группы, надо просто разжиться новым символом и добавить его в URL. Например, если нас интересует Novell, добавим символ NOVL; наш URL станет таким: http://download.finance.yahoo.com/d/quotes.csv?s=MSF.L&s=NOVL&f=sd1l1&e=.csv. Ради этой новой информации модифицируем наш код. Начнем с добавки новой процедуры – она упростит нам жизнь:

Sub download_stock_price(companySymbols)
Dim oDoc as Object
Dim cSymbols as String, oUrl as String
cSymbols = join(companySymbols, "&s=")
oUrl = "http://download.finance.yahoo.com/d/quotes.csv?s=" _ & cSymbols & "&f=sl1d1&e=.csv"
oDoc = open_csv_file(oUrl)
End Sub

Вы заметите, что новый макрос принимает companySymbols как параметр – это будет массив, содержащий список кодов фирм.

Процедура соединяет все символы в единую строку (с &s= между каждым символом), а затем создает правильный URL для заготовленной нами функции open_csv_file. После создания нового макроса изменим процедуру Main, чтобы она принимала массив фирм:

Sub Main
download_stock_price(array("MSF.L","NOVL"))
End Sub

Когда на этот раз вы нажмете кнопку запуска, то увидите файл Calc, содержащий детали всех фирм, указанных в списке – и, конечно, можете добавить столько символов фирм, сколько душе угодно.

Сохраняем файл

Следующий этап автоматизации – сохранение файла на жесткий диск. Чтобы это сделать, опять напишем макрос:

Sub save_file_as_ods(doc as Object, directory as String, prefix as
String)
Dim oUrl as String
oUrl = convertToUrl(directory & "/" & prefix & ".ods")
doc.storeAsUrl(oUrl,Array())
End Sub

Здесь следует обратить внимание на пару моментов: во-первых, на функцию convertToUrl. При открытии и закрытии файлов макросу требуется имя файла в определенном формате – и convertToUrl делает для вас это преобразование. Во-вторых, вы увидите, что наравне с каталогом и префиксом файла (то есть именем файла без расширения '.ods') процедуре также передается doc. Это имя объекта, созданного с помощью функции open_csv_file.

Далее вам надо немного изменить функцию download_stock_price.

Добавьте следующую строку в конец процедуры:

save_file_as_ods(oDoc, "/tmp", "test_lxf94")

На этот раз, запустив Main, вы увидите, что ваш документ переименован в test_lxf94, а если вы заглянете в каталог /tmp, то найдете файл test_lxf94.ods, который (если его открыть) покажет свежескачанные данные.

В командную строку!

В начале этой статьи я говорил, что все это можно делать, не открывая OpenOffice.org (кроме как для просмотра результата). Давайте выясним, как этого достичь. Узнав, как автоматически открывать и сохранять наш файл, вы сумеете это сделать и без отображения результатов. Начнем с добавления строки кода в конец макроса download_stock_price:

oDoc.close(true)

Она всего-навсего закрывает документ. Если вы запустите Main, то увидите, что документ откроется и сразу же закроется. Зачем мы начали с этого? Да просто чтобы удостовериться, что у нас не останется никаких сессий в фоновом режиме, когда мы приступим к изменениям, которые спрячут наш документ.

Вы уже знаете, как открыть CSV-документ, не используя мастер импорта, установкой соответствующих свойств, и, по-моему, нетрудно сообразить, что открытие документа в невидимом режиме происходит точно так же. Итак, назад к функции open_csv_file. Сначала переопределим свойства, намеченные для использования:

Dim oProperty(1) as New com.sun.star.beans.PropertyValue

Затем укажем детали для нового свойства:

oProperty(1).Name = "Hidden"
oProperty(1).Value = True

Проделав изменения в коде, нажмите на кнопку запуска... и опять ничего. Не пугайтесь. Проверьте:

bainm@aeneas:~> ls -l /tmp/test_lxf94.ods
-rw-r--r-- 1 bainm users 6455 2007-04-23 09:00 /tmp/test_lxf94.ods

Теперь запустите макрос и снова проверьте. Вы увидите, что файл действительно изменился:

bainm@aeneas:~> ls -l /tmp/test_lxf94.ods
-rw-r--r-- 1 bainm users 6454 2007-04-23 09:01 /tmp/test_lxf94.ods

Это значит, что вы можете запускать процессы незримо, но (в настоящий момент) надо держать OpenOffice.org открытым, чтобы запускать макрос. А надо ли? Нет! Закройте все экземпляры OOo и наберите в командной строке:

scalc -headless "macro:///Standard.lxf94.Main"

Абсолютно ничего не произойдет – вы даже не увидите экрана OpenOffice.org. Однако если вы запустите ls -l и посмотрите на файл, то заметите перемены.

Для завершения процедуры автоматизации, создадим задачу Cron: тогда уже не придется беспокоиться о запуске макроса. Например, поставим задание Cron на запуск каждый день в 8:45, и в 9 утра к вашему приходу уже будет новый файл. Чтобы это сделать, откройте командную строку. Наберите crontab -e, а затем:

45 8 * * * scalc -headless "macro:///Standard.lxf94.Main"

Далее нажмите Control-D, чтобы сохранить файл Cron. И все – загрузка ваших котировок полностью автоматизирована.

Представляем графики

Каждый знает, что «лучше один раз увидеть»… это же касается и графиков. Не знаю, как насчет вас, но я понимаю графики лучше, чем голые цифры – а у нас пока что есть только цифры. Давайте преобразуем данные.

Вы ведь умеете создавать график в OpenOffice.org, правда? Просто выбираете ячейки, которые хотите использовать в качестве диапазона, нажимаете на Insert Chart и следуете инструкциям – нет ничего проще. Но разве это не утомительно? Я думаю, вы согласитесь, что это еще один кандидат на автоматизацию. Очевидно, не помешает создать процедуру для рисования графика, но прежде чем это сделать, немного изменим исходный код.

Для начала, мы не будем закрывать документ в процедуре download_stock_price:

REM oDoc.close(true)

Затем перестанем прятать документ в open_csv_file:

oProperty(1).Name = "Hidden"
oProperty(1).Value = False

Это значит, что мы можем разрабатывать новый код, не открывая сохраненный файл, чтобы увидеть эффект. Но тогда по окончании не забудьте включить функции закрытия документа и скрытия отображения. Если вас это устраивает, создайте новую процедуру:

Sub insert_chart (doc as Object, cTitle as String)
End Sub

а затем вставьте новую строку в download_stock_price:

insert_chart (oDoc, "My Shares")

Вам надо поместить ее до выражения save_file_as_ods. Теперь подумаем о том, какой код добавить в новую процедуру.

Если вам случалось вручную создавать график по скачанным данным, то вы уже поняли, что есть проблема: ключ не имеет говорящего имени (он просто пишет Столбец B). Это, конечно, потому, что ключ появляется из строки-шапки – но в нашем случае это тоже данные. Чтобы это исправить, напишем макрос для вставки заголовка:

Sub insert_chart (doc as Object, cTitle as String )
Dim oSheet as Object, oCell as Object
oSheet = doc.Sheets(0)
oSheet.getRows.insertByIndex(0,1)
oCell = oSheet.getCellByPosition(1,0)
oCell.String = "Share Value"
End Sub

Объясняю, что здесь происходит: мы выбираем первый лист таблицы, затем вставляем новую строку, а затем устанавливаем содержимое B1 в Share Value.

Если вы запустите Main и затем вручную создадите график, то увидите, что столбец значений будет назван Share value. Начало хорошее; теперь пусть макрос создает график сам. Первое, что необходимо выявить макросу, это количество используемых данных:

r = 1
oCell = oSheet.getCellByPosition(0,r)
while oCell.String <> ""
r = r + 1
oCell = oSheet.getCellByPosition(0,r)
wend

С помощью этой информации определим диапазон данных в таблице:

Dim oRange as Object
Dim oRangeAddress as Object
oRange = oSheet.getCellRangeByPosition(0,0,1,r – 1)
oRangeAddress = oRange.getRangeAddress

Теперь мы можем определить данные по x и y в объекте CellRangeAddress:

Dim oCellRangeAddress(1) as New com.sun.star.table.CellRangeAddress
'Set X axis
oCellRangeAddress(0).Sheet = oRangeAddress.Sheet
oCellRangeAddress(0).startColumn = oRangeAddress.endColumn
oCellRangeAddress(0).endColumn = oRangeAddress.endColumn
oCellRangeAddress(0).startRow = oRangeAddress.startRow
oCellRangeAddress(0).endRow = oRangeAddress.endRow
'Set Y axis
oCellRangeAddress(1).Sheet = oRangeAddress.Sheet
oCellRangeAddress(1).startColumn = oRangeAddress.startColumn
oCellRangeAddress(1).endColumn = oRangeAddress.startColumn
oCellRangeAddress(1).startRow = oRangeAddress.startRow
oCellRangeAddress(1).endRow = oRangeAddress.endRow

Следующий шаг – определение области для графика. Вы обнаружите, что размер по умолчанию довольно мал, так что сделаем его побольше:

Dim oRect as New com.sun.star.awt.Rectangle
oRect.Width = 20000
oRect.Height = 10000

Прямо сейчас мы можем написать код, рисующий график:

Dim oCharts as Object
oCharts = oSheet.Charts
oCharts.addNewByName(cTitle, oRect, oCellRangeAddress(),TRUE,TRUE)

Вы можете запустить макрос, если хотите – и появится график. Однако работа еще не кончена: например, хорошо бы написать название графика и обозначить оси X и Y…

Dim oChart as Object
oChart = oCharts.getByName(cTitle).embeddedObject
oChart.HasMainTitle = True
oChart.Title.String = cTitle
oChart.diagram.HasXAxisTitle = True
oChart.diagram.XAxisTitle.String = "Company Symbol"
oChart.diagram.HasYAxisTitle = True
oChart.diagram.YAxisTitle.String = "Closing Value"

Теперь у вас есть полностью автоматизированная система для скачивания котировок ваших акций и создания по ним диаграммы. Все, что вам осталось сделать, это включить автоматическое закрытие и скрытие экрана... а на следующее утро встать, выпить кофе и посмотреть на результаты усердной работы.

«Погодите!» – слышу я ваш крик, «Мне не нравится диаграмма из столбиков – желаю, чтоб данные отображались в виде пончика; как насчет этого?» Да легко, хоть и не столь очевидно. Мы использовали тип графика по умолчанию, а чтобы использовать любой другой тип, укажите

oChart.diagram = oChart.createInstance("com.sun.star.chart.DonutDiagram")

Вот полный список доступных типов графиков: AreaDiagram, BarDiagram (по умолчанию), DonutDiagram, LineDiagram, NetDiagram, PieDiagram, StackableDiagram, StockDiagram и XYDiagram.

Теперь можете вытворять что угодно. Можете загрузить CSV-файл прямо в Calc, можете создать любой график по данным, и все это – автоматически, без ввода данных. На данном уроке мы занимались Yahoo Finance, так как он свободно доступен и использует CSV-формат. Вы можете, конечно, использовать любой CSV-файл, то есть любой источник данных, при условии, что они загружаются в OpenOffice.org – например, приложить этот метод к базам данных. Но если вы примените эти приемы на деле для анализа ваших котировок и урвете крупный куш, уж не забудьте, кто научил вас уму-разуму!


Используем crontab

Если вы новичок в crontab, то поля и звездочки могут вас озадачить. Однако порядок полей довольно прост:

  • 1 Минуты (0–59)
  • 2 Часы (0–23)
  • 3 Число (1–31)
  • 4 Месяц (1–12)
  • 5 День недели (0–6, где 0 означает воскресенье)
  • 6 Запускаемая команда

Звездочка означает «запускать в любом случае» – так, * в третьем поле означает «запускать каждый день месяца». Вы также можете использовать комбинации чисел в полях: 1,3,10–20 (снова в 3-м поле) будет означать «запускать по первым и третьим числам и каждый день с 10-го по 20-е».

Необязательный ввод

На нашем уроке мы отключали Скрытый режим, но если вы собираетесь делать это довольно часто, то можете поменять код, чтобы сделать этот аргумент необязательным:

Function open_csv_file (url as String, Optional show_form as Boolean) 
as Object Dim oProperty(1) as New com.sun.star.beans.PropertyValue
if ismissing(show_form) then
show_form = False
end if
oProperty(0).Name = "FilterOptions"
oProperty(0).Value = "44"
oProperty(1).Name = "Hidden"
if (show_form) then
oProperty(1).Value = False
else
oProperty(1).Value = True
end if
open_csv_file = starDeskTop.loadComponentFromUrl(url, "_blank", 0, oProperty())
End Function

Только помните, что по умолчанию документ останется невидимым, а если вы захотите его все же узреть, просто измените код в open_csv_file на

oDoc = open_csv_file(oUrl, True)
Персональные инструменты
купить
подписаться
Яндекс.Метрика