From 0905bbeb07a4ee05682fb2f44dae2be31b488bda Mon Sep 17 00:00:00 2001 From: Zhwt Date: Mon, 2 May 2022 03:02:54 +0800 Subject: [PATCH] feat(main.go, csfutil.go, excel.go): Implement new file and excel import / export logic --- cmd/main.go | 89 ++++++++++++++++++++++++++++++++++++++++++++++------- csfutil.go | 14 +++++++++ excel.go | 76 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 11 deletions(-) create mode 100644 excel.go diff --git a/cmd/main.go b/cmd/main.go index 29218ec..3bd0803 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,6 +5,7 @@ import ( "github.com/Zhwt/csfutil" "github.com/Zhwt/csfutil/utils" "os" + "strconv" ) var usageMessages = map[string]string{ @@ -15,15 +16,19 @@ Exports all CSF LabelValue items inside the given CSF file into a spreadsheet. T This file can be imported into a CSF file later.`, - "import": `Usage: csfutil import + "import": `Usage: csfutil import -Import all CSF LabelValue items inside the spread sheet into the CSF file. Existing items will be overwritten and missing items will be created.`, +Import all CSF LabelValue items inside the spread sheet into the CSF file. Existing items will be overwritten and missing items will be created. The file must have the following structure: + + + +Otherwise the`, "merge": `Usage: csfutil merge Merges all CSF LabelValue items inside the source file into the destination file. Only existing items will be overwritten and missing items won't' be created.`, - "new": `Usage: csfutil new + "new": `Usage: csfutil new [language code] -Create a empty csf file.`, +Create a empty Version 3 csf file. Valid language code can be 0~9, otherwise it will be recognized as "Unknown".`, "help": `csfutil is a tool for manipulating CSF files. Usage: @@ -35,7 +40,7 @@ The commands are: export convert a CSF file to a spreadsheet import merge items from a spreadsheet into a CSF file merge merge one CSF file into another - new create empty CSF file + new create empty Version 3 CSF file Use "csfutil help " for more information about a command.`, } @@ -49,6 +54,10 @@ func help(cmd string) { } } +func printError(err error) { + fmt.Println("Error:", err) +} + func merge(src, dst string) error { srcFile, err := csfutil.Open(src) if err != nil { @@ -56,7 +65,7 @@ func merge(src, dst string) error { } dstFile, err := csfutil.Open(dst) if err != nil { - return fmt.Errorf("%s: %w", src, err) + return fmt.Errorf("%s: %w", dst, err) } for _, s := range dstFile.Order { @@ -81,21 +90,79 @@ func main() { } else { switch os.Args[1] { case "export": - fmt.Println("not implemented") + if argCount == 3 || argCount == 4 { + input := os.Args[2] + output := "output.xlsx" + if argCount == 4 { + output = os.Args[3] + } + + csf, err := csfutil.Open(input) + if err != nil { + printError(err) + return + } + + err = csfutil.ExportExcel(csf, output) + if err != nil { + printError(err) + return + } + } else { + fmt.Println("Incorrect argument count, want 3 or 4, got", argCount) + help(os.Args[1]) + } case "import": - fmt.Println("not implemented") + if argCount == 4 { + input := os.Args[2] + output := os.Args[3] + err := csfutil.ImportExcel(input, output) + if err != nil { + printError(err) + return + } + } else { + fmt.Println("Incorrect argument count, want 4, got", argCount) + help(os.Args[1]) + } case "merge": if argCount == 4 { err := merge(os.Args[2], os.Args[3]) if err != nil { - fmt.Println("Error:", err) + printError(err) + return } } else { fmt.Println("Incorrect argument count, want 4, got", argCount) - help("merge") + help(os.Args[1]) } case "new": - fmt.Println("not implemented") + if argCount == 3 || argCount == 4 { + output := os.Args[2] + language := 0 + var err error + if argCount == 4 { + language, err = strconv.Atoi(os.Args[3]) + if err != nil { + printError(err) + return + } + } + + csf := csfutil.New(output, 3, 0, uint(language)) + if err != nil { + printError(err) + return + } + + if err = csf.Save(); err != nil { + printError(err) + return + } + } else { + fmt.Println("Incorrect argument count, want 3 or 4, got", argCount) + help(os.Args[1]) + } case "help": if argCount > 2 { help(os.Args[2]) diff --git a/csfutil.go b/csfutil.go index cef543b..ef0c22e 100644 --- a/csfutil.go +++ b/csfutil.go @@ -458,3 +458,17 @@ func MustOpen(name string) *CSFUtil { return u } + +func New(name string, version, unused, language uint) *CSFUtil { + return &CSFUtil{ + filename: name, + Version: version, + NumLabels: 0, + NumStrings: 0, + Unused: unused, + Language: language, + Values: map[string]LabelValue{}, + Categories: map[string][]string{}, + Order: []string{}, + } +} diff --git a/excel.go b/excel.go new file mode 100644 index 0000000..7b3a332 --- /dev/null +++ b/excel.go @@ -0,0 +1,76 @@ +package csfutil + +import ( + "fmt" + "github.com/xuri/excelize/v2" + "strconv" +) + +const ( + sheet = "Sheet1" + labelColumn = "A" + valueColumn = "B" + extraValueColumn = "C" +) + +func ExportExcel(csf *CSFUtil, output string) error { + f := excelize.NewFile() + defer f.Close() + + for i := 0; i < len(csf.Order); i++ { + row := strconv.Itoa(i + 1) + + if err := f.SetCellValue(sheet, labelColumn+row, csf.Values[csf.Order[i]].Label.ValueString()); err != nil { + return err + } + + if err := f.SetCellValue(sheet, valueColumn+row, csf.Values[csf.Order[i]].Value.ValueString()); err != nil { + return err + } + + if csf.Values[csf.Order[i]].Value.HaveExtra { + if err := f.SetCellValue(sheet, extraValueColumn+row, csf.Values[csf.Order[i]].Value.ExtraValueString()); err != nil { + return err + } + } + } + + return f.SaveAs(output) +} + +func ImportExcel(input, output string) error { + f, err := excelize.OpenFile(input) + if err != nil { + return err + } + defer f.Close() + + csf, err := Open(output) + if err != nil { + return err + } + + rows, err := f.GetRows(sheet) + if err != nil { + return err + } + + if len(rows) < 1 { + return fmt.Errorf("no data to read") + } + + for i, row := range rows { + switch len(row) { + case 1: + csf.WriteLabelValue(NewLabelValue(row[0], ""), false) + case 2: + csf.WriteLabelValue(NewLabelValue(row[0], row[1]), false) + case 3: + csf.WriteLabelValue(NewLabelValue(row[0], row[1], row[2]), false) + default: + return fmt.Errorf("wrong column count, want 2~3, got %d, at row: %d", len(row), i) + } + } + + return csf.Save() +}