<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mehedi Hasan Sajib</title>
    <description>The latest articles on DEV Community by Mehedi Hasan Sajib (@mhsajib).</description>
    <link>https://dev.to/mhsajib</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3638045%2F7eb4a0de-977e-45c7-98f6-98ce21ce83b6.jpg</url>
      <title>DEV Community: Mehedi Hasan Sajib</title>
      <link>https://dev.to/mhsajib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mhsajib"/>
    <language>en</language>
    <item>
      <title>avro-phonetic-go: Avro-style Banglish to বাংলা transliteration in Go</title>
      <dc:creator>Mehedi Hasan Sajib</dc:creator>
      <pubDate>Mon, 29 Dec 2025 21:23:45 +0000</pubDate>
      <link>https://dev.to/mhsajib/avro-phonetic-go-avro-style-banglish-to-baanlaa-transliteration-in-go-4f6d</link>
      <guid>https://dev.to/mhsajib/avro-phonetic-go-avro-style-banglish-to-baanlaa-transliteration-in-go-4f6d</guid>
      <description>&lt;p&gt;If you work with Bengali users, you already know the problem.&lt;/p&gt;

&lt;p&gt;People type Bangla using Latin letters. Not carefully. Not consistently.&lt;br&gt;
Yet they expect your application to understand them.&lt;/p&gt;

&lt;p&gt;The Avro Phonetic keyboard showed that this problem can be solved using&lt;br&gt;
a grammar-driven approach: pattern matching combined with local context rules.&lt;/p&gt;

&lt;p&gt;This article introduces &lt;strong&gt;avro-phonetic-go&lt;/strong&gt;, a Go library that implements&lt;br&gt;
an Avro-style phonetic transliteration engine with a clean, production-oriented API.&lt;/p&gt;
&lt;h2&gt;
  
  
  Design goals
&lt;/h2&gt;

&lt;p&gt;The library was built with the following principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grammar-driven, not hardcoded&lt;/li&gt;
&lt;li&gt;Deterministic output using longest-match scanning&lt;/li&gt;
&lt;li&gt;Explicit rule evaluation (prefix and suffix constraints)&lt;/li&gt;
&lt;li&gt;No magic heuristics in strict mode&lt;/li&gt;
&lt;li&gt;Optional BD mode for modern Bangladeshi typing shortcuts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The overall idea is credited to the Avro Phonetic keyboard.&lt;br&gt;
The internal design of this library was strongly influenced by&lt;br&gt;
the PHP reference implementation &lt;a href="https://github.com/imerfanahmed/avro-php" rel="noopener noreferrer"&gt;https://github.com/imerfanahmed/avro-php&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick example
&lt;/h2&gt;

&lt;p&gt;Strict mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avrophonetic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;To&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ami bangla gan gai"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// আমি বাংলা গান গাই&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BD mode (opt-in):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avrophonetic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToBD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tmi valo"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// তুমি ভালো&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;At a high level, the engine works in four steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load a grammar consisting of patterns and rules&lt;/li&gt;
&lt;li&gt;Build a trie for fast longest-match lookup&lt;/li&gt;
&lt;li&gt;Scan the input left to right&lt;/li&gt;
&lt;li&gt;Validate candidate patterns using local context rules&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rules are evaluated only against immediate neighbors.&lt;br&gt;
There is no backtracking, which keeps the algorithm predictable and fast.&lt;/p&gt;
&lt;h2&gt;
  
  
  Strict mode vs BD mode
&lt;/h2&gt;

&lt;p&gt;Strict mode is intended to behave as a clean Avro-style baseline.&lt;br&gt;
If you want exact behavior, use strict mode only.&lt;/p&gt;

&lt;p&gt;BD mode layers a small set of additional patterns on top of strict grammar.&lt;br&gt;
These patterns capture real-world Bangladeshi typing habits&lt;br&gt;
without polluting the base grammar.&lt;/p&gt;

&lt;p&gt;This separation keeps the engine usable for both compatibility&lt;br&gt;
and user-experience–oriented applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Custom grammar support
&lt;/h2&gt;

&lt;p&gt;The engine is fully grammar-driven.&lt;/p&gt;

&lt;p&gt;You can load a complete grammar JSON file to reach parity with the grammar you prefer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;avrophonetic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromGrammarFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"grammar.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;avrophonetic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avrophonetic&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithGrammar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ami"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the library suitable for search indexing, chat processing,&lt;br&gt;
form normalization, and NLP pipelines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Avro Phonetic keyboard: original idea and grammar concept&lt;/li&gt;
&lt;li&gt;PHP reference implementation: &lt;a href="https://github.com/imerfanahmed/avro-php" rel="noopener noreferrer"&gt;https://github.com/imerfanahmed/avro-php&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project is an independent Go implementation and is not affiliated with the original Avro project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;Transliteration is a small feature with outsized impact.&lt;/p&gt;

&lt;p&gt;If your product handles Bengali user input,&lt;br&gt;
doing this well is not optional anymore.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/mhshajib/avro-phonetic-go" rel="noopener noreferrer"&gt;https://github.com/mhshajib/avro-phonetic-go&lt;/a&gt;&lt;br&gt;
Documentation and examples are available in the README.&lt;/p&gt;

