Add value to the last empty cell in a defined column - vba

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

Related

Trying to control an automatated suffix output

I am wrting code for an excel spreadsheet to record change numbers such as 1735.01 .1735.02 for example but when it exceeds 1735.10 it outputs 1735.01 then 1735.011 where i would like 1735.10, 1735.11 up to 99,
can anyone help?
Option Explicit
Dim ws As Worksheet
Set ws = ActiveSheet
Dim newcolumn As Long
Dim i As Integer
Dim CELL As Range
newcolumn = Application.WorksheetFunction.CountA(ws.Range("A:A")) + 1
'The next two lines can be expanded as many times as needed for all the entry fields in your project
ws.Cells(newcolumn, 1).Value = Me.TextBox2.Value
ws.Cells(newcolumn, 2).Value = Me.TextBox3.Value
ws.Cells(newcolumn, 3).Value = Date
ws.Cells(newcolumn, 5).Value = Me.TextBox1.Value
ws.Cells(newcolumn, 4).Value = ws.Name & ".0" & Application.WorksheetFunction.CountA(ws.Range("D:D"))
End Sub
below is an amige of the output on the spreadsheet
[![enter image description here](https://i.stack.imgur.com/Ck7qZ.jpg)](https://i.stack.imgur.com/Ck7qZ.jpg)Private Sub CommandButton1_Click()

In VBA, looping with multiple conditions 'And' along with 'Or' conditions together by grouping them?

I am trying to build a code to check for two conditions simultaneously from my data file. Currently my script works fine because its only checking for the brand name on column A. However I also want to check for the category on column B whether its a "Sun" or "Vista".
Structurally I want something like:
For i = 2 to Last_row
If Cells(i,1).value = "BananaRepublic" and Cells(i, 2).value = "Sun" or "Vista" then,
Row(i).Copy
Worksheet(new_worksheet).Paste
Please note: on an average there are over 30 different brands that I need to enter in this list which need to be matched with their value on column B(Sun/Vista) and I then need to replicate this for 20 different macros each for a different combination of brand names and Sun/Optical category. Doing it individually seems very inefficient. Is there a better solution?
Here's what I've done so far:
Option Compare Text
Sub StarOptical()
'Define all variables
Dim customer_name As String
Dim sheetName As String
sName = ActiveSheet.Name
'ActiveWorkbook.Worksheets(sName).Sort.SortFields.Clear
'Enter the Customer Name here
customer_name = "StarOptical"
Sheets.Add.Name = customer_name
'Copy same header to the new worksheet
Worksheets(sName).Rows(1).Copy
Worksheets(customer_name).Cells(1, 1).Select
ActiveSheet.Paste
'Find the last row of the report
last_row = Worksheets(sName).Cells(Rows.Count, 1).End(xlUp).Row
'Start the loop and scan through each row for listed brands
For i = 2 To last_row
'Update the names of the approved brands in the line below
If Worksheets(sName).Cells(i, 1).Value = "ADENSCO" Or Worksheets(sName).Cells(i, 1).Value = "BANANAREPUBLI" Or Worksheets(sName).Cells(i, 1).Value = "BOSS(HUB)" Then
Worksheets(sName).Rows(i).Copy
Worksheets(customer_name).Activate
last_row_new = Worksheets(customer_name).Cells(Rows.Count, 1).End(xlUp).Row
Worksheets(customer_name).Cells(last_row_new + 1, 1).Select
ActiveSheet.Paste
End If
Next
Application.CutCopyMode = False
Worksheets(customer_name).Cells(1, 1).Select
End Sub
You can do something like this:
Sub tester()
CreateSheet "BananaRepublic", Array("Sun", "Vista")
'etc for other sheets
End Sub
Sub CreateSheet(sBrand As String, arrVals)
Dim wsSrc As Worksheet, wsDest As Worksheet, i As Long, c As Range
Set wsSrc = ActiveSheet
Set wsDest = wsSrc.Parent.Sheets.Add()
wsDest.Name = sBrand
wsSrc.Rows(1).Copy wsDest.Cells(1, 1)
Set c = wsDest.Cells(2, 1)
For i = 2 To wsSrc.Cells(Rows.Count, 1).End(xlUp).Row
'match on ColA?
If wsSrc.Cells(i, 1).Value = sBrand Then
'match on colB ?
If Not IsError(Application.Match(wsSrc.Cells(i, 2).Value, arrVals, 0)) Then
wsSrc.Rows(i).Copy c 'copy the row
Set c = c.Offset(1, 0) 'next cell down for copy destination
End If
End If
Next
End Sub

creating a form in excel using VBA

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()

VBA - put value in each empty row created

I have a vba code that creates empty row after each row with value:
Row 1
Row 2
Row 3
Output
Row 1
Row 2
Row 3
In the empty rows I want to insert value "check1", "check2", the auto increment of "check" and "autonumber"
To get a final output of the below:
Row 1
check1
row 2
check2
row n
check n
here is the code I have started:
Sub Insert_Blank_Rows()
'Select last row in worksheet.
Selection.End(xlDown).Select
Do Until ActiveCell.Row = 1
'Insert blank row.
ActiveCell.EntireRow.Insert shift:=xlDown
'Move up one row.
ActiveCell.Offset(-1, 0).Select
Loop
End Sub
Here's a quick and easy and efficient way with only minimal adjustment to your current code.
Sub Insert_Blank_Rows()
Dim rng as Range
Set rng = Selection ' grab top most cell in range, you may want to actually refer to the actual cell.
rng.End(xlDown).Select 'Select last row in worksheet.
Do Until ActiveCell.Row = 1
'Insert blank row.
ActiveCell.EntireRow.Insert shift:=xlDown
'Move up one row.
ActiveCell.Offset(-1, 0).Select
Loop
'fill blanks with incremental checks
Dim rngBottom as Range
Set rngBottom = Cells(rows.Count,rng.Column).End(xlUp).Offset(1)
Range(rng, rngBottom).SpecialCells(xlCellTypBlanks).FormulaR1C1 = "=""Check""&ROW()/2"
End Sub
I'll throw in this solution, with no looping nor inserting
it's very fast (less than 1 second for 20k rows)
Option Explicit
Sub main()
Dim helperCol As Range
With ActiveSheet.UsedRange
Set helperCol = .Columns(.Columns.Count + 1)
End With
With Range(ActiveCell, ActiveCell.End(xlDown))
.Offset(, helperCol.Column - .Column).Formula = "=ROW()"
With .Offset(.Rows.Count)
.Formula = "=CONCATENATE(""check"",ROW()-" & .Rows.Count & ")"
.Value = .Value
With .Offset(, helperCol.Column - .Column)
.Formula = "=ROW()-" & .Rows.Count & "+ 0.1"
.Value = .Value
End With
End With
.Resize(2 * .Rows.Count, helperCol.Column - .Column + 1).Sort Key1:=helperCol.Resize(2 * .Rows.Count), Header:=xlNo
helperCol.Resize(2 * .Rows.Count).Clear
End With
End Sub
as per OP's request, it takes move from ActiveCell
So every other row is empty and you want to fill it? One way would be something like
finalRow = cells(1000000,1).end(xlup).row
yourIncrement = 1
for i = 1 to finalRow
if isempty(cells(i,1)) then
cells(i,1) = "check" & yourIncrement
yourIncrement = yourIncrement + 1
end if
next i
I am assuming your want to fill column 1 (A).
How's this?
Sub Insert_Blank_Rows()
Dim lastRow&, i&
'Assuming column A has the most data (if not change the `1` to whatever column # does have the most data
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
'Select last row in worksheet.
'Selection.End(xlDown).Select ' Don't use `.Select`
i = 2
Do While i <= lastRow
Rows(i).Select
Rows(i).EntireRow.Insert shift:=xlDown
Cells(i, 1).Value = "Check " & Cells(i - 1, 1).Value
Cells(i, 1).Value = Cells(i, 1).Value
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
i = i + 2
Loop
End Sub
Here, I got one for you. I already tested it and work well for requirement.
Which is special in my code? My code will miss no row. Perfect auto-increment.
And I also reference from BruceWayne's code because I don't want to edit his own code.
Sub checkingData()
Dim exeRow As Integer 'For indexing the executing row
Dim lastRow As Integer 'For storing last row
exeRow = 2 'Checking from first row
'Assume that First Column has more data row than Other Column
lastRow = Cells(Rows.Count, 1).End(xlUp).row
'Loop from First Row to Last Row
Do While exeRow <= lastRow + 1
'Select data row
Rows(exeRow).Select
'Insert row below data row
Rows(exeRow).EntireRow.Insert shift:=xlDown
'Set auto-increment result
Cells(exeRow, 1) = "Check " & (exeRow / 2)
'Increase lastRow count because of adding blank row
lastRow = lastRow + 1
'Go to next data row
exeRow = exeRow + 2
Loop
End Sub

Excel VBA Not Writing to Summary Sheet

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.