Pywin32 работа с excel

Введение

Python имеет множество возможностей для создания стандартных типов файлов Microsoft Office, включая Excel, Word и PowerPoint. Однако в некоторых случаях может оказаться слишком сложно использовать чистый подход Python для решения проблемы. К счастью, для python есть пакет “Python for Windows Extensions” (Python для расширений Windows), известный как pywin32, который позволяет нам легко получить доступ к Component Object Model (COM), компонентной объектной модели Windows, и управлять приложениями Microsoft через python. В этой статье будут рассмотрены некоторые базовые сценарии использования этого типа автоматизации и рассказывается о том, как приступить к работе с некоторыми полезными скриптами.

С веб-сайта Microsoft о модели компонентных объектов (COM):

Платформенно-независимая распределенная объектно-ориентированная система для создания двоичных программных компонентов, которые могут взаимодействовать. COM является базовой технологией для технологий Microsoft OLE Automation (составные документы) и ActiveX (компоненты с доступом в Интернет). COM-объекты могут быть созданы с помощью множества языков программирования.

Эта технология позволяет нам управлять приложениями Windows из другой программы. Многие из читателей этого блога, вероятно, видели или использовали VBA для некоторой автоматизации задачи Excel. COM — это основополагающая технология, поддерживающая VBA.

pywin32

Пакет pywin32 существует уже очень давно. Фактически, книга, посвященная этой теме, была опубликована в 2000 году Марком Хаммондом и Энди Робинсоном. Несмотря на то, что с тех пор уже прошло много лет (что заставляет меня чувствовать себя действительно старым), лежащие в основе технологии и концепции работают и сегодня. Pywin32 — это, по сути, очень тонкая оболочка python, которая позволяет нам взаимодействовать с COM-объектами и автоматизировать приложения Windows с помощью python. Сила этого подхода заключается в том, что вы можете делать практически все, что может делать приложение Microsoft, через python. Обратной стороной является то, что вам придется запускать это в системе Windows с установленным Microsoft Office. Прежде чем мы рассмотрим несколько примеров, убедитесь, что в вашей системе установлен pywin32 с помощью pip или conda.

Еще одна рекомендация: держите под рукой ссылку на страницу Тима Голдена. На этом ресурсе есть еще много подробностей о том, как использовать python в Windows для автоматизации и других административных задач.

Начиная

Все наши приложения начинаются с одинакового импорта и процесса активации приложения. Вот очень короткий пример открытия Excel:

import win32com.client as win32
excel = win32.gencache.EnsureDispatch('Excel.Application')

excel.Visible = True
_ = input("Press ENTER to quit:")

excel.Application.Quit()

Как только вы запустите скрипт из командной строки, то должны увидеть, как открывается Excel. Когда вы нажмете ENTER, приложение закроется. Прежде чем мы действительно сделаем это приложение более полезным, необходимо изучить несколько ключевых концепций.

Первый шаг — импортировать клиента win32. Я использовал соглашение об импорте его как win32, чтобы сделать фактический код отправки немного короче.

Магия этого кода заключается в использовании EnsureDispatch для запуска Excel. В этом примере я использую gencache.EnsureDispatch для создания статического прокси. Я рекомендую прочитать эту статью, если вы хотите узнать больше о статических и динамических прокси. Мне посчастливилось использовать этот подход для примеров, включенных в эту статью, но буду честен — я не слишком много экспериментировал с различными подходами к диспетчеризации.

Теперь, когда объект excel запущен, нам нужно явно сделать его видимым, установив excel.Visible = TrueКод.

win32 довольно умен и закроет Excel после завершения работы программы. Это означает, что если мы просто оставим код работать самостоятельно, вы, вероятно, не увидите Excel. Я включаю фиктивную подсказку, чтобы Excel оставался видимым на экране, пока пользователь не нажмет ENTER.

Я включаю последнюю строку excel.Application.Quit(), как немного ремня и подтяжек. Строго говоря, win32 должен закрыть Excel, когда программа будет завершена, но я решил включить excel.Application.Quit(), чтобы показать, как принудительно закрыть приложение.

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

Открыть файл в Excel

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

Вот полный пример:

import win32com.client as win32
import pandas as pd
from pathlib import Path

# Read in the remote data file
df = pd.read_csv("https://github.com/chris1610/pbpython/blob/master/data/sample-sales-tax.csv?raw=True")

