Generate file xls di Elixir

3 Sep 2019

Tips singkat bagaimana mengenerate file xlsx di Elixir dengan paket elixlsx. Pertama tambahkan ektensi ke file mix.exs pada bagian fungsi deps

defp deps do
    {:elixlsx, "~> 0.4.2"}
end

Kemudian jalankan perintah berikut diterminal kamu

$ mix deps.get

Setelah itu baru kita bisa mengenerate file xls. saya asumsikan bahwa kamu sudah membuat modul jadi tinggal tambahkan fungsi download. Misal nama modulnya Playgorund lalu tambahkan alias Elixlsx.Sheet dan Elixlsx.Workbook pada bagian setelah definisi modul.

defmodule Playground do
    alias Elixlsx.{Workbook, Sheet}

    def download do
        rows = [
            %{id: 1, name: "PHP"},
            %{id: 2, name: "Go"},
            %{id: 3, name: "Javascript"},
            %{id: 4, name: "Elixir"},
            %{id: 5, name: "Rust"}
        ]

        sheets = 
            rows
            |> Stream.with_index
            |> Enum.reduce(%Sheet{}, fn({row, idx}, acc) -> 
                acc 
                |> Sheet.set_at(idx, 0, row.id) 
                |> Sheet.set_at(idx, 1, row.name)
            end)

        Workbook.append_sheet(%Workbook{}, sheets) |> Elixlsx.write_to("todos.xlsx")
    end
end

Pada fungsi download kita membuat variabel rows menyimpan struct yang berisi id dan name. Kemudian variabel sheets menyimpan daftar Sheet. Pertama rows kita kirim ke pemipaan(|>) Stream.with_index

rows |> Stream.with_index 

Stream.with_index berfungsi membuat stream data dengan setiap datanya terdiri dari tuple data dan index seperti ini {data, index} sehingga index bisa digunakan untuk isian baris pada sheet.

Hasil dari Stream.with_index kita pipakan lagi ke fungsi sebelah kanan yaitu Enum.reduce, fungsi ini akan mengembalikan daftar sheet. Fungsi ini parameter kedua berupa struct %Sheet{} sebagai accumulator/variabel yang akan menyimpan hasil reduce, parameter ketiga berupa fungsi data dan acc kemudian didalamnya akumulator akan diisi dengan data dari rows di atas. Sheet.set_at(idx, 0, row.id) fungsi akan menset data pada baris idx, kolom 0 dengan value berupa row.id lalu fungsi yang kedua menset data berupa row.name sampai data pada rows habis.

Enum.reduce(%Sheet{}, fn({row, idx}, acc) -> 
    acc 
    |> Sheet.set_at(idx, 0, row.id) 
    |> Sheet.set_at(idx, 1, row.name)
end)

Terakhir sheets akan ditambahkan ke Workbook lalu dipipakan ke fungsi write_to untuk disimpan menjadi file todos.xlsx.

Workbook.append_sheet(%Workbook{}, sheets) |> Elixlsx.write_to("todos.xlsx")

Kemudian buka iex diterminal kamu, lalu seperti biasa ketikan alias Playgorund baru jalankan fungsi download.

$ iex
iex(1)> alias Playground
iex(2)> Playground.download()

sekian.