---
title: "Картинки: AddPicture и привязка к ячейкам"
description: "Excelize картинка: addpicture excelize вставляет логотип в шапку — масштаб, якоря oneCell и twoCell, вес файла и медиа внутри xlsx. Практика привязки к ячейкам."
course: "Excel в Go: чтение и генерация xlsx на excelize"
url: "https://golangmaster.ru/courses/excelize/lessons/14-izobrazheniya/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 16
---

# Картинки: AddPicture и привязка к ячейкам

*Курс «Excel в Go: чтение и генерация xlsx на excelize», урок 14 из 25. ~16 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/excelize/lessons/14-izobrazheniya/*

Запрос addpicture excelize приходит, когда отчёту нужен логотип в шапке, накладной — печать, а прайсу — фото товара в строке. Excelize картинку копирует внутрь xlsx в папку медиа, а листу оставляет якорь: ячейку привязки, масштаб и поведение при растягивании. В уроке разберём AddPicture с GraphicOptions, масштаб вместо размеров, три режима якоря, вес файла и честные ограничения: что произойдёт с логотипом, когда пользователь раздвинет колонки.

Внутри xlsx картинка — это файл в пакете: PNG или JPEG кладётся в xl/media, а лист получает описание привязки — якорь с ячейкой, смещением и режимом поведения. Отсюда следствие, которое объясняет половину вопросов про вес файла: каждая вставка копирует картинку целиком, и тридцать фото товара утяжеляют прайс на все их мегабайты, а не на ссылки. Второе следствие касается поведения: картинка привязана к ячейке не намертво, а по правилу, которое выбирает генератор — двигаться с ячейками, двигаться без растягивания или не двигаться вовсе. Эти правила описывает структура GraphicOptions, и в них же живёт масштаб. Отдельная тонкость: excelize не знает ни размеров листа, ни замысла макета — логотип поверх шапки означает, что шапка должна уступить место, и это тоже работа генератора. Разберём вызов по частям: якорь, масштаб, режим привязки, и кейс про логотип, который растянулся на поллиста после правки ширины колонок.

### AddPicture: addpicture excelize и якорь

Сигнатура в современных версиях: f.AddPicture принимает лист, ячейку-якорь, путь к файлу и указатель на GraphicOptions, а возвращает пару (string, error) — идентификатор вставки. Вызов f.AddPicture("Отчёт", "A1", "logo.png", opts) поставит верхний-левый угол картинки в ячейку A1: логотип встанет в угол шапки, а не по центру ячейки. Ошибка вернётся на несуществующем файле — путь проверяется при вставке, поэтому ошибка чтения диска всплывёт именно здесь, а не при SaveAs. Если картинка уже в памяти — файл из сети, из базы, из архива — вместо чтения с диска берут AddPictureFromBytes: он принимает байты и расширение и работает так же, только без промежуточного файла на диске. Список вставленного читается GetPictures: метод вернёт картинки листа с содержимым, что удобно в тестах — проверить, что логотип в файле попал, можно без открытия Excel. Запрос excelize картинка упирается в эту четвёрку: путь, ячейка, опции, идентификатор.

### Логотип в шапке отчёта

```go
logoID, err := f.AddPicture("Отчёт", "A1", "logo.png", &excelize.GraphicOptions{
    ScaleX:          0.4,
    ScaleY:          0.4,
    Positioning:     excelize.PositionOneCell,
    LockAspectRatio: true,
})
if err != nil {
    panic(err)
}

f.SetColWidth("Отчёт", "A", "A", 12)
```

Масштаб 0.4 ужал логотип до сорока процентов исходного размера, якорь oneCell позволит картинке двигаться с ячейкой, но не растягиваться, а LockAspectRatio сохранит пропорции. Ширина колонки A задана под логотип: ячейка-якорь отвечает за верхний-левый угол картинки.

> **Якорь решает, что случится при растягивании.** Режим Positioning определяет поведение картинки, когда пользователь меняет ширину колонок и высоту строк: twoCell — картинка тянется вместе с ячейками и может растянуться до неузнаваемости, oneCell — картинка сдвинется вслед за ячейками, но размер сохранит, absolute — картинка не двигается вовсе и живёт на координатах листа. По умолчанию действует twoCell, и именно из-за него логотипы расползаются после правки ширины: для лого и печатей берут oneCell, для декоративных подложек — absolute.

### Масштаб и размеры: ScaleX и ScaleY

Размер картинки в GraphicOptions задаётся масштабом, а не шириной и высотой: ScaleX и ScaleY — множители исходного размера файла, единица оставляет как есть, ноль целых четыре десятых — сорок процентов. Отдельного поля «вставить шириной три сантиметра» нет, и когда размер в сантиметрах требуется, масштаб считают в Go: исходные пиксели картинки известны, целевые тоже, множитель — деление одного на другое. Полезно знать, что исходный размер — это пиксели файла, а не экранное впечатление: логотип на четыре тысячи пикселей и логотип на четыреста с одним множителем встанут по-разному, поэтому множитель считают от конкретного файла, а не от привычки. LockAspectRatio true связывает обе оси: при изменении одной эксель пропорционально подстроит вторую, и логотип не станет квадратным из прямоугольного. Смещение внутри ячейки задают OffsetX и OffsetY — пригодится, когда картинку нужно сдвинуть на пару пикселей от границ. Полезные флаги: PrintObject решает, попадёт ли картинка на печать — логотипу положено true, водяному знаку данных нет, AltText пишет альтернативный текст для доступности и поиска. Так addpicture excelize описывает картинку одним набором полей, и всё остальное — вычисление множителей и выбор якоря.

### Фото товара в строке прайса

```go
for i, item := range items {
    if item.Photo == "" {
        continue
    }
    cell := fmt.Sprintf("D%d", i+2)
    if _, err := f.AddPicture("Прайс", cell, item.Photo, &excelize.GraphicOptions{
        ScaleX:      0.25,
        ScaleY:      0.25,
        Positioning: excelize.PositionOneCell,
    }); err != nil {
        panic(err)
    }
}
```

Якорь считается по строке прайса той же Sprintf-техникой, что в формулы и координаты. Пустые фото пропущены: AddPicture вернёт ошибку на несуществующем файле, и один битый путь уронил бы весь прайс — наличие файлов проверяют до цикла, на месте генерации.

### Вес файла и медиа внутри xlsx

Картинка переезжает в файл целиком: xlsx — это zip, и xl/media получит копию вашего PNG. Три вставки одного логотипа — три копии в медиа, и никаких дедупликаций библиотека не делает. Прайс с тридцатью фотографиями по пятьсот килобайт станет тяжелее на пятнадцать мегабайт, а Excel при открытии будет раскладывать все эти медиа — на слабых машинах это заметная задержка. Лечение генераторное: готовьте картинки заранее — ужимайте, режьте миниатюры, держите в отдельной папке версии под xlsx — и вставляйте их, а не оригиналы из фотоаппарата. Тот же подход экономит и трафик: отчёт на пятнадцать мегабайт не каждый почтовый ящик примет, и вложение урежет фильтр сервера раньше, чем его увидит получатель.

### Чтение и форматы: GetPictures без Excel

Сказанное про медиа верно и в обратную сторону: GetPictures вернёт байты вставленных картинок, и их можно вынуть из файла без Excel, что удобно для миграций и аудита. По чужому файлу видно, какие изображения в нём лежат, сколько они весят и где на листе стоят — картина полезнее, чем визуальный осмотр, потому что якоря и копии видны сразу. Расширения поддерживаются распространённые — PNG, JPEG, GIF и ещё несколько графических форматов, а вот SVG excelize в xlsx не положит: вектор придётся растеризовать заранее, и это ещё один пункт в копилку подготовки медиа до генерации. Запрос excelize картинка на проде чаще всего превращается в вопрос дисциплины: кто готовит медиа, какого веса и в какой папке они хранятся.

### Поля GraphicOptions одним взглядом

| Поле | Значение | Для чего берут |
| --- | --- | --- |
| ScaleX, ScaleY | 0.4 — сорок процентов | масштаб от исходного размера файла |
| Positioning | oneCell, twoCell, absolute | поведение при правке строк и колонок |
| OffsetX, OffsetY | сдвиг от угла ячейки | поправить позицию логотипа в шапке |
| LockAspectRatio | true | пропорции при изменении одной из осей |
| PrintObject | true или false | включить картинку в печать или убрать |
| AltText | текст-описание | доступность и поиск по файлу |

> **Картинки читаются обратно.** GetPictures вернёт вставленные картинки листа с их содержимым: файл можно разобрать без Excel и вынуть логотипы или фото для миграции в другую систему. Пригодится и для тестов: проверка, что прайс получил свои медиа, не требует офисного пакета — байты сравниваются прямо в тесте генерации.

### Чек-лист картинок

- AddPicture принимает лист, якорь, путь и GraphicOptions, возвращает (string, error).
- Размер задаётся масштабом ScaleX и ScaleY от исходного файла, а не сантиметрами.
- Positioning: twoCell тянется с ячейками, oneCell двигается без растягивания, absolute стоит намертво.
- LockAspectRatio true держит пропорции; OffsetX и OffsetY сдвигают внутри якоря.
- Каждая вставка копирует файл в xl/media: вес растёт на размер картинок, дедупликации нет.
- Несуществующий путь вернёт ошибку при вставке: проверяйте наличие файлов до цикла.

> **В песочнице файлов нет.** AddPicture требует файла картинки на диске, поэтому в браузерной песочнице не запускается: там доступны fmt, strings, strconv, math, sort, errors и time без файлового ввода-вывода. Посчитать масштаб потренировать можно: поделите целевую ширину на исходную math'ем и напечатайте множитель с двумя знаками — файл с логотипом соберите локально.

Кейс про логотип, который съел шапку. Команда вставляла логотип компании в шапку еженедельного отчёта, и первая версия выглядела нормально ровно до первой правки: кто-то раздвинул колонку A под длинные наименования, и логотип потянулся вдвое, закрыв шапку и половину строки данных. Причина оказалась в умолчании twoCell: картинка привязана к двум ячейкам и тянется вместе с ними. Лечение заняло один вызов: Positioning oneCell с LockAspectRatio — логотип двигается вслед за ячейками, но растягиваться перестал. Вторая волна жалоб пришла от получателей на слабых машинах: файл потяжелел вдвое после того, как в прайс добавили фото товара — оригиналы по два мегабайта вставлялись тридцать штук. Собрали миниатюры на двести пикселей, вес вернулся, а к генератору добавили правило: медиа для xlsx готовятся отдельно, в оригинальном размере вставка не делается. Спорная сторона осталась с дизайнером: логотип в шапке поверх заливки требует прозрачного PNG, и часть старых файлов с белой плашкой вокруг логотипа так и живёт в архиве.

### Проверка: поведение якоря

**Вопрос:** Логотип вставлен с Positioning: excelize.PositionOneCell. Что произойдёт, когда пользователь увеличит ширину колонки, к которой привязана картинка?

- ✅ Картинка сдвинется с ячейками, но размер сохранит
- Картинка растянется вслед за колонкой
- Картинка останется на месте и не сдвинется
- Картинка исчезнет: привязка потеряется

oneCell означает привязку к одной ячейке: при правке строк и колонок картинка двигается вместе с якорем, но размер не меняет. Растягивание — это twoCell, неподвижность на координатах листа — absolute.

### Проверка: куда попадает файл

**Вопрос:** После AddPicture("Отчёт", "A1", "logo.png", opts) где физически лежит картинка внутри xlsx?

- ✅ В пакете xl/media, лист хранит якорь-ссылку
- В самой ячейке A1 в виде текста
- В styles.xml рядом со стилями шапки
- Нигде: excelize вставляет только ссылку на путь

xlsx — это zip-пакет: картинка копируется в xl/media, а лист получает описание привязки с якорем и настройками. Ссылки на путь файл не хранит — иначе отчёт не открылся бы на другой машине без логотипа.

### Что напечатает код?

```go
opts := &excelize.GraphicOptions{ScaleX: 1, ScaleY: 1}

opts.ScaleX = 0.5

fmt.Println(opts.ScaleY)
```

**Что выведет программа?**

- ✅ 1: масштаб по вертикали не меняли
- 0.5: оси связаны по умолчанию
- 0: нулевой масштаб по умолчанию
- Ошибку: ScaleX после создания менять нельзя

ScaleX и ScaleY — независимые поля структуры: изменение одного второе не трогает, связывает оси только LockAspectRatio в Excel. Умолчание единица — исходный размер картинки.

### Соберите вставку логотипа

Допишите вызов вставки, второй масштаб, режим якоря и переменную ошибки.

```go
_, err := f.___("Отчёт", "A1", "logo.png", &excelize.GraphicOptions{
    ScaleX:      0.4,
    ___:         0.4,
    Positioning: excelize.___,
})
if err != nil {
    panic(___)
}
```

Подсказка: Картинку вставляет AddPicture, вертикальный масштаб — ScaleY, якорь без растягивания — PositionOneCell, ошибка живёт в err.

Правильные ответы в пропусках: `AddPicture`, `ScaleY`, `PositionOneCell`, `err`

### Соберите шапку с логотипом

Расставьте строки в порядке выполнения: написать заголовок, вставить логотип, проверить ошибку, задать ширину колонки, сохранить файл, закрыть книгу.

Правильный порядок строк:

1. `f.SetCellValue("Отчёт", "B1", "Отчёт за второй квартал")`
2. `logoID, err := f.AddPicture("Отчёт", "A1", "logo.png", logoOpts)`
3. `if err != nil { panic(err) }`
4. `f.SetColWidth("Отчёт", "A", "A", 12)`
5. `err = f.SaveAs("otchet.xlsx")`
6. `f.Close()`

### Карточки: картинки

- **AddPicture** — Вставляет картинку: лист, ячейка-якорь, путь к файлу, GraphicOptions; возвращает (string, error). Ошибка вернётся на несуществующем пути.
- **GraphicOptions** — Описание вставки: масштабы ScaleX и ScaleY, смещения OffsetX и OffsetY, якорь Positioning, пропорции, печать и альтернативный текст.
- **Positioning** — Режим якоря: twoCell тянется с ячейками, oneCell двигается без растягивания, absolute стоит на координатах листа. Логотипам берут oneCell.
- **ScaleX и ScaleY** — Множители исходного размера: 1 — как есть, 0.4 — сорок процентов. Полей «ширина в сантиметрах» нет — масштаб считают в Go.
- **xl/media** — Папка внутри xlsx, куда копируется файл картинки. Каждая вставка — новая копия без дедупликации: вес растёт на размер вставленного.
- **AddPictureFromBytes** — Вставка из байтов в памяти: файл из сети, базы или архива идёт в xlsx без промежуточного файла на диске.

Логотип стоит в шапке, якорь выбран осознанно, вес файла под контролем. Отчёт готов к последним штрихам навигации: в уроке про [закрепление областей и автофильтры](/courses/excelize/lessons/15-zakreplenie-filtry/) шапка перестанет уезжать на длинных выгрузках, а в уроке про [защиту листа](/courses/excelize/lessons/16-zashchita-lista/) логотип получит соседей, которых нельзя подвинуть случайно. Ширина колонки под логотип ставится тем же SetColWidth из урока про [слияние и ширину](/courses/excelize/lessons/10-obyedinenie-yacheek/), а координаты якоря собираются техникой из урока про [чтение ячеек](/courses/excelize/lessons/06-stroki-i-stolbcy/). Логотип и фото товара встречаются в шаблоне [экспорта отчёта из базы](/courses/excelize/lessons/19-eksport-iz-bd/) — там медиа готовятся до цикла, а не внутри него. Домашнее задание — логотип в шапку с якорем oneCell и пересчёт масштаба под свои размеры.

## Коротко: что запомнить

- AddPicture копирует файл в xl/media и ставит якорь на листе; возвращает (string, error).
- Размер задаётся масштабом ScaleX и ScaleY; сантиметров в опциях нет — множитель считают в Go.
- Positioning решает поведение: twoCell тянется, oneCell двигается, absolute стоит намертво.
- LockAspectRatio держит пропорции, OffsetX и OffsetY сдвигают картинку внутри ячейки.
- Каждая вставка — новая копия в медиа: миниатюры готовят до вставки, а не вместо неё.
- GetPictures читает картинки обратно — пригодится в тестах и миграциях без Excel.

## Домашнее задание

Вставьте логотип своей компании в шапку отчёта: якорь A1, масштаб подберите так, чтобы картинка встала в колонку шириной двенадцать символов, режим oneCell с сохранением пропорций. Добавьте фото в первую строку прайса, проверьте GetPictures, что обе картинки в файле, затем раздвиньте колонки в Excel и убедитесь, что логотип больше не растягивается.

## Вопросы и ответы по уроку

### Почему логотип растянулся после изменения ширины колонок?

Вставка прошла с умолчанием twoCell: картинка привязана к двум ячейкам и тянется вместе с ними. Перевставьте с Positioning: excelize.PositionOneCell и LockAspectRatio: true — логотип будет двигаться с ячейками, но размер сохранит.

### Как задать картинке размер в сантиметрах?

Поля ширины и высоты в GraphicOptions нет — размер задаётся множителями ScaleX и ScaleY от исходного файла. Посчитайте масштаб в Go: целевую ширину поделите на исходные пиксели картинки и передайте результат в оба поля.

### Файл с картинками стал тяжелее ожидаемого — что делать?

Каждая вставка копирует картинку целиком в xl/media без дедупликации, поэтому оригиналы по мегабайту утяжеляют файл на каждый экземпляр. Готовьте миниатюры заранее и вставляйте их; если картинка приходит из памяти, берите AddPictureFromBytes вместо временных файлов.
