├── common.go ├── structs.go ├── go.mod ├── LICENSE ├── html.go ├── README.md ├── pdf.go ├── excel.go └── go.sum /common.go: -------------------------------------------------------------------------------- 1 | package json2docs 2 | 3 | import ( 4 | "math/rand" 5 | "strconv" 6 | "time" 7 | ) 8 | 9 | func IsDigit(str string) bool { 10 | _, err := strconv.ParseFloat(str, 64) 11 | return err == nil 12 | } 13 | func RandStringBytes(n int) string { 14 | const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 15 | rand.Seed(time.Now().UnixNano()) 16 | b := make([]byte, n) 17 | for i := range b { 18 | b[i] = letterBytes[rand.Intn(len(letterBytes))] 19 | } 20 | return string(b) 21 | } 22 | -------------------------------------------------------------------------------- /structs.go: -------------------------------------------------------------------------------- 1 | package json2docs 2 | 3 | type Format struct { 4 | Header []HeaderField 5 | BodyHeader []BodyHeaderField 6 | BodyFields []BodyField 7 | Summary []SummaryField 8 | } 9 | 10 | type HeaderField struct { 11 | Line int 12 | Text string 13 | } 14 | 15 | type BodyHeaderField struct { 16 | Index int 17 | Text string 18 | Width int 19 | } 20 | 21 | type BodyField struct { 22 | Index int `json:"Index"` 23 | Field string `json:"Field"` 24 | Width int `json:"Width"` 25 | } 26 | 27 | type SummaryField struct { 28 | Index int 29 | Text string 30 | Width int 31 | } 32 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sanda0/json2docs 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/buger/jsonparser v1.1.1 7 | github.com/jung-kurt/gofpdf v1.16.2 8 | github.com/xuri/excelize/v2 v2.7.1 9 | ) 10 | 11 | require ( 12 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect 13 | github.com/richardlehane/mscfb v1.0.4 // indirect 14 | github.com/richardlehane/msoleps v1.0.3 // indirect 15 | github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect 16 | github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect 17 | golang.org/x/crypto v0.8.0 // indirect 18 | golang.org/x/net v0.9.0 // indirect 19 | golang.org/x/text v0.9.0 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 sandakelum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /html.go: -------------------------------------------------------------------------------- 1 | package json2docs 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "strings" 8 | 9 | "github.com/buger/jsonparser" 10 | ) 11 | 12 | func HtmlTabularGenerator(format []byte, data []byte, filename string) (string, error) { 13 | // Parse the format and data JSON arrays 14 | var formatData Format 15 | err := json.Unmarshal(format, &formatData) 16 | if err != nil { 17 | return "", err 18 | } 19 | 20 | // Create the HTML table string 21 | tableHTML := `` 27 | // Add header lines 28 | tableHTML += `

` 29 | for _, header := range formatData.Header { 30 | tableHTML += fmt.Sprintf(`%s
`, header.Text) 31 | } 32 | tableHTML += "

" 33 | tableHTML += `` 34 | // Add table header 35 | tableHTML += "" 36 | for _, header := range formatData.BodyHeader { 37 | tableHTML += fmt.Sprintf("", header.Text) 38 | } 39 | tableHTML += "" 40 | 41 | // Add table rows 42 | 43 | var items [][]byte 44 | i := 0 45 | jsonparser.ArrayEach(data, func(item []byte, dataType jsonparser.ValueType, offset int, err error) { 46 | items = append(items, item) 47 | var tds []string 48 | for td, _ := range formatData.BodyFields { 49 | tds = append(tds, fmt.Sprintf("%d", td)) 50 | } 51 | tableHTML += "" 52 | 53 | jsonparser.ObjectEach(item, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { 54 | for j, field := range formatData.BodyFields { 55 | if field.Field == string(key) { 56 | if IsDigit(string(value)) { 57 | tds[j] = fmt.Sprintf("", value) 58 | } else { 59 | tds[j] = fmt.Sprintf("", value) 60 | 61 | } 62 | } 63 | 64 | } 65 | 66 | return nil 67 | }) 68 | 69 | tableHTML += strings.Join(tds, "") 70 | 71 | tableHTML += "" 72 | i++ 73 | }) 74 | 75 | // Add summary row 76 | tableHTML += "" 77 | for _, summary := range formatData.Summary { 78 | if IsDigit(string(summary.Text)) { 79 | tableHTML += fmt.Sprintf("", summary.Text) 80 | } else { 81 | tableHTML += fmt.Sprintf("", summary.Text) 82 | 83 | } 84 | } 85 | tableHTML += "" 86 | 87 | tableHTML += "
%s
%s%s
%s%s
" 88 | 89 | // Save the HTML file 90 | filename = filename + ".html" 91 | 92 | err = ioutil.WriteFile(filename, []byte(tableHTML), 0644) 93 | if err != nil { 94 | return "", err 95 | } 96 | 97 | return filename, nil 98 | } 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # json2docs 2 | 3 | ### install 4 | 5 | ``` 6 | go get github.com/sanda0/json2docs 7 | ``` 8 | 9 | ### example 10 | 11 | ```go 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "log" 17 | 18 | "github.com/sanda0/json2docs" 19 | ) 20 | 21 | func main() { 22 | formatJSON := []byte(`{ 23 | "Header": [ 24 | {"Line": 1, "Text": "Abc Company"}, 25 | {"Line": 2, "Text": "123 Main Street"}, 26 | {"Line": 3, "Text": "Special report"}, 27 | {"Line": 4, "Text": "Reporting period January to December 2018"} 28 | ], 29 | "BodyHeader": [ 30 | {"Index": 1, "Text": "Code", "Width": 10}, 31 | {"Index": 2, "Text": "Name", "Width": 30}, 32 | {"Index": 3, "Text": "Quantity", "Width": 10}, 33 | {"Index": 4, "Text": "Price", "Width": 10}, 34 | {"Index": 5, "Text": "Total", "Width": 10}, 35 | {"Index": 6, "Text": "AVG", "Width": 10} 36 | ], 37 | "BodyFields": [ 38 | {"Index": 1, "Field": "prodId", "Width": 10}, 39 | {"Index": 2, "Field": "description", "Width": 30}, 40 | {"Index": 3, "Field": "qty", "Width": 10}, 41 | {"Index": 4, "Field": "price", "Width": 10}, 42 | {"Index": 5, "Field": "amount", "Width": 10}, 43 | {"Index": 6, "Field": "avg", "Width": 10} 44 | 45 | ], 46 | "Summary": [ 47 | {"Index": 1, "Text": "", "Width": 10}, 48 | {"Index": 2, "Text": "", "Width": 30}, 49 | {"Index": 3, "Text": "", "Width": 10}, 50 | {"Index": 4, "Text": "", "Width": 10}, 51 | {"Index": 5, "Text": "150.00", "Width": 10}, 52 | {"Index": 6, "Text": "10.00", "Width": 10} 53 | ] 54 | }`) 55 | 56 | dataJSON := []byte(`[ 57 | { 58 | "prodId": "1", 59 | "description": "Product 1", 60 | "qty": 1, 61 | "price": 10.00, 62 | "amount": 10.00, 63 | "avg": 5.00 64 | }, 65 | { 66 | "prodId": "2", 67 | "description": "Product 2", 68 | "qty": 1, 69 | "price": 20.00, 70 | "amount": 20.00, 71 | "avg": 5.00 72 | 73 | }, 74 | { 75 | "prodId": "3", 76 | "description": "Product 3", 77 | "qty": 1, 78 | "price": 30.00, 79 | "amount": 30.00, 80 | "avg": 5.00 81 | 82 | }, 83 | { 84 | "prodId": "4", 85 | "description": "Product 4", 86 | "qty": 1, 87 | "price": 40.00, 88 | "amount": 40.00, 89 | "avg": 5.00 90 | 91 | }, 92 | { 93 | "prodId": "5", 94 | "description": "Product 5", 95 | "qty": 1, 96 | "price": 50.00, 97 | "amount": 50.00, 98 | "avg": 5.00 99 | 100 | }, 101 | { 102 | "prodId": "3", 103 | "description": "Product 3", 104 | "qty": 1, 105 | "price": 30.00, 106 | "amount": 30.00, 107 | "avg": 5.00 108 | 109 | }, 110 | { 111 | "prodId": "4", 112 | "description": "Product 4", 113 | "qty": 1, 114 | "price": 40.00, 115 | "amount": 40.00, 116 | "avg": 5.00 117 | 118 | }, 119 | { 120 | "prodId": "5", 121 | 122 | "qty": 1, 123 | "price": 50.00, 124 | "amount": 50.00, 125 | "description": "Product 5", 126 | "avg": 5.00 127 | 128 | } 129 | ]`) 130 | 131 | excelFilename,err := json2docs.ExcelTabularGenerator(formatJSON, dataJSON, "filename") 132 | if err != nil { 133 | log.Fatal(err) 134 | } 135 | pdfFilename,err := json2docs.PdfTabularGenerator(formatJSON, dataJSON,"filename") 136 | if err != nil { 137 | log.Fatal(err) 138 | } 139 | htmlFilename,err := json2docs.HtmlTabularGenerator(formatJSON, dataJSON,"filename") 140 | if err != nil { 141 | log.Fatal(err) 142 | } 143 | fmt.Println("Excel file generated:", excelFilename) 144 | fmt.Println("pdf file generated:", pdfFilename) 145 | fmt.Println("html file generated:", htmlFilename) 146 | 147 | // /================================================================ 148 | 149 | } 150 | ``` 151 | Buy Me A Coffee 152 | -------------------------------------------------------------------------------- /pdf.go: -------------------------------------------------------------------------------- 1 | package json2docs 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/buger/jsonparser" 7 | "github.com/jung-kurt/gofpdf" 8 | ) 9 | 10 | func PdfTabularGenerator(format []byte, data []byte, filename string) (string, error) { 11 | // Parse the format and data JSON arrays 12 | var formatData Format 13 | err := json.Unmarshal(format, &formatData) 14 | if err != nil { 15 | return "", err 16 | } 17 | 18 | // Create a new PDF document 19 | pdf := gofpdf.New("P", "mm", "A4", "") 20 | 21 | // Add a new page 22 | pdf.AddPage() 23 | 24 | // Set font and font size for the header 25 | pdf.SetFont("Arial", "B", 16) 26 | 27 | // Print header lines 28 | for _, header := range formatData.Header { 29 | pdf.SetXY(10, float64(header.Line*10)) 30 | pdf.CellFormat(0, 10, header.Text, "", 0, "C", false, 0, "") 31 | } 32 | 33 | // Set font and font size for the table 34 | pdf.SetFont("Arial", "", 12) 35 | 36 | // Set table header background color 37 | pdf.SetFillColor(240, 240, 240) 38 | 39 | // Calculate total table width 40 | totalWidth := 0 41 | for _, header := range formatData.BodyHeader { 42 | totalWidth += header.Width 43 | } 44 | for _, field := range formatData.BodyFields { 45 | totalWidth += field.Width 46 | } 47 | 48 | // Calculate available width on the page 49 | pageWidth, _ := pdf.GetPageSize() 50 | leftMargin, _, rightMargin, _ := pdf.GetMargins() 51 | availableWidth := pageWidth - leftMargin - rightMargin 52 | 53 | // Adjust table width to fit the page 54 | if totalWidth > int(availableWidth) { 55 | scaleFactor := float64(availableWidth) / float64(totalWidth) 56 | for i := range formatData.BodyHeader { 57 | formatData.BodyHeader[i].Width = int(float64(formatData.BodyHeader[i].Width) * scaleFactor) 58 | } 59 | for i := range formatData.BodyFields { 60 | formatData.BodyFields[i].Width = int(float64(formatData.BodyFields[i].Width) * scaleFactor) 61 | } 62 | } 63 | 64 | tableCellWidth := availableWidth / float64(len(formatData.BodyFields)) 65 | // Print table header 66 | x := 10.0 67 | y := float64(len(formatData.Header)*10 + 20) 68 | for _, header := range formatData.BodyHeader { 69 | pdf.Rect(x, y, float64(tableCellWidth), 10, "F") 70 | pdf.SetXY(x, y) 71 | pdf.CellFormat(float64(tableCellWidth), 10, header.Text, "", 0, "C", false, 0, "") 72 | x += float64(tableCellWidth) 73 | } 74 | 75 | // Set body fields values 76 | var items [][]byte 77 | i := 0 78 | jsonparser.ArrayEach(data, func(item []byte, dataType jsonparser.ValueType, offset int, err error) { 79 | 80 | y += 10 81 | items = append(items, item) 82 | jsonparser.ObjectEach(item, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { 83 | x = 10 84 | for _, field := range formatData.BodyFields { 85 | if field.Field == string(key) { 86 | pdf.Rect(x, y, float64(tableCellWidth), 10, "") 87 | pdf.SetXY(x, y) 88 | txt := string(value) 89 | if IsDigit(txt) { 90 | pdf.CellFormat(float64(tableCellWidth), 10, txt, "", 0, "R", false, 0, "") 91 | } else { 92 | pdf.CellFormat(float64(tableCellWidth), 10, txt, "", 0, "C", false, 0, "") 93 | } 94 | } 95 | x += float64(tableCellWidth) 96 | } 97 | 98 | return nil 99 | }) 100 | 101 | i++ 102 | }) 103 | 104 | // Print summary 105 | x = 10.0 106 | for _, summary := range formatData.Summary { 107 | pdf.Rect(x, y, tableCellWidth, 10, "F") 108 | pdf.SetXY(x, y) 109 | if IsDigit(summary.Text) { 110 | pdf.CellFormat(tableCellWidth, 10, summary.Text, "", 0, "R", false, 0, "") 111 | } else { 112 | pdf.CellFormat(tableCellWidth, 10, summary.Text, "", 0, "C", false, 0, "") 113 | } 114 | x += tableCellWidth 115 | } 116 | 117 | // Save the PDF file 118 | filename = filename + ".pdf" 119 | err = pdf.OutputFileAndClose(filename) 120 | if err != nil { 121 | return "", err 122 | } 123 | 124 | return filename, nil 125 | } 126 | -------------------------------------------------------------------------------- /excel.go: -------------------------------------------------------------------------------- 1 | package json2docs 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/buger/jsonparser" 8 | "github.com/xuri/excelize/v2" 9 | ) 10 | 11 | func ExcelTabularGenerator(format []byte, data []byte, filename string) (string, error) { 12 | // Parse format and data JSON 13 | var formatData Format 14 | err := json.Unmarshal(format, &formatData) 15 | if err != nil { 16 | return "", err 17 | } 18 | 19 | // Create a new Excel file 20 | file := excelize.NewFile() 21 | 22 | // Set header values and merge cells 23 | for _, field := range formatData.Header { 24 | cell1 := fmt.Sprintf("A%d", field.Line) 25 | cell2 := fmt.Sprintf("%s%d", GetColumnLetter(len(formatData.BodyHeader)), field.Line) 26 | file.SetCellValue("Sheet1", cell1, field.Text) 27 | file.MergeCell("Sheet1", cell1, cell2) 28 | style, err := file.NewStyle(&excelize.Style{ 29 | Alignment: &excelize.Alignment{ 30 | Horizontal: "center", 31 | }, 32 | }) 33 | if err != nil { 34 | return "", err 35 | } 36 | if err := file.SetCellStyle("Sheet1", cell1, cell2, style); err != nil { 37 | return "", err 38 | } 39 | } 40 | 41 | // Set body header values 42 | for _, field := range formatData.BodyHeader { 43 | cell := fmt.Sprintf("%s%d", GetColumnLetter(field.Index), len(formatData.Header)+1) 44 | file.SetCellValue("Sheet1", cell, field.Text) 45 | file.SetColWidth("Sheet1", GetColumnLetter(field.Index), GetColumnLetter(field.Index), float64(field.Width)) 46 | } 47 | 48 | // Set body fields values 49 | var items [][]byte 50 | i := 0 51 | _, err = jsonparser.ArrayEach(data, func(item []byte, dataType jsonparser.ValueType, offset int, err error) { 52 | items = append(items, item) 53 | jsonparser.ObjectEach(item, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { 54 | for _, field := range formatData.BodyFields { 55 | if field.Field == string(key) { 56 | file.SetCellValue("Sheet1", fmt.Sprintf("%s%d", GetColumnLetter(field.Index), i+2+len(formatData.Header)), string(value)) 57 | file.SetColWidth("Sheet1", GetColumnLetter(field.Index), GetColumnLetter(field.Index), float64(field.Width)) 58 | if IsDigit(string(value)) { 59 | style, err := file.NewStyle(&excelize.Style{ 60 | Alignment: &excelize.Alignment{ 61 | Horizontal: "right", 62 | }, 63 | }) 64 | if err != nil { 65 | return err 66 | } 67 | c := fmt.Sprintf("%s%d", GetColumnLetter(field.Index), i+2+len(formatData.Header)) 68 | if err := file.SetCellStyle("Sheet1", c, c, style); err != nil { 69 | return err 70 | } 71 | } 72 | } 73 | 74 | } 75 | return nil 76 | }) 77 | i++ 78 | }) 79 | 80 | if err != nil { 81 | return "", err 82 | } 83 | 84 | // Set summary values 85 | for _, field := range formatData.Summary { 86 | c := fmt.Sprintf("%s%d", GetColumnLetter(field.Index), len(formatData.Header)+2+len(items)) 87 | file.SetCellValue("Sheet1", c, field.Text) 88 | file.SetColWidth("Sheet1", GetColumnLetter(field.Index), GetColumnLetter(field.Index), float64(field.Width)) 89 | if IsDigit(string(field.Text)) { 90 | style, err := file.NewStyle(&excelize.Style{ 91 | Alignment: &excelize.Alignment{ 92 | Horizontal: "right", 93 | }, 94 | }) 95 | if err != nil { 96 | return "", err 97 | 98 | } 99 | if err := file.SetCellStyle("Sheet1", c, c, style); err != nil { 100 | return "", err 101 | } 102 | } 103 | } 104 | 105 | // Save the Excel file 106 | filename = filename + ".xlsx" 107 | err = file.SaveAs(filename) 108 | if err != nil { 109 | return "", err 110 | } 111 | 112 | return filename, nil 113 | } 114 | 115 | func GetColumnLetter(index int) string { 116 | const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 117 | if index <= 26 { 118 | return string(letters[index-1]) 119 | } 120 | first := (index-1)/26 - 1 121 | second := (index - 1) % 26 122 | return string(letters[first]) + string(letters[second]) 123 | } 124 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 2 | github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= 3 | github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= 8 | github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc= 9 | github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0= 10 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= 11 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= 12 | github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= 13 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 14 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 15 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 16 | github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= 17 | github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= 18 | github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= 19 | github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM= 20 | github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= 21 | github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= 22 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 23 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 24 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 25 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 26 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 27 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 28 | github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c= 29 | github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= 30 | github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI= 31 | github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY= 32 | github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M= 33 | github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= 34 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 35 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 36 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 37 | golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= 38 | golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= 39 | golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 40 | golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= 41 | golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= 42 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 43 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 44 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 45 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 46 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 47 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 48 | golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= 49 | golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= 50 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 51 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 52 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 53 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 54 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 55 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 56 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 57 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 58 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 59 | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 60 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 61 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 62 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 63 | golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= 64 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 65 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 66 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 67 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 68 | golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= 69 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 70 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 71 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 72 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 73 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 74 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 75 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 76 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 77 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 78 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 79 | --------------------------------------------------------------------------------