Skip to content

Commit ae5d482

Browse files
committed
update docs and add tests
1 parent 7ca53a1 commit ae5d482

File tree

7 files changed

+141
-41
lines changed

7 files changed

+141
-41
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/_build
22
/cover
33
/deps
4+
/doc
45
erl_crash.dump
56
*.ez

README.md

+34-34
Original file line numberDiff line numberDiff line change
@@ -16,58 +16,58 @@ If [available in Hex](https://hex.pm/docs/publish), the package can be installed
1616

1717
1. Import `Excelerator.Workbook` into your module, then generate the XML content:
1818

19-
workbook do
20-
worksheet "My Sheet" do
21-
row do
22-
cell "Name"
23-
cell "Status"
24-
end
25-
26-
row do
27-
cell "Elixir"
28-
cell 1
19+
workbook do
20+
worksheet "My Sheet" do
21+
row do
22+
cell "Name"
23+
cell "Status"
24+
end
25+
26+
row do
27+
cell "Elixir"
28+
cell 1
29+
end
2930
end
3031
end
31-
end
3232

33-
# => <?xml version="1.0" encoding="UTF-8" ?><Workbook ...
33+
# => <?xml version="1.0" encoding="UTF-8" ?><Workbook ...
3434

3535
## Usage with Phoenix
3636

3737
1. Use `Excelerator.Phoenix` in your controller:
3838

39-
defmodule MyApp.MyController do
40-
use MyApp.Web, :controller
41-
use Excelerator.Phoenix
39+
defmodule MyApp.MyController do
40+
use MyApp.Web, :controller
41+
use Excelerator.Phoenix
4242

4343
1. Import `Excelerator.Workbook` into your view module:
4444

45-
defmodule MyApp.MyView do
46-
use MyApp.Web, :view
47-
import Excelerator.Workbook
45+
defmodule MyApp.MyView do
46+
use MyApp.Web, :view
47+
import Excelerator.Workbook
4848

49-
1. Alternatively, add the use / import statements to the appropriate sections
49+
(Alternatively, add the use / import statements to the appropriate sections
5050
of `web/web.ex`, which will make excelerator available in all controllers/
51-
views.
51+
views.)
5252

5353
1. Call `xls` in your controller action to send content as a file download:
5454

55-
def show(conn, %{"format" => "xls"} = params) do
56-
xls conn, "show.xls", favorite: "Elixir"
57-
end
55+
def show(conn, %{"format" => "xls"} = params) do
56+
xls conn, "show.xls", favorite: "Elixir"
57+
end
5858

5959
1. Create `web/templates/RESOURCE/NAME.xls.exs`
6060

61-
workbook do
62-
worksheet "My Sheet" do
63-
row do
64-
cell "Name"
65-
cell "Status"
66-
end
67-
68-
row do
69-
cell assigns.favorite
70-
cell 1
61+
workbook do
62+
worksheet "My Sheet" do
63+
row do
64+
cell "Name"
65+
cell "Status"
66+
end
67+
68+
row do
69+
cell assigns.favorite
70+
cell 1
71+
end
7172
end
7273
end
73-
end

lib/excelerator/phoenix.ex

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
11
defmodule Excelerator.Phoenix do
2+
@moduledoc """
3+
Provides the `xls` function for rendering Excel spreadsheets as file downloads
4+
from Phoenix controllers.
5+
6+
## Using
7+
8+
When used, `Excelerator.Phoenix` generates the `xls` function in your
9+
controller so you can send file downloads like:
10+
11+
xls conn, "invoice.xls", items: line_items
12+
13+
The attachment filename defaults to the same name as the controller, but can
14+
be overridden with the `:filename` option.
15+
16+
xls conn, "template.xls", data, filename: "SrsBizness.xls"
17+
18+
"""
19+
220
defmacro __using__(options) do
321
quote do
4-
def xls(conn, template, data, opts \\ []) do
5-
excel_data = view_module(conn).render(template, data)
22+
def xls(conn, template, assigns, opts \\ []) do
23+
excel_data = view_module(conn).render(template, assigns)
624

725
default_filename = Phoenix.Naming.resource_name(__MODULE__, "Controller") <> ".xls"
826
filename = Keyword.get(opts, :filename, default_filename)

lib/excelerator/workbook.ex

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
defmodule Excelerator.Workbook do
2+
@moduledoc """
3+
Provides functions to generate Excel spreadsheets.
4+
5+
## Importing
6+
7+
You may want to import this module where you are generating spreadsheets.
8+
"""
9+
210
require Logger
311
import XmlBuilder
412

@@ -25,12 +33,18 @@ defmodule Excelerator.Workbook do
2533
end
2634
end
2735

28-
defmacro row(do: {_, _, statements}) do
36+
defmacro row(do: {_, _, statements} = content) do
2937
quote do
3038
{:Row, unquote(statements)}
3139
end
3240
end
3341

42+
defmacro row(do: content) do
43+
quote do
44+
{:Row, unquote(content || [])}
45+
end
46+
end
47+
3448
def cell(content) when is_bitstring(content), do: cell(content, "String")
3549
def cell(content) when is_number(content), do: cell(content, "Number")
3650
def cell(content) do

mix.exs

+7-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ defmodule Excelerator.Mixfile do
66
app: :excelerator,
77
version: "0.0.1",
88
elixir: "~> 1.0",
9+
name: "excelerator",
10+
source_url: "https://github.com/rubysolo/excelerator",
911
description: description,
1012
package: package,
11-
deps: deps
13+
deps: deps,
14+
docs: [extras: ["README.md"]]
1215
]
1316
end
1417