# Define the full path for the output file
out_file = Path.cwd() / "tax_summary.xlsx"

# Do some summary calcs
# In the real world, this would likely be much more involved
df_summary = df.groupby('category')['ext price', 'Tax amount'].sum()

# Save the file as Excel
df_summary.to_excel(out_file)

# Open up Excel and make it visible
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = True

# Open up the file
excel.Workbooks.Open(out_file)

# Wait before closing it
_ = input("Press enter to close Excel")
excel.Application.Quit()

Вот результат в Excel:

Этот простой пример расширяет предыдущий, показывая, как использовать объект Workbooks для открытия файла.

Прикрепите файл Excel к Outlook

Другой простой сценарий, в котором полезен COM, — это когда вы хотите прикрепить файл к электронному письму и отправить его в список рассылки. В этом примере показано, как выполнять некоторые манипуляции с данными, открывать электронную почту Outlook,прикрепите файл и оставьте его открытым для дополнительного текста перед отправкой.

Вот полный пример:

import win32com.client as win32
import pandas as pd
from pathlib import Path
from datetime import date


to_email = """
Lincoln, Abraham <>; 
"""

cc_email = """
Franklin, Benjamin <>
"""

# Read in the remote data file
df = pd.read_csv("https://github.com/chris1610/pbpython/blob/master/data/sample-sales-tax.csv?raw=True")

# Define the full path for the output file
out_file = Path.cwd() / "tax_summary.xlsx"

# Do some summary calcs
# In the real world, this would likely be much more involved
df_summary = df.groupby('category')['ext price', 'Tax amount'].sum()

# Save the file as Excel
df_summary.to_excel(out_file)

# Open up an outlook email
outlook = win32.gencache.EnsureDispatch('Outlook.Application')
new_mail = outlook.CreateItem(0)

# Label the subject
new_mail.Subject = "{:%m/%d} Report Update".format(date.today())

# Add the to and cc list
new_mail.To = to_email
new_mail.CC = cc_email

# Attach the file
attachment1 = out_file

# The file needs to be a string not a path object
new_mail.Attachments.Add(Source=str(attachment1))

# Display the email
new_mail.Display(True)

Этот пример немного усложняется, но основные концепции те же. Нам нужно создать наш объект (в данном случае Outlook) и создать новое электронное письмо. Одним из сложных аспектов работы с COM является отсутствие согласованного API. Создание такого электронного письма не является интуитивным: new_mail = outlook.CreateItem (0) Обычно требуется немного поисков, чтобы выяснить точный API для конкретной проблемы. Google и stackoverflow — ваши друзья.

После создания объекта электронной почты вы можете добавить получателя и список CC, а также прикрепить файл. Когда все сказано и сделано, это выглядит так:

Электронное письмо открыто, и вы можете добавить дополнительную информацию и отправить ее. В этом примере я решил не закрывать Outlook и позволить python обрабатывать эти детали.

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

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

Вот пример панели инструментов Excel, которую мы хотим создать:

Да, я знаю, что круговые диаграммы ужасны, но я могу почти гарантировать, что кто-то попросит вас поместить их на панель инструментов в какой-то момент! Кроме того, в этом шаблоне была круговая диаграмма, и я решил оставить ее в окончательном виде вместо того, чтобы пытаться вычислить другую диаграмму. Было бы полезно сделать шаг назад и посмотреть на основной процесс, которому будет следовать код:

Приступим к работе с кодом.

import win32com.client as win32
import pandas as pd
from pathlib import Path

# Read in the remote data file
df = pd.read_csv("https://github.com/chris1610/pbpython/blob/master/data/sample-sales-tax.csv?raw=True")

# Define the full path for the data file file
data_file = Path.cwd() / "sales_summary.xlsx"

# Define the full path for the final output file
save_file = Path.cwd() / "sales_dashboard.xlsx"

# Define the template file
template_file = Path.cwd() / "sample_dashboard_template.xlsx"

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

Далее выполняем анализ и сохраняем временный файл Excel:

# Do some summary calcs
# In the real world, this would likely be much more involved
df_summary = df.groupby('category')['quantity', 'ext price', 'Tax amount'].sum()

# Save the file as Excel
df_summary.to_excel(data_file, sheet_name="Data")

Теперь мы используем COM, чтобы объединить временный выходной файл с нашей вкладкой панели управления Excel и сохранить новую копию:

