Browse Source

Doc Builder Class Finished
- Implented in Main for creation of Bills

Danny 2 years ago
parent
commit
c3c1d192d4

+ 0 - 53
fast_excel_to_bill/bill_doc/create_custom_bill_doc.py

@@ -1,53 +0,0 @@
-from docx import Document
-from docx.shared import Inches
-import time
-
-'https://python-docx.readthedocs.io/en/latest/user/text.html'
-
-def create_custome_doc_file():
-    '''
-    :return: Bill as Doc file
-    '''
-
-
-
-document = Document()
-
-document.add_heading('Document Title', 0)
-
-p = document.add_paragraph('A plain paragraph having some ')
-p.add_run('bold').bold = True
-p.add_run(' and some ')
-p.add_run('italic.').italic = True
-
-document.add_heading('Heading, level 1', level=1)
-document.add_paragraph('Intense quote', style='Intense Quote')
-
-document.add_paragraph(
-    'first item in unordered list', style='List Bullet'
-)
-document.add_paragraph(
-    'first item in ordered list', style='List Number'
-)
-
-records = (
-    (3, '101', 'Spam'),
-    (7, '422', 'Eggs'),
-    (4, '631', 'Spam, spam, eggs, and spam')
-)
-
-table = document.add_table(rows=1, cols=3)
-hdr_cells = table.rows[0].cells
-hdr_cells[0].text = 'Qty'
-hdr_cells[1].text = 'Id'
-hdr_cells[2].text = 'Desc'
-for qty, id, desc in records:
-    row_cells = table.add_row().cells
-    row_cells[0].text = str(qty)
-    row_cells[1].text = id
-    row_cells[2].text = desc
-
-document.add_page_break()
-
-doc_output_path = r'C:\Users\Danny\Desktop\ssd wichtige dinge D\Tools\fast_excel_to_bill\test_folder' + r'\doc_test_{}.docx'.format(time.strftime("%Y-%m-%d_H%H-M%M"))
-document.save(doc_output_path)

+ 221 - 0
fast_excel_to_bill/bill_doc/docx_builder.py

