Migrate from spreadsheets to EspoCRM

Replacing Excel or Google Sheets customer lists with EspoCRM is a bounded import job when the data is cleaned and ordered first. This page explains what maps cleanly, what does not, and what drives effort.

On this page

Migrate from spreadsheets to EspoCRM: what the move involves

If your accounts, contacts and opportunities live in scattered Excel or Google Sheets files, the move to EspoCRM means turning those files into one shared record that the whole team trusts. The work is mostly data preparation, field mapping and a controlled import, not software installation. Effort is driven by two things: how clean the spreadsheets are today, and how many entities you need to load, since accounts, contacts and opportunities each have their own columns, links and duplicate rules. The EspoCRM Import tool reads CSV files only, so every spreadsheet has to be exported and saved as UTF-8 CSV before anything else happens. It is found at Administration > Import and is run by administrators. The EspoCRM import documentation also warns that any user granted Import access through Roles should be treated as privileged, because that person can create or overwrite large volumes of records. Decide early who will run imports and who may be granted the permission, and record that decision as part of the plan.

DeployOpen works within this documented import path rather than around it. In practice that means agreeing the scope in writing before work starts: which spreadsheets and tabs are in scope, which EspoCRM entities they map to, who owns the business rules for duplicates and blank values, and what must be checked before go-live. Ask any partner, including us, to show how they will profile the source data, which exceptions they expect, and how each import batch will be reviewed and reverted if needed. Clean-up that is done in the spreadsheet before export is usually cheaper than correcting records after they are in the CRM.

Which spreadsheet columns map cleanly to EspoCRM and which need design

This table compares common spreadsheet structures against EspoCRM accounts, contacts, opportunities, teams and user assignments. Read each row as a decision: the column either maps directly, needs a custom field or fixed option list, or should stay out of the CRM. The main takeaway is that most of the effort sits in status values, owner names and multi-contact layouts, not in the basic name and address fields.

Sheet structureEspoCRM targetWhat to decide before importWhere it usually goes wrong
One row per customerAccountConfirm the account name is unique enough to act as the duplicate match fieldSubsidiaries and branches share a name and get merged on import
Several contacts stacked under one companyAccount plus multiple Contact recordsDecide whether each contact row links to its account by a company name or an account ID you addName-only matching creates duplicate accounts with slightly different spellings
Opportunity tab or separate sheetOpportunity linked to AccountMap the account key column so each opportunity points to exactly one accountOpportunities import without a parent account and appear orphaned in pipeline views
Dropdown status values such as Hot, Warm, Won, PendingEnum fields on Opportunity or LeadList every distinct value and map it to an existing option or add options in the Entity Manager firstValues that do not match an option are rejected or stored as text that breaks reports
Owner or rep names typed as textAssigned user and teamMatch each name to an active EspoCRM user and decide which team owns the recordFormer staff names have no user, so records are left unassigned or assigned to the importer
Notes or comments columnStream posts, or a custom text fieldDecide whether notes become history entries or a single long text field, and keep their dateLong free-text notes truncate or lose their original dates
Industry, region or segment columnsCustom field, or an existing field if one fitsAdd a custom field in the Entity Manager when no standard field fits, and fix its option listFree-text segments create near-duplicate values that split filters and reports
Renewal date, contract value, probabilityOpportunity date and amount fields, plus custom fields if neededConfirm the currency and decimal format, and whether probability is a number or a stageLocale formats such as day-first dates import as wrong months
Personal data columns not needed for selling or service (for example, national ID numbers, bank details, health notes)Not importedRemove them from the file and document why, which supports data minimization reviewsSensitive columns get copied into a broadly visible CRM and then need a cleanup project

Documented import paths and what each one is for

EspoCRM gives you one documented way to load spreadsheet data through the web interface, plus an API for later automation. The cards below cover what the CSV import tool does, who can use it, and where the risks sit, so you can decide how your migration runs before any file is touched.

CSV import at Administration > Import

The import tool reads CSV files and is opened from Administration > Import. It is the path most spreadsheet migrations use, because each file maps directly to one entity such as accounts, contacts or opportunities. Load one entity type at a time, and confirm the file encoding and column headers before the first real run. Test with a copy of a few hundred rows in a non-production instance first.

