def insert(self): if DEBUG: print('Adding number...') table = self.cell_object.cell.add_table(rows=1, cols=1) if DEBUG: table.style = 'Table Grid' # add background color background_color = self.section.layout.get('style', {}).get( 'backgroundColor', '')[1:] # Add the main number inner_cell = table.cell(0, 0) style_cell(inner_cell, color_hex=background_color) main_number = CellObject(inner_cell) sign = self.section.layout.get('sign', '') sign = '' if sign is None else sign insert_text(main_number, str(self.section.contents) + sign, self.style['main']) main_number.add_paragraph(add_run=True) insert_text(main_number, str(self.section.extra['title']), self.style['title'])
def test_cell_object_add_run(): d = Document() table = d.add_table(1, 1) cell = table.cell(0, 0) co = CellObject(cell) cur_run = co.run co.add_run() assert co.run != cur_run
def test_cell_object_get_last_paragraph(): d = Document() table = d.add_table(1, 1) cell = table.cell(0, 0) co = CellObject(cell) co.run.text = 'old' p = co.add_paragraph() co.run.text = 'new' last_p = co.get_last_paragraph() last_p.text = 'newnew' assert p.text == 'newnew' assert co.paragraph.text == 'newnew'
def insert(self): if DEBUG: print("Adding trend...") table = self.cell_object.cell.add_table(rows=2, cols=4) # add background color background_color = self.section.layout.get('style', {}).get('backgroundColor', '')[1:] # Add the main number current_sum = self.section.contents['currSum'] inner_cell = table.cell(0, 1) style_cell(inner_cell, color_hex=background_color) main_number = CellObject(inner_cell) insert_text(main_number, str(current_sum), self.style['main']) # Add the trend number previous_sum = self.section.contents['prevSum'] # Fix for the percentages divider = previous_sum if previous_sum == 0: divider = 1 change = ((current_sum - previous_sum) * 100) / divider if change < 0: direction = '▼' # Down arrow elif change == 0: direction = '= ' else: direction = '▲' # Up arrow if change > 999.0: change = '> 999' elif change < -999.0: change = '< -999' else: change = "{0:.2f}".format(change) value_percent = f'{direction}{change}%' inner_cell = table.cell(0, 2) style_cell(inner_cell, color_hex=background_color) trend_number = CellObject(inner_cell) insert_text(trend_number, value_percent, self.style['trend']) # Add the title third_cell = table.cell(1, 1) style_cell(third_cell, color_hex=background_color) table.cell(1, 2).merge(third_cell) title = CellObject(third_cell) insert_text(title, str(self.section.extra['title']), self.style['title'])
def insert(self): if DEBUG: print("Adding list...") list_data = self.section.contents if isinstance(list_data, dict) and len(list_data) != 1: list_data = [list_data] if isinstance(list_data, dict) and len(list_data) == 1: # Create the parent title wrapper_table = self.cell_object.cell.add_table(rows=2, cols=1) title_cell = wrapper_table.cell(0, 0) title_text = list(list_data.keys())[0] insert_text(title_cell, title_text, self.style['title']) # Create a list in a list because this is a grouped list co = CellObject(wrapper_table.cell(1, 0)) table_data = list_data[title_text] invoke(co, Section('list', table_data, self.section.layout, {})) else: table.invoke(self.cell_object, Section('table', list_data, self.section.layout, {'list_style': True}))
def test_cell_object_init(): d = Document() table = d.add_table(1, 1) cell = table.cell(0, 0) co = CellObject(cell) assert co.cell == cell assert isinstance(co.paragraph, Paragraph) assert isinstance(co.run, Run)
def insert(self): if DEBUG: print("Adding table...") table_data = self.section.contents if 'tableColumns' not in self.section.layout: return if 'readableHeaders' in self.section.layout: ordered = self.section.layout['tableColumns'] readable_headers = self.section.layout['readableHeaders'].values() table_columns = fix_order(ordered, readable_headers) else: table_columns = self.section.layout['tableColumns'] for i, header_text in enumerate(table_columns): if not isinstance(header_text, str): table_columns.remove(header_text) if 'title' in self.section.extra: table = self.cell_object.cell.add_table(rows=2, cols=len(table_columns)) title = table.cell(0, 0) title.merge(table.cell(0, len(table_columns) - 1)) insert_text(title, self.section.extra['title'], self.style['title']) hdr_cells = table.rows[1].cells else: table = self.cell_object.cell.add_table(rows=2, cols=len(table_columns)) hdr_cells = table.rows[0].cells table.style = DEFAULT_TABLE_STYLE if 'list_style' in self.section.extra and self.section.extra[ 'list_style']: table.style = None for i, header_text in enumerate(table_columns): insert_text(hdr_cells[i], header_text, self.style['text']) for r in table_data: row_cells = table.add_row().cells for i, header_text in enumerate(table_columns): if header_text not in r: continue # Old json format can have 'Avatars', which are images if isinstance(r[header_text], dict) and \ r[header_text]['type'] == 'image': row_temp = r[header_text] s = Section(row_temp['type'], row_temp['data'], {}, {}) co = CellObject(row_cells[i], add_run=False) image.invoke(co, s) else: insert_text(row_cells[i], r[header_text], self.style['text'])
def add_header_logos(self): # Find the headers section = self.document.sections[0] section.header_distance = Pt(0) header = section.header table = header.add_table(rows=1, cols=2, width=Inches(24)) table.alignment = WD_TABLE_ALIGNMENT.CENTER table.autofit = True left_cell = table.cell(0, 0) right_cell = table.cell(0, 1) # Add the left cell to the header left_image = CellObject(left_cell) left_cell.paragraphs[-1].alignment = WD_PARAGRAPH_ALIGNMENT.LEFT left_cell.vertical_alignment = 1 # Add the right cell to the header right_image = CellObject(right_cell) right_cell.paragraphs[-1].alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT right_cell.vertical_alignment = 1 # Add the main logo left_logo_b64 = self.options.get('demistoLogo', XSOAR_LOGO_BASE64) s = Section('image', left_logo_b64, {}, {}) image.invoke(left_image, s) # Add the customer logo right_logo_b64 = self.options.get('customerLogo', False) if right_logo_b64: s = Section( 'image', right_logo_b64, {}, { 'max_size': { 'height': MAX_CUSTOMER_LOGO_HEIGHT_INCH, # max size in inches 'width': MAX_CUSTOMER_LOGO_WIDTH_INCH } }) image.invoke(right_image, s)
def insert(self): if DEBUG: print('Adding number...') table = self.cell_object.cell.add_table(rows=1, cols=1) if DEBUG: table.style = 'Table Grid' # Add the main number inner_cell = table.cell(0, 0) style_cell(inner_cell) main_number = CellObject(inner_cell) insert_text(main_number, str(self.section.contents), self.style['main']) main_number.add_paragraph(add_run=True) insert_text(main_number, str(self.section.extra['title']), self.style['title'])
def test_cell_object_add_paragraph(): d = Document() table = d.add_table(1, 1) cell = table.cell(0, 0) co = CellObject(cell) co.run.text = 'old' assert len(d.element.xpath("//w:t[text()='old']")) == 1 assert len(d.element.xpath("//w:t[text()='new']")) == 0 co.add_paragraph() co.run.text = 'new' assert len(d.element.xpath("//w:t[text()='old']")) == 1 assert len(d.element.xpath("//w:t[text()='new']")) == 1 # Here we check it acctually came after check_order = d.element.xpath( '//w:p//w:t[text()="new"]/preceding::w:p//w:t[text()="old"]') assert check_order[0].text == 'old'
def insert(self): if DEBUG: print("Adding trend...") table = self.cell_object.cell.add_table(rows=2, cols=4) # Add the main number current_sum = self.section.contents['currSum'] inner_cell = table.cell(0, 1) style_cell(inner_cell) main_number = CellObject(inner_cell) insert_text(main_number, str(current_sum), self.style['main']) # Add the trend number previous_sum = self.section.contents['prevSum'] # Fix for the percentages if previous_sum == 0: previous_sum = 1 change = (current_sum * 100) / previous_sum if change < 0: direction = '⏷' # Down arrow elif change == 0: direction = '= ' else: direction = '⏶' # Up arrow change = "{0:.2f}".format(change) value_percent = f'{direction}{change}%' inner_cell = table.cell(0, 2) style_cell(inner_cell) trend_number = CellObject(inner_cell) insert_text(trend_number, value_percent, self.style['trend']) # Add the title third_cell = table.cell(1, 1) style_cell(third_cell) table.cell(1, 2).merge(third_cell) title = CellObject(third_cell) insert_text(title, str(self.section.extra['title']), self.style['title'])
def populate_report(self) -> None: if not self.options.get('disableHeaders', False): self.add_header_logos() paper_size = self.options.get('paper_size', 'A4') self.change_page_size(paper_size) self._decrease_layout_margins() page_count = self.sane_json.get_pages_count() - 1 orientation = self.options.get('orientation', 'portrait') for page_num, sane_page in enumerate(self.sane_json.get_sane_pages()): cols, rows = sane_page.calculate_page_grid() if DEBUG: print(f'Creating a layout grid of size ({rows},{cols})' + f' for page: {page_num}') if orientation == 'landscape': if DEBUG: print("Changing orientation to landscape.") self.orient_landscape() grid = self.document.add_table(rows=rows, cols=cols) if DEBUG: grid.style = 'Table Grid' page = self.pages[page_num] for section in page: cell, grid_pos = get_cell(grid, section) grid_pos = { "width": 0 if not len(grid_pos) == 2 else grid_pos[0], "height": 0 if not len(grid_pos) == 2 else grid_pos[1], "global_rows": rows, "global_cols": cols } merge_cells(grid, section) cell_object = CellObject(cell, add_run=False, grid_position=grid_pos, paper_size=paper_size, orientation=orientation) self._insert_section(cell_object, section) # If this isn't the last page, we can add another page break. if page_num != page_count: p = self.document.add_paragraph() r = p.add_run() if DEBUG: r.text = f'Page break ({page_num})' r.add_break(WD_BREAK.PAGE)
def insert_elem(cell_object: Union[CellObject, _Cell], section: Section, add_run=False): """ Insert text into a specified cell, can add a style and a run element too. """ # Get the relevant cell object if isinstance(cell_object, _Cell): cell_object = CellObject(cell_object, add_run=add_run) elif add_run: cell_object = cell_object cell_object.add_run() if not add_run: has_run(cell_object) # Apply the relevant style apply_style(cell_object, section) text.invoke(cell_object, section, apply_styling=False)
def test_error(): """ To check the xpath: rename the .elements to .zip and open word/document.xml """ d = Document() t = d.add_table(1, 1) test_section = Section('tedxt', "some contents", {}, {}) c = CellObject(t.cell(0, 0)) # This will invoke an error element because of the wrong type: text.invoke(c, test_section) assert len(d.element.xpath('//w:p')) == 3 # Styles or error assert len(d.element.xpath('//w:i[@w:val="0"]')) == 1 assert len(d.element.xpath('//w:strike[@w:val="0"]')) == 1 assert len(d.element.xpath('//w:color[@w:val="FF0013"]')) == 1 assert len(d.element.xpath('//w:sz[@w:val="20"]')) == 1 assert len(d.element.xpath('//w:u[@w:val="none"]')) == 1
def wrap(self): if DEBUG: print('Wrapping quote...') self.cell_object.add_paragraph() cell = self.cell_object.cell.add_table(1, 1).cell(0, 0) quote_color = name_to_hex("cornsilk") new_cell = insert_cell_background(cell, quote_color) self.cell_object = CellObject(new_cell) contents = self.section.contents if isinstance(contents, str): temp_section = MarkdownSection( 'markdown', [MarkdownSection('span', contents, {}, {})], {}, {}) else: temp_section = MarkdownSection('markdown', contents, {}, {}) markdown.invoke(self.cell_object, temp_section, invoked_from_wrapper=True)
def wrap(self): if DEBUG: print("Wrapping code...") if 'inline' not in self.section.extra: self.cell_object.add_paragraph() # TODO: remove newlines from OXML cell = self.cell_object.cell.add_table(1, 1).cell(0, 0) code_color = name_to_hex("whitesmoke") new_cell = insert_cell_background(cell, code_color) self.cell_object = CellObject(new_cell) contents = self.section.contents if isinstance(contents, str): temp_section = MarkdownSection( 'markdown', [MarkdownSection('span', contents, {}, {})], {}, {}) else: temp_section = MarkdownSection('markdown', contents, {}, {}) markdown.invoke(self.cell_object, temp_section, invoked_from_wrapper=True)
def insert_table_image(item, item_key, insertion_cell): row_temp = item[item_key] s = Section(row_temp['type'], row_temp['data'], {}, {}) co = CellObject(insertion_cell, add_run=False) image.invoke(co, s)
def insert(self): if DEBUG: print("Adding table...") table_data = self.section.contents if isinstance(table_data, dict): table_data = table_data.get('data', table_data) if 'tableColumns' not in self.section.layout: # Quick dirty fix for test - will be refactored in upcoming PR self.section.layout['tableColumns'] = list(table_data[0].keys()) # Fix new lists if isinstance(table_data, dict): wrapper_table = self.cell_object.cell.add_table( rows=2, cols=len(table_data.keys())) i = 0 # Add the wrapping headers for wrapper_header, table_contents in table_data.items(): hdr = wrapper_table.cell(0, i) insert_text(hdr, wrapper_header, self.style['title']) body = wrapper_table.cell(1, i) c = CellObject(body) # Hacky but will do the job invoke(c, Section('table', table_contents, {}, {})) i += 1 return if 'readableHeaders' in self.section.layout: ordered = self.section.layout['tableColumns'] readable_headers = self.section.layout['readableHeaders'] table_columns = fix_order(ordered, readable_headers) else: table_columns = self.section.layout['tableColumns'] # Quick fix, word crashes on more than 64 columns. # See: https://stackoverflow.com/questions/36921010/docx-does-not-support-more-than-63-columns-in-a-table table_columns = table_columns[0:63] for i, header_text in enumerate(table_columns): if not isinstance(header_text, str): table_columns.remove(header_text) if 'title' in self.section.extra: table = self.cell_object.cell.add_table(rows=2, cols=len(table_columns)) title = table.cell(0, 0) title.merge(table.cell(0, len(table_columns) - 1)) insert_text(title, self.section.extra['title'], self.style['title']) hdr_cells = table.rows[1].cells else: table = self.cell_object.cell.add_table(rows=2, cols=len(table_columns)) hdr_cells = table.rows[0].cells table.style = DEFAULT_TABLE_STYLE if 'list_style' in self.section.extra and self.section.extra[ 'list_style']: table.style = None for i, header_text in enumerate(table_columns): insert_text(hdr_cells[i], header_text, self.style['text']) if len(table_columns) > 63: # TODO: add error. pass for r in table_data: row_cells = table.add_row().cells for i, header_text in enumerate(table_columns): if header_text not in r: continue # Old json format can have 'Avatars', which are images if isinstance(r[header_text], dict) and \ r[header_text]['type'] == 'image': row_temp = r[header_text] s = Section(row_temp['type'], row_temp['data'], {}, {}) co = CellObject(row_cells[i], add_run=False) image.invoke(co, s) else: insert_text(row_cells[i], r[header_text], self.style['text'])