Вопрос по excel – Написание файла Excel через Erlang

3

Я пытаюсь написать файл Excel через Erlang. Я использовал следующий код для написания файла Excel

-module(excel).
-export([start/1]).

start(Val)->
        case  file:open("office-test.xls",[append]) of
        {ok,Fd} -> io:format(" file created"),
                io:fwrite(Fd,"~p\t~p\t~p~n", ["Name","Date","Number"]),
                export(Fd,Val),
                file:close(Fd);
        {error,_} ->  io:format("~nerror in creation of file")
        end.


export(_,0)->
        ok;

export(Fd,Val) ->
        io:fwrite(Fd, "~p\t~p\t~p\t~n" ,["B123","2012/10/11 12:12:12","val"++integer_to_list(Val)]),
        export(Fd,Val-1).

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

1) Есть ли такой способ, что офис (MS Office или Libre Office) будет автоматически анализировать его. ??

2) Есть ли другой способ написать листы Excel через Erlang .. ??

Ваш Ответ

2   ответа
-1

Следующая информация по следующей ссылке, она создает данные Excel напрямую и удовлетворяет вашим требованиям:

http://www.erlang.org/documentation/doc-5.0.1/lib/comet-1.0/doc/html/ch_examples.html

3 примера

Подробные примеры использования Comet 3.1 Примеры комет

В этой главе подробно описаны некоторые примеры использования Comet; самые простые первые и самые продвинутые последние.

Приведены четыре примера:

Browsing to a specified address

Opening Excel, dumping some data, showing a graph

Calling a function in a C++ library

Исходный код для них включен в дистрибутив, в каталог комет / примеров.

Аббревиатуры VB и VBA используются для Visual Basic и Visual Basic для приложений. 3.2 Требования

Первый пример требует, чтобы был установлен Internet Explorer 4.0 или новее.

Пример два требует Excel из Office 97 или Office 2000.

Последний пример можно запустить как есть, но для изменения COM-библиотеки требуется Visual C ++ 5.0 или более поздняя версия. 3.3 Пример первый, открытие браузера для определенного URL

В этом примере показано, как открыть браузер (Internet Explorer) и перейти по нему по определенному адресу.

Чтобы получить интерфейс COM для браузера, мы используем инструмент, такой как OLE / COM Object Viewer, который включен в Microsoft Windows Platform SDK, Visual C и Visual Basic.

Проверяя интерфейс для Internet Explorer, мы находим пару вещей, которые нам нужны. Во-первых, нам нужен идентификатор класса. Затем нам нужен список имен и параметров функций и свойств, необходимых для создания и использования браузера.

Поскольку запуск браузера не является критичной для производительности задачей, мы можем использовать самый медленный и безопасный способ сделать это из Erlang. Это означает запуск erl_com в качестве процесса порта и использование интерфейса IDispatch для доступа к Internet Explorer.

Хотя Internet Explorer предоставляет двойной интерфейс (то есть интерфейс с таблицей методов и интерфейсом IDispatch), интерфейс IDispatch безопаснее и медленнее. Предоставление списка неверных параметров возвращает код ошибки, а не дамп ядра.

Чтобы использовать COM-объект, мы должны запустить сервер (который запускает порт) и запустить поток. Затем мы можем создать объект и делать с ним все, что хотим.

Чтобы иметь возможность использовать константы, мы помещаем источник в модуль, а не вызываем его интерактивно в оболочке Erlang.

-module(win_browse).

-include("erl_com.hrl").

-export([open/1, example/0]).
open(Url) ->
    {ok, Pid}= erl_com:start_process(),
    T= erl_com:new_thread(Pid),
    Obj= erl_com:create_dispatch(T, "InternetExplorer.Application", 
                                 ?CLSCTX_LOCAL_SERVER),
    erl_com:invoke(Obj, "Navigate", [Url]),
    erl_com:property_put(Obj, "Visible", true),
    Obj.

example() ->
    open("www.erlang.org").

Приложение Internet Explorer имеет диспетчерский интерфейс, который реализует интерфейс IWebBrowser. Есть много методов. Мы используем метод Navigate, чтобы открыть определенный URL, и свойство Visible, чтобы показать браузер. (По умолчанию браузер создается невидимым, как и другие программы Microsoft, используемые в COM.) 3.4 Пример два, создание графика в Excel

В этом примере мы также запускаем экземпляр приложения Excel. Мы используем имя программы «Excel.Application», которое можно использовать вместо идентификатора класса. Это выбирает Excel, который установлен; Excel из Office 97 или Office 2000.

Самый простой способ сделать что-либо с Excel - это сначала записать макрос VBA. Полученный макрос VBA показан на рисунке 1. Этот макрос немного переписан вручную, чтобы упростить его. Мы попробуем это, и результат показан на рисунке 2.

Теперь, чтобы выполнить это в Erlang, у нас есть два варианта: либо мы можем вызвать код VB как подпрограмму, используя COM из Erlang, либо мы можем переопределить макрос VB в Erlang. Поскольку это руководство пользователя, мы, конечно, выбираем последнее.

