Skip to content

Loading Spreadsheets

To use the SpreadsheetViewer component, you need to provide a model prop. This guide shows you how to create a Model from .xlsx files.

First, install the required dependency for parsing Excel files:

Terminal window
npm install @borgar/xlsx-convert

You’ll also need to install the model library:

Terminal window
npm install @grid-is/cellatrix

The pattern for creating a Model from an Excel file involves three steps:

  1. Read the file as an ArrayBuffer
  2. Convert the binary data to JSF (JSON Spreadsheet Format) using convertBinary
  3. Create a Model instance from the JSF data

Here’s a complete example of loading an Excel file from a file input:

import { useState } from "react";
import { Model } from "@grid-is/cellatrix";
import { convertBinary } from "@borgar/xlsx-convert";
import { SpreadsheetViewer } from "@grid-is/mondrian-react";
function App() {
const [model, setModel] = useState<Model | null>(null);
const [isLoading, setIsLoading] = useState(false);
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
setIsLoading(true);
try {
// Step 1: Read file as ArrayBuffer
const arrayBuffer = await file.arrayBuffer();
// Step 2: Convert to JSF format
const jsf = await convertBinary(arrayBuffer, file.name);
// Step 3: Create Model from JSF
const newModel = Model.fromJSF(jsf);
setModel(newModel);
} catch (error) {
console.error("Failed to load file:", error);
} finally {
setIsLoading(false);
}
};
return (
<div>
<input
type="file"
accept=".xlsx"
onChange={handleFileChange}
disabled={isLoading}
/>
{isLoading && <p>Loading...</p>}
{model && (
<div style={{ height: "600px" }}>
<SpreadsheetViewer model={model} />
</div>
)}
</div>
);
}

You can also load spreadsheets from a URL using fetch:

import { useState, useEffect } from "react";
import { Model } from "@grid-is/cellatrix";
import { convertBinary } from "@borgar/xlsx-convert";
import { SpreadsheetViewer } from "@grid-is/mondrian-react";
function App() {
const [model, setModel] = useState<Model | null>(null);
useEffect(() => {
async function loadSpreadsheet() {
try {
// Fetch the file
const response = await fetch("/path/to/spreadsheet.xlsx");
const arrayBuffer = await response.arrayBuffer();
// Convert and create model
const jsf = await convertBinary(arrayBuffer, "spreadsheet.xlsx");
const newModel = Model.fromJSF(jsf);
setModel(newModel);
} catch (error) {
console.error("Failed to load spreadsheet:", error);
}
}
loadSpreadsheet();
}, []);
return model ? (
<div style={{ height: "600px" }}>
<SpreadsheetViewer model={model} />
</div>
) : (
<p>Loading...</p>
);
}

For a better user experience, you can add drag and drop support:

const handleDrop = async (event: React.DragEvent) => {
event.preventDefault();
const file = event.dataTransfer.files[0];
if (!file) return;
setIsLoading(true);
try {
const arrayBuffer = await file.arrayBuffer();
const jsf = await convertBinary(arrayBuffer, file.name);
const newModel = Model.fromJSF(jsf);
setModel(newModel);
} catch (error) {
console.error("Failed to load file:", error);
} finally {
setIsLoading(false);
}
};
return (
<div
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
>
{/* Your UI */}
</div>
);

It’s good practice to validate that the file is actually an Excel file:

const isExcelFile = (file: File): boolean => {
const validMimeType = file.type ===
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
const validExtension = file.name.toLowerCase().endsWith(".xlsx");
// Some browsers don't provide correct MIME types, so check both
return validMimeType || validExtension;
};
const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
if (!isExcelFile(file)) {
alert("Please select a .xlsx file");
return;
}
// Load the file...
};

Always handle potential errors when loading files:

try {
const arrayBuffer = await file.arrayBuffer();
const jsf = await convertBinary(arrayBuffer, file.name);
const newModel = Model.fromJSF(jsf);
setModel(newModel);
setError(null);
} catch (error) {
setError("Failed to load file. Please make sure it's a valid Excel file.");
console.error("File loading error:", error);
}

Now that you know how to create a Model, you can: