Python - wrong logic in nested 'if' in a for-loop
Question: I am having script to read an Excel file, which cells A1 ~ A6 contains:

    
    
    OK 17
    OK 9
    BKK 17
    OK 16
    OK 12
    BKK 16
    

They are the only contents of the Excel file.

What I want to do is, to check the codes either ‘OK’ or ‘BKK’ is in the cell,
and tell me whether the code in the cell is the same with that one row above.

For example, row 2 has ‘OK’, which is the same with row 1 has ‘OK’, so it
shall tell me ‘OK found’ and ‘row no.2 and 1 found same code’.

However the result of running below skip some rows:

    
    
    from xlrd import open_workbook
    
    the_file = open_workbook('c:\\file.xls',formatting_info=True)
    the_sheet = the_file.sheet_by_index(0) 
    
    for row in range(0, the_sheet.nrows):
        a = the_sheet.cell(row, 0).value
        above_a = the_sheet.cell(row-1, 0).value
        if a[0:2] == above_a[0:2]:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code'
            if 'OK' in a:
                print 'OK found'
            else:
                print 'BKK found'
    

As the result is:

    
    
    row no.2 and 1 found same code
    OK found
    row no.5 and 4 found same code
    OK found
    

The logic is wrong. Could you please help me? Thanks.

* * *

* * *

* * *

sorry for the confusion. there are 6 values to be checked so I expect 6
results, however there are only 4. 2 were skipped.

it can be worked out like this but there shall be a way to simplify it?

    
    
    for row in range(0, the_sheet.nrows):
        a = the_sheet.cell(row, 0).value
        above_a = the_sheet.cell(row-1, 0).value
        if a[0:2] == above_a[0:2] and 'OK' in a:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' OK found'
        if a[0:2] == above_a[0:2] and 'BKK' in a:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' BKK found'
        if a[0:2] != above_a[0:2] and 'BKK' in a:
            print 'BKK found'
    
        if a[0:2] != above_a[0:2] and 'OK' in a:
            print 'OK found'
    


Answer: I'm not sure your code actually skips rows. You just don't print anything when
a match isn't found. If you add an `else` to your outer `if` loop as follows:

    
    
    from xlrd import open_workbook
    
    the_file = open_workbook('c:\\file.xls',formatting_info=True)
    the_sheet = the_file.sheet_by_index(0) 
    
    for row in range(0, the_sheet.nrows):
        a = the_sheet.cell(row, 0).value
        above_a = the_sheet.cell(row-1, 0).value
        if a[0:2] == above_a[0:2]:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code'
            if 'OK' in a:
                print 'OK found'
            else:
                print 'BKK found'
        else:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' do not match'
    

You should get the following results:

    
    
    row no.1 and 0 do not match
    row no.2 and 1 found same code
    OK found
    row no.3 and 2 do not match
    row no.4 and 3 do not match
    row no.5 and 4 found same code
    OK found
    row no.6 and 5 do not match
    

The bigger problem is that you are comparing a row with the row above by
starting at the first row (because the range in the for loop goes from 0 to
5). So the first comparison is between "OK 17" and "BKK 16" (i.e. row 0 and
row -1). You should be able to see this if you comment out the `if` loops and
tell python to `print a, above_a` within the `for` loop.

    
    
    for row in range(0, the_sheet.nrows):
        a = the_sheet.cell(row, 0).value
        above_a = the_sheet.cell(row-1, 0).value
    
        print a, above_a
    

In terms of row indices, you are comparing the following (a, above_a):

    
    
    0 -1
    1 0
    2 1
    3 2
    4 3
    5 4
    

You could fix this by starting at 0 and comparing with the row below, or more
simply, start your `for` loop at 1. That would give you the following results:

    
    
    row no.2 and 1 found same code
    OK found
    row no.3 and 2 do not match
    row no.4 and 3 do not match
    row no.5 and 4 found same code
    OK found
    row no.6 and 5 do not match
    

==================================================================================

To address your edit:

Your second version of the `for` loop does better in that it includes the
cases where there is no match. But you still start your range at 0, so it is
comparing the first row (index 0) with the last row (index -1). This is not
ideal.

With regard to simplifying your if statements in the new `for` loop, you can
use `elif` and `else` instead of four `if` statements. You can also change the
last two `if` statements into a single `else` and nest an `if` to test if the
row has a "OK" or "BKK" in it. The following code is an example:

    
    
    for row in range(1, the_sheet.nrows):
        a = the_sheet.cell(row, 0).value
        above_a = the_sheet.cell(row-1, 0).value
        if a[0:2] == above_a[0:2] and 'OK' in a:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' OK found'
        elif a[0:2] == above_a[0:2] and 'BKK' in a:
            print 'row no.' + str(row + 1) + ' and ' + str(row) + ' found same code' + ' BKK found'
        else:
            if 'BKK' in a:
                print 'BKK found in row %d' % row
            else:
                print 'OK found in row %d' % row
    

There is a further issue to address. The above code only gives you 5 results.
It sounds like you want to know two separate things:

  1. Do the contents of a cell contain "OK" or "BKK"? 
  2. Do the contents of a cell match the contents of the cell above it with regard to the first question?

The issue you might be running into is that the first question involves 6
answers but the second question only involves 5. The first row doesn't have a
row above it and thus doesn't have an answer to the second question. You might
change the code to answer each question separately or to combine the two
questions into a single print statement that includes a comparison for every
row but the first one.

If I'm misunderstanding the problem you're trying to answer, please clarify
further.

