Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 3 из 25 ~16 мин +20 XP

Листы книги: NewSheet, навигация и удаление

NewSheet в excelize — первый шаг от черновика с Sheet1 к книге, которую приятно открывать: листы Отчёт, Детализация и Справочник вместо безликой вкладки по умолчанию. В этом уроке разберём excelize листы со всех сторон: создание с индексами, активную вкладку, навигацию через GetSheetName и GetSheetMap, переименование, копирование и удаление — плюс ограничения имён, о которых Excel расскажет только в диалоге ошибки.

Содержание урока · 9 разделов

Откройте файл из прошлого урока: в книге ровно один лист с именем Sheet1, и выглядит это как черновик, а не как готовый продукт. Бизнес ждёт структуру: сводка на первой вкладке, детализация по дням на второй, справочники и примечания в конце. Заодно вспомним, что листы — это не просто вкладки для красоты: на них ссылаются формулы, диаграммы и настройки печати, а порядок вкладок определяет, что первым увидит человек, который файл откроет. В excelize весь этот слой закрывается горсткой методов дескриптора File — создание, активация, навигация, переименование, копирование, удаление — и все они следуют одной схеме: работа с листами идёт по именам и индексам, и путаница между ними источник половины ошибок новичков. В этом уроке разложим оба измерения по полочкам: где API ждёт имя, где индекс, что возвращает NewSheet в актуальных версиях и почему удаление листа — операция с последствиями, а не с кнопкой undo.

NewSheet: новый лист и его индекс#

newsheet excelize-вызов выглядит так: f.NewSheet("Отчёт") — и в актуальных версиях v2 возвращает пару значений: индекс нового листа и ошибку. Индекс — это позиция листа в книге, нумерация начинается с единицы: свежая книга имеет Sheet1 с индексом 1, и первый же NewSheet получит индекс 2. Ошибка возвращается, когда имя невалидно — пустая строка, запрещённые символы или дубликат существующего листа; в старых туториалах сигнатура без ошибки, поэтому код из статей пятилетней давности не скомпилируется — та же история, что с путями импорта, только здесь меняется число возвращаемых значений. Порядок вкладок в файле соответствует порядку создания: кто первым сделал NewSheet, тот раньше в списке. Переставлять вкладки руками excelize не даёт — если порядок важен, создавайте листы в нужной последовательности или переименовывайте существующие, а не плодите новые. И запомните: NewSheet не делает лист активным — открытие файла покажет ту вкладку, которую вы назначили активной отдельно, о чём дальше.

Книга с тремя листами

GO
f := excelize.NewFile()
defer f.Close()

for _, name := range []string{"Отчёт", "Детализация", "Справочник"} {
    if _, err := f.NewSheet(name); err != nil {
        panic(err)
    }
}

if err := f.SaveAs("workbook.xlsx"); err != nil {
    panic(err)
}

NewSheet в цикле создаёт три листа после дефолтного Sheet1: Отчёт получит индекс 2, Детализация — 3, Справочник — 4. Индексы из цикла не сохраняем — они нужны только там, где вы дальше работаете по ним. Ошибку проверяем честно: дубликат имени или запрещённые символы здесь не прощаются. Файл откроется на Sheet1 — активным листом мы его пока не меняли.

SetActiveSheet: какая вкладка откроется первой#

Активный лист — это вкладка, которую Excel покажет при открытии файла, и управляется он парой методов: f.SetActiveSheet(index) назначает, f.GetActiveSheetIndex() возвращает текущий индекс. Логика для отчётов простая и почти всегда одна: открываем то, ради чего файл генерировался. Сводка для директора — активной становится вкладка со сводкой, а не технический первый лист, на котором по инерции лежали данные для расчётов. Активный лист — не вопрос вкуса, а вопрос обслуживания: файл, который открывается на правильной вкладке, экономит каждому читателю пару кликов и вопрос в чат «а где смотреть». Практический нюанс: SetActiveSheet принимает именно индекс — то самое число из NewSheet, поэтому в реальном коде возвращаемое значение сохраняют в переменную и передают дальше. Если лист с индексом отсутствует, метод молча ничего не изменит: ошибки не будет, но и эффекта тоже — ещё одна причина хранить индексы осознанно, а не пересчитывать на пальцах. И раз уж называли листы русскими словами — так и оставляйте: имена вкладок кодируются в XML в UTF-8, и Отчёт откроется так же корректно, как Report.

Навигация: GetSheetName и GetSheetMap#