Create, update and update-only modes

The import tool offers three modes: Create Only, Create and Update, and Update Only. Create Only is the safest choice for a first load into an empty system. Create and Update fits a second pass that refreshes existing records, while Update Only should be used when you want to change records that already exist without adding new ones. Pick the mode per file and record the choice in your migration log.

Field mapping and duplicate matching

Field mapping connects each spreadsheet column to an EspoCRM field, and duplicate matching decides which existing records a row updates. Choose match fields that are stable and unique in your data, such as an external customer ID or a normalized email address, rather than a name that people spell differently. Review a sample of matches before running the full file, because a weak match key silently merges unrelated customers.

Idle execution through cron

Large files can run in idle mode, where the work is handled by the scheduled job runner rather than the browser session. This requires cron or a scheduled task to be configured on the server, so confirm it is running before you start a large import. Check the job status and error output after completion, and schedule imports outside working hours so the runner does not compete with users.

Access through Roles and privileged use

Import access can be granted to other users through Roles, not only to administrators. The documentation warns that anyone with Import access should be treated as privileged, because a single file can create, overwrite or bulk-change many records. Limit the permission to a small migration team, remove it after cutover, and review the role assignments in your security checklist.

REST API for later automation

The REST API is a route for scripted loads and recurring syncs once the initial migration is complete. Use dedicated API users with narrow role permissions rather than personal accounts. Before building anything on the API, confirm its request limits and endpoint behavior with the EspoCRM API documentation, because a script that works in a test instance can behave differently under production volume.

How to prepare UTF-8 CSV files so the import does not fail halfway

Most of the effort in a spreadsheet migration sits in preparing the files, not in running the import. EspoCRM's Import tool reads CSV files, so every file needs one encoding (UTF-8), one delimiter used consistently, and exactly one header row. Mixed encodings usually show up as garbled accented names or broken currency symbols after import, and a stray merged header row can shift every column by one. Check each file in a plain text editor before upload, and confirm that the delimiter your export tool produces matches what you choose in the import wizard. Spreadsheet exports often add a byte order mark or convert values such as long account numbers or ZIP codes into scientific notation, so inspect a sample of rows after export rather than trusting the first screen.

Clean the data before it reaches EspoCRM. Trim leading and trailing whitespace, since " Acme Ltd " and "Acme Ltd" will not match on duplicate detection. Normalize phone numbers to one format, ideally international notation, and store country values in one agreed form, such as ISO country codes, so that field mapping and any later dropdowns behave predictably. Resolve duplicate customer rows inside the spreadsheet before import, because the Import tool's duplicate matching on chosen fields is only as good as the keys you give it. Decide which row wins when two rows describe the same customer, and record that decision. Add a source ID column to every file that holds the original spreadsheet row or legacy key. This column lets you trace any EspoCRM record back to its source, reconcile counts after each run, and rerun a corrected file in Update Only mode without creating new records. Confirm the exact field names and any limits for your EspoCRM version in the import documentation, and test with a small sample file before loading the full dataset.

Migration sequence from inventory to decommissioning the spreadsheets

