From 3be35debe8204bfe63f986d9677ef8c68cdc6043 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Thu, 4 Jan 2018 10:34:29 +0100 Subject: [PATCH 01/12] =?UTF-8?q?ajout=20du=20composant=20de=20fa=C3=A7ade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .project | 17 +++ .pydevproject | 8 ++ docx/facade.py | 277 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 .project create mode 100644 .pydevproject create mode 100644 docx/facade.py diff --git a/.project b/.project new file mode 100644 index 000000000..50fa98662 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + python-docx + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 000000000..de9d7361d --- /dev/null +++ b/.pydevproject @@ -0,0 +1,8 @@ + + +Default +python interpreter + +/${PROJECT_DIR_NAME} + + diff --git a/docx/facade.py b/docx/facade.py new file mode 100644 index 000000000..c9bb87733 --- /dev/null +++ b/docx/facade.py @@ -0,0 +1,277 @@ +from docx import Document +from docx.shared import Cm, Pt +from docx.enum.dml import MSO_THEME_COLOR_INDEX as MSO_THEME_COLOR +from docx.enum.section import WD_SECTION_START +from docx.enum.section import WD_ORIENTATION +from PIL import Image + +class DocxEntityParagraphNormal: + def __init__(self, text, style=None): + self.text, self.style = text, style + def render(self, p, doc): + p.add_run(self.text, self.style) + +class DocxEntityParagraphItalic: + def __init__(self, text, style=None): + self.text, self.style = text, style + def render(self, p, doc): + p.add_run(self.text, self.style).italic = True + +class DocxEntityParagraphBold: + def __init__(self, text, style=None): + self.text, self.style = text, style + def render(self, p, doc): + p.add_run(self.text, self.style).bold = True + +class DocxEntityParagraphItem: + def __init__(self, text, style="List Paragraph"): + self.text, self.style = text, style + def render(self, p, doc): + doc.add_paragraph(self.text, self.style) + +class DocxEntityParagraphRef: + def __init__(self, ref, key): + self.key, self.ref = key, ref + def render(self, p, doc): + if self.ref: + p.add_run(self.ref(self.key)) + +class DocxEntityParagraph: + def __init__(self, text, style=None, _ref=None): + self.text, self.style = text, style + self._ref = _ref + self.subs = [] + def b(self, text, style=None): + self.subs.append(DocxEntityParagraphBold(text, style)) + return self + def it(self, text, style=None): + self.subs.append(DocxEntityParagraphItalic(text, style)) + return self + def n(self, text, style=None): + self.subs.append(DocxEntityParagraphNormal(text, style)) + return self + def item(self, text="", style="List Paragraph"): + self.subs.append(DocxEntityParagraphItem(text, style)) + return self + def ref(self, key): + self.subs.append(DocxEntityParagraphRef(self._ref, key)) + return self + def render(self, doc): + p = doc.add_paragraph(self.text, self.style) + for obj in self.subs: + obj.render(p, doc) + +class DocxEntityPicture: + + DEFAULT_WIDTH = Cm(17.8) + DEFAULT_WIDTH_LANDSCAPE = Cm(25.5) + MAX_HEIGHT = Cm(13) + MAX_HEIGHT_PORTRAIT = Cm(26) + + def __init__(self, filename, width = DEFAULT_WIDTH, height = None, caption=None): + self.width, self.height, self.filename, self.caption = width, height, filename, caption + self.imageRoot = 'images/' + self.key = "?"; + + def render(self, doc): + imagePath = self.imageRoot + self.filename + + # autosize en fonction de l'orientation + last_section = doc.sections[-1] + if last_section.orientation == WD_ORIENTATION.LANDSCAPE: # @UndefinedVariable + print("Autoresize image in landscape : "+self.filename) + width = self.DEFAULT_WIDTH_LANDSCAPE + else: + width = self.width + + # ajuster de sorte que l'image ne sorte pas de la page verticalement + im = Image.open(imagePath) + ratio = im.size[0] / float(im.size[1]) + computedHeight = width / ratio + #print(ratio, computedHeight, self.MAX_HEIGHT) + if last_section.orientation == WD_ORIENTATION.LANDSCAPE: # @UndefinedVariable + if computedHeight > self.MAX_HEIGHT or (self.height and self.height > self.MAX_HEIGHT): + print("debordement en hauteur : "+ self.filename) + width = None + height = self.MAX_HEIGHT + else: + height = self.height + else: + if computedHeight > int(self.MAX_HEIGHT_PORTRAIT) or (self.height and self.height > self.MAX_HEIGHT_PORTRAIT): + print("debordement en hauteur") + width = None + height = self.MAX_HEIGHT + else: + height = self.height + + doc.add_picture(imagePath, width, height) + if self.caption: + doc.add_paragraph('Figure '+self.key+" : "+ self.caption, 'Caption') + +class DocsEntityPageSection: + def __init__(self, start_type = WD_SECTION_START.NEW_PAGE, orientation = WD_ORIENTATION.PORTRAIT): # @UndefinedVariable + self.start_type, self.orientation = start_type, orientation + def render(self, doc): + last_section = doc.sections[-1] + last_orientation = last_section.orientation + s = doc.add_section(self.start_type) + if not last_orientation == self.orientation: + new_width, new_height = s.page_height, s.page_width + s.orientation, s.page_height, s.page_width = self.orientation, new_height, new_width + print("changed page orientation") + + + +class DocsEntityPageBreak: + def render(self, doc): + doc.add_page_break() + +class DocxEntityDocumentTitle: + def __init__(self, title, level = 0): + self.title, self.level = title, level + def render(self, doc): + doc.add_heading(self.title, level=self.level) + +class DocxEntitySection(DocxEntityDocumentTitle): + def __init__(self, title): + DocxEntityDocumentTitle.__init__(self, title, 1) + +class DocxEntitySubSection(DocxEntityDocumentTitle): + def __init__(self, title): + DocxEntityDocumentTitle.__init__(self, title, 2) + +class DocxEntitySubSubSection(DocxEntityDocumentTitle): + def __init__(self, title): + DocxEntityDocumentTitle.__init__(self, title, 3) + +class DocxEntityTable: + def __init__(self, callback, rows, cols, caption=None, style=None): + self.callback, self.caption, self.rows, self.cols, self.style = callback, caption, rows, cols, style + self.key = "?" + def render(self, doc): + table = doc.add_table(self.rows, self.cols, self.style) + self.callback(table) + if self.caption: + doc.add_paragraph('Tableau '+self.key+" : "+ self.caption, 'Caption') + +class DocxEntityListOfFigures: + def render(self, doc): + doc.add_paragraph('Liste des figures', 'Illustration Index Heading') + + +class DocxEntity: + def __init__(self, filename): + self.filename = filename + self.entities = [] + + def getFilename(self): + return self.filename + + def append(self, obj): + self.entities.append(obj) + return obj + + def initialize(self, doc): + # caption defaults + style = doc.styles['Caption'] + font = style.font + font.name = 'Calibri' + font.size = Pt(10) + font.italic = True + font.bold = False + print(font.color.theme_color) + font.color.theme_color = MSO_THEME_COLOR.ACCENT_2 # @UndefinedVariable + paragraph_format = style.paragraph_format + paragraph_format.space_before = Pt(1) + paragraph_format.space_after = Pt(12) + # text defaults + style = doc.styles['Normal'] + font = style.font + font.name = 'Calibri' + font.size = Pt(11) + font.italic = False + font.bold = False + # section defaults + #s = doc.sections[-1] + #s.left_margin = Cm(1) + #s.right_margin = Cm(1) + #s.top_margin = Cm(1) + #s.bottom_margin = Cm(1) + # heading 1 default + style = doc.styles['Heading 1'] + paragraph_format = style.paragraph_format + paragraph_format.space_before = Pt(6) + paragraph_format.space_after = Pt(12) + # heading 2 default + style = doc.styles['Heading 2'] + paragraph_format = style.paragraph_format + paragraph_format.space_before = Pt(6) + paragraph_format.space_after = Pt(12) + + def render(self, doc): + self.initialize(doc) + for obj in self.entities: + obj.render(doc) + +class Docx: + + class ORIENT: + LANDSCAPE = WD_ORIENTATION.LANDSCAPE # @UndefinedVariable + PORTRAIT = WD_ORIENTATION.PORTRAIT # @UndefinedVariable + + class START_TYPE: + NEW_PAGE = WD_SECTION_START.NEW_PAGE # @UndefinedVariable + CONTINUOUS = WD_SECTION_START.CONTINUOUS # @UndefinedVariable + ODD_PAGE = WD_SECTION_START.ODD_PAGE # @UndefinedVariable + + def __init__(self, filename, _ref = None): + self.filename = filename + self._ref = _ref + self.entity = DocxEntity(filename) + + def title(self, title): + self.entity.append(DocxEntityDocumentTitle(title)) + + def sec(self, title): + self.entity.append(DocxEntitySection(title)) + + def subsec(self, title): + self.entity.append(DocxEntitySubSection(title)) + + def subsubsec(self, title): + self.entity.append(DocxEntitySubSubSection(title)) + + def pic(self, filename, width=DocxEntityPicture.DEFAULT_WIDTH, height=None, caption=None): + return self.entity.append(DocxEntityPicture(filename, width, height, caption)) + + def par(self, text = "", style=None): + return self.entity.append(DocxEntityParagraph(text, style, self._ref)) + + def b(self, text = "", style=None, pretext=""): + p = DocxEntityParagraph(pretext, style) + return self.entity.append(p.b(text)) + + def pageBreak(self): + self.entity.append(DocsEntityPageBreak()) + + def pageSection(self, start_type = START_TYPE.NEW_PAGE, orientation = ORIENT.PORTRAIT): + self.entity.append(DocsEntityPageSection(start_type, orientation)) + + def table(self, callback, rows, cols, caption=None, style=None): + return self.entity.append(DocxEntityTable(callback, rows, cols, caption, style)) + + def list_of_figures(self): + self.entity.append(DocxEntityListOfFigures()) + + def save(self, target=None): + if self.filename: + d = Document(self.filename) + else: + d = Document() + self.entity.render(d) + if target: + filename = target + else: + filename = self.filename + d.save(filename) + From ab3716e59f75c8e332c4d3b8f541dc4a5c8f2604 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Fri, 5 Jan 2018 15:23:28 +0100 Subject: [PATCH 02/12] modification de add_heading pour lui rajouter un style --- docx/document.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docx/document.py b/docx/document.py index ba94a7990..3ae0d5df1 100644 --- a/docx/document.py +++ b/docx/document.py @@ -28,7 +28,7 @@ def __init__(self, element, part): self._part = part self.__body = None - def add_heading(self, text='', level=1): + def add_heading(self, text='', level=1, style=None): """ Return a heading paragraph newly added to the end of the document, containing *text* and having its paragraph style determined by @@ -37,9 +37,10 @@ def add_heading(self, text='', level=1): `Heading {level}`. Raises |ValueError| if *level* is outside the range 0-9. """ - if not 0 <= level <= 9: - raise ValueError("level must be in range 0-9, got %d" % level) - style = 'Title' if level == 0 else 'Heading %d' % level + if not style: + if not 0 <= level <= 9: + raise ValueError("level must be in range 0-9, got %d" % level) + style = 'Title' if level == 0 else 'Heading %d' % level return self.add_paragraph(text, style) def add_page_break(self): From 0fb88b14fa0e5f7fada69f0f57e0de4c87f8c358 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Fri, 5 Jan 2018 15:23:42 +0100 Subject: [PATCH 03/12] =?UTF-8?q?am=C3=A9lioration=20de=20la=20facade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docx/facade.py | 152 ++++++++++++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 57 deletions(-) diff --git a/docx/facade.py b/docx/facade.py index c9bb87733..23a92737d 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -1,9 +1,12 @@ + +from PIL import Image from docx import Document from docx.shared import Cm, Pt from docx.enum.dml import MSO_THEME_COLOR_INDEX as MSO_THEME_COLOR from docx.enum.section import WD_SECTION_START from docx.enum.section import WD_ORIENTATION -from PIL import Image +from docx.oxml import OxmlElement +from docx.oxml.ns import qn class DocxEntityParagraphNormal: def __init__(self, text, style=None): @@ -62,24 +65,22 @@ def render(self, doc): obj.render(p, doc) class DocxEntityPicture: - + DEFAULT_WIDTH = Cm(17.8) DEFAULT_WIDTH_LANDSCAPE = Cm(25.5) MAX_HEIGHT = Cm(13) - MAX_HEIGHT_PORTRAIT = Cm(26) + MAX_HEIGHT_PORTRAIT = Cm(19.5) #Cm(24) def __init__(self, filename, width = DEFAULT_WIDTH, height = None, caption=None): self.width, self.height, self.filename, self.caption = width, height, filename, caption - self.imageRoot = 'images/' - self.key = "?"; + self.key = "?" def render(self, doc): - imagePath = self.imageRoot + self.filename + imagePath = 'images/' + self.filename # autosize en fonction de l'orientation last_section = doc.sections[-1] - if last_section.orientation == WD_ORIENTATION.LANDSCAPE: # @UndefinedVariable - print("Autoresize image in landscape : "+self.filename) + if last_section.orientation == WD_ORIENTATION.LANDSCAPE: # @UndefinedVariable pylint: disable=no-member width = self.DEFAULT_WIDTH_LANDSCAPE else: width = self.width @@ -88,28 +89,25 @@ def render(self, doc): im = Image.open(imagePath) ratio = im.size[0] / float(im.size[1]) computedHeight = width / ratio - #print(ratio, computedHeight, self.MAX_HEIGHT) - if last_section.orientation == WD_ORIENTATION.LANDSCAPE: # @UndefinedVariable + if last_section.orientation == WD_ORIENTATION.LANDSCAPE: # @UndefinedVariable pylint: disable=no-member if computedHeight > self.MAX_HEIGHT or (self.height and self.height > self.MAX_HEIGHT): - print("debordement en hauteur : "+ self.filename) width = None height = self.MAX_HEIGHT else: height = self.height else: if computedHeight > int(self.MAX_HEIGHT_PORTRAIT) or (self.height and self.height > self.MAX_HEIGHT_PORTRAIT): - print("debordement en hauteur") width = None - height = self.MAX_HEIGHT + height = self.MAX_HEIGHT_PORTRAIT else: height = self.height doc.add_picture(imagePath, width, height) if self.caption: - doc.add_paragraph('Figure '+self.key+" : "+ self.caption, 'Caption') + doc.add_paragraph(Docx.DEFAULT_FIGURE+self.key+" : "+ self.caption, Docx.DEFAULT_STYLE_LEGENDE_FIGURE) class DocsEntityPageSection: - def __init__(self, start_type = WD_SECTION_START.NEW_PAGE, orientation = WD_ORIENTATION.PORTRAIT): # @UndefinedVariable + def __init__(self, start_type = WD_SECTION_START.NEW_PAGE, orientation = WD_ORIENTATION.PORTRAIT): # @UndefinedVariable pylint: disable=no-member self.start_type, self.orientation = start_type, orientation def render(self, doc): last_section = doc.sections[-1] @@ -118,31 +116,28 @@ def render(self, doc): if not last_orientation == self.orientation: new_width, new_height = s.page_height, s.page_width s.orientation, s.page_height, s.page_width = self.orientation, new_height, new_width - print("changed page orientation") - - class DocsEntityPageBreak: def render(self, doc): doc.add_page_break() class DocxEntityDocumentTitle: - def __init__(self, title, level = 0): - self.title, self.level = title, level + def __init__(self, title, level = 0, style=None): + self.title, self.level, self.style = title, level, style def render(self, doc): - doc.add_heading(self.title, level=self.level) + doc.add_heading(self.title, level=self.level, style=self.style) class DocxEntitySection(DocxEntityDocumentTitle): - def __init__(self, title): - DocxEntityDocumentTitle.__init__(self, title, 1) + def __init__(self, title, style=None): + DocxEntityDocumentTitle.__init__(self, title, 1, style) class DocxEntitySubSection(DocxEntityDocumentTitle): - def __init__(self, title): - DocxEntityDocumentTitle.__init__(self, title, 2) + def __init__(self, title, style=None): + DocxEntityDocumentTitle.__init__(self, title, 2, style) class DocxEntitySubSubSection(DocxEntityDocumentTitle): - def __init__(self, title): - DocxEntityDocumentTitle.__init__(self, title, 3) + def __init__(self, title, style=None): + DocxEntityDocumentTitle.__init__(self, title, 3, style) class DocxEntityTable: def __init__(self, callback, rows, cols, caption=None, style=None): @@ -152,13 +147,38 @@ def render(self, doc): table = doc.add_table(self.rows, self.cols, self.style) self.callback(table) if self.caption: - doc.add_paragraph('Tableau '+self.key+" : "+ self.caption, 'Caption') + doc.add_paragraph(Docx.DEFAULT_TABLEAU+self.key+" : "+ self.caption, Docx.DEFAULT_STYLE_LEGENDE_TABLEAU) -class DocxEntityListOfFigures: +class DocxEntityTOC: + def __init__(self, titre, command): + self.command, self.titre = command, titre def render(self, doc): - doc.add_paragraph('Liste des figures', 'Illustration Index Heading') - - + if self.titre: + doc.add_paragraph(self.titre, "Illustration Index Heading") + paragraph = doc.add_paragraph() + run = paragraph.add_run() + fldChar = OxmlElement('w:fldChar') # creates a new element + fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element + instrText = OxmlElement('w:instrText') + instrText.set(qn('xml:space'), 'preserve') # sets attribute on element + instrText.text = self.command # change 1-3 depending on heading levels you need + + fldChar2 = OxmlElement('w:fldChar') + fldChar2.set(qn('w:fldCharType'), 'separate') + fldChar3 = OxmlElement('w:t') + fldChar3.text = "Right-click to update field." + fldChar2.append(fldChar3) + + fldChar4 = OxmlElement('w:fldChar') + fldChar4.set(qn('w:fldCharType'), 'end') + + r_element = run._r + r_element.append(fldChar) + r_element.append(instrText) + r_element.append(fldChar2) + r_element.append(fldChar4) + p_element = paragraph._p + class DocxEntity: def __init__(self, filename): self.filename = filename @@ -174,13 +194,13 @@ def append(self, obj): def initialize(self, doc): # caption defaults style = doc.styles['Caption'] - font = style.font - font.name = 'Calibri' - font.size = Pt(10) - font.italic = True - font.bold = False - print(font.color.theme_color) - font.color.theme_color = MSO_THEME_COLOR.ACCENT_2 # @UndefinedVariable + #font = style.font + #font.name = 'Calibri' + #font.size = Pt(10) + #font.italic = True + #font.bold = False + #print(font.color.theme_color) + #font.color.theme_color = MSO_THEME_COLOR.ACCENT_2 # @UndefinedVariable pylint: disable=no-member paragraph_format = style.paragraph_format paragraph_format.space_before = Pt(1) paragraph_format.space_after = Pt(12) @@ -215,33 +235,52 @@ def render(self, doc): class Docx: + # https://support.office.com/en-us/article/Field-codes-TOC-Table-of-Contents-field-1f538bc4-60e6-4854-9f64-67754d78d05c?ui=en-US&rs=en-US&ad=US + # \\o... Builds a table of contents from paragraphs formatted with built-in heading styles. + # For example, { TOC \o "1-3" } lists only headings formatted with the styles Heading 1 through Heading 3. + # If no heading range is specified, all heading levels used in the document are listed. Enclose the + # range numbers in quotation marks. + # \\h Inserts TOC entries as hyperlinks. + # \\z Hides tab leader and page numbers in Web layout view. + # \\u Builds a table of contents by using the applied paragraph TE000128012. + DEFAULT_COMMAND = 'TOC \\o "1-3" \\h \\z \\u' + DEFAULT_TOC_TITLE = "Table des matières" + DEFAULT_STYLE_LEGENDE_TABLEAU = "Légende Tableau" + DEFAULT_STYLE_LEGENDE_FIGURE = "Légende Figure" + DEFAULT_FIGURE = "Figure " + DEFAULT_TABLEAU = "Tableau " + CHAPITRE_STYLE = "Chapitre" + class ORIENT: - LANDSCAPE = WD_ORIENTATION.LANDSCAPE # @UndefinedVariable - PORTRAIT = WD_ORIENTATION.PORTRAIT # @UndefinedVariable + LANDSCAPE = WD_ORIENTATION.LANDSCAPE # @UndefinedVariable pylint: disable=no-member + PORTRAIT = WD_ORIENTATION.PORTRAIT # @UndefinedVariable pylint: disable=no-member class START_TYPE: - NEW_PAGE = WD_SECTION_START.NEW_PAGE # @UndefinedVariable - CONTINUOUS = WD_SECTION_START.CONTINUOUS # @UndefinedVariable - ODD_PAGE = WD_SECTION_START.ODD_PAGE # @UndefinedVariable + NEW_PAGE = WD_SECTION_START.NEW_PAGE # @UndefinedVariable pylint: disable=no-member + CONTINUOUS = WD_SECTION_START.CONTINUOUS # @UndefinedVariable pylint: disable=no-member + ODD_PAGE = WD_SECTION_START.ODD_PAGE # @UndefinedVariable pylint: disable=no-member def __init__(self, filename, _ref = None): self.filename = filename self._ref = _ref self.entity = DocxEntity(filename) + + def toc(self, titre=DEFAULT_TOC_TITLE, command = DEFAULT_COMMAND): + self.entity.append(DocxEntityTOC(titre, command)) - def title(self, title): - self.entity.append(DocxEntityDocumentTitle(title)) + def title(self, title, style=CHAPITRE_STYLE): + self.entity.append(DocxEntityDocumentTitle(title, style=style)) - def sec(self, title): - self.entity.append(DocxEntitySection(title)) + def sec(self, title, style=None): + self.entity.append(DocxEntitySection(title, style)) - def subsec(self, title): - self.entity.append(DocxEntitySubSection(title)) + def subsec(self, title, style=None): + self.entity.append(DocxEntitySubSection(title, style)) - def subsubsec(self, title): - self.entity.append(DocxEntitySubSubSection(title)) + def subsubsec(self, title, style=None): + self.entity.append(DocxEntitySubSubSection(title, style)) - def pic(self, filename, width=DocxEntityPicture.DEFAULT_WIDTH, height=None, caption=None): + def _pic(self, filename, width=DocxEntityPicture.DEFAULT_WIDTH, height=None, caption=None): return self.entity.append(DocxEntityPicture(filename, width, height, caption)) def par(self, text = "", style=None): @@ -260,14 +299,13 @@ def pageSection(self, start_type = START_TYPE.NEW_PAGE, orientation = ORIENT.POR def table(self, callback, rows, cols, caption=None, style=None): return self.entity.append(DocxEntityTable(callback, rows, cols, caption, style)) - def list_of_figures(self): - self.entity.append(DocxEntityListOfFigures()) - - def save(self, target=None): + def save(self, target=None, pre=None): if self.filename: d = Document(self.filename) else: d = Document() + if pre: + pre(d) self.entity.render(d) if target: filename = target From 37b635ca23edbb2909bb62c56e5d1ece71ec7bac Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Sat, 6 Jan 2018 23:08:37 +0100 Subject: [PATCH 04/12] =?UTF-8?q?typage=20de=20toutes=20les=20fonctions=20?= =?UTF-8?q?de=20la=20fa=C3=A7ade?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pydevproject | 2 +- docx/__init__.py | 18 ++--- docx/api.py | 4 +- docx/facade.py | 190 +++++++++++++++++++++++++++-------------------- docx/table.py | 26 +++---- 5 files changed, 133 insertions(+), 107 deletions(-) diff --git a/.pydevproject b/.pydevproject index de9d7361d..ce2424cfb 100644 --- a/.pydevproject +++ b/.pydevproject @@ -1,6 +1,6 @@ -Default +python3 python interpreter /${PROJECT_DIR_NAME} diff --git a/docx/__init__.py b/docx/__init__.py index cfa48729d..32c73626e 100644 --- a/docx/__init__.py +++ b/docx/__init__.py @@ -7,15 +7,15 @@ # register custom Part classes with opc package reader -from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT -from docx.opc.part import PartFactory -from docx.opc.parts.coreprops import CorePropertiesPart - -from docx.parts.document import DocumentPart -from docx.parts.image import ImagePart -from docx.parts.numbering import NumberingPart -from docx.parts.settings import SettingsPart -from docx.parts.styles import StylesPart +from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT # type: ignore +from docx.opc.part import PartFactory # type: ignore +from docx.opc.parts.coreprops import CorePropertiesPart # type: ignore + +from docx.parts.document import DocumentPart # type: ignore +from docx.parts.image import ImagePart # type: ignore +from docx.parts.numbering import NumberingPart # type: ignore +from docx.parts.settings import SettingsPart # type: ignore +from docx.parts.styles import StylesPart # type: ignore def part_class_selector(content_type, reltype): diff --git a/docx/api.py b/docx/api.py index 63e18c406..5cc06bd43 100644 --- a/docx/api.py +++ b/docx/api.py @@ -10,8 +10,8 @@ import os -from docx.opc.constants import CONTENT_TYPE as CT -from docx.package import Package +from docx.opc.constants import CONTENT_TYPE as CT # type: ignore +from docx.package import Package # type: ignore def Document(docx=None): diff --git a/docx/facade.py b/docx/facade.py index 23a92737d..478b4fcf5 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -1,81 +1,97 @@ -from PIL import Image -from docx import Document -from docx.shared import Cm, Pt -from docx.enum.dml import MSO_THEME_COLOR_INDEX as MSO_THEME_COLOR -from docx.enum.section import WD_SECTION_START -from docx.enum.section import WD_ORIENTATION -from docx.oxml import OxmlElement -from docx.oxml.ns import qn +from PIL import Image # type: ignore +from docx import Document # type: ignore +from docx.shared import Cm, Pt # type: ignore +from docx.enum.dml import MSO_THEME_COLOR_INDEX as MSO_THEME_COLOR # type: ignore +from docx.enum.section import WD_SECTION_START # type: ignore +from docx.enum.section import WD_ORIENTATION # type: ignore +from docx.oxml import OxmlElement # type: ignore +from docx.oxml.ns import qn # type: ignore +from typing import Callable, List, cast +from docx.text.paragraph import Paragraph # type: ignore +from docx.table import Table # type: ignore +import abc -class DocxEntityParagraphNormal: - def __init__(self, text, style=None): +ref_t = Callable[[str], str] + +class IDocxParRenderer(object, metaclass=abc.ABCMeta): + @abc.abstractmethod + def render(self, p: Paragraph, doc: Document) -> None: + raise NotImplementedError('users must define render to use this base class') + +class DocxEntityParagraphNormal(IDocxParRenderer): + def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p, doc): + def render(self, p: Paragraph, _: Document) -> None: p.add_run(self.text, self.style) -class DocxEntityParagraphItalic: - def __init__(self, text, style=None): +class DocxEntityParagraphItalic(IDocxParRenderer): + def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p, doc): + def render(self, p: Paragraph, _: Document) -> None: p.add_run(self.text, self.style).italic = True -class DocxEntityParagraphBold: - def __init__(self, text, style=None): +class DocxEntityParagraphBold(IDocxParRenderer): + def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p, doc): + def render(self, p: Paragraph, _: Document) -> None: p.add_run(self.text, self.style).bold = True -class DocxEntityParagraphItem: - def __init__(self, text, style="List Paragraph"): +class DocxEntityParagraphItem(IDocxParRenderer): + def __init__(self, text: str, style: str="List Paragraph") -> None: self.text, self.style = text, style - def render(self, p, doc): + def render(self, _: Paragraph, doc: Document) -> None: doc.add_paragraph(self.text, self.style) -class DocxEntityParagraphRef: - def __init__(self, ref, key): +class DocxEntityParagraphRef(IDocxParRenderer): + def __init__(self, ref: ref_t, key: str) -> None: self.key, self.ref = key, ref - def render(self, p, doc): + def render(self, p: Paragraph, _: Document) -> None: if self.ref: p.add_run(self.ref(self.key)) -class DocxEntityParagraph: - def __init__(self, text, style=None, _ref=None): +class IDocxEntityRenderer(object, metaclass=abc.ABCMeta): + @abc.abstractmethod + def render(self, doc: Document): + raise NotImplementedError('users must define render to use this base class') + +class DocxEntityParagraph(IDocxEntityRenderer): + def __init__(self, text: str, style: str=None, _ref: ref_t=None) -> None: self.text, self.style = text, style self._ref = _ref - self.subs = [] - def b(self, text, style=None): + self.subs = [] # type: List[IDocxParRenderer] + def b(self, text: str, style: str=None) -> 'DocxEntityParagraph': # forward declaration self.subs.append(DocxEntityParagraphBold(text, style)) return self - def it(self, text, style=None): + def it(self, text: str, style: str=None) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphItalic(text, style)) return self - def n(self, text, style=None): + def n(self, text: str, style: str=None) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphNormal(text, style)) return self - def item(self, text="", style="List Paragraph"): + def item(self, text: str="", style: str="Bullet0") -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphItem(text, style)) return self - def ref(self, key): + def ref(self, key: str) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphRef(self._ref, key)) return self - def render(self, doc): + def render(self, doc: Document) -> None: p = doc.add_paragraph(self.text, self.style) for obj in self.subs: obj.render(p, doc) -class DocxEntityPicture: +class DocxEntityPicture(IDocxEntityRenderer): - DEFAULT_WIDTH = Cm(17.8) - DEFAULT_WIDTH_LANDSCAPE = Cm(25.5) - MAX_HEIGHT = Cm(13) - MAX_HEIGHT_PORTRAIT = Cm(19.5) #Cm(24) + DEFAULT_WIDTH = Cm(17.8) # type: Cm + DEFAULT_WIDTH_LANDSCAPE = Cm(25.5) # type: Cm + MAX_HEIGHT = Cm(13) # type: Cm + MAX_HEIGHT_PORTRAIT = Cm(19.5) # type: Cm - def __init__(self, filename, width = DEFAULT_WIDTH, height = None, caption=None): + def __init__(self, filename: str, width: Cm = DEFAULT_WIDTH, height : Cm= None, caption: str=None) -> None: self.width, self.height, self.filename, self.caption = width, height, filename, caption self.key = "?" - def render(self, doc): + def render(self, doc: Document) -> None: imagePath = 'images/' + self.filename # autosize en fonction de l'orientation @@ -106,10 +122,10 @@ def render(self, doc): if self.caption: doc.add_paragraph(Docx.DEFAULT_FIGURE+self.key+" : "+ self.caption, Docx.DEFAULT_STYLE_LEGENDE_FIGURE) -class DocsEntityPageSection: +class DocsEntityPageSection(IDocxEntityRenderer): def __init__(self, start_type = WD_SECTION_START.NEW_PAGE, orientation = WD_ORIENTATION.PORTRAIT): # @UndefinedVariable pylint: disable=no-member self.start_type, self.orientation = start_type, orientation - def render(self, doc): + def render(self, doc: Document) -> None: last_section = doc.sections[-1] last_orientation = last_section.orientation s = doc.add_section(self.start_type) @@ -117,11 +133,11 @@ def render(self, doc): new_width, new_height = s.page_height, s.page_width s.orientation, s.page_height, s.page_width = self.orientation, new_height, new_width -class DocsEntityPageBreak: - def render(self, doc): +class DocsEntityPageBreak(IDocxEntityRenderer): + def render(self, doc: Document) -> None: doc.add_page_break() -class DocxEntityDocumentTitle: +class DocxEntityDocumentTitle(IDocxEntityRenderer): def __init__(self, title, level = 0, style=None): self.title, self.level, self.style = title, level, style def render(self, doc): @@ -139,20 +155,25 @@ class DocxEntitySubSubSection(DocxEntityDocumentTitle): def __init__(self, title, style=None): DocxEntityDocumentTitle.__init__(self, title, 3, style) -class DocxEntityTable: - def __init__(self, callback, rows, cols, caption=None, style=None): +class TableConstructor(object, metaclass=abc.ABCMeta): + @abc.abstractmethod + def render(self, t: Table) -> None: + raise NotImplementedError('users must define render to use this base class') + +class DocxEntityTable((IDocxEntityRenderer)): + def __init__(self, callback: TableConstructor, rows: int, cols: int, caption: str=None, style: str=None) -> None: self.callback, self.caption, self.rows, self.cols, self.style = callback, caption, rows, cols, style self.key = "?" - def render(self, doc): + def render(self, doc: Document) -> None: table = doc.add_table(self.rows, self.cols, self.style) - self.callback(table) + self.callback.render(table) if self.caption: doc.add_paragraph(Docx.DEFAULT_TABLEAU+self.key+" : "+ self.caption, Docx.DEFAULT_STYLE_LEGENDE_TABLEAU) -class DocxEntityTOC: - def __init__(self, titre, command): +class DocxEntityTOC(IDocxEntityRenderer): + def __init__(self, titre:str, command:str) -> None: self.command, self.titre = command, titre - def render(self, doc): + def render(self, doc: Document) -> None: if self.titre: doc.add_paragraph(self.titre, "Illustration Index Heading") paragraph = doc.add_paragraph() @@ -179,19 +200,19 @@ def render(self, doc): r_element.append(fldChar4) p_element = paragraph._p -class DocxEntity: - def __init__(self, filename): +class DocxEntity(IDocxEntityRenderer): + def __init__(self, filename: str) -> None: self.filename = filename - self.entities = [] + self.entities = [] # type: List[IDocxEntityRenderer] - def getFilename(self): + def getFilename(self) -> str: return self.filename - def append(self, obj): + def append(self, obj: IDocxEntityRenderer) -> IDocxEntityRenderer: self.entities.append(obj) return obj - def initialize(self, doc): + def initialize(self, doc: Document) -> None: # caption defaults style = doc.styles['Caption'] #font = style.font @@ -228,12 +249,12 @@ def initialize(self, doc): paragraph_format.space_before = Pt(6) paragraph_format.space_after = Pt(12) - def render(self, doc): + def render(self, doc: Document) -> None: self.initialize(doc) for obj in self.entities: obj.render(doc) -class Docx: +class Docx(object): # https://support.office.com/en-us/article/Field-codes-TOC-Table-of-Contents-field-1f538bc4-60e6-4854-9f64-67754d78d05c?ui=en-US&rs=en-US&ad=US # \\o... Builds a table of contents from paragraphs formatted with built-in heading styles. @@ -260,50 +281,55 @@ class START_TYPE: CONTINUOUS = WD_SECTION_START.CONTINUOUS # @UndefinedVariable pylint: disable=no-member ODD_PAGE = WD_SECTION_START.ODD_PAGE # @UndefinedVariable pylint: disable=no-member - def __init__(self, filename, _ref = None): + def __init__(self, filename: str, _ref: Callable[[str], str] = None) -> None: self.filename = filename self._ref = _ref self.entity = DocxEntity(filename) - def toc(self, titre=DEFAULT_TOC_TITLE, command = DEFAULT_COMMAND): + def toc(self, titre: str=DEFAULT_TOC_TITLE, command: str= DEFAULT_COMMAND) -> None: self.entity.append(DocxEntityTOC(titre, command)) - def title(self, title, style=CHAPITRE_STYLE): - self.entity.append(DocxEntityDocumentTitle(title, style=style)) + def title(self, title: str, style: str=CHAPITRE_STYLE) -> DocxEntityDocumentTitle: + return cast(DocxEntityDocumentTitle, self.entity.append(DocxEntityDocumentTitle(title, style=style))) - def sec(self, title, style=None): - self.entity.append(DocxEntitySection(title, style)) + def sec(self, title: str, style: str=None) -> DocxEntitySection: + return cast(DocxEntitySection, self.entity.append(DocxEntitySection(title, style))) - def subsec(self, title, style=None): - self.entity.append(DocxEntitySubSection(title, style)) + def subsec(self, title: str, style: str=None) -> DocxEntitySubSection: + return cast(DocxEntitySubSection, self.entity.append(DocxEntitySubSection(title, style))) - def subsubsec(self, title, style=None): - self.entity.append(DocxEntitySubSubSection(title, style)) + def subsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + return cast(DocxEntitySubSubSection, self.entity.append(DocxEntitySubSubSection(title, style))) - def _pic(self, filename, width=DocxEntityPicture.DEFAULT_WIDTH, height=None, caption=None): - return self.entity.append(DocxEntityPicture(filename, width, height, caption)) + def pic(self, filename: str, width:Cm=DocxEntityPicture.DEFAULT_WIDTH, height:Cm=None, caption:str=None) -> DocxEntityPicture: + """ + Utiliser plutôt add_pic de chapters.metier.pictures_tables + """ + return cast(DocxEntityPicture, self.entity.append(DocxEntityPicture(filename, width, height, caption))) - def par(self, text = "", style=None): - return self.entity.append(DocxEntityParagraph(text, style, self._ref)) + def par(self, text:str = "", style:str=None) -> DocxEntityParagraph: + return cast(DocxEntityParagraph, self.entity.append(DocxEntityParagraph(text, style, self._ref))) - def b(self, text = "", style=None, pretext=""): + def b(self, text:str = "", style:str=None, pretext:str="") -> DocxEntityParagraph: p = DocxEntityParagraph(pretext, style) - return self.entity.append(p.b(text)) + return cast(DocxEntityParagraph, self.entity.append(p.b(text))) - def pageBreak(self): - self.entity.append(DocsEntityPageBreak()) + def pageBreak(self) -> DocsEntityPageBreak: + return cast(DocsEntityPageBreak, self.entity.append(DocsEntityPageBreak())) - def pageSection(self, start_type = START_TYPE.NEW_PAGE, orientation = ORIENT.PORTRAIT): - self.entity.append(DocsEntityPageSection(start_type, orientation)) + def pageSection(self, start_type: 'START_TYPE' = START_TYPE.NEW_PAGE, orientation: 'ORIENT' = ORIENT.PORTRAIT) -> DocsEntityPageSection: + return cast(DocsEntityPageSection, self.entity.append(DocsEntityPageSection(start_type, orientation))) - def table(self, callback, rows, cols, caption=None, style=None): - return self.entity.append(DocxEntityTable(callback, rows, cols, caption, style)) + def table(self, callback: TableConstructor, rows: int, cols: int, caption=None, style=None) -> DocxEntityTable: + return cast(DocxEntityTable, self.entity.append(DocxEntityTable(callback, rows, cols, caption, style))) - def save(self, target=None, pre=None): + def save(self, target:str=None, pre: Callable[[Document],None]=None) -> None: if self.filename: d = Document(self.filename) else: d = Document() + #for i in d.styles: + # print(i) if pre: pre(d) self.entity.render(d) diff --git a/docx/table.py b/docx/table.py index d0b472fc8..543a24efe 100644 --- a/docx/table.py +++ b/docx/table.py @@ -6,11 +6,11 @@ from __future__ import absolute_import, print_function, unicode_literals -from .blkcntnr import BlockItemContainer -from .enum.style import WD_STYLE_TYPE -from .oxml.simpletypes import ST_Merge -from .shared import Inches, lazyproperty, Parented - +from .blkcntnr import BlockItemContainer # type: ignore +from .enum.style import WD_STYLE_TYPE # type: ignore +from .oxml.simpletypes import ST_Merge # type: ignore +from .shared import Inches, lazyproperty, Parented # type: ignore +from typing import Tuple, List, cast class Table(Parented): """ @@ -33,7 +33,7 @@ def add_column(self, width): tc.width = width return _Column(gridCol, self) - def add_row(self): + def add_row(self) -> '_Row': """ Return a |_Row| instance, newly added bottom-most to the table. """ @@ -80,7 +80,7 @@ def cell(self, row_idx, col_idx): cell_idx = col_idx + (row_idx * self._column_count) return self._cells[cell_idx] - def column_cells(self, column_idx): + def column_cells(self, column_idx: int) -> List['_Cell']: """ Sequence of cells in the column at *column_idx* in this table. """ @@ -106,7 +106,7 @@ def row_cells(self, row_idx): return self._cells[start:end] @lazyproperty - def rows(self): + def rows(self) -> '_Rows': """ |_Rows| instance containing the sequence of rows in this table. """ @@ -250,7 +250,7 @@ def tables(self): return super(_Cell, self).tables @property - def text(self): + def text(self) -> str: """ The entire contents of this cell as a string of text. Assigning a string to this property replaces all existing content with a single @@ -259,7 +259,7 @@ def text(self): return '\n'.join(p.text for p in self.paragraphs) @text.setter - def text(self, text): + def text(self, text: str) -> None: """ Write-only. Set entire contents of cell to the string *text*. Any existing content or revisions are replaced. @@ -291,11 +291,11 @@ def __init__(self, gridCol, parent): self._gridCol = gridCol @property - def cells(self): + def cells(self) -> Tuple[_Cell]: """ Sequence of |_Cell| instances corresponding to cells in this column. """ - return tuple(self.table.column_cells(self._index)) + return cast(Tuple[_Cell], tuple(self.table.column_cells(self._index))) @property def table(self): @@ -407,7 +407,7 @@ def __init__(self, tbl, parent): super(_Rows, self).__init__(parent) self._tbl = tbl - def __getitem__(self, idx): + def __getitem__(self, idx: int) -> _Row: """ Provide indexed access, (e.g. 'rows[0]') """ From d08d836f971c3421ff7129be057dfdbaefea0ae3 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Mon, 8 Jan 2018 16:09:08 +0100 Subject: [PATCH 05/12] ajout de NOBullet --- docx/facade.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docx/facade.py b/docx/facade.py index 478b4fcf5..281a96838 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -271,6 +271,7 @@ class Docx(object): DEFAULT_FIGURE = "Figure " DEFAULT_TABLEAU = "Tableau " CHAPITRE_STYLE = "Chapitre" + NOBULLET_STYLE = "NoBullet" class ORIENT: LANDSCAPE = WD_ORIENTATION.LANDSCAPE # @UndefinedVariable pylint: disable=no-member From b6a2f09db7aada98c58fd5270dbb34c385e14481 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Mon, 15 Jan 2018 09:33:11 +0100 Subject: [PATCH 06/12] ajout nom style tableau --- docx/facade.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docx/facade.py b/docx/facade.py index 281a96838..f38e31caa 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -14,6 +14,8 @@ ref_t = Callable[[str], str] +TABLE_STD_STYLE = "Table Grid" + class IDocxParRenderer(object, metaclass=abc.ABCMeta): @abc.abstractmethod def render(self, p: Paragraph, doc: Document) -> None: From 3a49be8547a5993675261a20835bfc6ae5955a5f Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Thu, 1 Feb 2018 09:38:23 +0100 Subject: [PATCH 07/12] maj --- docx/facade.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docx/facade.py b/docx/facade.py index f38e31caa..84fe642aa 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -157,6 +157,18 @@ class DocxEntitySubSubSection(DocxEntityDocumentTitle): def __init__(self, title, style=None): DocxEntityDocumentTitle.__init__(self, title, 3, style) +class DocxEntitySubSubSubSection(DocxEntityDocumentTitle): + def __init__(self, title, style=None): + DocxEntityDocumentTitle.__init__(self, title, 4, style) + +class DocxEntitySubSubSubSubSection(DocxEntityDocumentTitle): + def __init__(self, title, style=None): + DocxEntityDocumentTitle.__init__(self, title, 5, style) + +class DocxEntitySubSubSubSubSubSection(DocxEntityDocumentTitle): + def __init__(self, title, style=None): + DocxEntityDocumentTitle.__init__(self, title, 6, style) + class TableConstructor(object, metaclass=abc.ABCMeta): @abc.abstractmethod def render(self, t: Table) -> None: @@ -304,6 +316,15 @@ def subsec(self, title: str, style: str=None) -> DocxEntitySubSection: def subsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: return cast(DocxEntitySubSubSection, self.entity.append(DocxEntitySubSubSection(title, style))) + def subsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + return cast(DocxEntitySubSubSubSection, self.entity.append(DocxEntitySubSubSubSection(title, style))) + + def subsubsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + return cast(DocxEntitySubSubSubSubSection, self.entity.append(DocxEntitySubSubSubSubSection(title, style))) + + def subsubsubsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + return cast(DocxEntitySubSubSubSubSubSection, self.entity.append(DocxEntitySubSubSubSubSubSection(title, style))) + def pic(self, filename: str, width:Cm=DocxEntityPicture.DEFAULT_WIDTH, height:Cm=None, caption:str=None) -> DocxEntityPicture: """ Utiliser plutôt add_pic de chapters.metier.pictures_tables From bb3636ea413b77e634579e255768cc9a8f1396f1 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Tue, 6 Feb 2018 11:15:00 +0100 Subject: [PATCH 08/12] factorisation --- docx/facade.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docx/facade.py b/docx/facade.py index 84fe642aa..0c6dd3ba7 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -11,6 +11,10 @@ from docx.text.paragraph import Paragraph # type: ignore from docx.table import Table # type: ignore import abc +import uno # type: ignore +import Danny.OOo.OOoLib +from Danny.OOo import OOoLib as ooo +from Danny.OOo.OOoLib import makePropertyValue ref_t = Callable[[str], str] @@ -338,6 +342,9 @@ def b(self, text:str = "", style:str=None, pretext:str="") -> DocxEntityParagrap p = DocxEntityParagraph(pretext, style) return cast(DocxEntityParagraph, self.entity.append(p.b(text))) + def df(self, name, definition): + return self.b("Définition "+name+" : ").n(definition) + def pageBreak(self) -> DocsEntityPageBreak: return cast(DocsEntityPageBreak, self.entity.append(DocsEntityPageBreak())) @@ -363,3 +370,44 @@ def save(self, target:str=None, pre: Callable[[Document],None]=None) -> None: filename = self.filename d.save(filename) + def export_pdf(self, target:str=None, source:str=None): + ## open docx with libreoffice + if source: + path = source + else: + if self.filename: + path = self.filename + else: + raise "Error source filename" + if target: + target_path = target + else: + target_path = "file://"+self.filename + + print("Loading file "+path) + p = makePropertyValue("Hidden", True) + oDoc = ooo.loadComponentFromURL( "file://"+path, (p,) ) + + if False: + ## add a page break and insert a document + cursor = oDoc.Text.createTextCursor() + cursor.gotoStart(False) + # Inserts a paragraph break at cursor position + oDoc.Text.insertControlCharacter( cursor.End, uno.getConstantByName('com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK'), False) + cursor.gotoStart(False) + cursor.insertDocumentFromURL("file:///work/deva/dev/docs/sdd/templates/test.odt", ()) + + ## refresh all indexes (TOC, etc.) + dispatcher = Danny.OOo.OOoLib.createUnoService( "com.sun.star.frame.DispatchHelper" ) + #dispatcher.executeDispatch(oDoc.getCurrentController(), ".uno:UpdateAllIndexes", "", 0, ()) + dispatcher.executeDispatch(oDoc.getCurrentController(), ".uno:UpdateAll", "", 0, ()) + + ## export to PDF + p = makePropertyValue("FilterName", "writer_pdf_Export") + oDoc.storeToURL(target_path, (p,)) + + ## clean all + #oDoc.store() + oDoc.dispose() + oDoc.close(True) + From 8aedaacdccf4eac34298052703555c19d93a814d Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Sun, 11 Feb 2018 11:21:34 +0100 Subject: [PATCH 09/12] adaptation mba --- .pydevproject | 2 +- docx/opc/part.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pydevproject b/.pydevproject index ce2424cfb..183106b11 100644 --- a/.pydevproject +++ b/.pydevproject @@ -1,7 +1,7 @@ python3 -python interpreter +python 3.0 /${PROJECT_DIR_NAME} diff --git a/docx/opc/part.py b/docx/opc/part.py index 928d3c183..70bdfcb7a 100644 --- a/docx/opc/part.py +++ b/docx/opc/part.py @@ -9,7 +9,7 @@ ) from .compat import cls_method_fn -from .oxml import serialize_part_xml +from .oxml import serialize_part_xml # type: ignore from ..oxml import parse_xml from .packuri import PackURI from .rel import Relationships From b6643551d6dee61d8d6e252e5e9c273f19c1ffec Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Sun, 11 Feb 2018 16:44:04 +0100 Subject: [PATCH 10/12] ajout de gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index de25a6f76..e465aa2b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.settings/ .coverage /dist/ /docs/.build/ From ae83623fe39559829acf4908a2b9c0719df42c0d Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Sun, 18 Feb 2018 22:49:37 +0100 Subject: [PATCH 11/12] ajout couleur + underline --- docx/facade.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docx/facade.py b/docx/facade.py index 0c6dd3ba7..891fa626f 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -15,6 +15,7 @@ import Danny.OOo.OOoLib from Danny.OOo import OOoLib as ooo from Danny.OOo.OOoLib import makePropertyValue +from docx.shared import RGBColor ref_t = Callable[[str], str] @@ -37,12 +38,33 @@ def __init__(self, text: str, style: str=None) -> None: def render(self, p: Paragraph, _: Document) -> None: p.add_run(self.text, self.style).italic = True +class DocxEntityParagraphUnderline(IDocxParRenderer): + def __init__(self, text: str, style: str=None) -> None: + self.text, self.style = text, style + def render(self, p: Paragraph, _: Document) -> None: + p.add_run(self.text, self.style).underline = True + +class DocxEntityParagraphColor(IDocxParRenderer): + def __init__(self, text: str, color: RGBColor, style: str=None) -> None: + self.text, self.style, self.color = text, style, color + def render(self, p: Paragraph, _: Document) -> None: + p.add_run(self.text, self.style).font.color.rgb = self.color + class DocxEntityParagraphBold(IDocxParRenderer): def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style def render(self, p: Paragraph, _: Document) -> None: p.add_run(self.text, self.style).bold = True +class DocxEntityParagraphFont(IDocxParRenderer): + def __init__(self, text: str, font_name:str, font_size:int, style: str=None) -> None: + self.text, self.style = text, style + self.font_name, self.font_size = font_name, font_size + def render(self, p: Paragraph, _: Document) -> None: + font = p.add_run(self.text, self.style).font + font.name = self.font_name + font.size = Pt(self.font_size) + class DocxEntityParagraphItem(IDocxParRenderer): def __init__(self, text: str, style: str="List Paragraph") -> None: self.text, self.style = text, style @@ -72,6 +94,17 @@ def b(self, text: str, style: str=None) -> 'DocxEntityParagraph': # forward decl def it(self, text: str, style: str=None) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphItalic(text, style)) return self + def u(self, text: str, style: str=None) -> 'DocxEntityParagraph': + self.subs.append(DocxEntityParagraphUnderline(text, style)) + return self + def color(self, text: str, r:int=0, g:int=0, b:int=0, style: str=None) -> 'DocxEntityParagraph': + self.subs.append(DocxEntityParagraphColor(text, RGBColor(r,g,b), style)) + return self + def font(self, text:str = "", font_name:str="Calibri", font_size:int=12, style:str=None) -> 'DocxEntityParagraph': + self.subs.append(DocxEntityParagraphFont(text, font_name, font_size, style)) + return self + def red(self, text: str, style: str=None) -> 'DocxEntityParagraph': + return self.color(text, 0xff, 0, 0, style) def n(self, text: str, style: str=None) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphNormal(text, style)) return self @@ -338,6 +371,18 @@ def pic(self, filename: str, width:Cm=DocxEntityPicture.DEFAULT_WIDTH, height:Cm def par(self, text:str = "", style:str=None) -> DocxEntityParagraph: return cast(DocxEntityParagraph, self.entity.append(DocxEntityParagraph(text, style, self._ref))) + def red(self, text:str = "", style:str=None, pretext:str="") -> DocxEntityParagraph: + p = DocxEntityParagraph(pretext, style) + return cast(DocxEntityParagraph, self.entity.append(p.red(text))) + + def font(self, text:str = "", font_name:str="Calibri", font_size:int=12, style:str=None, pretext:str="") -> DocxEntityParagraph: + p = DocxEntityParagraph(pretext, style) + return cast(DocxEntityParagraph, self.entity.append(p.font(text, font_name, font_size))) + + def color(self, text: str, r:int=0, g:int=0, b:int=0, style: str=None, pretext:str="") -> 'DocxEntityParagraph': + p = DocxEntityParagraph(pretext, style) + return cast(DocxEntityParagraph, self.entity.append(p.color(text, r, g, b, style))) + def b(self, text:str = "", style:str=None, pretext:str="") -> DocxEntityParagraph: p = DocxEntityParagraph(pretext, style) return cast(DocxEntityParagraph, self.entity.append(p.b(text))) From c14f87826d71766771186f7298f9e39be0b9bc10 Mon Sep 17 00:00:00 2001 From: Daniel CHEUNG Date: Mon, 19 Feb 2018 09:51:37 +0100 Subject: [PATCH 12/12] =?UTF-8?q?corrections=20par=20rapport=20=C3=A0=20my?= =?UTF-8?q?py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docx/__init__.py | 2 +- docx/document.py | 2 +- docx/facade.py | 57 ++++++++++++++++++++++--------------------- docx/opc/part.py | 2 +- docx/oxml/__init__.py | 2 +- 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/docx/__init__.py b/docx/__init__.py index 32c73626e..77a315a34 100644 --- a/docx/__init__.py +++ b/docx/__init__.py @@ -24,7 +24,7 @@ def part_class_selector(content_type, reltype): return None -PartFactory.part_class_selector = part_class_selector +PartFactory.part_class_selector = part_class_selector # type: ignore PartFactory.part_type_for[CT.OPC_CORE_PROPERTIES] = CorePropertiesPart PartFactory.part_type_for[CT.WML_DOCUMENT_MAIN] = DocumentPart PartFactory.part_type_for[CT.WML_NUMBERING] = NumberingPart diff --git a/docx/document.py b/docx/document.py index 3ae0d5df1..b08c1290a 100644 --- a/docx/document.py +++ b/docx/document.py @@ -9,7 +9,7 @@ ) from .blkcntnr import BlockItemContainer -from .enum.section import WD_SECTION +from .enum.section import WD_SECTION # type: ignore from .enum.text import WD_BREAK from .section import Section, Sections from .shared import ElementProxy, Emu diff --git a/docx/facade.py b/docx/facade.py index 891fa626f..bf812eae0 100644 --- a/docx/facade.py +++ b/docx/facade.py @@ -1,6 +1,7 @@ from PIL import Image # type: ignore -from docx import Document # type: ignore +import docx # type: ignore +import docx.document # type: ignore from docx.shared import Cm, Pt # type: ignore from docx.enum.dml import MSO_THEME_COLOR_INDEX as MSO_THEME_COLOR # type: ignore from docx.enum.section import WD_SECTION_START # type: ignore @@ -15,7 +16,7 @@ import Danny.OOo.OOoLib from Danny.OOo import OOoLib as ooo from Danny.OOo.OOoLib import makePropertyValue -from docx.shared import RGBColor +from docx.shared import RGBColor # type: ignore ref_t = Callable[[str], str] @@ -23,44 +24,44 @@ class IDocxParRenderer(object, metaclass=abc.ABCMeta): @abc.abstractmethod - def render(self, p: Paragraph, doc: Document) -> None: + def render(self, p: Paragraph, doc: docx.document.Document) -> None: raise NotImplementedError('users must define render to use this base class') class DocxEntityParagraphNormal(IDocxParRenderer): def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: p.add_run(self.text, self.style) class DocxEntityParagraphItalic(IDocxParRenderer): def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: p.add_run(self.text, self.style).italic = True class DocxEntityParagraphUnderline(IDocxParRenderer): def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: p.add_run(self.text, self.style).underline = True class DocxEntityParagraphColor(IDocxParRenderer): def __init__(self, text: str, color: RGBColor, style: str=None) -> None: self.text, self.style, self.color = text, style, color - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: p.add_run(self.text, self.style).font.color.rgb = self.color class DocxEntityParagraphBold(IDocxParRenderer): def __init__(self, text: str, style: str=None) -> None: self.text, self.style = text, style - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: p.add_run(self.text, self.style).bold = True class DocxEntityParagraphFont(IDocxParRenderer): def __init__(self, text: str, font_name:str, font_size:int, style: str=None) -> None: self.text, self.style = text, style self.font_name, self.font_size = font_name, font_size - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: font = p.add_run(self.text, self.style).font font.name = self.font_name font.size = Pt(self.font_size) @@ -68,19 +69,19 @@ def render(self, p: Paragraph, _: Document) -> None: class DocxEntityParagraphItem(IDocxParRenderer): def __init__(self, text: str, style: str="List Paragraph") -> None: self.text, self.style = text, style - def render(self, _: Paragraph, doc: Document) -> None: + def render(self, _: Paragraph, doc: docx.document.Document) -> None: doc.add_paragraph(self.text, self.style) class DocxEntityParagraphRef(IDocxParRenderer): def __init__(self, ref: ref_t, key: str) -> None: self.key, self.ref = key, ref - def render(self, p: Paragraph, _: Document) -> None: + def render(self, p: Paragraph, _: docx.document.Document) -> None: if self.ref: p.add_run(self.ref(self.key)) class IDocxEntityRenderer(object, metaclass=abc.ABCMeta): @abc.abstractmethod - def render(self, doc: Document): + def render(self, doc: docx.document.Document): raise NotImplementedError('users must define render to use this base class') class DocxEntityParagraph(IDocxEntityRenderer): @@ -98,7 +99,7 @@ def u(self, text: str, style: str=None) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphUnderline(text, style)) return self def color(self, text: str, r:int=0, g:int=0, b:int=0, style: str=None) -> 'DocxEntityParagraph': - self.subs.append(DocxEntityParagraphColor(text, RGBColor(r,g,b), style)) + self.subs.append(DocxEntityParagraphColor(text, RGBColor(r,g,b), style)) # type: ignore return self def font(self, text:str = "", font_name:str="Calibri", font_size:int=12, style:str=None) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphFont(text, font_name, font_size, style)) @@ -114,7 +115,7 @@ def item(self, text: str="", style: str="Bullet0") -> 'DocxEntityParagraph': def ref(self, key: str) -> 'DocxEntityParagraph': self.subs.append(DocxEntityParagraphRef(self._ref, key)) return self - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: p = doc.add_paragraph(self.text, self.style) for obj in self.subs: obj.render(p, doc) @@ -130,7 +131,7 @@ def __init__(self, filename: str, width: Cm = DEFAULT_WIDTH, height : Cm= None, self.width, self.height, self.filename, self.caption = width, height, filename, caption self.key = "?" - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: imagePath = 'images/' + self.filename # autosize en fonction de l'orientation @@ -164,7 +165,7 @@ def render(self, doc: Document) -> None: class DocsEntityPageSection(IDocxEntityRenderer): def __init__(self, start_type = WD_SECTION_START.NEW_PAGE, orientation = WD_ORIENTATION.PORTRAIT): # @UndefinedVariable pylint: disable=no-member self.start_type, self.orientation = start_type, orientation - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: last_section = doc.sections[-1] last_orientation = last_section.orientation s = doc.add_section(self.start_type) @@ -173,7 +174,7 @@ def render(self, doc: Document) -> None: s.orientation, s.page_height, s.page_width = self.orientation, new_height, new_width class DocsEntityPageBreak(IDocxEntityRenderer): - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: doc.add_page_break() class DocxEntityDocumentTitle(IDocxEntityRenderer): @@ -215,7 +216,7 @@ class DocxEntityTable((IDocxEntityRenderer)): def __init__(self, callback: TableConstructor, rows: int, cols: int, caption: str=None, style: str=None) -> None: self.callback, self.caption, self.rows, self.cols, self.style = callback, caption, rows, cols, style self.key = "?" - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: table = doc.add_table(self.rows, self.cols, self.style) self.callback.render(table) if self.caption: @@ -224,7 +225,7 @@ def render(self, doc: Document) -> None: class DocxEntityTOC(IDocxEntityRenderer): def __init__(self, titre:str, command:str) -> None: self.command, self.titre = command, titre - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: if self.titre: doc.add_paragraph(self.titre, "Illustration Index Heading") paragraph = doc.add_paragraph() @@ -263,7 +264,7 @@ def append(self, obj: IDocxEntityRenderer) -> IDocxEntityRenderer: self.entities.append(obj) return obj - def initialize(self, doc: Document) -> None: + def initialize(self, doc: docx.document.Document) -> None: # caption defaults style = doc.styles['Caption'] #font = style.font @@ -300,7 +301,7 @@ def initialize(self, doc: Document) -> None: paragraph_format.space_before = Pt(6) paragraph_format.space_after = Pt(12) - def render(self, doc: Document) -> None: + def render(self, doc: docx.document.Document) -> None: self.initialize(doc) for obj in self.entities: obj.render(doc) @@ -353,13 +354,13 @@ def subsec(self, title: str, style: str=None) -> DocxEntitySubSection: def subsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: return cast(DocxEntitySubSubSection, self.entity.append(DocxEntitySubSubSection(title, style))) - def subsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + def subsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSubSection: return cast(DocxEntitySubSubSubSection, self.entity.append(DocxEntitySubSubSubSection(title, style))) - def subsubsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + def subsubsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSubSubSection: return cast(DocxEntitySubSubSubSubSection, self.entity.append(DocxEntitySubSubSubSubSection(title, style))) - def subsubsubsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSection: + def subsubsubsubsubsec(self, title:str, style:str=None) -> DocxEntitySubSubSubSubSubSection: return cast(DocxEntitySubSubSubSubSubSection, self.entity.append(DocxEntitySubSubSubSubSubSection(title, style))) def pic(self, filename: str, width:Cm=DocxEntityPicture.DEFAULT_WIDTH, height:Cm=None, caption:str=None) -> DocxEntityPicture: @@ -399,11 +400,11 @@ def pageSection(self, start_type: 'START_TYPE' = START_TYPE.NEW_PAGE, orientatio def table(self, callback: TableConstructor, rows: int, cols: int, caption=None, style=None) -> DocxEntityTable: return cast(DocxEntityTable, self.entity.append(DocxEntityTable(callback, rows, cols, caption, style))) - def save(self, target:str=None, pre: Callable[[Document],None]=None) -> None: + def save(self, target:str=None, pre: Callable[[docx.document.Document],None]=None) -> None: if self.filename: - d = Document(self.filename) + d = docx.Document(self.filename) else: - d = Document() + d = docx.Document() #for i in d.styles: # print(i) if pre: @@ -423,7 +424,7 @@ def export_pdf(self, target:str=None, source:str=None): if self.filename: path = self.filename else: - raise "Error source filename" + raise BaseException("Error source filename") if target: target_path = target else: diff --git a/docx/opc/part.py b/docx/opc/part.py index 70bdfcb7a..a15ef60db 100644 --- a/docx/opc/part.py +++ b/docx/opc/part.py @@ -178,7 +178,7 @@ class PartFactory(object): is used to construct the part, which is by default ``opc.package.Part``. """ part_class_selector = None - part_type_for = {} + part_type_for = {} # type: ignore default_part_type = Part def __new__(cls, partname, content_type, reltype, blob, package): diff --git a/docx/oxml/__init__.py b/docx/oxml/__init__.py index 528b1eac7..b67c9ec31 100644 --- a/docx/oxml/__init__.py +++ b/docx/oxml/__init__.py @@ -7,7 +7,7 @@ from __future__ import absolute_import -from lxml import etree +from lxml import etree # type: ignore from .ns import NamespacePrefixedTag, nsmap