Skip to content

Extract Images

Sheet.Images() returns the images the sheet’s drawing refers to, as common.ImageRef values carrying the format, the pixel size and a path to the stored bytes. It is the way to inspect or export pictures from a workbook you did not create, and it is a read of what is already related to the sheet rather than a scan of the file, so it costs nothing to call.

The bytes themselves are not on your filesystem. When spreadsheet.Open unzips a workbook it extracts each image into unioffice’s temporary storage and hands back a reference into it, which is why the copy below goes through tempstorage.Open rather than os.Open.

Writing images out

wb, err := spreadsheet.Open("images.xlsx")
if err != nil {
    panic(err)
}
defer wb.Close()

for si, sheet := range wb.Sheets() {
    for i, img := range sheet.Images() {
        in, err := tempstorage.Open(img.Path())
        if err != nil {
            panic(err)
        }
        out, err := os.Create(fmt.Sprintf("sheet%d_image%d.%s", si+1, i+1, img.Format()))
        if err != nil {
            panic(err)
        }
        io.Copy(out, in)
        in.Close()
        out.Close()
    }
}

Format() returns the extension the image was stored under, so it makes a serviceable file suffix. Size() returns an image.Point of the pixel dimensions, which is the stored size and not necessarily the size the picture is displayed at; display size comes from the anchor.

The ordering is relationship order within the drawing, not visual order on the sheet. If you need to know where an image sits, read the anchors on the drawing returned by Sheet.GetDrawing().

Limitations

wb.Close() deletes the temporary storage the images live in. Copy the bytes out before the workbook goes out of scope; a defer wb.Close() at the top of a function is fine, a Close in the middle of the loop is not.

Sheet.Images() returns nil when the sheet has no drawing at all, which is the common case, so an empty result is not an error.

Images embedded through VML or a legacy drawing are excluded. In practice that means comment background images, which will not appear in the results even though Excel displays them.

Workbook.Sheets() skips sheets marked hidden or very hidden, so a loop over Sheets() will not reach images on a hidden tab.

Two placements of the same picture share one stored file. The workbook de-dupes on the original target when it reads the file, so a picture used on two sheets yields one set of bytes reached from both.

Run the example

The example opens images.xlsx, prints a count per sheet, and writes each image out as sheet<N>_image<M>.<ext>. Its saveImage helper is the piece to copy; everything else is reporting.

git clone https://github.com/unidoc/unioffice-examples.git
cd unioffice-examples/spreadsheet/image_extraction
go run main.go

If this is your first time using UniOffice, follow the getting started guide to create an API key and set up your development environment.

View the full source
Last updated on