Excel VBA Course
Excel VBA Course - From Beginner to Expert

200+ Video Lessons
50+ Hours of Video
200+ Excel Guides

Become a master of VBA and Macros in Excel and learn how to automate all of your tasks in Excel with this online course. (No VBA experience required.)

View Course

Professional Forms Course - Exercise 2

0

Please know that I work diligently to find answers to questions prior to submitting!

I'm having trouble with using variables to move a column to the right.  I've debugged with no luck.   

Here is the entire routine and below  I'll ask specific question.

 
Sub AddData()
' Excel VBA/Macro Course - TeachExcel.com
'The following are previously defined named ranges in Excel
'
Dim sectionFor As Range
Dim sectionTo As Range
Dim headerRow As Range
Dim subtotalRow As Range
Dim NewDescrip As Range
Dim NewQty As Range
Dim NewPrice As Range
Dim RngInsertRow As Range
Dim RngClear As Range
Dim NewTotal As Range
Set sectionFor = Range("D9:D11")
Set sectionTo = Range("B9:B11")
Set headerRow = Range("B13:E13")
Set subtotalRow = Range("D21")
Set totalcell = Range("E14")
'Add a new row below the header row and copy formatting (except this does not copy borders)
Set RngInsertRow = headerRow.Offset(1, 0)
'Add a new row below the header row and copy formatting
RngInsertRow.EntireRow.Insert Shift:=xlShiftDown, CopyOrigin:=xlFormatFromRightOrBelow
'Since a new line was added, need to put the RngInsertRow back up one line
Set RngInsertRow = RngInsertRow.Offset(-1, 0)
' Copy the border and other formatting.
    RngInsertRow.Offset(1, 0).Copy
    RngInsertRow.Select
    Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
        SkipBlanks:=False, Transpose:=False
    Application.CutCopyMode = False
'===============================================
'Set up Ranges for Inputting Invoice data
'===============================================
Set NewDescrip = RngInsertRow.Cells(1, 1)
'MsgBox "NewDescrip address= " & NewDescrip.Address
Set NewQty = NewDescrip.Offset(0, 1)
'MsgBox "NewQty address= " & NewQty.Address
Set NewPrice = NewDescrip.Offset(0, 2)
'Copy the formula from the Total column to the new row.  This is now two rows below the totalCell
Set NewTotal = NewDescrip.Offset(0, 3)
'Must use R1C1 references because when formula is copied, it is based on the
' relative position of the cells.  It automatically adjusts.
NewTotal.FormulaR1C1 = totalcell.FormulaR1C1
'=====================================================
'Ask User to Input new data
'=====================================================
'Uncomment this later
                    ' Prompt the user to enter a description and directly assign it to the cell
                    'NewDescrip.Value = InputBox("Enter Description of product")
                    'NewQty.Value = InputBox("Enter Quantity of product")
                    'NewPrice.Value = InputBox("Enter Price of product")
NewDescrip.Value = "Stuff I Want"
NewQty.Value = 99
NewPrice.Value = 55
'======================================================
'clear the old data
'=======================================================
' Determine the last used row in the worksheet
    Dim lastRow As Long
    Dim lastCol As Long
    lastRow = Cells(Rows.Count, NewDescrip.Column).End(xlUp).Row
    lastCol = Cells(RngInsertRow.Row, Columns.Count).End(xlToLeft).Column
    MsgBox "RngInsertRow Address = " & RngInsertRow.Address
    MsgBox "lastRow = " & lastRow & "lasCol= " & lastCol
    Debug.Print "lastRow: " & lastRow
    Debug.Print "lastCol: " & lastCol
    'Need to move one column to the left to exclude Total column
    lastCol = lastCol - 1
    MsgBox "lastCol revised" & lastCol
    ' Set RngClear to start from one cell below RngInsertRow and extend to the last used row and the second to last column
    MsgBox "RngInsertRow   " & RngInsertRow.Address
    Debug.Print "lastCol: " & lastCol
    Set RngClear = Range(RngInsertRow.Offset(1, 0), Cells(lastRow, lastCol))
    MsgBox "RngClear= " & RngClear.Cells(1, 1).Address & RngClear.Address
    ' Debug statement to verify RngClear interpretation
     Debug.Print "RngClear: " & RngClear.Address
    Debug.Print "lastRow: " & lastRow
    Debug.Print "lastCol: " & lastCol
    ' Display the information in a MsgBox (for verification purposes)
    If Not RngClear Is Nothing Then
        MsgBox "RngClear starts at " & RngClear.Cells(1, 1).Address & " and includes region " & RngClear.Address
    Else
        MsgBox "RngClear is not properly defined."
    End If
    ' clear contents of adjusted RngClear
    ' RngClear.ClearContents
End Sub

What I am having trouble with is in the section I labeled as "clear the old data". I  set up a variables named lastRow and lastCol to store row and column numbers.  I use a previously defined range to store values into lastRow and lastCol. 

Then I need to move a column in a range one to the right relative to the value in lastCol so I subtract one from the lastCol variable.  I verified that the lastCol value changes, but when I use lastCol in a range, it seems like the variable's value is not being interpreted correctly.  

It goes like this: 

I first find the last column of a pre-defined range and assign it to lastCol 

as follows

Dim lastRow As Long
    Dim lastCol As Long
    lastRow = Cells(Rows.Count, NewDescrip.Column).End(xlUp).Row
    lastCol = Cells(RngInsertRow.Row, Columns.Count).End(xlToLeft).Column
    MsgBox "RngInsertRow Address = " & RngInsertRow.Address
    MsgBox "lastRow = " & lastRow & "lasCol= " & lastCol
    Debug.Print "lastRow: " & lastRow
    Debug.Print "lastCol: " & lastCol