Чтобы добраться до интерфейсов, мы используем OLE / COM Object Viewer и получаем IDL для Excel. Доступна библиотека типов Excel. Мы не хотим всего этого, потому что это огромно. Мы просто выбираем нужные интерфейсы: _Application, _Graph и _Range. Мы также извлекаем некоторые перечисления, которые являются константами, используемыми для параметров в вызовах COM.

Есть некоторые хитрые проблемы при вызове COM из Erlang

Во-первых, VB неявно обрабатывает освобождение COM-интерфейсов. Erlang и COM этого не делают, поэтому мы должны вызывать erl_com: release / 1 для каждого получаемого нами интерфейса. Например, каждый _Range, который мы получаем из свойства _Application.Range, должен быть освобожден. Мы делаем это во вспомогательной функции data_to_column / 3.

Во-вторых, когда возвращается интерфейс, он возвращается как целое число. Это целое число на самом деле является индексом в массиве интерфейса, содержащемся в программе порта erl_com_drv. При вызове функций в erl_com мы должны предоставить как pid, так и номер потока, так что есть вспомогательная функция erl_com :: package_interface / 2, которая перепаковывает целое число интерфейса с данным потоком или другим интерфейсом. Однако при передаче интерфейса в качестве параметра функции COM (через erl_com: call или erl_com: invoke) интерфейс должен быть преобразован в указатель, что делается с помощью записи кортежа для типов COM: {vt_unknown, Interface}.

Когда Excel запускается, мы выполняем серию команд Excel для ввода данных и построения графика. Команды переведены из макроса VBA, который мы получили с помощью стандартного средства записи макросов Excel.

