commit fed464e87e786698ac9bddcac53ebcfb65eb485a Author: RobViren Date: Mon Oct 18 10:19:17 2021 -0500 Added diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e604003 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +data.db \ No newline at end of file diff --git a/CFY.sql b/CFY.sql new file mode 100644 index 0000000..e24f140 --- /dev/null +++ b/CFY.sql @@ -0,0 +1,3 @@ +-- SQLite +SELECT SUM(quantity) AS qty, SUM(revenue) AS rev +FROM data WHERE description LIKE "%RoboSHOT 30E USB%" AND date >= '2021-01-01'; \ No newline at end of file diff --git a/buildwin.sh b/buildwin.sh new file mode 100644 index 0000000..b22f909 --- /dev/null +++ b/buildwin.sh @@ -0,0 +1,3 @@ +#!/usr/bin/zsh + +CGO_ENABLED=1 CXX="x86_64-w64-mingw32-g++" CXX_FOR_TARGET="x86_64-w64-mingw32-g++" CC="x86_64-w64-mingw32-gcc" CC_FOR_TARGET="x86_64-w64-mingw32-gcc" GOOS=windows GOARCH=amd64 go build -x \ No newline at end of file diff --git a/data.xlsx b/data.xlsx new file mode 100644 index 0000000..05f1501 Binary files /dev/null and b/data.xlsx differ diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9f4d83e --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module github.com/robviren/xl + +go 1.17 + +require ( + github.com/mattn/go-sqlite3 v1.14.8 + github.com/xuri/excelize/v2 v2.4.1 +) + +require ( + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/richardlehane/mscfb v1.0.3 // indirect + github.com/richardlehane/msoleps v1.0.1 // indirect + github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 // indirect + golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect + golang.org/x/text v0.3.6 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6f3637c --- /dev/null +++ b/go.sum @@ -0,0 +1,38 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= +github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/richardlehane/mscfb v1.0.3 h1:rD8TBkYWkObWO0oLDFCbwMeZ4KoalxQy+QgniCj3nKI= +github.com/richardlehane/mscfb v1.0.3/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= +github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o= +github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3 h1:EpI0bqf/eX9SdZDwlMmahKM+CDBgNbsXMhsN28XrM8o= +github.com/xuri/efp v0.0.0-20210322160811-ab561f5b45e3/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= +github.com/xuri/excelize/v2 v2.4.1 h1:veeeFLAJwsNEBPBlDepzPIYS1eLyBVcXNZUW79exZ1E= +github.com/xuri/excelize/v2 v2.4.1/go.mod h1:rSu0C3papjzxQA3sdK8cU544TebhrPUoTOaGPIh0Q1A= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..c5bb78e --- /dev/null +++ b/main.go @@ -0,0 +1,107 @@ +package main + +import ( + "fmt" + "log" + "strconv" + "strings" + "time" + + "database/sql" + + _ "github.com/mattn/go-sqlite3" + "github.com/xuri/excelize/v2" +) + +var schema = ` +CREATE TABLE IF NOT EXISTS data ( + description text, + sku text, + level2 text, + level3 text, + revenue float, + cost float, + quantity integer, + year integer, + month integer +); +` + +type Data struct { + Description string + SKU string + Level2 string + Level3 string + Revenue float64 + Cost float64 + Quantity int64 + Year int64 + Month int64 +} + +func checkErr(err error) { + if err != nil { + log.Fatal(err) + } +} + +func main() { + fmt.Println("Processing excel file...") + start := time.Now() + + f, err := excelize.OpenFile("data.xlsx") + checkErr(err) + + rows, err := f.GetRows("Sheet1") + checkErr(err) + + const offset = 3 + data := []Data{} + for i, row := range rows { + if i >= offset { + new_data := Data{SKU: row[33], Level2: row[29], Level3: row[30], Description: row[44]} + + //Parse Rev + rev, err := strconv.ParseFloat(row[72], 64) + checkErr(err) + new_data.Revenue = rev + + //Parse Cost + cost, err := strconv.ParseFloat(row[16], 64) + checkErr(err) + new_data.Cost = cost + + //Parse Quantity + qty, err := strconv.ParseInt(row[71], 10, 64) + checkErr(err) + new_data.Quantity = qty + + //Parse Time + day, err := time.Parse("2006-01", row[26]) + checkErr(err) + new_data.Year = int64(day.Year()) + new_data.Month = int64(day.Month()) + + data = append(data, new_data) + } + } + + db, err := sql.Open("sqlite3", "data.db") + checkErr(err) + defer db.Close() + + db.Exec("DROP TABLE IF EXISTS data") + db.Exec(schema) + + values := []string{} + for _, elm := range data { + values = append(values, fmt.Sprintf(`("%s","%s","%s","%s",%f,%f,%d,"%d","%d")`, strings.ReplaceAll(elm.Description, "\"", ""), elm.SKU, elm.Level2, elm.Level3, elm.Revenue, elm.Cost, elm.Quantity, elm.Year, elm.Month)) + } + + stmt := "INSERT INTO data (description,sku,level2,level3,revenue,cost,quantity,year,month) VALUES " + strings.Join(values, ",") + _, err = db.Exec(stmt) + checkErr(err) + + elapsed := time.Since(start) + fmt.Printf("Operation complete in %s\n", elapsed) +} diff --git a/top.sql b/top.sql new file mode 100644 index 0000000..d9d8636 --- /dev/null +++ b/top.sql @@ -0,0 +1,68 @@ +SELECT + description, + sku, + level2, + level3, + rev, + qty, + trend, + sum(rev) over ( + partition by level2 + ) theorder +from + ( + SELECT + ROW_NUMBER () OVER ( + PARTITION BY level2 + ORDER BY + SUM(revenue) DESC + ) rownum, + SUM(revenue) OVER (PARTITION BY level2) total, + description, + sku, + level2, + level3, + ROUND(SUM(revenue), 2) as rev, + SUM(quantity) as qty, + trend + FROM + ( + select + *, + cast(past as float) / 3 as past, + round( + cast(present as float) /(cast(past as float) / 3.0), + 2 + ) as trend + from + ( + select + *, + sum(quantity) FILTER ( + WHERE + year = 2021 + and month between 6 + and 8 + ) over (PARTITION BY description) as past, + sum(quantity) FILTER ( + WHERE + year = 2021 + and month = 9 + ) over (PARTITION BY description) as present + from + data + ) + ) + where + year = 2021 + and month = 9 + GROUP BY + description + ORDER BY + total DESC + ) +WHERE + rownum <= 10 + and rev > 0 +order by + theorder desc; \ No newline at end of file