Question

I've been using this command:

LastRow = ActiveSheet.UsedRange.Rows.Count

But the UsedRange property can often be inaccurate. So I'm looking for an alternative. I found a great tip explaining this method:

LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row

This works a treat in Excel. However, I'm running code from an HTA, so I need to convert this line, and I'm struggling. THIS is my question --- please can someone offer guidance on how to convert this simple code into an HTA-compatible one?

Out of interest, to try to circumvent this problem, I tried writing a routine in a way that I understand. The result works, but is very slow. Here it is for giggles:

    Set objExcel = GetObject(,"Excel.Application") 
    wb = "test.xlsx"
    objExcel.Workbooks(wb).Activate
    wbactiveSheet = objExcel.Workbooks(wb).ActiveSheet.Name

    'determine rows and columns in range of first xls
    theNumRow = objExcel.Workbooks(wb).Sheets(wbactiveSheet).UsedRange.Rows.Count
    theNumCol = objExcel.Workbooks(wb).Sheets(wbactiveSheet).UsedRange.Columns.Count

    'determine genuine used rows:
    x = 1 'start at first row
    blankRows = 0
    Do 'each row
        y = 1 'start at first column
        blankCells = 0
        Do 'each column
            If objExcel.Workbooks(wb).Sheets(wbactiveSheet).Cells(x, y).Value <> "" Then
                theNumRowActual = x
                'found non-blank, skip to next row
                Exit Do 'the columns loop
            Else
                blankCells = blankCells + 1
            End If
            y = y + 1
        Loop Until (y - 1) = theNumCol
        If blankCells = theNumCol Then 'blank row
            blankRows = blankRows + 1
            If blankRows = 50 Then
                Exit Do
            End If
        Else
            blankRows = 0
        End If
        x = x + 1
    Loop Until x = theNumRow 'i.e. until the testing area matches the usedRange property

    'determine genuine used columns:
    y = 1 'start at first column
    blankCols = 0
    Do 'each column
        x = 1 'start at first row
        blankCells = 0
        Do 'each row
            If objExcel.Workbooks(wb).Sheets(wbactiveSheet).Cells(x, y).Value <> "" Then
                theNumColActual = y
                'found non-blank, skip to next column
                Exit Do 'the rows loop
            Else
                blankCells = blankCells + 1
            End If
            x = x + 1
        Loop Until (x - 1) = theNumRowActual
        If blankCells = theNumRowActual Then 'blank column
            blankCols = blankCols + 1
            If blankCols = 50 Then
                Exit Do
            End If
        Else
            blankCols = 0
        End If
        y = y + 1
    Loop Until (y - 1) = theNumCol 'i.e. until the testing area matches the usedRange property
    'bug


    MsgBox "USEDRANGEMETHOD:" &vbNewLine & "rows: " & theNumRow & vbNewLine & "columns: " & theNumCol & vbNewLine & vbNewLine & "NEWMETHOD:" & vbNewLine & "rows: " & theNumRowActual & vbNewLine & "columns: " & theNumColActual

Thank you

Was it helpful?

Solution

It looks like you already have your worksheet open and active? In that case:

Const xlByRows = 1
Const xlPrevious = 2

Set objExcel = GetObject(,"Excel.Application")
LastRow = objExcel.ActiveSheet.Cells.Find("*", , , , xlByRows, xlPrevious).Row

See my recent post about using VBScript to call an Excel function for additional tips.

When you're programming using VBA within Excel then Cells is a native object that you can reference directly. But when you're outside of Excel -- in an HTA or WSH script -- your script has no idea what Cells refers to. The only Excel objects you have are the ones you create. So you must work your way down the chain, from your main Excel (Application) object to a workbook and then to a sheet before you can operate on the Cells property. It might make more sense if you use the same names Excel does:

' Define the same objects that Excel does...
Set Application = GetObject(, "Excel.Application")
Set ThisWorkbook = Application.ActiveWorkbook

' Now get a sheet based on its name ("Sheet1", in this example)..
Set MySheet = ThisWorkbook.Sheets("Sheet1")

' And operate on the Cells collection...
MySheet.Cells.Find(...)

As a shortcut, Excel provides an ActiveSheet property that you can use directly on the Application object to get the current sheet, essentially bypassing the workbook layer. That's what I've used in my first code snippet.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top