У стилей из прошлых уроков есть слепая зона: они красят ячейки, но не двигают их. А почти каждый настоящий отчёт требует геометрии: шапка «Итоги за II квартал» растягивается над тремя колонками, длинное наименование не помещается в ячейку шириной восемь символов, строка заголовка сжимает крупный шрифт в узкую полоску. Это три отдельные ручки листа — объединение ячеек, ширина столбцов и высота строк. В отличие от стилей, они применяются не через идентификаторы, а прямыми вызовами на файле: MergeCell, SetColWidth и SetRowHeight. Объединения работают в обе стороны: шапку тянут по горизонтали над колонками, а вертикальные блоки — в декоративных зонах вроде боковика с названием раздела, хотя слияния внутри колонок данных, как увидим ниже, удовольствие сомнительное. Порядок работы свободный, но в отчётах ручки обычно проходят сверху вниз: сначала собирают шапку с объединениями, потом расставляют ширины под данные, в конце подгоняют высоты. И стили из прошлых уроков пригодятся сразу: объединённый блок красится тем же SetCellStyle, только диапазон теперь совпадает с областью слияния — на этом правиле здесь будет отдельная врезка.
MergeCell: excelize mergecell собирает один блок#
Метод f.MergeCell принимает лист и две ячейки: верхнюю-левую и нижнюю-правую будущего блока — и помечает прямоугольник как один. Вызов f.MergeCell("Отчёт", "A1", "D1") растягивает первую строку на четыре колонки, а тот же метод с координатами A10 и A20 соберёт вертикальный блок из одиннадцати строк — так оформляют боковики и зоны-разделители. Значение живёт в верхней-левой ячейке: Excel рисует его по всей площади блока, а физически остальные ячейки пусты — пишите значение до слияния или после, лишь бы по координате угла. Повторное слияние того же диапазона excelize отклонит ошибкой, как и пересечение с уже объединённым блоком: карта слияний хранится в файле, и библиотека проверяет её перед записью. Снимается слияние зеркально: UnmergeCell с теми же координатами — значение остаётся в углу, остальные ячейки снова становятся обычными. Важно понимать границы операции: слияние не склеивает тексты и не суммирует числа, это про геометрию, а не про данные. Для аудита есть GetMergeCells: вернёт список блоков листа с начальной и конечной координатами, и чужой файл разумно просматривать именно с этой карты.
Шапка на четыре колонки
GOf.SetCellValue("Отчёт", "A1", "Отчёт за второй квартал")
if err := f.MergeCell("Отчёт", "A1", "D1"); err != nil {
panic(err)
}
header, err := f.NewStyle(&excelize.Style{
Font: &excelize.Font{Bold: true, Size: 13},
Alignment: &excelize.Alignment{
Horizontal: "center",
Vertical: "center",
},
})
if err != nil {
panic(err)
}
if err := f.SetCellStyle("Отчёт", "A1", "D1", header); err != nil {
panic(err)
}Значение пишется в верхнюю-левую ячейку, слияние накрывает прямоугольник, стиль прикладывается тем же прямоугольником: выравнивание центрует содержимое блока, а заливка и рамки из прошлых уроков лягут на каждую ячейку. Примените стиль только к A1 — и покрашется один угол шапки.
Стиль объединённой шапки прикладывайте тем же прямоугольником, что и слияние: заливка, границы и выравнивание лежат на каждой ячейке блока отдельно. Покрасили только A1 — шапка оказалась наполовину синей, а рамка обрамила один угол. Правило одной строкой: диапазон SetCellStyle совпадает с диапазоном MergeCell.
Чтение файла со слияниями#
Плата за красивую шапку приходит при чтении собственного файла. GetRows вернёт текст в первой ячейке блока и пустые строки в остальных: построчный парсер увидит строку, где три ячейки пусты, и решит, что данные кончились. GetCellValue("C1") вернёт пустую строку, хотя на экране Excel показывает заголовок по всей площади блока. Отсюда правило разделения труда: слияния — для декоративных зон, заголовков, подписей и периодов; данные живут по одной ячейке на значение. Шапку объединить можно и нужно, колонку с ценами — не стоит: импорт из урока про чтение ячеек сломается на ровном месте, а поиск причины затянется на вечер. Вертикальные слияния в данных мешают сильнее горизонтальных: колонка категорий, слитая на десять строк, в GetRows выглядит как одна заполненная и девять пустых, и группировка по ней соберёт мусор. Если файлы со слияниями приходят со стороны, первым делом постройте карту блоков через GetMergeCells — парсеру она нужнее самих строк, потому что отличает честные пустые ячейки от пустых внутри объединения.
SetColWidth: ширина столбцов excelize в символах#
Метод f.SetColWidth принимает лист, начальную и конечную колонку и ширину — один вызов покрывает диапазон: SetColWidth("Отчёт", "B", "D", 14) задаст ширину трём колонкам сразу, для одной начало и конец совпадают. Единица — не пиксель: ширина столбцов excelize измеряет в символах шрифта по умолчанию, точнее в ширине цифры ноль базового шрифта, поэтому 14 на Calibri и на другом шрифте занимают разное место. Предел — 255 символов, а колонка без явной ширины узкая, около 8.43. Значение пишется в файл и рисуется как есть: библиотека не измеряет содержимое, а в xlsx нет понятия «ширина текста» до открытия файла в Excel. Отсюда и отсутствие автоподбора из коробки: команда «автоширина» живёт в Excel и пересчитывает ширину по факту отображения. В генераторах автоподбор эмулируют: посчитать максимум длины строки в колонке и выставить SetColWidth с запасом — приём в коде ниже.
Автоширина по содержимому
GOrows, err := f.GetRows("Отчёт")
if err != nil {
panic(err)
}
const cols = 4
for i := 0; i < cols; i++ {
widest := 8.0
for _, row := range rows {
if i < len(row) {
if l := float64(len([]rune(row[i]))); l > widest {
widest = l
}
}
}
col, _ := excelize.ColumnNumberToName(i + 1)
f.SetColWidth("Отчёт", col, col, widest*1.1+2)
}Максимум длины строки в колонке считается в рунах: русские буквы занимают два байта в UTF-8, и подсчёт по байтам раздул бы колонку вдвое. Константа 8.0 держит нижнюю границу на уровне дефолта, множитель 1.1 и плюс два символа дают запас под шрифт. Считайте по отображаемым значениям: серийный номер даты короче строки 15.06.2024, которая видна на экране.
Методы размеров одним взглядом#
| Вызов | Что делает | Единицы |
|---|---|---|
| f.MergeCell("Отчёт", "A1", "D1") | объединяет прямоугольник в один блок | ячейки |
| f.UnmergeCell("Отчёт", "A1", "D1") | снимает слияние по тем же координатам | ячейки |
| f.SetColWidth("Отчёт", "B", "D", 14) | ширина колонок диапазоном | символы шрифта |
| f.GetColWidth("Отчёт", "B") | текущая ширина колонки | символы шрифта |
| f.SetRowHeight("Отчёт", 1, 26) | высота строки | пункты |
| f.GetRowHeight("Отчёт", 2) | текущая высота строки | пункты |
Высота строк и решётки вместо чисел#
Высота задаётся SetRowHeight в пунктах: по умолчанию строка около 15 пунктов, шапке с тринадцатым шрифтом ставят 22–26, иначе верхушки букв упираются в границу. С переносом текста из урока про стили есть нюанс: Excel растит строку под переносимый текст сам, но только пока высота не задана вручную — после SetRowHeight автоподбор для этой строки отключается, и длинный текст обрезается. Числа ведут себя иначе текста: когда колонке не хватает ширины, Excel не обрезает значение и не лезет на соседей, а рисует решётки ##### — страдают деньги и даты первыми, у текста есть выход на пустую соседку. Датам формата DD.MM.YYYY из урока про форматы чисел и дат нужно десять символов, а колонка по умолчанию — около 8.43: вот и решётки на первой же выгрузке. Лечение одно: ширину считает генератор по отображаемым значениям, а не надежда, что кто-то потянет границу колонки в Excel.
GetMergeCells("Отчёт") возвращает список объединённых блоков, у каждого доступны координаты начала и конца. Скрипт, разбирающий чужие файлы, сначала строит карту блоков, потом читает строки: без неё объединённая шапка выглядит как строка с тремя пустыми ячейками и одним полным углом, и логика парсера от неё ломается.
Чек-лист размеров#
- MergeCell — прямоугольник в один блок: значение живёт в верхней-левой ячейке.
- Стиль блока прикладывайте на весь диапазон слияния, а не на угол.
- GetRows под слиянием видит пустые ячейки: данные держите без объединений.
- SetColWidth — ширина в символах шрифта: от и до, предел 255.
- SetRowHeight — высота в пунктах: шапке 22–26, данным по умолчанию.
- Решётки ##### — числу не хватило ширины: ширину считает генератор.
MergeCell и SetColWidth требуют книги на диске, поэтому в браузерной песочнице не запускаются: там доступны только fmt, strings, strconv, math, sort, errors и time без файлового ввода-вывода. Ядро автоширины в песочнице потренировать можно: посчитайте максимум длины строки в срезе срезов в рунах — логика та же, что в коде урока, а файл с шапкой соберите локально.
Кейс про решётки на фото экрана. Руководителю прислали квартальный отчёт, он открыл его и отправил назад скриншот: колонка дат вся в решётках, колонка денег — тоже. Причина считалась на пальцах: даты писались time.Time со стилем DD.MM.YYYY, отображаемая строка 15.06.2024 — десять символов, ширина колонки — дефолтные 8.43. Ширину посчитал генератор: максимум по отображаемым значениям каждой колонки, множитель 1.1 и два символа запаса; деньгам с рублём досталось 14, датам 12. Заголовок заодно объединили в один блок и подняли шапке высоту до 26. В команду ушло правило: файл открывается готовым, границу колонки в Excel никто не тянет. Ширины вынесли в константы рядом с описанием колонок отчёта: данные и их размеры живут в одном месте, и новая колонка добавляется одним блоком, а не правкой в двух концах файла. Спорная сторона: автоширина по максимуму раздувает колонку из-за одного выброса на двести строк; там, где выбросы ожидаемы, максимум отбрасывают и включают перенос текста — решение по данным, а не по вкусу.
Проверка: где живёт значение блока
После f.MergeCell("Отчёт", "A1", "D1") где окажется значение ячейки A1?
Проверка: ширина диапазоном
Какой вызов задаст ширину колонок B, C и D одной строкой?
Что вернёт чтение из блока?
Прочитайте код и выберите, что он выведет:
f.SetCellValue("Sheet1", "A1", "Отчёт за квартал")
f.MergeCell("Sheet1", "A1", "D1")
val, _ := f.GetCellValue("Sheet1", "C1")
fmt.Println(val)Соберите шапку по размеру
Допишите объединение блока, перевод номера колонки в букву, ширину и высоту.
Соберите шапку и её размеры
Расставьте строки в порядке выполнения: написать заголовок, объединить блок, создать стиль, проверить ошибку, применить стиль к блоку, задать ширину колонок.
Строки
Ваша программа
Нажимайте на строки слева, чтобы собрать программу
Карточки: слияния и размеры
Геометрия закрыта: шапка стоит блоком, колонки не жмут данные, высота строк подогнана. Дальше файл станет умнее: в уроке про формулы итоги посчитает сам Excel через SetCellFormula, а в уроке про условное форматирование колонка подсветит отрицательные остатки без единого нового стиля. Стили, границы и размеры из последних четырёх уроков складываются в готовый шаблон оформления — целиком он используется в экспорте отчёта из базы и в разборе типичных ошибок excelize. Если длина строки в рунах показалась тёмной темой, вернитесь к уроку про строки и руны базового курса. Домашнее задание — шапка блоком и ширина по содержимому.
Песочница урока
Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.
Запустите код, чтобы увидеть вывод.
Коротко: что запомнить
- MergeCell объединяет прямоугольник ячеек: значение остаётся в верхней-левой.
- Стиль слияния прикладывайте ко всему блоку, а не к углу.
- Чтение возвращает пустые строки для ячеек под слиянием: парсер должен знать карту блоков.
- SetColWidth задаёт ширину в символах шрифта: от и до, предел 255.
- SetRowHeight измеряет высоту в пунктах; ручная высота отключает автоподбор при переносе.
- Решётки ##### — числу не хватило ширины: ширину считает генератор по отображаемым значениям.
Домашнее задание
В своём отчёте объедините шапку листа в один блок на все колонки данных и отцентрируйте её, поднимите высоту строки до 26, а колонкам посчитайте ширину по максимуму отображаемой длины с множителем 1.1 и двумя символами запаса. Проверьте GetMergeCells, что блок один, и убедитесь, что ни одна числовая колонка не показывает решётки.
Личные заметкиПусто
Вопросы и ответы по уроку
Что вернёт GetCellValue для ячейки внутри слияния?
Пустую строку: значение хранится в верхней-левой ячейке блока, остальные Excel держит пустыми. На экране текст виден по всей площади, но чтение по отдельным ячейкам его не отдаёт — читайте угловую координату.
Почему после MergeCell шапка покрашена наполовину?
Стиль применили только к угловой ячейке: заливка и границы лежат на каждой ячейке блока отдельно. Прикладывайте стиль SetCellStyle на тот же прямоугольник, что и слияние, — тогда оформление накроет весь блок.
Есть ли в excelize автоподбор ширины, как в Excel?
Из коробки нет: в файле не хранится ширина содержимого, и библиотеке нечего измерять до открытия файла. Ширину считают при генерации — максимум длины отображаемых значений колонки, множитель 1.1 и пара символов запаса через SetColWidth.
Термины урока
Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.
Изучайте дальше
Следующая ступень учебного пути
Фоновые задачи в Go: планировщик на robfig/cron
Курс по cron в Go: robfig/cron v3, синтаксис выражений, пояса, wrappers, конкурентность и graceful shutdown. 25 уроков с примерами и проектом.
- Собирать планировщик на robfig/cron v3 и запускать задачи по расписанию
- Читать и писать cron-выражения: пять полей, спецсимволы, @daily
- Управлять жизненным циклом: Start, Stop, Entry, Remove
- Держать часовые пояса и секундные расписания под контролем