Найти в Дзене

[Python] Создание и наполнение XLSB с помощью pywin32

С помощью библиотеки pywin32 попробуем создать и наполнить XLSB файл. Сделаем так, чтобы основной класс вызывался через оператор with За пределами статьи: В конце статьи есть ссылка в GitLab на финальную версию программы. ОС: Windows 10 Язык: Python 3.12 Основные библиотеки: pywin32 Прочее: Microsoft Office 2013 Создадим папку "XLSB_CREATOR", куда будем клонировать репозиторий mkdir XLSB_CREATOR Клонируем репозиторий git clone https://gitlab.com/pytechnotes1/xlsb_creator XLSB_CREATOR Заходим в папку cd XLSB_CREATOR/ Делаем чекаут версии коммита, который я сделал специально для статьи git checkout 8485adfbc6d6a04369068eb243b85843204f265b Открываем в cmd наш проект XLSB_CREATOR и создать виртуальную среду py -3.12 -m venv venv Активируем среду venv\Scripts\activate Производим установку библиотек из файла, который я подготовил заранее pip install -r requirements.txt Выходим из виртуальной среды deactivate Архитектуру сделаем без излишеств, всего будет четыре скрипта: Первым делом из
Оглавление

Введение

С помощью библиотеки pywin32 попробуем создать и наполнить XLSB файл. Сделаем так, чтобы основной класс вызывался через оператор with

За пределами статьи:

  • заранее были подготовлены файлы для работы с виртуальной средой. О том, как их подготавливать, описываю в отдельной статье: https://dzen.ru/a/aEKVHTM_GULyazKa
  • стартовые исходники для статьи лежат в GitLab. В рамках статьи не объясняется, как устанавливать и настраивать git. Всё это описываю в отдельной статье: https://dzen.ru/a/aGgSbU4TnF-_7wL_
  • должен быть установлен Excel от версии 2007 и старше

В конце статьи есть ссылка в GitLab на финальную версию программы.

Используемые технологии

ОС: Windows 10

Язык: Python 3.12

Основные библиотеки: pywin32

Прочее: Microsoft Office 2013

План работы

  • Клонируем репозиторий с GitLab
  • Настраиваем виртуальную среду
  • Планируем архитектуру программы
  • Создаём программу
  • Запускаем программу

Клонируем репозиторий с GitLab

Создадим папку "XLSB_CREATOR", куда будем клонировать репозиторий

mkdir XLSB_CREATOR

Клонируем репозиторий

git clone https://gitlab.com/pytechnotes1/xlsb_creator XLSB_CREATOR

Заходим в папку

cd XLSB_CREATOR/

Делаем чекаут версии коммита, который я сделал специально для статьи

git checkout 8485adfbc6d6a04369068eb243b85843204f265b

Настраиваем виртуальную среду

Открываем в cmd наш проект XLSB_CREATOR и создать виртуальную среду

py -3.12 -m venv venv

Активируем среду

venv\Scripts\activate

Производим установку библиотек из файла, который я подготовил заранее

pip install -r requirements.txt

Выходим из виртуальной среды

deactivate

Планируем архитектуру программы

Архитектуру сделаем без излишеств, всего будет четыре скрипта:

  • app.py - скрипт, который будет запускать нашу программу.
  • creator.py - основная программа, которая будет создавать xlsb файл
  • copier.py - функционал, который не связан напрямую с манипуляциями с xlsb файлом, выведен в отдельный скрипт
  • creator_format.py - как такового конфигурационного файла в программе нет, но был создан скрипт, который является неким контейнером входящих параметров программы.

Создаём программу

Первым делом изучим файл app.py.

файл app.py
файл app.py

В файле ничего менять не будем.

В 1 строке указываем шебанг, в котором указывается путь до интерпретатора в виртуальной среде.

В 7 и 8 строках указываем путь к будущему XLSB файлу, а так как программа будет напрямую обращаться к библиотеке Excel, которая не знает, в какой директории запущена программа на Python, необходимо указать полный путь до XLSB файла, который будем создавать. В рамках теста эксель файл будет создаваться в той же директории, где расположен файл app.py.

На 9 строке указываем размерность начальной строки для записи. Первая ячейка будет (1, 1), т.е. "A1", последняя ячейка будет (1, 3), т.е. "A3".

С 10 по 15 строку тестовый набор данных. Программа сделана максимально просто, чтоб можно было легко ее переделать под себя, например для работы с библиотекой pandas.

На 17 строке вызываем нашу программу, применяя оператор with. В терминологии Python это называется "вызов менеджера контекста".

С 18 по 20 строки производим построчную запись в файл.

Начнем реализацию с файла creator_format.py

В этом файле реализуем 2 небольших класса:

  • RangeData - будет хранить координаты диапазона ячеек
  • XLConfig - будет хранить параметры XLSB файла

Для реализации нам понадобится библиотека dataclasses

from dataclasses import dataclass

Классам мы присваиваем декоратор @dataclass

Для класса XLConfig в декоратор передаем дополнительный параметр frozen=True, таким образом класс XLConfig станет неизменяемым.

Класс RangeData нам нужен изменяемым, т.к. диапазон ячеек будет постоянно меняться.

файл creator_format.py после редактирования
файл creator_format.py после редактирования

По параметрам RangeData - это просто координаты начальной и конечной ячеек строки, которая будет заполняться данными.

