Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AttributeError: 'DocumentPart' object has no attribute '_numbering_part' #68

Open
retsyo opened this issue Jul 5, 2021 · 4 comments
Open

Comments

@retsyo
Copy link

retsyo commented Jul 5, 2021

the simple code

import glob

from docxcompose.composer import Composer
from docx import Document

lstFile = list(glob.glob('r:/*.docx'))

master = Document(lstFile[0])
composer = Composer(master)

for fnDoc in lstFile[1:]:
    doc1 = Document(fnDoc)
    composer.append(doc1)

composer.save("r:/combined.docx")

can't run as expected, instead, it says

>e:\prg\py\Anaconda3_64\python.exe -u "mergeDocx.py"
Traceback (most recent call last):
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\shared.py", line 169, in get_prop_value
    return getattr(obj, cache_attr_name)
AttributeError: 'DocumentPart' object has no attribute '_numbering_part'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\parts\document.py", line 100, in numbering_part
    return self.part_related_by(RT.NUMBERING)
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\opc\part.py", line 121, in part_related_by
    return self.rels.part_with_reltype(reltype)
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\opc\rel.py", line 63, in part_with_reltype
    rel = self._get_rel_of_type(reltype)
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\opc\rel.py", line 116, in _get_rel_of_type
    raise KeyError(tmpl % reltype)
KeyError: "no relationship of type 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering' in collection"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "mergeDocx.py", line 13, in <module>
    composer.append(doc1)
  File "R:\docxcompose-master\docxcompose\composer.py", line 51, in append
    self.insert(index, doc, remove_property_fields=remove_property_fields)
  File "R:\docxcompose-master\docxcompose\composer.py", line 72, in insert
    self.add_numberings(doc, element)
  File "R:\docxcompose-master\docxcompose\composer.py", line 317, in add_numberings
    src_numbering_part = doc.part.numbering_part
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\shared.py", line 171, in get_prop_value
    value = f(obj)
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\parts\document.py", line 102, in numbering_part
    numbering_part = NumberingPart.new()
  File "e:\prg\py\pure_pylib\_io\_docx\python-openxml\python-docx\docx\parts\numbering.py", line 26, in new
    raise NotImplementedError
NotImplementedError
>Exit code: 1

campanya pushed a commit to campanya/docxcompose that referenced this issue Aug 24, 2021
@campanya
Copy link

Could you upload the .docx files ? Thank you

@geovens
Copy link

geovens commented Feb 13, 2023

This is a file that triggers the same error message.
Edit: file deleted because this is resolved.

@KaHuier
Copy link

KaHuier commented Dec 12, 2023

This is an issue with 'python-docx'. You can temporarily fix it using the following methods, and I have already submitted a PR in 'docxcompose' to fix this issue.

from docxcompose.composer import Composer
from docxcompose.utils import xpath
from docxcompose.utils import NS
from copy import deepcopy
import glob
from docx import Document


def add_numberings(self, doc, element):
    """Add numberings from the given document used in the given element."""
    # Search for numbering references
    num_ids = set([n.val for n in xpath(element, './/w:numId')])
    if not num_ids:
        return

    next_num_id, next_anum_id = self._next_numbering_ids()
    try:
        src_numbering_part = doc.part.numbering_part
    except NotImplementedError:
        src_numbering_part = self.numbering_part()

    for num_id in num_ids:
        if num_id in self.num_id_mapping:
            continue

        # Find the referenced <w:num> element
        res = src_numbering_part.element.xpath(
            './/w:num[@w:numId="%s"]' % num_id)
        if not res:
            continue
        num_element = deepcopy(res[0])
        num_element.numId = next_num_id

        self.num_id_mapping[num_id] = next_num_id

        anum_id = num_element.xpath('//w:abstractNumId')[0]
        if anum_id.val not in self.anum_id_mapping:
            # Find the referenced <w:abstractNum> element
            res = src_numbering_part.element.xpath(
                './/w:abstractNum[@w:abstractNumId="%s"]' % anum_id.val)
            if not res:
                continue
            anum_element = deepcopy(res[0])
            self.anum_id_mapping[anum_id.val] = next_anum_id
            anum_id.val = next_anum_id
            # anum_element.abstractNumId = next_anum_id
            anum_element.set('{%s}abstractNumId' % NS['w'], str(next_anum_id))

            # Make sure we have a unique nsid so numberings restart properly
            nsid = anum_element.find('.//w:nsid', NS)
            if nsid is not None:
                nsid.set(
                    '{%s}val' % NS['w'],
                    "{0:08X}".format(int(10 ** 8 * random.random()))
                )

            self._insert_abstract_num(anum_element)
        else:
            anum_id.val = self.anum_id_mapping[anum_id.val]

        self._insert_num(num_element)

    # Fix references
    for num_id_ref in xpath(element, './/w:numId'):
        num_id_ref.val = self.num_id_mapping.get(
            num_id_ref.val, num_id_ref.val)


Composer.add_numberings = add_numberings


lstFile = list(glob.glob('r:/*.docx'))

master = Document(lstFile[0])
composer = Composer(master)

for fnDoc in lstFile[1:]:
    doc1 = Document(fnDoc)
    composer.append(doc1)

composer.save("r:/combined.docx")

@geovens
Copy link

geovens commented Dec 16, 2023

That's great. I may need this next month.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants