Skip to main content
L
Loopaloo
Buy Us a Coffee
All ToolsImage ProcessingAudio ProcessingVideo ProcessingDocument & TextPDF ToolsCSV & Data AnalysisConverters & EncodersWeb ToolsMath & ScienceGames
Guides & BlogAboutContact
Buy Us a Coffee
L
Loopaloo

Free online tools for developers, designers, and content creators. Your files are processed in your browser and are never uploaded - no accounts required. A few network utilities (like What's My IP and Currency Converter) call public APIs to do their job and say so on their pages.

support@loopaloo.com

Tool Categories

  • Image Tools
  • Audio Tools
  • Video Tools
  • Document & Text
  • PDF Tools
  • CSV & Data
  • Converters
  • Web Tools
  • Math & Science
  • Games

Company

  • About Us
  • Contact
  • Blog
  • FAQ

Legal

  • Privacy Policy
  • Terms of Service
  • Disclaimer

Support

Buy Us a Coffee

© 2026 Loopaloo. All rights reserved. Built with privacy in mind.

Privacy|Terms|Disclaimer
  1. Home
  2. CSV & Data Analysis
  3. CSV Data Transformer
Add to favorites

CSV Data Transformer

Chain 34 cell transformations, each stating its own rule, with anything it could not do reported rather than passed through unchanged

Rows never leave your deviceMore csv & data analysisJump to full guide

Initializing in your browser…

You might also like

CSV to JSON Converter

Convert both ways, converting a type only when it reads back the same, and naming every value that cannot

Image Format Converter

Convert images between PNG, JPG, WebP, AVIF, BMP formats. Features quality control, transparency support, and batch conversion for efficient workflow.

Audio Format Converter

Convert between MP3, WAV, OGG, AAC, M4A and FLAC with a bitrate, sample rate, channel count and bit depth that all reach the encoder, and a panel that reports what was actually written.

A sample run

Two rows through a five step pipeline: trim and title-case a name, strip a price down to a number, reformat a date, and turn a column into percentages. One row is clean and the other holds 12abc where a price should be and 2025-02-29 where a date should be.

The file, and five steps

name,price,joined,pct
"  ALICE brown  ","$1,299.99",2024-01-15,50%
bob SMITH,12abc,2025-02-29,0.25

1 Trim · 2 Title Case · 3 Number only · 4 Reformat a date (DD MMM YYYY) · 5 To percentage
What CSV Data Transformer produces

Result

name,price,joined,pct
Alice Brown,1299.99,15 Jan 2024,50.0%
Bob Smith,12abc,2025-02-29,25.0%

7 of 10 cells visited changed. 2 could not be transformed:
  step 3, row 2, "12abc" mixes digits with other characters
  step 4, row 2, "2025-02-29" is not a date on the calendar

The two rows that did not change are the point. The previous version read 12abc as 12 and wrote 12.00, because parseFloat reads a prefix and stops; and it read 2025-02-29 as 28 February, because new Date accepts an impossible date and moves it. Both are silent, and both put a number into your file that was never in it. Here each is left as it was and reported with the reason. Two of the three that did change were also wrong before: 2024-01-15 shifted to 14 January for anyone whose clock is behind UTC, because new Date reads an ISO date as UTC midnight and the tool then asked for the LOCAL day; and 50% became 5000.0%, because To Percentage multiplied by 100 whether the value was a fraction or not.

Transformations That Say Exactly What They Do

Stack cell transformations on a column and watch them run: change case, trim, find and replace, extract, reformat a number or a date, mask, or build a slug. Every operation states its own rule, and anything it cannot do to a value is reported with the reason rather than passed through unchanged.

How to use

  1. 1Upload your CSV, or load the sample
  2. 2Pick an operation; each one says exactly what it does under its name
  3. 3Choose the column and set the parameters
  4. 4Stack more steps: they run top to bottom, each on what the last one left
  5. 5Read the preview and any report of cells that could not be transformed, then apply and download

Key features

  • Thirty four operations, each carrying the rule it enforces and a worked example that is checked against what it produces
  • A live preview: the same run the download uses, so a step failing on every row is visible before you commit
  • Cells that could not be transformed reported with the reason, rather than passed through unchanged
  • Characters counted as a reader sees them, so an emoji, a flag and an accented letter each count as one
  • Unicode-aware case, letters and slugs, so an accented or CJK value is not destroyed
  • Numbers read through a stated decimal grammar: a currency symbol, grouped thousands and accounting parentheses come off, and 12abc is refused rather than read as 12
  • Number separators as a setting rather than the reader's browser locale, with the file's convention and the one to write kept apart
  • Rounding half away from zero, so -0.5 is -1 rather than the -0 Math.round gives
  • Percentages that read a percent sign, so a column already written as 50% does not become 5000%
  • Dates read against the calendar and written from their calendar fields, with no Date object and therefore no timezone anywhere
  • An ambiguous date like 03/04 settled by a stated choice, and an impossible one refused
  • Rows too short for a step's column counted rather than skipped in silence
  • The header row transformed when you ask, and left alone when you do not
  • RFC 4180 output: CRLF records, minimum quoting, and a UTF-8 byte order mark
  • Three steps over 100,000 rows in about 280 milliseconds

How it works

Scored the way a validator is: a corpus of 100 (value, operation) pairs with a known answer, each answer cross-checked first against Python's own deciders (`unicodedata` for what a letter is, `datetime.date` for the calendar, `decimal.Decimal` for rounding). **Baseline 48 of 89 of the cases the shipped operations could express; after, 100 of 100 in the module and 100 of 100 through the browser**, with 556 module assertions, 174 browser assertions and 240 corpus assertions. The faults fell into four groups and every one of them is a fact about text or numbers rather than about this tool.

**Text was treated as UTF-16 code units.** Reverse was `value.split('').reverse().join('')`, which turns an emoji into two lone surrogates and moves a combining accent onto the wrong letter; Substring and Mask cut a surrogate pair in half. Everything that counts or reorders characters now counts user-perceived characters, so a flag, an emoji and an accented letter are each one.

**`\w` and `[a-zA-Z]` are ASCII.** Title Case matched a word starting at the first ASCII word character, so `émile dupont` came out as `éMile Dupont`; it also treated an apostrophe and a hyphen as part of a word, giving `O'brien` and `Mary-jane`. Extract Letters reduced `Café` to `Caf` and removed `東京` entirely. The slug builder turned `Café Münster` into `caf-mnster`. Every character class is a Unicode property escape now, and the slug can fold accents to their base letters or keep them.

**Numbers went through `parseFloat(value.replace(/,/g, ''))`.** That reads a PREFIX and stops, so `12abc` formatted as `12.00` and a hexadecimal product code `0x1F` became `0.00`; and stripping every comma turned the German `1,5` into 15. Values go through a stated decimal grammar now, and one the tool cannot read is reported rather than quietly changed. The formatting used `toLocaleString(undefined, ...)`, which takes the reader's own locale: the same file gave `1,234.50` in London and `1.234,50` in Berlin, and only one of those can go into a comma-delimited CSV unquoted. The separators are a setting, with the file's own convention and the one to write kept apart so a file can be converted between them. And To Percentage multiplied by 100 unconditionally, so a column already written as `50%` came out as `5000.0%`; a percent sign is now read and the direction is a choice.

**Dates went through `new Date(value)`.** ECMA-262 makes `new Date('2023-01-15')` UTC midnight and `new Date('01/20/2023')` local midnight, so reading the local fields back shifts an ISO date by a day for most of the world. Measured in the browser during the pass, in America/Toronto: `new Date('2024-01-15')` has local fields 2024-01-14. It also accepted `2023-02-30` and moved it to 1 March, and `2025-02-29` and moved it to 28 February. Dates are read against the calendar now and written from their calendar fields with no `Date` object anywhere, an ambiguous `03/04` is a stated choice rather than a guess, and an impossible date is refused and reported.

Two smaller ones. Find and Replace was `value.split(find).join(replace)` and `''.split('')` splits into characters, so leaving the Find box empty inserted the replacement between every character of every cell. And a row too short to have the target column was skipped in silence; those are counted and shown.

The preview is now the live run rather than something computed only when Apply is pressed, so a step that fails on every row is visible before you commit it. Three operations were added along the way (sentence case, collapse spaces, the email local part, normalise Unicode and blank out a marker), the header row can be transformed when you ask, and the download goes through the RFC 4180 writer with a UTF-8 byte order mark. A single-column CSV loads, where it was refused before.

Where this fits a data pipeline

  • Cleaning a contact export

    Trim and title-case the names, lower-case the addresses, and reduce the phone numbers to digits, in one pipeline that runs top to bottom.

  • Making a price column arithmetic-ready

    Number only strips the currency symbol, the grouped thousands and the accounting parentheses, and tells you which cells were not numbers at all rather than turning them into zeros.

  • Normalising dates from two systems

    Reformat a date reads ISO and slash-separated forms alike and writes one form, with 03/04 settled by your choice rather than by a guess, and never shifted by a timezone.

  • Masking before you share

    Mask hides everything but the last few characters. A value short enough that nothing would be hidden is hidden entirely, rather than being returned in the clear as it used to be.

Frequently asked questions

Why did a value come back unchanged?

Because the operation could not be carried out on it, and the panel above the preview says which cells and why. A number operation on a cell that is not a number, a date operation on 2025-02-29, or a split asking for a part that does not exist are all reported. The previous version returned the value unchanged in silence, so a step that failed on every row looked exactly like one that had nothing to do.

My dates moved by a day. Why not here?

Because nothing here constructs a Date. new Date("2024-01-15") is UTC midnight and new Date("01/20/2024") is local midnight, so reading the day back out of the first shifts it for most of the world. Measured in the browser during this pass, in Toronto: new Date("2024-01-15") has local fields 2024-01-14. Dates are read against the calendar and written from their year, month and day.

What happens to 03/04/2025?

It has two readings and you choose which. A value like 31/12/2025 has only one, and that one is used whatever the setting says.

Why is my number formatted with the wrong separators?

Set them. Two settings are kept apart: the convention your file uses, so 1,5 is read as one and a half or as fifteen as you say, and the convention to write, so a file can be converted between them. Neither comes from the reader's browser, which is where the previous version got them, so the same file gave a different answer to different people.

Does To Percentage multiply by 100?

Only when the value is a fraction, which is a choice on the operation. A cell already written as 50% is read as one half and comes back as 50%, whichever way the choice is set. The previous version multiplied unconditionally and turned 50% into 5000.0%.

Can I transform the header row?

Yes, with a toggle. It is off by default, because a step meant for the data usually makes a mess of the names. For renaming under a convention, the CSV Column Renamer is the tool.

Does an emoji survive Reverse or Mask?

Yes. Characters are counted as a reader sees them, so an emoji, a flag and a letter with a combining accent are each one character. Splitting a string into UTF-16 code units, which is what the previous version did, turned an emoji into two halves that render as replacement characters.

Private by design

Rows and columns are parsed and transformed in memory in your browser. No record ever reaches a server.