RatesToExcel

Часто возникающий (и довольно практичный) вопрос у пользователей MetaTrader - «Как скопировать котировки в Excel?» . При помощи библиотеки ATcl это программируется довольно легко. В состав библиотеки входит «большая» программа работающая с Excel, но для частых потребностей сделал короткий скрипт, который делает самую простую вещь - экспорт данных из MT4 в таблицу.


Вам понадобиться - библиотека ATcl и скрипт разбираемый в данной статье. В следующих версиях он будет включен в дистрибутив. Прикладываемый к статье скрипт поместите в каталог скриптов терминала (не забудьте скопилировать, прикладывается только текст),а потом для экспорта котировок - просто перетаскивайте его на нужный график.

Работа скрипта основана на пакете Cawt - автоматизация доступа к MS-Office. Документация по всем его функциям : http://www.cawt.tcl3d.org/download/CawtReference.html

Из всего обилия функционала Cawt, нам потребуются только:

Полное описание этих функций см. в документации 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 построен на основе этой библиотеки и её функции вам доступны.


Если Вам интересен проект вы можете помочь материально :-)

https://paypal.me/nektomk

другие способы: donate

по возможности укажите наиболее интересные для вас фичи

Вследствии малой адекватности администрации mql5.com, мне закрыт доступ к фрилансу и мои продукты понижены в рейтинге ротации (если не исключены полностью).

Сделать персональный заказ на разработку пока можно только на странице http://nektomk.ru/service:start или через личые контакты http://nektomk.ru/contact