I'm writing a macro to update key cells from a form, then write the data to a table in a second sheet. To do this, I'm using a For i = 1 to LR to match, then write the Row number to a variable if it finds a match.
However the code to find the last row, and therefore the length of the loop isn't working as expected.
Dim LR as Long
LR = Cells(Workbooks("Tracking Sheet.xlsx").Sheets("Sheet1").Rows.Count, "A").End(xlUp).Row
Debug.Print LR
I've tried pre-populating both less than 25 and more than 25 (e.g. 38) , but the LR variable is always showing 25 in the Immediate window. In the immediate window,
?Cells(Workbooks("Tracking Sheet.xlsx").Sheets("Sheet1").Rows.Count, "A").End(xlUp).Row
returns 38, as it should.
LR = Cells(Workbooks("Tracking Sheet.xlsx").Sheets("Sheet1").Rows.Count, "A").End(xlUp).Row
?LR
also returns 38
I just don't get it...
Try this:
Dim LR As Long
With Application.Workbooks("Tracking Sheet.xlsx").Worksheets("Sheet1")
LR = .Range("A" & .Rows.Count).End(xlUp).Row
End With
Maybe the code explained will help?
LRow = ThisWorkbook.Sheets(1).Cells(ThisWorkbook.Sheets(1).Rows.Count, "A").End(xlUp).Row
Let's break up this code. First, we place it in a With statement to save us some typing
With ThisWorkbook.Sheets(1)
LRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Let's break this up in pieces. First, there is .Cells(.Rows.Count, "A")
This is a reference to a single cell. Specifically, the very last row in column A of ThisWorkbook.Sheets(1). Rows.Count gives the last row number in the Excel sheets. Recent Excel versions support 1,048,576 rows, but e.g. Excel 97 only supported 65536 rows.
In short, .Cells(.Rows.Count, "A") is for recent excel versions equal to (A1048576)
Then End(xlUp). This does the same as when you hold CTRL and press the arrow up button on your keyboard. This brings Excel to the first filled row from the bottom.
Finally .Row, which returns the row number of this found cell.
You could also start looking from the the top. Try holding CTRL and then pressing the arrow down button. This would stop at the last non-empty cell. However, it would also stop when you have blank cells between filled cells. So, not always a preferred method. The code would be
With ThisWorkbook.Sheets(1)
LRow = .Cells(1, "A").End(xlDown).Row
End With
Related
As shown in image, I am trying to fill numbers in increasing order in alternate merged cells, which are different in size. So, I can't use autofill function of excel. But I want a macro so I can do it every time just hitting button once.
Note that I want numbers till the used range only.
I tried a lot to do it my self, but I am stuck now...Plz help the beginner, it's my third day in VBA.
This should do what you are looking for.
It will ignore non merged cells, I didn't see any in your screenshot that needed a number and were not merged so that shouldn't be an issue.
It uses column B to figure out the last row of your data.
Dim i As Long
Dim lr As Long
Dim counter As Long
counter = 1
With Sheet1 'Change to whatever your sheets code name is
lr = .Cells(.Rows.Count, 2).End(xlUp).Row 'If you want to use something other than column B, change the 2 to the right column index
For i = 2 To lr
If .Cells(i, 1).MergeCells = True Then
If .Cells(i, 1).MergeArea.Item(1).Address = .Cells(i, 1).Address Then
.Cells(i, 1) = counter
counter = counter + 1
End If
End If
Next i
End With
so I'm running a code that filters my data and then takes the count of the data and inserts it into an excel file. I'm using this code to count the data:
lastrow = Cells(Rows.count, "A").End(xlUp).Row
count = Application.WorksheetFunction.Subtotal(3, Range("A2:A" & lastrow))
For some reason, when I've filtered my data so that no value is visible aside from my top row, which is located in row 1, It gives me a value of 1 rather than 0. Any ideas why it's doing so?
Thanks
This is actually a funny thing I, too, discovered a while ago. What's happening is that, with a blank (or just filtered to appear blank) column A, lastrow = 1, which means the range you're Subtotaling is Range("A2:A1").
For example, test:
Debug.Print Application.WorksheetFunction.Subtotal(3, Range("A2:A1"))
UPDATE:
Thank you for your help thus far! That definitely worked.
I am wondering though if there is a way to add a loop function as well. What i would like it to do is to reference Column A of Worksheet 888 to identify the same value in Column A of 999, and sum the values in the last column of the sheet (keeping in mind that the last column may differ, thus allowing the macro to be more dynamic).
Dim LastRow, LastColumn As Long
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
LastColumn = Worksheets("888").Cells(1,
Columns.Count).End(xlToLeft).Column
For x= 1 To LastRow
Cells(x, 2).Value =
WorksheetFunction.SumIf(Worksheets("888").Range("A:LastRow"),
Worksheets("999").Range("A:LastRow"),
Worksheets("888").Range("LastColumn:LastColumn"))
Next c
I keep getting the error "Unable to get the SumIf property of the worksheet function class. Any thoughts on how to fix?
i don't really understand why do you want to use macro when formula can do the job
put below in C2 and drag down the formula should do the job
=SUMIF(Sheet2!F:F,A2,Sheet2!H:H)+SUMIF(Sheet3!J:J,A2,Sheet3!L:L)
but if you insist macro,
Worksheets("Sheet1").Range("C2").Value = "=SUMIF(Sheet2!F:F,A2,Sheet2!H:H)+SUMIF(Sheet3!J:J,A2,Sheet3!L:L)"
Worksheets("Sheet1").Range("C2:C7").FillDown
Hoping you can help an basic excel user please!
I have a file of around 2000 rows and I need to add a line/break after every third one. Is there a simple way of doing this please?
Your help and advice would be much appreciated.
Thanks
Quick way without VBA
In a empty column add this formula, =IF(MOD(ROW(),3)=0,NA(),"") and copy down
Press F5, Goto .... Special, Formulas Errors (selects every third row)
Insert Rows
step 2 shown below
If you want to try some VBA here is a button click event that will do the insert on every third row. Let me know if you have any questions.
Private Sub CommandButton1_Click()
Dim ws As Excel.Worksheet
Dim lRow As Long
Dim lastRow As Long
'Set the worksheet object to the sheet by name
Set ws = Application.Sheets("Sheet1")
'Set the row to start looping(inserting) rows at
lRow = 4
'Find the last row with a value in column A
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
'Account for the amount of rows that will be inserted.
lastRow = lastRow + (lastRow * 0.33)
'Loop through the worksheet from the start row to the last row
Do While lRow <= lastRow
'Insert a row
ws.Rows(lRow).EntireRow.Insert
'Increment the row to insert at on the next pass of the loop
lRow = lRow + 4
Loop
End Sub
a non vba way is create a new column and insert numbering
1
2
3
4
5
6
......
then for empty row, number as 3,6,9,.... (let say u have 2k records, duplicate it 2k)
then sort by the number column, then remove the column
If your content is the same, or repeating, for each row, you could open the file in any basic text editor and do the following:
Highlight and copy the first three rows (including the third line break).
Using find-and-replace (Opt-Cmd-F in TextEdit on Macs), copy that content into the 'find' field as well as the 'replace' field.
Add a line break at the end of the content you pasted in the 'replace' field.
Execute the find-and-replace action.
This should turn something like this:
item
item
item
item
item
item
item
...into this:
item
item
item
item
item
item
item
...and so on.
This definitely isn't the most elegant solution, but is one of the quickest/simplest I've seen without resorting to a text parsing script in bash, etc.
Assuming data starts in A1, in B1 and copied down to suit (i.e. past the end of the cells populated in ColumnA):
=IF(MOD(ROW(),4)=0,"",OFFSET(A$1,3*INT((ROW()-1)/4)+MOD(ROW(),4)-1,))
Here is a VBA equivalent to the solution proposed by Eric K. above. The orientation assumes column header labels in row 1 that should be left alone.
Sub insBlankFourthRow()
Debug.Print Timer
With Worksheets("Sheet3")
.Columns(1).Insert
With .Cells(1, 1).CurrentRegion '<~~ original CurrentRegion
With .Resize(.Rows.Count - 1, 1).Offset(1, 0)
.Cells(1, 1) = 1
.Cells.DataSeries Rowcol:=xlColumns, Type:=xlLinear, Step:=1
End With
With .Resize(Int(.Rows.Count / 3) + 1, 1).Offset(.Rows.Count, 0)
.Cells(1, 1) = 3.5
.Cells.DataSeries Rowcol:=xlColumns, Type:=xlLinear, Step:=3
End With
End With
'
With .Cells(1, 1).CurrentRegion '<~~ new expanded CurrentRegion
.Cells.Sort Key1:=.Columns(1), Order1:=xlAscending, _
Orientation:=xlTopToBottom, Header:=xlYes
End With
.Columns(1).Delete
End With
Debug.Print Timer
End Sub
tbh, ~2000 rows of data isn't that much to be worried about but 10× or 100× that amount of data will start to lag significantly when inserting rows individually or in a bulk non-contiguous orientation. A 'helper' column populated with a Range.DataSeries method (fastest way I know of populating a sequence) can be readily discarded once its purpose has been fulfilled.
Running the above against 2500 rows of random data typical of the image took ⁸⁄₁₀₀ of a second. That time might be moderately improved with disabling the Application.ScreenUpdating property and similar overhead.
I have a column that has U.S. state abbreviations (MI, NY, FL, etc.). I have an issue where there is an observation that is listed as "NJ NJ". This observation moves around within the same column each week.
I want to create a macro that substrings each observation to two characters and just drops everything afterwords.
Would I be able to use the Mid function to grab the first two characters, and then paste it overtop of the original value. Further, would it be appropriate to offset by one or is there a way to do it all at once?
Thanks!
Assuming you have your List in the 1st Column, starting at Row 1, the following Macro will do it. Obviously you can make a lot of improvements and error checks to the code, but this should get you started.
Sub FixStates()
Dim lRow As Long
Dim lCol As Long
Dim strContent As String
lRow = 1
lCol = 1
Do While Cells(lRow, lCol) <> ""
strContent = Trim(Cells(lRow, lCol))
If Len(strContent) > 2 Then Cells(lRow, lCol) = Left(strContent, 2)
lRow = lRow + 1
Loop
End Sub
If you want your result to be offset by one cell from the source cell, then the formula by Daniel Cook works fine.
On the other hand, if you want your result to overwrite the source cell, you would have to copy the cell with the result (using the same formula as above) and paste-special as value on top of the source cell (you can do this for many cells at once), or write a VBA sub.
I personally find it simpler the "copy and paste-special as value" way.