I Am LAZY. And That’s Why I Automated 80% of My Reporting Workflow.
Every Monday, same routine: export from Sprinklr, clean the data, map the columns, update the Google Sheet, fix whatever broke. Costing me…
I Am LAZY. And That’s Why I Automated 80% of My Reporting Workflow.
Every Monday, same routine: export from Sprinklr, clean the data, map the columns, update the Google Sheet, fix whatever broke. Costing me 45 minutes. If something goes wrong, maybe a mismapped column, a duplicate post slipping through, a formula row getting overwritten, double the time investment
As a Social Media Analyst, I should be spending that time on analysis. Not on being a human copy-paste machine.
So I automated it.
The Problem
The workflow had three major pain points.
Raw exports are messy. Column names don’t always match the master sheet. Percentage fields are stored as decimals. Dates come in formats that the Sheet doesn’t expect. Cleaning this manually every single week is exactly the kind of work that shouldn’t require a human.
Updating metrics for existing posts was even worse. Every fortnight, I had to refresh all the engagement metrics for every asset from the current year. That meant matching hundreds of rows between two files using lookup formulae, praying nothing mismatched, and then manually verifying the output.
And the most frustrating part: almost all of this was operational overhead. Time that should have gone into insights and strategy was going into maintaining a spreadsheet.
If a system could handle all of this, which can be faster, more accurate, and without getting tired, then why not build and implement it?
The Solution
I built a local automation tool using Python, Streamlit, the Google Sheets API, and OpenPyXL. The architecture is straightforward:
Sprinklr Export (.xlsx)
↓
Transformation Engine
↓
Validation Layer
↓
Google Sheets Sync
The idea was simple: download the raw dump from Sprinklr, drop it into the app → Preview → Review → Watch the system write data into Google Sheet.
Designing the Transformation Engine
The core of the project is the transformation engine. This is the part that tells the machine exactly what to do with a raw Sprinklr file.
The first job is column mapping. Sprinklr has its own naming conventions. the GSheet has different ones. The engine translates between them:
SPRINKLR_TO_MASTER = {
"Published Date": "Date",
"PublishedTime": "Time",
"Campaign Name": "Campaign Name",
"Permalink": "Permalink",
"IG Post Reach": "Reach",
"IG Post Views": "Views",
"IG Likes": "Likes",
}
Critically, this mapping lives in settings.json and not hardcoded in Python. If any of the files need column renaming, I update the config file. I don't touch the code.
The second job is handling business-specific logic. Reels have metrics like Skip Rate and Average Watch Time. Static posts don’t. Hence, the engine detects reel vs. non-reel from the permalink and sets those fields to NA automatically:
if source_header in non_reel_overrides and not is_reel_permalink(
sprinklr_row.get("Permalink")
):
return "NA"
The third job is duplicate detection. Each post has a unique Instagram permalink. Before inserting anything, the engine checks whether that permalink already exists in the Sheet:
if permalink in existing:
duplicate_rows_skipped += 1
continue
Two Workflows, One Tool
Not every update is the same. There are two completely different scenarios this tool needs to handle.
Weekly Append: Every week, new assets need to be added to the Sheet. The system reads the Sprinklr dump, checks every permalink against what’s already in the Sheet, and appends only the rows that don’t exist yet. Duplicates are skipped, not errored.
Periodical Update: Every fortnight, engagement metrics for all existing posts need to be refreshed. This mode matches each row by permalink and updates only the metric columns . It doesn’t touch anything else, and it doesn’t add new rows.
Both modes share the same underlying engine. What changes is what happens at the end: append vs. update.

Key Design Decisions
Permalink as the unique key: Every Instagram post has a unique URL. It’s more reliable than post caption, as it can be edited after publishing.
Config-driven mappings: All source-to-master column mappings, update columns, and special-case rules live in settings.json. Future changes happen in config, not in code.
Dry-run first, always: The biggest risk in a tool like this is when something breaks, and bad writes happen without you knowing exactly what changed. The preview step shows a full row-level audit before anything touches the Sheet

Every single row in the Sprinklr dump is accounted for. Nothing disappears silently.
The Result
What used to be a ~30–40 minute task that happens 5–6 times a month, now takes about 3–5 minutes: download the export, drop it into the app, preview, confirm.
The time saving is real. But what I didn’t expect was how much the audit trail would change the way I work. I used to finish a manual update and then spend a few minutes eyeballing the Sheet, hoping nothing looked off. Now I have a log that tells me exactly what happened to every row.
The broader lesson: the most valuable thing about automating a repetitive process isn’t always the time saved. Its about investing the saved time into high-quality mid-work naps ✨✨
The code is on GitHub: [link]
If you work with Sprinklr, Google Sheets, or social media data, I’m on LinkedIn: [link]
메타데이터
- post_id
- 32f6807e248d
- slug
- i-am-lazy-and-thats-why-i-automated-80-of-my-reporting-workflow-32f6807e248d
- url
- https://medium.com/@ommk24/i-am-lazy-and-thats-why-i-automated-80-of-my-reporting-workflow-32f6807e248d
- canonical_url
- https://medium.com/@ommk24/i-am-lazy-and-thats-why-i-automated-80-of-my-reporting-workflow-32f6807e248d
- author_url
- https://medium.com/@ommk24
- status
- ok
- fetched_at
- 2026-07-11 15:31:54