Всем привет.
В статье приведу немного скриптов на Python для решения вопросов с которыми иногда пересекается инженер ПТО строительной организации. Склёпал сам по мотивам информации из инета. Профи будет скучно), уровень «без диплома программиста».
На рабочем ноуте используется: Win10, Python 3.11, Office2019. Програмлю в PyScripter (нравится мне он))
Пример 1. Надо архивировать (не в смысле запаковать)
Проводятся испытания отдельных участков трубопровода, штук 50-60. На каждое заводится папка. Так как ни заказчик, ни технадзор, ни еще кто-нибудь не могут определиться, как лучше оформить это дело, то возникает ситуация когда куча документов имеет 2-3-4 варианта оформления. Значит надо скрипт, который текущий вариант закинет в архивную папку. (Ну да, «мой комьютер» или «тотал коммандер» никак с этим не справляются)):
##------------ЗАДАЧА--------------------------- ## Создать папку Архив, в ней создать подпапку ## Переместить все файлы ворд/Эксель в подпапку архива import glob, os, shutil source_dir = os.getcwd() #Path where your files are at the moment dst = source_dir+'/Архив/Вар2' #Path you want to move your files to if not os.path.isdir(dst): #создаем архив os.makedirs(dst) #либо выбираем типы файлов - типа оффис format_move_files = ['*.xls*', '*.doc*'] #либо все. ##format_move_files = ['*.*'] for fmf in format_move_files: files = glob.iglob(os.path.join(source_dir, fmf)) for file in files: if os.path.isfile(file): shutil.move(file, dst)
Пример 2. Создаем папки
Собралось как-то много файлов в одной папке. И тут супостаты опять пристали со своими хотелками — каждый файл в свою папку. Нууу, лааадно. Лучше день потерять….потом за минуту само сделается. Идея такова, тем же тоталом получаю список файлов, его сохраняю в файле «папки.txt». Вот теперь его скрипт должен открыть и наштамповать папок:
import os codirovk = 'utf-8' #------------вар2 работает------------------ with open('папки.txt', "r", encoding=codirovk) as file1: # итерация по строкам for line in file1: print(line.strip()) if not os.path.isdir(line.strip()): ##делаем папки если их нет os.makedirs(line.strip()) #------------вар1 работает------------------ ##file1 = open('папки.txt', "r") ## ### считываем все строки ##lines = file1.readlines() ## ### итерация по строкам ##for line in lines: #### print(line.strip()) ## if not os.path.isdir(line.strip()): делаем папки если их нет ## os.makedirs(line.strip()) ## ### закрываем файл ##file1.close
Пример 3. Достаем файлы
И вот присылают как-то папку со сметами, а они каждый файл в отдельной папке, да еще вперемешку с ведомостями всякими, да еще названия файлов пляшут, ну и их 392шт. Шо делать, шо делать — расчехляем питон. Надо достать все файлы смет с попутным переименованием их в одну папку:
# задача - достать из множества папок все файлы в одну папку (где скрипт) # допзадача - переименовать добавляя имена подпапок import os, shutil import glob import re dst = os.getcwd() print(dst) # допзадача переименовать добавляя имена подпапок for name in sorted(glob.glob(dst+'/**/*локал*.xls', recursive=True)): # имеем D:\1 На почту\КС-6\Глава 1\01-02-01Р-01\Л0326174_Локальная смета.xls # вырезаем эту часть D:\1 На почту\КС-6\ и заменяем косые черты на тире newname = name[len(dst)+1:] newname = re.sub(r'\\', '-', newname) os.rename(name, newname) # пройтись по всем папкам каталога запуска скрипта и переместить # файлы *локал*.xls в папку скрипта for name in sorted(glob.glob(dst+'/**/*локал*.xls', recursive=True)): try: shutil.move(name, dst) except: pass
Пример 4. Из ворда в пдф)
Есть пару десятков файлов ворда в формате docx, надо из них pdf. Ну конечно, сча я буду сидеть каждый ручками открывать и делать сохранить как. Хотя есть еще и пдф-принтеры…..Так, ладно, питон погнали:
##*******************работает только docx #pip install docx2pdf from docx2pdf import convert import os convert(os.getcwd()) # конвертация текущего каталога
Пример 5 с подпримером 6. Работаем с Excel. Замена текста во множестве файлов.
Мы строили, строили и наконец — построили. Но….да твою ж дивизию: ну почему когда 85% исполнительной документации уже сделано и подписано (а это примерно 1200-1500 актов скрытых работ, сделанных в эксель) вдруг какой-то заразе приходит в голову поменять подписанта из-за игр генподрядчик-субподрядчик-субсубподрядчик. И, шо, эти люди думают, радостно потирая ручки, шо я буду мучиться. Ну держитесь — где там мой удав, пора придушить воооон того….А ладно, смотрим шо есть в интернете для питона. А там много чего есть, те что приглянулись вот:
-
openpyxl — работает только с xlsx Для его использования возникла подзадача сконвертировать из xls в xlsx. Смотрим вопрос в инете. Находим pyexcel, xls2xlsx — но рушат форматирование. Находим pywin32. Делаем:
# Задача: конвертация эксель из xls в xlsx # Все остальные библиотеки работают вкось # Эксель должен быть установлен на компе!!! # pip bloks ## python -m pip install --upgrade pywin32 # import bloks import os import win32com.client as win32 # config bloks path =os.getcwd() format_files = ('.xls') pred_prefiks_file_name = '' # relise bloks for root, dirs, files in os.walk(path): for file in files: if(file.endswith(format_files, 0, len(file))): ## print(os.path.join(file))## - этот вариант выводит только имя файла print(file) ## print(os.path.join(root, file))## - этот вариант выводит полный путь и имя файла # -------делаем через COM объект ----------------------------- excel = win32.gencache.EnsureDispatch('Excel.Application') wb = excel.Workbooks.Open(os.path.join(root, file)) wb.SaveAs(pred_prefiks_file_name+os.path.join(root, file)+'x', FileFormat = 51) #FileFormat = 51 is for .xlsx extension wb.Close() #FileFormat = 56 is for .xls extension excel.Application.Quit() input("Работа завершена. Тисни ентер.")
Далее обрабатываем openpyxl, но он тоже нарушает форматирование. Ищем дальше и находим:
-
aspose-cells -добавляет лист ‘Evaluation Warning’ и может еще какое ограничение содержит, так как он платный.
Практически он работает как надо. Делаю через него скрипт, а лишний лист удаляю с помощью pywin32.
## худо бедно работает как надо мне, но компонент платный ##pip install aspose-cells ##pip install aspose-cells-python ##python -m pip install --upgrade pywin32 import os from aspose.cells import Workbook, ReplaceOptions import win32com.client as win32 path =os.getcwd() format_files = ('.xlsx')##'.pdf','.doc', '.docx', '.dwg', '.py' ## - закомментировать если нужны все файлы find_str = 'Руководитель проекта ООО "Капуста" ' removent_str = 'Заместитель генерального директора по объектам ООО "Рога и копыта"' # ВНИМАНИЕ - замена осуществляет по полным данным в ячейке. Т.е. меняется ячейка на ячейку pred_prefiks_file_name = '' for root, dirs, files in os.walk(path): for file in files: if(file.endswith(format_files, 0, len(file))):## - закомментировать если нужны все файлы print(file) # Load Excel file workbook = Workbook(file) ##Workbook("Workbook.xlsx") # Create replace options replace = ReplaceOptions() # Set case sensitivity and text matching options - раздел выдает ошибку ## replace.setCaseSensitive(False) ## replace.setMatchEntireCellContents(False) # Replace text workbook.replace(find_str, removent_str, replace) # Save as Excel XLSX file workbook.save(pred_prefiks_file_name+file); ## этот блок удаляет последний добавляемый лист 'Evaluation Warning' - по факту просто последний excel = win32.gencache.EnsureDispatch('Excel.Application') wb = excel.Workbooks.Open(os.path.join(root, pred_prefiks_file_name+file)) ws = wb.ActiveSheet try: excel.DisplayAlerts=False wb.Worksheets(wb.Sheets.Count).Delete() finally: pass wb.Save() wb.Close() excel.Application.Quit() input("Работа завершена. Тисни ентер.")
Да шо ж я упускаю что-то. Как то все топорно. Стоп, эту работу лучше экселя никто не сделает, а это значит вот же решение — pywin32. И конвертировать ничего не надо было. Ищем материалы в инете, просматриваем, пробуем раз 50 с попутным улучшением, готово:
##python -m pip install --upgrade pywin32 import os import win32com.client as win32 import re path = os.getcwd() format_files = ('.xlsx', '.xls')##'.pdf','.doc', '.docx', '.dwg', '.py' ## - закомментировать если что-то не надо # ищем строку find_str = 'Сидоров Ю.М.' # строка для замены найденной строки removent_str = 'Сидоров Ю.А.' # делаем 4 замены по порядку, а можно было и через список сделать #Сидоров Ю.М. Сидоров Ю.А. #Руководитель проекта ООО "Капуста" Заместитель генерального директора по объектам ООО "Рога и копыта" #Сидоров Ю.М. Приказ №15 29.03.2023 Сидоров Ю.А. Приказ № П100 от 31.09.2022 #Иванов А.А. Сидоров Ю.А. #количество строк в которых надо делать поиск row_find = 125 #количество столбцов в которых надо делать поиск col_find = 40 #если надо спереди имени файла добавить префикс pred_prefiks_file_name = '' excel = win32.gencache.EnsureDispatch('Excel.Application') for root, dirs, files in os.walk(path): for file in files: if ((file.endswith(format_files, 0, len(file))) and (not file.endswith('~$', 0, 2))): # not file.endswith('~$', 0, 2) - защита от временных файлов эксель которые имена начинаются на ~$ print('файл: ',file) #print(os.path.join(file))## - этот вариант выводит только имя файла #print(os.path.join(root, file))## - этот вариант выводит полный путь и имя файла ## excel = win32.gencache.EnsureDispatch('Excel.Application') wb = excel.Workbooks.Open(os.path.join(root, file)) print('листов: ', wb.Worksheets.Count) for sh_i in range(1, wb.Worksheets.Count+1): #перебираем листы книги ws = wb.Worksheets(sh_i) # идем на лист и активируем его ws.Activate() print('лист: ', sh_i) fp = 0 cii2 = 0 for row_i in range(1, row_find): #ws.Columns.Count - это вообще все строки for col_i in range(1, col_find): #ws.Rows.Count - это вообще все колонки if ws.Cells(row_i,col_i).Value: cii2 = cii2 + 1 #вариант с re - заменяет внутри data_from_cell = str(ws.Cells(row_i,col_i).Value) #получаем строку из данных result = re.findall(find_str, data_from_cell) if len(result) > 0: print('в ячейке: ',row_i,',',col_i) print('данные в ячейке: '+data_from_cell) fp = 1 data_from_cell2 = re.sub(find_str, removent_str, data_from_cell, count=0) print('измененные данные: '+data_from_cell2) ws.Cells(row_i,col_i).Value = data_from_cell2 print('замена выполнена') #вариант через данные эксель - совпадение по ячейке полностью - плохой вариант ## if ws.Cells(row_i,col_i).Value == find_str: ## print('найдено на листе: ', sh_i) ## print('в ячейке: ',row_i,', ',col_i) ## fp = 1 ## ws.Cells(109,1).Value = removent_str ## print('замена выполнена') if fp == 0: print('не найдено на листе: ', sh_i) print('пройдено ячеек: ', cii2) wb.Save(os.path.join(root, pred_prefiks_file_name+file)) wb.Close() ## excel.Application.Quit() excel.Application.Quit() print('') print('----------------------------------------------') input("Работа завершена. Тисни ентер.")
В общем как поиск/замену сделать через pywin32 не нашел. Перебираю заданную область по ячейково. Сначала всю ячейку заменял — но это отдельный текст внутри ячейки не заменишь, а только целиком. Потом через модуль re уже стало работать, как я и хотел. Работает медленнее, чем aspose, но мне как-то спокойнее)).
P.S.: Так и живём в ПТО 🙂
ссылка на оригинал статьи https://habr.com/ru/articles/761484/
Добавить комментарий