At this point the value of lastCol is 5, 

I then subtract one from lastCol and use it to define a new range named RngClear

lastCol = lastCol - 1
    MsgBox "lastCol revised" & lastCol
    ' Set RngClear to start from one cell below RngInsertRow and extend to the last used row and the second to last column
    MsgBox "RngInsertRow   " & RngInsertRow.Address
    Debug.Print "lastCol: " & lastCol
    Set RngClear = Range(RngInsertRow.Offset(1, 0), Cells(lastRow, lastCol))
    MsgBox "RngClear= " & RngClear.Cells(1, 1).Address & RngClear.Address
    ' Debug statement to verify RngClear interpretation
     Debug.Print "RngClear: " & RngClear.Address
    Debug.Print "lastRow: " & lastRow
    Debug.Print "lastCol: " & lastCol
    ' Display the information in a MsgBox (for verification purposes)
    If Not RngClear Is Nothing Then
        MsgBox "RngClear starts at " & RngClear.Cells(1, 1).Address & " and includes region " & RngClear.Address
    Else
        MsgBox "RngClear is not properly defined."
    End If
    ' clear contents of adjusted RngClear
    ' RngClear.ClearContents
End Sub

I verify several times in the routine that after subtracting 1, the value of lastCol is 4, but this somehow does not get passed through to the following line of  code

Set RngClear = Range(RngInsertRow.Offset(1, 0), Cells(lastRow, lastCol))

I expect RngClear address to be $B$15:$D$17  but rather VBA result is $B$15:$E$17.

Why?  What is going on with the lastCol variable?  Is there something wrong with the Set RngClear =    line of code?

Thank you as always.

I'm attaching the whole .xlsm file

Answer
Discuss

Discussion

Hi Susan,
You say you have attached the file but there is no file attached.
First - you don't have a "Dim" statement for "totalcell". If you put "Option Explicit" at the top of the code module then VBE will catch these errors. You can set this as the default while in the editor window. Select the "Tools" menu then "Options". In the window which opens, on the "Editor" tab select the second item "Require Variable Declaration". Having this setting checked will cause all modules to automatically have "Option Explicit" at the top.

Now, as for the "Set RngClear" line I too am stumped. When I step through the code (F8), when I get to that line, I hover my mouse over "lastCol" it shows that it is indeed 4 but for a reason I can't figure out, it uses 5 when it sets the range. I tried several different codes with no success. Sorry.

Hopefully John will have an explanation and answer for you.

Cheers   :-)
WillieD24 (rep: 587) Jun 14, '24 at 8:40 pm
@Susan - the file is missing, as Willie said above, but I've answered you without it. Please take special note of the last paragraph of my Answer (with action required from you)

For the future however, please note that if you have questions on any course contents, please don't post them (or code/ files) here or elsewhere. Instead use the Contact link (in the green bar above) and use the Premium Courses option and opose your question Don will then answer you directly but allow him some time- he's a busy man!

@Willie - thanks for the tip on using "Require Variable Declaration" - I hadn't come across that!
John_Ru (rep: 6417) Jun 15, '24 at 6:28 am
Add to Discussion

Answers

0
Selected Answer

Susan

After being puzzled, I realised your problem doesn't relate to your variable lastCol.

You have two lines as follows:

    Set RngClear = Range(RngInsertRow.Offset(1, 0), Cells(lastRow, lastCol))
    MsgBox "RngClear= " & RngClear.Cells(1, 1).Address & RngClear.Address

and the issue relates to the portion in bold above.

You insert a row above the original row 14 (which include a subtotal in E14) so when your variable RngInsertRow is offset by a row, it covers the range $B$15:$E$15. That's the start point of RngClear and the end point is Cells(lastRow, lastCol) ($D$22 with my sample data) so RngClear becomes $B$15:$E$22 - a rectangular area (since you're no making a Union of areas).

There's a simple fix luckily. Just change the start cell of RngClear to be the first cell in the offset range, see changes in bold below:

    Set RngClear = Range(RngInsertRow.Offset(1, 0),.Cells(1, 1), Cells(lastRow, lastCol))
    MsgBox "RngClear= " & RngClear.Address

You'll then get RngClear being $B$15:$D$22, as required.

Hope this fixes things for you. if so, please Select my Answer as usual but then REMOVE the code in your question (since it's from a Premium Course). No need to attach the file now.

Discuss

Discussion

@John
Once again, nice work. Like Susan, I too suspected the problem to be with the "Set RngClear = " but I was having a mental block and just couldn't arrive at the solution.
WillieD24 (rep: 587) Jun 15, '24 at 10:58 pm
@Willie - thanks. It took me a bit to realise that line was giving an unwanted result because of the earlier Set RngInsertRow. Hope it works for Susan's file too.
John_Ru (rep: 6417) Jun 16, '24 at 2:03 am
@WillieD24  @John
 
Much thanks.
I am glad I submitted the code although it took a second (and third) set of eyes to help me see what I was doing wrong.  I actually should have been resetting the column size not row size.  AND, after looking at my notes, what I was trying to accomplish would have been much easier had I used the Resize property in vba. 

I also learned from your answers that one can hover over a variable to get its value!

This is what learning is all about!
SusanUser (rep: 22) Jun 17, '24 at 5:19 pm
Thanks for selecting my Answer, Susan. Good to hear you learned useful things from this problem. 
John_Ru (rep: 6417) Jun 17, '24 at 5:45 pm
Susan, please remove the large portion of course code from your Question (as I requested earlier) - I can't do it for you.
John_Ru (rep: 6417) Jun 18, '24 at 2:22 am
Add to Discussion


Answer the Question

You must create an account to use the forum. Create an Account or Login