go-csv-table/gocsvtable.go
2025-03-30 13:14:15 -03:00

114 lines
2.3 KiB
Go

package gocsvtable
import (
"encoding/csv"
"fmt"
"io"
"os"
)
type GoCSVtable struct {
file *csv.Reader
rows int
data [][]string
Headers map[string]int
Separator rune
Comment rune
lastRow int
// Row is the active CSV row, the data will start at 1
Row int
}
func (gct *GoCSVtable) OpenCSV(filename string) error {
osfile, err := os.Open(filename)
if err != nil {
return fmt.Errorf("Not possible to os.Open file: %s\n", err)
}
defer osfile.Close()
// The default rune is 0
if gct.Separator != 0 {
gct.file.Comma = gct.Separator
}
// The default rune is 0
if gct.Comment != 0 {
gct.file.Comment = gct.Comment
}
gct.file = csv.NewReader(osfile)
gct.data, err = gct.file.ReadAll()
if err != nil {
return fmt.Errorf("Not possible to csv.ReadAll file: %s\n", err)
}
gct.getHeaders()
// First data row is 1
gct.Row = 1
// Last row number
gct.lastRow = len(gct.data) - 1
return nil
}
// getHeaders will associate the Headers names with the correct column number
func (gct *GoCSVtable) getHeaders() {
header := gct.data[0]
columnsNumber := len(header)
// Initiate Headers
gct.Headers = make(map[string]int)
for field := 0; field < columnsNumber; field++ {
name := header[field]
gct.Headers[name] = field
}
}
// Next will jump to the next CSV row. If file is over, will return an io.EOF
func (gct *GoCSVtable) Next() error {
if gct.Row >= gct.lastRow {
return io.EOF
}
gct.Row++
return nil
}
// GetNumberOfRows will return the number of data rows, not considering the
// header
func (gct *GoCSVtable) GetNumberOfRows() int {
return gct.lastRow
}
// Read return a specific field from active row
func (gct *GoCSVtable) Read(field string) string {
col := gct.Headers[field]
return gct.data[gct.Row][col]
}
// Read and return the entire row
func (gct *GoCSVtable) ReadRow(row int) ([]string, error) {
if row > gct.lastRow {
return []string{}, fmt.Errorf("Not possible to read row %v. Data has max of %v rows.\n", row, gct.lastRow)
}
return gct.data[row], nil
}
// ReadCol will return a slice with all row values from a single column (field)
func (gct *GoCSVtable) ReadCol(field string) ([]string, error) {
data := []string{}
fieldNumber := gct.Headers[field]
for row := 1; row <= gct.lastRow; row++ {
data = append(data, gct.data[row][fieldNumber])
}
return data, nil
}