typed-xlsx
Columns

Images

Add embedded worksheet images or URL-backed Excel IMAGE formulas.

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:

ModeAPIXLSX outputBest for
Embedded bytestype: "image"Stores PNG/JPEG bytes under xl/media/* and draws them in the sheetPortable exports, offline workbooks, attachments
URL formulatype: "image", source: "url"Writes Excel's IMAGE("https://...") formula into the cellLightweight 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 callback
  • size: { width, height } in pixels
  • fit: "contain", "cover", or "stretch" as display intent

Embedded images also support:

  • mediaType
  • padding

URL images reject mediaType and padding because there is no media part in the XLSX package.

Copyright © 2026 Cyprien Thao. Released under the MIT License.