{"id":34212059,"url":"https://github.com/mhshajib/retroxl","last_synced_at":"2026-05-29T17:31:44.441Z","repository":{"id":326965777,"uuid":"1107264649","full_name":"mhshajib/retroxl","owner":"mhshajib","description":"RetroXL — legacy-compatible XLS generation for modern Go applications.","archived":false,"fork":false,"pushed_at":"2025-11-30T23:29:07.000Z","size":833,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-19T01:30:34.070Z","etag":null,"topics":["banking","excel","go","golang","library","spreadsheet","xls","xlsx"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mhshajib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-30T22:04:29.000Z","updated_at":"2025-12-08T08:56:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mhshajib/retroxl","commit_stats":null,"previous_names":["mhshajib/retroxl"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/mhshajib/retroxl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhshajib%2Fretroxl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhshajib%2Fretroxl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhshajib%2Fretroxl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhshajib%2Fretroxl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mhshajib","download_url":"https://codeload.github.com/mhshajib/retroxl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mhshajib%2Fretroxl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33664259,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["banking","excel","go","golang","library","spreadsheet","xls","xlsx"],"created_at":"2025-12-15T21:01:18.209Z","updated_at":"2026-05-29T17:31:44.416Z","avatar_url":"https://github.com/mhshajib.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RetroXL — Legacy-Compatible XLS Generation for Modern Go Applications\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./retroxl.png\" alt=\"RetroXL Logo\" width=\"500\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://pkg.go.dev/github.com/mhshajib/retroxl\"\u003e\u003cimg src=\"https://pkg.go.dev/badge/github.com/mhshajib/retroxl.png\" alt=\"Go Reference\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/mhshajib/retroxl\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/mhshajib/retroxl?branch=main\" alt=\"Go Report Card\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License: MIT\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\nA pure-Go library for converting XLSX/CSV/TSV and in-memory data into legacy-compatible `.xls` files.\n\n`RetroXL` is a lightweight Go library for generating legacy-compatible `XLS` files from modern spreadsheet data. It converts `XLSX`, `CSV`, `TSV`, and in-memory tabular structures into Excel-friendly `.xls` outputs — all without external binaries or system dependencies. `RetroXL` produces SpreadsheetML-based `XLS` files that open seamlessly in Excel and satisfy strict legacy upload systems such as banking portals. The API supports both `file-path` inputs and `in-memory streams`, allowing you to write directly to `disk`, return `bytes` in an API response, or upload to `S3` like cloud storage — all from pure Go.\n\nRepository: https://github.com/mhshajib/retroxl\n\n## Why RetroXL?\n\nMany banking, government, and enterprise portals still refuse `.xlsx` files and\nonly accept legacy `.xls` uploads. Generating real `.xls` files normally requires\nexternal tools like LibreOffice, Python, or Windows-only libraries.\n\nRetroXL solves this by providing a **pure-Go**, dependency-free way to generate\nSpreadsheetML-based `.xls` files directly from your Go services — ideal for APIs,\nbackground jobs, cloud functions, or banking integrations.\n\n## Features\n\n- Pure-Go XLS generation (no LibreOffice, no Python, no system binaries)\n- Converts:\n  - `.xlsx` → `.xls`\n  - `.csv` / `.tsv` → `.xls`\n  - in-memory tables (`[][]any`) → `.xls`\n- Generates SpreadsheetML-compatible `.xls` recognized by Excel\n- Supports:\n  - file-path input/output\n  - byte slice output (`[]byte`)\n  - streaming output via `io.Writer` (HTTP, gRPC, S3)\n- Ideal for:\n  - banking portals\n  - government upload systems\n  - legacy enterprise workflows\n\n## Supported Formats\n\n| Input Type                 | Output                   |\n| -------------------------- | ------------------------ |\n| XLSX file                  | XLS (SpreadsheetML 2003) |\n| CSV / TSV                  | XLS                      |\n| In-memory data (`[][]any`) | XLS                      |\n| gRPC request               | XLS (bytes)              |\n| HTTP streaming             | XLS                      |\n\n## Installation\n\n```bash\ngo get github.com/mhshajib/retroxl\n```\n\n## Basic usage\n\n### Convert an existing `.xlsx` file to `.xls` on disk\n\n```go\npackage main\n\nimport (\n    \"log\"\n\n    \"github.com/mhshajib/retroxl\"\n)\n\nfunc main() {\n    if err := retroxl.ConvertXLSXToXLSFile(\"input.xlsx\", \"output.xls\"); err != nil {\n        log.Fatalf(\"convert failed: %v\", err)\n    }\n}\n```\n\n### Generate a bank upload file from in-memory data\n\n```go\npackage main\n\nimport (\n    \"log\"\n\n    \"github.com/mhshajib/retroxl\"\n)\n\nfunc main() {\n    headers := []string{\"AccountNo\", \"Amount\", \"Reference\"}\n    rows := [][]any{\n        {\"1234567890\", 1200.50, \"Invoice-2025-001\"},\n        {\"0987654321\", 300.00,  \"Invoice-2025-002\"},\n    }\n\n    sheet := retroxl.FromRows(\"BankUpload\", headers, rows)\n\n    if err := retroxl.WriteXLSFile(\"bank_upload.xls\", []retroxl.Sheet{sheet}); err != nil {\n        log.Fatalf(\"write xls failed: %v\", err)\n    }\n}\n```\n\n### Stream XLS content over HTTP\n\n```go\npackage main\n\nimport (\n    \"log\"\n    \"net/http\"\n\n    \"github.com/mhshajib/retroxl\"\n)\n\nfunc bankHandler(w http.ResponseWriter, r *http.Request) {\n    headers := []string{\"AccountNo\", \"Amount\", \"Reference\"}\n    rows := [][]any{\n        {\"1234567890\", 1200.50, \"Invoice-2025-001\"},\n        {\"0987654321\", 300.00,  \"Invoice-2025-002\"},\n    }\n\n    sheet := retroxl.FromRows(\"BankUpload\", headers, rows)\n\n    w.Header().Set(\"Content-Type\", \"application/vnd.ms-excel\")\n    w.Header().Set(\"Content-Disposition\", `attachment; filename=\"bank_upload.xls\"`)\n\n    if err := retroxl.WriteXLSWriter(w, []retroxl.Sheet{sheet}); err != nil {\n        http.Error(w, \"failed to generate xls\", http.StatusInternalServerError)\n        return\n    }\n}\n\nfunc main() {\n    http.HandleFunc(\"/bank-upload.xls\", bankHandler)\n\n    if err := http.ListenAndServe(\":8080\", nil); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\n### Convert any supported path to XLS bytes\n\n```go\ndata, err := retroxl.ConvertAnyToXLSBytes(\"input.xlsx\")\nif err != nil {\n    // handle error\n}\n\n// data contains the XLS file content.\n```\n\n### Convert a slice of structs to XLS\n\n```go\ntype Payment struct {\n    AccountNo string\n    Amount    float64\n    Reference string\n}\n\nfunc main() {\n    items := []Payment{\n        {\"1234567890\", 1200.50, \"Invoice-2025-001\"},\n        {\"0987654321\", 300.00,  \"Invoice-2025-002\"},\n    }\n\n    headers := []string{\"AccountNo\", \"Amount\", \"Reference\"}\n    var rows [][]any\n    for _, p := range items {\n        rows = append(rows, []any{p.AccountNo, p.Amount, p.Reference})\n    }\n\n    sheet := retroxl.FromRows(\"BankUpload\", headers, rows)\n    _ = retroxl.WriteXLSFile(\"payments.xls\", []retroxl.Sheet{sheet})\n}\n```\n\n## API Overview\n\nAll types and functions are documented with GoDoc comments.\n\nKey pieces:\n\n- `type Sheet` – in-memory representation of a sheet\n- `FromRows` – build a `Sheet` from headers and rows\n- `WriteXLSFile` – write one or more sheets to a `.xls` file\n- `WriteXLSBytes` – generate XLS content as `[]byte`\n- `WriteXLSWriter` – stream XLS content to any `io.Writer`\n- `XLSXToSheets` – read `.xlsx` from a path into `[]Sheet`\n- `CSVToSheets` – read `.csv`/`.tsv` into `[]Sheet`\n- `PathToSheets` – helper that dispatches by file extension\n- `ConvertXLSXToXLSFile` / `ConvertXLSXToXLSBytes`\n- `ConvertAnyToXLSFile` / `ConvertAnyToXLSBytes`\n\n## Limitations\n\n- The generated files are XML Spreadsheet 2003 wrapped in `.xls`.\n  They are understood by Excel and many legacy systems that require\n  `.xls`, but they are not BIFF8 binary workbooks.\n- `retroxl` focuses on simple tabular data:\n  - values are written as strings, numbers, or booleans\n  - advanced Excel features such as formulas, styles, and merged cells\n    are not currently supported.\n\n## Contributing\n\nIssues and pull requests are welcome at:\n\nhttps://github.com/mhshajib/retroxl\n\nPlease include tests for any functional changes.\n\n## Contributors\n\n\u003ca href=\"https://github.com/mhshajib/retroxl/graphs/contributors\"\u003e\n  \u003cimg src=\"https://img.shields.io/github/contributors/mhshajib/retroxl?style=for-the-badge\" alt=\"Contributors\"/\u003e\n\u003c/a\u003e\n\n[![Contributors](https://contrib.rocks/image?repo=mhshajib/retroxl\u0026max=36\u0026v=2)](https://github.com/mhshajib/retroxl/graphs/contributors)\n\n## License\n\nRetroXL is licensed under the MIT License.\nSee the full text in [LICENSE](./LICENSE).\n\nAttribution is appreciated but not required.\nSee [RETROXL_ATTRIBUTION](./RETROXL_ATTRIBUTION) for optional attribution guidelines.\n\n```\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhshajib%2Fretroxl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmhshajib%2Fretroxl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmhshajib%2Fretroxl/lists"}