Package Information
Available Nodes
Documentation
n8n-nodes-excel-api
An n8n community node for accessing Excel files via API with concurrent safety protection. Perfect for scenarios where multiple users simultaneously access the same Excel file through n8n workflows.
π― Why This Node?
The Problem
When working with Excel files directly in n8n:
- β Multiple workflows accessing the same file cause file corruption
- β Concurrent writes lead to data overwrite and loss
- β No file locking mechanism
- β Difficult to handle simultaneous webhook form submissions
The Solution
This node works with Excel API Server to provide:
- β File Locking - Automatically queue concurrent requests
- β Data Integrity - No data loss or corruption
- β Multi-User Support - Perfect for multi-user HTML form submissions
- β Google Sheets-like Interface - Familiar operations in n8n
π¦ Installation
Method 1: npm (Recommended)
npm install n8n-nodes-excel-api
Method 2: Manual Installation
# 1. Clone repository
git clone https://gitlab.com/hueyanchen-group/n8n-nodes-excel-api.git
cd n8n-nodes-excel-api
# 2. Install dependencies
npm install
# 3. Build
npm run build
# 4. Link to n8n
npm link
cd ~/.n8n
npm link n8n-nodes-excel-api
# 5. Restart n8n
n8n start
Method 3: Community Package (After Publication)
In n8n:
- Go to Settings β Community Nodes
- Click Install
- Enter:
n8n-nodes-excel-api - Click Install
π Prerequisites
You must run Excel API Server first!
Install and start Excel API Server:
# Quick start with Docker
docker run -d \
-p 8000:8000 \
-v $(pwd)/data:/app/data \
-e API_TOKEN=your-secret-token \
yourusername/excel-api-server
See Excel API Server Documentation for details.
π§ Configuration
1. Set Up Credentials
In n8n:
- Go to Credentials β New
- Search for "Excel API"
- Fill in:
- API URL:
http://localhost:8000(Your API server address) - API Token:
your-secret-token(From Excel API Server)
- API URL:
- Click Save
2. Add Node to Workflow
- Create or open a workflow
- Click Add Node
- Search for "Excel API"
- Select the node
- Choose your credential
- Configure operation
π Operations
1. Append
Add a new row to the end of the sheet.
Two Modes:
Object Mode - Recommended
Map values by column names, safer and easier to maintain.
Example:
{
"Employee ID": "{{ $json.body.employeeId }}",
"Name": "{{ $json.body.name }}",
"Department": "{{ $json.body.department }}",
"Position": "{{ $json.body.position }}",
"Salary": "{{ $json.body.salary }}"
}
Features:
- β Automatically read Excel headers (first row)
- β Intelligently map by column names
- β Ignore unknown columns with warnings in response
- β Column order can be arbitrary
- β Missing columns automatically filled with empty values
Array Mode
Specify values in exact column order.
Example:
["E100", "John Doe", "HR", "Manager", "70000"]
Note: Value order must exactly match Excel column order.
2. Read
Read data from Excel file.
Parameters:
file: File name (e.g.,employees.xlsx)sheet: Sheet name (default:Sheet1)range: Cell range (e.g.,A1:D10, leave empty to read all)
Output:
- Auto-convert first row to column names if headers detected
- Return array of objects with headers as keys
- Return raw data array if no headers
3. Update
Update existing row data by looking up specific column values.
Process Modes:
All Matching Records - Default
Update all matching rows, suitable for scenarios where multiple rows share the same value.
Example: Update all IT department employees
{
"operation": "update",
"lookupColumn": "Department",
"lookupValue": "IT",
"processMode": "all",
"valuesToSet": {
"Status": "Reviewed",
"Review Date": "2026-01-06"
}
}
First Match Only
Update only the first matching record, suitable for unique identifier lookups.
Example: Update specific employee data
{
"operation": "update",
"lookupColumn": "Employee ID",
"lookupValue": "E100",
"processMode": "first",
"valuesToSet": {
"Salary": "80000",
"Position": "Senior Manager"
}
}
π‘ Usage Tips:
- When looking up by unique identifiers (Employee ID, Email), use
processMode: "first"for better performance - Use
processMode: "all"when updating multiple records that share the same value - Default is
"all"to ensure no matching records are missed
4. Delete
Delete rows from the sheet by looking up specific column values.
Process Modes:
All Matching Records - Default
Delete all matching rows.
Example: Delete all terminated employees
{
"operation": "delete",
"lookupColumn": "Status",
"lookupValue": "Terminated",
"processMode": "all"
}
First Match Only
Delete only the first matching record.
Example: Delete specific employee
{
"operation": "delete",
"lookupColumn": "Employee ID",
"lookupValue": "E100",
"processMode": "first"
}
β οΈ Important:
- Delete operations cannot be undone, use with caution
- When looking up by unique identifiers, use
processMode: "first" - Verify lookup conditions carefully to avoid accidental data loss
π¨ Usage Examples
Example 1: Webhook Form to Excel
Perfect for scenarios with multiple simultaneous form submissions!
ββββββββββββββββββββ
β Webhook β Receive form submission
β POST /submit β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Excel API β Operation: Append (Object Mode)
β β File: registrations.xlsx
β β Values: {
β β "Name": "{{ $json.body.name }}",
β β "Email": "{{ $json.body.email }}",
β β "Phone": "{{ $json.body.phone }}",
β β "Submit Time": "{{ $now }}"
β β }
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Respond Webhook β Return success message
ββββββββββββββββββββ
HTML Form:
<form id="registrationForm">
<input type="text" name="name" placeholder="Name" required>
<input type="email" name="email" placeholder="Email" required>
<input type="tel" name="phone" placeholder="Phone" required>
<button type="submit">Submit</button>
</form>
<script>
document.getElementById('registrationForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
await fetch('YOUR_WEBHOOK_URL', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(Object.fromEntries(formData))
});
alert('Submitted successfully!');
});
</script>
Example 2: Daily Report Generation
ββββββββββββββββββββ
β Schedule β Every day at 9:00 AM
β 0 9 * * * β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Excel API β Operation: Read
β (Read) β File: sales.xlsx
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Filter β Filter today's records
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Send Email β Send daily report
ββββββββββββββββββββ
Example 3: Update Salary by Employee ID
ββββββββββββββββββββ
β Webhook β Receive update request
β POST /update β { "employeeId": "E100", "salary": 85000 }
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Excel API β Operation: Update
β β Identify By: Lookup
β β Lookup Column: Employee ID
β β Lookup Value: {{ $json.body.employeeId }}
β β Process Mode: First Match Only
β β Values To Set: { "Salary": "{{ $json.body.salary }}" }
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Respond Webhook β Return update result
ββββββββββββββββββββ
Example 4: Batch Department Status Update
Use Case: Review all employees in a department at once
ββββββββββββββββββββ
β Webhook β Receive batch review request
β POST /approve β { "department": "IT", "status": "Reviewed" }
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Excel API β Operation: Update
β β Identify By: Lookup
β β Lookup Column: Department
β β Lookup Value: {{ $json.body.department }}
β β Process Mode: All Matching Records
β β Values To Set: {
β β "Status": "{{ $json.body.status }}",
β β "Review Date": "{{ $now.format('YYYY-MM-DD') }}",
β β "Reviewer": "{{ $json.body.reviewer }}"
β β }
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Respond Webhook β Return: Updated N records
ββββββββββββββββββββ
Example 5: Clean Up Expired Data
Use Case: Periodically delete employee records terminated over a year ago
ββββββββββββββββββββ
β Schedule β Execute on 1st of month
β 0 0 1 * * β
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Excel API β Operation: Delete
β β Identify By: Lookup
β β Lookup Column: Status
β β Lookup Value: Terminated
β β Process Mode: All Matching Records
ββββββββββ¬ββββββββββ
β
βΌ
ββββββββββββββββββββ
β Send Email β Notify admin: Cleaned N records
ββββββββββββββββββββ
π§ͺ Concurrent Testing
Test 10 simultaneous submissions:
// concurrent_test.js
const promises = [];
for (let i = 0; i < 10; i++) {
promises.push(
fetch('YOUR_WEBHOOK_URL', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
EmployeeID: `E${String(i).padStart(3, '0')}`,
Name: `Test User ${i}`,
Timestamp: new Date().toISOString()
})
})
);
}
await Promise.all(promises);
console.log('All requests completed!');
Result: All 10 records will be safely written to Excel without data loss or corruption!
β οΈ Troubleshooting
Issue 1: Node Not Showing in n8n
Solution:
# Restart n8n
pkill -f n8n
n8n start
# Or with pm2
pm2 restart n8n
Issue 2: API Connection Failed
Solution:
- Check if Excel API Server is running:
curl http://localhost:8000/ - Verify API URL in credentials is correct
- Check API Token is correct
- Check firewall settings
Issue 3: "Parameter Not Found" Error
Cause: Incorrect parameter name configuration
Solution:
- Confirm correct Append Mode is selected (Object or Array)
- Object Mode: Use
appendValuesObjectparameter - Array Mode: Use
appendValuesArrayparameter - Check JSON format is correct
Issue 4: "File Lock" Error
Cause: Too many concurrent requests or API server issues
Solution:
- Wait a moment and retry
- Check API server status
- Restart Excel API Server if necessary
π Security
Best Practices
Use Strong API Token
# Generate secure token openssl rand -hex 32Use HTTPS in Production
- Set up reverse proxy (Nginx)
- Use SSL certificate
Restrict Access
- Allow only trusted networks to access API URL
- Use VPN for remote access
Regular Backups
- Set up automatic backups of Excel files
- Store backups in secure location
π Performance Optimization Tips
1. Specify Range When Reading
// β Bad: Read entire file
range: ""
// β
Good: Only read needed range
range: "A1:D100"
2. Use Efficient Workflows
- Combine related operations in one workflow
- Reduce number of API calls
- Use caching appropriately
π Latest Features
π Automatic Type Conversion (v1.0.3)
- β Smart Type Detection: Automatically convert strings to appropriate data types
- β
Number Conversion:
"123"β123,"45.67"β45.67 - β
Boolean Conversion:
"true"βtrue,"false"βfalse - β
Null Conversion:
"null"or empty string βnull - β
Date Conversion: ISO format date strings auto-convert (
"2024-01-15") - β Preserve Typed Values: Numbers, booleans, etc. remain unchanged
- β All Operations: Supported in both Append and Update operations
Example:
{
"EmployeeID": "E001", // Remains string
"Age": "30", // Auto-converts to number 30
"Salary": "50000.50", // Auto-converts to 50000.50
"IsActive": "true", // Auto-converts to boolean true
"TerminationDate": "null", // Auto-converts to null
"HireDate": "2020-01-15" // Auto-converts to date format
}
Object Mode
- β
Uses
/api/excel/append_objectAPI - β Automatically reads Excel headers (first row)
- β Intelligently maps by column names
- β Ignores unknown columns with warnings in response
- β No need to remember column order
Advanced Update and Delete
- β Support operations by column value lookup
- β Can update specific columns without affecting others
- β Process modes: all matching records or first match only
Lookup Column Selection
- β Dynamic dropdown selection of Excel headers
- β Support for Chinese and special character column names
- β Automatic URL encoding for special characters
- β Enhanced user experience with visual column selection
π€ Contributing
Contributions are welcome!
- Fork this repository
- Create your feature branch:
git checkout -b feature/AmazingFeature - Commit your changes:
git commit -m 'Add some AmazingFeature' - Push to the branch:
git push origin feature/AmazingFeature - Open a Pull Request
π License
MIT License - see LICENSE file
π Related Projects
- Excel API Server - Backend API server (Required)
- n8n - Workflow automation tool
π§ Support
- Work Items: GitLab Work Items
- Merge Requests: GitLab Merge Requests
- Email: hueyan.chen@gmail.com
- n8n Community: n8n Forum
β Star History
If this project helps you, please give it a β!
Built with β€οΈ for the n8n community