from datetime import datetime, timedelta import os import shutil from docx import Document from docx.text.paragraph import Paragraph from docx.shared import Inches, Pt, RGBColor from docx.enum.style import WD_STYLE_TYPE import sys import subprocess import re from random import randint import random from pathlib import Path from pdf2image import convert_from_path from PIL import Image, ImageFilter, ImageDraw from PIL.ImageFilter import ( BLUR, CONTOUR, DETAIL, EDGE_ENHANCE, EDGE_ENHANCE_MORE, EMBOSS, FIND_EDGES, SMOOTH, SMOOTH_MORE, SHARPEN ) def convert_to(folder, source, timeout=None): args = [libreoffice_exec(), '--headless', '--convert-to', 'pdf', '--outdir', folder, source] process = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=timeout) filename = re.search('-> (.*?) using filter', process.stdout.decode()) return filename.group(1) def libreoffice_exec(): # TODO: Provide support for more platforms if sys.platform == 'darwin': return '/Applications/LibreOffice.app/Contents/MacOS/soffice' elif sys.platform == 'win32': # you need to add libreoffice to path return 'soffice.exe' return 'libreoffice' def create_photo(address, user): month = datetime.now().month info = get_info(user) path_to_template = os.path.join(os.path.abspath('.'), 'data', user) template_docx = os.path.join(path_to_template, 'new_template.docx') if len(info) > 0: if not os.path.exists(template_docx): # print(f"Копируем шаблоны графиков в {user}") template_in_user = shutil.copyfile('new_template.docx', template_docx) path_for_photo = os.path.join(path_to_template, str(month), address) photos = get_photo(address, user) if len(photos) > 0: # print(len(photos)) if len(photos) > 7: open_document(template_docx, True, info, address, path_for_photo, user) else: open_document(template_docx, False, info, address, path_for_photo, user) return path_for_photo else: print(f"Нет фотографий по адресу {address}") def get_info(user): path = os.path.join(os.path.abspath('.'), 'data', user, 'img_5.txt') if not os.path.exists(path): print(f"Нет файла с информацией у пользователя {user}") return [] with open(path, 'r') as f: fd = f.readlines() return fd def get_photo(address, email): photos = [] month = datetime.now().month main_path = os.path.join(os.path.abspath('.'), 'data', email, str(month), address) if not os.path.exists(main_path): print(f"Нет фотографий по адресу: {address}") return photos else: for images in os.listdir(main_path): if images.endswith(".jpg") or images.endswith(".jpeg") or images.endswith(".JPG"): photos.append(main_path + '/' + images) return photos def open_document(filename, lift, info, address, path_for_photo, user): # print(f"Наличие лифта по адресу: {address} - {lift}") # print(f"Начинаем подготавливать график для {address}, шаблон {filename}") row_for_sign = 0 document = Document(filename) styles = document.styles tables = document.tables date_now = datetime.today() first_date = tables[0].rows[1].cells[0].text first_date = datetime.strptime(first_date, '%d.%m.%y') if datetime.now().date()-timedelta(12) > first_date.date(): clear_table(tables, lift, styles, info) row_for_sign = fill_table(tables) document.save(filename) else: row_for_sign = fill_table(tables) document.save(filename) paragraphs = document.paragraphs fill_info(paragraphs, styles, info, address, lift) document.save(filename) make_png_with_sign(filename, row_for_sign, lift, path_for_photo, user) def make_png_with_sign(filename, row_for_sign, lift, path_for_photo, user): # print(f"Создаем картинку из графика {filename}") horizontal = 0 if lift: start_vertical = 780 else: start_vertical = 680 result = convert_to('.', filename, timeout=15) pages = convert_from_path(result, 200) pages[0].save('template.png', 'PNG') img2 = Image.open('template.png') img2 = img2.convert("RGBA") datas = img2.getdata() newData = [] for item in datas: if item[0] == 255 and item[1] == 255 and item[2] == 255: newData.append((255, 255, 255, 0)) else: # if item[0] > 120: # newData.append((105, 105, 105, 255)) # else: newData.append(item) img2.putdata(newData) while (row_for_sign+1) > 0: # if lift: # horizontal = randint(1320, 1450) # else: horizontal = randint(1320, 1450) vertical = start_vertical + ((row_for_sign) * 100) # clear_background('my_sign.png') sign = Image.open(os.path.join(os.path.abspath('.'), 'data', user, 'sign.png')) width, height = sign.size sign = sign.resize((int(width*1.5), int(height*1.5))) # print(horizontal) img2.paste(sign, (horizontal, vertical), sign) # vertical step = 150 row_for_sign -= 1 img2.save('template.png', "PNG") add_image_to_image('template.png', 'fon2.png', path_for_photo) def add_image_to_image(filename, filename_fon, dst_folder): # print(f"Накладываем график {filename} на фон") left = randint(0, 140) upper = randint(0, 85) w_rand = random.uniform(0.8, 1) b_rand = random.uniform(0.5, 0.8) try: angle = 0 # img = img.filter(ImageFilter.GaussianBlur(radius=1)) background = Image.open(filename_fon) foreground = Image.open(filename) width, height = foreground.size size = int(width*0.25), int(height*0.25) width_b, height_b = background.size foreground = foreground.resize(size).rotate(angle) background.paste(foreground, (195, 290), foreground) background = background.crop((left, upper, width_b*w_rand, height_b*w_rand)) background = background.filter(ImageFilter.GaussianBlur(radius=b_rand)) background.save(os.path.join(dst_folder, 'graph.jpg')) # print(os.path.join(dst_folder, 'graph.jpg')) # print(os.path.dirname(dst_folder)) except IOError: print(sys.exc_info()[0]) pass def delete_paragraph(paragraph): p = paragraph._element p.getparent().remove(p) p._p = p._element = None def clear_table(tables, lift, styles, info): # print(f"Очищаем таблицу в графике") fio = info[0].split('\n')[0] count = 0 while count < len(tables[0].rows)-1: date_to_add = datetime.now().date()+timedelta(count) delete_paragraph(tables[0].rows[count+1].cells[0].paragraphs[0]) delete_paragraph(tables[0].rows[count+1].cells[2].paragraphs[0]) par = tables[0].rows[count+1].cells[0].add_paragraph() par_fio = tables[0].rows[count+1].cells[2].add_paragraph() p = par.add_run(datetime.strftime(date_to_add, '%d.%m.%y')) p_fio = par_fio.add_run(fio) par_fio.alignment = 1 p_fio.bold = True p.bold = True font = p.font count += 1 def fill_table(tables): # print("Заполняем таблицу в графике") r_count = 0 count = 0 while count < len(tables[0].rows)-1: date_in_cell = tables[0].rows[count+1].cells[0].text date_in_cell = datetime.strptime(date_in_cell, '%d.%m.%y') if date_in_cell.date() == datetime.now().date(): r_count = count count += 1 return r_count def fill_info(paragraphs, styles, info, address, lift): # print(f"Заполняем шапку графика в {address}") fio = info[0].split('\n')[0] dol = info[1].split('\n')[0] phone_number = info[2].split('\n')[0] for paragraph in paragraphs: name_style = paragraph.style.name if 'по адресу:' in paragraph.text: # p = paragraph.insert_paragraph_before() style = styles[name_style] style.font.size = Pt(14) paragraph.text = '' p = paragraph.add_run('по адресу: '+address[:-4]+' Подъезд № ' + address[-2]) p.bold = True font = p.font font.color.rgb = RGBColor(128, 128, 128) paragraph.style = styles[name_style] elif 'Должность:' in paragraph.text: paragraph.text = '' if lift: text_for_perechen = 'Перечень обрабатываемых объектов:\n - Первые этажи подъездов: полы, дверные и оконные ручки, почтовые ящики, панели домофонов и кодовых замков, перила лестничных маршей\n - Лифтовые кабины: напольные покрытия, панели управления лифтами, лифтовые вентиляционные решетки' else: text_for_perechen = 'Перечень обрабатываемых объектов:\n - Первые этажи подъездов: полы, дверные и оконные ручки, почтовые ящики, панели домофонов и кодовых замков, перила лестничных маршей' run = paragraph.add_run(' Должность: ' + dol +' Ф.И.О.: ' + fio + '\n тел: ' + phone_number + '\n' + text_for_perechen) font = run.font