I have a "Task Tracker" workbook that uses columns A:J to display and calculate task information (A:E are for user-entered data, F:J contain formulas that use the information in C:E and perform calculations. F:J are hidden cells in the user view.) The remainder of the columns display a heat map of where the tasks fall on a timeline, and whether or not they are running on time, are behind, or are complete.
There are two buttons for users to use: one to insert a new row, and one to insert a new column. The InsertRow() macro inserts a row into the list, then copies the formulas down from the above row. The InsertColumn() macro locates the last used column in the worksheet and copies everything over from the column to the left of it.
Originally, I had a macro for InsertRow using Range that copied from Column F (where the formulas start) to Column XFD. However, once I created the InsertColumn macro I realized that I cannot do InsertRow like that because InsertColumn needs to locate the last data-containing column in the worksheet and add a new one to the right...and if InsertRow gets run first, InsertColumn won't work because the value for lastColumn comes back as the index of column XFD.
What I am looking for help with:
I need to locate the lastColumn value in my InsertRow macro, then use that value as part of the Range when the program executes the Copy/Paste portion of the code. I think that the problem I'm having has to do with the fact that the code I'm using to find the last column returns the index, and the Range function needs the name of the column.
Here is what I have for both macros:
Sub InsertTaskRow()
' InsertTaskRow Macro
'
' This macro inserts a new row below whatever role the user currently has selected, then
' copies the formulas and formatting from above down to the new row
Dim lastColumn As Long
Dim currrentRow As Long
Dim newRow As Long
lastColumn = ActiveSheet.Range("A1").SpecialCells(xlCellTypeLastCell).Column
currentRow = ActiveCell.Row
newRow = currentRow + 1
ActiveCell.Offset(1).EntireRow.Insert Shift:=xlDown
Range("F" & currentRow & ":" & lastColumn & currentRow).Copy Destination:=Range("F" & newRow & ":" & currentRow & newRow)
End Sub
Sub InsertColumn()
' InsertColumn Macro
'
' This macro copies the formulas and formatting from the last data-containing column
' in the worksheet, and pastes it into the next column to the right.
Dim lastColumn As Long
lastColumn = ActiveSheet.Range("A1").SpecialCells(xlCellTypeLastCell).Column
MsgBox lastColumn
Columns(lastColumn).Copy Destination:=Columns(lastColumn + 1)
End Sub
You can try changing your lastColumn occurances to the following:
lastColumn = ActiveSheet.Range("A1").End(xlToRight).Column
This will stretch your range to all used cells. I tried using the clCellTypeLastCell, but it was pulling further than necessary for no apparent reason; even after deleting the entire columns it claimed were applicable. Just an FYI, there is no issue with using indexes or column names when utilizing Range() - even interchangibly, they are both fully qualified.
Related
My data range needs to be copied from one tab to another. The key to this is it needs to paste the information in the data range into a new row, even if the information is the same. So each time it is run a new row will be populated. Another key here is the row data range consists of criteria, depending on the value of criteria the code will decide which tab to copy into.
I was able to create the code to copy but without if statement and it copies into the same row each time
if Cell E3 = "Revenue" then copy into Revenue worksheet, if not then copy into Cost worksheet.
Each time code is run, the data will be copied into the last unoccupied row available in that worksheet
If I understood You right, this should work:
Sub copy2sheet()
Dim cond As String
Dim lastRow As Integer
With Sheets(ActiveSheet.Name)
'taking name of the sheet from "E3"
cond = .Range("E3").Value
'checking last filled row in sheet we gonna copy data
lastRow = Sheets(cond).Cells(Rows.Count, 1).End(xlUp).row
'copy data starting from "A1" to every cell is close to - CurrentRegion
'a paste it into first empty cell in column "A"
'.Range("A1").CurrentRegion.Copy Sheets(cond).Range("A" & lastRow + 1)
.Range("E3:H3").Copy Sheets(cond).Range("A" & lastRow + 1)
End With
End Sub
I have two sheets of data. The first sheet is imported data that will show total users to my site from the day before. The second sheet is a table with all historical data from those daily reports. I'd like to automate a way to copy the data from my first sheet (that data will always be in the same cell) to a new row at the bottom of my existing table. Here's what I have:
Sub Insert_New_Rows()
Dim Lr As Integer
Lr = Range("AF" & Rows.Count).End(xlUp).Row
Rows(Lr + 1).Insert Shift:=xlDown
Cells(Lr + 1, "AF") = Cells(Lr, "AF") + 1
Sheets("Day Before").Range("$A$12:$B$12").Copy
Sheets("Historical").Cells(Lr + 1, "AF").Paste
Application.CutCopyMode = False
End Sub
In this, you'll see that my table is in columns AF and AG. When I run this macro, it only adds a row, it does not copy and paste the information.
I am not really sure where your table starts on the sheet "Day Before". So, I am assuming that it starts in row 1. Based on this assumption here is a little revision to your code:
Option Explicit
Sub Insert_New_Rows()
Dim lngNextEmptyRow As Long
Dim lngLastImportRow As Long
Dim shtYstrdy As Worksheet
Set shtYstrdy = ThisWorkbook.Worksheets("Day Before")
With ThisWorkbook.Worksheets("Historical")
lngNextEmptyRow = .Cells(.Rows.Count, "AF").End(xlUp).Row + 1
.Rows(lngNextEmptyRow).Insert Shift:=xlDown
.Cells(lngNextEmptyRow, "AF").Value2 = _
.Cells(lngNextEmptyRow - 1, "AF").Value2 + 1
lngLastImportRow = shtYstrdy.Cells(shtYstrdy.Rows.Count, "A").End(xlUp).Row
shtYstrdy.Range("A1:B" & lngLastImportRow).Copy _
Destination:=.Cells(lngNextEmptyRow, "AF")
End With
End Sub
Changes:
Explicit coding as suggested by #findwindow stating the workbook and the sheet before each Range, Cells, reference.
Copy and paste in one line of code (before three lines of code).
Using lngNextEmptyRow instead of LastRow so be can skip all these +1.
Determine the size (last row) of the table on the sheet "Day Before", so we know how much we need to copy over.
I hope this is the answer you've been looking for. Let me know if I misunderstood something or if anything requires more explanations.
There is no need to Active or Select Ranges. It is best to work with the Ranges directly. Rarely should you use ActiveCell, ActiveWorkSheet, or Selection.
This is how Copy and Paste work
Here is the shorthand for Copy and Paste
Range(SourceRange).Copy Range(DestinationRange)
Know that this will work for you:
Sheets("Day Before").Range("$A$12:$B$12").Copy Sheets("Historical").Cells(Rows.Count, "AF").End(xlUp).Offset(1)
I have a database that is growing quite large. Every day I add about 100 rows of information.
I have about 20 columns that autofill with calculations, etc. A few of those columns pull from a VERY large file using Vlookups. That takes forever because it's pulling the entire column everyday because my current autofill macro starts in row 2.
Is there any way to write the macro so that it autofills from the previous "last row" so it's only autofilling 100 or so new rows instead of several thousand?
I have tried the following with no luck:
Range("BZ2").AutoFill Destination:=Range("BZ2:BZ" & LastRow) is an example of one of my VBA codes for an autofill I use. LastRow is the last row after the new data is pasted in. I would like it to ideally start at the OldLastRow which would be the last row before I paste in the new data. I tried Range("BZ" & OldLastRow).AutoFill Destination:=Range("BZ" & OldLastRow & ":BZ" & LastRow) without luck.
Try this.
Dim LastRow As Long
With ActiveSheet
'This will get you the OldLastRow. Add +1 to the end to get the first empty row if you need it.
'The "A" in .Rows.Count, "A" should be replaced with a column that will always have data in every row.
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("BZ2").AutoFill Destination:=Range("BZ2:BZ" & LastRow)
'This will pause the macro until Calculations are complete.
Do While Application.CalculationState <> xlDone
DoEvents
Loop
End With
Ideally you would be doing the autofill from the point that you pasted your data in, so you wouldnt want to have "BZ2" anywhere in there if you just want to autofill new data.
you could try this one as well.
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, "BZ").End(xlUp).Row
.Range("BZ2").AutoFill Destination:=Range("BZ" & LastRow & ":BZ" & Cells(Rows.Count, "BY").End(xlUp).Row)
Do While Application.CalculationState <> xlDone
DoEvents
Loop
End With
This is assuming you only have one column of calculations. if not change the "BZ" & LastRow & ":BZ" to "BZ" & LastRow & ":CA" or whatever your last calculated column is.
I want to make drop Down List in sheet2 which contains values from sheet1 column. I have tried this code.
Sub testIt()
Dim r As Long, endRow As Long, pasteRowIndex As Long
endRow = 10 ' of course it's best to retrieve the last used row number via a function
pasteRowIndex = 1
For r = 1 To endRow 'Loop through sheet1 and search for your criteria
If Cells(r, Columns("B").Column).Value = "YourCriteria" Then 'Found
'Copy the current row
Rows(r).Select
Selection.Copy
'Switch to the sheet where you want to paste it & paste
Sheets("Sheet2").Select
Rows(pasteRowIndex).Select
ActiveSheet.Paste
'Next time you find a match, it will be pasted in a new row
pasteRowIndex = pasteRowIndex + 1
'Switch back to your table & continue to search for your criteria
Sheets("Sheet1").Select
End If
Next r
columns in sheet1 are changing oftenly. so needs to create Dynamic VBA Macro code.
Please guide me for this query.
For your case, I don't think that you need a macro to manage the drop down list but perhaps data validation will do.
Create a new worksheet,
I got a worksheet contain the following data at column A
At the worksheet that i want the dropdownlist, i just highlight the cell and click on the data validation button at data ribbon
In the data validation, create the following setting
Click on the ok button and the list will be created
Since in the columns in the worksheet(source) keep on changing, you need write the macro to copy the entire needed column exclude the header of the column to next worksheet(e.g. worksheet that create the dropdown list).
Edited: Code to detect the criteria column and copy the column
Option Explicit
Dim MyWorkbook As Workbook
Dim MyWorksheet As Worksheet
Dim MyWorksheet2 As Worksheet
Dim WantedColumn As Long
Dim ColumnPointer As Long
Sub copyCriteria()
Set MyWorkbook = Workbooks(ActiveWorkbook.Name)
Set MyWorksheet = MyWorkbook.Sheets("Sheet6")
Set MyWorksheet2 = MyWorkbook.Sheets("Sheet5")
For ColumnPointer = 1 To MyWorksheet.Cells(1, Columns.Count).End(xlToLeft).Column
If MyWorksheet.Cells(1, ColumnPointer).Value = "ColumnE" Then
MyWorksheet.Columns(ColumnPointer).Copy
MyWorksheet2.Range("A1").PasteSpecial xlPasteValues
Application.CutCopyMode = False
MyWorksheet2.Rows("1:1").Delete Shift:=xlUp
End If
Next
End Sub
What you are trying to do can be done with a simple named range and Data Validation to use that Name. If you have not heard of Dynamic Ranges, then you should read on.
If Sheet1 only has the 1 column for the DropDown list via Data Validation, you should use a Named Range instead of a fixed Range. But this named range is dynamic (by using formula)! See OFFSET usage.
Lets say Sheet1 is like below:
Lets say the name to be used is MyList, then in Excel click Name Manager in Formulas tab, and place in below as the Range Refers to:
=OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A))
Now in Sheet2, the Data Validation is placed on B2, when setting it up, once you put in the source to =MyList, Excel highlights it:
Then the drop down list worked:
Now if you add data to your list (Column A on Sheet 1), the MyList automatically expands and hence your DataValidation drop down list!
Note the list will go up to the first blank cell in Column A, so NO GAPS!
Enjoy!
I am trying to create an "Insert Column" macro in Excel.
The workbook uses formulas and conditional formatting to display progress along a timeline. I need to provide users with a way to add additional columns to the timeline.
The macro I am trying to build locates the last column and copies the entirety of column lastColumn into column newColumn. However, everything that I find online and try to adapt either gives me an object error or doesn't do anything. Please help me figure out how to do this.
Here's my code so far.
Sub InsertColumn()
Dim lastColumn As Long
Dim newColumn As Long
With ActiveSheet
lastColumn = .Range("A1").SpecialCells(xlCellTypeLastCell).column
End With
newColumn = lastColumn + 1
Selection.AutoFill Destination:=Columns(lastColumn & ":" & newColumn), Type:=xlFillDefault
End Sub
If you are simply trying to copy the one column to another then this will work:
Sub InsertColumn()
Dim lastColumn As Long
lastColumn = ActiveSheet.Range("A1").SpecialCells(xlCellTypeLastCell).Column
Columns(lastColumn).Copy Destination:=Columns(lastColumn + 1)
End Sub