This sequence moves customer data out of spreadsheets and into EspoCRM in a controlled order, with a tested revert path, a parallel run and an archived copy of the sheets that remain available as reference.

  1. Inventory every sheet and its owner

    List each spreadsheet, shared drive folder and local file that holds customer, contact, account or pipeline data, and record who maintains it, who reads it and which reports or mail merges depend on it. Note which columns are actually used and where the same customer appears in several files. The output is a signed-off inventory that the sales, service and finance owners have reviewed, with each sheet marked as migrate, archive or discard. Confirm with each owner that nothing important lives only in a personal copy.

  2. Build the cleaning and mapping workbook

    Create a workbook that maps every source column to an EspoCRM field on accounts, contacts or opportunities, and lists the rules for cleaning values: trimming spaces, standardizing country and phone formats, merging duplicate accounts and resolving conflicting owners. Save each CSV as UTF-8 and check that dates and currency values follow the format your import will expect. The workbook is done when every column has a target or an explicit reason to drop it, and the business owners have approved the duplicate rules.

  3. Run a pilot import into a non-production instance

    Load a representative sample of accounts, then contacts linked to those accounts, then opportunities linked to accounts and contacts, into a non-production EspoCRM instance. Use the Import tool with field mapping and the duplicate matching fields you chose in the workbook. Review each batch for unmatched links, wrong field types and unexpected duplicates, then correct the workbook and repeat until the sample loads as expected. The output is a pilot log that records the rows loaded, rows rejected and the fix applied to each error.

  4. Test a revert of the pilot import

    Before any production load, use EspoCRM's revert function on the pilot import and confirm that the imported records are removed and that records created by users in the meantime are not affected. Check the results in the user interface and in the record counts for each entity. Also confirm that users with Import access are limited to the people you intend to trust, because the documentation treats them as privileged. The revert test is complete when the pilot data is gone, the counts match the pre-import state and the outcome is written into the cutover runbook.

  5. Import production data in dependency order

    Run the production import in three passes: accounts first, then contacts linked to their accounts, then opportunities linked to accounts and contacts. Each pass should use the duplicate rules and mapping that the pilot approved, and each file should be checked for links to records created in an earlier pass. Keep the import log for every run so that any pass can be reverted independently. The step is finished when record counts match the cleaned source files and a sample of records has been checked against the original sheets.

  6. Run the parallel period with sheets read-only

    Have the teams work in EspoCRM for all new activity while the original spreadsheets stay open for reference only, with edit rights removed or the files marked read-only. Track questions, missing fields and data that users discover is wrong, and fix them in EspoCRM rather than in the sheets. The period ends when the team reports no gaps that block daily work and the open issues list is closed or accepted by the business owners.

  7. Cut over and archive the spreadsheets

    Declare the cutover date, make a final import of any changes made in the sheets during the parallel period if they were not already captured, and then make the sheets read-only for everyone. Export a complete archived copy of each file to a controlled location with retention rules agreed by the data owner, and record where the copy is kept. Confirm that reports, mail merges and integrations that depended on the sheets have been replaced or retired.

  8. Decommission the sheets and keep the audit trail

    Remove the working spreadsheets from shared drives and personal folders according to the archive plan, and revoke any sharing links. Keep the cutover runbook, pilot log, production import logs and the archive index together so that any later question about where a record came from can be answered. The sequence is complete when the sheets are no longer used for customer data, the archive is verified as readable and the owners have signed off the decommissioning record.

Handling relations and duplicates during import

In a spreadsheet, a contact sits on the same row as its company, or carries a company name in a column. EspoCRM stores these as relationships between records, so the import has to resolve each text value in a child row to an existing account before the link can be made. The import order matters here: accounts must exist before contacts and opportunities refer to them. Confirm in the Import documentation and on your version exactly which field the importer uses to find the parent record, because the lookup behavior is the part most likely to differ from what you expect.

  • Pick one stable key: Use an account identifier that does not change, such as an ID from your old system or a unique account code, rather than a company name that people spell several ways.
  • Handle missing link values: Rows with an empty parent key will either import unlinked or fail, depending on the mapping you choose. Filter these rows into a separate file and decide whether each one needs a new account or a correction.
  • Watch for ambiguous matches: If two accounts share a name, a name-based lookup cannot know which one is meant. Resolve these in the source file before import.
  • Check opportunity ownership: Opportunities usually need an account link and an assigned user. Map the user column to valid EspoCRM usernames, not display names.
  • Spot-check relations after each run: Open a sample account and confirm its contacts and opportunities appear in the expected panels.

Before the full run, import a small batch of accounts and their contacts into a test instance and confirm every link resolves.

What drives the cost and duration of a spreadsheet migration

This table lists the factors that change the effort of moving spreadsheet data into EspoCRM, why each one matters and what to ask for in a written quote. Read it before comparing quotes, because a low number often reflects a smaller scope rather than a cheaper method.

