diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
new file mode 100644
index 0000000..1333e15
--- /dev/null
+++ b/.github/workflows/go.yml
@@ -0,0 +1,27 @@
+# This workflow will build a golang project
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
+
+name: Go
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ branches: ["main"]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up Go
+ uses: actions/setup-go@v4
+ with:
+ go-version: "1.22"
+
+ - name: Build
+ run: go build -v ./...
+
+ - name: Test
+ run: go test -v -cover ./...
diff --git a/.gitignore b/.gitignore
index 66fd13c..acc436c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,5 @@
# Dependency directories (remove the comment below to include it)
# vendor/
+
+cover.html
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index bcda1cd..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-language: go
-
-go:
- - 1.17.x
-
-before_install:
- - go get -t -v ./...
-
-script:
- - go test -race -coverprofile=coverage.txt -covermode=atomic
diff --git a/README.md b/README.md
index 2767e91..41a0c7a 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-# Excelsior
+[
](https://github.com/kakilangit/excelsior)
+[
](https://pkg.go.dev/github.com/kakilangit/excelsior)
-[![PkgGoDev](https://pkg.go.dev/badge/github.com/kakilangit/excelsior)](https://pkg.go.dev/github.com/kakilangit/excelsior)
-[![Build Status](https://app.travis-ci.com/kakilangit/excelsior.svg?branch=main)](https://app.travis-ci.com/github/kakilangit/excelsior)
+# Excelsior
An excelize wrapper to separate the presentation and business logic.
@@ -73,3 +73,8 @@ func main() {
}
```
+
+## License
+
+MIT
+Copyright (c) 2022 kakilangit
diff --git a/serialize.go b/serialize.go
index 08f7370..4ab4c47 100644
--- a/serialize.go
+++ b/serialize.go
@@ -44,8 +44,8 @@ func Serialize(f SerializeFn) ([]byte, error) {
return f(file, style)
}
-// DefaultStyleSetter is helper for the default excelsior row style.
-func DefaultStyleSetter(_ int) int {
+// DefaultGetStyleFn is helper for the default excelsior row style.
+func DefaultGetStyleFn(int) int {
return DefaultStyleID
}
diff --git a/serialize_test.go b/serialize_test.go
new file mode 100644
index 0000000..d56cc43
--- /dev/null
+++ b/serialize_test.go
@@ -0,0 +1,65 @@
+package excelsior_test
+
+import (
+ "net/http"
+ "testing"
+
+ "github.com/kakilangit/excelsior"
+ "github.com/xuri/excelize/v2"
+)
+
+type nopResponseWriter struct{}
+
+func (nopResponseWriter) Header() http.Header {
+ return http.Header{}
+}
+
+func (nopResponseWriter) Write([]byte) (int, error) {
+ return 0, nil
+}
+
+func (nopResponseWriter) WriteHeader(int) {}
+
+func TestSerialize(t *testing.T) {
+ data, err := excelsior.Serialize(func(file *excelize.File, style excelsior.Style) ([]byte, error) {
+ const sheetName = "not found alphabet"
+
+ excelsior.SetDefaultSheetName(file, sheetName)
+
+ headers := []any{"alphabet"}
+ data := nopSheetData{row: excelsior.Row{"a"}}
+
+ sheet := excelsior.NewSheet(headers, excelsior.DefaultGetStyleFn, style.Header(), data)
+ if err := sheet.Generate(file, sheetName); err != nil {
+ return nil, err
+ }
+
+ return excelsior.Byte(file)
+ })
+
+ if err != nil {
+ t.Errorf("failed to serialize: %v", err)
+ }
+
+ if len(data) == 0 {
+ t.Errorf("empty data")
+ }
+}
+
+func TestSetHeader(t *testing.T) {
+ header := http.Header{}
+ excelsior.SetHeader(header, "test")
+
+ if header.Get("Content-Disposition") != "attachment; filename=test.xlsx" {
+ t.Errorf("failed to set header")
+ }
+}
+
+func TestWriteByt(t *testing.T) {
+ data := []byte("test")
+ rw := nopResponseWriter{}
+ err := excelsior.WriteByte(data, "test", rw)
+ if err != nil {
+ t.Errorf("failed to write byte: %v", err)
+ }
+}
diff --git a/sheet.go b/sheet.go
index c1e5b9f..b83eaa6 100644
--- a/sheet.go
+++ b/sheet.go
@@ -11,15 +11,15 @@ type SheetProvider interface {
// Row represents Excel row.
type Row []any
-// StyleSetter is signature function for set the row by providing column number.
-type StyleSetter func(colID int) int
+// GetStyleByColIDFn is signature function for get the style by providing column number.
+type GetStyleByColIDFn func(colID int) int
// SheetBase is the interface generated by excelsior.Sheet, reducing the boiler-plates.
type SheetBase interface {
TotalColumn() int
HeaderRow() Row
- HeaderRowStyle() StyleSetter
- RowStyle() StyleSetter
+ HeaderRowStyle() GetStyleByColIDFn
+ RowStyle() GetStyleByColIDFn
}
// SheetData is the interface need to be provided by the user of excelsior.
@@ -31,18 +31,18 @@ type SheetData interface {
// Sheet implements SheetProvider interface.
type Sheet struct {
SheetData
- headerRow Row
- rowSetter StyleSetter
- headStyleID int
+ headerRow Row
+ rowGetStyleFn GetStyleByColIDFn
+ headStyleID int
}
// NewSheet will create new Sheet.
-func NewSheet(headerRow Row, rowSetter StyleSetter, headStyleID int, data SheetData) *Sheet {
+func NewSheet(headerRow Row, rowGetStyleFn GetStyleByColIDFn, headStyleID int, data SheetData) *Sheet {
return &Sheet{
- SheetData: data,
- headerRow: headerRow,
- rowSetter: rowSetter,
- headStyleID: headStyleID,
+ SheetData: data,
+ headerRow: headerRow,
+ rowGetStyleFn: rowGetStyleFn,
+ headStyleID: headStyleID,
}
}
@@ -57,15 +57,15 @@ func (s Sheet) TotalColumn() int {
}
// HeaderRowStyle returns the style rowSetter for the header row.
-func (s Sheet) HeaderRowStyle() StyleSetter {
+func (s Sheet) HeaderRowStyle() GetStyleByColIDFn {
return func(_ int) int {
return s.headStyleID
}
}
// RowStyle returns the style rowSetter for the remaining row.
-func (s Sheet) RowStyle() StyleSetter {
- return s.rowSetter
+func (s Sheet) RowStyle() GetStyleByColIDFn {
+ return s.rowGetStyleFn
}
// Generate creates Excel sheet with provided excelize.File, and sheet name.
diff --git a/sheet_test.go b/sheet_test.go
new file mode 100644
index 0000000..4f58a31
--- /dev/null
+++ b/sheet_test.go
@@ -0,0 +1,63 @@
+package excelsior_test
+
+import (
+ "testing"
+
+ "github.com/kakilangit/excelsior"
+)
+
+type nopSheetData struct {
+ row excelsior.Row
+}
+
+func (nopSheetData) Total() int {
+ return 1
+}
+
+func (d nopSheetData) Row(int) excelsior.Row {
+ return d.row
+}
+
+func TestSheet(t *testing.T) {
+ header := excelsior.Row{"Name", "Age"}
+ getRowStyle := func(int) int { return 0 }
+ headStyleID := 1
+ data := nopSheetData{row: excelsior.Row{"John Doe", 30}}
+ s := excelsior.NewSheet(header, getRowStyle, headStyleID, data)
+
+ if s.TotalColumn() != 2 {
+ t.Errorf("TotalColumn() = %d; want 2", s.TotalColumn())
+ }
+
+ if s.HeaderRow()[0] != "Name" {
+ t.Errorf("HeaderRow()[0] = %s; want Name", s.HeaderRow()[0])
+ }
+
+ if s.HeaderRow()[1] != "Age" {
+ t.Errorf("HeaderRow()[1] = %s; want Age", s.HeaderRow()[1])
+ }
+
+ if s.HeaderRowStyle()(0) != 1 {
+ t.Errorf("HeaderRowStyle()(0) = %d; want 1", s.HeaderRowStyle()(0))
+ }
+
+ if s.HeaderRowStyle()(1) != 1 {
+ t.Errorf("HeaderRowStyle()(1) = %d; want 1", s.HeaderRowStyle()(1))
+ }
+
+ if s.RowStyle()(0) != 0 {
+ t.Errorf("RowStyle()(0) = %d; want 0", s.RowStyle()(0))
+ }
+
+ if s.RowStyle()(1) != 0 {
+ t.Errorf("RowStyle()(1) = %d; want 0", s.RowStyle()(1))
+ }
+
+ if s.Row(0)[0] != "John Doe" {
+ t.Errorf("Row(0)[0] = %s; want John Doe", s.Row(0)[0])
+ }
+
+ if s.Row(0)[1] != 30 {
+ t.Errorf("Row(0)[1] = %d; want 30", s.Row(0)[1])
+ }
+}
diff --git a/stream.go b/stream.go
index f6bae75..77ca1c1 100644
--- a/stream.go
+++ b/stream.go
@@ -7,10 +7,10 @@ import (
)
// SetRow sets a single row.
-func SetRow(writer *excelize.StreamWriter, colID, rowID int, data []any, styleSetter StyleSetter) error {
+func SetRow(writer *excelize.StreamWriter, colID, rowID int, data []any, getStyle GetStyleByColIDFn) error {
row := make([]any, len(data))
for i, value := range data {
- row[i] = excelize.Cell{Value: value, StyleID: styleSetter(i)}
+ row[i] = excelize.Cell{Value: value, StyleID: getStyle(i)}
}
cell, err := excelize.CoordinatesToCellName(colID, rowID)