# Use com to copy the files around
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
excel.DisplayAlerts = False

# Template file
wb_template = excel.Workbooks.Open(template_file)

# Open up the data file
wb_data = excel.Workbooks.Open(data_file)

# Copy from the data file (select all data in A:D columns)
wb_data.Worksheets("Data").Range("A:D").Select()

# Paste into the template file
excel.Selection.Copy(Destination=wb_template.Worksheets("Data").Range("A1"))

# Must convert the path file object to a string for the save to work
wb_template.SaveAs(str(save_file))

Код открывает Excel и удостоверяется, что его не видно. Затем он открывает шаблон панели мониторинга и файлы данных. Он использует Range("A: D").Select() для выбора всех данных, а затем копирует их в файл шаблона.

Последний шаг — сохранить шаблон как новый файл. Этот подход может быть очень удобным ярлыком, когда у вас есть ситуация, когда вы хотите использовать python для обработки данных, но вам нужен сложный вывод Excel. Возможно, сейчас у вас нет явной потребности в этом, но если вы когда-нибудь создадите сложный отчет Excel, этот подход будет намного проще, чем пытаться вручную кодировать электронную таблицу с помощью python.

Заключение

Я предпочитаю стараться как можно больше придерживаться python для повседневного анализа данных. Однако важно знать, когда другие технологии могут упростить процесс или повысить эффективность результатов. Технология Microsoft COM является зрелой технологией, и ее можно эффективно использовать через Python для выполнения задач, которые в противном случае были бы слишком сложными. Надеюсь, эта статья дала вам несколько идей о том, как включить эту технику в свой рабочий процесс. Если у вас есть какие-либо задачи, для которых вы хотите использовать pywin32, сообщите нам об этом в комментариях.

По материалам Automating Windows Applications Using COM

Print Friendly, PDF & Email


#Для работы потребуется:
#Python for Windows Extensions — http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/
#.NET(я использовал 4.5) — http://www.microsoft.com/ru-ru/download/details.aspx?id=30653

#Импортируем библиотеку
import win32com.client

#Создаем COM объект
Excel = win32com.client.Dispatch(«Excel.Application»)

#Получаем доступ к активному листу
wb = Excel.Workbooks.Open(u’C:\python\script.xlsx’)
sheet = wb.ActiveSheet

#Получим значение ячейки A1 активного листа
val = sheet.Cells(1,1).value
print(val)

#Получим значения диапазона A1:A2 активного листа
vals = [r[0].value for r in sheet.Range(«A1:A2»)]
print(vals)

#Запишем новое значение в ячейку A3 активного листа
sheet.Cells(3,1).value = ‘A3Value’

#Сохраним
wb.Save()

#Получаем доступ к листу — Лист2 и диапазону ячеек
sheet2 = wb.Worksheets(u’Лист2′).Range(‘A1:A2’)

#Получим значения диапазона A1:A2 Лист2
vals = [r[0].value for r in sheet2]
print(vals)

#Закроем файл
wb.Close()

#Закроем COM объект
Excel.Quit()


Комментарии пользователей

Анонимам нельзя оставоять комментарии, зарегистрируйтесь!

Besides my regular job, I’m also a teaching assistant at the strategic planning course in my university. There, to evaluate the students, we give them a business scenario and an Excel file with a set of questions in a predefined template.

However, grading these files is really a hassle because you have to open one by one, adjust the zoom level and the size of the cells for a proper reading (even some students use LibreOffice and when you open the files in Excel the format goes all wonky).

In order to reduce all this process of grading files, I decided that I’ll use Python to extract all the information into a little report and with the help of another Excel file I’ll put the grades back in each of the student’s files.

Introduction

Python has many options for working with Excel files (pandas, openpyxL, xlsxwriter, etc). However, there is another option to work directly with the functionalites of Windows OS programs called “Python for Windows Extensions” also known as pywin32. With this package, you can easily access Window’s Component Object Model (COM) and control Microsoft applications via Python.

What is COM?

The Microsoft Component Object Model (COM) is a platform-independent, distributed, object-oriented system for creating binary software components that can interact. COM is the foundation technology for Microsoft’s OLE (compound documents), ActiveX (Internet-enabled components), as well as others that allows us to control Windows applications from another program.

With the use of this technology, pywin32 allows us to interact with COM objects and do almost anything that a Microsoft Application can do with some Python code.

