Converting Word Lists to Text

@ln22 You can use the following code to unlink only LISTNUM fields:

for f in doc.range.fields:
    if f.type == aw.fields.FieldType.FIELD_LIST_NUM:
        f.unlink()

If I run the following code below on the specific paragraph range.fields the (CC) sadly changes to (A).

    for p in aspose_doc.get_child_nodes(aw.NodeType.PARAGRAPH, True):
        para = p.as_paragraph()
        if para.is_list_item and para.list_label.label_string != "":
            if para.list_label.label_string == "(CC)":
                range_text = para.range.text
                run_0 = para.runs[0]
                for f in para.range.fields:
                    if f.type == aw.fields.FieldType.FIELD_LIST_NUM:
                        f.unlink()

Also, the code above then leads to list below the unlinked list to remove it from the list and start one level up. For example, if I unlink an β€œ(ii) (A)” then the next list label which should be β€˜(iii)’ becomes β€˜(ii)’. Is there a way to relink?

It seems f.display_result holds the listnum actual text. Can this be inserted into the paragraph text in the proper place somehow?

@ln22 You can create a Run with this text and insert it after the field. Something like this:

for f in para.range.fields:
    if f.type == aw.fields.FieldType.FIELD_LIST_NUM:
        para.insert_after(aw.Run(doc, f.display_result), f.end)

That code works accept it clears the styling if the f.display_result text. How could I make the run that same style as the current run? For example if f.display_result=β€˜(a)’ is italic, the current code removes this italic styling, and I would prefer is stay with the original styling.

@ln22 You can clone the run from the first value to keep the formatting:

for f in para.range.fields:
    if f.type == aw.fields.FieldType.FIELD_LIST_NUM:
        r =  f.end.previous_sibling.clone(False).as_run()
        r.text = f.display_result
        para.insert_after(r, f.end)

Great! How could I do the same for this code:

fake_list_label_run = aw.Run(aspose_doc, label)
para.list_format.remove_numbers()
para.prepend_child(fake_list_label_run)

@ln22 Sure, you can modify the code like this:

fake_list_label_run = para.runs[0].clone(False).as_run()
fake_list_label_run.text = label
para.list_format.remove_numbers()

Hello @alexey.noskov ,

I when I run the following code:

r =  f.end.previous_sibling.clone(False).as_run()

I sometimes get the following error:
RuntimeError: Proxy error(InvalidCastException): Unable to cast object of type 'Aspose.Words.BookmarkStart' to type 'Aspose.Words.Run'.

Do you know why this would occur?

@ln22 The problem occurs because the previous sibling of field end is BookmarkStart. Please modify the code like this:

r = f.end.previous_sibling
while r != None and r.node_type != aw.NodeType.RUN :
    r = r.previous_sibling
r =  r.clone(False).as_run()

Thanks this works great!

1 Like

Hello,

I am getting the following error when running the code above:

RuntimeError("Proxy error(InvalidCastException): Unable to cast object of type 'Aspose.Words.BookmarkStart' to type 'Aspose.Words.Run'.")

It specifically fails on: r = r.clone(False).as_run()

Any idea how to fix that?

My current full function is:

def add_list_num_text_to_paragraph(para: aw.Paragraph) -> None:
    """
    Adds the list number text to the paragraph.

    :param para: The paragraph to add the list number text to.
    :type para: aw.Paragraph
    :return: None
    :rtype: None
    """
    for f in para.range.fields:
        if f.type == aw.fields.FieldType.FIELD_LIST_NUM:
            r = f.end.previous_sibling
            max_previous_siblings = 5
            iter_index = 0
            # Handle when the previous object is of type 'Aspose.Words.BookmarkStart' not 'Aspose.Words.Run'
            # by pulling the previous sibling before the bookmark start which is a run and not none
            while r is not None and r.node_type != aw.NodeType.RUN and iter_index <= max_previous_siblings:
                r = r.previous_sibling
                iter_index += 1
            r = r.clone(False).as_run()
            r.text = f.display_result
            para.insert_after(r, f.end)

@ln22 The exceptions says that r in your document is not a Run, but BookmarkStart. The following peace of code should handle the case:

# Handle when the previous object is of type 'Aspose.Words.BookmarkStart' not 'Aspose.Words.Run'
# by pulling the previous sibling before the bookmark start which is a run and not none
while r is not None and r.node_type != aw.NodeType.RUN and iter_index <= max_previous_siblings:
    r = r.previous_sibling
    iter_index += 1

Could you please attach the problematic input document to inspect it’s structure? We will check it and provide you more information. Probably you should simply increase max_previous_siblings value to get the Run.

Alternatively, you can try using DocumentBuilder:

def add_list_num_text_to_paragraph(para: aw.Paragraph) -> None:
    """
    Adds the list number text to the paragraph.

    :param para: The paragraph to add the list number text to.
    :type para: aw.Paragraph
    :return: None
    :rtype: None
    """
    builder = aw.DocumentBuilder(para.document)
    for f in para.range.fields:
        if f.type == aw.fields.FieldType.FIELD_LIST_NUM:
            print(f.display_result)
            builder.move_to_field(f, True)
            builder.write(f.display_result)

This is a great solution! Thanks!

1 Like