用Erlang编写Excel文件

用Erlang编写Excel文件,excel,erlang,Excel,Erlang,我正在尝试通过erlang编写excel文件。我使用以下代码编写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"

我正在尝试通过erlang编写excel文件。我使用以下代码编写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) 是否有任何方式使office(ms office或libre office)自动解析它


2) 是否有其他方法通过erlang.编写excel表格?

以下链接中的以下信息,可直接创建excel数据,并满足您的要求:

3个例子

有关如何使用Comet的详细示例 3.1彗星实例

本章详细描述了有关Comet使用的som示例;首先是最简单的,最后是最高级的

以下是四个例子:

Browsing to a specified address

Opening Excel, dumping some data, showing a graph

Calling a function in a C++ library
这些的源代码包含在发行版的comet/examples目录中

缩写VB和VBA用于Visual Basic和Visual Basic for Applications。 3.2要求

第一个示例要求安装Internet Explorer 4.0或更高版本

示例二需要Office 97或Office 2000中的Excel

最后一个示例可以运行,但要修改COM库,需要VisualC++ 5或更高版本。 3.3示例一,打开特定URL的浏览器

此示例显示如何打开浏览器(Internet Explorer),并在其中导航到特定地址

为了获得浏览器的COM接口,我们使用了一个工具,如OLE/COM对象查看器,它包含在Microsoft的Windows平台SDK、Visual C和Visual Basic中

检查InternetExplorer的界面,我们发现了一些我们需要的东西。首先,我们需要类ID。然后我们需要创建和使用浏览器所需的函数和属性的名称和参数列表

由于启动浏览器不是一项性能关键任务,因此我们可以使用最慢、最安全的方式从Erlang启动浏览器。这意味着将erl_com作为端口进程启动,并使用IDispatch接口访问Internet Explorer

尽管Internet Explorer提供了双接口(即同时具有方法表和IDispatch接口的接口),但IDispatch接口更安全、速度更慢。给它一个错误的参数列表,返回一个错误代码,而不是核心转储

要使用COM对象,我们必须启动服务器(启动端口)并启动线程。然后我们可以创建这个对象,并用它做我们想做的事情

为了能够使用常量,我们将源代码放在一个模块中,而不是在erlangshell中交互调用它

-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属性显示浏览器。(默认情况下,浏览器是不可见的,就像从COM使用的其他Microsoft程序一样。) 3.4示例二,在Excel中绘制图形

在本例中,我们还启动了Excel应用程序的一个实例。我们使用程序名“Excel.Application”,它可以用来代替类ID。这将选择安装的Excel;来自Office 97或Office 2000的Excel

使用Excel执行任何操作的最简单方法是首先记录VBA宏。生成的VBA宏如图1所示。此宏被手动重写一点以使其更简单。我们尝试一下,结果如图2所示

现在,要在Erlang中执行此操作,我们有两种选择:要么使用Erlang中的COM调用VB代码作为子例程,要么在Erlang中重新实现VB宏。因为这是用户指南,我们当然选择后者

为了访问接口,我们使用OLE/COM对象查看器,并获取用于Excel的IDL。有一个Excel类型库可用。我们不想要全部,因为它是巨大的。我们只需要选择所需的接口,即_应用程序、_图形和_范围。我们还提取了一些枚举,这些枚举是COM调用中用于参数的常量

从Erlang调用COM时存在一些棘手的问题

首先,VB隐式地处理COM接口的释放。Erlang和COM不能做到这一点,所以我们必须为每个接口调用erl_COM:release/1。例如,我们从属性Application.Range获得的每个_范围都必须被释放。我们在helper函数data_to_列/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命令来输入数据和绘制图形。这些命令是从我们使用Excel的标准宏记录器获得的VBA宏转换而来的

我们使用Excel命令所需的一些常量。这些代码取自Visual Basic从Excel界面生成的代码。尽管可以使用COM从Excel获取这些数据,但erl_COM尚不支持这一点。(未来的版本将包括代码生成,这将大大简化大型COM接口的使用

-module(xc).
-author('jakob@erix.ericsson.se').

-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示例三,在C中调用COM对象++


要完成。

您必须编写一个
CSV、逗号分隔的文本文件
。您必须使用
.CSV
文件扩展名保存它。您可以逐行写入此文件。确保每行以
\r\n
结尾。此文件可以 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 %%% --- 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). 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>