@@ -18,7 +21,7 @@ defmodule Excelerator.Mixfile do
1821

1922
def description do
2023
"""
21-
Generate Excel workbooks
24+
Generate Excel workbooks in Elixir
2225
"""
2326
end
2427

@@ -36,7 +39,8 @@ defmodule Excelerator.Mixfile do
3639

3740
defp deps do
3841
[
39-
{:xml_builder, github: "joshnuss/xml_builder"}
42+
{:xml_builder, github: "joshnuss/xml_builder"},
43+
{:earmark, "~> 0.1", optional: true},
4044
]
4145
end
4246
end

mix.lock

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
%{"ex_doc": {:git, "https://github.com/elixir-lang/ex_doc.git", "63342194e8a572485b37b4a58668f9b43ab7ab26", []},
1+
%{"earmark": {:hex, :earmark, "0.1.17"},
2+
"ex_doc": {:git, "https://github.com/elixir-lang/ex_doc.git", "63342194e8a572485b37b4a58668f9b43ab7ab26", []},
23
"xml_builder": {:git, "https://github.com/joshnuss/xml_builder.git", "84c310903af9b80fc54829c88d2c4bc898a65233", []}}

test/excelerator/workbook_test.exs

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
defmodule Excelerator.WorkbookTest do
2+
use ExUnit.Case
3+
doctest Excelerator.Workbook
4+
5+
import Excelerator.Workbook
6+
7+
test "top-level workbook structure" do
8+
xml = workbook do: []
9+
assert xml == """
10+
<?xml version="1.0" encoding="UTF-8" ?>
11+
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel">
12+
<Styles>
13+
<Style ss:ID="Default" ss:Name="Normal">
14+
<Alignment ss:Vertical="Bottom"/>
15+
<Borders/>
16+
<Font ss:FontName="Verdana"/>
17+
<Interior/>
18+
<NumberFormat/>
19+
<Protection/>
20+
</Style>
21+
</Styles>
22+
23+
</Workbook>
24+
""" |> String.rstrip
25+
end
26+
27+
test "worksheet with default name" do
28+
sheet = worksheet do: :content
29+
assert sheet == {:Worksheet, %{"ss:Name" => "Sheet1"}, [Table: [:content]]}
30+
end
31+
32+
test "worksheet with custom name" do
33+
sheet = worksheet "Custom", do: :content
34+
assert sheet == {:Worksheet, %{"ss:Name" => "Custom"}, [Table: [:content]]}
35+
end
36+
37+
test "row" do
38+
r = row do
39+
end
40+
assert r == {:Row, []}
41+
end
42+
43+
defmodule User do
44+
defstruct name: "John", age: 27
45+
end
46+
47+
test "row with cells" do
48+
user = %User{}
49+
50+
r = row do
51+
cell "Hello"
52+
cell 123
53+
cell user.name
54+
end
55+
56+
assert r == {:Row, [
57+
{:Cell, [{:Data, %{"ss:Type" => "String"}, "Hello"}]},
58+
{:Cell, [{:Data, %{"ss:Type" => "Number"}, 123}]},
59+
{:Cell, [{:Data, %{"ss:Type" => "String"}, "John"}]},
60+
]}
61+
end
62+
end

0 commit comments

Comments
 (0)