Skip to content

Commit

Permalink
Initial implementation of excel support (no tests)
Browse files Browse the repository at this point in the history
  • Loading branch information
JasiekChomiak committed Aug 8, 2019
1 parent e1beee3 commit 8ac2bbf
Show file tree
Hide file tree
Showing 5 changed files with 666 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -15,6 +15,7 @@ OctoSQL is a query tool that allows you to join, analyse and transform data from
- [PostgreSQL](#postgresql)
- [MySQL](#mysql)
- [Redis](#redis)
- [Excel](#excel)
- [Documentation](#documentation)
- [Architecture](#architecture)
- [Datasource Pushdown Operations](#datasource-pushdown-operations)
Expand Down Expand Up @@ -123,6 +124,18 @@ CSV file seperated using commas. The first row should contain column names.
##### options:
- path - path to file containing the data, required

---
#### Excel
A single, coherent table in a Excel spreadsheet.
The data may or may not have column names as first row.
The data can be in any sheet, and start at any point, but it must
be coherent (no spaces between rows, no spaces between columns).
##### options:
- path - path to file, required
- columns - does the first row contain column names, optional: defaults to true
- sheet - name of the sheet in which data is stored, optional: defaults to "Sheet1"
- root - name of cell (i.e "A3", "BA14") which is the leftmost cell of the first
row, optional: defaults to "A1"
---
#### PostgreSQL
Single PostgreSQL database table.
Expand Down
2 changes: 2 additions & 0 deletions cmd/octosql/main.go
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"github.com/cube2222/octosql/storage/excel"
"log"
"os"
"reflect"
Expand Down Expand Up @@ -52,6 +53,7 @@ With OctoSQL you don't need O(n) client tools or a large data analysis system de
"mysql": mysql.NewDataSourceBuilderFactoryFromConfig,
"postgres": postgres.NewDataSourceBuilderFactoryFromConfig,
"redis": redis.NewDataSourceBuilderFactoryFromConfig,
"excel": excel.NewDataSourceBuilderFactoryFromConfig,
},
cfg,
)
Expand Down
99 changes: 99 additions & 0 deletions storage/excel/cell.go
@@ -0,0 +1,99 @@
package excel

import (
"github.com/pkg/errors"
"strconv"
"strings"
"unicode"
)

var ErroneousCell = newCell("_", 0)

type cell struct {
column string
row int
}

func newCell(col string, row int) cell {
return cell{
column: col,
row: row,
}
}

func (cell cell) getCellName() string {
return cell.column + strconv.Itoa(cell.row)
}

func isAllZs(columnName string) bool {
for _, char := range columnName {
if char != 'Z' {
return false
}
}

return true
}

func (cell cell) getCellToTheRight() cell {
columnName := cell.column

if isAllZs(columnName) {
newColumnName := strings.Repeat("A", len(columnName)+1)
return newCell(newColumnName, cell.row)
}

index := len(columnName)

newColumnName := ""

for i := len(columnName) - 1; i >= 0; i-- {
index--

if columnName[i] == 'Z' {
newColumnName += "A"
} else {
newColumnName = string(columnName[i]+1) + newColumnName
break
}
}

newColumnName = columnName[:index] + newColumnName

return newCell(newColumnName, cell.row)
}

func (cell cell) getCellBelow() cell {
return newCell(cell.column, cell.row+1)
}

func isCorrectChar(char rune) bool {
return unicode.IsUpper(char) || unicode.IsDigit(char)
}

func getCellFromName(cell string) (cell, error) {

for index, char := range cell {
if !isCorrectChar(char) {
return ErroneousCell, errors.Errorf("The character %v can't make up for column name", char)
}

if unicode.IsDigit(char) {
if index == 0 {
return ErroneousCell, errors.Errorf("The first char of a cell can't be a digit")
}

columnName := cell[:index]
row := cell[index:]

rowNumeric, err := strconv.Atoi(row)
if err != nil {
return ErroneousCell, errors.Wrap(err, "couldn't parse row of cell")
}

return newCell(columnName, rowNumeric), nil
}
}

return ErroneousCell, errors.Errorf("cell %s has no row number", cell)
}

0 comments on commit 8ac2bbf

Please sign in to comment.