Касательно параметров XLConfig:

  • file_path - полный путь к XLSB файлу
  • visible_flag - (Application.Visible) - Если указать False, то все создание и заполнение файла будет происходить в фоновом режиме, но есть шанс, что что-то пойдет не так и процесс Excel не завершится и останется висеть в активных процессах в диспетчере задач. Если поставить True и что-то пойдет не так, то процесс не завершится, но мы будем видеть окно Excel открытым.
  • screen_update_flag - (Application.ScreenUpdating) - Если указать False, то программа будет работать быстрее, но мы не увидим магии заполнения экселя:)
  • ac_sheet - программа умеет работать только с Sheet(1)
  • file_format - Для создания XLSB файла необходимо указать значение: 50

Теперь откроем файл creator.py

В файле частично намечена архитектура класса XLSBCreator.

файл creator.py до редактирования
файл creator.py до редактирования

Из архитектуры видно, что:

  • будет только один внешний метод set_row
  • есть методы __enter__ и __exit__ , реализовав которые, XLSBCreator станет менеджером контекста и сможет вызываться через оператор with

Первым делом начнем заполнять конструктор __init__:

-5

В момент создания экземпляра класса XLSBCreator будут созданы:

  • self.conf - конфиг с параметрами для создания Excel файла
  • self.range - диапазон ячеек экселя в формате конструкций языка Python
  • self.target_range - объект Range библиотеки Excel

Укажем импорт классов, которые создали ранее

from creator_format import RangeData, XLConfig

Реализуем метод __enter__:

-6

В рамках метода вызовем класс Copier (его реализуем позже) , а также выполним ряд действий для создания эксель файла.

Если по причине COM-ошибки произойдет падение создания файла, то вызовется метод __exit__.

Укажем необходимые импорты

import sys
from typing import Self
from pywintypes import com_error
from copier import Copier

Реализуем методы _create_new_app, _create_new_wb и _activate_sheet:

-7

Создание эксель файла и манипуляции с ним происходит с помощью библиотеки Excel, т.е. если бы создавали эксель файл с помощью VBA, мы бы обращались бы к той же библиотеке, к тем же объектам и функциям с теми же параметрами.

Для удобства манипуляции с объектами эксель, добавляем их в переменные класса: self.xl_app , self.xl_wb , self._xl_sheet

По умолчанию программа работает только с первым листом в эксель файле.

Добавляем в импорт внешнюю библиотеку

import win32com.client

Реализуем метод __exit__:

-8

В задачу данного метода входит:

  • сохранить и закрыть эксель файл
  • в случае COM-ошибки, просто закрыть приложение, иначе в диспетчере задач будут висеть и накапливаться незакрытые процессы MS Excel

В дополнение к COM-ошибкам еще можно обработать прочие ошибки, но я не стал этого делать

Реализуем метод set_row:

-9

Метод принимает на вход list, где лежат данные для заполнения одной строки. Далее метод получает координаты для объекта Range и создает этот объект. После диапазон ячеек, на который ссылается объект Range, заполняется данными, которые поступили методу на вход. И в конце метод определяет следующие координаты ячеек.

Реализуем методы _get_cells_for_range и _next_cells:

-10

Метод _get_cells_for_range создает объекты Cells, которые потом будут использоваться для создания объекта Range.

Метод _next_cells смещает координаты ячеек на 1 строку вниз.

Теперь перейдем к файлу copier.py

В файле намечена архитектура класса Copier.

файл copier.py до редактирования
файл copier.py до редактирования

В задачу класса будет входить 2 задачи:

  • проверить, существует ли файл, который планируется создать с помощью класса XLSBCreator
  • и если существует такой файл, то переименовать его с указанием даты последней модификации файла

Из архитектуры видим, что все методы у класса являются методами класса. Можно было бы сделать все методы статическими, но при написании логики класса мне показалось это менее удобным.

Сразу укажем библиотеки, которые нам понадобятся

from datetime import datetime as dt
from pathlib import Path

Касательно библиотеки pathlib, то выбор на нее пал, так как её богатый функционал лучше подошел к задаче, чем функционал более привычной библиотеки os.

Начнем с реализации методов run и _check_file:

-12

В рамках этих двух методов прекрасно показывается функционал класса, мы просто проверяем, существует ли файл по пути, который будет использовать XLSBCreator, и если существует, то вызываем _rename_exist_file.

Реализуем методы _rename_exist_file, _get_file_time и _get_new_file_name:

-13

В рамках метода _get_file_time мы берем последнюю дату модификации файла. Вообще, это не очень надежный параметр, т.к. если зайти в файл и нажать кнопку Сохранить, то дата модификации изменится, хотя мы в файле ничего не меняли. Но для текущей задачи нам это неважно.

В рамках метода _get_new_file_name мы формируем новое название файла.

В рамках метода _rename_exist_file мы производим переименование файла.

На этом все, можем запускать программу.

Запускаем программу

Запускаем скрипт через "py", таким образом запустится интерпретатор из виртуальной среды.

py app.py

Поздравляю, файл создался и заполнился данными.

test.xlsb
test.xlsb

Исходники проекта

PyTechNotes / XLSB_CREATOR · GitLab

Подписывайтесь на Дзен, а также приглашаю в мой телеграмм канал, там публикую другой, но не менее интересный контент.