<?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: Wei Li</title>
    <description>The latest articles on DEV Community by Wei Li (@weilidev2026).</description>
    <link>https://dev.to/weilidev2026</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4142165%2Febfbf8b6-7e5d-451e-a754-3198f2abfedb.png</url>
      <title>DEV Community: Wei Li</title>
      <link>https://dev.to/weilidev2026</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/weilidev2026"/>
    <language>en</language>
    <item>
      <title>The 4 Excel jobs I refuse to do by hand anymore (so I automated them in Python)</title>
      <dc:creator>Wei Li</dc:creator>
      <pubDate>Fri, 25 Sep 2026 03:59:45 +0000</pubDate>
      <link>https://dev.to/weilidev2026/the-4-excel-jobs-i-refuse-to-do-by-hand-anymore-so-i-automated-them-in-python-4poh</link>
      <guid>https://dev.to/weilidev2026/the-4-excel-jobs-i-refuse-to-do-by-hand-anymore-so-i-automated-them-in-python-4poh</guid>
      <description>&lt;p&gt;Excel work has a way of eating entire afternoons: twelve monthly workbooks to merge, a sheet per month to split back out, formulas that break the moment the file touches pandas or a BI tool. These four command-line tools (openpyxl is the only dependency) do the boring versions of those jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Summarize a workbook before opening it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python xlsx_summary.py report.xlsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prints rows, columns and a header preview per sheet. For a folder of workbooks, it's the fastest "what am I even looking at" pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Merge monthly workbooks — with a header contract
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;xlsx_merge.py&lt;/code&gt; refuses files whose columns don't match (silently stacked mis-aligned exports are how data goes wrong), tolerates trailing empty header cells, and can tag every row with its source file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python xlsx_merge.py year.xlsx jan.xlsx feb.xlsx mar.xlsx &lt;span class="nt"&gt;--add-source&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. One file per sheet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python xlsx_split_sheets.py big.xlsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each sheet becomes its own workbook — handy when downstream tools want single sheets.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Flatten formulas to values
&lt;/h2&gt;

&lt;p&gt;The classic "why is this cell empty in pandas" problem: formulas have no cached value until Excel recalculates. &lt;code&gt;xlsx_values.py&lt;/code&gt; writes a formula-free copy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python xlsx_values.py report.xlsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The take
&lt;/h2&gt;

&lt;p&gt;The tools are tiny on purpose: each maps to one flag, one transformation, and always prints what it changed. If a script's output can't be audited in five seconds, it's not automation — it's a liability.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What's next:&lt;/strong&gt; I'm bundling these (plus the CSV cleanup tools from &lt;a href="https://dev.to/weilidev2026/i-got-tired-of-cleaning-messy-csvs-by-hand-so-i-wrote-5-tiny-python-tools-13p3"&gt;my previous post&lt;/a&gt;) into downloadable toolkits with READMEs and a money-back guarantee. I'll link them here as soon as they're live — drop a comment if you want a ping.&lt;/p&gt;

&lt;p&gt;Questions about gnarly .xlsx edge cases? Ask in the comments.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>excel</category>
    </item>
    <item>
      <title>I got tired of cleaning messy CSVs by hand, so I wrote 5 tiny Python tools</title>
      <dc:creator>Wei Li</dc:creator>
      <pubDate>Fri, 25 Sep 2026 03:25:09 +0000</pubDate>
      <link>https://dev.to/weilidev2026/i-got-tired-of-cleaning-messy-csvs-by-hand-so-i-wrote-5-tiny-python-tools-13p3</link>
      <guid>https://dev.to/weilidev2026/i-got-tired-of-cleaning-messy-csvs-by-hand-so-i-wrote-5-tiny-python-tools-13p3</guid>
      <description>&lt;p&gt;Every data job I've ever touched starts the same way: someone hands me an export that's &lt;em&gt;almost&lt;/em&gt; usable. Duplicated rows. Columns named &lt;code&gt;"Order Date "&lt;/code&gt;. Numbers stored as text. I kept writing the same cleanup snippets over and over, so I turned them into five small command-line tools. They have zero dependencies (just Python 3.8+), each one does exactly one job, and every one of them prints a summary of what it changed so you can trust the output.&lt;/p&gt;

&lt;p&gt;Here's what each tool does and how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. csv_cleaner.py — the one you'll use the most
&lt;/h2&gt;

&lt;p&gt;Deduplicates rows, trims whitespace in every cell, normalizes headers (&lt;code&gt;Order Date&lt;/code&gt; → &lt;code&gt;order_date&lt;/code&gt;), and prints a report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python csv_cleaner.py messy.csv &lt;span class="nt"&gt;--dedupe&lt;/span&gt; &lt;span class="nt"&gt;--trim&lt;/span&gt; &lt;span class="nt"&gt;--headers&lt;/span&gt; &lt;span class="nt"&gt;--summary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cleaned file written -&amp;gt; messy_clean.csv
--- summary ---
           rows_in: 4
duplicates_removed: 1
empty_rows_dropped: 1
          rows_out: 2
          columns: 3 -&amp;gt; ['name', 'age', 'city']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. csv_splitter.py — when the file is too big to open
&lt;/h2&gt;

&lt;p&gt;Split by rows per chunk or by number of parts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python csv_splitter.py big.csv &lt;span class="nt"&gt;--rows&lt;/span&gt; 100000
python csv_splitter.py big.csv &lt;span class="nt"&gt;--parts&lt;/span&gt; 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. csv_merger.py — merge monthly exports without surprises
&lt;/h2&gt;

&lt;p&gt;Refuses to merge files with different headers (instead of silently mangling your data), skips stray repeated header lines, and can tag each row with its source file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python csv_merger.py year.csv jan.csv feb.csv mar.csv &lt;span class="nt"&gt;--add-source&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. csv_to_json.py — feed the cleaned data to an API
&lt;/h2&gt;

&lt;p&gt;Converts to a JSON array or JSON Lines, with smart type conversion ("30" → 30, "true" → true, "" → null):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python csv_to_json.py clean.csv clean.json
python csv_to_json.py clean.csv clean.jsonl &lt;span class="nt"&gt;--jsonl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. file_organizer.py — not just CSVs
&lt;/h2&gt;

&lt;p&gt;Sorts any folder (hello, Downloads) into subfolders by type, extension, or year-month — with a dry-run mode so you can see the plan before anything moves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python file_organizer.py ~/Downloads &lt;span class="nt"&gt;--by&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The patterns behind all five
&lt;/h2&gt;

&lt;p&gt;If you're writing your own version, the whole toolkit rests on three ideas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read with &lt;code&gt;utf-8-sig&lt;/code&gt; (kills the BOM Excel adds) and write with &lt;code&gt;newline=""&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Every flag maps to one obvious transformation — no magic.&lt;/li&gt;
&lt;li&gt;Always print what changed. Silent success is how data bugs survive.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;What's next:&lt;/strong&gt; I'm packaging these five tools (plus a README with more examples) into a small downloadable toolkit. Drop a comment if you'd find that useful — I'll link it here as soon as it's live.&lt;/p&gt;

&lt;p&gt;Questions or messy-data edge cases? Ask in the comments — I read everything.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
