0

I have an Excel file and I use python Win32com to operate on it.

how do I check if the last row has value in a specific column ?

when I try , the nrows is 28, not 23 (the last row have value not empty)

 used = sht1.UsedRange
 nrows = used.Row + used.Rows.Count - 1

i want to find the position I24

user3885927
  • 3,363
  • 2
  • 22
  • 42
soneedu
  • 73
  • 1
  • 3
  • 11

5 Answers5

3

UsedRange is not reliable always when you want to get last row of any specific column. You should use EndXlUp or EndXlDown function.

Check this below line:

LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row

Where, A is the column to get last row.

Also, check this URL: Error in finding last used cell in VBA

As your are using python win32 com, Endxlup will not work. There's one basic thing you can do. Check the below code:

ws = wb.Worksheets('Sheet1')
rw = 2
While ws.cells(rw, 1) <> ""
    rw +=1

Where, rw is the starting row from where you want to start row count. 1 in (rw, 1) represents column. Column A represents A.

Logic behind this is while loop will run till it does not get blank cell in column A and you will get row count in variable rw

Community
  • 1
  • 1
Paresh J
  • 2,401
  • 3
  • 24
  • 31
  • i trid End(xlUP) but got: NameError: name 'xlUp' is not defined. and i use python, not VBA – soneedu Nov 06 '14 at 06:04
  • i just try cells(A65534).End(xlUP).Row, i think python win32com do not have this, maybe is another way to use, but i do not know – soneedu Nov 06 '14 at 07:39
  • @soneedu: Check the modified answer and try this. – Paresh J Nov 06 '14 at 08:04
  • if have an empty cell in the middle, maybe the rw will not be the last row. – soneedu Nov 06 '14 at 14:49
  • @soneedu: Yes, you are right this is the problem with that solution. – Paresh J Nov 06 '14 at 14:54
  • @soneedu: Check this URL. Have you added Microsoft Excel Library? Have a look at this URL : http://bytes.com/topic/python/answers/599460-excel-find-last-column After this, try End(xlUp) to get last row. – Paresh J Nov 06 '14 at 15:03
  • thanks a lot to you, it is a good idea to use "const = win32com.client.constants", i will try later – soneedu Nov 20 '14 at 03:49
  • FYI - instead of using "xlUp" you could use "win32c.xlShiftUp" – DaniB Nov 16 '22 at 12:21
2

I'm currently writing an Excel wrapper, and part of it is this function returning all data from a certain offset to the last row of that column. For example, if I want everything from the 3rd row up till including the last line. This should work for your problem as well. Note where the constant is retrieved from and how all methods are stacked together to get the data and the last row.

Key functions:

def get_column_after(self, column, offset):
    for item in self.ws.Range("{0}{1}:{0}{2}".format(column, offset, self.get_last_row_from_column(column))).Value:
        print(item[0])

def get_last_row_from_column(self, column):
    return self.ws.Range("{0}{1}".format(column, self.ws.Rows.Count)).End(win32com.client.constants.xlUp).Row

NOTE: This code is a work in progress and at the moment only supports one worksheet, one workbook per instance. I'm sure you can figure out a way to get this to work in your project though.

import string
import win32com.client

SOURCE_PATH = "C:\ExternData\somefile.xlsx"
WORKSHEET_NAME = "WS_1"

class ExcelInstance():
    def __init__(self, wb=None):
        self.source_path = SOURCE_PATH
        try:
            self.app = win32com.client.gencache.EnsureDispatch('Excel.Application')
        except:
            print("Application could not be opened.")
            return
        try:
            self.open_workbook()
        except:
            print("Workbook could not be opened.")
            return
        try:
            self.ws = self.wb.Worksheets(WORKSHEET_NAME) 
        except:
            print("Worksheet not found.")
            return
        self.app.Visible = True
        self.app.WindowState = win32com.client.constants.xlMaximized

    def open_workbook(self):
        """
        If it doesn't open one way, try another.
        """
        try:        
            self.wb = self.app.Workbooks(self.source_path)            
        except Exception as e:
            try:
                self.wb = self.app.Workbooks.Open(self.source_path)
            except Exception as e:
                print(e)
                self.wb = None   

    def get_column_after(self, column, offset):
        for item in self.ws.Range("{0}{1}:{0}{2}".format(column, offset, self.get_last_row_from_column(column))).Value:
            print(item[0])

    def get_last_row_from_column(self, column):
        return self.ws.Range("{0}{1}".format(column, self.ws.Rows.Count)).End(win32com.client.constants.xlUp).Row


def main():
    f = ExcelInstance()
    f.get_column_after("A", 3)

if __name__ == "__main__":
    main()
Mast
  • 1,788
  • 4
  • 29
  • 46
1

xlUp is nothing short of a pre-defined constant.

So the most simple way is to type the code in the direct window of the VBE

? xlUp

you will see the following result.

-4162

add the line to your python code

xlUp = -4162

Done!

WinH
  • 11
  • 1
1

Replace .End(xlUp).Row with .End(3).Row.

tambre
  • 4,625
  • 4
  • 42
  • 55
Serhii
  • 11
  • 1
  • 4
    Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. Thanks for improving the answer's reference value and making it more understandable! – Tim Diekmann Jun 22 '18 at 10:06
0

i use this stupid way to do . not sure have problem or not. so far work for myself

def find_lastrow_oncolumn(worksht, colno):
    used = worksht.UsedRange
    nrows = used.Row + used.Rows.Count - 1
    lastrow_havevalue = 0
    for k in range(nrows):
        if worksht.Cells(nrows-k, colno).Value is not None:
            print worksht.Cells(nrows-k, colno).Value, nrows-k , k
            lastrow_havevalue = nrows-k
            break
    return lastrow_havevalue
soneedu
  • 73
  • 1
  • 3
  • 11