DriverWhy it changes effortWhat to ask for in a quote
Number of sheets and entitiesEach sheet that maps to a separate entity adds a mapping, an import run and a validation pass. Merging sheets into fewer entities removes work but may change how records relate.A sheet-by-sheet inventory showing which entity each sheet maps to and the import order
Row counts and data qualityLarge files need cron-driven idle execution, and inconsistent names, phone formats or duplicate accounts add cleaning rounds before any import runs.A stated assumption on row counts per sheet and a list of cleaning steps the quote includes or excludes
Custom fields in the Entity ManagerColumns with no matching EspoCRM field require new fields, types and options to be created before import, which adds configuration and testing.A field map listing each spreadsheet column, its target field and whether the field is new
Layouts, teams and access to set up firstLayouts, teams and default assignment rules must exist before records arrive, or imported data appears in the wrong views for the wrong people.Confirmation of which layouts, teams and assignment rules are built and tested before the first import
User and role designImport access is a privileged permission in EspoCRM, so role design, user creation and the number of people allowed to import affect both setup time and control reviews.Role definitions, the named users who will run imports and who will hold import access
Owners who must validate recordsEach sales or service owner who checks their own accounts and opportunities adds review cycles, and disputes over ownership often extend timelines.The number of validation owners, the review method and who signs off each batch
Pilot and parallel runA pilot on one team's data and a parallel period with the spreadsheet still in use add test cycles, reconciliation work and a second round of corrections.Whether a pilot and parallel run are included, their scope and the exit criteria for cutover
Integration needsConnections to email, calendars or other systems add mapping, duplicate rules and testing, and may need official extensions or API users.A list of connected systems, the direction of data flow and the authentication method planned for each

What usually goes wrong with spreadsheet imports and how to prevent it

Most failed spreadsheet migrations are not caused by EspoCRM itself. They come from file preparation, re-runs, link errors and loose permissions on the Import tool. Each risk below has a preventive control you can put in place before the first production import.

Encoding errors that corrupt names

A file saved in a legacy encoding can turn accented names, currency symbols and punctuation into garbage characters that look valid on screen. Export your sheet as UTF-8 CSV and confirm the encoding before import. Run a test import of 20 to 50 rows and check names with diacritics, apostrophes and non-Latin scripts against the source sheet.

Duplicate accounts from re-runs

Running the same import twice in Create Only mode creates a second copy of every account. Choose a duplicate matching field such as an external customer ID or a normalized email domain, and use Create and Update mode for corrections. Review the count of created and updated records in the import log after every run.

Opportunities without a valid account

Opportunities imported before their accounts exist, or with account names that do not match exactly, load without a usable relation. Import accounts first, then contacts, then opportunities, and use the account ID column as the link key. Filter the opportunity list for records with an empty account after each stage.

Status values outside configured options

Spreadsheet stages such as "Closed Won!" or "Negotiation 2" rarely match the dropdown options configured in EspoCRM. Export the option list from the Entity Manager, map every spreadsheet value to an existing option, and reject rows with unmapped values before the file reaches production.

Over-broad Import access

The Import tool can create and change large numbers of records, so any user who holds it should be treated as privileged. Keep Import with administrators during the migration, grant it through a narrow role only to the named person running the load, and remove it afterward.

No tested revert path

A bad import that has not been rehearsed is difficult to undo under pressure. Take a database and file backup before every production run, test the revert function on a staging copy with the same file, and confirm that reverting a batch does not remove records created by daily users in the meantime.

Questions buyers ask before moving spreadsheets into EspoCRM

What does a spreadsheet to EspoCRM migration cost?

The cost depends on the size and state of the spreadsheets, the number of entities involved, and how much configuration EspoCRM needs before data arrives. Cost components are the discovery and field mapping work, the CSV preparation and cleansing, the import runs and checks, and any custom entities or layouts built first. Most of this is one-time. Recurring costs come from the EspoCRM hosting you choose and any official extensions you license. EspoCRM's open-source edition can be downloaded and self-hosted for free, according to the EspoCRM pricing page. Ask any quote to break out mapping, cleansing, import validation and post-go-live fixes separately, and to state what is excluded.

How long does moving spreadsheets into EspoCRM take?

