Appending a column in xlsx file using Python

Great. I've changed it to 'while cell_pos.value:' and this works just perfect for my script.
Out of curiosity if I wanted to say go until all the cells E, G, and F are empty, how would I go about that ?

I really appreciate how tolerant you have been and extremely helpful since the past couple of weeks following up on my issues and helping me out with tutorials. Thank you, thank you very much and good luck and best wishes! :slight_smile:

Congratulations!

while cell_pos.value:

will run the "while" loop as long as cell_pos.value is True that is, it is non-empty.

In order to check "all of cells E, G, F are empty" we use the logical operator "and" to combine the three cell values:
1) cell_pos.value
2) cell_alt.value
3) cell_ref.value

Such a condition is called a "compound" condition.
So:

while cell_pos.value and cell_alt.value and cell_ref.value:

will enter the "while" loop as long as all of cells E, G, F are non-empty i.e. they have some value in them. The moment any one of the cells E, G, F is empty, the loop stops.

and

while cell_pos.value or cell_alt.value or cell_ref.value:

will enter the "while" loop as long as any one of cells E, G, F is non-empty. The moment all of cells E, G, F are empty, the loop stops.

Your program will loop through the rows checking only pos value.
So if, in a row, the pos value is non-empty but alt and/or ref values are empty, it will still form the key and try to check if the key exists in the dictionary dict_pos.
This may or may not work, depending on how the dictionary was formed from "scores.txt" text file.

Here's the complete program for your reference:

#!/usr/bin/python
import os
import csv
from openpyxl import load_workbook
from datetime import datetime
from collections import namedtuple

# Variables
sheet_directory = '<absolute_path_till_sheet_directory>'
txt_file = '<absolute_path_till_text_directory>/scores.txt'

def process_xl_sheets():
    # Process the text file and form the dictionary of positions
    dict_pos = {}
    Scores = namedtuple("Scores", ["POS", "ALT", "REF"])
    first_line = True
    with open(txt_file) as txt_filename:
        for line in txt_filename:
            if not line.strip():   # Skip empty lines
                continue
            if first_line:         # Skip the header
                first_line = False
                continue
            line = line.rstrip('\n')
            x = line.split('\t')
            cpos = Scores(POS=x[0], ALT=x[2], REF=x[1])
            dict_pos[cpos] = x[3]

    # Now process all Excel files
    pos_col_no = 'E'
    alt_col_no = 'G'
    ref_col_no = 'F'
    score_col_no = 'V'
    row_no = 4
    for sheet_root, sheet_dirs, sheet_files in os.walk(sheet_directory):
        for sheet_file in sheet_files:
            if sheet_file.endswith('.xlsx'):
                sheet_xl_file = os.path.join(sheet_root, sheet_file)
                wb = load_workbook(sheet_xl_file, data_only=True)
                ws = wb.get_sheet_by_name('raw_data')
                pos = ws[pos_col_no + str(row_no)].value
                alt = ws[alt_col_no + str(row_no)].value
                ref = ws[ref_col_no + str(row_no)].value
                while pos or alt or ref:
                    cpos = Scores(POS=str(pos), ALT=alt, REF=ref)
                    if cpos in dict_pos:
                        ws[score_col_no + str(row_no)].value = dict_pos[cpos]
                    else:
                        ws[score_col_no + str(row_no)].value = 'Unknown_' + datetime.now().strftime("%B") + datetime.now().strftime("%Y")
                    row_no += 1
                    pos = ws[pos_col_no + str(row_no)].value
                    alt = ws[alt_col_no + str(row_no)].value
                    ref = ws[ref_col_no + str(row_no)].value
    wb.save(sheet_xl_file)

# Main section
process_xl_sheets()

Got it! Thank you!

Wow! I have not read the entire thread, but the library Pandas is designed for these types of things. You read in the Excel data into a Pandas Dataframe. And you also read in the text file into a Dataframe, both of them is one command each. And then you solve the problem by a few lines of Pandas code, probably you can do that in one line. So your entire solution would be 5-10 lines or so. If you post this question on stack exchange, someone will surely post the entire solution in a few hours.