package loader import ( "fmt" "io" "math" "strconv" "strings" "git.ecogood.org/andreas.schroepfer/excelConverter/pkg/ecalc" "git.ecogood.org/andreas.schroepfer/excelConverter/pkg/set" "github.com/360EntSecGroup-Skylar/excelize/v2" ) // XLSX reads the data out of the reader. If conf is nil // the default configuration is used. func XLSX(r io.Reader, conf *Conf) (*ecalc.Ecalc, error) { eBalance := &ecalc.Ecalc{} var errs []error if conf == nil { conf = DefaultConf() } eBalance.Version = conf.Version eBalance.Type = conf.Type xFile, err := excelize.OpenReader(r) if err != nil { return nil, fmt.Errorf("XLSX.OpenReader: %w", err) } for _, v := range conf.Values { cellValue, err := xFile.GetCellValue( xFile.GetSheetName(v.Sheet), v.Cell, ) if err != nil { errs = append(errs, err) } switch v.Struct { case "CompanyFacts": set.Field(&eBalance.CompanyFacts, v.Field, cellValue) } } for _, a := range conf.Areas { switch a.Struct { case "SupplyFraction": for r := a.StartRow; r <= a.EndRow; r++ { sf := ecalc.SupplyFraction{} for _, c := range a.Cols { axis := fmt.Sprintf("%s%d", c.Col, r) cellValue, err := xFile.GetCellValue( xFile.GetSheetName(a.Sheet), axis) if err != nil { errs = append(errs, err) } if cellValue == c.Default { continue } else if c.Split != "" { cellValue = strings.Split(cellValue, c.Split)[0] } err = set.Field(&sf, c.Field, cellValue) if err != nil { errs = append(errs, fmt.Errorf("XLSXL.SupplyFraction: Sheet %d, Cell %s: %w", a.Sheet, axis, err)) } } if (sf == ecalc.SupplyFraction{}) { // do not add a empty struct continue } eBalance.CompanyFacts.SupplyFractions = append( eBalance.CompanyFacts.SupplyFractions, sf) } case "EmployeesFraction": for r := a.StartRow; r <= a.EndRow; r++ { ef := ecalc.EmployeesFraction{} for _, c := range a.Cols { axis := fmt.Sprintf("%s%d", c.Col, r) cellValue, err := xFile.GetCellValue( xFile.GetSheetName(a.Sheet), axis) if err != nil { errs = append(errs, err) } if cellValue == c.Default { continue } else if c.Split != "" { cellValue = strings.Split(cellValue, c.Split)[0] } err = set.Field(&ef, c.Field, cellValue) if err != nil { errs = append(errs, fmt.Errorf("XLSXL.EmployeesFraction: Sheet %d, Cell %s: %w", a.Sheet, axis, err)) } } if (ef == ecalc.EmployeesFraction{}) { // do not add a empty struct continue } eBalance.CompanyFacts.EmployeesFractions = append( eBalance.CompanyFacts.EmployeesFractions, ef) } case "IndustrySector": for r := a.StartRow; r <= a.EndRow; r++ { is := ecalc.IndustrySector{} for _, c := range a.Cols { axis := fmt.Sprintf("%s%d", c.Col, r) cellValue, err := xFile.GetCellValue( xFile.GetSheetName(a.Sheet), axis) if err != nil { errs = append(errs, err) } if cellValue == c.Default { continue } else if c.Split != "" { cellValue = strings.Split(cellValue, c.Split)[0] } err = set.Field(&is, c.Field, cellValue) if err != nil { errs = append(errs, fmt.Errorf("XLSXL.IndustrySector: Sheet %d, Cell %s: %w", a.Sheet, axis, err)) } } if (is == ecalc.IndustrySector{}) { // do not add a empty struct continue } eBalance.CompanyFacts.IndustrySectors = append( eBalance.CompanyFacts.IndustrySectors, is) } } } var topic ecalc.Topic for r := conf.Rating.StartRow; r <= conf.Rating.EndRow; r++ { shortName, err := xFile.GetCellValue( xFile.GetSheetName(conf.Rating.Sheet), fmt.Sprintf("%s%d", conf.Rating.ShortNameCol, r), ) if err != nil { errs = append(errs, err) } if len(shortName) < 2 { continue } else if len(shortName) == 2 { if topic.ShortName != "" { eBalance.CompanyFacts.Rating.Topics = append(eBalance.CompanyFacts.Rating.Topics, topic) } topic = ecalc.Topic{ ShortName: shortName, } for _, c := range conf.Rating.Cols { cellValue, err := xFile.GetCellValue( xFile.GetSheetName(conf.Rating.Sheet), fmt.Sprintf("%s%d", c.Col, r), ) if err != nil { errs = append(errs, err) } set.Field(&topic, c.Field, cellValue) } } else { aspect := ecalc.Aspect{ ShortName: shortName, } for _, c := range conf.Rating.Cols { cellValue, err := xFile.GetCellValue( xFile.GetSheetName(conf.Rating.Sheet), fmt.Sprintf("%s%d", c.Col, r), ) if err != nil { errs = append(errs, err) } set.Field(&aspect, c.Field, cellValue) } topic.Aspects = append(topic.Aspects, aspect) } } eBalance.CompanyFacts.Rating.Topics = append(eBalance.CompanyFacts.Rating.Topics, topic) for _, stakeh := range conf.Matrix.Stakeholders { for _, val := range conf.Matrix.Values { mTopic := ecalc.MatrixTopic{ ShortName: fmt.Sprintf("%s%s", stakeh.ShortName, val.ShortName), } readCell := func(col, field string) { axis := fmt.Sprintf("%s%d", col, stakeh.Row) cellValue, err := xFile.GetCellValue( xFile.GetSheetName(conf.Matrix.Sheet), axis, ) if err != nil { errs = append(errs, err) } f, err := strconv.ParseFloat(cellValue, 64) switch field { case "Points": f = math.Round(f) mTopic.Points = int(f) case "MaxPoints": f = math.Round(f) mTopic.MaxPoints = int(f) case "PercentageReached": mTopic.PercentageReached = int(f * 100) } // fmt.Println(axis, field, f, cellValue) } readCell(val.PointsCol, "Points") readCell(val.MaxPointsCol, "MaxPoints") readCell(val.PercentageReachedCol, "PercentageReached") eBalance.Matrix.Topics = append(eBalance.Matrix.Topics, mTopic) } } // TODO: error handling of errs return eBalance, nil }