Duration is driven by the number of sheets, how many records are duplicated or inconsistent, how many people must approve field decisions, and whether custom entities must exist before import. A single customer list with clean columns moves far faster than several linked sheets for accounts, contacts and opportunities that need relations set in order. Timing also depends on how quickly your data owners answer mapping questions. Ask for a plan with separate milestones for mapping sign-off, a trial import, full import and cleanup, so you can see which step controls the schedule.

What must our team provide before the import starts?

Your team must provide the spreadsheets, a named data owner for each entity, and written decisions on which columns map to which EspoCRM fields. Data owners need to confirm how duplicates are defined, which records are current, and who signs off the trial import. Sales and service leads should agree on the pipeline stages and opportunity fields that the CRM will use. Without these decisions, imported data will reflect old habits and need rework. Confirm the owners, sign-off dates and access to source files in the scope before work begins.

Can our internal team migrate spreadsheets to EspoCRM alone?

An internal team can do it alone if it has someone comfortable with CSV formatting, UTF-8 encoding, and the EspoCRM Import tool, plus an administrator who can run imports safely. The harder parts are usually relation ordering, duplicate matching and deciding what to do with inconsistent values, which need business input. Import access is itself privileged, so the team must decide who holds it. A partner can take on mapping, the trial runs and validation while your staff keep ownership of the data. Compare both options against the people, time and review capacity you have.

How do we revert a bad EspoCRM import?

EspoCRM's CSV import supports reverting imported records, so a bad run can be rolled back from the import results rather than edited by hand. Reverting is only a safe fallback if you check the first trial import carefully before running the full file, because records changed by later edits or other imports must be reviewed separately. Keep the original spreadsheets and a copy of the CSV files used for each run. Use Create Only for first loads and Update Only when refining existing records. Confirm the revert behavior on a test instance before relying on it in production.

Can EspoCRM hold personal data safely during migration?

EspoCRM can hold personal data safely only when the instance, access and transfer steps are controlled. Spreadsheets often sit in shared drives or personal inboxes, so the migration should remove those copies after the import is verified and restrict who can see the CSV files. The EspoCRM security documentation recommends enforcing a password policy, requiring two-factor authentication, avoiding admin accounts for daily work, and restricting access by IP address. Limit Import permissions to the people who need them. Ask your compliance and security leads to confirm retention and access rules before the data moves. DeployOpen prepares systems and evidence for compliance assessments but does not issue audit reports or certifications.

Which EspoCRM version and hosting should we plan for?

Plan the hosting and version before the import, because the supported PHP, database and web server combinations shape where the data lands. The EspoCRM server configuration documentation lists PHP 8.3 to 8.5, MySQL 8.0 or newer, MariaDB 10.6 or newer or PostgreSQL 15, on Apache, Nginx or IIS, with cron required for background jobs. Import of large files runs idle through cron, so a scheduled task must be working before you load data. Confirm the current release with the EspoCRM releases page and test on a staging instance first.

How DeployOpen works on this

DeployOpen plans, implements, tests, documents and supports self-hosted open-source platforms inside the client's own infrastructure. For a spreadsheet migration, that means we start from your actual sheets, agree the import order and matching rules in writing, and run every step in a test instance before production.

How we scope

  • We review your current sheets, column definitions, owners and duplicate patterns before naming any deliverable.
  • The written scope lists which entities, fields, relations and import modes are covered, and which sheets are excluded.
  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.

How we build

  • We prepare UTF-8 CSV files and mapping sheets, then import accounts, contacts and opportunities in dependency order.
  • Duplicate matching fields and Create Only, Create and Update, or Update Only modes are tested on sample data first.
  • Each test import is run against a non-production instance and checked record by record against the source sheets.

How we hand over

  • You receive the field mapping, import order, duplicate rules and reversal steps as written documentation.
  • Administrator and Import access are reviewed and limited to the people who need them, with the reasons recorded.
  • We walk your team through the first live imports and the revert procedure so they can run the next batch themselves.

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after the migration closes.
  • Support can cover recurring imports from new sheets, mapping changes and checks after EspoCRM upgrades.
  • Ask us to confirm which support tasks the retainer includes before you sign, so responsibilities are clear.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.