</description>
      <category>go</category>
      <category>bangla</category>
      <category>transliteration</category>
      <category>avro</category>
    </item>
    <item>
      <title>Generate Legacy .xls Files in Go Without LibreOffice — Introducing RetroXL</title>
      <dc:creator>Mehedi Hasan Sajib</dc:creator>
      <pubDate>Sun, 30 Nov 2025 23:59:19 +0000</pubDate>
      <link>https://dev.to/mhsajib/generate-legacy-xls-files-in-go-without-libreoffice-introducing-retroxl-2an0</link>
      <guid>https://dev.to/mhsajib/generate-legacy-xls-files-in-go-without-libreoffice-introducing-retroxl-2an0</guid>
      <description>&lt;h1&gt;
  
  
  Generate Legacy &lt;code&gt;.xls&lt;/code&gt; Files in Go Without LibreOffice — Introducing RetroXL
&lt;/h1&gt;

&lt;p&gt;Many banks, government portals, and older enterprise systems still require uploads in the legacy &lt;code&gt;.xls&lt;/code&gt; Excel format. Go makes it easy to generate modern &lt;code&gt;.xlsx&lt;/code&gt; files, but generating real &lt;code&gt;.xls&lt;/code&gt; content usually requires installing LibreOffice, Python scripts, COM automation, or external system binaries.&lt;/p&gt;

&lt;p&gt;This approach is slow, hard to deploy, and unsuitable for containers or microservice workflows.&lt;/p&gt;

&lt;p&gt;To solve this problem, I built &lt;strong&gt;RetroXL&lt;/strong&gt;, a pure-Go library that generates legacy-compatible &lt;code&gt;.xls&lt;/code&gt; files from &lt;code&gt;.xlsx&lt;/code&gt;, &lt;code&gt;.csv&lt;/code&gt;, &lt;code&gt;.tsv&lt;/code&gt;, or in-memory data structures.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/mhshajib/retroxl" rel="noopener noreferrer"&gt;https://github.com/mhshajib/retroxl&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Problem
&lt;/h2&gt;

&lt;p&gt;If you work with banking integrations, you may have faced this issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Some bank portal rejects &lt;code&gt;.xlsx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Some bank only accepts &lt;code&gt;.xls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The validation rules are strict&lt;/li&gt;
&lt;li&gt;The older systems cannot parse modern formats&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most Go libraries output &lt;code&gt;.xlsx&lt;/code&gt;. Meanwhile, generating &lt;code&gt;.xls&lt;/code&gt; typically requires tools that are heavy, slow, and not ideal for production deployments.&lt;/p&gt;

&lt;p&gt;RetroXL addresses this directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  What RetroXL Does
&lt;/h2&gt;

&lt;p&gt;RetroXL generates &lt;code&gt;.xls&lt;/code&gt; files using the SpreadsheetML 2003 (XML) format accepted by Excel as a valid &lt;code&gt;.xls&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Key characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure Go implementation&lt;/li&gt;
&lt;li&gt;Zero external dependencies or binaries&lt;/li&gt;
&lt;li&gt;Converts &lt;code&gt;.xlsx&lt;/code&gt; to &lt;code&gt;.xls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Converts &lt;code&gt;.csv&lt;/code&gt; and &lt;code&gt;.tsv&lt;/code&gt; to &lt;code&gt;.xls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Builds &lt;code&gt;.xls&lt;/code&gt; from in-memory slices or tables&lt;/li&gt;
&lt;li&gt;Outputs to file, bytes, or any &lt;code&gt;io.Writer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Works over HTTP, gRPC, S3, etc.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/mhshajib/retroxl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example 1: Convert &lt;code&gt;.xlsx&lt;/code&gt; to &lt;code&gt;.xls&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/mhshajib/retroxl"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConvertXLSXToXLSFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.xlsx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"output.xls"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"convert failed: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example 2: Generate &lt;code&gt;.xls&lt;/code&gt; from a slice of structs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/mhshajib/retroxl"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Payment&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AccountNo&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Amount&lt;/span&gt;    &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="n"&gt;Reference&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1200.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invoice-001"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"9876543210"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;300.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s"&gt;"Invoice-002"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"AccountNo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Amount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Reference"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountNo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reference&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromRows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BankUpload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteXLSFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bank_upload.xls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sheet&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example 2: Generate &lt;code&gt;.xls&lt;/code&gt; from a slice without structs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/mhshajib/retroxl"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"AccountNo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Amount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Reference"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1200.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invoice-001"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"9876543210"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;300.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="s"&gt;"Invoice-002"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromRows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BankUpload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteXLSFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bank_upload.xls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sheet&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example 3: Stream &lt;code&gt;.xls&lt;/code&gt; over HTTP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"AccountNo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Amount"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[][]&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="s"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="n"&gt;sheet&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromRows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/vnd.ms-excel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Disposition"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;`attachment; filename="demo.xls"`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteXLSWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;retroxl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sheet&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sheet&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When To Use RetroXL
&lt;/h2&gt;

&lt;p&gt;Use RetroXL when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bank or government portal only accepts &lt;code&gt;.xls&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Your Go app generates &lt;code&gt;.xlsx&lt;/code&gt; or &lt;code&gt;.csv&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You want a container-friendly, dependency-free solution&lt;/li&gt;
&lt;li&gt;You need direct streaming over HTTP, gRPC, or cloud storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid RetroXL if you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex styling&lt;/li&gt;
&lt;li&gt;Formulas or pivot tables&lt;/li&gt;
&lt;li&gt;BIFF8 binary (.xls) output&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;RetroXL provides a clean, dependency-free way to generate legacy &lt;code&gt;.xls&lt;/code&gt; files directly from Go. If your workflows involve banking portals, finance systems, or older enterprise applications, RetroXL removes the complexity of external conversion tools.&lt;/p&gt;

&lt;p&gt;Repository:&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/mhshajib/retroxl" rel="noopener noreferrer"&gt;https://github.com/mhshajib/retroxl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback and contributions are welcome.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>go</category>
      <category>opensource</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