Мы используем некоторые константы, которые необходимы для команд Excel. Они взяты из генерации кода Visual Basic из интерфейсов Excel. Хотя их можно извлечь из Excel с помощью COM, erl_com пока не поддерживает это. (Будущие выпуски будут включать генерацию кода, которая значительно упростит использование больших COM-интерфейсов.

-module(xc).
-author('[email protected]').

-include("erl_com.hrl").

%% enum XlChartFormat
-define(XlPieExploded, 69).
-define(XlPie, 5).

%% enum XlChartLocation
-define(xlLocationAsNewSheet, 1).
-define(xlLocationAsObject, 2).
-define(xlLocationAutomatic, 3.


%% enum XlRowCol
-define(xlColumns, 2).
-define(xlRows, 1).


-export([populate_area/4, f/3, make_graph/6, sample1/0]).

to_cell_col(C) when C > 26 ->
        [C / 26 + 64, C rem 26 + 64];
to_cell_col(C) ->
        [C+64].

populate_area(E, _, _, []) ->
        ok;
populate_area(E, Row, Col, [Data | Resten]) ->
        Cell= to_cell_col(Col)++integer_to_list(Row),
        io:format(" ~s ~n ", [Cell]),
        N= erl_com:property_get(E, "range", [Cell]),
        Range= erl_com:package_interface(E, N),
        erl_com:property_put(Range, "Value", Data),
        erl_com:release(Range),
        populate_area(E, Row+1, Col, Resten).

f(E, _, []) ->
        ok;
f(E, Startcell, [Data | Resten]) ->
        {R, C}= Startcell,
        Cell= "R"++integer_to_list(R)++"C"++integer_to_list(C),
        io:format(" ~p ~n ", [Cell]),
        f(E, {R+1, C}, Resten).

make_graph(E, Row1, Col1, Row2, Col2, Title) ->
        Charts = erl_com:package_interface(E, erl_com:property_get(E, "Charts")),
        erl_com:invoke(Charts, "Add"),
        ActiveChart= erl_com:package_interface(E, erl_com:property_get
                                               (E, "ActiveChart")),
        erl_com:property_put(ActiveChart, "ChartType", {vt_i4, ?XlPieExploded}),
        erl_com:invoke(ActiveChart, "Location", [{vt_i4, ?xlLocationAsObject}, 
                                                 "Sheet1"]),
        Chart= erl_com:package_interface(E, erl_com:property_get(E, "ActiveChart")),
        R= to_cell_col(Col1)++integer_to_list(Row1)++":"
         ++to_cell_col(Col2)++integer_to_list(Row2),
        io:format(" ~s ~n ", [R]),
        Range= erl_com:property_get(E, "Range", [R]),
        erl_com:invoke(Chart, "SetSourceData", [{vt_unknown, Range}, 
                                                {vt_i4, ?xlColumns}]),
        erl_com:property_put(Chart, "HasTitle", true),
        ChartTitle= erl_com:package_interface(E, erl_com:property_get
                                              (Chart, "ChartTitle")),
        erl_com:property_put(ChartTitle, "Caption", Title).
        %erl_com:release(erl_com:package_interface(E, Range)),
        %erl_com:release(ActiveChart),
        %erl_com:release(Charts).

sample1() ->
        {ok, Pid}= erl_com:start_process(),
        T= erl_com:new_thread(Pid),
        E= erl_com:create_dispatch(T, "Excel.Application", ?CLSCTX_LOCAL_SERVER),
        erl_com:property_put(E, "Visible", true),
        Wb= erl_com:package_interface(T, erl_com:property_get(E, "Workbooks")),
        erl_com:invoke(Wb, "Add"),
        populate_area(E, 1, 1, ["Erlang", "Java", "C++"]),
        populate_area(E, 1, 2, ["25", "100", "250"]),
        make_graph(E, 1, 1, 3, 2, "Programming errors, by programming language"),
        {T, E, Wb}.

3.5 Пример три, вызов COM-объекта в C ++

Быть готовым

4

ты должен написатьCSV , Comma delimited text file, Вы должны были бы сохранить это с.csv  расширение файла. Вы пишете в этот файл построчно. убедитесь, что каждая строка заканчивается\r\n, Этот файл можно прочитать очень хорошо из Excel.

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

Name,Sex,Project\r\n
Joe Armstrong,Male,Erlang\r\n
Klacke Wickstrom,Male,Yaws\r\n
Rusty R,Male,Nitrogen\r\n
Bill Gates,Male,\r\n
Muzaaya Joshua,Male,ZeePay\r\n
Также имеет значение кодировка файла. Кодировка ANSI лучше. Вы также можете обрабатывать файлы Excel в Erlang, сначала преобразовав / повторно сохранив файл как.csv , comma delimited file используя Excel.
Тогда используйте этоcsv file parser module
%%% --- csv parser in Erlang. ------
%%% To help process large csv files without loading them into
%%% memory. Similar to the xml parsing technique of SAX
-module(csv). -compile(export_all).
parse(FilePath,ForEachLine,Opaque)-> case file:open(FilePath,[read]) of {_,S} -> start_parsing(S,ForEachLine,Opaque); Error -> Error end.

start_parsing(S,ForEachLine,Opaque)-> Line = io:get_line(S,''),
case Line of eof -> {ok,Opaque}; "\n" -> start_parsing(S,ForEachLine,Opaque); "\r\n" -> start_parsing(S,ForEachLine,Opaque); _ -> NewOpaque = ForEachLine(scanner(clean(clean(Line,10),13)),Opaque), start_parsing(S,ForEachLine,NewOpaque) end.
scan(InitString,Char,[Head|Buffer]) when Head == Char -> {lists:reverse(InitString),Buffer}; scan(InitString,Char,[Head|Buffer]) when Head =/= Char -> scan([Head|InitString],Char,Buffer); scan(X,_,Buffer) when Buffer == [] -> {done,lists:reverse(X)}. scanner(Text)-> lists:reverse(traverse_text(Text,[])).
traverse_text(Text,Buff)-> case scan("",$,,Text) of {done,SomeText}-> [SomeText|Buff]; {Value,Rem}-> traverse_text(Rem,[Value|Buff]) end.
clean(Text,Char)-> string:strip(string:strip(Text,right,Char),left,Char).

Как использовать этот модуль для анализа CSV-файлов из Excel. Пример нашего простого CSV-файла выше, в оболочке

C:\Windows\System32>erl
Eshell V5.9  (abort with ^G)
1> ForEachLine = fun(Line,Buffer)-> io:format("Line: ~p~n",[Line]),Buffer end.
#Fun<erl_eval.12.111823515>
2> InitialBuffer = [].
[]
3> csv:parse("E:/erlang_projects.csv",ForEachLine,InitialBuffer).
Line: ["Name","Sex","Project"]
Line: ["Joe Armstrong","Male","Erlang"]
Line: ["Klacke Wickstrom","Male","Yaws"]
Line: ["Rusty R","Male","Nitrogen"]
Line: ["Bill Gates","Male",[]]
Line: ["Muzaaya Joshua","Male","ZeePay"]
{ok,[]}
4> ForEachLine2 = fun(Line,Buffer)-> io:format("Line: ~p~n",[Line]),[Line|Buffer] end.
#Fun<erl_eval.12.111823515>
5> csv:parse("E:/erlang_projects.csv",ForEachLine2,InitialBuffer).
Line: ["Name","Sex","Project"]
Line: ["Joe Armstrong","Male","Erlang"]
Line: ["Klacke Wickstrom","Male","Yaws"]
Line: ["Rusty R","Male","Nitrogen"]
Line: ["Bill Gates","Male",[]]
Line: ["Muzaaya Joshua","Male","ZeePay"]
{ok,[["Muzaaya Joshua","Male","ZeePay"],
     ["Bill Gates","Male",[]],
     ["Rusty R","Male","Nitrogen"],
     ["Klacke Wickstrom","Male","Yaws"],
     ["Joe Armstrong","Male","Erlang"],
     ["Name","Sex","Project"]]}
6>

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

Похожие вопросы