Навигация по книге строится на двух чтениях. f.GetSheetName(index) возвращает имя листа по индексу: единица — первый лист книги, и для невалидного индекса метод вернёт пустую строку, не паникуя. Обратное преобразование тоже нужно, но здесь аккуратнее: метод GetSheetIndex существует, однако его поведение на отсутствующих именах менялось между версиями, поэтому в новом коде я предпочитаю явный проход по f.GetSheetMap() — карте индекс-имя, по которой видно всю книгу целиком. Итерируясь по GetSheetMap, вы за один вызов получаете и количество листов, и их названия с индексами — этого хватает и для проверки, что файл сгенерировался с правильной структурой, и для поиска листа с нужным именем перед чтением данных. Такие проходы удобно оставлять в тестах генерации: структура файла — тоже контракт, и она должна проверяться, а не доверяться памяти. Запомните асимметрию: имя по индексу — тривиально, индекс по имени — с оговорками по версиям, поэтому архитектура кода, которая держит индексы из NewSheet в переменных, надёжнее архитектуры, которая ищет их обратно по строкам в рантайме.

Аптечка методов для листов#

  • NewSheet(имя) — создаёт лист, возвращает индекс и ошибку (актуальные версии v2).
  • SetActiveSheet(индекс) — назначает вкладку, которая откроется первой.
  • GetActiveSheetIndex() — возвращает индекс активного листа.
  • GetSheetName(индекс) — имя листа по индексу, пустая строка для невалидного индекса.
  • GetSheetMap() — карта индекс-имя по всей книге: структура одним вызовом.
  • RenameSheet(старое, новое) — переименование по именам.
  • CopySheet(источник, цель) — копирование по индексам.
  • DeleteSheet(имя) — удаление по имени, без undo и с эффектом #REF! в формулах.

Переименование, копирование и чтение карты

GO
f := excelize.NewFile()
defer f.Close()

f.SetCellValue("Sheet1", "A1", "Итог за квартал")

if err := f.RenameSheet("Sheet1", "Сводка"); err != nil {
    panic(err)
}

draft, err := f.NewSheet("Шаблон")
if err != nil {
    panic(err)
}

if err := f.CopySheet(1, draft); err != nil {
    panic(err)
}

for index, name := range f.GetSheetMap() {
    fmt.Println(index, name)
}

RenameSheet работает по именам: Sheet1 становится Сводкой, индекс при этом не меняется. CopySheet копирует содержимое листа с индекса 1 на существующий лист Шаблон — цель обязана существовать, поэтому сначала NewSheet. Обратите внимание на честную оговорку документации: картинки и диаграммы при копировании не переносятся, только данные, формулы и оформление ячеек. GetSheetMap в конце печатает структуру книги для проверки.

Ограничения имён листов и порядок вкладок#

Excel накладывает ограничения на имена листов, и excelize транслирует их в ошибки NewSheet и RenameSheet: имя короче 32 символов, то есть максимум 31; запрещены двоеточие, обратный и обычный слэш, вопросительный знак, звёздочка и квадратные скобки; нельзя пустое имя и нельзя History — резервное имя для журнала изменений общих книг. Звучит как список для зубрёжки, но всплывает ровно в двух местах: когда вы генерируете вкладки с датами вроде 2024/06 — слэш сломает создание, и когда названия приходят из пользовательских данных, где звёздочка встречается свободно. Санитизируйте имена одним местом в коде: функция, заменяющая запрещённые символы на дефис и обрезающая до 31 символа, стоит пять строк и экономит вечер отладки. Порядок вкладок при этом — порядок создания, и переименование его не меняет: Сводка останется на своей позиции, как ни назови. Поэтому последовательность NewSheet-вызовов — это и есть дизайн файла, и относиться к ней стоит как к части контракта отчёта.

Методы листов: сигнатуры и правила#

МетодСигнатураЧто важно помнить
NewSheet(имя string) (int, error)индексы с единицы; ошибка на дубликате и запрещённых символах
SetActiveSheet(индекс int)не делает лист активным автоматически при создании
GetSheetName(индекс int) stringпустая строка для невалидного индекса
GetSheetMap() map[int]stringвся книга одним вызовом: индексы и имена
CopySheet(источник, цель int) errorцель должна существовать; картинки и диаграммы не копируются
DeleteSheet(имя string) errorпо имени; формулы-ссылки превращаются в #REF!

Кейс, который делает эти методы неакадемическими. Сервис генерировал ежемесячные отчёты: каждый месяц новый файл с листом на месяц, а через год накопилась книга-архив, где двенадцать почти одинаковых листов — сводка, детализация, методология. Ручная сборка такого файла — час монотонной работы и постоянные опечатки, поэтому её автоматизировали так: шаблонный лист со стилями и итоговыми формулами создаётся один раз, и на каждый месяц CopySheet копирует его под новым именем, после чего код заполняет ячейки данными периода. Отдельно приятная деталь: активным делается лист текущего месяца — бухгалтер открывает файл и сразу видит свежую вкладку, а не январь. Единственная ловушка, которая проявилась в продакшене: в шаблоне была логотип-картинка, и CopySheet её не перенёс — картинки в новый лист пришлось добавлять отдельно, потому что копирование, как сказано в документации, про данные и оформление, а не про рисунки. Прежде чем строить такую схему, проверьте свой шаблон: диаграммы и изображения не переживут копирование.

