summaryrefslogtreecommitdiff
path: root/rows_generic.go
diff options
context:
space:
mode:
authorGeorge Abbott <otg@gabbott.dev>2023-06-15 22:17:12 +0100
committerGeorge Abbott <otg@gabbott.dev>2023-06-15 22:17:12 +0100
commit9987f77b7100bb5934faa7427d1a4acda866ff38 (patch)
tree6aa4da902be7f6af0d2926accd151b949f92d81d /rows_generic.go
parentc4d71b0fdb4bef63e1553843efa9cb9ea9270806 (diff)
excelize -> anyxcelizegetRowInterface
Diffstat (limited to 'rows_generic.go')
-rw-r--r--rows_generic.go259
1 files changed, 253 insertions, 6 deletions
diff --git a/rows_generic.go b/rows_generic.go
index fff3019..87f4087 100644
--- a/rows_generic.go
+++ b/rows_generic.go
@@ -1,10 +1,10 @@
-package excelize
+package anyxcelize
import (
- // "bytes"
+ "bytes"
"encoding/xml"
"errors"
- // "fmt"
+ "fmt"
// "io"
// "math"
"strings"
@@ -14,6 +14,226 @@ import (
// "github.com/mohae/deepcopy"
)
+// Functions: cols
+
+// Rows return the current column's row values.
+func (cols *ColsGeneric) RowsGeneric(opts ...Options) ([]any, error) {
+ var rowIterator rowXMLIteratorGeneric
+ if cols.stashCol >= cols.curCol {
+ return rowIterator.cells, rowIterator.err
+ }
+ cols.rawCellValue = parseOptions(opts...).RawCellValue
+ if cols.sst, rowIterator.err = cols.f.sharedStringsReader(); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
+ }
+ decoder := cols.f.xmlNewDecoder(bytes.NewReader(cols.sheetXML))
+ for {
+ token, _ := decoder.Token()
+ if token == nil {
+ break
+ }
+ switch xmlElement := token.(type) {
+ case xml.StartElement:
+ rowIterator.inElement = xmlElement.Name.Local
+ if rowIterator.inElement == "row" {
+ rowIterator.cellCol = 0
+ rowIterator.cellRow++
+ attrR, _ := attrValToInt("r", xmlElement.Attr)
+ if attrR != 0 {
+ rowIterator.cellRow = attrR
+ }
+ }
+ if cols.rowXMLHandlerGeneric(&rowIterator, &xmlElement, decoder); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
+ }
+ case xml.EndElement:
+ if xmlElement.Name.Local == "sheetData" {
+ return rowIterator.cells, rowIterator.err
+ }
+ }
+ }
+ return rowIterator.cells, rowIterator.err
+}
+
+func (f *File) ColsGeneric(sheet string) (*ColsGeneric, error) {
+ name, ok := f.getSheetXMLPath(sheet)
+ if !ok {
+ return nil, ErrSheetNotExist{sheet}
+ }
+ if ws, ok := f.Sheet.Load(name); ok && ws != nil {
+ worksheet := ws.(*xlsxWorksheet)
+ worksheet.Lock()
+ defer worksheet.Unlock()
+ output, _ := xml.Marshal(worksheet)
+ f.saveFileList(name, f.replaceNameSpaceBytes(name, output))
+ }
+ var colIterator columnXMLIteratorGeneric // do me !
+ colIterator.cols.sheetXML = f.readBytes(name)
+ decoder := f.xmlNewDecoder(bytes.NewReader(colIterator.cols.sheetXML))
+ for {
+ token, _ := decoder.Token()
+ if token == nil {
+ break
+ }
+ switch xmlElement := token.(type) {
+ case xml.StartElement:
+ columnXMLHandlerGeneric(&colIterator, &xmlElement)
+ if colIterator.err != nil {
+ return &colIterator.cols, colIterator.err
+ }
+ case xml.EndElement:
+ if xmlElement.Name.Local == "sheetData" {
+ colIterator.cols.f = f
+ colIterator.cols.sheet = trimSheetName(sheet)
+ return &colIterator.cols, nil
+ }
+ }
+ }
+ return &colIterator.cols, nil
+}
+
+// columnXMLHandler parse the column XML element of the worksheet.
+func columnXMLHandlerGeneric(colIterator *columnXMLIteratorGeneric, xmlElement *xml.StartElement) {
+ colIterator.err = nil
+ inElement := xmlElement.Name.Local
+ if inElement == "row" {
+ colIterator.row++
+ for _, attr := range xmlElement.Attr {
+ if attr.Name.Local == "r" {
+ if colIterator.curRow, colIterator.err = strconv.Atoi(attr.Value); colIterator.err != nil {
+ return
+ }
+ colIterator.row = colIterator.curRow
+ }
+ }
+ colIterator.cols.totalRows = colIterator.row
+ colIterator.cellCol = 0
+ }
+ if inElement == "c" {
+ colIterator.cellCol++
+ for _, attr := range xmlElement.Attr {
+ if attr.Name.Local == "r" {
+ if colIterator.cellCol, _, colIterator.err = CellNameToCoordinates(attr.Value); colIterator.err != nil {
+ return
+ }
+ }
+ }
+ if colIterator.cellCol > colIterator.cols.totalCols {
+ colIterator.cols.totalCols = colIterator.cellCol
+ }
+ }
+}
+
+
+// columnXMLIterator defined runtime use field for the worksheet column SAX parser.
+type columnXMLIteratorGeneric struct {
+ err error
+ cols ColsGeneric
+ cellCol, curRow, row int
+}
+
+type ColsGeneric struct {
+ err error
+ curCol, totalCols, totalRows, stashCol int
+ rawCellValue bool
+ sheet string
+ f *File
+ sheetXML []byte
+ sst *xlsxSST
+}
+
+// rowXMLHandler parse the row XML element of the worksheet.
+func (cols *ColsGeneric) rowXMLHandlerGeneric(rowIterator *rowXMLIteratorGeneric, xmlElement *xml.StartElement, decoder *xml.Decoder) {
+ if rowIterator.inElement == "c" {
+ rowIterator.cellCol++
+ for _, attr := range xmlElement.Attr {
+ if attr.Name.Local == "r" {
+ if rowIterator.cellCol, rowIterator.cellRow, rowIterator.err = CellNameToCoordinates(attr.Value); rowIterator.err != nil {
+ return
+ }
+ }
+ }
+ blank := rowIterator.cellRow - len(rowIterator.cells)
+ for i := 1; i < blank; i++ {
+ rowIterator.cells = append(rowIterator.cells, "")
+ }
+ if rowIterator.cellCol == cols.curCol {
+ colCell := xlsxC{}
+ _ = decoder.DecodeElement(&colCell, xmlElement)
+ val, _ := colCell.getValueFrom(cols.f, cols.sst, cols.rawCellValue)
+ rowIterator.cells = append(rowIterator.cells, val)
+ }
+ }
+}
+func (f *File) GetColsGeneric(sheet string, opts ...Options) ([][]any, error) {
+ cols, err := f.ColsGeneric(sheet)
+ if err != nil {
+ return nil, err
+ }
+ results := make([][]any, 0, 64)
+ for cols.Next() {
+ col, _ := cols.RowsGeneric(opts...)
+ results = append(results, col)
+ }
+ return results, nil
+}
+
+
+// Next will return true if the next column is found.
+func (cols *ColsGeneric) Next() bool {
+ cols.curCol++
+ return cols.curCol <= cols.totalCols
+}
+
+// Error will return an error when the error occurs.
+func (cols *ColsGeneric) Error() error {
+ return cols.err
+}
+
+// Rows return the current column's row values.
+func (cols *ColsGeneric) Rows(opts ...Options) ([]any, error) {
+ var rowIterator rowXMLIteratorGeneric
+ if cols.stashCol >= cols.curCol {
+ return rowIterator.cells, rowIterator.err
+ }
+ cols.rawCellValue = parseOptions(opts...).RawCellValue
+ if cols.sst, rowIterator.err = cols.f.sharedStringsReader(); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
+ }
+ decoder := cols.f.xmlNewDecoder(bytes.NewReader(cols.sheetXML))
+ for {
+ token, _ := decoder.Token()
+ if token == nil {
+ break
+ }
+ switch xmlElement := token.(type) {
+ case xml.StartElement:
+ rowIterator.inElement = xmlElement.Name.Local
+ if rowIterator.inElement == "row" {
+ rowIterator.cellCol = 0
+ rowIterator.cellRow++
+ attrR, _ := attrValToInt("r", xmlElement.Attr)
+ if attrR != 0 {
+ rowIterator.cellRow = attrR
+ }
+ }
+ if cols.rowXMLHandlerGeneric(&rowIterator, &xmlElement, decoder); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
+ }
+ case xml.EndElement:
+ if xmlElement.Name.Local == "sheetData" {
+ return rowIterator.cells, rowIterator.err
+ }
+ }
+ }
+ return rowIterator.cells, rowIterator.err
+}
+
+
+
+
+// Functions: rows
+
func (f *File) GetRowsGeneric(sheet string, opts ...Options) ([][]any, error) {
rows, err := f.RowsGeneric(sheet)
if err != nil {
@@ -194,8 +414,10 @@ func (c *xlsxC) getValueFromGeneric(f *File, d *xlsxSST, raw bool) (any, error)
defer f.Unlock()
switch c.T {
case "b": // done, not tested
+ // fmt.Println("Calling c.getcellBoolGeneric")
return c.getCellBoolGeneric(f, raw)
case "d": // done, not tested
+ // fmt.Println("Calling c.getCellDateGeneric")
return c.getCellDateGeneric(f, raw)
case "s": // Don't touch, strings are a-ok
if c.V != "" {
@@ -216,6 +438,7 @@ func (c *xlsxC) getValueFromGeneric(f *File, d *xlsxSST, raw bool) (any, error)
return f.formattedValue(c.S, c.V, raw)
default: // For integrals and floatings? These need to go into int or float64.
// We need to change it to return an int or a decimal.
+ // fmt.Println("Calling c.getCellNumeric")
return c.getCellNumeric(f, raw)
// if isNum, precision, decimal := isNumeric(c.V); isNum && !raw {
// if precision > 15 {
@@ -239,7 +462,7 @@ func (c *xlsxC) getCellBoolGeneric(f *File, raw bool) (any, error) {
return false, nil
}
- return f.formattedValue(c.S, c.V, raw)
+ return f.formattedValueGeneric(c.S, c.V, raw)
}
// TODO: I probably actually have to like, do something, to get a valid
@@ -253,6 +476,7 @@ func (c *xlsxC) getCellBoolGeneric(f *File, raw bool) (any, error) {
// function not to call formattedValue, and just to return a proper date like
// it should. I don't want to return a float64, but a time.Time I believe.
func (c *xlsxC) getCellDateGeneric(f *File, raw bool) (time.Time, error) {
+ fmt.Printf("getCellDateGeneric with date %v\n", c.V)
// if !raw {
layout := "20060102T150405.999"
if strings.HasSuffix(c.V, "Z") {
@@ -284,18 +508,41 @@ func (c *xlsxC) getCellDateGeneric(f *File, raw bool) (time.Time, error) {
// For now, we could just try parse as a float, and if it doesn't work parse as
// an int, and if it doesn't work cry.
func (c *xlsxC) getCellNumeric(f *File, raw bool) (any, error) {
+ // fmt.Printf("rows.getCellNumeric with value %v\n", c.V)
// This can either be a float or an int. If it is a float, return a
// float64. Otherwise, return an int.
/* TODO: implement according to above comment. */
if isNum, precision, decimal := isNumeric(c.V); isNum && !raw {
+ // fmt.Printf("isNum true, prec{%v} ; decimal(%v)\n", precision, decimal)
+
+ /* new way, see comment below */
+ /* 2023-02-28: I'm commenting this out to try have it call
+ * formattedValueGeneric, which should (?) solve my worries. */
+ // v, err := strconv.ParseInt(c.V, 10, 64)
+ // if err != nil {
+ // return strconv.ParseFloat(c.V, 64)
+ // }
+ // return v, err
+
+
+
if precision > 15 {
+ // We actually just need a way to return a float. I
+ // say try return int first, if it doesn't work try
+ // float, else cry and die.
// Return here a float64
+ // r, err := strconv.ParseFloat(c.V, 64)
+ // fmt.Printf("prec15: ret(%v)\n", r)
+ // return r, err
c.V = strconv.FormatFloat(decimal, 'G', 15, 64)
} else {
// I think, return here an int?
+ // return strconv.ParseInt(c.V, 10, 64)
c.V = strconv.FormatFloat(decimal, 'f', -1, 64)
}
- }
- return f.formattedValue(c.S, c.V, raw)
+ }
+ // fmt.Printf("getCellNumeric is failing, value %v\n", c.V)
+ // return nil, errors.New("getCellNumeric failed like")
+ return f.formattedValueGeneric(c.S, c.V, raw)
}