Getting started

First, be sure that you have pywin32 installed in your computer. If not, you can easilly install it using pip:

Opening a file

In order to get the data from the Excel files, we need to open them. To do this, we need to activate the application and then make it open a file in a desired path:

import win32com.client

# Open up Excel and make it visible
excel = win32com.client.Dispatch('Excel.Application')
excel.Visible = True

# Select a file and open it
file = "path_of_file"
workbook = excel.Workbooks.Open(file)

# Wait before closing it
_ = input("Press enter to close Excel")
excel.Quit()

Once we opened a file, we are able to manipulate it and get all of its data to write it into our answers report.

Then, to extract the data of the Excel file and manipulate it to save it into a more readable format, we need to access each of the cells. In this case, since I have a predefined format, I will go directly into those cells and use a .txt file to put a summary of all the worksheets I need.

import win32com.client
import sys, io

# Open up Excel and make it visible (actually you don't need to make it visible)
excel = win32com.client.Dispatch('Excel.Application')
excel.Visible = True

# Redirect the stdout to a file
orig_stdout = sys.stdout
bk = io.open("Answers_Report.txt", mode="w", encoding="utf-8")
sys.stdout = bk

# Select a file and open it
file = "path_of_file"
wb_data = excel.Workbooks.Open(file)
  
# Get the answers to the Q1A and write them into the summary file
mission=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C6")
vision =wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C7")
print("Question 1A")
print("Mission:",mission)
print("Vision:" ,vision)
print()

# Get the answers to the Q1B and write them into the summary file
oe1=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C14")
ju1=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("D14")
oe2=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C15")
ju2=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("D15")
print("Question 1B")
print("OEN1:",oe1, "- JUSTIF:",ju1)
print("OEN2:",oe2, "- JUSTIF:",ju2)
print()
    
# Close the file without saving
wb_data.Close(True)

# Closing Excel and restoring the stdout
sys.stdout = orig_stdout
bk.close()
excel.Quit()

With this little code we are able to get all the desired data and write it into a .txt report with the answers of a student.

Repeating the process for multiple files

Then, I need to go through all the files of each student and make the summary and the grading template. For this, I will place all the files in a folder and then repeat the previous process for each one. Also, we need to create a new file for the grading template and write the path of each student file.

import win32com.client
import glob
import sys, io

# Open up Excel and make it visible (actually you don't need to make it visible)
excel = win32com.client.Dispatch('Excel.Application')
excel.Visible = True

# Select the path of the folder with all the files
files = glob.glob("folder_path/*.xlsx")

# Redirect the stdout to a file
orig_stdout = sys.stdout
bk = io.open("Answers_Report.txt", mode="w", encoding="utf-8")
sys.stdout = bk

