MS Word Mail Merge exluding TextBox in Tables until last row

29 Views Asked by At

Hopefully a simple issue I've just overlooked where a different perspective may help.

I've written one LabelGenerator.py with the purpose of generating an A4 document that contains a series of labels. Simple enough.

It writes all of type STR data correctly, however has an issue with Text Boxes contained within the table. They are excluded from the Table EXCEPT for the last row. This is true no matter the number of rows.

The purpose of these Text Boxes is to include images in them. Now I am aware the MailMerge that I am using does not support this at the moment, but still having the boxes as a placeholder is ideal over it's complete absence.

So the question is; Is there a solution to this? Does MailMerge have support for this? Or are textboxes within a table a bust?

Alternatively, if someone knows of a module that can do this same MailMerge AND add images, I would love you eternally if you shared :)

The Code is as follows:

def MailMerge(self):
        
        exampleData = [{            
            'Image'     : 'Add Image Here',
            'Customer'  : 'Test Company',
            'PO'        : 'PO 01',
            'PartDesc'  : 'Test Part',
            'CustPart'  : 'TST00010',
            'PartQty'   : 3
        },{
            'Image'     : 'Add Image Here',
            'Customer'  : 'Test Company',
            'PO'        : 'PO 02',
            'PartDesc'  : 'Test Part',
            'CustPart'  : 'TST00020',
            'PartQty'   : 1
        },{
            'Image'     : 'Add Image Here',
            'Customer'  : 'Test Company',
            'PO'        : 'PO 03',
            'PartDesc'  : 'Test Part',
            'CustPart'  : 'TST00030',
            'PartQty'   : 4
        }]

This is taken and duplicated into another array, one instance of each per Qty. So in this example the array perLabel contains 3x TST00010, 1x TST00020, 4x TST00030.

        # Create an array of each individual Label
        listLabels = exampleData
        perLabel = []
        for item in listLabels:
            for n in range(item['PartQty']):
                perLabel.append(item)


        # Calculate the number of operations 
        ## - Two labels per row, so we HALF the total qty to get Number of rows
        numLabels = len(perLabel)
        numOps = 0

        if (numLabels % 2) == 0: numOps = numLabels/2
        else:                    numOps = (numLabels/2) + 0.5 # Must be a whole number


        # Assign Lables to temp vars 'cell_Left' and 'cell_Right'
        ## These contain the correct MergeField names depending on which side the Label will be placed on
        numRem = numLabels
        mergeList = []

        for n in range(int(numOps)):
            print(f"rem. {numRem}")


            ## No Longer use 'cell_Right' as it was adding ONE label per row, leaving its neighbour empty
            ### Instead, cell_Left now contains both row's data
            cell_Left = {
                'Image_1'    : '',
                'Customer_1' : '',
                'PO_1'       : '',
                'PartDesc_1' : '',
                'CustPart_1' : '',
                'PartQty_1'  : ''
            }
            # cell_Right = {
            #     'Image_2'    : '',
            #     'Customer_2' : '',
            #     'PO_2'       : '',
            #     'PartDesc_2' : '',
            #     'CustPart_2' : '',
            #     'PartQty_2'  : ''
            # }

            # MailMerge Left cell and Right cell
            if numRem >= 2:
                # Assign Data Values to CellLeft/Right
                ## find a way to index each item
                ## (n * 2) = y, process y and y+1
                ## (0 * 2) = 0 - so we do 0 and 1
                ## (1 * 2) = 2 - so we do 2 and 3
                ## (2 * 2) = 4 - so we do 4 and 5
                ## (3 * 2) = 6 - so we do 6 and 7

                left  = n*2
                right = (n*2)+1

                # Whitepaces are intentional - they are used to format the labels within MS Word
                cell_Left['Image_1']    = perLabel[left]['Image']
                cell_Left['Customer_1'] = f"     Customer:              {perLabel[left]['Customer']}"
                cell_Left['PO_1']       = f"     Purchase Order:    {perLabel[left]['PO']}"
                cell_Left['PartDesc_1'] = f"     Part description:    {perLabel[left]['PartDesc']}"
                cell_Left['CustPart_1'] = f"     Cust. Part n#:        {perLabel[left]['CustPart']}"
                cell_Left['PartQty_1']  = f"     Part quantity:         {str(perLabel[left]['PartQty'])}"

                cell_Left['Image_2']    = perLabel[right]['Image']
                cell_Left['Customer_2'] = f"     Customer:              {perLabel[right]['Customer']}"
                cell_Left['PO_2']       = f"     Purchase Order:    {perLabel[right]['PO']}"
                cell_Left['PartDesc_2'] = f"     Part description:    {perLabel[right]['PartDesc']}"
                cell_Left['CustPart_2'] = f"     Cust. Part n#:        {perLabel[right]['CustPart']}"
                cell_Left['PartQty_2']  = f"     Part quantity:         {str(perLabel[right]['PartQty'])}"

                mergeList.append(cell_Left)
                # mergeList.append(cell_Right) 

                numRem -= 2

            # MailMerge Left cell only
            else:

                cell_Left['Image_1']    = perLabel[left]['Image']
                cell_Left['Customer_1'] = f"     Customer:              {perLabel[n*2]['Customer']}"
                cell_Left['PO_1']       = f"     Purchase Order:    {perLabel[n*2]['PO']}"
                cell_Left['PartDesc_1'] = f"     Part description:    {perLabel[n*2]['PartDesc']}"
                cell_Left['CustPart_1'] = f"     Cust. Part n#:        {perLabel[n*2]['CustPart']}"
                cell_Left['PartQty_1']  = f"     Part quantity:         {str(perLabel[n*2]['PartQty'])}"

                mergeList.append(cell_Left)
                numRem -= 1

                # We are done here in the For()
                ## Note the for() should break without this, but we shall leave her here for the sake of it
                break

        # return #Use for Debug
        doc = MailMerge(self.temPath)

        doc.merge_rows('Image_1', mergeList)
        doc.write('X:\Scripts\mergedoc.docx')

Screenshots of the Template and Result, respectively: Images are with "Ctrl+A" for clarity regarding Text Boxes (They have no border)

Template File Screenshot

Result File Screenshot

0

There are 0 best solutions below