Using variables to select a range of cells - excel

I'm trying to make a section of a small macro in Excel that copies info from some inputs between cells AE13 and AI13. The thing is that I want to make it so that the next row is selected by Excel once the program does its thing (so, once the program copies the content for AE13:AI13 and does some processing, it'll jump to copy the contents of AE14:AE14 and so on as long as it encounters data (for this example, let that be until the variable I'm using reaches 20)). For this I'm doing the following:
Do while Active < 20
Active = 13
'The code that does the cleanup from the prior run goes here
Range("AE" & Active & ":AI" & Active).Select
Selection.Copy
'Then here goes the rest code that does the actual program, which has been running fine prior to implementing this "Active" variable (which is not used anywhere else in the code).
Active = Active + 1
Loop
To me that's how it's supposed to go, but when I try to run this, Excel selects rows AE:AI, it activates all the cells in those columns instead of the ones in the row I'm specifying.
Could anyone help me see if I'm doing something wrong?
Kudos from a ramdon, troubled gen z trying to survive in the workplace.

Related

Managing Excel Worksheet_Change Feature

I have created a spreadsheet which uses the Worksheet_Change feature and the code associated with that works very well. I can stop it firing unnecessarily when inside the module by using Application.EnableEvents = False.
However, while I've created a form to enter data directly into the next available row (again, that works fine in terms of entry) it doesn't cause the formulae in the sheet to calculate (even though auto calculation is on and re-enabled within the module). If I manually place my cursor in the row, hit F2 and simply press enter, everything then fires up.
I have tried to enter data directly into the cells, but of course the Worksheet_Change feature then kicks in again and the cursor isn't simply moving to the next adjacent cell ....
I've tried to check firs for any direct entry with the code below and if it looks like the user isn't entering directly into the cell, the Worksheet_Change is disabled:
Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo eventhandler
Sheets(1).Range("a1").Select
LastCell2 = Sheets(1).Cells(Rows.Count, "A").End(xlUp).Row
Dim intersection As Range
Set intersection = Intersect(Target, Range("A3:F" & LastCell2))
If intersection.Row = LastCell + 1 Then
Exit Sub
End If
Application.EnableEvents = False
The code above is simply checking to see if data is being entered into the next empty cell and if that's the case I want it to just exit there but it isn't working.
So I actually have 2 problems :
the first is why this formula isn't triggering after entry via a vba form - I've used INDIRECT since there are other macros that delete rows by moving the remaining cells up and that was causing the count in the $A$3:$A$500 to reduce to $A$499 and then 498 etc - the addition is done depending on the system date and the transaction date so I get a current value and a future value using a standard sum statement:
=AD1-(SUMIF(INDIRECT("$A$3:$A$500"),"<="&TODAY(),INDIRECT("$E$3:$E$500")))+(SUMIF(INDIRECT("$A$3:$A$500"),"<="&TODAY(),INDIRECT("$F$3:$F$500")))
The second is why I can't enter data directly into the spreadsheet and trap the fact that I don't want it to do anything and simply allow the user to hit enter and move to the next adjacent cell to the one they just entered data into.
Is this a lost cause and am I trying to do too much here? I'm relatively new to coding and teaching myself so apologies if the standard and style isn't to everyone's taste.
Thanks in advance for any replies.

Excel VBA Range 'Delete' method randomly fails

Background
I have a piece of VBA code which deletes multiple rows on a worksheet depending on if the values on each row are TRUE or FALSE in a specific column (a 'control range'). The worksheets as switched as a master loop (above the level of this function) that cycles through multiple sheets and workbooks.
This is used in the Excel 2013 and 2016
Naturally the code searches for matching rows and builds up a range object and only once the loop has ended is that rage deleted.
Code extract
I can't send a copy of the actual workbook because it is too large, too complicated and I don't have time to explain how it works - besides it is confidential.
I have listed below an extract of the key code that is failing (with the command that fails in bold).
' Build up a list of rows which are valid
For Each rngCurControlCell In rngSheetControlRange.Cells
If rngCurControlCell.Value = True Then
If rngRowsToDelete Is Nothing Then
Set rngRowsToDelete = rngCurControlCell.EntireRow
Else
Set rngRowsToDelete = Union(rngCurControlCell.EntireRow, rngRowsToDelete)
End If
End If 'rngCurControlCell.Value = True
Next rngCurControlCell
' Delete the rows
If Not rngRowsToDelete Is Nothing Then rngRowsToDelete.Delete
Problem / Issue
Sometimes this code works and sometimes it does not.
I have put various debugging in the code and can confirm that the code always finds the target rows ('rngRowsToDelete' in the extract above) and always builds up the range object correctly.
HOWEVER ... sometimes the delete works and sometimes it does not - even though it it run against the same worksheet. No error is generated.
Has anyone come across a similar situation / have any thoughts ?

Macro Code to delete rows untill defined column

How do I limit a Macro to function only within certain range let's say until certain column?
I have a case where macro needs to delete the rows based on condition. I also want to put some instructions on the right and a form control button for macro but it seems like every time the code is activated, it deletes everything in that row, including the instructions and button I made. So I want to define a range where macro should be active.
I have following logic active.
First flag the item to be checked.
In loop, keep checking and deleting the rows.
Delete the rows based on an extra condition.
The code is working fine, but I want to add limitation until certain column like said.
Where do i define the range? In three separate logic, or at once on top?
Any help would be appreciated.
BR,
Manny
It sounds like you have told your code to delete the entire row. If you only want the macro to delete the data in columns A to G, for example, then use code along the lines of
Range("A" & rownumber & ":G" & rownumber).Delete Shift:=xlUp
you need to replace the line of code that deletes the whole row with code that deletes only set range. So for example instead of
Rows("12:12").Delete Shift:=xlUp
you will have
Range("A12:N12").Delete Shift:=xlUp

Excel automatically changing to date format, even after correcting

I am helping to update someone else's VBA code since they got pulled to a different project. The code reads data from an input sheet, then unhides 4 results forms, populates them, saves them as a CSV file, then rehides them.
The issue: One of the data entries are numbers formatted as ##-#, like 20-2, 13-5, and 12-1. The 12-1 is the issue. Excel sees it and reads it as a date format and prints 1-Dec in my results sheet.
Solutions I've tried: I tried stopping the program before it rehides the data and changing the format but it throws off the numbers. And then I can't save it either, because the program has run halfway and I don't want to save the document like that. I then tried to unhide the sheets at the end after the program ran and cleared, but without completely removing the data after the program runs, it doesn't run correctly when you try to run it a second time. Lastly I tried unhiding before the program even ran and changed the format setting from "General" to "Text", but even after saving and closing it doesn't seem like that had an affect.
My Question: First of all am I changing the format right? And secondly does anyone know how to combat excel automatically formatting in this way. I have been working in VBA for about 3 weeks and have only encountered this once before but it fixed easily. This one doesn't seem to follow that pattern.
Since I was given an answer I thought I'd run my first self Q & A now, for those who may come upon this in the future. Credit to those users in the comments above for helping me figure this out. A code line like this:
Dim variable1 As Variant
variable1 = Sheets("Sheet 1").Range("A1").Value
Sheets("Sheet 2").Range("A1").NumberFormat = "#"
Sheets("Sheet 2").Range("A1") = variable1
Or with the cells option, we'd see code like this:
Dim variable1 As Variant
variable1 = Sheets("Sheet 1").Cells(1,1).Value
Sheets("Sheet 2").Cells(1,1).NumberFormat = "#"
Sheets("Sheet 2").Cells(1,1) = variable1
Both of these codes dimension a variable to store cell A1 in from Sheet 1, refer to sheet 2 and set that cell to a new format (making it format as a number as opposed to automatically formatting), then the last line sets that newly formatted cell equal to the value in the variable, but while retaining the new format we've set.

Copying MSProject information to Excel

I have a macro-enabled Excel workbook that opens a series of MSProject files, applies filters to a specific column, and copies portions of the visible range to Excel. The code for the copy action looks like this:
For Each Task In ActiveSelection.Tasks
If Not Task Is Nothing Then
TargetWS.Cells(Row, 3) = Task.PercentComplete / 100
TargetWS.Cells(Row, 4) = Task.Name
TargetWS.Cells(Row, 5) = Task.Start
TargetWS.Cells(Row, 6) = Task.Finish
TargetWS.Cells(Row, 7) = Task.BaselineFinish
Row = Row + 1
End If
Next Task
Essentially, I am looping through every row in the filtered range and copying each column one at a time. As you can imagine, this takes a long time.
My hope is to replace this iterative method with the standard set of actions I would use in Excel VBA: define first & last rows, then use one copy action for each column I want. This would greatly reduce the number of copy actions required to complete the task, which should provide a speed increase.
In Excel VBA, the code I want would look something like this, having defined the last row:
TargetWS.Range("A2:" & LastRow).Copy Destination:= (destination cells)
I know how to find the last visible task in Project, but am unfamiliar with range selection. Could someone fill in the gaps?
Thanks!
Your current method takes a sound approach, so instead of changing the method, try improving the performance.
The slowest part of your code right now isn't that you are looping through the tasks one-by-one, it's that you are writing to Excel cell-by-cell. The first step you can take is to write all data for a single task at one:
TargetWS.Range("C" & Row & ":G" & Row) = Array(Task.PercentComplete / 100, _
Task.Name, Task.Start, Task.Finish, _
Task.BaselineFinish)
Once you are comfortable with that, then you can move on to writing blocks of data at a time. To do this, store the data in a 2-dimensional array and only write it to Excel when you are done looping through the tasks. (Note, if you have many thousands of tasks, you may need to write the data in smaller chunks.)
Also, make sure you have turned calculation off in Excel. This will improve performance as can turning off screen updates. Just make sure you reset both application settings when your code is completed (even it if finishes with an error).
One last tip, avoid naming variables the same as objects (e.g a Task object named Task).

Resources