# Go through all the files in the folder
for file in files:
	print(file.split('\')[1])
	wb_data = excel.Workbooks.Open(file) 
  
  # Get the answers to the Q1A
	mission=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C6")
	vision =wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C7")
	print("Question 1A")
	print("Mission:",mission)
	print("Vision:" ,vision)
	print()

  # Get the answers to the Q1B
	oe1=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C14")
	ju1=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("D14")
	oe2=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("C15")
	ju2=wb_data.Worksheets("1ayb_MisiónyVisiónFutura").Range("D15")
	print("Question 1B")
	print("OEN1:",oe1, "- JUSTIF:",ju1)
	print("OEN2:",oe2, "- JUSTIF:",ju2)
	print()

  # Get the answers to the Q2A
	mision=wb_data.Worksheets("2a_MisionyVisionSI").Range("C6")
	vision=wb_data.Worksheets("2a_MisionyVisionSI").Range("C7")
	print("Question 2A")
	print("Mission SI:",mision)
	print("Vision SI:",vision)
	print()
  
  # Get the answers to the Q3A
	print("Question 3A")
	for i in range(5,13): 
		proy=wb_data.Worksheets("3a_ProySI").Range("B"+str(i))
		desc=wb_data.Worksheets("3a_ProySI").Range("D"+str(i))
		mcfr=wb_data.Worksheets("3a_ProySI").Range("E"+str(i))
		tipo=wb_data.Worksheets("3a_ProySI").Range("F"+str(i))	
		print("tProyect:",proy)
		print("tDesc:",desc)
		print("tMacFarlan:",mcfr,"- Tipo",tipo)
		print()
    
  # Close the file without saving
	wb_data.Close(True)

# Restoring the stdout
sys.stdout = orig_stdout
bk.close()

# Create a new Excel file for the grading template
wb_template = excel.Workbooks.Add()

# Headers of the template
wb_template.Worksheets(1).Range("A1").Value = 'File'
wb_template.Worksheets(1).Range("B1").Value = 'Q1A'
wb_template.Worksheets(1).Range("C1").Value = 'C1A'
wb_template.Worksheets(1).Range("D1").Value = 'Q1B'
wb_template.Worksheets(1).Range("E1").Value = 'C1A'
wb_template.Worksheets(1).Range("F1").Value = 'Q2A'
wb_template.Worksheets(1).Range("G1").Value = 'C2A'
wb_template.Worksheets(1).Range("H1").Value = 'Q3A'
wb_template.Worksheets(1).Range("I1").Value = 'C3A'

# Add the path of each file into the template
for idx, arch in enumerate(files):
	wb_template.Worksheets(1).Range("A"+str(idx+2)).Value = arch.replace('\','/')	

# Save the grading template without alerts
excel.DisplayAlerts = False
wb_template.SaveAs(r'folder_pathGrades_Template.xlsx')

# Close the file and the program
wb_template.Close()
excel.DisplayAlerts = True
excel.Quit()

Finally, with this I’m able to get the summary of all the files in a little .txt

And a template for grading each of the students with the path to each of the files

The full code with some of the Excel files used for the example can be found in the blog’s github.

Conclusion

Whenever someone wants to work with Excel files in Python, most tutorials and websites suggest the use of pandas, opepyxl or xlsxwriter packages. However, it is important to know that there are other options availabe that can help you with more functionalities. Microsoft’s COM technology is an option that can be used effectively through Python to do tasks that might be too difficult to do otherwise and not limitting its use to only Excel. Hopefully this example can give you some inspiration on how to incorporate this library into your work.

Next steps

With this example, I showed you how to open an set of Excel files with the same structure from a folder and extract all of its data into a .txt report. Also, how to create a new Excel file and add data to it to create a template to grade the different questions in each of the files.

In the next tutorial, I’ll show you how to read the template file with the grades and put its data into each of the student files to avoid the work of opening each individual file and working directly in them.

Время на прочтение
6 мин

Количество просмотров 349K

Добрый день, уважаемые читатели.

В сегодняшней статье я хотел бы, как можно подробнее, рассмотреть интеграцию приложений Python и MS Excel. Данные вопрос может возникнуть, например, при создании какой-либо системы онлайн отчетности, которая должна выгружать результаты в общепринятый формат ну или какие-либо другие задачи. Также в статье я покажу и обратную интеграцию, т.е. как использовать функцию написанную на python в Excel, что также может быть полезно для автоматизации отчетов.

Работаем с файлами MS Excel на Python

Для работы с Excel файлами из Python мне известны 2 варианта:

  1. Использование библиотек, таких как xlrd, xlwt, xlutils или openpyxl
  2. Работа с com-объектом

Рассмотрим работу с этими способами подробнее. В качестве примера будем использовать готовый файл excel из которого мы сначала считаем данные из первой ячейки, а затем запишем их во вторую. Таких простых примеров будет достаточно для первого ознакомления.

Использование библиотек

Итак, первый метод довольно простой и хорошо описан. Например, есть отличная статья для описания работы c xlrd, xlwt, xlutils. Поэтому в данном материале я приведу небольшой кусок кода с их использованием.

Для начала загрузим нужные библиотеки и откроем файл xls на чтение и выберем
нужный лист с данными:

import xlrd, xlwt
#открываем файл
rb = xlrd.open_workbook('../ArticleScripts/ExcelPython/xl.xls',formatting_info=True)

#выбираем активный лист
sheet = rb.sheet_by_index(0)

Теперь давайте посмотрим, как считать значения из нужных ячеек:

#получаем значение первой ячейки A1
val = sheet.row_values(0)[0]

#получаем список значений из всех записей
vals = [sheet.row_values(rownum) for rownum in range(sheet.nrows)]

Как видно чтение данных не составляет труда. Теперь запишем их в другой файл. Для этого создам новый excel файл с новой рабочей книгой:

wb = xlwt.Workbook()
ws = wb.add_sheet('Test')

Запишем в новый файл полученные ранее данные и сохраним изменения:

#в A1 записываем значение из ячейки A1 прошлого файла
ws.write(0, 0, val[0])

#в столбец B запишем нашу последовательность из столбца A исходного файла
i = 0
for rec in vals:
    ws.write(i,1,rec[0])
    i =+ i

#сохраняем рабочую книгу
wb.save('../ArticleScripts/ExcelPython/xl_rec.xls')

Из примера выше видно, что библиотека xlrd отвечает за чтение данных, а xlwt — за запись, поэтому нет возможности внести изменения в уже созданную книгу без ее копирования в новую. Кроме этого указанные библиотеки работают только с файлами формата xls (Excel 2003) и у них нет поддержки нового формата xlsx (Excel 2007 и выше).

Чтобы успешно работать с форматом xlsx, понадобится библиотека openpyxl. Для демонстрации ее работы проделаем действия, которые были показаны для предыдущих библиотек.

Для начала загрузим библиотеку и выберем нужную книгу и рабочий лист:

import openpyxl
wb = openpyxl.load_workbook(filename = '../ArticleScripts/ExcelPython/openpyxl.xlsx')
sheet = wb['test']

Как видно из вышеприведенного листинга сделать это не сложно. Теперь посмотрим как можно считать данные:

#считываем значение определенной ячейки
val = sheet['A1'].value

#считываем заданный диапазон
vals = [v[0].value for v in sheet.range('A1:A2')]

Отличие от прошлых библиотек в том, что openpyxl дает возможность отображаться к ячейкам и последовательностям через их имена, что довольно удобно и понятно при чтении программы.

Теперь посмотрим как нам произвести запись и сохранить данные:

#записываем значение в определенную ячейку
sheet['B1'] = val

#записываем последовательность
i = 0
for rec in vals:
    sheet.cell(row=i, column=2).value = rec
    i =+ 1

# сохраняем данные
wb.save('../ArticleScripts/ExcelPython/openpyxl.xlsx')

Из примера видно, что запись, тоже производится довольно легко. Кроме того, в коде выше, можно заметить, что openpyxl кроме имен ячеек может работать и с их индексами.

К недостаткам данной библиотеки можно отнести, то что, как и в предыдущем примере, нет возможности сохранить изменения без создания новой книги.

Как было показано выше, для более менее полноценной работы с excel файлами, в данном случае, нужно 4 библиотеки, и это не всегда удобно. Кроме этого, возможно нужен будет доступ к VBA (допустим для какой-либо последующей обработки) и с помощью этих библиотек его не получить.

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

Работа с com-объектом

В своих отчетах я предпочитаю использовать второй способ, а именно использование файла Excel через com-объект с использованием библиотеки win32com. Его преимуществом, является то, что вы можете выполнять с файлом все операции, которые позволяет делать обычный Excel с использованием VBA.

Проиллюстрируем это на той же задаче, что и предыдущие примеры.

Для начала загрузим нужную библиотеку и создадим COM объект.

import win32com.client
Excel = win32com.client.Dispatch("Excel.Application")

Теперь мы можем работать с помощью объекта Excel мы можем получить доступ ко всем возможностям VBA. Давайте, для начала, откроем любую книгу и выберем активный лист. Это можно сделать так:

wb = Excel.Workbooks.Open(u'D:\Scripts\DataScience\ArticleScripts\ExcelPython\xl.xls')
sheet = wb.ActiveSheet

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

#получаем значение первой ячейки
val = sheet.Cells(1,1).value

#получаем значения цепочки A1:A2
vals = [r[0].value for r in sheet.Range("A1:A2")]

Как можно заметить, мы оперируем здесь функциями чистого VBA. Это очень удобно если у вас есть написанные макросы и вы хотите использовать их при работе с Python при минимальных затратах на переделку кода.

Посмотрим, как можно произвести запись полученных значений:

#записываем значение в определенную ячейку
sheet.Cells(1,2).value = val

#записываем последовательность
i = 1
for rec in vals:
    sheet.Cells(i,3).value = rec
    i = i + 1

#сохраняем рабочую книгу
wb.Save()

#закрываем ее
wb.Close()

#закрываем COM объект
Excel.Quit()

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

Однако, внимательный читатель, обратит внимание на переменную i, которая инициализируется не 0, как принято python, а 1. Это связано с тем, что мы работаем с индексами ячеек как из VBA, а там нумерация начинается не с 0, а с 1.

На этом закончим разбор способов работы с excel файлами в python и перейдем к обратной задаче.

Вызываем функции Python из MS Excel

Может возникнуть такая ситуация, что у вас уже есть какой-либо функция, которая обрабатывает данные на python, и нужно перенести ее функциональность в Excel. Конечно же можно переписать ее на VBA, но зачем?

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

Итак, предположим у нас есть функция, написанная на python, которой мы хотим воспользоваться:

def get_unique(lists):
    sm = 0
    for i in lists:
        sm = sm + int(i.pop()) 
    return sm

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

Сохраним функцию в файле plugin.py и положим его в ту же директорию, где будет лежать наш excel файл, с которым мы будем работать.

Теперь установим ExcelPython. Установка происходит через запуск exe-файла и не вызывает затруднений.

Когда все приготовления выполнены, открываем тестовый файл excel и вызовем редактор VBA (Alt+F11). Для работы с вышеуказанной надстройкой необходимо ее подключить, через Tools->References, как показано на рисунке:

Ну что же, теперь можно приступить к написанию функции-обертки для нашего Python-модуля plugin.py. Выглядеть она будет следующим образом:

Function sr(lists As Range)
    On Error GoTo do_error
        Set plugin = PyModule("plugin", AddPath:=ThisWorkbook.Path)
        Set result = PyCall(plugin, "get_unique", PyTuple(lists.Value2))
        sr = WorksheetFunction.Transpose(PyVar(result))
        Exit Function
do_error:
        sr = Err.Description
End Function

Итак, что же происходит в данной функции?

Для начала, с помощью PyModule, мы подключаем нужный модуль. Для этого в качестве параметров ей передается имя модуля без расширения, и путь до папки в которой он находится. На выходе работы PyModule мы получаем объект для работы с модулем.

Затем, с помощью PyCall, вызываем нужную нам функцию из указанного модуля. В качестве параметров PyCall получает следующее:

  1. Объект модуля, полученный на предыдущем шаге
  2. Имя вызываемой функции
  3. Параметры, передаваемые функции (передаются в виде списка)

Функция PyTuple, получает на вход какие-либо значения и преобразует их в объект tuple языка Python.
Ну и, соответственно, PyVar выполняет операцию преобразования результата функции python, к типу понятному Excel.

Теперь, чтобы убедиться в работоспособности нашей связки, вызовем нашу свежеиспеченую функцию на листе в Excel:

Как видно из рисунка все отработало правильно.

Надо отметить, что в данном материале используется старая версия ExcelPython, и на GitHub’e автора доступна новая версия.

Заключение

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

Также хочу заметить, что указанные пакеты не являются единственными и в статье опущено рассмотрение, таких пакетов как xlsxwriter для генерации excel файлов или xlwings, который может работать с Excel файлами «на лету», а также же PyXLL, который выполняет аналогичные функции ExcelPython.

Кроме этого в статье я попытался несколько обобщить разборасанный по сети материал, т.к. такие вопросы часто фигурируют на форумах и думаю некоторым будет полезно иметь, такую «шпаргалку» под рукой.

Improve Article

Save Article

Like Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Like Article

    In this article, we will learn how we can automate refreshing an Excel Spreadsheet using Python.

    So to open the Excel application and workbooks we are going to use the pywin32 module. You can install the module using the below code:

    pip install pywin32

    Then we are going to open the Excel application using the win32com.client.Dispatch() method and workbooks using the Workbooks.open() method.

    Syntax: File.Workbooks.open(PATH_OF_FILE)

    Parameters: It will take the path of the excel file as its parameter.

    And then use refresh the file using RefershAll():

    Workbook.RefreshAll()

    For this example, we created an excel file named “Book1” with the below content:

    Below is the implementation:

    Python3

    import win32com.client

    File = win32com.client.Dispatch("Excel.Application")

    File.Visible = 1

    Workbook = File.Workbooks.open("Book1.xlsx")

    Workbook.RefreshAll()

    Workbook.Save()

    File.Quit()

    Output:

    Like Article

    Save Article

    Понравилась статья? Поделить с друзьями:
  • Python чтение документа word
  • Python чтение excel файла pandas
  • Python форматирование ячеек excel
  • Python форматирование текста word
  • Python сравнить два файла excel