Images
Use type: "image" when a column should render a picture instead of normal text or numeric data — product thumbnails in a catalog export, logos in a partner directory, photos in an inspection report.
typed-xlsx supports two image sources:
| Mode | API | XLSX output | Best for |
|---|---|---|---|
| Embedded bytes | type: "image" | Stores PNG/JPEG bytes under xl/media/* and draws them in the sheet | Portable exports, offline workbooks, attachments |
| URL formula | type: "image", source: "url" | Writes Excel's IMAGE("https://...") formula into the cell | Lightweight workbooks where live external images are acceptable |
Embedded images
Embedded images are the default. The accessor must resolve to image bytes:
import { createExcelSchema, type ImageValue } from "typed-xlsx";
type Product = {
name: string;
thumbnail?: Uint8Array;
};
const schema = createExcelSchema<Product>()
.column("thumbnail", {
type: "image",
accessor: "thumbnail",
alt: "name",
size: { width: 56, height: 56 },
padding: 3,
})
.column("name", {
accessor: "name",
})
.build();
The accessor can also resolve to a full ImageValue when a row needs to carry per-image metadata alongside the bytes:
const image: ImageValue = {
data: pngBytes,
mediaType: "image/png",
alt: "Product thumbnail",
};
If the bytes have a recognizable PNG or JPEG signature, mediaType is optional. Otherwise pass mediaType: "image/png" or mediaType: "image/jpeg" on the column or the row value.
For remote images that need to be portable, fetch them in your application and pass the bytes to typed-xlsx:
async function fetchImageBytes(url: string) {
const response = await fetch(url);
return new Uint8Array(await response.arrayBuffer());
}
typed-xlsx does not fetch remote images for embedded mode. This keeps the buffered API synchronous and makes network failures explicit in your export pipeline.
File size and compression
Embedded images increase workbook size because the image bytes are part of the XLSX package. typed-xlsx deduplicates identical embedded image bytes across the workbook, so a repeated logo or thumbnail payload is written once under xl/media/* and referenced by each drawing.
The rendered size controls the worksheet drawing box. It does not shrink the embedded image bytes. If you pass a 1900x1900 image and render it as 40x40, the workbook still carries the original 1900x1900 payload.
typed-xlsx does not resize, transcode, or recompress image pixels. PNG and JPEG files are already compressed formats, so the biggest file-size wins usually come from preparing export-sized thumbnails before building the workbook:
type Product = {
name: string;
rawImageUrl: string;
};
declare function createThumbnail(
url: string,
size: { width: number; height: number },
): Promise<Uint8Array>;
async function prepareRows(products: Product[]) {
return Promise.all(
products.map(async (product) => ({
...product,
thumbnail: await createThumbnail(product.rawImageUrl, { width: 80, height: 80 }),
})),
);
}
Use URL images when embedding is not required and the workbook can depend on public remote images instead.
URL images
URL images opt into Excel's IMAGE() formula. The accessor must resolve to a URL string or { url, alt?, size?, fit? }:
import { createExcelSchema, type ImageUrlValue } from "typed-xlsx";
type Product = {
name: string;
thumbnailUrl?: string;
};
const schema = createExcelSchema<Product>()
.column("remotePreview", {
type: "image",
source: "url",
accessor: "thumbnailUrl",
alt: "name",
size: { width: 56, height: 56 },
})
.column("name", {
accessor: "name",
})
.build();
const remoteImage: ImageUrlValue = {
url: "https://cdn.example.com/products/sku-123.png",
alt: "Product thumbnail",
size: { width: 56, height: 56 },
};
This mode does not embed image bytes. Excel fetches the image when the workbook opens or recalculates.
Choosing a mode
Use embedded images when:
- the workbook must work offline
- recipients may not have access to the original image host
- the image URL requires cookies, headers, signed requests, or other authentication
- the file is an attachment or a durable audit/export artifact
Use URL images when:
- the workbook can depend on network access
- images are public HTTPS resources
- you want smaller workbooks
- it is acceptable for images to update or fail independently of the XLSX file
URL constraints
URL image columns inherit Excel IMAGE() and Office external-content behavior:
- Excel support depends on the user's Excel version.
- Authenticated URLs do not render.
- Redirected URLs can be blocked for security reasons.
- Long URLs may hit Excel formula/source limits.
- Office security settings may block external content until the user trusts the workbook.
Microsoft documents the IMAGE() function behavior in IMAGE function - Microsoft Support, and external-content blocking in Block or unblock external content in Office documents.
Layout options
Both modes support:
alt: static text, row path, or row callbacksize:{ width, height }in pixelsfit:"contain","cover", or"stretch"as display intent
Embedded images also support:
mediaTypepadding
URL images reject mediaType and padding because there is no media part in the XLSX package.