Проверка: NewSheet

Что возвращает f.NewSheet("Отчёт") в актуальных версиях excelize v2?

Проверка: удаление листа

Какой параметр принимает f.DeleteSheet?

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

Прочитайте код и выберите, что он выведет:

f := excelize.NewFile()

f.NewSheet("Отчёт")

name := f.GetSheetName(1)

fmt.Println(name)

Создайте и активируйте лист

Допишите создание листа с проверкой ошибки и его активацию.

idx, err := f.("Отчёт") if err != nil { panic(err) } f.(idx)

Соберите работу с листом

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

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: листы книги

Термин

NewSheet

нажмите, чтобы перевернуть
Определение

Создаёт лист, возвращает индекс и ошибку. Индексы с единицы: Sheet1 — первый. Ошибка на дубликате и запрещённых символах.

1 / 6

Структура книги теперь в ваших руках: NewSheet создаёт вкладки с индексами, SetActiveSheet решает, что увидит читатель первым, GetSheetMap показывает всю книгу, а RenameSheet и CopySheet превращают ручную сборку отчётов в цикл. Дальше — данные: в уроке про запись ячеек разберём SetCellValue и типы значений, которые excelize кладёт в xlsx, включая ловушку длинных номеров, а затем научимся читать чужие файлы через GetCellValue в уроке про чтение ячеек. Защита готовых вкладок от случайных правок — отдельная тема: ProtectSheet с паролем рассматривается ближе к середине курса. Если план на будущее — отчётная система с вкладками и диаграммами, гляньте заранее итоговый проект, куда все эти методы соберутся вместе. Домашнее задание — собрать книгу из трёх листов с осмысленными именами.

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

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

  • NewSheet возвращает индекс и ошибку; индексы листов начинаются с единицы.
  • SetActiveSheet назначает вкладку, которую Excel откроет первой, — обычно сводку, а не технический лист.
  • Навигация: GetSheetName по индексу, GetSheetMap для структуры всей книги.
  • RenameSheet и DeleteSheet работают по именам, CopySheet — по индексам существующих листов.
  • CopySheet не переносит картинки и диаграммы — их добавляют отдельно.
  • Имена листов: до 31 символа, без : \ / ? * [ ], имя History запрещено.

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

Соберите программу, которая создаёт книгу с четырьмя листами: переименуйте Sheet1 в Сводка, добавьте Детализация и Справочник через NewSheet, сделайте Сводку активной и сохраните файл. Распакуйте workbook.xlsx и проверьте по xl/workbook.xml, что порядок вкладок соответствует порядку создания.

Личные заметкиПусто
Хранятся только в вашем браузере (Excelize · Листы книги: NewSheet, навигация и удаление)

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

Как переставить листы в нужном порядке?

Прямого метода перемещения вкладок excelize не предоставляет — порядок соответствует порядку создания. Планируйте последовательность NewSheet-вызовов под желаемую структуру или создавайте листы заранее в нужном порядке и заполняйте позже; переименование существующих листов порядок не меняет.

Что будет, если создать лист с существующим именем?

В актуальных версиях NewSheet вернёт ошибку — дубликаты имён запрещены на уровне формата Excel. Обрабатывайте её явно: попытка молча проигнорировать ошибку приведёт к книге без ожидаемого листа и заполнению данных в несуществующий дескриптор.

Почему CopySheet не скопировал диаграмму и логотип?

Так задокументировано: копируются данные, формулы и оформление ячеек, а изображения, диаграммы и рисунки — нет. Схема «шаблон плюс копии» работает, если графику добавляют в каждую копию отдельно через AddPicture и AddChart.

Термины курса

Понятия, на которых строится этот курс, — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылок на практику.

Следующая ступень учебного пути

Cron25 уроков~9 чпрактика25 уроков уже доступны

Фоновые задачи в Go: планировщик на robfig/cron

Курс по cron в Go: robfig/cron v3, синтаксис выражений, пояса, wrappers, конкурентность и graceful shutdown. 25 уроков с примерами и проектом.

  • Собирать планировщик на robfig/cron v3 и запускать задачи по расписанию
  • Читать и писать cron-выражения: пять полей, спецсимволы, @daily
  • Управлять жизненным циклом: Start, Stop, Entry, Remove
  • Держать часовые пояса и секундные расписания под контролем