Часто возникающий (и довольно практичный) вопрос у пользователей MetaTrader - «Как скопировать котировки в Excel?» . При помощи библиотеки ATcl это программируется довольно легко. В состав библиотеки входит «большая» программа работающая с Excel, но для частых потребностей сделал короткий скрипт, который делает самую простую вещь - экспорт данных из MT4 в таблицу.
Вам понадобиться - библиотека ATcl и скрипт разбираемый в данной статье. В следующих версиях он будет включен в дистрибутив. Прикладываемый к статье скрипт поместите в каталог скриптов терминала (не забудьте скопилировать, прикладывается только текст),а потом для экспорта котировок - просто перетаскивайте его на нужный график.
Работа скрипта основана на пакете Cawt - автоматизация доступа к MS-Office. Документация по всем его функциям : http://www.cawt.tcl3d.org/download/CawtReference.html
Из всего обилия функционала Cawt, нам потребуются только:
- Excel Open - открыть новый Excel
- Excel AddWorkbook - в уже открытом экселе создать новую книгу
- Excel GetWorksheetIdByIndex - выбрать лист по порядковому номеру
- Excel SelectRangeById - выделить диапазон ячеек листа
- Excel SetRangeValues - заполнить диапазон значениями
- Cawt Destroy - удаление ранее созданных объектов COM
Полное описание этих функций см. в документации Cawt, а их применение максимально прокоментировано в коде
Несколько слов про применение ATcl в скрипте. В основном используются методы
- Set - задать значение именованной переменной, которую потом можно подставлять в следующие выражения
- Eval - производит подстановки переменных и исполняет скрипты
на начальном этапе вы можете вообще обойтись только этими двумя функциями при написании своих программ.
Основу скрипта RatesToExcel составляет функция :
int CopyRatesToExcel(const MqlRates &rates[],int pos=0,int count=WHOLE_ARRAY) { // создаём интерпретатор ATcl *tcl=new ATcl; if (tcl==NULL) return -1; // объекты которыми будем оперировать Tcl_Obj Excel=0; // инстанс Cawt Excel Tcl_Obj Workbook=0; // книга Tcl_Obj Worksheet=0; // лист Tcl_Obj Range=0; // диапазон ячеек Tcl_Obj data=0; // данные // последовательно исполняем команды // прим.: do {...} while(0); нужен чтобы не городить "лесенку" из вложений {{{}}} do { // если в вашем сист.дистрибутиве tcl есть пакет Cawt то закоментируйте // укажем путь к библиотекам включенным в ATcl tcl.Eval("lappend auto_path [ file join [pwd] MQL4 Libraries ATcl lib ]"); // нам нужен будет пакет Cawt if (tcl.Eval("package require cawt")!=TCL_OK) { // если произошла какая-то ошибка, // то её описания можно получить как Result() в виде объекта // или StringResult() в виде строки PrintFormat("package Cawt error %s",tcl.StringResult()); break; } // Открываем Excel // заодно создаём переменную Excel в интерпретаторе для подстановок как $Excel if (tcl.Eval("set Excel [ Excel Open ]")!=TCL_OK) { PrintFormat("[ Excel Open ] error %s",tcl.StringResult()); break; } Excel=tcl.Ref(tcl.Result()); // сохраним результат, чтобы потом вызвать корректный деструктор // Открываем новую пустую книгу // (она будет создана сразу с одним листом) if (tcl.Eval("set Workbook [ Excel AddWorkbook $Excel ]")!=TCL_OK) { PrintFormat("[ Excel AddWorkbook ] error %s",tcl.StringResult()); break; } Workbook=tcl.Ref(tcl.Result()); // чтобы потом вызвать корректный деструктор // Выбираем лист if (tcl.Eval("set Worksheet [ Excel GetWorksheetIdByIndex $Workbook 1 ]")!=TCL_OK) { PrintFormat("[ Excel GetWorksheetById ] error %s",tcl.StringResult()); break; } Worksheet=tcl.Ref(tcl.Result()); // чтобы потом вызвать корректный деструктор // готовим данные // можно было обойтись встроенной Obj(const MqlRates &[],..) но она не отформатирует время data=tcl.Ref(tcl.Obj()); // будет список из строк // первая строка - заголовки колонок tcl.AppendObj(data,tcl.List( tcl.Obj("time"), tcl.Obj("open"), tcl.Obj("high"), tcl.Obj("low"), tcl.Obj("close"), tcl.Obj("tick_volume"), tcl.Obj("spread"), tcl.Obj("real_volume") )); // заполняем данные int total=ArraySize(rates); if (count==WHOLE_ARRAY) count=total; for(int i=0;i<count && i+pos<total;i++) { // добавляем строки tcl.AppendObj(data,tcl.List( tcl.Obj(TimeToString(rates[i+pos].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS)), tcl.Obj(rates[i+pos].open), tcl.Obj(rates[i+pos].high), tcl.Obj(rates[i+pos].low), tcl.Obj(rates[i+pos].close), tcl.Obj(rates[i+pos].tick_volume), tcl.Obj(rates[i+pos].spread), tcl.Obj(rates[i+pos].real_volume) )); } // выделяем ячейки tcl.Set("Row",1); tcl.Set("Col",1); tcl.Set("EndRow",total); tcl.Set("EndCol",8); if (tcl.Eval("set Range [ Excel SelectRangeByIndex $Worksheet $Row $Col $EndRow $EndCol ]")!=TCL_OK) { PrintFormat("[ Excel SelectRangeByIndex ] error %s",tcl.StringResult()); break; } Range=tcl.Ref(tcl.Result()); // чтобы потом вызвать корректный деструктор // копируем данные в ячейки tcl.SetObj("Data",data); if (tcl.Eval("Excel SetRangeValues $Range $Data")!=TCL_OK) { PrintFormat("[ Excel GetWorksheetById ] error %s",tcl.StringResult()); break; } } while(0); // удаляем все созданные объекты if (Range!=0) { tcl.Eval("Cawt Destroy $Range"); tcl.Unref(Range); } if (Worksheet!=0) { tcl.Eval("Cawt Destroy $Worksheet"); tcl.Unref(Worksheet); } if (Workbook!=0) { tcl.Eval("Cawt Destroy $Workbook"); tcl.Unref(Workbook); } if (Excel!=0) { tcl.Eval("Cawt Destroy $Excel"); tcl.Unref(Excel); } if (data!=0) { tcl.Unref(data); } delete tcl; return 0; }
Полный скрипт вызывающий эту функцию прикладываю к статье.ratestoexcel.mq4
Аналогичными методами вы можете не только отправлять данные в Эксель но и читать их, оформлять таблицы, аналогичным образом обращаться к другим программам MS-Office. To есть используя библиотеку ATcl полностю интегрировать свои советники, индикаторы и скрипты с привычным для трейдера окружением.
Если хорошо разбираетесь с системными сервисами, то при помощи ATcl вы можете интегрировать свои программы не только с офисными приложениями, но и вообще со всей системой - для этого есть пакет TWAPI предоставляющий доступ к Windows API. Упомянутый выше Cawt построен на основе этой библиотеки и её функции вам доступны.
Оригинал статьи на моём сайте : http://nektomk.ru/atcl:ratestoexcel
Библиотека ATcl предоставляется бесплатно и без ограничений на использование
Если Вам интересен проект вы можете помочь материально
другие способы: donate
по возможности укажите наиболее интересные для вас фичи
В следствии БАНА никакие заказы через фриланс невозможны,
теперь только исключительно через личные контакты в профиле.
а мои продукты на маркете видимо подавлены в ротации,
но можете с ними ознакомиться на витрине : https://www.mql5.com/ru/users/nektomk/seller