@@ -0,0 +1,221 @@
+from docx.api import Document
+from docx.oxml.table import CT_Tbl
+from docx.oxml.text.paragraph import CT_P
+from docx.table import _Cell, Table, _Row
+from docx.text.paragraph import Paragraph
+import time
+import re
+
+path = r'C:\Users\Danny\Desktop\ssd wichtige dinge D\Tools\fast_excel_to_bill\test_folder\Templates\templeta.docx'
+doc_output_path = r'C:\Users\Danny\Desktop\ssd wichtige dinge D\Tools\fast_excel_to_bill\test_folder' + r'\doc_test_{}.docx'.format(
+    time.strftime("%Y-%m-%d_H%H-M%M"))
+
+
+class DOCFileBuilder:
+    def __init__(self, docx_input_path='', docx_save_path=''):
+        if docx_input_path:
+            self.document = Document(docx_input_path)
+        else:
+            self.document = Document()
+        self.docx_save_path = docx_save_path
+
+    # Low Level Functions
+    def save_docx(self):
+        if self.docx_save_path != '': # Default
+            self.document.save()
+        else:
+            self.document.save(self.docx_save_path)
+
+    def get_header_footer(self):
+        self.header_ = self.document.sections[0].header
+        self.footer_ = self.document.sections[0].footer
+
+    def replace_text_in_paragraph(self, paragraph,search_str, replace_str):
+        inline = paragraph.runs
+        for i in range(len(inline)):
+            if search_str in inline[i].text:
+                text = inline[i].text.replace(search_str, replace_str)
+                inline[i].text = text
+
+    def paragraphs_in_table(self):
+        for t in self.document.tables:
+            for row in t.rows:
+                for cell in row.cells:
+                    for p in cell.paragraphs:
+                        yield p
+
+    def replace_string_in_standard_text(self, search_str, replace_str):
+        for p in self.document.paragraphs:
+            self.replace_text_in_paragraph(p,search_str,replace_str)
+
+    def replace_string_in_all_tables(self, search_str, replace_str):
+        for p in self.paragraphs_in_table():
+            self.replace_text_in_paragraph(p,search_str, replace_str)
+
+    def replace_dates_string_in_standard_text(self, replace_date_str):
+        for p in self.document.paragraphs:
+            inline = p.runs
+            for i in range(len(inline)):
+                try:
+                    found_date = re.search(r'\d\d\.\d\d\.\d+', inline[i].text).group()
+                    text = inline[i].text.replace(found_date, replace_date_str)
+                    inline[i].text = text
+                except AttributeError:
+                    pass
+
+    def delete_empty_rows_in_table(self, table, column_count):
+        for row in table.rows:
+            column_counter = 0
+            for cell in row.cells:
+                for p in cell.paragraphs:
+                    inline = p.runs
+                    for i in range(len(inline)):
+                        if inline[i].text == '':
+                            column_counter += 1
+            if column_counter == column_count:
+                remove_row(table, row)
+
+    def replace_dates_string_in_all_tables(self, replace_date_str):
+        for p in self.paragraphs_in_table():
+            inline = p.runs
+            for i in range(len(inline)):
+                try:
+                    found_date = re.search(r'\d\d\.\d\d\.\d+', inline[i].text).group()
+                    text = inline[i].text.replace(found_date, replace_date_str)
+                    inline[i].text = text
+                except AttributeError:
+                    pass
+
+    def add_heading(self, text, level, alignment=0):
+        self.title = self.document.add_heading(text, level)
+        self.title.alignment = alignment
+
+    def search_table_with_key_columns(self, keys):
+        for t in self.document.tables:
+            len_key_list = 0
+            for row in t.rows:
+                for cell in row.cells:
+                    for p in cell.paragraphs:
+                        inline = p.runs
+                        for i in range(len(inline)):
+                            for key in keys:
+                                try:
+                                    re.search(key, inline[i].text).group()
+                                    len_key_list += 1
+                                    if len_key_list == len(keys):
+                                        return t
+                                except AttributeError:
+                                    pass
+
+    def replace_rows(self, table, list_tuple):
+        # each tuple builds a row, tuple must be the same size as cells in row
+        # replacing till list of tuple is iterate through
+        # then deleting the rest
+        len_insert_rows = 0
+        for tuple in list_tuple:
+            for row in table.rows:
+                count_columns = 0
+                for count, elem in enumerate(tuple):
+                    for p in row.cells[count].paragraphs:
+                        inline = p.runs
+                        for i in range(len(inline)):
+                            if inline[i].text == '':
+                                inline[i].text = str(elem)
+                                count_columns += 1
+                if count_columns == len(tuple):
+                    len_insert_rows += 1
+                if len_insert_rows == len(list_tuple):
+                    return
+
+    # Custom Format functions
+    def replace_Leistungszeitraum(self, start_date, end_date):
+        for p in self.paragraphs_in_table():
+            inline = p.runs
+            for i in range(len(inline)):
+                try:
+                    re.search(r'Leistungszeitraum', inline[i].text).group()
+                    text = inline[i].text.replace(inline[i].text,
+                                                  'Leistungszeitraum: {} bis zum {}'.format(start_date, end_date))
+                    inline[i].text = text
+                except AttributeError:
+                    pass
+
+    # High Tier functions
+    def replace_all_dates_custom_wise(self, start_date, end_date):
+        self.replace_dates_string_in_standard_text(end_date)
+        self.replace_dates_string_in_all_tables(end_date)
+        self.replace_Leistungszeitraum(start_date, end_date)
+
+    def replace_custom_placeholder_in_doc(self, placeholder, replace_str):
+        for p in self.document.paragraphs:
+            self.replace_text_in_paragraph(p, placeholder, replace_str)
+        for p in self.paragraphs_in_table():
+            self.replace_text_in_paragraph(p, placeholder,replace_str)
+
+
+def remove_row(table, row):
+    tbl = table._tbl
+    tr = row._tr
+    tbl.remove(tr)
+
+
+
+
+
+def iter_block_items(parent):
+    """
+    Yield each paragraph and table child within *parent*, in document order.
+    Each returned value is an instance of either Table or Paragraph.
+    """
+    if isinstance(parent, Document):
+        parent_elm = parent._document_part.body._body
+    elif isinstance(parent, _Cell):
+        parent_elm = parent._tc
+    elif isinstance(parent, _Row):
+        parent_elm = parent._tr
+    else:
+        raise ValueError("something's not right")
+
+    for child in parent_elm.iterchildren():
+        if isinstance(child, CT_P):
+            yield Paragraph(child, parent)
+        if isinstance(child, CT_Tbl):
+            yield Table(child, parent)
+
+
+def find_table_text_in_standard(doc):  # not header or footer
+    table_text = []
+    for table in doc.tables:
+        for row in table.rows:
+            for cell in row.cells:
+                for paragraph in cell.paragraphs:
+                    table_text += [paragraph.text]
+    return table_text
+
+
+def create_custome_doc_file():
+    '''
+    :return: Bill as Doc file
+    '''
+    doc = DOCFileBuilder()
+    doc.add_heading('EnD-GbR', 0, 2)
+    return doc.document
+
+
+if __name__ == '__main__':
+    builder_obj = DOCFileBuilder(path)
+    builder_obj.replace_dates_string_in_standard_text('03.11.2022')
+    builder_obj.replace_dates_string_in_all_tables('03.11.2022')
+    keys = ['KW', 'Leistung', 'Zeit in Stunden', 'Betrag in Euro']
+    example_tuple = [(123123, 213123, 12312312, 445235)]
+    key_table = builder_obj.search_table_with_key_columns(keys)
+    builder_obj.replace_rows(key_table, example_tuple)
+    builder_obj.delete_empty_rows_in_table(key_table, 4)
+    builder_obj.document.add_page_break()
+    key_table = builder_obj.search_table_with_key_columns(['KW', 'Leistungsübersicht'])
+    builder_obj.delete_empty_rows_in_table(key_table, 2)
+    doc = builder_obj.document
+
+
+
+

