@mertdeveci55/univer-import-export
Version:
Excel/CSV import and export library for Univer spreadsheets with full format preservation
407 lines (312 loc) • 13.2 kB
Markdown
# @mertdeveci55/univer-import-export
A robust Excel/CSV import and export library for [Univer](https://github.com/dream-num/univer) spreadsheets with full format preservation, including formulas, styling, charts, and conditional formatting.
[](https://www.npmjs.com/package/@mertdeveci55/univer-import-export)
[](https://opensource.org/licenses/MIT)
## Features
✅ **Import Support**
- Excel files (.xlsx, .xls)
- CSV files (.csv)
- Preserves ALL sheets (including empty ones)
- Handles special characters in sheet names (>>>, etc.)
- Maintains exact sheet order
- Full styling preservation (fonts, colors, borders, alignment)
- Formula and calculated value retention (including TRANSPOSE and array formulas)
- Merged cells support
- Images and charts
- Conditional formatting
- Data validation
- Hyperlinks and rich text
✅ **Export Support**
- Excel files (.xlsx)
- CSV files (.csv)
- Full formatting preservation
- Formula export
- Named ranges
- Multiple sheets
## Installation
```bash
npm install @mertdeveci55/univer-import-export
```
or
```bash
yarn add @mertdeveci55/univer-import-export
```
## Usage
### Import Excel to Univer
```javascript
import { LuckyExcel } from '@mertdeveci55/univer-import-export';
// Handle file input
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
LuckyExcel.transformExcelToUniver(
file,
(univerData) => {
// Use the Univer data
console.log('Converted data:', univerData);
// Create Univer instance with the data
univer.createUnit(UniverInstanceType.UNIVER_SHEET, univerData);
},
(error) => {
console.error('Import error:', error);
}
);
});
```
### Import CSV to Univer
```javascript
import { LuckyExcel } from '@mertdeveci55/univer-import-export';
LuckyExcel.transformCsvToUniver(
csvFile,
(univerData) => {
// Use the converted CSV data
univer.createUnit(UniverInstanceType.UNIVER_SHEET, univerData);
},
(error) => {
console.error('CSV import error:', error);
}
);
```
### Export Univer to Excel
```javascript
import { LuckyExcel } from '@mertdeveci55/univer-import-export';
// Get Univer snapshot
const snapshot = univer.getActiveWorkbook().save();
LuckyExcel.transformUniverToExcel({
snapshot: snapshot,
fileName: 'my-spreadsheet.xlsx',
success: () => {
console.log('Export successful');
},
error: (err) => {
console.error('Export error:', err);
}
});
```
### Export Univer to CSV
```javascript
import { LuckyExcel } from '@mertdeveci55/univer-import-export';
const snapshot = univer.getActiveWorkbook().save();
LuckyExcel.transformUniverToCsv({
snapshot: snapshot,
fileName: 'my-data.csv',
sheetName: 'Sheet1', // Optional: specific sheet to export
success: () => {
console.log('CSV export successful');
},
error: (err) => {
console.error('CSV export error:', err);
}
});
```
## API Reference
### `LuckyExcel.transformExcelToUniver(file, callback, errorHandler)`
Converts Excel file to Univer format.
- **file**: `File` - The Excel file (.xlsx or .xls)
- **callback**: `(data: IWorkbookData) => void` - Success callback with converted data
- **errorHandler**: `(error: Error) => void` - Error callback
### `LuckyExcel.transformCsvToUniver(file, callback, errorHandler)`
Converts CSV file to Univer format.
- **file**: `File` - The CSV file
- **callback**: `(data: IWorkbookData) => void` - Success callback
- **errorHandler**: `(error: Error) => void` - Error callback
### `LuckyExcel.transformUniverToExcel(params)`
Exports Univer data to Excel file.
**Parameters object:**
- **snapshot**: `any` - Univer workbook snapshot
- **fileName**: `string` - Output filename (optional, default: `excel_[timestamp].xlsx`)
- **getBuffer**: `boolean` - Return buffer instead of downloading (optional, default: false)
- **success**: `(buffer?: Buffer) => void` - Success callback
- **error**: `(err: Error) => void` - Error callback
### `LuckyExcel.transformUniverToCsv(params)`
Exports Univer data to CSV file.
**Parameters object:**
- **snapshot**: `any` - Univer workbook snapshot
- **fileName**: `string` - Output filename (optional, default: `csv_[timestamp].csv`)
- **sheetName**: `string` - Specific sheet to export (optional, exports all if not specified)
- **getBuffer**: `boolean` - Return content instead of downloading (optional, default: false)
- **success**: `(content?: string) => void` - Success callback
- **error**: `(err: Error) => void` - Error callback
## Browser Support
The library works in all modern browsers that support:
- ES6+
- File API
- Blob API
## Project Structure
```
src/
├── ToLuckySheet/ # Excel → LuckySheet conversion
│ ├── LuckyFile.ts # Main file orchestrator - handles sheet discovery
│ ├── LuckySheet.ts # Individual sheet processor
│ ├── ReadXml.ts # XML parser with special character escaping
│ ├── LuckyCell.ts # Cell data processor
│ └── ...
├── LuckyToUniver/ # LuckySheet → Univer conversion
│ ├── UniverWorkBook.ts # Workbook structure converter
│ ├── UniverSheet.ts # Sheet data converter
│ └── ...
├── UniverToExcel/ # Univer → Excel export
│ ├── Workbook.ts # Excel workbook builder using ExcelJS
│ └── ...
├── HandleZip.ts # ZIP file operations using JSZip
└── main.ts # Entry point with public API
dist/ # Built output (ESM, CJS, UMD formats)
publish.sh # Automated publishing script
gulpfile.js # Build configuration
CLAUDE.md # Detailed technical documentation
```
## Key Implementation Details
### Special Character Handling
Sheet names with special characters (like `>>>`) are handled through an escape/unescape mechanism in `src/ToLuckySheet/ReadXml.ts`:
```javascript
// Escapes ">" to "__GT__" before XML parsing
escapeXmlAttributes(xmlString)
// Restores "__GT__" back to ">" after parsing
unescapeXmlAttributes(xmlString)
```
### Empty Sheet Preservation
All sheets are preserved during import, even if completely empty. This maintains Excel file structure integrity.
### Formula Support
Comprehensive formula support including:
- Standard formulas (SUM, AVERAGE, IF, VLOOKUP, etc.)
- Array formulas
- TRANSPOSE formulas with proper array handling
- Shared formulas
- Named range references
## Development
### Building
```bash
npm install
npm run build # Uses gulp to compile TypeScript and bundle
```
### Publishing
Always use the publish script for releases:
```bash
./publish.sh
```
This script:
1. Builds the project
2. Increments version
3. Commits changes
4. Pushes to GitHub
5. Publishes to npm
### Testing
```bash
npm test
```
## Key Improvements (v0.1.24)
1. **Special Character Support**: Handles sheet names with `>>>` and other special characters via escape/unescape mechanism
2. **Empty Sheet Preservation**: Empty sheets are never skipped during import
3. **No Hardcoded Solutions**: Removed all hardcoded sheet additions - all solutions are generic
4. **Sheet Order**: Maintains exact sheet order from original file
5. **Style Preservation**: Complete style mapping including bold, italic, colors, borders
6. **Formula Handling**: Preserves both formulas and calculated values, including TRANSPOSE
7. **XLS Support**: Automatic conversion of .xls files to .xlsx format
8. **Better Error Handling**: Comprehensive error messages and detailed logging
## Dependencies
### Core Dependencies
- [`@progress/jszip-esm`](https://www.npmjs.com/package/@progress/jszip-esm) - ZIP file handling for Excel files
- [`@zwight/exceljs`](https://www.npmjs.com/package/@zwight/exceljs) - Excel file structure (export)
- [`@univerjs/core`](https://github.com/dream-num/univer) - Univer core types and interfaces
- [`dayjs`](https://day.js.org/) - Date manipulation for Excel dates
- [`papaparse`](https://www.papaparse.com/) - CSV parsing
- [`xlsx`](https://sheetjs.com/) - Additional Excel format support
### Build Dependencies
- `gulp` - Build orchestration
- `rollup` - Module bundling
- `typescript` - Type safety
- `terser` - Minification (configured to preserve console.logs)
## Related Projects & References
### Core Dependencies
- **[Univer](https://github.com/dream-num/univer)** - The spreadsheet engine this library supports
- **[LuckySheet](https://github.com/mengshukeji/Luckysheet)** - Intermediate format inspiration
- **[LuckyExcel](https://github.com/dream-num/Luckyexcel)** - Original codebase this fork is based on
### Implementation Examples
- **[alphafrontend](https://github.com/mertdeveci/alphafrontend)** - Production implementation
- See: `src/utils/excel-import.ts` for usage example
- See: `src/pages/SpreadsheetsPage.tsx` for UI integration
### Documentation
- **[CLAUDE.md](./CLAUDE.md)** - Detailed technical documentation for AI assistants
- **[publish.sh](./publish.sh)** - Automated publishing script
- **[gulpfile.js](./gulpfile.js)** - Build configuration
## Known Issues & Solutions
### ✅ Resolved Issues
| Issue | Solution | Version Fixed |
|-------|----------|---------------|
| Sheets with special characters (>>>) not importing | Escape/unescape mechanism in ReadXml.ts | v0.1.23+ |
| AttributeList undefined errors | Defensive initialization | v0.1.21+ |
| Duplicate sheets appearing | Removed hardcoded sheet additions | v0.1.24 |
| TRANSPOSE formulas not working | Array formula support | v0.1.18+ |
| Border styles not importing | Added style collection in UniverWorkBook | v0.1.38 |
### ⚠️ Export Limitations & Solutions
Due to limitations in the underlying ExcelJS library, some advanced Excel features have issues during **export**. However, we provide comprehensive solutions:
## 🔧 **Backend Post-Processing Solution**
For production applications, we recommend using backend post-processing to achieve **100% Excel compatibility**:
### **Architecture**
```
Frontend Export → Backend API → openpyxl Post-Processing → Fixed Excel File
```
### **Django Integration Example**
```python
from spreadsheets.import_export import UniverToExcelConverter, ExcelPostProcessor
# Step 1: Export with existing functionality (preserves all working features)
converter = UniverToExcelConverter()
excel_buffer = converter.convert(univer_data)
# Step 2: Apply surgical fixes for ExcelJS limitations
post_processor = ExcelPostProcessor()
fixed_buffer = post_processor.process_excel_buffer(
excel_buffer.getvalue(),
univer_data
)
```
### **What Gets Fixed**
- ✅ **Defined Names**: All named ranges work perfectly in Excel
- ✅ **Array Formula Attributes**: Proper XML attributes for spill ranges
- ✅ **Excel 365 Compatibility**: Full support for modern Excel features
- ✅ **Performance**: ~7ms processing overhead
- ✅ **Safety**: Preserves ALL existing functionality
### **Frontend Integration**
```typescript
// Enhanced export with backend post-processing
const result = await exportToExcel({
workbookData,
fileName: 'spreadsheet.xlsx',
useBackendExport: true, // Enable backend processing
enablePostProcessing: true, // Fix ExcelJS limitations
exportSpreadsheetToExcel: api.exportSpreadsheetToExcel
});
// Automatic fallback to frontend if backend unavailable
if (result.stats?.postProcessingApplied) {
console.log('✅ Enhanced Excel compatibility applied!');
}
```
### **Setup Requirements**
1. **Python Backend** with `openpyxl` installed
2. **API Endpoint** for post-processing
3. **Optional**: Feature flag for gradual rollout
## 📊 **Pure Frontend Limitations**
When using **frontend-only** export (without backend post-processing):
| Issue | Impact | Status |
|-------|--------|---------|
| **Defined Names** | Named ranges don't work in Excel | Use backend fix |
| **Array Formulas** | Missing spill attributes | Use backend fix |
| **All Other Features** | Work perfectly | ✅ Fully supported |
**Import functionality works perfectly** - these limitations only affect export operations.
## Contributing
Contributions are welcome! Please ensure:
1. **No hardcoded solutions** - All fixes must be generic
2. **Extensive logging** - Add console.log for debugging
3. **Use publish.sh** - Never manually publish to npm
4. **Test edge cases** - Including special characters, empty sheets
5. **Follow existing patterns** - Check CLAUDE.md for architecture
## License
MIT © mertdeveci
## Credits
- Original [LuckyExcel](https://github.com/dream-num/Luckyexcel) by DreamNum
- [Univer](https://github.com/dream-num/univer) spreadsheet engine
- All contributors and issue reporters
## Support
For issues and feature requests:
- [GitHub Issues](https://github.com/mertdeveci/univerjs-import-export/issues)
- Check [CLAUDE.md](./CLAUDE.md) for technical details
- Review closed issues for solutions