@eykalman/data-importer
v1.0.0
Published
Import data to Dataverse from CSV or XLSX
Maintainers
Readme
Data Importer
A Power Platform ToolBox (PPTB) tool for importing data into Microsoft Dataverse from CSV or Excel (.xlsx / .xls) files.
It maps spreadsheet columns to Dataverse fields, handles every column data type (including choices, lookups and owner), and supports batched create / update / upsert operations with progress reporting, cancellation, and saveable mapping configurations.
Built with React, TypeScript, Vite, Fluent UI v9, and SheetJS.
By The CRM Ninja.
Table of contents
- Features
- Quick start
- Using the tool
- How each column type is handled
- Working with choice / option set columns
- Working with lookup columns
- Create, update and upsert
- Saving and loading configurations
- Sample data
- Development
- Project structure
- Security & permissions
- License
Features
- CSV & XLSX import — pick a file and worksheet; headers are detected automatically.
- Searchable table list — choose the target Dataverse table from a dropdown of the environment's tables.
- Field-first mapping — the mapping grid lists Dataverse fields and lets you pick the source column for each, with a search box and a "Mapped only" filter. Fields are auto-matched to source columns by logical name and display name.
- Full data-type support — text, numbers, currency, dates, GUIDs, Yes/No, choices, status/status reason, multi-select, lookups, owner, and a Created On override.
- Choice value mapping — confirm how each distinct spreadsheet value maps to a Dataverse option (local or global option sets), with per-field green/red status badges and a Refresh Values button. Individual values can be ignored.
- Lookup resolution — resolve by GUID or by a column value (queried in Dataverse). Polymorphic lookups let you pick the target table, and an optional filter narrows candidates (with a dropdown of options when the filter column is itself a choice).
- Create / Update / Upsert — match existing records by one or more columns (no alternate key required in Dataverse).
- Batched, fast writes — uses
createMultiple/updateMultiplewith a configurable batch size, and resolves lookups/matches in parallel for speed. - Stop Import — cancel a running import between batches.
- Save / Load configuration — export your table, settings and mappings to an XML file and reload them later.
- Progress & error reporting — live progress with a per-row failure report; the import continues past failures.
- Light & dark themes — follows the PPTB theme and updates live when it changes.
Quick start
- Open Data Uploader/Importer in Power Platform ToolBox with an active Dataverse connection.
- Select File → choose a
.csv,.xlsx, or.xlsfile. - Target Table → select the Dataverse table; its fields load automatically.
- Column Mapping → confirm/adjust which source column feeds each Dataverse field.
- Import Settings → choose Create / Update / Upsert (add match columns for update/upsert).
- Import → run it and watch progress; review any failed rows in the Event Log.
Using the tool
The left column contains the setup steps; the right column is the column mapping; the preview and event log run full width underneath.
1. Select a file
Click Choose file… and pick a .csv, .xlsx, or .xls file. If the workbook has multiple worksheets, choose the one to import from the Worksheet dropdown. The first row is treated as the header row. Selecting a new file resets all downstream sections.
2. Choose the target table
Pick the destination table from the Table dropdown (shown as Display Name (logicalname)). The tool loads the table's fields and metadata, then auto-maps any source columns whose name matches a field's logical name or display name.
3. Configuration (save / load)
- Save — writes the current table, import settings and all mappings to an XML file of your choosing.
- Load — opens a saved XML file and re-applies the table, settings and mappings (re-loading option sets while preserving your saved value maps).
4. Import settings
- Operation — Create, Update, or Upsert.
- Match columns (Update/Upsert only) — one or more column → field pairs used to find existing records by querying Dataverse (no Dataverse alternate key required).
- Batch size — how many records are sent per
createMultiple/updateMultiplecall.
5. Column mapping
The mapping grid lists every writable Dataverse field. For each field:
- Pick the Source Column that feeds it (or leave it Not mapped).
- Type-specific settings appear for lookups and choices (see below).
- Use the Search box to find a field quickly, or Mapped only to hide unmapped fields.
Fields are auto-mapped where the source header matches the field's logical name or display name — you can override any of these.
6. Preview
Shows the first few rows of the selected worksheet. The table scrolls horizontally and wraps long values so wide files don't distort the layout.
7. Run the import
Click Import N Row(s). A progress bar shows rows processed with created / updated / failed counts. Click Stop Import to cancel after the current batch. When finished, any failed rows are listed with their reasons, and a summary is written to the Event Log.
How each column type is handled
| Dataverse type | Behaviour |
|----------------|-----------|
| Single line of text / Multiple lines | Set as text; values longer than the field's max length fail the row |
| Whole number / BigInt | Parsed as an integer |
| Decimal / Float / Currency | Parsed as a number |
| Yes/No (Boolean) | true/false, 1/0, yes/no, or a confirmed value mapping |
| Date and Time | Parsed as UTC and sent as ISO (date-only fields send the date part) |
| Unique identifier (GUID) | Set as a GUID string |
| Choice / Status / Status Reason | Mapped to an option value (see below) |
| Choices (multi-select) | Cell split on commas/semicolons, each part mapped to an option value |
| Lookup / Customer / Owner | Resolved to a record and bound via @odata.bind (see below) |
| Created On (override) | Writes overriddencreatedon on create |
| Calculated / rollup / virtual | Read-only — not offered for mapping |
Empty cells are skipped (the field is left at its default / existing value).
Working with choice / option set columns
When a mapped field is a choice, status, status reason, or Yes/No column, a Map values button appears with a status badge:
- 🟢 All values mapped — every distinct spreadsheet value in that column is mapped (or ignored).
- 🔴 Unmapped values — one or more values still need attention (those rows would fail).
Click Map values to expand the mapper. It shows each distinct spreadsheet value with a dropdown of the field's Dataverse options (label and numeric value). The tool automatically maps values that match an option's number or label; you can change any mapping, or choose Ignore this value to leave the field unset for rows with that value.
- Refresh Values re-queries the options directly from Dataverse.
- Both local and shared/global option sets are supported.
Working with lookup columns
For a mapped lookup field, choose:
- Table — for polymorphic lookups (e.g. Customer, Owner, or custom multi-table lookups), pick which table the value refers to. Single-target lookups select automatically.
- Resolve by:
- GUID — the source value is the target record's ID.
- Key / column value — pick a Match column on the target table; the tool queries Dataverse to find the matching record's ID. If no record or more than one matches, the row fails.
- Filter (optional toggle) — narrow the candidate records with an extra condition: pick a Filter column and a Filter value. If the filter column is itself a choice, the value is chosen from a dropdown of options. This is separate from the match column and is useful when a key value isn't unique on its own (e.g. only match active records).
Create, update and upsert
- Create — every row becomes a new record.
- Update — each row updates the existing record found via the match column(s); rows with no match fail.
- Upsert — updates a matched record, or creates a new one when there's no match.
Matching queries Dataverse on your chosen column(s), so no Dataverse alternate key is required. If more than one record matches, the row fails as ambiguous. Writes are sent in batches (createMultiple / updateMultiple); if a batch fails, its rows are retried individually so failures are isolated and reported per row.
Saving and loading configurations
Use Configuration → Save to export everything needed to reproduce an import — the target table, import settings (operation, match columns, batch size), and every column mapping (including value maps and lookup settings) — as an XML file on your machine. Use Load to pick that file again later and re-apply it. This makes recurring imports repeatable and shareable.
Sample data
The sample-data/ folder contains example account files (accounts-sample.csv and accounts-sample.xlsx) that exercise text, number, currency, Yes/No, choice, and date columns — handy for a first test run against a sandbox environment.
Development
Prerequisites: Node.js 18+ and npm.
npm install # install dependencies
npm run build # type-check and build to dist/
npm run watch # rebuild on change during development
npm run validate # validate the manifest against PPTB rules
npm pack # produce a distributable .tgzLoad into Power Platform ToolBox
- In PPTB, open Settings and enable Show Debug Menu.
- Go to Debug → Load Local Tool → Browse and select this project's root folder.
- Click Load Tool. After each rebuild, close and reopen the tool tab to pick up changes.
Project structure
src/
App.tsx FluentProvider, theme, logo, layout
main.tsx React entry point
styles.ts Shared Fluent (griffel) styles
assets/ Logo image
hooks/useToolboxAPI.ts Connection, events, theme, and event-log hooks
components/ Fluent UI components (upload, mapping, settings, choice mapper, log)
lib/ Import engine:
metadata.ts Tables, entity context, columns, option sets
coerce.ts Cell value coercion per data type
lookup.ts Lookup resolution (+ filter)
matching.ts Existing-record matching
importer.ts Create/update/upsert orchestration + batching + cancel
config.ts Save/load configuration (XML)
excel.ts CSV/XLSX parsing (SheetJS)
public/icons/ Theme-aware tool icon
sample-data/ Example account CSV/XLSXSecurity & permissions
- All Dataverse access goes through the host
dataverseAPI(no direct network calls from the tool), and SheetJS is bundled locally, so no CSP exceptions are required. - Uses the patched SheetJS CDN release to avoid known vulnerabilities in the public npm
xlsxpackage.
License
MIT