BIN
fast_excel_to_bill/bills/out.docx


+ 4 - 0
fast_excel_to_bill/config_for_custom_bills.py

@@ -0,0 +1,4 @@
+# Docx Builder
+docx_input_path =...
+docx_output_dir_path = r'C:\Users\Danny\Desktop\ssd wichtige dinge D\Tools\fast_excel_to_bill\test_folder'
+list_of_place_holders = ['?Netto?','?zzgl.?', '?gesamt?', '?insert_date?']

+ 33 - 2
fast_excel_to_bill/main.py

@@ -1,8 +1,39 @@
+from fast_excel_to_bill.bill_doc.docx_builder import DOCFileBuilder
+from fast_excel_to_bill import config_for_custom_bills
+from tool_lib import datetime_functions
+
+
+current_month_year= datetime_functions.get_current_month_year_as_str()
+docx_output_path = config_for_custom_bills.docx_output_dir_path+ r'\bill_{}.docx'.format(current_month_year)
+
+
 def main():
-    get_data_from_excel=...
+    # Get Data which is necessary for the docx
+    data_from_excel = ...
+    burden_date = ...
+    data_from_excel.append(burden_date)
+
+    # Create a doc file which is based on a docx template
+    builder_obj = DOCFileBuilder(config_for_custom_bills.docx_input_path, docx_output_path)
+    place_holders = config_for_custom_bills.list_of_place_holders
+    for place_holder in place_holders:
+        builder_obj.replace_custom_placeholder_in_doc(place_holder, data_from_excel)
+    builder_obj.replace_dates_string_in_standard_text('03.11.2022')
+    builder_obj.replace_dates_string_in_all_tables('03.11.2022')
+
+    keys = ['KW', 'Leistung', 'Zeit in Stunden', 'Betrag in Euro']
+    example_tuple = [(123123, 213123, 12312312, 445235)]
+    key_table = builder_obj.search_table_with_key_columns(keys)
+    builder_obj.replace_rows(key_table, example_tuple)
+    builder_obj.delete_empty_rows_in_table(key_table, 4)
+    builder_obj.document.add_page_break()
+    key_table = builder_obj.search_table_with_key_columns(['KW', 'Leistungsübersicht'])
+    builder_obj.delete_empty_rows_in_table(key_table, 2)
     data_to_bill_doc = ...
+
+    # Transform the doc file to a pdf file
     doc_to_pdf = ...
 
 
 if __name__ == '__main__':
-    main()
+    main()

BIN
time_recoder/time_recorded_tables/Septemnber.xlsx


BIN
time_recoder/time_recorded_tables/example.xlsx


BIN
time_recoder/time_recorded_tables/worked_time_table.xlsx


+ 6 - 1
tool_lib/datetime_functions.py

@@ -4,4 +4,9 @@ def get_calendarweek_from_datetime(datetime_obj):
     return datetime_obj.strftime('%V')
 
 def get_current_date():
-    return datetime.date.today()
+    return datetime.date.today()
+
+def get_current_month_year_as_str():
+    current_date = datetime.datetime.now()
+    return current_date.strftime("%m/%Y")
+