Python Forum
How to create a table with different sizes of columns in MS word
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to create a table with different sizes of columns in MS word
#9
This myApp() manipulates the document.xml file within the zip file, which is the .docx file, and creates a new file with different column widths, which actually show up in Libre Office!

Haven't tried to open the new file in Windows. I'm happy if it works in Libre Office!

Word is putting the settings somewhere else, not in document.xml, because, when I open the file in Windows, without manipulating document.xml, it displays correctly. This may be a version problem.

Maybe someone here could help me tidy this up a bit?? I never worked with zipfile before!

from zipfile import ZipFile 
import os
import re

# got to change the overall table width too!
def myApp():
    path2files = "/home/pedro/myPython/zipfile/"
    # change to zfile directory
    os.chdir(path2files)
    # specifying the zip file name 
    zfile = "example_copy.docx"
    # opening the zip file in READ mode
    # closes automatically
    with ZipFile(zfile, 'r') as zf: 
        # printing all the contents of the zip file 
        zf.printdir()
        # extracting document.xml
        zf.extract('word/document.xml')
        # returns bytes
        docdata = zf.read('word/document.xml')
        print(f'opened the zip file word/document.xml as {type(docdata)}') 

    # set new column sizes
    newcolsizes = [500, 300, 600]
    twidth = sum(newcolsizes)
    # search pattern
    regex1 = b'<w:tblW w:w="\d+" w:type="dxa"/>'
    # set the table width to twidth which is: sum(newcolsizes) (only 1 of these, so far, could be more +2500   
    matches = re.finditer(regex1, docdata, re.MULTILINE)
    for num, match in enumerate(matches):
        print(num, match.group(), type(match[0]))
        # I don't understand what the numbers mean, maybe Pt
        # but trial and error shows with these column sizes +2500 works
        widthstring = str(twidth + 2500)
        print(f'widthstring is {widthstring}, type(widthstring) is {type(widthstring)}')
        byte_val = widthstring.encode()
        print(f'byte_val is {byte_val}, type(byte_val) is {type(byte_val)}')
        # pattern must be bytes or you get an error: b'\d+'
        newbytes = re.sub(b'\d+', byte_val, match[0], flags=0)
        print(newbytes)
        newdata = re.sub(match[0], newbytes, docdata, count=1)
        # reassign or only the last one will be changed
        docdata = newdata
    # find the column size lines in docdata and change them to the desired values from the list newcolsizes
    regex2 = b'<w:gridCol w:w="\d+"/>'
    matches = re.finditer(regex2, docdata, re.MULTILINE)
    for num, match in enumerate(matches):
        print(num, match.group(), type(match[0]))
        widthstring = str(newcolsizes[num])
        print(f'widthstring is {widthstring}, type(widthstring) is {type(widthstring)}')
        byte_val = widthstring.encode()
        print(f'byte_val is {byte_val}, type(byte_val) is {type(byte_val)}')
        # pattern must be bytes or you get an error: b'\d+'
        newbytes = re.sub(b'\d+', byte_val, match[0], flags=0)
        print(newbytes)
        newdata = re.sub(match[0], newbytes, docdata, count=1)
        # reassign or only the last one will be changed
        docdata = newdata

    # reopen to create a new file which doesn't have word/document.xml
    # basically, make a copy but leave out the original word/document.xml 
    # then add docdata from above to the new zip file as word/document.xml 
    zin = ZipFile (zfile, 'r')
    zout = ZipFile ('example_copy2.docx', 'w')
    for item in zin.infolist():
        print(item.filename)
        if item.filename != 'word/document.xml':
            buffer = zin.read(item.filename)
            zout.writestr(item, buffer)
        elif item.filename == 'word/document.xml':
            zout.writestr(item, docdata)
    # close the files
    # seems to work. At least displays correctly in Libre Office, have not tried in Windows
    zin.close()
    zout.close()
If there are several tables, this may get more complicated!
Reply


Messages In This Thread
RE: How to create a table with different sizes of columns in MS word - by Pedroski55 - Dec-08-2023, 07:31 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Create Choices from .ods file columns cspower 3 1,773 Dec-28-2023, 09:59 PM
Last Post: deanhystad
  Create csv file with 4 columns for process mining thomaskissas33 3 1,817 Nov-06-2023, 09:36 PM
Last Post: deanhystad
Thumbs Up Convert word into pdf and copy table to outlook body in a prescribed format email2kmahe 1 1,652 Sep-22-2023, 02:33 PM
Last Post: carecavoador
  Printing effect sizes for variables in an anova eyavuz21 2 1,717 Feb-01-2023, 02:12 PM
Last Post: eyavuz21
  Output difference from 2 lists of different sizes with words gracenz 5 2,461 Sep-02-2022, 05:09 PM
Last Post: Larz60+
  group by create pivot table python dawid294 1 2,106 Jun-22-2022, 06:13 PM
Last Post: Larz60+
  Sum the values in a pandas pivot table specific columns klllmmm 1 6,277 Nov-19-2021, 04:43 PM
Last Post: klllmmm
Question Problem: Check if a list contains a word and then continue with the next word Mangono 2 3,632 Aug-12-2021, 04:25 PM
Last Post: palladium
  SaltStack: MySQL returner save less data into Database table columns xtc14 2 3,006 Jul-02-2021, 02:19 PM
Last Post: xtc14
  Create SQLite columns from a list or tuple? snakes 6 12,347 May-04-2021, 12:06 PM
Last Post: snakes

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020