I am trying to write code to copy certain ranges of data from each sheet to a summary sheet. I have attempted many versions of this (far too many for me to put them all here), but with each one the summary sheet has empty values. I don't understand what is going wrong, and I have no theories.
Here is the version that I wrote myself. All of the other variations I tried were found on the Internet:
Note: The actual summary sheet is created elsewhere in code. Also, the reason why I have sheetIndex starting at 6 is because that's the first sheet I want to take data from.
Sub PopulateSummary()
Dim nmbrParts As Integer
Dim partIndex As Integer
Dim sheetIndex As Integer
Dim sheetCount As Integer
sheetCount = ThisWorkbook.Sheets.Count
for sheetIndex = 6 To sheetCount
With Sheets(sheetIndex)
.Activate
.Range("B2").Select
Call SelectFirstToLastInColumn
nmbrParts = Selection.Count
Sheets("Summary").Activate
for partIndex = 1 To nmbrParts
row = partIndex + 1
Sheets("Summary").Cells(row, 1).Value = .Cells(row, 1).Value
Sheets("Summary").Cells(row, 2).Value = .Cells(row, 2).Value
Sheets("Summary").Cells(row, 3).Value = .Cells(row, 4).Value
Sheets("Summary").Cells(row, 3).Value = .Cells(row, 3).Value
Sheets("Summary").Cells(row, 5).Value = .Cells(row, 6).Value
Next partIndex
End With
Next sheetIndex
End Sub
EDIT: I figured something out. Since I'm invoking these macros from another workbook, I changed ThisWorkbook to ActiveWorkbook, so it counts the right number of sheets. The problem isn't solved, though.
Break it into pieces and step through the code one line at a time. That will tell you whether you're selecting what you think you're selecting, whether row is what you think it is, etc. Also, pause when the code hits your first Sheets("Summary").Cells... line and use the Immediate Window (Ctrl+G) to output the value of your destination cell with
?.Cells(row, 1).Value
Also, since you've got a With block, you don't really need to activate and select cells (and you shouldn't select most of the time in VBA anyway, as doing stuff in the sheet is slow), and you also don't have to activate Sheets("Summary") since you're referencing it directly. You could do something like:
With Sheets(sheetIndex)
nmbrParts = .Range("B:B").Find(what:="*",searchDirection:=xlPrevious).Row
for ...
.
.
.
End With
The simpler and shorter the code, the easier it is to test.
I figured it out....
I was having some problem with variable names being in the wrong place. My macro SHOULD look
something like this:
Sub PopulateSummary()
Dim nmbrParts As Integer
Dim partIndex As Integer
Dim sheetIndex As Integer
Dim sheetCount As Integer
Dim row As Integer
row = 2
sheetCount = ActiveWorkbook.Sheets.Count
For sheetIndex = 6 To sheetCount
With Sheets(sheetIndex)
.Activate
.Range("B2").Select
nmbrParts = .Range("B:B").Find(what:="*", searchDirection:=xlPrevious).row
For partIndex = 1 To nmbrParts
destRow = partIndex + 1
Sheets("Summary").Cells(row, 1).Value = .Cells(destRow, 1).Value
Sheets("Summary").Cells(row, 2).Value = .Cells(destRow, 2).Value
Sheets("Summary").Cells(row, 3).Value = .Cells(destRow, 4).Value
Sheets("Summary").Cells(row, 4).Value = .Cells(destRow, 3).Value
Sheets("Summary").Cells(row, 5).Value = .Cells(destRow, 6).Value
row = row + 1
Next partIndex
End With
Next sheetIndex
End Sub
The difference is that I used a different name to refer to rows on the sheets that I was taking from. So, I would be able to keep the numbers separate. I also found an error that I had mentioned in my Edit where I had to change ThisWorkbook to ActiveWorkbook so the sheet count could be correct.
Thanks to redOctober13 for the testing advice. You've taught me the importance of using the debugger.
Related
I want to write macro which sets cells in worksheets "Section_errors" and "Elemant_errors" is equal to cells in "ICS Analysis" worksheet. All data exists in "ICS Analysis" . I try the code below, but it doesnot work and any error doesnot appear. What can be a reason? I tryied also simple copy-paste, it operates, but it takes too much time
Sub copy_id()
Dim i As Integer
Dim lastrow As Integer
lastrow = Worksheets("ICS Analysis").Cells(Worksheets("ICS Analysis").Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
Worksheets("Element_errors").Cells(i, 73).Value = Worksheets("ICS Analysis").Cells(i, 3).Value
Worksheets("Section_errors").Cells(i, 10).Value = Worksheets("ICS Analysis").Cells(i, 3).Value
Next i
End Sub
The solution according to me is:
Sub copy_id()
Dim i As Integer
Dim lastrow As Integer
lastrow = Worksheets("ICS Analysis").Cells(Worksheets("ICS Analysis").Rows.Count,1).End(xlUp).Row
For i = 1 To lastrow
Worksheets("Element_errors").Cells(i, 73).Value = Worksheets("ICS Analysis").Cells(i,3).Value
Worksheets("Section_errors").Cells(i, 10).Value = Worksheets("ICS Analysis").Cells(i,3).Value
Next i
End Sub
The change is the location of the definition of the variable lastrow.
You see, in the earlier version, the lastrow was getting a value 1 before entering the loop and thus the loop was not running.
Hence no data.
Hope this helps...
I am currently trying to create a program that will Search through an excel file and delete duplicate entries.
I have made this code that does this. However, I also need it to delete the entry before the duplicate and after the duplicate. I've looked everywhere and can not find any examples, please help!
These are my example entries
The1
Car
Car
The2
I'd need it to delete The1 and both Car entries leaving the The2.
Here is my code so far
Sub rar()
Dim i As Long
With Worksheets("Sheet1") 'DEFINES WHICH SHEET TO USE'
For i = Cells(Rows.Count, "A").End(xlUp).Row To 2 Step -1
If Cells(i, 1).Value = Cells(i - 1, 1).Value Then
Rows(i+1).Delete
Rows(i).Delete
Rows(i-1).delete
End If
Next i
End With
End Sub
As Chris Neilsen pointed out below - using With was a great idea, but you need to put a . before your cell and range references to ensure they refer to the worksheet you specified in your With token
Try this:
Sub rar()
Dim i As Long, rng As Range
With Worksheets("Sheet1") 'DEFINES WHICH SHEET TO USE'
For i = 3 to .Cells(.Rows.Count, "A").End(xlUp).Row
If .Cells(i, 1).Value = .Cells(i - 1, 1).Value Then
If rng Is Nothing Then
Set rng = .Rows(i - 2 & ":" & i)
Else
Set rng = Union(rng, .Rows(i - 2 & ":" & i))
End If
End If
Next i
End With
rng.Delete
End Sub
Note: untested - but the idea is to create build up your range as you loop through and then delete at the end. This way you don't have to worry about looping backwards.
I am trying to creat a form in excel using VBA, but I am stuck at the Code. I need to find out the code to enter a data to my worksheet using VBA form . here is the code I am using, but doesn't work..
Private Sub cmdAdd_Click()
Dim LastRow As Range
Dim DPDIAdhocRequestTable As ListObject
With LastRow
Cells(1, 2) = RequesterName.Value
Cells(1, 3) = RequesterPhoneNumber.Value
Cells(1, 4) = RequesterBureau.Value
Cells(1, 5) = DateRequestMade.Value
Cells(1, 6) = DateRequestDue.Value
Cells(1, 7) = PurposeofRequest.Value
Cells(1, 8) = ExpectedDataSaurce.Value
Cells(1, 9) = Timeperiodofdatarequested.Value
Cells(1, 10) = ReoccuringRequest.Value
Cells(1, 11) = RequestNumber.Value
Cells(1, 12) = AnalystAssigned.Value
Cells(1, 13) = AnalystEstimatedDueDate.Value
Cells(1, 14) = AnalystCompletedDate.Value
Cells(1, 15) = SupervisiorName.Value
End With
End Sub
can you help me to figure out the correct code for enter command?
thank you so much for your help.
As #Adam said - you've created LastRow and not assigned it to anything.
I'm guessing it's the next row you want to paste your data into, so it should be a Long holding the row number rather than an actual reference to the cell.
In the code below you could qualify the form controls by adding Me., for example Me.RequesterName.Value
https://msdn.microsoft.com/en-us/library/office/gg251792.aspx
Private Sub cmdAdd_Click()
Dim wrkSht As Worksheet
Dim LastRow As Long
'The sheet you want the data to go into.
Set wrkSht = ThisWorkbook.Worksheets("Sheet1")
'You're after the last row number, rather than referencing the range so LastRow is a Long.
'This looks for the last cell containing data in column A (the 1 in 'Cells(...)').
LastRow = wrkSht.Cells(Rows.Count, 1).End(xlUp).Row + 1
'With... End With block. Cells is preceded by a '.' notation - indicating it's referencing the 'With wkrSht'#
'https://msdn.microsoft.com/en-us/library/wc500chb.aspx
With wrkSht
'Using LastRow as row number in cell reference.
.Cells(LastRow, 2) = RequesterName.Value
'Before adding dates to the sheet you might want to check that the
'user entered a date and not rubbish.
.Cells(LastRow, 5) = DateRequestMade.Value
'You could use CDATE to force it to a date - will try and coerce the entered text into a date.
'Note - 1 will be changed to 01/01/1900 (so will need to add extra code to check it really is a date).
.Cells(LastRow, 5) = CDate(DateRequestMade.Value)
End With
End Sub
The first problem is that you've created a Range named LastRow but haven't assigned anything to it.
'Declaration
Dim LastRow As Range
'Assigns the last row based on the last item in Column A
Set LastRow = Range("A" & Rows.Count).End(xlUp).Row
With LastRow
...
End With
The second issue is a minor syntax error in your With LastRow block.
With LastRow
Cells(x,y).Value = "Foo"
End With
Should be
With LastRow
.Cells(x,y).Value = "Foo"
End With
Which is essentially the same as saying LastRow.Cells(x,y).Value = "Foo". Without the "." in front of Cells() VBA will not apply the With to that object, and assume you meant ActiveSheet.Cells()
My model takes two numbers from one sheet, adds the average to another sheet in the last cell of a defined column. The problem that I have is that when I insert a new column, the references get missed up and I'm trying to have a macro that would 1. take the average 2. look for a specific column on the second sheet 3. paste the averaged value to the last cell.
Please help me with this I have been trying to get my head around it for a long time.
Thank you.
This is my code: what it basically does now is find the last emptyrow and I have to put in a number for a column to reference a cell. What I want is to have the column reference dynamic so when I insert a new column i dont have to change the macro.
Private Sub CommandButton1_Click()
Dim emptyRow As Long, Answer As Double, result As String
Application.ScreenUpdating = False
Sheet1.Activate
RowCount = Worksheets("Sheet1").Range("A1").CurrentRegion.Rows.Count
With Sheets("Sheet1").Range("A1")
.Offset(1, 2).Value = Me.TextBox1.Value
.Offset(1, 3).Value = Me.TextBox2.Value
.Offset(2, 2).Value = Me.TextBox3.Value
.Offset(2, 3).Value = Me.TextBox4.Value
.Offset(3, 2).Value = Me.TextBox5.Value
.Offset(3, 3).Value = Me.TextBox6.Value
.Offset(4, 2).Value = Me.TextBox7.Value
.Offset(4, 3).Value = Me.TextBox8.Value
End With
Sheet2.Activate
emptyRow = Sheet2.Range("A" & Rows.Count).End(xlUp).Row + 1
Answer = Application.WorksheetFunction.Average(Range("C2:D2"))
Sheets("Sheet2").Cells(emptyRow, 1).Value = Answer
Answer = Application.WorksheetFunction.Average(Range("C3:D3"))
Sheets("Sheet2").Cells(emptyRow, 2).Value = Answer
Answer = Application.WorksheetFunction.Average(Range("C4:D4"))
Sheets("Sheet2").Cells(emptyRow, 3).Value = Answer
Answer = Application.WorksheetFunction.Average(Range("C5:D5"))
Sheets("Sheet2").Cells(emptyRow, 4).Value = Answer
End Sub
One way is to assign a Name to the column:
Sub demo()
Range("B:B").Cells.Name = "expenses"
End Sub
If columns are inserted at the beginning of the worksheet, the named range will adjust.
EDIT#1:
After the Name has been assigned, here is an example of filling the first empty cell (at the bottom of the column) of the expense column with the value 123
Sub TheNextStep()
Dim expCol As Long, FirstEmptyRow As Long
expCol = Range("expenses").Column
FirstEmptyRow = Cells(Rows.Count, expCol).End(xlUp).Row + 1
Cells(FirstEmptyRow, expCol).Value = 123
End Sub
I am very new to VBA and I am trying to solve what I think should be a very simple problem (I have a Java/J2EE background)... I am looping through a table and want to copy rows to a table on another worksheet based on some conditional statements. See code below.
Sub closeActionItems()
Dim i, iLastRow As Integer
Dim date1 As Date
Dim oLastRow As ListRow
date1 = Date
iLastRow = ActiveSheet.ListObjects("Open_Items").ListRows.Count
For i = 6 To iLastRow
If Cells(i, 7).Value <= date1 And Cells(i, 7).Value <> vbNullString Then
Rows(i).Copy
Set oLastRow = Worksheets("Closed").ListObject("Closed_Items").ListRows.Add
'Paste into new row
Application.CutCopyMode = False
Rows(i).EntireRow.Delete
End If
Next
End Sub
I have tried many different iterations but have been unable to find the correct way to copy the contents of the clipboard to the newly created row.
Any help would be appreciated. Thanks ahead of time.
Define srcRow as a Range like so:
Dim srcRow as Range
Then in your loop try doing this:
Set srcRow = ActiveSheet.ListObjects("Open_Items").ListRows(i).Range
Set oLastRow = Worksheets("Closed").ListObjects("Closed_Items").ListRows.Add
srcRow.Copy
oLastRow.Range.PasteSpecial xlPasteValues
Application.CutCopyMode = False
Rows(i).EntireRow.Delete
Notice that you still have a problem in that you are deleting rows as you are trying to loop through them, so you probably want to change your loop so that it starts at the bottom and goes up.